From f7ca1857b4cec097d54fe0bc90ca833094dd1f45 Mon Sep 17 00:00:00 2001 From: Davide Basso <davide.basso@skywarder.eu> Date: Sat, 14 Sep 2024 09:27:00 +0200 Subject: [PATCH 1/4] [CubeSat] BPS support --- cmake/boards.cmake | 1 + .../config/board_options.cmake | 123 ++++++ .../config/board_settings.h | 74 ++++ .../config/miosix_settings.h | 240 ++++++++++ .../core/stage_1_boot.cpp | 372 ++++++++++++++++ .../interfaces-impl/arch_registers_impl.h | 34 ++ .../interfaces-impl/bsp.cpp | 418 ++++++++++++++++++ .../interfaces-impl/bsp_impl.h | 76 ++++ .../interfaces-impl/hwmapping.h | 109 +++++ .../stm32_2m+256k_rom.ld | 181 ++++++++ .../stm32_2m+8m_xram.ld | 178 ++++++++ .../sensors/analog/pressure/nxp/MPXH6250A.h | 56 +++ .../analog/pressure/nxp/MPXH6250AData.h | 40 ++ 13 files changed, 1902 insertions(+) create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/config/board_options.cmake create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/config/board_settings.h create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/config/miosix_settings.h create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/arch_registers_impl.h create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp.cpp create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp_impl.h create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/hwmapping.h create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/stm32_2m+256k_rom.ld create mode 100644 src/bsps/stm32f429zi_lyra_cubesat/stm32_2m+8m_xram.ld create mode 100644 src/shared/sensors/analog/pressure/nxp/MPXH6250A.h create mode 100644 src/shared/sensors/analog/pressure/nxp/MPXH6250AData.h diff --git a/cmake/boards.cmake b/cmake/boards.cmake index ae1be8a92..cab852390 100644 --- a/cmake/boards.cmake +++ b/cmake/boards.cmake @@ -41,4 +41,5 @@ set(BOARDCORE_BOARDS_OPTIONS_FILES ${BOARDCORE_PATH}/src/bsps/stm32f767zi_lyra_biscotto/config/board_options.cmake ${BOARDCORE_PATH}/src/bsps/stm32f767zi_lyra_motor/config/board_options.cmake ${BOARDCORE_PATH}/src/bsps/stm32f767zi_lyra_gs/config/board_options.cmake + ${BOARDCORE_PATH}/src/bsps/stm32f429zi_lyra_cubesat/config/board_options.cmake ) diff --git a/src/bsps/stm32f429zi_lyra_cubesat/config/board_options.cmake b/src/bsps/stm32f429zi_lyra_cubesat/config/board_options.cmake new file mode 100644 index 000000000..17daacb87 --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/config/board_options.cmake @@ -0,0 +1,123 @@ +# Copyright (C) 2024 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 stm32f429zi_lyra_cubesat) +set(ARCH_NAME cortexM4_stm32f4) + +# Base directories with header files for this board +set(ARCH_PATH ${KPATH}/arch/${ARCH_NAME}/common) +set(BOARD_PATH ${BOARDCORE_PATH}/src/bsps/${BOARD_NAME}) +set(BOARD_CONFIG_PATH ${BOARDCORE_PATH}/src/bsps/${BOARD_NAME}/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 + $<$<CONFIG:Debug>:-O2> + $<$<CONFIG:Release>:-O2> +) + +# Boot and linker files +set(BOOT_FILE ${BOARD_PATH}/core/stage_1_boot.cpp) + +# Linker script type, there are three options +# 1) Code in FLASH, stack + heap in internal RAM (file *_rom.ld) +# the most common choice, available for all microcontrollers +# 2) Code in FLASH, stack + heap in external RAM (file *8m_xram.ld) +# You must uncomment -D__ENABLE_XRAM below in this case. +# set(LINKER_SCRIPT ${BOARD_PATH}/stm32_2m+256k_rom.ld) +set(LINKER_SCRIPT ${BOARD_PATH}/stm32_2m+8m_xram.ld) + +# Uncommenting __ENABLE_XRAM enables the initialization of the external +# 8MB SDRAM memory. Do not uncomment this even if you don't use a linker +# script that requires it, as it is used for the LCD framebuffer. +set(XRAM -D__ENABLE_XRAM) + +# Select clock frequency. Warning: the default clock frequency for +# this board is 168MHz and not 180MHz because, due to a limitation in +# the PLL, it is not possible to generate a precise 48MHz output when +# running the core at 180MHz. If 180MHz is chosen the USB peripheral will +# NOT WORK and the SDIO and RNG will run ~6% slower (45MHz insteand of 48) +# Define USE_INTERNAL_CLOCK to bypass the external oscillator +#set(CLOCK_FREQ -DHSE_VALUE=25000000 -DSYSCLK_FREQ_180MHz=180000000) +set(CLOCK_FREQ -DHSE_VALUE=25000000 -DSYSCLK_FREQ_168MHz=168000000) +#set(CLOCK_FREQ -DHSE_VALUE=25000000 -DSYSCLK_FREQ_100MHz=100000000) + +# 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-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-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_CORTEXM4_STM32F4 + ${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/STM32F4xx/Source/Templates/system_stm32f4xx.c + ${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/stm32f429zi_lyra_cubesat/config/board_settings.h b/src/bsps/stm32f429zi_lyra_cubesat/config/board_settings.h new file mode 100644 index 000000000..6cee46f02 --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/config/board_settings.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2024 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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 BOARD_SETTINGS_H +#define BOARD_SETTINGS_H + +#include "util/version.h" + +/** + * \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) but the +/// STM32F407VG only has 192KB of RAM so there is room for a big 4K stack. +const unsigned int MAIN_STACK_SIZE = 16 * 1024; + +/// Serial port +const unsigned int defaultSerial = 1; +const unsigned int defaultSerialSpeed = 115200; +const bool defaultSerialFlowctrl = false; +#define SERIAL_1_DMA +// #define SERIAL_2_DMA //Serial 2 can't be used (GPIO conflict), so no DMA +// #define SERIAL_3_DMA //Serial 3 can't be used (GPIO conflict), so no DMA + +// #define I2C_WITH_DMA + +// SD card driver +static const unsigned char sdVoltage = 33; // Board powered @ 3.3V +#ifdef __ENABLE_XRAM +// Reduce SD clock to ~4.8MHz +#define OVERRIDE_SD_CLOCK_DIVIDER_MAX 8 +#endif //__ENABLE_XRAM +#define SD_ONE_BIT_DATABUS // This board supports 4 bit databus to SD card + +/// Analog supply voltage for ADC, DAC, Reset blocks, RCs and PLL +#define V_DDA_VOLTAGE 3.3f + +/** + * \} + */ + +} // namespace miosix + +#endif /* BOARD_SETTINGS_H */ diff --git a/src/bsps/stm32f429zi_lyra_cubesat/config/miosix_settings.h b/src/bsps/stm32f429zi_lyra_cubesat/config/miosix_settings.h new file mode 100644 index 000000000..66b92921e --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/config/miosix_settings.h @@ -0,0 +1,240 @@ +/* Copyright (c) 2024 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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/stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp b/src/bsps/stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp new file mode 100644 index 000000000..b189eb8bf --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp @@ -0,0 +1,372 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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/interrupts.h" //For the unexpected interrupt call +#include "interfaces/arch_registers.h" +#include "interfaces/bsp.h" +#include "kernel/stage_2_boot.h" + +/* + * startup.cpp + * STM32 C++ startup. + * NOTE: for stm32f42x 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 M3 core appears to get out of reset with interrupts already + // enabled + __disable_irq(); + + // 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: + // First, the CMSIS specifications say that SystemInit() must not access + // global variables, so it is actually possible to call it before + // 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 + // 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 stm32f429-disco 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 + + /* + * Initialize process stack and switch to it. + * 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" // Privileged, process stack + "msr control, r0 \n\t" + "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)) SDIO_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)) HASH_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(); + +// 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, SDIO_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, HASH_RNG_IRQHandler, + FPU_IRQHandler, UART7_IRQHandler, UART8_IRQHandler, SPI4_IRQHandler, + SPI5_IRQHandler, SPI6_IRQHandler, SAI1_IRQHandler, LTDC_IRQHandler, + LTDC_ER_IRQHandler, DMA2D_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 SDIO_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 HASH_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 diff --git a/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/arch_registers_impl.h b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/arch_registers_impl.h new file mode 100644 index 000000000..f3276b6d0 --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/arch_registers_impl.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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 + +// Always include stm32f4xx.h before core_cm4.h, there's some nasty dependency +#define STM32F429xx +#include "CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h" +#include "CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h" +#include "CMSIS/Include/core_cm4.h" + +#define RCC_SYNC() __DSB() // Workaround for a bug in stm32f42x + +#endif // ARCH_REGISTERS_IMPL_H diff --git a/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp.cpp b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp.cpp new file mode 100644 index 000000000..e4447baca --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp.cpp @@ -0,0 +1,418 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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 <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 "hwmapping.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 +// + +/** + * The example code from ST checks for the busy flag after each command. + * Interestingly I couldn't find any mention of this in the datsheet. + */ +static void sdramCommandWait() +{ + for (int i = 0; i < 0xffff; i++) + if ((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) == 0) + return; +} + +#ifdef SDRAM_ISSI + +void configureSdram() +{ + // Enable all gpios, passing clock + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | + RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | + RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | + RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN; + RCC_SYNC(); + + // First, configure SDRAM GPIOs + 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] = 0x00cc00cc; + GPIOG->AFR[1] = 0xc000000c; + + GPIOB->MODER = 0x00002800; + GPIOC->MODER = 0x00000002; + GPIOD->MODER = 0xa02a000a; + GPIOE->MODER = 0xaaaa800a; + GPIOF->MODER = 0xaa800aaa; + GPIOG->MODER = 0x80020a0a; + + GPIOA->OSPEEDR = 0xaaaaaaaa; // Default to 50MHz speed for all GPIOs... + GPIOB->OSPEEDR = + 0xaaaaaaaa | 0x00003c00; //...but 100MHz for the SDRAM pins + GPIOC->OSPEEDR = 0xaaaaaaaa | 0x00000003; + GPIOD->OSPEEDR = 0xaaaaaaaa | 0xf03f000f; + GPIOE->OSPEEDR = 0xaaaaaaaa | 0xffffc00f; + GPIOF->OSPEEDR = 0xaaaaaaaa | 0xffc00fff; + GPIOG->OSPEEDR = 0xaaaaaaaa | 0xc0030f0f; + GPIOH->OSPEEDR = 0xaaaaaaaa; + + // Since we'we un-configured PB3/PB4 from the default at boot TDO,NTRST, + // finish the job and remove the default pull-up + GPIOB->PUPDR = 0; + + // Second, actually start the SDRAM controller + RCC->AHB3ENR |= RCC_AHB3ENR_FMCEN; + RCC_SYNC(); + + // SDRAM is a IS42S16400J -7 speed grade, connected to bank 2 (0xd0000000) + // Some bits in SDCR[1] are don't care, and the have to be set in SDCR[0], + // they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDCR[0] = FMC_SDCR1_SDCLK_1 // SDRAM runs @ half CPU frequency + | FMC_SDCR1_RBURST // Enable read burst + | 0; // 0 delay between reads after CAS + FMC_Bank5_6->SDCR[1] = 0 // 8 bit column address + | FMC_SDCR1_NR_0 // 12 bit row address + | FMC_SDCR1_MWID_0 // 16 bit data bus + | FMC_SDCR1_NB // 4 banks + | + FMC_SDCR1_CAS_1; // 2 cycle CAS latency (F<133MHz) + +#ifdef SYSCLK_FREQ_180MHz + // One SDRAM clock cycle is 11.1ns + // Some bits in SDTR[1] are don't care, and the have to be set in SDTR[0], + // they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDTR[0] = (6 - 1) << 12 // 6 cycle TRC (66.6ns>63ns) + | (2 - 1) << 20; // 2 cycle TRP (22.2ns>15ns) + FMC_Bank5_6->SDTR[1] = (2 - 1) << 0 // 2 cycle TMRD + | (7 - 1) << 4 // 7 cycle TXSR (77.7ns>70ns) + | (4 - 1) << 8 // 4 cycle TRAS (44.4ns>42ns) + | (2 - 1) << 16 // 2 cycle TWR + | (2 - 1) << 24; // 2 cycle TRCD (22.2ns>15ns) +#elif defined(SYSCLK_FREQ_168MHz) + // One SDRAM clock cycle is 11.9ns + // Some bits in SDTR[1] are don't care, and the have to be set in SDTR[0], + // they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDTR[0] = (6 - 1) << 12 // 6 cycle TRC (71.4ns>63ns) + | (2 - 1) << 20; // 2 cycle TRP (23.8ns>15ns) + FMC_Bank5_6->SDTR[1] = (2 - 1) << 0 // 2 cycle TMRD + | (6 - 1) << 4 // 6 cycle TXSR (71.4ns>70ns) + | (4 - 1) << 8 // 4 cycle TRAS (47.6ns>42ns) + | (2 - 1) << 16 // 2 cycle TWR + | (2 - 1) << 24; // 2 cycle TRCD (23.8ns>15ns) +#else +#error No SDRAM timings for this clock +#endif + + FMC_Bank5_6->SDCMR = FMC_SDCMR_CTB2 // Enable bank 2 + | 1; // MODE=001 clock enabled + sdramCommandWait(); + + // ST and SDRAM datasheet agree a 100us delay is required here. + delayUs(100); + + FMC_Bank5_6->SDCMR = FMC_SDCMR_CTB2 // Enable bank 2 + | 2; // MODE=010 precharge all command + sdramCommandWait(); + + FMC_Bank5_6->SDCMR = (8 - 1) << 5 // NRFS=8 SDRAM datasheet says + // "at least two AUTO REFRESH cycles" + | FMC_SDCMR_CTB2 // Enable bank 2 + | 3; // MODE=011 auto refresh + sdramCommandWait(); + + FMC_Bank5_6->SDCMR = 0x220 << 9 // MRD=0x220:CAS latency=2 burst len=1 + | FMC_SDCMR_CTB2 // Enable bank 2 + | 4; // MODE=100 load mode register + sdramCommandWait(); + +// 64ms/4096=15.625us +#ifdef SYSCLK_FREQ_180MHz + // 15.625us*90MHz=1406-20=1386 + FMC_Bank5_6->SDRTR = 1386 << 1; +#elif defined(SYSCLK_FREQ_168MHz) + // 15.625us*84MHz=1312-20=1292 + FMC_Bank5_6->SDRTR = 1292 << 1; +#else +#error No refresh timings for this clock +#endif +} + +#else + +void configureSdram() +{ + // Enable all gpios + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | + RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | + RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | + RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN; + RCC_SYNC(); + + // First, configure SDRAM GPIOs + 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] = 0x00cc00cc; + GPIOG->AFR[1] = 0xc000000c; + + GPIOB->MODER = 0x00002800; + GPIOC->MODER = 0x00000002; + GPIOD->MODER = 0xa02a000a; + GPIOE->MODER = 0xaaaa800a; + GPIOF->MODER = 0xaa800aaa; + GPIOG->MODER = 0x80020a0a; + + GPIOA->OSPEEDR = 0xaaaaaaaa; // Default to 50MHz speed for all GPIOs... + GPIOB->OSPEEDR = + 0xaaaaaaaa | 0x00003c00; //...but 100MHz for the SDRAM pins + GPIOC->OSPEEDR = 0xaaaaaaaa | 0x00000003; + GPIOD->OSPEEDR = 0xaaaaaaaa | 0xf03f000f; + GPIOE->OSPEEDR = 0xaaaaaaaa | 0xffffc00f; + GPIOF->OSPEEDR = 0xaaaaaaaa | 0xffc00fff; + GPIOG->OSPEEDR = 0xaaaaaaaa | 0xc0030f0f; + GPIOH->OSPEEDR = 0xaaaaaaaa; + + // Since we'we un-configured PB3/PB4 from the default at boot TDO,NTRST, + // finish the job and remove the default pull-up + GPIOB->PUPDR = 0; + + // Second, actually start the SDRAM controller + RCC->AHB3ENR |= RCC_AHB3ENR_FMCEN; + RCC_SYNC(); + + // SDRAM is a AS4C4M16SA-6TAN, connected to bank 2 (0xd0000000) + // Some bits in SDCR[1] are don't care, and the have to be set in SDCR[0], + // they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDCR[0] = FMC_SDCR1_SDCLK_1 // SDRAM runs @ half CPU frequency + | FMC_SDCR1_RBURST // Enable read burst + | 0; // 0 delay between reads after CAS + FMC_Bank5_6->SDCR[1] = + 0 // 8 bit column address + | FMC_SDCR1_NR_0 // 12 bit row address + | FMC_SDCR1_MWID_0 // 16 bit data bus + | FMC_SDCR1_NB // 4 banks + | FMC_SDCR1_CAS_1; // 2 cycle CAS latency (TCK>9+0.5ns [1]) + +#ifdef SYSCLK_FREQ_180MHz + // One SDRAM clock cycle is 11.1ns + // Some bits in SDTR[1] are don't care, and the have to be set in SDTR[0], + // they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDTR[0] = (6 - 1) << 12 // 6 cycle TRC (66.6ns>60ns) + | (2 - 1) << 20; // 2 cycle TRP (22.2ns>18ns) + FMC_Bank5_6->SDTR[1] = (2 - 1) << 0 // 2 cycle TMRD + | + (6 - 1) << 4 // 6 cycle TXSR (66.6ns>61.5+0.5ns [1]) + | (4 - 1) << 8 // 4 cycle TRAS (44.4ns>42ns) + | (2 - 1) << 16 // 2 cycle TWR + | (2 - 1) << 24; // 2 cycle TRCD (22.2ns>18ns) +#elif defined(SYSCLK_FREQ_168MHz) + // One SDRAM clock cycle is 11.9ns + // Some bits in SDTR[1] are don't care, and the have to be set in SDTR[0], + // they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDTR[0] = (6 - 1) << 12 // 6 cycle TRC (71.4ns>60ns) + | (2 - 1) << 20; // 2 cycle TRP (23.8ns>18ns) + FMC_Bank5_6->SDTR[1] = (2 - 1) << 0 // 2 cycle TMRD + | + (6 - 1) << 4 // 6 cycle TXSR (71.4ns>61.5+0.5ns [1]) + | (4 - 1) << 8 // 4 cycle TRAS (47.6ns>42ns) + | (2 - 1) << 16 // 2 cycle TWR + | (2 - 1) << 24; // 2 cycle TRCD (23.8ns>18ns) +#else +#error No SDRAM timings for this clock +#endif + // NOTE [1]: the timings for TCK and TIS depend on rise and fall times + //(see note 9 and 10 on datasheet). Timings are adjusted accordingly to + // the measured 2ns rise and fall time + + FMC_Bank5_6->SDCMR = FMC_SDCMR_CTB2 // Enable bank 2 + | 1; // MODE=001 clock enabled + sdramCommandWait(); + + // SDRAM datasheet requires 200us delay here (note 11), here we use 10% more + delayUs(220); + + FMC_Bank5_6->SDCMR = FMC_SDCMR_CTB2 // Enable bank 2 + | 2; // MODE=010 precharge all command + sdramCommandWait(); + + // FIXME: note 11 on SDRAM datasheet says extended mode register must be + // set, but the ST datasheet does not seem to explain how + FMC_Bank5_6->SDCMR = 0x220 << 9 // MRD=0x220:CAS latency=2 burst len=1 + | FMC_SDCMR_CTB2 // Enable bank 2 + | 4; // MODE=100 load mode register + sdramCommandWait(); + + FMC_Bank5_6->SDCMR = (4 - 1) << 5 // NRFS=8 SDRAM datasheet requires + // a minimum of 2 cycles, here we use 4 + | FMC_SDCMR_CTB2 // Enable bank 2 + | 3; // MODE=011 auto refresh + sdramCommandWait(); + +// 32ms/4096=7.8125us, but datasheet says to round that to 7.8us +#ifdef SYSCLK_FREQ_180MHz + // 7.8us*90MHz=702-20=682 + FMC_Bank5_6->SDRTR = 682 << 1; +#elif defined(SYSCLK_FREQ_168MHz) + // 7.8us*84MHz=655-20=635 + FMC_Bank5_6->SDRTR = 635 << 1; +#else +#error No refresh timings for this clock +#endif +} + +#endif + +void IRQbspInit() +{ +// If using SDRAM GPIOs are enabled by configureSdram(), else enable them here +#ifndef __ENABLE_XRAM + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | + RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | + RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | + RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN; + RCC_SYNC(); +#endif //__ENABLE_XRAM + + // enable spi1, spi2 + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; + RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; + + // enable can1 + RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; + + RCC_SYNC(); + + using namespace interfaces; + + spi1::sck::mode(Mode::ALTERNATE); + spi1::sck::alternateFunction(5); + spi1::miso::mode(Mode::ALTERNATE); + spi1::miso::alternateFunction(5); + spi1::mosi::mode(Mode::ALTERNATE); + spi1::mosi::alternateFunction(5); + + spi4::sck::mode(Mode::ALTERNATE); + spi4::sck::alternateFunction(5); + spi4::miso::mode(Mode::ALTERNATE); + spi4::miso::alternateFunction(5); + spi4::mosi::mode(Mode::ALTERNATE); + spi4::mosi::alternateFunction(5); + + uart2::rx::mode(Mode::ALTERNATE); + uart2::rx::alternateFunction(7); + uart2::tx::mode(Mode::ALTERNATE); + uart2::tx::alternateFunction(7); + + uart4::rx::mode(Mode::ALTERNATE); + uart4::rx::alternateFunction(8); + uart4::tx::mode(Mode::ALTERNATE); + uart4::tx::alternateFunction(8); + + using namespace sensors; + + ads131m04::cs::mode(Mode::OUTPUT); + ads131m04::cs::high(); + + ubxgps::cs::mode(Mode::OUTPUT); + ubxgps::cs::high(); + + LSM6DSRX::cs::mode(Mode::OUTPUT); + LSM6DSRX::cs::high(); + + DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>( + new STM32Serial(defaultSerial, defaultSerialSpeed, + defaultSerialFlowctrl ? STM32Serial::RTSCTS + : STM32Serial::NOFLOWCTRL))); + + using namespace leds; + + led_red1::mode(Mode::OUTPUT); + led_ext::mode(Mode::OUTPUT); + led_green::mode(Mode::OUTPUT); +} + +void bspInit2() +{ +#ifdef WITH_FILESYSTEM + // PA2,PA3 + intrusive_ref_ptr<DevFs> devFs = + basicFilesystemSetup(SDIODriver::instance()); +#endif // WITH_FILESYSTEM +} + +// +// Shutdown and reboot +// + +void reboot() +{ + ioctl(STDOUT_FILENO, IOCTL_SYNC, 0); + +#ifdef WITH_FILESYSTEM + FilesystemManager::instance().umountAll(); +#endif // WITH_FILESYSTEM + + disableInterrupts(); + miosix_private::IRQsystemReboot(); +} + +/** + * For safety reasons, we never want the board to shutdown. + * When requested to shutdown, we reboot instead. + */ +void shutdown() { reboot(); } + +} // namespace miosix diff --git a/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp_impl.h b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp_impl.h new file mode 100644 index 000000000..6bea1f4d5 --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/bsp_impl.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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 "drivers/stm32_hardware_rng.h" +#include "hwmapping.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 + * used by the ledOn() and ledOff() implementation + */ + +inline void ledOn() +{ + leds::led_red1::high(); + leds::led_green::high(); + leds::led_ext::high(); +} + +inline void ledOff() +{ + leds::led_red1::low(); + leds::led_green::low(); + leds::led_ext::low(); +} + +/** +\} +*/ + +} // namespace miosix + +#endif // BSP_IMPL_H diff --git a/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/hwmapping.h b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/hwmapping.h new file mode 100644 index 000000000..a96880095 --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/interfaces-impl/hwmapping.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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 HWMAPPING_H +#define HWMAPPING_H +#endif + +#include "interfaces/gpio.h" + +namespace miosix +{ + +namespace interfaces +{ + +// spi LSM6DSRX +namespace spi1 +{ +using sck = Gpio<GPIOA_BASE, 5>; +using miso = Gpio<GPIOA_BASE, 6>; +using mosi = Gpio<GPIOA_BASE, 7>; +} // namespace spi1 + +// spi gps,adc +namespace spi4 +{ +using sck = Gpio<GPIOE_BASE, 2>; +using miso = Gpio<GPIOE_BASE, 5>; +using mosi = Gpio<GPIOE_BASE, 6>; +} // namespace spi4 + +// USB UART +namespace uart1 +{ +using tx = Gpio<GPIOA_BASE, 9>; +using rx = Gpio<GPIOA_BASE, 10>; +} // namespace uart1 + +// HIL UART +namespace uart2 +{ +using tx = Gpio<GPIOA_BASE, 2>; +using rx = Gpio<GPIOA_BASE, 3>; +} // namespace uart2 + +// SIM900 UART +namespace uart4 +{ +using tx = Gpio<GPIOA_BASE, 0>; +using rx = Gpio<GPIOA_BASE, 1>; +} // namespace uart4 + +} // namespace interfaces + +namespace sensors +{ + +namespace LSM6DSRX +{ +using cs = Gpio<GPIOC_BASE, 4>; + +} // namespace LSM6DSRX + +namespace ads131m04 +{ +using cs = Gpio<GPIOE_BASE, 4>; +} // namespace ads131m04 + +namespace ubxgps +{ +using cs = Gpio<GPIOE_BASE, 3>; +} // namespace ubxgps + +} // namespace sensors + +namespace leds +{ +using led_red1 = Gpio<GPIOB_BASE, 0>; +using led_green = Gpio<GPIOB_BASE, 1>; +using led_ext = Gpio<GPIOB_BASE, 10>; + +/** + * These are connected to the enable pin of the thermal cutters and the cs of + * the lis3mdl magnetometer. + */ +// using led_blue2 = Gpio<GPIOG_BASE, 2>; +// using led_green1 = Gpio<GPIOG_BASE, 6>; +// using led_green2 = Gpio<GPIOD_BASE, 11>; +} // namespace leds +} // namespace miosix diff --git a/src/bsps/stm32f429zi_lyra_cubesat/stm32_2m+256k_rom.ld b/src/bsps/stm32f429zi_lyra_cubesat/stm32_2m+256k_rom.ld new file mode 100644 index 000000000..cfcc2ce53 --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/stm32_2m+256k_rom.ld @@ -0,0 +1,181 @@ +/* + * C++ enabled linker script for stm32 (2M FLASH, 256K RAM) + * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel + */ + +/* + * This chip has an unusual quirk that the RAM is divided in two block mapped + * at two non contiguous memory addresses. I don't know why they've done that, + * probably doing the obvious thing would have made writing code too easy... + * Anyway, since hardware can't be changed, we've got to live with that and + * try to make use of both RAMs. + * + * Given the constraints above, this linker script puts: + * - read only data and code (.text, .rodata, .eh_*) in FLASH + * - the 512Byte main (IRQ) stack, .data and .bss in the "small" 64KB RAM + * - stacks and heap in the "large" 192KB RAM. + * + * Unfortunately thread stacks can't be put in the small RAM as Miosix + * allocates them inside the heap. + */ + +/* + * 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 = 0x00000200; /* main stack = 512Bytes */ +_main_stack_top = 0x10000000 + _main_stack_size; +ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error"); + +/* Mapping the heap into the large 192KB RAM */ +_end = 0x20000000; +_heap_end = 0x20030000; /* end of available ram */ + +/* identify the Entry Point */ +ENTRY(_Z13Reset_Handlerv) + +/* specify the memory areas */ +MEMORY +{ + flash(rx) : ORIGIN = 0x08000000, LENGTH = 2M + /* + * Note, the small ram starts at 0x10000000 but it is necessary to add the + * size of the main stack, so it is 0x10000200. + */ + smallram(wx) : ORIGIN = 0x10000200, LENGTH = 64K-0x200 + largeram(wx) : ORIGIN = 0x20000000, LENGTH = 192K + backupram(rw): ORIGIN = 0x40024000, LENGTH = 4K +} + +/* 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 ram, but also store a copy to + flash to initialize them */ + .data : ALIGN(8) + { + _data = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + _edata = .; + } > smallram AT > flash + _etext = LOADADDR(.data); + + /* .bss section: uninitialized global variables go to ram */ + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + . = ALIGN(8); + } > smallram + _bss_end = .; + + /*_end = .;*/ + /*PROVIDE(end = .);*/ +} diff --git a/src/bsps/stm32f429zi_lyra_cubesat/stm32_2m+8m_xram.ld b/src/bsps/stm32f429zi_lyra_cubesat/stm32_2m+8m_xram.ld new file mode 100644 index 000000000..b6a0d2668 --- /dev/null +++ b/src/bsps/stm32f429zi_lyra_cubesat/stm32_2m+8m_xram.ld @@ -0,0 +1,178 @@ +/* + * C++ enabled linker script for stm32 (2M FLASH, 256K RAM, 8M XRAM) + * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel + */ + +/* + * This chip has an unusual quirk that the RAM is divided in two block mapped + * at two non contiguous memory addresses. I don't know why they've done that, + * probably doing the obvious thing would have made writing code too easy... + * Anyway, since hardware can't be changed, we've got to live with that and + * try to make use of both RAMs. + * + * Given the constraints above, this linker script puts: + * - read only data and code (.text, .rodata, .eh_*) in FLASH + * - the 512Byte main (IRQ) stack, .data and .bss in the "small" 64KB RAM + * - .data, .bss, stacks and heap in the external 8MB 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 = 0x00000200; /* main stack = 512Bytes */ +_main_stack_top = 0x10000000 + _main_stack_size; +ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error"); + +/* Mapping the heap into XRAM */ +_heap_end = 0xd0800000; /* end of available ram */ + +/* identify the Entry Point */ +ENTRY(_Z13Reset_Handlerv) + +/* specify the memory areas */ +MEMORY +{ + flash(rx) : ORIGIN = 0x08000000, LENGTH = 2M + /* + * Note, the small ram starts at 0x10000000 but it is necessary to add the + * size of the main stack, so it is 0x10000200. + */ + smallram(wx) : ORIGIN = 0x10000200, LENGTH = 64K-0x200 + largeram(wx) : ORIGIN = 0x20000000, LENGTH = 192K + backupram(rw): ORIGIN = 0x40024000, LENGTH = 4K + xram(wx) : ORIGIN = 0xd0000000, LENGTH = 8M +} + +/* 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 ram, 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 ram */ + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + . = ALIGN(8); + } > xram + _bss_end = .; + + _end = .; + PROVIDE(end = .); +} diff --git a/src/shared/sensors/analog/pressure/nxp/MPXH6250A.h b/src/shared/sensors/analog/pressure/nxp/MPXH6250A.h new file mode 100644 index 000000000..5e2c66022 --- /dev/null +++ b/src/shared/sensors/analog/pressure/nxp/MPXH6250A.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2024 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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 + +#include <sensors/analog/pressure/AnalogPressureSensor.h> +#include <utils/Stats/Stats.h> + +#include "MPXH6250AData.h" + +namespace Boardcore +{ + +/** + * @brief Driver for NXP's MPXHZ6130A pressure sensor + */ +class MPXH6250A final : public AnalogPressureSensor<MPXH6250AData> +{ +public: + MPXH6250A(std::function<ADCData()> getVoltage, + const float supplyVoltage = 5.0) + : AnalogPressureSensor(getVoltage, supplyVoltage, 250000, 20000) + { + } + +private: + float voltageToPressure(float voltage) override + { + return (((voltage / supplyVoltage) + CONST_B) / CONST_A) * 1000.0; + } + + // Constants from datasheet + static constexpr float CONST_A = 0.0040; + static constexpr float CONST_B = 0.040; +}; + +} // namespace Boardcore diff --git a/src/shared/sensors/analog/pressure/nxp/MPXH6250AData.h b/src/shared/sensors/analog/pressure/nxp/MPXH6250AData.h new file mode 100644 index 000000000..a35e28010 --- /dev/null +++ b/src/shared/sensors/analog/pressure/nxp/MPXH6250AData.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2024 Skyward Experimental Rocketry + * Author: Vincenzo Tirolese + * + * 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 + +#include <sensors/SensorData.h> + +namespace Boardcore +{ + +struct MPXH6250AData : public PressureData +{ + static std::string header() { return "pressureTimestamp,pressure\n"; } + + void print(std::ostream& os) const + { + os << pressureTimestamp << "," << pressure << "\n"; + } +}; + +} // namespace Boardcore -- GitLab From 409f937b2237ae28fd8204f4eb32aab413d19877 Mon Sep 17 00:00:00 2001 From: Davide Basso <davide.basso@skywarder.eu> Date: Sat, 14 Sep 2024 17:18:45 +0200 Subject: [PATCH 2/4] [BSP] Add lyra_cubesat config to c_cpp_properties --- .vscode/c_cpp_properties.json | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 89f94061b..a715574af 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -571,6 +571,29 @@ "${workspaceFolder}/libs/miosix-kernel/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery", "${workspaceFolder}/libs/miosix-kernel/miosix/config/arch/cortexM7_stm32f7/stm32f769ni_discovery" ] + }, + { + "name": "stm32f429zi_lyra_cubesat", + "cStandard": "c11", + "cppStandard": "c++14", + "compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++", + "defines": [ + "${defaultDefines}", + "_MIOSIX_BOARDNAME=stm32f429zi_lyra_cubesat", + "_BOARD_STM32F429ZI_LYRA_CUBESAT", + "_ARCH_CORTEXM4_STM32F4", + "STM32F429xx", + "HSE_VALUE=8000000", + "SYSCLK_FREQ_168MHz=168000000", + "__ENABLE_XRAM", + "V_DDA_VOLTAGE=3.3f" + ], + "includePath": [ + "${defaultIncludePaths}", + "${workspaceFolder}/libs/miosix-kernel/miosix/arch/cortexM4_stm32f4/common", + "${workspaceFolder}/src/bsps/stm32f429zi_lyra_cubesat/config", + "${workspaceFolder}/src/bsps/stm32f429zi_lyra_cubesat" + ] } ], "version": 4 -- GitLab From aaf259db663559ef5e1cc2c4d63ea6939f7be06b Mon Sep 17 00:00:00 2001 From: Davide Basso <davide.basso@skywarder.eu> Date: Mon, 9 Dec 2024 22:44:11 +0100 Subject: [PATCH 3/4] [BSP] Remove final keyword from MPXH6250A --- src/shared/sensors/analog/pressure/nxp/MPXH6250A.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/sensors/analog/pressure/nxp/MPXH6250A.h b/src/shared/sensors/analog/pressure/nxp/MPXH6250A.h index 5e2c66022..a862bfa79 100644 --- a/src/shared/sensors/analog/pressure/nxp/MPXH6250A.h +++ b/src/shared/sensors/analog/pressure/nxp/MPXH6250A.h @@ -33,7 +33,7 @@ namespace Boardcore /** * @brief Driver for NXP's MPXHZ6130A pressure sensor */ -class MPXH6250A final : public AnalogPressureSensor<MPXH6250AData> +class MPXH6250A : public AnalogPressureSensor<MPXH6250AData> { public: MPXH6250A(std::function<ADCData()> getVoltage, -- GitLab From e3b1a8be4f2bf21a94c4c006747f158374127196 Mon Sep 17 00:00:00 2001 From: Davide Basso <davide.basso@skywarder.eu> Date: Tue, 17 Dec 2024 19:14:20 +0100 Subject: [PATCH 4/4] [Style] Fix format --- .../config/miosix_settings.h | 14 +++++++------- .../stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/bsps/stm32f429zi_lyra_cubesat/config/miosix_settings.h b/src/bsps/stm32f429zi_lyra_cubesat/config/miosix_settings.h index 66b92921e..c1dcb0cd3 100644 --- a/src/bsps/stm32f429zi_lyra_cubesat/config/miosix_settings.h +++ b/src/bsps/stm32f429zi_lyra_cubesat/config/miosix_settings.h @@ -27,8 +27,8 @@ // 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. +// #error This error is a reminder that you have not edited miosix_settings.h +// yet. #endif // PARSING_FROM_IDE /** @@ -70,14 +70,14 @@ namespace miosix // Uncomment only *one* of those #define SCHED_TYPE_PRIORITY -//#define SCHED_TYPE_CONTROL_BASED -//#define SCHED_TYPE_EDF +// #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 +// #define WITH_CPU_TIME_COUNTER // // Filesystem options @@ -110,7 +110,7 @@ const unsigned char MAX_OPEN_FILES = 8; /// 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 +// #define WITH_PROCESSES #if defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS) #error Processes require C++ exception support @@ -145,7 +145,7 @@ const unsigned char MAX_OPEN_FILES = 8; /// \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 +// #define WITH_DEEP_SLEEP /** * \def JTAG_DISABLE_SLEEP diff --git a/src/bsps/stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp b/src/bsps/stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp index b189eb8bf..87ecbf08e 100644 --- a/src/bsps/stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp +++ b/src/bsps/stm32f429zi_lyra_cubesat/core/stage_1_boot.cpp @@ -55,11 +55,11 @@ void program_startup() 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; + 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); -- GitLab