From aee67d343a788da9dca4bfbffee27dbb8aca1a44 Mon Sep 17 00:00:00 2001 From: Davide Mor <davide.mor@skywarder.eu> Date: Tue, 20 Feb 2024 19:06:06 +0100 Subject: [PATCH] [compute_unit_v2] Added compute_unit_v2 target --- .vscode/c_cpp_properties.json | 23 + CMakeLists.txt | 3 + cmake/boards.cmake | 2 + .../config/board_options.cmake | 106 ++++ .../config/board_options_no_xram.cmake | 106 ++++ .../config/board_settings.h | 62 ++ .../config/miosix_settings.h | 240 ++++++++ .../core/stage_1_boot.cpp | 505 +++++++++++++++ .../interfaces-impl/arch_registers_impl.h | 39 ++ .../interfaces-impl/bsp.cpp | 304 +++++++++ .../interfaces-impl/bsp_impl.h | 108 ++++ .../stm32_2m+32m_xram.ld | 190 ++++++ .../stm32_2m+384k_ram.ld | 189 ++++++ src/entrypoints/compute-unit-v2-testsuite.cpp | 580 ++++++++++++++++++ 14 files changed, 2457 insertions(+) create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/config/board_options.cmake create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/config/board_options_no_xram.cmake create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/config/board_settings.h create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/config/miosix_settings.h create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/core/stage_1_boot.cpp create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/arch_registers_impl.h create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp.cpp create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp_impl.h create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/stm32_2m+32m_xram.ld create mode 100644 src/bsps/stm32f767zi_compute_unit_v2/stm32_2m+384k_ram.ld create mode 100644 src/entrypoints/compute-unit-v2-testsuite.cpp diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index b16913f5d..9d1fd9c7d 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -273,6 +273,29 @@ "${workspaceFolder}/src/bsps/stm32f767zi_compute_unit" ] }, + { + "name": "stm32f767zi_compute_unit_v2", + "cStandard": "c11", + "cppStandard": "c++14", + "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++", + "defines": [ + "${defaultDefines}", + "_MIOSIX_BOARDNAME=stm32f767zi_compute_unit_v2", + "_BOARD_STM32F767ZI_COMPUTE_UNIT_V2", + "_ARCH_CORTEXM7_STM32F7", + "STM32F769xx", + "HSE_VALUE=25000000", + "SYSCLK_FREQ_216MHz=216000000", + "__ENABLE_XRAM", + "V_DDA_VOLTAGE=3.3f" + ], + "includePath": [ + "${defaultIncludePaths}", + "${workspaceFolder}/libs/miosix-kernel/miosix/arch/cortexM7_stm32f7/common", + "${workspaceFolder}/src/bsps/stm32f767zi_compute_unit_v2/config", + "${workspaceFolder}/src/bsps/stm32f767zi_compute_unit_v2" + ] + }, { "name": "stm32f767zi_death_stack_v4", "cStandard": "c11", diff --git a/CMakeLists.txt b/CMakeLists.txt index 2671df6f6..820ee31d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,9 @@ sbs_target(imu-calibration stm32f429zi_parafoil) add_executable(mxgui-helloworld src/entrypoints/examples/mxgui-helloworld.cpp) sbs_target(mxgui-helloworld stm32f429zi_stm32f4discovery) +add_executable(compute-unit-v2-testsuite src/entrypoints/compute-unit-v2-testsuite.cpp) +sbs_target(compute-unit-v2-testsuite stm32f767zi_compute_unit_v2_no_xram) + # add_executable(kernel-testsuite src/entrypoints/kernel-testsuite.cpp) # sbs_target(kernel-testsuite stm32f767zi_compute_unit) diff --git a/cmake/boards.cmake b/cmake/boards.cmake index aaf6074cb..9db7a898b 100644 --- a/cmake/boards.cmake +++ b/cmake/boards.cmake @@ -31,6 +31,8 @@ set(BOARDCORE_BOARDS_OPTIONS_FILES ${BOARDCORE_PATH}/src/bsps/stm32f756zg_nucleo/config/board_options.cmake ${BOARDCORE_PATH}/src/bsps/stm32f767zi_automated_antennas/config/board_options.cmake ${BOARDCORE_PATH}/src/bsps/stm32f767zi_compute_unit/config/board_options.cmake + ${BOARDCORE_PATH}/src/bsps/stm32f767zi_compute_unit_v2/config/board_options.cmake + ${BOARDCORE_PATH}/src/bsps/stm32f767zi_compute_unit_v2/config/board_options_no_xram.cmake ${BOARDCORE_PATH}/src/bsps/stm32f767zi_gemini_gs/config/board_options.cmake ${BOARDCORE_PATH}/src/bsps/stm32f767zi_gemini_motor/config/board_options.cmake ${BOARDCORE_PATH}/src/bsps/stm32f767zi_death_stack_v4/config/board_options.cmake diff --git a/src/bsps/stm32f767zi_compute_unit_v2/config/board_options.cmake b/src/bsps/stm32f767zi_compute_unit_v2/config/board_options.cmake new file mode 100644 index 000000000..e4a000b5b --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/config/board_options.cmake @@ -0,0 +1,106 @@ +# Copyright (C) 2023 by Skyward +# +# This program is free software; you can redistribute it and/or +# it under the terms of the GNU General Public License as published +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# As a special exception, if other files instantiate templates or use +# macros or inline functions from this file, or you compile this file +# and link it with other works to produce a work based on this file, +# this file does not by itself cause the resulting work to be covered +# by the GNU General Public License. However the source code for this +# file must still be made available in accordance with the GNU +# Public License. This exception does not invalidate any other +# why a work based on this file might be covered by the GNU General +# Public License. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/> + +set(BOARD_NAME stm32f767zi_compute_unit_v2) +set(ARCH_NAME cortexM7_stm32f7) + +# Base directories with header files for this board +set(ARCH_PATH ${KPATH}/arch/${ARCH_NAME}/common) +set(BOARD_PATH ${BOARDCORE_PATH}/src/bsps/stm32f767zi_compute_unit_v2) +set(BOARD_CONFIG_PATH ${BOARDCORE_PATH}/src/bsps/stm32f767zi_compute_unit_v2/config) + +# Specify where to find the board specific config/miosix_settings.h +set(BOARD_MIOSIX_SETTINGS_PATH ${BOARD_PATH}) + +# Specify where to find the board specific config/mxgui_settings.h +set(BOARD_MXGUI_SETTINGS_PATH ${BOARD_PATH}) + +# Optimization flags: +# -O0 do no optimization, the default if no optimization level is specified +# -O or -O1 optimize minimally +# -O2 optimize more +# -O3 optimize even more +# -Ofast optimize very aggressively to the point of breaking the standard +# -Og Optimize debugging experience, enables optimizations that do not +# interfere with debugging +# -Os Optimize for size with -O2 optimizations that do not increase code size +set(OPT_OPTIMIZATION -O2) + +# Boot file and linker script +set(BOOT_FILE ${BOARD_PATH}/core/stage_1_boot.cpp) +# set(LINKER_SCRIPT ${BOARD_PATH}/stm32_2m+384k_ram.ld) +set(LINKER_SCRIPT ${BOARD_PATH}/stm32_2m+32m_xram.ld) + +# Enables the initialization of the external 16MB SDRAM memory +set(XRAM -D__ENABLE_XRAM) + +# Select clock frequency (HSE_VALUE is the xtal on board, fixed) +set(CLOCK_FREQ -DHSE_VALUE=25000000 -DSYSCLK_FREQ_216MHz=216000000) + +# C++ Exception/rtti support disable flags. +# To save code size if not using C++ exceptions (nor some STL code which +# implicitly uses it) uncomment this option. +# -D__NO_EXCEPTIONS is used by Miosix to know if exceptions are used. +# set(OPT_EXCEPT -fno-exceptions -fno-rtti -D__NO_EXCEPTIONS) + +# Specify a custom flash command +# This is the program that is invoked when the flash flag (-f or --flash) is +# used with the Miosix Build System. Use $binary or $hex as placeolders, they +# will be replaced by the build systems with the binary or hex file repectively. +# If a command is not specified, the build system will use st-flash if found +# set(PROGRAM_CMDLINE "here your custom flash command") + +# Basic flags +set(FLAGS_BASE -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16) + +# Flags for ASM and linker +set(AFLAGS_BASE ${FLAGS_BASE}) +set(LFLAGS_BASE ${FLAGS_BASE} -Wl,--gc-sections,-Map,main.map -Wl,-T${LINKER_SCRIPT} ${OPT_EXCEPT} ${OPT_OPTIMIZATION} -nostdlib) + +# Flags for C/C++ +string(TOUPPER ${BOARD_NAME} BOARD_UPPER) +set(CFLAGS_BASE + -D_BOARD_${BOARD_UPPER} -D_MIOSIX_BOARDNAME=\"${BOARD_NAME}\" + -D_DEFAULT_SOURCE=1 -ffunction-sections -Wall -Werror=return-type -g + -D_ARCH_CORTEXM7_STM32F7 + ${CLOCK_FREQ} ${XRAM} ${SRAM_BOOT} ${FLAGS_BASE} ${OPT_OPTIMIZATION} -c +) +set(CXXFLAGS_BASE ${CFLAGS_BASE} ${OPT_EXCEPT}) + +# Select architecture specific files +set(ARCH_SRC + ${ARCH_PATH}/interfaces-impl/delays.cpp + ${ARCH_PATH}/interfaces-impl/gpio_impl.cpp + ${ARCH_PATH}/interfaces-impl/portability.cpp + ${BOARD_PATH}/interfaces-impl/bsp.cpp + ${KPATH}/arch/common/CMSIS/Device/ST/STM32F7xx/Source/Templates/system_stm32f7xx.c + ${KPATH}/arch/common/core/cache_cortexMx.cpp + ${KPATH}/arch/common/core/interrupts_cortexMx.cpp + ${KPATH}/arch/common/core/mpu_cortexMx.cpp + ${KPATH}/arch/common/core/stm32f2_f4_l4_f7_h7_os_timer.cpp + ${KPATH}/arch/common/drivers/sd_stm32f2_f4_f7.cpp + ${KPATH}/arch/common/drivers/serial_stm32.cpp + ${KPATH}/arch/common/drivers/stm32_hardware_rng.cpp +) diff --git a/src/bsps/stm32f767zi_compute_unit_v2/config/board_options_no_xram.cmake b/src/bsps/stm32f767zi_compute_unit_v2/config/board_options_no_xram.cmake new file mode 100644 index 000000000..e16999d91 --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/config/board_options_no_xram.cmake @@ -0,0 +1,106 @@ +# Copyright (C) 2023 by Skyward +# +# This program is free software; you can redistribute it and/or +# it under the terms of the GNU General Public License as published +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# As a special exception, if other files instantiate templates or use +# macros or inline functions from this file, or you compile this file +# and link it with other works to produce a work based on this file, +# this file does not by itself cause the resulting work to be covered +# by the GNU General Public License. However the source code for this +# file must still be made available in accordance with the GNU +# Public License. This exception does not invalidate any other +# why a work based on this file might be covered by the GNU General +# Public License. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/> + +set(BOARD_NAME stm32f767zi_compute_unit_v2_no_xram) +set(ARCH_NAME cortexM7_stm32f7) + +# Base directories with header files for this board +set(ARCH_PATH ${KPATH}/arch/${ARCH_NAME}/common) +set(BOARD_PATH ${BOARDCORE_PATH}/src/bsps/stm32f767zi_compute_unit_v2) +set(BOARD_CONFIG_PATH ${BOARDCORE_PATH}/src/bsps/stm32f767zi_compute_unit_v2/config) + +# Specify where to find the board specific config/miosix_settings.h +set(BOARD_MIOSIX_SETTINGS_PATH ${BOARD_PATH}) + +# Specify where to find the board specific config/mxgui_settings.h +set(BOARD_MXGUI_SETTINGS_PATH ${BOARD_PATH}) + +# Optimization flags: +# -O0 do no optimization, the default if no optimization level is specified +# -O or -O1 optimize minimally +# -O2 optimize more +# -O3 optimize even more +# -Ofast optimize very aggressively to the point of breaking the standard +# -Og Optimize debugging experience, enables optimizations that do not +# interfere with debugging +# -Os Optimize for size with -O2 optimizations that do not increase code size +set(OPT_OPTIMIZATION -O2) + +# Boot file and linker script +set(BOOT_FILE ${BOARD_PATH}/core/stage_1_boot.cpp) +set(LINKER_SCRIPT ${BOARD_PATH}/stm32_2m+384k_ram.ld) +# set(LINKER_SCRIPT ${BOARD_PATH}/stm32_2m+16m_xram.ld) + +# Enables the initialization of the external 16MB SDRAM memory +set(XRAM -D__ENABLE_XRAM) + +# Select clock frequency (HSE_VALUE is the xtal on board, fixed) +set(CLOCK_FREQ -DHSE_VALUE=25000000 -DSYSCLK_FREQ_216MHz=216000000) + +# C++ Exception/rtti support disable flags. +# To save code size if not using C++ exceptions (nor some STL code which +# implicitly uses it) uncomment this option. +# -D__NO_EXCEPTIONS is used by Miosix to know if exceptions are used. +# set(OPT_EXCEPT -fno-exceptions -fno-rtti -D__NO_EXCEPTIONS) + +# Specify a custom flash command +# This is the program that is invoked when the flash flag (-f or --flash) is +# used with the Miosix Build System. Use $binary or $hex as placeolders, they +# will be replaced by the build systems with the binary or hex file repectively. +# If a command is not specified, the build system will use st-flash if found +# set(PROGRAM_CMDLINE "here your custom flash command") + +# Basic flags +set(FLAGS_BASE -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16) + +# Flags for ASM and linker +set(AFLAGS_BASE ${FLAGS_BASE}) +set(LFLAGS_BASE ${FLAGS_BASE} -Wl,--gc-sections,-Map,main.map -Wl,-T${LINKER_SCRIPT} ${OPT_EXCEPT} ${OPT_OPTIMIZATION} -nostdlib) + +# Flags for C/C++ +string(TOUPPER ${BOARD_NAME} BOARD_UPPER) +set(CFLAGS_BASE + -D_BOARD_${BOARD_UPPER} -D_MIOSIX_BOARDNAME=\"${BOARD_NAME}\" + -D_DEFAULT_SOURCE=1 -ffunction-sections -Wall -Werror=return-type -g + -D_ARCH_CORTEXM7_STM32F7 + ${CLOCK_FREQ} ${XRAM} ${SRAM_BOOT} ${FLAGS_BASE} ${OPT_OPTIMIZATION} -c +) +set(CXXFLAGS_BASE ${CFLAGS_BASE} ${OPT_EXCEPT}) + +# Select architecture specific files +set(ARCH_SRC + ${ARCH_PATH}/interfaces-impl/delays.cpp + ${ARCH_PATH}/interfaces-impl/gpio_impl.cpp + ${ARCH_PATH}/interfaces-impl/portability.cpp + ${BOARD_PATH}/interfaces-impl/bsp.cpp + ${KPATH}/arch/common/CMSIS/Device/ST/STM32F7xx/Source/Templates/system_stm32f7xx.c + ${KPATH}/arch/common/core/cache_cortexMx.cpp + ${KPATH}/arch/common/core/interrupts_cortexMx.cpp + ${KPATH}/arch/common/core/mpu_cortexMx.cpp + ${KPATH}/arch/common/core/stm32f2_f4_l4_f7_h7_os_timer.cpp + ${KPATH}/arch/common/drivers/sd_stm32f2_f4_f7.cpp + ${KPATH}/arch/common/drivers/serial_stm32.cpp + ${KPATH}/arch/common/drivers/stm32_hardware_rng.cpp +) diff --git a/src/bsps/stm32f767zi_compute_unit_v2/config/board_settings.h b/src/bsps/stm32f767zi_compute_unit_v2/config/board_settings.h new file mode 100644 index 000000000..2332aa30e --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/config/board_settings.h @@ -0,0 +1,62 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +/** + * \internal + * Versioning for board_settings.h for out of git tree projects + */ +#define BOARD_SETTINGS_VERSION 300 + +namespace miosix +{ + +/** + * \addtogroup Settings + * \{ + */ + +/// Size of stack for main(). +/// The C standard library is stack-heavy (iprintf requires 1KB) +const unsigned int MAIN_STACK_SIZE = 16 * 1024; + +/// Serial port +const unsigned int defaultSerial = 1; +const unsigned int defaultSerialSpeed = 115200; +#define SERIAL_1_DMA +// #define SERIAL_2_DMA +// #define SERIAL_3_DMA + +// SD card driver +static const unsigned char sdVoltage = 33; // Board powered @ 3.3V +// #define SD_ONE_BIT_DATABUS +#define SD_SDMMC 1 // Select either SDMMC1 or SDMMC2 + +/// Analog supply voltage for ADC, DAC, Reset blocks, RCs and PLL +#define V_DDA_VOLTAGE 3.3f + +/** + * \} + */ + +} // namespace miosix diff --git a/src/bsps/stm32f767zi_compute_unit_v2/config/miosix_settings.h b/src/bsps/stm32f767zi_compute_unit_v2/config/miosix_settings.h new file mode 100644 index 000000000..e1ca4aac6 --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/config/miosix_settings.h @@ -0,0 +1,240 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// Before you can compile the kernel you have to configure it by editing this +// file. After that, comment out this line to disable the reminder error. +// The PARSING_FROM_IDE is because Netbeans gets confused by this, it is never +// defined when compiling the code. +#ifndef PARSING_FROM_IDE +//#error This error is a reminder that you have not edited miosix_settings.h +// yet. +#endif // PARSING_FROM_IDE + +/** + * \file miosix_settings.h + * NOTE: this file contains ONLY configuration options that are not dependent + * on architecture specific details. The other options are in the following + * files which are included here: + * miosix/arch/architecture name/common/arch_settings.h + * miosix/config/arch/architecture name/board name/board_settings.h + */ +#include "arch_settings.h" +#include "board_settings.h" +#include "util/version.h" + +/** + * \internal + * Versioning for miosix_settings.h for out of git tree projects + */ +#define MIOSIX_SETTINGS_VERSION 300 + +namespace miosix +{ + +/** + * \addtogroup Settings + * \{ + */ + +// +// Scheduler options +// + +/// \def SCHED_TYPE_PRIORITY +/// If uncommented selects the priority scheduler +/// \def SCHED_TYPE_CONTROL_BASED +/// If uncommented selects the control based scheduler +/// \def SCHED_TYPE_EDF +/// If uncommented selects the EDF scheduler +// Uncomment only *one* of those + +#define SCHED_TYPE_PRIORITY +//#define SCHED_TYPE_CONTROL_BASED +//#define SCHED_TYPE_EDF + +/// \def WITH_CPU_TIME_COUNTER +/// Allows to enable/disable CPUTimeCounter to save code size and remove its +/// overhead from the scheduling process. By default it is not defined +/// (CPUTimeCounter is disabled). +//#define WITH_CPU_TIME_COUNTER + +// +// Filesystem options +// + +/// \def WITH_FILESYSTEM +/// Allows to enable/disable filesystem support to save code size +/// By default it is defined (filesystem support is enabled) +#define WITH_FILESYSTEM + +/// \def WITH_DEVFS +/// Allows to enable/disable DevFs support to save code size +/// By default it is defined (DevFs is enabled) +#define WITH_DEVFS + +/// \def SYNC_AFTER_WRITE +/// Increases filesystem write robustness. After each write operation the +/// filesystem is synced so that a power failure happens data is not lost +/// (unless power failure happens exactly between the write and the sync) +/// Unfortunately write latency and throughput becomes twice as worse +/// By default it is defined (slow but safe) +#define SYNC_AFTER_WRITE + +/// Maximum number of open files. Trying to open more will fail. +/// Cannot be lower than 3, as the first three are stdin, stdout, stderr +const unsigned char MAX_OPEN_FILES = 8; + +/// \def WITH_PROCESSES +/// If uncommented enables support for processes as well as threads. +/// This enables the dynamic loader to load elf programs, the extended system +/// call service and, if the hardware supports it, the MPU to provide memory +/// isolation of processes +//#define WITH_PROCESSES + +#if defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS) +#error Processes require C++ exception support +#endif // defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS) + +#if defined(WITH_PROCESSES) && !defined(WITH_FILESYSTEM) +#error Processes require filesystem support +#endif // defined(WITH_PROCESSES) && !defined(WITH_FILESYSTEM) + +#if defined(WITH_PROCESSES) && !defined(WITH_DEVFS) +#error Processes require devfs support +#endif // defined(WITH_PROCESSES) && !defined(WITH_DEVFS) + +// +// C/C++ standard library I/O (stdin, stdout and stderr related) +// + +/// \def WITH_BOOTLOG +/// Uncomment to print bootlogs on stdout. +/// By default it is defined (bootlogs are printed) +#define WITH_BOOTLOG + +/// \def WITH_ERRLOG +/// Uncomment for debug information on stdout. +/// By default it is defined (error information is printed) +#define WITH_ERRLOG + +// +// Kernel related options (stack sizes, priorities) +// + +/// \def WITH_DEEP_SLEEP +/// Adds interfaces and required variables to support deep sleep state switch +/// automatically when peripherals are not required +//#define WITH_DEEP_SLEEP + +/** + * \def JTAG_DISABLE_SLEEP + * JTAG debuggers lose communication with the device if it enters sleep + * mode, so to use debugging it is necessary to disable sleep in the idle + * thread. By default it is not defined (idle thread calls sleep). + */ +//#define JTAG_DISABLE_SLEEP + +#if defined(WITH_DEEP_SLEEP) && defined(JTAG_DISABLE_SLEEP) +#error Deep sleep cannot work together with jtag +#endif // defined(WITH_PROCESSES) && !defined(WITH_DEVFS) + +/// Minimum stack size (MUST be divisible by 4) +const unsigned int STACK_MIN = 256; + +/// \internal Size of idle thread stack. +/// Should be >=STACK_MIN (MUST be divisible by 4) +const unsigned int STACK_IDLE = 256; + +/// Default stack size for pthread_create. +/// The chosen value is enough to call C standard library functions +/// such as printf/fopen which are stack-heavy +const unsigned int STACK_DEFAULT_FOR_PTHREAD = 2048; + +/// Maximum size of the RAM image of a process. If a program requires more +/// the kernel will not run it (MUST be divisible by 4) +const unsigned int MAX_PROCESS_IMAGE_SIZE = 64 * 1024; + +/// Minimum size of the stack for a process. If a program specifies a lower +/// size the kernel will not run it (MUST be divisible by 4) +const unsigned int MIN_PROCESS_STACK_SIZE = STACK_MIN; + +/// Every userspace thread has two stacks, one for when it is running in +/// userspace and one for when it is running in kernelspace (that is, while it +/// is executing system calls). This is the size of the stack for when the +/// thread is running in kernelspace (MUST be divisible by 4) +const unsigned int SYSTEM_MODE_PROCESS_STACK_SIZE = 2 * 1024; + +/// Number of priorities (MUST be >1) +/// PRIORITY_MAX-1 is the highest priority, 0 is the lowest. -1 is reserved as +/// the priority of the idle thread. +/// The meaning of a thread's priority depends on the chosen scheduler. +#ifdef SCHED_TYPE_PRIORITY +// Can be modified, but a high value makes context switches more expensive +const short int PRIORITY_MAX = 4; +#elif defined(SCHED_TYPE_CONTROL_BASED) +// Don't touch, the limit is due to the fixed point implementation +// It's not needed for if floating point is selected, but kept for consistency +const short int PRIORITY_MAX = 64; +#else // SCHED_TYPE_EDF +// Doesn't exist for this kind of scheduler +#endif + +/// Priority of main() +/// The meaning of a thread's priority depends on the chosen scheduler. +const unsigned char MAIN_PRIORITY = 1; + +#ifdef SCHED_TYPE_PRIORITY +/// Maximum thread time slice in nanoseconds, after which preemption occurs +const unsigned int MAX_TIME_SLICE = 1000000; +#endif // SCHED_TYPE_PRIORITY + +// +// Other low level kernel options. There is usually no need to modify these. +// + +/// \internal Length of wartermark (in bytes) to check stack overflow. +/// MUST be divisible by 4 and can also be zero. +/// A high value increases context switch time. +const unsigned int WATERMARK_LEN = 16; + +/// \internal Used to fill watermark +const unsigned int WATERMARK_FILL = 0xaaaaaaaa; + +/// \internal Used to fill stack (for checking stack usage) +const unsigned int STACK_FILL = 0xbbbbbbbb; + +// Compiler version checks +#if !defined(_MIOSIX_GCC_PATCH_MAJOR) || _MIOSIX_GCC_PATCH_MAJOR < 3 +#error \ + "You are using a too old or unsupported compiler. Get the latest one from https://miosix.org/wiki/index.php?title=Miosix_Toolchain" +#endif +#if _MIOSIX_GCC_PATCH_MAJOR > 3 +#warning "You are using a too new compiler, which may not be supported" +#endif + +/** + * \} + */ + +} // namespace miosix diff --git a/src/bsps/stm32f767zi_compute_unit_v2/core/stage_1_boot.cpp b/src/bsps/stm32f767zi_compute_unit_v2/core/stage_1_boot.cpp new file mode 100644 index 000000000..83eac53b4 --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/core/stage_1_boot.cpp @@ -0,0 +1,505 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> + +#include "core/cache_cortexMx.h" +#include "core/interrupts.h" //For the unexpected interrupt call +#include "core/interrupts_cortexMx.h" +#include "interfaces/arch_registers.h" +#include "interfaces/bsp.h" +#include "kernel/stage_2_boot.h" + +/* + * startup.cpp + * STM32 C++ startup. + * NOTE: for stm32f767 devices ONLY. + * Supports interrupt handlers in C++ without extern "C" + * Developed by Terraneo Federico, based on ST startup code. + * Additionally modified to boot Miosix. + */ + +/** + * Called by Reset_Handler, performs initialization and calls main. + * Never returns. + */ +void program_startup() __attribute__((noreturn)); +void program_startup() +{ + // Cortex M7 core appears to get out of reset with interrupts already + // enabled + __disable_irq(); + + miosix::IRQconfigureCache((const unsigned int *)0xd0000000, + 8 * 1024 * 1024); + + // These are defined in the linker script + extern unsigned char _etext asm("_etext"); + extern unsigned char _data asm("_data"); + extern unsigned char _edata asm("_edata"); + extern unsigned char _bss_start asm("_bss_start"); + extern unsigned char _bss_end asm("_bss_end"); + + // Initialize .data section, clear .bss section + unsigned char *etext = &_etext; + unsigned char *data = &_data; + unsigned char *edata = &_edata; + unsigned char *bss_start = &_bss_start; + unsigned char *bss_end = &_bss_end; + memcpy(data, etext, edata - data); + memset(bss_start, 0, bss_end - bss_start); + + // Move on to stage 2 + _init(); + + // If main returns, reboot + NVIC_SystemReset(); + for (;;) + ; +} + +/** + * Reset handler, called by hardware immediately after reset + */ +void Reset_Handler() __attribute__((__interrupt__, noreturn)); +void Reset_Handler() +{ + /** + * SystemInit() is called *before* initializing .data and zeroing .bss + * Despite all startup files provided by ST do the opposite, there are three + * good reasons to do so: + * 1. First, the CMSIS specifications say that SystemInit() must not access + * global variables, so it is actually possible to call it before + * 2. Second, when running Miosix with the xram linker scripts .data and + * .bss are placed in the external RAM, so we *must* call SystemInit(), + * which enables xram, before touching .data and .bss + * 3. Third, this is a performance improvement since the loops that + * initialize .data and zeros .bss now run with the CPU at full speed + * instead of 8MHz + */ + SystemInit(); + +/** + * ST does not provide code to initialize the SDRAM at boot. + * Put after SystemInit() as SDRAM is timing-sensitive and needs the full + * clock speed. + */ +#ifdef __ENABLE_XRAM + miosix::configureSdram(); +#endif //__ENABLE_XRAM + + /* + * Load into the program stack pointer the heap end address and switch from + * the msp to sps. + * This is required for booting Miosix, a small portion of the top of the + * heap area will be used as stack until the first thread starts. After, + * this stack will be abandoned and the process stack will point to the + * current thread's stack. + */ + asm volatile( + "ldr r0, =_heap_end \n\t" + "msr psp, r0 \n\t" + "movw r0, #2 \n\n" // Set the control register to use + "msr control, r0 \n\t" // the process stack + "isb \n\t" :: + : "r0"); + + program_startup(); +} + +/** + * All unused interrupts call this function. + */ +extern "C" void Default_Handler() { unexpectedInterrupt(); } + +// System handlers +void /*__attribute__((weak))*/ Reset_Handler(); // These interrupts are not +void /*__attribute__((weak))*/ NMI_Handler(); // weak because they are +void /*__attribute__((weak))*/ HardFault_Handler(); // surely defined by Miosix +void /*__attribute__((weak))*/ MemManage_Handler(); +void /*__attribute__((weak))*/ BusFault_Handler(); +void /*__attribute__((weak))*/ UsageFault_Handler(); +void /*__attribute__((weak))*/ SVC_Handler(); +void /*__attribute__((weak))*/ DebugMon_Handler(); +void /*__attribute__((weak))*/ PendSV_Handler(); +void __attribute__((weak)) SysTick_Handler(); + +// Interrupt handlers +void __attribute__((weak)) WWDG_IRQHandler(); +void __attribute__((weak)) PVD_IRQHandler(); +void __attribute__((weak)) TAMP_STAMP_IRQHandler(); +void __attribute__((weak)) RTC_WKUP_IRQHandler(); +void __attribute__((weak)) FLASH_IRQHandler(); +void __attribute__((weak)) RCC_IRQHandler(); +void __attribute__((weak)) EXTI0_IRQHandler(); +void __attribute__((weak)) EXTI1_IRQHandler(); +void __attribute__((weak)) EXTI2_IRQHandler(); +void __attribute__((weak)) EXTI3_IRQHandler(); +void __attribute__((weak)) EXTI4_IRQHandler(); +void __attribute__((weak)) DMA1_Stream0_IRQHandler(); +void __attribute__((weak)) DMA1_Stream1_IRQHandler(); +void __attribute__((weak)) DMA1_Stream2_IRQHandler(); +void __attribute__((weak)) DMA1_Stream3_IRQHandler(); +void __attribute__((weak)) DMA1_Stream4_IRQHandler(); +void __attribute__((weak)) DMA1_Stream5_IRQHandler(); +void __attribute__((weak)) DMA1_Stream6_IRQHandler(); +void __attribute__((weak)) ADC_IRQHandler(); +void __attribute__((weak)) CAN1_TX_IRQHandler(); +void __attribute__((weak)) CAN1_RX0_IRQHandler(); +void __attribute__((weak)) CAN1_RX1_IRQHandler(); +void __attribute__((weak)) CAN1_SCE_IRQHandler(); +void __attribute__((weak)) EXTI9_5_IRQHandler(); +void __attribute__((weak)) TIM1_BRK_TIM9_IRQHandler(); +void __attribute__((weak)) TIM1_UP_TIM10_IRQHandler(); +void __attribute__((weak)) TIM1_TRG_COM_TIM11_IRQHandler(); +void __attribute__((weak)) TIM1_CC_IRQHandler(); +void __attribute__((weak)) TIM2_IRQHandler(); +void __attribute__((weak)) TIM3_IRQHandler(); +void __attribute__((weak)) TIM4_IRQHandler(); +void __attribute__((weak)) I2C1_EV_IRQHandler(); +void __attribute__((weak)) I2C1_ER_IRQHandler(); +void __attribute__((weak)) I2C2_EV_IRQHandler(); +void __attribute__((weak)) I2C2_ER_IRQHandler(); +void __attribute__((weak)) SPI1_IRQHandler(); +void __attribute__((weak)) SPI2_IRQHandler(); +void __attribute__((weak)) USART1_IRQHandler(); +void __attribute__((weak)) USART2_IRQHandler(); +void __attribute__((weak)) USART3_IRQHandler(); +void __attribute__((weak)) EXTI15_10_IRQHandler(); +void __attribute__((weak)) RTC_Alarm_IRQHandler(); +void __attribute__((weak)) OTG_FS_WKUP_IRQHandler(); +void __attribute__((weak)) TIM8_BRK_TIM12_IRQHandler(); +void __attribute__((weak)) TIM8_UP_TIM13_IRQHandler(); +void __attribute__((weak)) TIM8_TRG_COM_TIM14_IRQHandler(); +void __attribute__((weak)) TIM8_CC_IRQHandler(); +void __attribute__((weak)) DMA1_Stream7_IRQHandler(); +void __attribute__((weak)) FMC_IRQHandler(); +void __attribute__((weak)) SDMMC1_IRQHandler(); +void __attribute__((weak)) TIM5_IRQHandler(); +void __attribute__((weak)) SPI3_IRQHandler(); +void __attribute__((weak)) UART4_IRQHandler(); +void __attribute__((weak)) UART5_IRQHandler(); +void __attribute__((weak)) TIM6_DAC_IRQHandler(); +void __attribute__((weak)) TIM7_IRQHandler(); +void __attribute__((weak)) DMA2_Stream0_IRQHandler(); +void __attribute__((weak)) DMA2_Stream1_IRQHandler(); +void __attribute__((weak)) DMA2_Stream2_IRQHandler(); +void __attribute__((weak)) DMA2_Stream3_IRQHandler(); +void __attribute__((weak)) DMA2_Stream4_IRQHandler(); +void __attribute__((weak)) ETH_IRQHandler(); +void __attribute__((weak)) ETH_WKUP_IRQHandler(); +void __attribute__((weak)) CAN2_TX_IRQHandler(); +void __attribute__((weak)) CAN2_RX0_IRQHandler(); +void __attribute__((weak)) CAN2_RX1_IRQHandler(); +void __attribute__((weak)) CAN2_SCE_IRQHandler(); +void __attribute__((weak)) OTG_FS_IRQHandler(); +void __attribute__((weak)) DMA2_Stream5_IRQHandler(); +void __attribute__((weak)) DMA2_Stream6_IRQHandler(); +void __attribute__((weak)) DMA2_Stream7_IRQHandler(); +void __attribute__((weak)) USART6_IRQHandler(); +void __attribute__((weak)) I2C3_EV_IRQHandler(); +void __attribute__((weak)) I2C3_ER_IRQHandler(); +void __attribute__((weak)) OTG_HS_EP1_OUT_IRQHandler(); +void __attribute__((weak)) OTG_HS_EP1_IN_IRQHandler(); +void __attribute__((weak)) OTG_HS_WKUP_IRQHandler(); +void __attribute__((weak)) OTG_HS_IRQHandler(); +void __attribute__((weak)) DCMI_IRQHandler(); +void __attribute__((weak)) CRYP_IRQHandler(); +void __attribute__((weak)) RNG_IRQHandler(); +void __attribute__((weak)) FPU_IRQHandler(); +void __attribute__((weak)) UART7_IRQHandler(); +void __attribute__((weak)) UART8_IRQHandler(); +void __attribute__((weak)) SPI4_IRQHandler(); +void __attribute__((weak)) SPI5_IRQHandler(); +void __attribute__((weak)) SPI6_IRQHandler(); +void __attribute__((weak)) SAI1_IRQHandler(); +void __attribute__((weak)) LTDC_IRQHandler(); +void __attribute__((weak)) LTDC_ER_IRQHandler(); +void __attribute__((weak)) DMA2D_IRQHandler(); +void __attribute__((weak)) SAI2_IRQHandler(); +void __attribute__((weak)) QUADSPI_IRQHandler(); +void __attribute__((weak)) LPTIM1_IRQHandler(); +void __attribute__((weak)) CEC_IRQHandler(); +void __attribute__((weak)) I2C4_EV_IRQHandler(); +void __attribute__((weak)) I2C4_ER_IRQHandler(); +void __attribute__((weak)) SPDIF_RX_IRQHandler(); +void __attribute__((weak)) DSIHOST_IRQHandler(); +void __attribute__((weak)) DFSDM1_FLT0_IRQHandler(); +void __attribute__((weak)) DFSDM1_FLT1_IRQHandler(); +void __attribute__((weak)) DFSDM1_FLT2_IRQHandler(); +void __attribute__((weak)) DFSDM1_FLT3_IRQHandler(); +void __attribute__((weak)) SDMMC2_IRQHandler(); +void __attribute__((weak)) CAN3_TX_IRQHandler(); +void __attribute__((weak)) CAN3_RX0_IRQHandler(); +void __attribute__((weak)) CAN3_RX1_IRQHandler(); +void __attribute__((weak)) CAN3_SCE_IRQHandler(); +void __attribute__((weak)) JPEG_IRQHandler(); +void __attribute__((weak)) MDIOS_IRQHandler(); + +// Stack top, defined in the linker script +extern char _main_stack_top asm("_main_stack_top"); + +// Interrupt vectors, must be placed @ address 0x00000000 +// The extern declaration is required otherwise g++ optimizes it out +extern void (*const __Vectors[])(); +void (*const __Vectors[])() __attribute__((section(".isr_vector"))) = { + reinterpret_cast<void (*)()>(&_main_stack_top), /* Stack pointer*/ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* NMI Handler */ + HardFault_Handler, /* Hard Fault Handler */ + MemManage_Handler, /* MPU Fault Handler */ + BusFault_Handler, /* Bus Fault Handler */ + UsageFault_Handler, /* Usage Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* SVCall Handler */ + DebugMon_Handler, /* Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* PendSV Handler */ + SysTick_Handler, /* SysTick Handler */ + + /* External Interrupts */ + WWDG_IRQHandler, + PVD_IRQHandler, + TAMP_STAMP_IRQHandler, + RTC_WKUP_IRQHandler, + FLASH_IRQHandler, + RCC_IRQHandler, + EXTI0_IRQHandler, + EXTI1_IRQHandler, + EXTI2_IRQHandler, + EXTI3_IRQHandler, + EXTI4_IRQHandler, + DMA1_Stream0_IRQHandler, + DMA1_Stream1_IRQHandler, + DMA1_Stream2_IRQHandler, + DMA1_Stream3_IRQHandler, + DMA1_Stream4_IRQHandler, + DMA1_Stream5_IRQHandler, + DMA1_Stream6_IRQHandler, + ADC_IRQHandler, + CAN1_TX_IRQHandler, + CAN1_RX0_IRQHandler, + CAN1_RX1_IRQHandler, + CAN1_SCE_IRQHandler, + EXTI9_5_IRQHandler, + TIM1_BRK_TIM9_IRQHandler, + TIM1_UP_TIM10_IRQHandler, + TIM1_TRG_COM_TIM11_IRQHandler, + TIM1_CC_IRQHandler, + TIM2_IRQHandler, + TIM3_IRQHandler, + TIM4_IRQHandler, + I2C1_EV_IRQHandler, + I2C1_ER_IRQHandler, + I2C2_EV_IRQHandler, + I2C2_ER_IRQHandler, + SPI1_IRQHandler, + SPI2_IRQHandler, + USART1_IRQHandler, + USART2_IRQHandler, + USART3_IRQHandler, + EXTI15_10_IRQHandler, + RTC_Alarm_IRQHandler, + OTG_FS_WKUP_IRQHandler, + TIM8_BRK_TIM12_IRQHandler, + TIM8_UP_TIM13_IRQHandler, + TIM8_TRG_COM_TIM14_IRQHandler, + TIM8_CC_IRQHandler, + DMA1_Stream7_IRQHandler, + FMC_IRQHandler, + SDMMC1_IRQHandler, + TIM5_IRQHandler, + SPI3_IRQHandler, + UART4_IRQHandler, + UART5_IRQHandler, + TIM6_DAC_IRQHandler, + TIM7_IRQHandler, + DMA2_Stream0_IRQHandler, + DMA2_Stream1_IRQHandler, + DMA2_Stream2_IRQHandler, + DMA2_Stream3_IRQHandler, + DMA2_Stream4_IRQHandler, + ETH_IRQHandler, + ETH_WKUP_IRQHandler, + CAN2_TX_IRQHandler, + CAN2_RX0_IRQHandler, + CAN2_RX1_IRQHandler, + CAN2_SCE_IRQHandler, + OTG_FS_IRQHandler, + DMA2_Stream5_IRQHandler, + DMA2_Stream6_IRQHandler, + DMA2_Stream7_IRQHandler, + USART6_IRQHandler, + I2C3_EV_IRQHandler, + I2C3_ER_IRQHandler, + OTG_HS_EP1_OUT_IRQHandler, + OTG_HS_EP1_IN_IRQHandler, + OTG_HS_WKUP_IRQHandler, + OTG_HS_IRQHandler, + DCMI_IRQHandler, + CRYP_IRQHandler, + RNG_IRQHandler, + FPU_IRQHandler, + UART7_IRQHandler, + UART8_IRQHandler, + SPI4_IRQHandler, + SPI5_IRQHandler, + SPI6_IRQHandler, + SAI1_IRQHandler, + LTDC_IRQHandler, + LTDC_ER_IRQHandler, + DMA2D_IRQHandler, + SAI2_IRQHandler, + QUADSPI_IRQHandler, + LPTIM1_IRQHandler, + CEC_IRQHandler, + I2C4_EV_IRQHandler, + I2C4_ER_IRQHandler, + SPDIF_RX_IRQHandler, + DSIHOST_IRQHandler, + DFSDM1_FLT0_IRQHandler, + DFSDM1_FLT1_IRQHandler, + DFSDM1_FLT2_IRQHandler, + DFSDM1_FLT3_IRQHandler, + SDMMC2_IRQHandler, + CAN3_TX_IRQHandler, + CAN3_RX0_IRQHandler, + CAN3_RX1_IRQHandler, + CAN3_SCE_IRQHandler, + JPEG_IRQHandler, + MDIOS_IRQHandler, +}; + +#pragma weak SysTick_IRQHandler = Default_Handler +#pragma weak WWDG_IRQHandler = Default_Handler +#pragma weak PVD_IRQHandler = Default_Handler +#pragma weak TAMP_STAMP_IRQHandler = Default_Handler +#pragma weak RTC_WKUP_IRQHandler = Default_Handler +#pragma weak FLASH_IRQHandler = Default_Handler +#pragma weak RCC_IRQHandler = Default_Handler +#pragma weak EXTI0_IRQHandler = Default_Handler +#pragma weak EXTI1_IRQHandler = Default_Handler +#pragma weak EXTI2_IRQHandler = Default_Handler +#pragma weak EXTI3_IRQHandler = Default_Handler +#pragma weak EXTI4_IRQHandler = Default_Handler +#pragma weak DMA1_Stream0_IRQHandler = Default_Handler +#pragma weak DMA1_Stream1_IRQHandler = Default_Handler +#pragma weak DMA1_Stream2_IRQHandler = Default_Handler +#pragma weak DMA1_Stream3_IRQHandler = Default_Handler +#pragma weak DMA1_Stream4_IRQHandler = Default_Handler +#pragma weak DMA1_Stream5_IRQHandler = Default_Handler +#pragma weak DMA1_Stream6_IRQHandler = Default_Handler +#pragma weak ADC_IRQHandler = Default_Handler +#pragma weak CAN1_TX_IRQHandler = Default_Handler +#pragma weak CAN1_RX0_IRQHandler = Default_Handler +#pragma weak CAN1_RX1_IRQHandler = Default_Handler +#pragma weak CAN1_SCE_IRQHandler = Default_Handler +#pragma weak EXTI9_5_IRQHandler = Default_Handler +#pragma weak TIM1_BRK_TIM9_IRQHandler = Default_Handler +#pragma weak TIM1_UP_TIM10_IRQHandler = Default_Handler +#pragma weak TIM1_TRG_COM_TIM11_IRQHandler = Default_Handler +#pragma weak TIM1_CC_IRQHandler = Default_Handler +#pragma weak TIM2_IRQHandler = Default_Handler +#pragma weak TIM3_IRQHandler = Default_Handler +#pragma weak TIM4_IRQHandler = Default_Handler +#pragma weak I2C1_EV_IRQHandler = Default_Handler +#pragma weak I2C1_ER_IRQHandler = Default_Handler +#pragma weak I2C2_EV_IRQHandler = Default_Handler +#pragma weak I2C2_ER_IRQHandler = Default_Handler +#pragma weak SPI1_IRQHandler = Default_Handler +#pragma weak SPI2_IRQHandler = Default_Handler +// #pragma weak USART1_IRQHandler = Default_Handler +// #pragma weak USART2_IRQHandler = Default_Handler +// #pragma weak USART3_IRQHandler = Default_Handler +#pragma weak EXTI15_10_IRQHandler = Default_Handler +#pragma weak RTC_Alarm_IRQHandler = Default_Handler +#pragma weak OTG_FS_WKUP_IRQHandler = Default_Handler +#pragma weak TIM8_BRK_TIM12_IRQHandler = Default_Handler +#pragma weak TIM8_UP_TIM13_IRQHandler = Default_Handler +#pragma weak TIM8_TRG_COM_TIM14_IRQHandler = Default_Handler +#pragma weak TIM8_CC_IRQHandler = Default_Handler +#pragma weak DMA1_Stream7_IRQHandler = Default_Handler +#pragma weak FMC_IRQHandler = Default_Handler +#pragma weak SDMMC1_IRQHandler = Default_Handler +#pragma weak TIM5_IRQHandler = Default_Handler +#pragma weak SPI3_IRQHandler = Default_Handler +// #pragma weak UART4_IRQHandler = Default_Handler +// #pragma weak UART5_IRQHandler = Default_Handler +#pragma weak TIM6_DAC_IRQHandler = Default_Handler +#pragma weak TIM7_IRQHandler = Default_Handler +#pragma weak DMA2_Stream0_IRQHandler = Default_Handler +#pragma weak DMA2_Stream1_IRQHandler = Default_Handler +#pragma weak DMA2_Stream2_IRQHandler = Default_Handler +#pragma weak DMA2_Stream3_IRQHandler = Default_Handler +#pragma weak DMA2_Stream4_IRQHandler = Default_Handler +#pragma weak ETH_IRQHandler = Default_Handler +#pragma weak ETH_WKUP_IRQHandler = Default_Handler +#pragma weak CAN2_TX_IRQHandler = Default_Handler +#pragma weak CAN2_RX0_IRQHandler = Default_Handler +#pragma weak CAN2_RX1_IRQHandler = Default_Handler +#pragma weak CAN2_SCE_IRQHandler = Default_Handler +#pragma weak OTG_FS_IRQHandler = Default_Handler +#pragma weak DMA2_Stream5_IRQHandler = Default_Handler +#pragma weak DMA2_Stream6_IRQHandler = Default_Handler +#pragma weak DMA2_Stream7_IRQHandler = Default_Handler +// #pragma weak USART6_IRQHandler = Default_Handler +#pragma weak I2C3_EV_IRQHandler = Default_Handler +#pragma weak I2C3_ER_IRQHandler = Default_Handler +#pragma weak OTG_HS_EP1_OUT_IRQHandler = Default_Handler +#pragma weak OTG_HS_EP1_IN_IRQHandler = Default_Handler +#pragma weak OTG_HS_WKUP_IRQHandler = Default_Handler +#pragma weak OTG_HS_IRQHandler = Default_Handler +#pragma weak DCMI_IRQHandler = Default_Handler +#pragma weak CRYP_IRQHandler = Default_Handler +#pragma weak RNG_IRQHandler = Default_Handler +#pragma weak FPU_IRQHandler = Default_Handler +// #pragma weak UART7_IRQHandler = Default_Handler +// #pragma weak UART8_IRQHandler = Default_Handler +#pragma weak SPI4_IRQHandler = Default_Handler +#pragma weak SPI5_IRQHandler = Default_Handler +#pragma weak SPI6_IRQHandler = Default_Handler +#pragma weak SAI1_IRQHandler = Default_Handler +#pragma weak LTDC_IRQHandler = Default_Handler +#pragma weak LTDC_ER_IRQHandler = Default_Handler +#pragma weak DMA2D_IRQHandler = Default_Handler +#pragma weak SAI2_IRQHandler = Default_Handler +#pragma weak QUADSPI_IRQHandler = Default_Handler +#pragma weak LPTIM1_IRQHandler = Default_Handler +#pragma weak CEC_IRQHandler = Default_Handler +#pragma weak I2C4_EV_IRQHandler = Default_Handler +#pragma weak I2C4_ER_IRQHandler = Default_Handler +#pragma weak SPDIF_RX_IRQHandler = Default_Handler +#pragma weak DSIHOST_IRQHandler = Default_Handler +#pragma weak DFSDM1_FLT0_IRQHandler = Default_Handler +#pragma weak DFSDM1_FLT1_IRQHandler = Default_Handler +#pragma weak DFSDM1_FLT2_IRQHandler = Default_Handler +#pragma weak DFSDM1_FLT3_IRQHandler = Default_Handler +#pragma weak SDMMC2_IRQHandler = Default_Handler +#pragma weak CAN3_TX_IRQHandler = Default_Handler +#pragma weak CAN3_RX0_IRQHandler = Default_Handler +#pragma weak CAN3_RX1_IRQHandler = Default_Handler +#pragma weak CAN3_SCE_IRQHandler = Default_Handler +#pragma weak JPEG_IRQHandler = Default_Handler +#pragma weak MDIOS_IRQHandler = Default_Handler diff --git a/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/arch_registers_impl.h b/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/arch_registers_impl.h new file mode 100644 index 000000000..3224edc9e --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/arch_registers_impl.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ARCH_REGISTERS_IMPL_H +#define ARCH_REGISTERS_IMPL_H + +// stm32f7xx.h defines a few macros like __ICACHE_PRESENT, __DCACHE_PRESENT and +// includes core_cm7.h. Do not include core_cm7.h before. +#define STM32F767xx +#include "CMSIS/Device/ST/STM32F7xx/Include/stm32f7xx.h" + +#if (__ICACHE_PRESENT != 1) || (__DCACHE_PRESENT != 1) +#error "Wrong include order" +#endif + +#include "CMSIS/Device/ST/STM32F7xx/Include/system_stm32f7xx.h" + +#define RCC_SYNC() __DSB() // TODO: can this dsb be removed? + +#endif // ARCH_REGISTERS_IMPL_H diff --git a/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp.cpp new file mode 100644 index 000000000..366e5457e --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp.cpp @@ -0,0 +1,304 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Alberto Nidasio, Davide Mor + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/*********************************************************************** + * bsp.cpp Part of the Miosix Embedded OS. + * Board support package, this file initializes hardware. + ************************************************************************/ + +#include "interfaces/bsp.h" + +#include <inttypes.h> +#include <sys/ioctl.h> + +#include <cstdlib> + +#include "board_settings.h" +#include "config/miosix_settings.h" +#include "drivers/sd_stm32f2_f4_f7.h" +#include "drivers/serial.h" +#include "drivers/serial_stm32.h" +#include "drivers/stm32_sgm.h" +#include "filesystem/console/console_device.h" +#include "filesystem/file_access.h" +#include "interfaces/arch_registers.h" +#include "interfaces/delays.h" +#include "interfaces/portability.h" +#include "kernel/kernel.h" +#include "kernel/logging.h" +#include "kernel/sync.h" + +namespace miosix +{ + +// +// Initialization +// + +static void sdramCommandWait() +{ + for (int i = 0; i < 0xffff; i++) + if ((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) == 0) + return; +} + +void configureSdram() +{ + // Enable gpios used by the ram + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN | + RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN | + RCC_AHB1ENR_GPIOFEN | RCC_AHB1ENR_GPIOGEN; + RCC_SYNC(); + + // On the compute unit with F767ZI, the SDRAM pins are: + // - PG8: FMC_SDCLK (sdram clock) + // - PB5: FMC_SDCKE1 (sdram bank 2 clock enable) + // - PB6: FMC_SDNE1 (sdram bank 2 chip enable) + // - PF0: FMC_A0 + // - PF1: FMC_A1 + // - PF2: FMC_A2 + // - PF3: FMC_A3 + // - PF4: FMC_A4 + // - PF5: FMC_A5 + // - PF12: FMC_A6 + // - PF13: FMC_A7 + // - PF14: FMC_A8 + // - PF15: FMC_A9 + // - PG0: FMC_A10 + // - PG1: FMC_A11 + // - PG2: FMC_A12 (used only by the 32MB ram, not by the 8MB one) + // - PD14: FMC_D0 + // - PD15: FMC_D1 + // - PD0: FMC_D2 + // - PD1: FMC_D3 + // - PE7: FMC_D4 + // - PE8: FMC_D5 + // - PE9: FMC_D6 + // - PE10: FMC_D7 + // - PE11: FMC_D8 + // - PE12: FMC_D9 + // - PE13: FMC_D10 + // - PE14: FMC_D11 + // - PE15: FMC_D12 + // - PD8: FMC_D13 + // - PD9: FMC_D14 + // - PD10: FMC_D15 + + // - PG4: FMC_BA0 + // - PG5: FMC_BA1 + // - PF11: FMC_SDNRAS + // - PG15: FMC_SDNCAS + // - PC0: FMC_SDNWE + // - PE0: FMC_NBL0 + // - PE1: FMC_NBL1 + + // All SDRAM GPIOs needs to be configured with alternate function 12 and + // maximum speed + + // WARNING: The current configuration is for the 8MB ram + + // Alternate functions + GPIOB->AFR[0] = 0x0cc00000; + GPIOC->AFR[0] = 0x0000000c; + GPIOD->AFR[0] = 0x000000cc; + GPIOD->AFR[1] = 0xcc000ccc; + GPIOE->AFR[0] = 0xc00000cc; + GPIOE->AFR[1] = 0xcccccccc; + GPIOF->AFR[0] = 0x00cccccc; + GPIOF->AFR[1] = 0xccccc000; + GPIOG->AFR[0] = 0x00cc0ccc; + GPIOG->AFR[1] = 0xc000000c; + + // Mode + GPIOB->MODER = 0x00002800; + GPIOC->MODER = 0x00000002; + GPIOD->MODER = 0xa02a000a; + GPIOE->MODER = 0xaaaa800a; + GPIOF->MODER = 0xaa800aaa; + GPIOG->MODER = 0x80020a2a; + + // Speed (high speed for all, very high speed for SDRAM pins) + GPIOB->OSPEEDR = 0x00003c00; + GPIOC->OSPEEDR = 0x00000003; + GPIOD->OSPEEDR = 0xf03f000f; + GPIOE->OSPEEDR = 0xffffc00f; + GPIOF->OSPEEDR = 0xffc00fff; + GPIOG->OSPEEDR = 0xc0030f3f; + + // Since we'we un-configured PB3 and PB4 (by default they are SWO and NJRST) + // finish the job and remove the default pull-up + GPIOB->PUPDR = 0; + + // Enable the SDRAM controller clock + RCC->AHB3ENR |= RCC_AHB3ENR_FMCEN; + RCC_SYNC(); + + // The SDRAM is a AS4C16M16SA-6TIN + // 16Mx16bit = 256Mb = 32MB + // HCLK = 216MHz -> SDRAM clock = HCLK/2 = 108MHz + + // 1. Memory device features + FMC_Bank5_6->SDCR[0] = 0 // 0 delay after CAS latency + | FMC_SDCR1_RBURST // Enable read bursts + | FMC_SDCR1_SDCLK_1; // SDCLK = HCLK / 2 + FMC_Bank5_6->SDCR[1] = 0 // Write accesses allowed + | FMC_SDCR2_CAS_1 // 2 cycles CAS latency + | FMC_SDCR2_NB // 4 internal banks + | FMC_SDCR2_MWID_0 // 16 bit data bus + | FMC_SDCR2_NR_1 // 13 bit row address + | FMC_SDCR2_NC_0; // 9 bit column address + +// 2. Memory device timings +#ifdef SYSCLK_FREQ_216MHz + // SDRAM timings. One clock cycle is 9.26ns + FMC_Bank5_6->SDTR[0] = + (2 - 1) << FMC_SDTR1_TRP_Pos // 2 cycles TRP (18.52ns > 18ns) + | (7 - 1) << FMC_SDTR1_TRC_Pos; // 7 cycles TRC (64.82ns > 60ns) + FMC_Bank5_6->SDTR[1] = + (2 - 1) << FMC_SDTR1_TRCD_Pos // 2 cycles TRCD (18.52ns > 18ns) + | (2 - 1) << FMC_SDTR1_TWR_Pos // 2 cycles TWR (min 2cc > 12ns) + | (5 - 1) << FMC_SDTR1_TRAS_Pos // 5 cycles TRAS (46.3ns > 42ns) + | (7 - 1) << FMC_SDTR1_TXSR_Pos // 7 cycles TXSR (74.08ns > 61.5ns) + | (2 - 1) << FMC_SDTR1_TMRD_Pos; // 2 cycles TMRD (min 2cc > 12ns) +#else +#error No SDRAM timings for this clock +#endif + + // 3. Enable the bank 2 clock + FMC_Bank5_6->SDCMR = + 0b001 << FMC_SDCMR_MODE_Pos // Clock Configuration Enable + | FMC_SDCMR_CTB2; // Bank 2 + sdramCommandWait(); + + // 4. Wait during command execution + delayUs(100); + + // 5. Issue a "Precharge All" command + FMC_Bank5_6->SDCMR = 0b010 << FMC_SDCMR_MODE_Pos // Precharge all + | FMC_SDCMR_CTB2; // Bank 2 + sdramCommandWait(); + + // 6. Issue Auto-Refresh commands + FMC_Bank5_6->SDCMR = 0b011 << FMC_SDCMR_MODE_Pos // Auto-Refresh + | FMC_SDCMR_CTB2 // Bank 2 + | (8 - 1) << FMC_SDCMR_NRFS_Pos; // 8 Auto-Refresh + sdramCommandWait(); + + // 7. Issue a Load Mode Register command + FMC_Bank5_6->SDCMR = + 0b100 << FMC_SDCMR_MODE_Pos // Load mode register + | FMC_SDCMR_CTB2 // Bank 2 + | 0 << FMC_SDCMR_MRD_Pos // Burst length = 1 + | (0b010 << 4) << FMC_SDCMR_MRD_Pos // CAS = 2 clocks, + | (1 << 9) << FMC_SDCMR_MRD_Pos; // Single bit write burst mode + sdramCommandWait(); + +// 8. Program the refresh rate (4K / 32ms) +// 64ms / 8192 = 7.8125us +#ifdef SYSCLK_FREQ_216MHz + // 7.8125us * 133MHz = 1039 - 20 = 1019 + FMC_Bank5_6->SDRTR = 1019 << FMC_SDRTR_COUNT_Pos; +#else +#error No SDRAM refresh timings for this clock +#endif +} + +void IRQbspInit() +{ + // Enable USART1 pins port + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; + + userLed1::mode(Mode::OUTPUT); + userLed2::mode(Mode::OUTPUT); + userLed3::mode(Mode::OUTPUT); + userLed4::mode(Mode::OUTPUT); + + DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>(new STM32Serial( + defaultSerial, defaultSerialSpeed, STM32Serial::NOFLOWCTRL))); +} + +void bspInit2() +{ +#ifdef WITH_FILESYSTEM + basicFilesystemSetup(SDIODriver::instance()); +#endif // WITH_FILESYSTEM + +#ifdef WITH_BACKUP_SRAM + // Print the reset reason + bootlog("Reset reson: "); + switch (SGM::instance().lastResetReason()) + { + case ResetReason::RST_LOW_PWR: + bootlog("low power\n"); + break; + case ResetReason::RST_WINDOW_WDG: + bootlog("window watchdog\n"); + break; + case ResetReason::RST_INDEPENDENT_WDG: + bootlog("indeendent watchdog\n"); + break; + case ResetReason::RST_SW: + bootlog("software reset\n"); + break; + case ResetReason::RST_POWER_ON: + bootlog("power on\n"); + break; + case ResetReason::RST_PIN: + bootlog("reset pin\n"); + break; + case ResetReason::RST_UNKNOWN: + bootlog("unknown\n"); + break; + } +#endif // WITH_BACKUP_SRAM +} + +// +// Shutdown and reboot +// + +void shutdown() +{ + ioctl(STDOUT_FILENO, IOCTL_SYNC, 0); + +#ifdef WITH_FILESYSTEM + FilesystemManager::instance().umountAll(); +#endif // WITH_FILESYSTEM + + disableInterrupts(); + for (;;) + ; +} + +void reboot() +{ + ioctl(STDOUT_FILENO, IOCTL_SYNC, 0); + +#ifdef WITH_FILESYSTEM + FilesystemManager::instance().umountAll(); +#endif // WITH_FILESYSTEM + + disableInterrupts(); + miosix_private::IRQsystemReboot(); +} + +} // namespace miosix diff --git a/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp_impl.h b/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp_impl.h new file mode 100644 index 000000000..feb02c128 --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/interfaces-impl/bsp_impl.h @@ -0,0 +1,108 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Davide Mor + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/*************************************************************************** + * bsp_impl.h Part of the Miosix Embedded OS. + * Board support package, this file initializes hardware. + ***************************************************************************/ + +#ifndef BSP_IMPL_H +#define BSP_IMPL_H + +#include "config/miosix_settings.h" +#include "interfaces/gpio.h" + +namespace miosix +{ + +/** +\addtogroup Hardware +\{ +*/ + +/** + * \internal + * Called by stage_1_boot.cpp to enable the SDRAM before initializing .data/.bss + * Requires the CPU clock to be already configured (running from the PLL) + */ +void configureSdram(); + +/** + * \internal + * Board pin definition + */ +typedef Gpio<GPIOC_BASE, 15> userLed1; +typedef Gpio<GPIOC_BASE, 2> userLed2; +typedef Gpio<GPIOC_BASE, 13> userLed3; +typedef Gpio<GPIOC_BASE, 14> userLed4; + +inline void led1On() { userLed1::high(); } + +inline void led1Off() { userLed1::low(); } + +inline void led2On() { userLed2::high(); } + +inline void led2Off() { userLed2::low(); } + +inline void led3On() { userLed3::high(); } + +inline void led3Off() { userLed3::low(); } + +inline void led4On() { userLed4::high(); } + +inline void led4Off() { userLed4::low(); } + +inline void ledOn() +{ + led1On(); + led2On(); + led3On(); + led4On(); +} + +inline void ledOff() +{ + led1Off(); + led2Off(); + led3Off(); + led4Off(); +} + +/** + * Polls the SD card sense GPIO. + * + * This board has no SD card whatsoever, but a card can be connected to the + * following GPIOs: + * TODO: never tested + * + * \return true. As there's no SD card sense switch, let's pretend that + * the card is present. + */ +inline bool sdCardSense() { return true; } + +/** +\} +*/ + +} // namespace miosix + +#endif // BSP_IMPL_H diff --git a/src/bsps/stm32f767zi_compute_unit_v2/stm32_2m+32m_xram.ld b/src/bsps/stm32f767zi_compute_unit_v2/stm32_2m+32m_xram.ld new file mode 100644 index 000000000..044ba1c62 --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/stm32_2m+32m_xram.ld @@ -0,0 +1,190 @@ +/* + * C++ enabled linker script for stm32f767zi (2M FLASH, 512K RAM, 32MB XRAM) + * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel + */ + +/* + * This linker script puts: + * - read only data and code (.text, .rodata, .eh_*) in FLASH + * - the 512Byte main (IRQ) stack, .data and .bss in the DTCM 128KB RAM + * - .data, .bss, stacks and heap in the external 32MB SDRAM. + */ + +/* + * The main stack is used for interrupt handling by the kernel. + * + * *** Readme *** + * This linker script places the main stack (used by the kernel for interrupts) + * at the bottom of the ram, instead of the top. This is done for two reasons: + * + * - as an optimization for microcontrollers with little ram memory. In fact + * the implementation of malloc from newlib requests memory to the OS in 4KB + * block (except the first block that can be smaller). This is probably done + * for compatibility with OSes with an MMU and paged memory. To see why this + * is bad, consider a microcontroller with 8KB of ram: when malloc finishes + * up the first 4KB it will call _sbrk_r asking for a 4KB block, but this will + * fail because the top part of the ram is used by the main stack. As a + * result, the top part of the memory will not be used by malloc, even if + * available (and it is nearly *half* the ram on an 8KB mcu). By placing the + * main stack at the bottom of the ram, the upper 4KB block will be entirely + * free and available as heap space. + * + * - In case of main stack overflow the cpu will fault because access to memory + * before the beginning of the ram faults. Instead with the default stack + * placement the main stack will silently collide with the heap. + * Note: if increasing the main stack size also increase the ORIGIN value in + * the MEMORY definitions below accordingly. + */ + +_main_stack_size = 512; /* main stack = 512Bytes */ +_main_stack_top = 0x20000000 + _main_stack_size; +ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error"); + +/* Mapping the heap into XRAM */ +_heap_end = 0xd0000000 + 32M; /* end of available ram */ + +/* Identify the Entry Point */ +ENTRY(_Z13Reset_Handlerv) + +/* + * Specify the memory areas + * + * NOTE: starting at 0x20000000 there's 128KB of DTCM (Data Tightly Coupled + * Memory). Technically, we could use this as normal RAM as there's a way for + * the DMA to access it, but the datasheet is unclear about performance + * penalties for doing so. To avoid nonuniform DMA memory access latencies, + * we leave this 128KB DTCM unused except for the first 512Bytes which are for + * the interrupt stack. This leaves us with 384KB of RAM + */ +MEMORY +{ + xram(wx) : ORIGIN = 0xd0000000, LENGTH = 32M + sram(wx) : ORIGIN = 0x20020000, LENGTH = 384K + dtcm(wx) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for main stack */ + bram(rw) : ORIGIN = 0x40024000, LENGTH = 4K /* Bakup SRAM */ + flash(rx) : ORIGIN = 0x08000000, LENGTH = 2M +} + +/* now define the output sections */ +SECTIONS +{ + . = 0; + + /* .text section: code goes to flash */ + .text : + { + /* Startup code must go at address 0 */ + KEEP(*(.isr_vector)) + + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + /* these sections for thumb interwork? */ + *(.glue_7) + *(.glue_7t) + /* these sections for C++? */ + *(.gcc_except_table) + *(.gcc_except_table.*) + *(.ARM.extab*) + *(.gnu.linkonce.armextab.*) + + . = ALIGN(4); + /* .rodata: constant data */ + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + + /* C++ Static constructors/destructors (eabi) */ + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __miosix_init_array_start = .; + KEEP (*(SORT(.miosix_init_array.*))) + KEEP (*(.miosix_init_array)) + __miosix_init_array_end = .; + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + /* C++ Static constructors/destructors (elf) */ + . = ALIGN(4); + _ctor_start = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + _ctor_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > flash + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > flash + __exidx_end = .; + + /* + * .data section: global variables go to xram, but also store a copy to + * flash to initialize them + */ + .data : ALIGN(8) + { + _data = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + _edata = .; + } > xram AT > flash + _etext = LOADADDR(.data); + + /* .bss section: uninitialized global variables go to xram */ + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + . = ALIGN(8); + } > xram + _bss_end = .; + + _end = .; + PROVIDE(end = .); + + .preserve(NOLOAD) : ALIGN(4) + { + _preserve_start = .; + . = ALIGN(4); + *(.preserve); + *(.preserve*); + . = ALIGN(4); + _preserve_end = .; + } > bram +} diff --git a/src/bsps/stm32f767zi_compute_unit_v2/stm32_2m+384k_ram.ld b/src/bsps/stm32f767zi_compute_unit_v2/stm32_2m+384k_ram.ld new file mode 100644 index 000000000..497bd5198 --- /dev/null +++ b/src/bsps/stm32f767zi_compute_unit_v2/stm32_2m+384k_ram.ld @@ -0,0 +1,189 @@ +/* + * C++ enabled linker script for stm32f767zi (2M FLASH, 512K RAM) + * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel + */ + +/* + * This linker script puts: + * - read only data and code (.text, .rodata, .eh_*) in FLASH + * - the 512Byte main (IRQ) stack, .data and .bss in the DTCM 128KB RAM + * - .data, .bss, stacks and heap in the internal RAM. + */ + +/* + * The main stack is used for interrupt handling by the kernel. + * + * *** Readme *** + * This linker script places the main stack (used by the kernel for interrupts) + * at the bottom of the ram, instead of the top. This is done for two reasons: + * + * - as an optimization for microcontrollers with little ram memory. In fact + * the implementation of malloc from newlib requests memory to the OS in 4KB + * block (except the first block that can be smaller). This is probably done + * for compatibility with OSes with an MMU and paged memory. To see why this + * is bad, consider a microcontroller with 8KB of ram: when malloc finishes + * up the first 4KB it will call _sbrk_r asking for a 4KB block, but this will + * fail because the top part of the ram is used by the main stack. As a + * result, the top part of the memory will not be used by malloc, even if + * available (and it is nearly *half* the ram on an 8KB mcu). By placing the + * main stack at the bottom of the ram, the upper 4KB block will be entirely + * free and available as heap space. + * + * - In case of main stack overflow the cpu will fault because access to memory + * before the beginning of the ram faults. Instead with the default stack + * placement the main stack will silently collide with the heap. + * Note: if increasing the main stack size also increase the ORIGIN value in + * the MEMORY definitions below accordingly. + */ + +_main_stack_size = 512; /* main stack = 512Bytes */ +_main_stack_top = 0x20000000 + _main_stack_size; +ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error"); + +/* Mapping the heap to the end of SRAM2 */ +_heap_end = 0x20000000 + 512K; /* end of available ram */ + +/* Identify the Entry Point */ +ENTRY(_Z13Reset_Handlerv) + +/* + * Specify the memory areas + * + * NOTE: starting at 0x20000000 there's 128KB of DTCM (Data Tightly Coupled + * Memory). Technically, we could use this as normal RAM as there's a way for + * the DMA to access it, but the datasheet is unclear about performance + * penalties for doing so. To avoid nonuniform DMA memory access latencies, + * we leave this 128KB DTCM unused except for the first 512Bytes which are for + * the interrupt stack. This leaves us with 384KB of RAM + */ +MEMORY +{ + sram(wx) : ORIGIN = 0x20020000, LENGTH = 384K + dtcm(wx) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for main stack */ + bram(rw) : ORIGIN = 0x40024000, LENGTH = 4K /* Bakup SRAM */ + flash(rx) : ORIGIN = 0x08000000, LENGTH = 2M +} + +/* now define the output sections */ +SECTIONS +{ + . = 0; + + /* .text section: code goes to flash */ + .text : + { + /* Startup code must go at address 0 */ + KEEP(*(.isr_vector)) + + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + /* these sections for thumb interwork? */ + *(.glue_7) + *(.glue_7t) + /* these sections for C++? */ + *(.gcc_except_table) + *(.gcc_except_table.*) + *(.ARM.extab*) + *(.gnu.linkonce.armextab.*) + + . = ALIGN(4); + /* .rodata: constant data */ + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + + /* C++ Static constructors/destructors (eabi) */ + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __miosix_init_array_start = .; + KEEP (*(SORT(.miosix_init_array.*))) + KEEP (*(.miosix_init_array)) + __miosix_init_array_end = .; + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + /* C++ Static constructors/destructors (elf) */ + . = ALIGN(4); + _ctor_start = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + _ctor_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > flash + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > flash + __exidx_end = .; + + /* + * .data section: global variables go to sram, but also store a copy to + * flash to initialize them + */ + .data : ALIGN(8) + { + _data = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + _edata = .; + } > sram AT > flash + _etext = LOADADDR(.data); + + /* .bss section: uninitialized global variables go to sram */ + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + . = ALIGN(8); + } > sram + _bss_end = .; + + _end = .; + PROVIDE(end = .); + + .preserve(NOLOAD) : ALIGN(4) + { + _preserve_start = .; + . = ALIGN(4); + *(.preserve); + *(.preserve*); + . = ALIGN(4); + _preserve_end = .; + } > bram +} diff --git a/src/entrypoints/compute-unit-v2-testsuite.cpp b/src/entrypoints/compute-unit-v2-testsuite.cpp new file mode 100644 index 000000000..424240b46 --- /dev/null +++ b/src/entrypoints/compute-unit-v2-testsuite.cpp @@ -0,0 +1,580 @@ +/* Copyright (c) 2024 Skyward Experimental Rocketry + * Author: Davide Mor, Emilio Corigliano + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include <interfaces-impl/bsp_impl.h> +#include <miosix.h> + +#include <array> +#include <atomic> +#include <cstdint> +#include <cstdio> +#include <thread> + +using namespace miosix; + +struct PinDef +{ + GpioPin pin; + const char *gpio_name; + const char *conan_name; + // ADRIANOOOOOOOOOOOOOOOO + const char *breakout_v1_name; +}; + +std::array<PinDef, 53> PIN_DEFS{{ + {Gpio<GPIOA_BASE, 0>::getPin(), "PA0", "PIN57", "PIN13"}, + {Gpio<GPIOA_BASE, 1>::getPin(), "PA1", "PIN55", "PIN15"}, + {Gpio<GPIOA_BASE, 2>::getPin(), "PA2", "PIN62", "PIN8"}, + {Gpio<GPIOA_BASE, 3>::getPin(), "PA3", "PIN60", "PIN10"}, + {Gpio<GPIOA_BASE, 4>::getPin(), "PA4", "PIN58", "PIN12"}, + {Gpio<GPIOA_BASE, 5>::getPin(), "PA5", "PIN56", "PIN14"}, + {Gpio<GPIOA_BASE, 6>::getPin(), "PA6", "PIN54", "PIN16"}, + {Gpio<GPIOA_BASE, 7>::getPin(), "PA7", "PIN52", "PIN18"}, + {Gpio<GPIOA_BASE, 8>::getPin(), "PA8", "PIN33", "PIN37"}, + // {Gpio<GPIOA_BASE, 9>::getPin(), "PA9", "PIN36", "PIN"}, Miosix serial + // {Gpio<GPIOA_BASE, 10>::getPin(), "PA10", "PIN34", "PIN"}, Miosix serial + {Gpio<GPIOA_BASE, 11>::getPin(), "PA11", "PIN27", "PIN43"}, + {Gpio<GPIOA_BASE, 12>::getPin(), "PA12", "PIN30", "PIN40"}, + // {Gpio<GPIOA_BASE, 13>::getPin(), "PA13", NULL, NULL}, SWDIO + // {Gpio<GPIOA_BASE, 14>::getPin(), "PA14", NULL, NULL}, SWCLK + {Gpio<GPIOA_BASE, 15>::getPin(), "PA15", "PIN32", "PIN38"}, + {Gpio<GPIOB_BASE, 0>::getPin(), "PB0", "PIN53", "PIN17"}, + {Gpio<GPIOB_BASE, 1>::getPin(), "PB1", "PIN51", "PIN19"}, + {Gpio<GPIOB_BASE, 2>::getPin(), "PB2", "PIN65", "PIN5"}, + {Gpio<GPIOB_BASE, 3>::getPin(), "PB3", "PIN15", "PIN55"}, + {Gpio<GPIOB_BASE, 4>::getPin(), "PB4", "PIN17", "PIN53"}, + // {Gpio<GPIOB_BASE, 5>::getPin(), "PB5", NULL, NULL}, RAM + // {Gpio<GPIOB_BASE, 6>::getPin(), "PB6", NULL, NULL}, RAM + {Gpio<GPIOB_BASE, 7>::getPin(), "PB7", "PIN14", "PIN56"}, + {Gpio<GPIOB_BASE, 8>::getPin(), "PB8", "PIN13", "PIN57"}, + {Gpio<GPIOB_BASE, 9>::getPin(), "PB9", "PIN11", "PIN59"}, + // {Gpio<GPIOB_BASE, 10>::getPin(), "PB10", NULL}, Flash + {Gpio<GPIOB_BASE, 11>::getPin(), "PB11", "PIN49", "PIN21"}, + {Gpio<GPIOB_BASE, 12>::getPin(), "PB12", "PIN47", "PIN23"}, + {Gpio<GPIOB_BASE, 13>::getPin(), "PB13", "PIN45", "PIN25"}, + {Gpio<GPIOB_BASE, 14>::getPin(), "PB14", "PIN43", "PIN27"}, + {Gpio<GPIOB_BASE, 15>::getPin(), "PB15", "PIN46", "PIN24"}, + // {Gpio<GPIOC_BASE, 0>::getPin(), "PC0", NULL, NULL}, RAM + {Gpio<GPIOC_BASE, 1>::getPin(), "PC1", "PIN63", "PIN7"}, + // {Gpio<GPIOC_BASE, 2>::getPin(), "PC2", NULL, NULL}, LED + {Gpio<GPIOC_BASE, 3>::getPin(), "PC3", "PIN61", "PIN9"}, + {Gpio<GPIOC_BASE, 4>::getPin(), "PC4", "PIN50", "PIN20"}, + {Gpio<GPIOC_BASE, 5>::getPin(), "PC5", "PIN48", "PIN22"}, + {Gpio<GPIOC_BASE, 6>::getPin(), "PC6", "PIN37", "PIN33"}, + {Gpio<GPIOC_BASE, 7>::getPin(), "PC7", "PIN35", "PIN35"}, + // {Gpio<GPIOC_BASE, 8>::getPin(), "PC8", NULL, NULL}, SD Card + // {Gpio<GPIOC_BASE, 9>::getPin(), "PC9", NULL, NULL}, SD Card + // {Gpio<GPIOC_BASE, 10>::getPin(), "PC10", NULL, NULL}, SD Card + // {Gpio<GPIOC_BASE, 11>::getPin(), "PC11", NULL, NULL}, SD Card + // {Gpio<GPIOC_BASE, 12>::getPin(), "PC12", NULL, NULL}, SD Card + // {Gpio<GPIOC_BASE, 13>::getPin(), "PC13", NULL, NULL}, LED + // {Gpio<GPIOC_BASE, 14>::getPin(), "PC14", NULL, NULL}, LED + // {Gpio<GPIOC_BASE, 15>::getPin(), "PC15", NULL, NULL}, LED + // {Gpio<GPIOD_BASE, 0>::getPin(), "PD0", NULL, NULL}, RAM + // {Gpio<GPIOD_BASE, 1>::getPin(), "PD1", NULL, NULL}, RAM + // {Gpio<GPIOD_BASE, 2>::getPin(), "PD2", NULL, NULL}, SD Card + {Gpio<GPIOD_BASE, 3>::getPin(), "PD3", "PIN28", "PIN42"}, + {Gpio<GPIOD_BASE, 4>::getPin(), "PD4", "PIN26", "PIN44"}, + {Gpio<GPIOD_BASE, 5>::getPin(), "PD5", "PIN22", "PIN48"}, + {Gpio<GPIOD_BASE, 6>::getPin(), "PD6", "PIN24", "PIN46"}, + {Gpio<GPIOD_BASE, 7>::getPin(), "PD7", "PIN23", "PIN47"}, + // {Gpio<GPIOD_BASE, 8>::getPin(), "PD8", NULL, NULL}, RAM + // {Gpio<GPIOD_BASE, 9>::getPin(), "PD9", NULL, NULL}, RAM + // {Gpio<GPIOD_BASE, 10>::getPin(), "PD10", NULL, NULL}, RAM + {Gpio<GPIOD_BASE, 11>::getPin(), "PD11", "PIN44", "PIN26"}, + {Gpio<GPIOD_BASE, 12>::getPin(), "PD12", "PIN41", "PIN29"}, + {Gpio<GPIOD_BASE, 13>::getPin(), "PD13", "PIN39", "PIN31"}, + // {Gpio<GPIOD_BASE, 14>::getPin(), "PD14", NULL, NULL}, RAM + // {Gpio<GPIOD_BASE, 15>::getPin(), "PD15", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 0>::getPin(), "PE0", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 1>::getPin(), "PE1", NULL, NULL}, RAM + {Gpio<GPIOE_BASE, 2>::getPin(), "PE2", "PIN7", "PIN63"}, + {Gpio<GPIOE_BASE, 3>::getPin(), "PE3", "PIN12", "PIN58"}, + {Gpio<GPIOE_BASE, 4>::getPin(), "PE4", "PIN9", "PIN61"}, + {Gpio<GPIOE_BASE, 5>::getPin(), "PE5", "PIN5", "PIN65"}, + {Gpio<GPIOE_BASE, 6>::getPin(), "PE6", "PIN3", "PIN67"}, + // {Gpio<GPIOE_BASE, 7>::getPin(), "PE7", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 8>::getPin(), "PE8", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 9>::getPin(), "PE9", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 10>::getPin(), "PE10", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 11>::getPin(), "PE11", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 12>::getPin(), "PE12", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 13>::getPin(), "PE13", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 14>::getPin(), "PE14", NULL, NULL}, RAM + // {Gpio<GPIOE_BASE, 15>::getPin(), "PE15", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 0>::getPin(), "PF0", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 1>::getPin(), "PF1", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 2>::getPin(), "PF2", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 3>::getPin(), "PF3", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 4>::getPin(), "PF4", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 5>::getPin(), "PF5", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 6>::getPin(), "PF6", NULL, NULL}, Flash + // {Gpio<GPIOF_BASE, 7>::getPin(), "PF7", NULL, NULL}, Flash + // {Gpio<GPIOF_BASE, 8>::getPin(), "PF8", NULL, NULL}, Flash + // {Gpio<GPIOF_BASE, 9>::getPin(), "PF9", NULL, NULL}, Flash + // {Gpio<GPIOF_BASE, 10>::getPin(), "PF10", NULL, NULL}, Flash + // {Gpio<GPIOF_BASE, 11>::getPin(), "PF11", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 12>::getPin(), "PF12", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 13>::getPin(), "PF13", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 14>::getPin(), "PF14", NULL, NULL}, RAM + // {Gpio<GPIOF_BASE, 15>::getPin(), "PF15", NULL, NULL}, RAM + // {Gpio<GPIOG_BASE, 0>::getPin(), "PG0", NULL, NULL}, RAM + // {Gpio<GPIOG_BASE, 1>::getPin(), "PG1", NULL, NULL}, RAM + // {Gpio<GPIOG_BASE, 2>::getPin(), "PG2", NULL, NULL}, RAM + {Gpio<GPIOG_BASE, 3>::getPin(), "PG3", "PIN42", "PIN28"}, + // {Gpio<GPIOG_BASE, 4>::getPin(), "PG4", NULL}, RAM + // {Gpio<GPIOG_BASE, 5>::getPin(), "PG5", NULL}, RAM + {Gpio<GPIOG_BASE, 6>::getPin(), "PG6", "PIN40", "PIN30"}, + {Gpio<GPIOG_BASE, 7>::getPin(), "PG7", "PIN38", "PIN32"}, + // {Gpio<GPIOG_BASE, 8>::getPin(), "PG8", NULL, NULL}, RAM + {Gpio<GPIOG_BASE, 9>::getPin(), "PG9", "PIN19", "PIN51"}, + {Gpio<GPIOG_BASE, 10>::getPin(), "PG10", "PIN25", "PIN45"}, + {Gpio<GPIOG_BASE, 11>::getPin(), "PG11", "PIN21", "PIN49"}, + {Gpio<GPIOG_BASE, 12>::getPin(), "PG12", "PIN20", "PIN50"}, + {Gpio<GPIOG_BASE, 13>::getPin(), "PG13", "PIN18", "PIN52"}, + {Gpio<GPIOG_BASE, 14>::getPin(), "PG14", "PIN16", "PIN54"}, + // {Gpio<GPIOG_BASE, 15>::getPin(), "PG15", NULL, NULL} RAM +}}; + +void banner(bool furry) +{ + if (furry) + { + puts(R"( +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡀⠀⠀⠀⠀⠀⠀⠀⢀⣠⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢶⣿⢃⣠⣴⣶⣶⣿⣛⢯⣹⣾â ⠀⠀⠀⠀⠀⢀⣀⣤⣴⣶⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣻⣾⣿⣞⣯⣷⣽⣾⣿â£â£€â£ ⢤⡶⣶⠿⣻⣶⣟⡿⣿⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣟⣯⣿⣶⣯⣿⣿⣿â¡â €â£´â ¿â£Ÿâ£¿â£Ÿâ£¿â£»â¢·â¢¯â£žâ¡â €â € +⠀⠀⠀⢠⡶⢒⣖⣲⡶⢶⡖⣶⣒⢶⡲⣞⣫â â£â£â£½â£â£¯â£½â£¿â£¿â£¿â£¿â£¿â£¿â£¿â ¿â¢¿â¡¿â ¿â ¿â ¿â£Œâ ¿â¢¿â£¿â£¿â£¿â£¿â¡¾â£½â¢¯â£Ÿâ£¿â ƒâ €â € +⠀⠀⠀⠀⢻⣯⣛⢧⣛⢧⣛⡶⣹⣎⢷â£â¡®â£Ÿâ¢·â¡¾â£¹â¢¯â¡Ÿâ ‰â ‰â ›â¢¿â£¿â£¿â£¯â£Ÿâ£¿â£«â£½â¡¿â£ƒâ£”⣬⣿⣷⣯⣿⣿⣿⣿⣽⣻⣾â¡â €â €â € +⠀⠀⠀⠀⠀⠹⣟⡾â£â¡Ÿâ£¾â£¹â¢—⣾⣫⢾⡽⣽⢾⡽⢯⡟⠀⠀⠀⢀⢈⣿⣿⣿⣿⣿⠿⢻⣷⣼⣿⣿⣟⣿⣟⣿⣿⣿⣿⣿⣿â ⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠙⣿⣷⣿⣷⣯⣟⡾⣽⣳⢿⡽⣾⡽⡟⠀⠀⢀⣰⠞⠟⠙⢻⣷⣿⣸⣷⣾⣟⣺⣽⣟⣻⣿⣿⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⣿⣿⣿⣷⣯⣿⣽⣳⢿⠃⠀⠀⢀⠀⢠⣤⣦⣄⣇⠉⠛⠛⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟â ⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠻⣿⣿⣿⣿⣿⣉⠉⠉⠻⠀⠀â ⢀⣾⢿⠋â¢â£¿â£¿â €â €â €â €â£¿â£§â ™â¢¿â£¹â£â¢ ⣛⠟â ⠀⠀⢀⣴⣷⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⠿⣿⣿⣿⣓⣈⣰⣦⣤⣀⣼⠋⠀⠀â¢â£½â£¿â¡‡â €â£€â£€â£¿â£¿â¡‡â¡¸â£¿â£¿â¡¤â ‰â ’⠤⣀⠀â ⡄⠀⣀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⢹â ⠀⠛⣞⣧⣾â ⠢⣀⠀⠈⠻⠟⣇⢉⣡⡶â£â ¯â¡€â ⠛⠙⢇⠀â ⢲â ⠀⠀⠈⠲⠞⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴â ⢀⠄⠂⢸⠛â ⣠⣲⡆⢔⠾⠋⠀⠈⠢⣉⠀⢀⣀⣈⡆⠀⠀⢸⣀⠔⠋⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠚⠤⣌â¡â €â €â ˆâ¢†â €â €â €â €â €â €â €â €â €â €â €â ¹â£¿â£¿â£¿â¡¿â €â €â£œâ£©â Ÿâ ƒâ €â €â €â €â €â €â €â € +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⣛⡉⠀⠀⠓⢄⡀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀⡹⠋⠀⣠⠞⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉â ⠒⠚⣿⣶⠦⣄⣀⡀⠘⠿⠽⠶⢾⣷⣀⠖â ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣀⡀⣀⣀⣠⡿â ⣛⠻⡿⠿⣟⣲⣶⣶⡶⠿⣿⣖⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠼⠛⢻⠿⠻⢿⣿⣷⣿⣶⣆⠬⡯⣑⣿⣿⣿⣿⣹â£â£§â£¾â ˆâ ‰â ‰â ’â ’â ⣄⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠋⠀⠀â â ’â ⣔â ⠀⠉⣿⣿⣿⢛⡖⠾⠿⢿⡿⠿⣾⠟â ⠀⠀⠀⠀⠀⠸⠀⠱⡄⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⡅⠀⠀⠀⠀⠀⠀⠀⠉⠒⠄⠘⢿⣿⠇⠈â ⠒⠺⣤⣢⡼⠀⠀⠀⠀⠀⠀⠀⠸⠀⠀⠘⣆⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠹⡄â â ’â ⠤⠀⣀⠀⠀⠀⠀⠈â£â €â €â €â €â €â ˆâ ‰â €â €â €â €â €â €â €â €â €â¢†â €â €â ™â£†â €â €â € +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰â ⠀⠘⣆⠀⠀⠀⠀⠀⠉⠑⠢⡀⢀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠀⠀⠀⠈⢆⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰â ⠀⠀⠀⠈⢣⡀â ⢄⣀⠀⠀⠀⢠⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠀⠀⠀⢣⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⠧⣀⣀⠀⢀⡤⠋⠀⠀⠀⠀⠈â¢â ’â¡â €â €â €â €â €â €â €â €â €â €â €â €â €â €â €â €â €â €â €â¡†â €â¢€â£ ⢾â¡â € +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠞⣻⡿â ⠀⠀⠀â ⠢⠄⢀⡀⣰â ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡷⠖⠋â£â¡¼â£‡â € + )"); + } + else + { + puts(R"( + / + / / / + / / / + / / / / + / _=^| / / + / / <^ | / + // | / / / + / / / + >/ / / / + / // / / / + </ /^>_ / / + / / / ^>_ / / + / /^<_ ^>_ / + / / / ^<_ ^>_ / + ^<_ / ^<_ ^>_ ___----____ + ^</ ^<_ ^>_ _-<^^^ + ^<_ ^<^ + ^<_ / / + ^/ /^>^>_ ******** + '<__/ /^> ^>_ ___*** + ^-/ /^>__^>_ ^^^ + ^-/ / ! / + ^-/^_/_/ + _____________._____________________ + /, O .. == * O ___ / + /, ,@@ @@@@@@@@@@ /()/ / + === %%%% """ @@@@@@@@@@ /"'/ / + ==='%%%% + @@@@@@@@@@ /"'/ / + /% . .% . @@@@@@@@@@ /"'/ / + /% . %..% . , , , , /__/ / + /____O_______________________O______/ + L__V + )"); + } + + puts(R"( + Welcome to the + ________ __ _ _____ ______ __ _ __ + / ____/ / / / | | / /__ \ /_ __/__ _____/ /________ __(_) /____ + / / / / / / | | / /__/ / / / / _ \/ ___/ __/ ___/ / / / / __/ _ \ +/ /___/ /_/ / | |/ // __/ / / / __(__ ) /_(__ ) /_/ / / /_/ __/ +\____/\____/ |___//____/ /_/ \___/____/\__/____/\__,_/_/\__/\___/ + )"); +} + +void led_task() +{ + ledOff(); + + const unsigned int DELAY = 200; + while (1) + { + led2Off(); + led1On(); + Thread::sleep(DELAY); + led1Off(); + led2On(); + Thread::sleep(DELAY); + led2Off(); + led3On(); + Thread::sleep(DELAY); + led3Off(); + led4On(); + Thread::sleep(DELAY); + led4Off(); + led3On(); + Thread::sleep(DELAY); + led3Off(); + led2On(); + Thread::sleep(DELAY); + } +} + +void sd_test() +{ + // Write 1MB of bytes + const size_t COUNT = 256 * 1024; + const uint32_t INITIAL_VALUE = 0xdeadbeef; + + puts("*** Starting SD test..."); + bool ok = true; + + FILE *f = fopen("/sd/test.bin", "wb"); + if (f == NULL) + { + puts("Failed to open test.bin"); + ok = false; + } + + if (ok) + { + uint32_t value = INITIAL_VALUE; + for (size_t i = 0; i < COUNT; i++) + { + size_t result = fwrite(&value, sizeof(value), 1, f); + if (result != 1) + { + printf("Failed to write word %d\n", i); + + // We had a problem + ok = false; + break; + } + + // Update value with xorshift + value = (value << 8) ^ (value >> 8); + } + + fclose(f); + } + + if (ok) + { + // Reopen file + f = fopen("/sd/test.bin", "rb"); + if (f == NULL) + { + puts("Failed to reopen test.bin"); + ok = false; + } + } + + if (ok) + { + uint32_t value = INITIAL_VALUE; + for (size_t i = 0; i < COUNT; i++) + { + uint32_t actual = 0; + size_t result = fread(&actual, sizeof(actual), 1, f); + if (result != 1) + { + printf("Failed to write word %d\n", i); + ok = false; + break; + } + + if (actual != value) + { + printf( + "Failed to validate word %d, expected: %lu, actual: %lu\n", + i, value, actual); + ok = false; + break; + } + + // Update value with xorshift + value = (value << 8) ^ (value >> 8); + } + + fclose(f); + } + + if (ok) + { + puts("*** SD test succesfull!"); + } + else + { + puts("*** SD test failed!"); + } +} + +void xram_test() +{ + volatile uint16_t *const START = (volatile uint16_t *)0xd0000000; + volatile uint16_t *const END = START + (16 * 1024 * 1024); + + // First clear the whole RAM + for (volatile uint16_t *iter = START; iter != END; iter++) + { + *iter = 0; + } + + __DMB(); // Flush cache + + puts("*** Starting basic XRAM test..."); + bool ok = true; + + for (volatile uint16_t *iter = START; iter != END; iter++) + { + // Set a marker value at this address + *iter = 0xffff; + __DMB(); // Flush cache + + if (*iter != 0xffff) + { + ok = false; + printf("Readback failed: %p\n", iter); + } + + // Reset the value back to 0 + *iter = 0; + __DMB(); // Flush cache + } + + if (ok) + { + puts("*** XRAM basic test succesfull!"); + } + else + { + puts("*** XRAM basic test failed!"); + } + + puts("*** Starting XRAM mirroring test..."); + ok = true; + + // Generate addresses to test every line + for (int i = 1; i < 25; i++) + { + volatile uint16_t *other = + (volatile uint16_t *)((size_t)START | (1 << i)); + + // Write something + *other = 0xdead; + __DMB(); // Flush cache + + for (volatile uint16_t *iter = START; iter != END; iter++) + { + // Skip the written address + if (iter == other) + { + continue; + } + + // Check for mirroring + if (*iter == 0xdead) + { + printf("Mirroring %p -> %p\n", other, iter); + ok = false; + } + } + + // Reset the value + *other = 0; + __DMB(); // Flush cache + } + + if (ok) + { + puts("*** XRAM mirror test succesfull!"); + } + else + { + puts("*** XRAM mirror test failed!"); + } +} + +void pin_continuity_test() +{ + for (auto &a : PIN_DEFS) + { + a.pin.mode(Mode::INPUT_PULL_DOWN); + } + + puts("*** Starting pin continuity test..."); + bool ok = true; + + // Ok now start testing + for (auto &a : PIN_DEFS) + { + a.pin.mode(Mode::OUTPUT); + a.pin.high(); + for (auto &b : PIN_DEFS) + { + if (a.pin.getNumber() == b.pin.getNumber() && + a.pin.getPort() == b.pin.getPort()) + { + continue; + } + + if (b.pin.value() == 1) + { + printf("Shorted pins %s %s\n", a.gpio_name, b.gpio_name); + ok = false; + } + } + + a.pin.low(); + a.pin.mode(Mode::INPUT_PULL_DOWN); + } + + if (ok) + { + puts("*** Pin continuity test succesfull!"); + } + else + { + puts("*** Pin continuity test failed!"); + } +} + +void pin_semi_test() +{ + for (auto &a : PIN_DEFS) + { + a.pin.mode(Mode::OUTPUT); + a.pin.low(); + } + + puts("*** Starting semi-automatic pin test..."); + + std::atomic<bool> running(true); + std::atomic<int> cur_idx(0); + + // Parallel test pulsing pin + std::thread t( + [&]() + { + while (running) + { + int idx = cur_idx; + + PIN_DEFS[idx].pin.high(); + Thread::sleep(10); + PIN_DEFS[idx].pin.low(); + Thread::sleep(10); + } + }); + + // Clean any pending newlines + while (getchar() != '\n') + ; + puts("Press enter to continue..."); + + for (size_t i = 0; i < PIN_DEFS.size(); i++) + { + auto &a = PIN_DEFS[i]; + + // Pause waiting for keys + while (getchar() != '\n') + ; + + cur_idx = i; + printf( + "Pulsing %s, conan: %s, breakout v1: %s, press enter to " + "continue...\n", + a.gpio_name, a.conan_name, a.breakout_v1_name); + } + + running = false; + t.join(); + + puts("*** Test finished!"); +} + +int main() +{ + banner(true); + + // Spawn the led blinker task + std::thread t(led_task); + + while (1) + { + printf( + "\nSelect test to run:\n" + "- 1 Automatic SD test\n" + "- 2 Automatic RAM test\n" + "- 3 Automatic pin continuity test\n" + "- 4 Semi-automatic pin test\n" + "\n" + "Command: "); + + int cmd; + scanf("%d", &cmd); + + switch (cmd) + { + case 1: + sd_test(); + break; + + case 2: + xram_test(); + break; + + case 3: + pin_continuity_test(); + break; + + case 4: + pin_semi_test(); + break; + } + } + + return 0; +} -- GitLab