Skip to content
Snippets Groups Projects
Commit e36fcd56 authored by Fabrizio Monti's avatar Fabrizio Monti Committed by Niccolò Betto
Browse files

[BSP] Orion Engine BSP

parent ef4e2d7b
No related branches found
No related tags found
1 merge request!358[BSP] Orion Engine BSP
Pipeline #11272 passed
Showing
with 2062 additions and 0 deletions
......@@ -502,6 +502,29 @@
"${workspaceFolder}/src/bsps/stm32f767zi_lyra_gs"
]
},
{
"name": "stm32f767zi_orion_engine",
"cStandard": "c11",
"cppStandard": "c++14",
"compilerPath": "/opt/arm-miosix-eabi/bin/arm-miosix-eabi-g++",
"defines": [
"${defaultDefines}",
"_MIOSIX_BOARDNAME=stm32f767zi_orion_engine",
"_BOARD_STM32F767ZI_ORION_ENGINE",
"_ARCH_CORTEXM7_STM32F7",
"STM32F767xx",
"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_orion_engine/config",
"${workspaceFolder}/src/bsps/stm32f767zi_orion_engine"
]
},
// Miosix boards
{
"name": "stm32f407vg_stm32f4discovery",
......
......@@ -43,4 +43,5 @@ set(BOARDCORE_BOARDS_OPTIONS_FILES
${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
${BOARDCORE_PATH}/src/bsps/stm32f767zi_orion_engine/config/board_options.cmake
)
# 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_orion_engine)
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/${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 -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
${KPATH}/arch/common/drivers/stm32_bsram.cpp
)
/* 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_SDMMC 1 // Select either SDMMC1 or SDMMC2
// Disable 4bit wire mode and set speed to 2Mhz (48Mhz / (22 + 2))
#define SD_ONE_BIT_DATABUS
#define OVERRIDE_SD_CLOCK_DIVIDER_MAX 22
/// Analog supply voltage for ADC, DAC, Reset blocks, RCs and PLL
#define V_DDA_VOLTAGE 3.3f
/**
* \}
*/
} // namespace miosix
/* 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
This diff is collapsed.
/* 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
/* Copyright (c) 2025 Skyward Experimental Rocketry
* Authors: Alberto Nidasio, Davide Mor, Fabrizio Monti
*
* 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_bsram.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
//
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 configureBackupSram()
{
// Initialize the backup SRAM device
BSRAM::init();
// Defined in the linker script
extern unsigned char _preserve_start asm("_preserve_start");
extern unsigned char _preserve_end asm("_preserve_end");
extern unsigned char _preserve_load asm("_preserve_load");
unsigned char* preserve_start = &_preserve_start;
unsigned char* preserve_end = &_preserve_end;
unsigned char* preserve_load = &_preserve_load;
// Load the .preserve section from flash if not a software reset
if (miosix::lastResetReason() != miosix::ResetReason::SOFTWARE)
{
BSRAM::EnableWriteLock l;
memcpy(preserve_start, preserve_load, preserve_end - preserve_start);
}
}
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);
interfaces::spi1::sck::alternateFunction(5);
interfaces::spi1::sck::mode(Mode::ALTERNATE);
interfaces::spi1::miso::alternateFunction(5);
interfaces::spi1::miso::mode(Mode::ALTERNATE);
interfaces::spi1::mosi::alternateFunction(5);
interfaces::spi1::mosi::mode(Mode::ALTERNATE);
interfaces::spi3::sck::alternateFunction(6);
interfaces::spi3::sck::mode(Mode::ALTERNATE);
interfaces::spi3::miso::alternateFunction(6);
interfaces::spi3::miso::mode(Mode::ALTERNATE);
interfaces::spi3::mosi::alternateFunction(5);
interfaces::spi3::mosi::mode(Mode::ALTERNATE);
interfaces::spi4::sck::alternateFunction(5);
interfaces::spi4::sck::mode(Mode::ALTERNATE);
interfaces::spi4::miso::alternateFunction(5);
interfaces::spi4::miso::mode(Mode::ALTERNATE);
interfaces::spi4::mosi::alternateFunction(5);
interfaces::spi4::mosi::mode(Mode::ALTERNATE);
// We do not need to setup the miosix usart
interfaces::uart4::tx::alternateFunction(8);
interfaces::uart4::tx::mode(Mode::ALTERNATE);
interfaces::uart4::rx::alternateFunction(8);
interfaces::uart4::rx::mode(Mode::ALTERNATE);
interfaces::can1::tx::alternateFunction(9);
interfaces::can1::tx::mode(Mode::ALTERNATE);
interfaces::can1::rx::alternateFunction(9);
interfaces::can1::rx::mode(Mode::ALTERNATE);
interfaces::timers::tim1ch1::alternateFunction(1);
interfaces::timers::tim1ch1::mode(Mode::ALTERNATE);
interfaces::timers::tim3ch1::alternateFunction(2);
interfaces::timers::tim3ch1::mode(Mode::ALTERNATE);
interfaces::timers::tim4ch1::alternateFunction(2);
interfaces::timers::tim4ch1::mode(Mode::ALTERNATE);
interfaces::timers::tim8ch2::alternateFunction(3);
interfaces::timers::tim8ch2::mode(Mode::ALTERNATE);
interfaces::timers::tim9ch1::alternateFunction(3);
interfaces::timers::tim9ch1::mode(Mode::ALTERNATE);
interfaces::timers::tim11ch1::alternateFunction(3);
interfaces::timers::tim11ch1::mode(Mode::ALTERNATE);
interfaces::timers::tim12ch2::alternateFunction(9);
interfaces::timers::tim12ch2::mode(Mode::ALTERNATE);
interfaces::adcs::adc12in9::mode(Mode::INPUT_ANALOG);
interfaces::adcs::adc12in14::mode(Mode::INPUT_ANALOG);
sensors::ADS131M08::cs::mode(Mode::OUTPUT);
sensors::ADS131M08::cs::high();
sensors::LPS22DF::cs::mode(Mode::OUTPUT);
sensors::LPS22DF::cs::high();
sensors::LIS2MDL::cs::mode(Mode::OUTPUT);
sensors::LIS2MDL::cs::high();
sensors::H3LIS331DL::cs::mode(Mode::OUTPUT);
sensors::H3LIS331DL::cs::high();
sensors::LSM6DSRX0::cs::mode(Mode::OUTPUT);
sensors::LSM6DSRX0::cs::high();
sensors::LSM6DSRX1::cs::mode(Mode::OUTPUT);
sensors::LSM6DSRX1::cs::high();
sensors::thermocouple::cs::mode(Mode::OUTPUT);
sensors::thermocouple::cs::high();
gpios::boardLed::mode(Mode::OUTPUT);
gpios::boardLed::low();
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
/* 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"
/**
* Macro to place a variable in the backup SRAM. Variables are allowed to have a
* default value. The kernel initializes the variable to the provided value if
* the reset reason is not a software reset.
*
* Example usage: `PRESERVE int myVar = 0;`
*/
#define PRESERVE __attribute__((section(".preserve")))
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
* Called by stage_1_boot.cpp to configure the backup SRAM and .preserve region
* Requires the CPU clock to be already configured (running from the PLL)
*/
void configureBackupSram();
/**
* \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
/* Copyright (c) 2025 Skyward Experimental Rocketry
* Author: Davide Mor, Fabrizio Monti
*
* 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 "interfaces/gpio.h"
#define MIOSIX_SENSOR_H3LIS331DL_SPI SPI1
#define MIOSIX_SENSOR_LPS22DF_SPI SPI1
#define MIOSIX_SENSOR_LSM6DSRX_SPI SPI3
#define MIOSIX_SENSOR_LIS2MDL_SPI SPI3
#define MIOSIX_SENSOR_ADS131M08_SPI SPI4
namespace miosix
{
namespace interfaces
{
// H3LIS, LPS22
namespace spi1
{
using sck = Gpio<GPIOA_BASE, 5>;
using miso = Gpio<GPIOA_BASE, 6>;
using mosi = Gpio<GPIOA_BASE, 7>;
} // namespace spi1
// LSM6, LIS2MDL
namespace spi3
{
using sck = Gpio<GPIOB_BASE, 3>;
using miso = Gpio<GPIOB_BASE, 4>;
using mosi = Gpio<GPIOD_BASE, 6>;
} // namespace spi3
// ADS131
namespace spi4
{
using sck = Gpio<GPIOE_BASE, 2>;
using miso = Gpio<GPIOE_BASE, 5>;
using mosi = Gpio<GPIOE_BASE, 6>;
} // namespace spi4
// Miosix UART
namespace usart1
{
using tx = Gpio<GPIOA_BASE, 9>;
using rx = Gpio<GPIOA_BASE, 10>;
} // namespace usart1
// HIL UART
namespace uart4
{
using tx = Gpio<GPIOA_BASE, 0>;
using rx = Gpio<GPIOA_BASE, 1>;
} // namespace uart4
namespace can1
{
using tx = Gpio<GPIOA_BASE, 12>;
using rx = Gpio<GPIOA_BASE, 11>;
} // namespace can1
namespace timers
{
using tim1ch1 = Gpio<GPIOA_BASE, 8>;
using tim3ch1 = Gpio<GPIOC_BASE, 6>;
using tim4ch1 = Gpio<GPIOD_BASE, 12>;
using tim8ch2 = Gpio<GPIOC_BASE, 7>;
using tim9ch1 = Gpio<GPIOA_BASE, 2>;
using tim11ch1 = Gpio<GPIOB_BASE, 9>;
using tim12ch2 = Gpio<GPIOB_BASE, 15>;
} // namespace timers
namespace adcs
{
using adc12in9 = Gpio<GPIOB_BASE, 1>;
using adc12in14 = Gpio<GPIOC_BASE, 4>;
} // namespace adcs
} // namespace interfaces
namespace sensors
{
namespace ADS131M08
{
using cs = Gpio<GPIOG_BASE, 13>;
}
namespace LPS22DF
{
using cs = Gpio<GPIOG_BASE, 14>;
}
namespace LIS2MDL
{
using cs = Gpio<GPIOD_BASE, 5>;
}
namespace H3LIS331DL
{
using cs = Gpio<GPIOB_BASE, 7>;
}
namespace LSM6DSRX0
{
using cs = Gpio<GPIOG_BASE, 12>;
}
namespace LSM6DSRX1
{
using cs = Gpio<GPIOG_BASE, 11>;
}
namespace thermocouple
{
using cs = Gpio<GPIOD_BASE, 11>;
}
} // namespace sensors
namespace adcs
{
using vbat = miosix::interfaces::adcs::adc12in14;
using servoCur = miosix::interfaces::adcs::adc12in9;
} // namespace adcs
namespace servos
{
#define MIOSIX_SERVOS_0_TIM TIM3
#define MIOSIX_SERVOS_0_CHANNEL CHANNEL_1
using servo0 = miosix::interfaces::timers::tim3ch1;
#define MIOSIX_SERVOS_1_TIM TIM1
#define MIOSIX_SERVOS_1_CHANNEL CHANNEL_1
using servo1 = miosix::interfaces::timers::tim1ch1;
#define MIOSIX_SERVOS_2_TIM TIM8
#define MIOSIX_SERVOS_2_CHANNEL CHANNEL_2
using servo2 = miosix::interfaces::timers::tim8ch2;
#define MIOSIX_SERVOS_3_TIM TIM9
#define MIOSIX_SERVOS_3_CHANNEL CHANNEL_1
using servo3 = miosix::interfaces::timers::tim9ch1;
#define MIOSIX_SERVOS_4_TIM TIM11
#define MIOSIX_SERVOS_4_CHANNEL CHANNEL_1
using servo4 = miosix::interfaces::timers::tim11ch1;
#define MIOSIX_SERVOS_5_TIM TIM4
#define MIOSIX_SERVOS_5_CHANNEL CHANNEL_1
using servo5 = miosix::interfaces::timers::tim4ch1;
} // namespace servos
namespace gpios
{
using boardLed = Gpio<GPIOC_BASE, 5>;
} // namespace gpios
} // namespace miosix
/*
* 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 : ALIGN(4)
{
_preserve_start = .;
. = ALIGN(4);
*(.preserve);
*(.preserve*);
. = ALIGN(4);
_preserve_end = .;
} > bram AT > flash
_preserve_load = LOADADDR(.preserve);
}
/*
* 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 : ALIGN(4)
{
_preserve_start = .;
. = ALIGN(4);
*(.preserve);
*(.preserve*);
. = ALIGN(4);
_preserve_end = .;
} > bram AT > flash
_preserve_load = LOADADDR(.preserve);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment