diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/core/stage_1_boot.cpp b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/core/stage_1_boot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..515049d746aa15dce770b727a0a4aa8b7b961ee7 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/core/stage_1_boot.cpp @@ -0,0 +1,413 @@ + +#include "interfaces/arch_registers.h" +#include "interfaces/bsp.h" +#include "core/interrupts.h" //For the unexpected interrupt call +#include "kernel/stage_2_boot.h" +#include <string.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 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/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/death_stack.cfg b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/death_stack.cfg new file mode 100644 index 0000000000000000000000000000000000000000..409f4009d1e873cd7f64d6f77e315add7dd84ddb --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/death_stack.cfg @@ -0,0 +1,17 @@ +# +# OpenOCD configuration file for in-circuit debugging the stm32f4discovery +# To start debugging issue those commands: +# arm-miosix-eabi-gdb main.elf +# target remote :3333 +# monitor reset halt +# load +# break main +# continue +# + +# Daemon configuration +telnet_port 4444 +gdb_port 3333 + +# Board support is available in newer oocd +source [find board/stm32f4discovery.cfg] diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/arch_registers_impl.h b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/arch_registers_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..dfa0203013e65b9bc414c954d4cb1ddc1867d258 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/arch_registers_impl.h @@ -0,0 +1,13 @@ + +#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/Include/core_cm4.h" +#include "CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h" + +#define RCC_SYNC() __DSB() //Workaround for a bug in stm32f42x + +#endif //ARCH_REGISTERS_IMPL_H diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/bsp.cpp b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/bsp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..857b118d74dda045515c8398bf9a651a5e23aaf1 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/bsp.cpp @@ -0,0 +1,339 @@ +/*************************************************************************** + * Copyright (C) 2014 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * 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 General * + * Public License. This exception does not invalidate any other reasons * + * 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/> * + ***************************************************************************/ + +/*********************************************************************** +* bsp.cpp Part of the Miosix Embedded OS. +* Board support package, this file initializes hardware. +************************************************************************/ + +#include <cstdlib> +#include <inttypes.h> +#include <sys/ioctl.h> +#include "interfaces/bsp.h" +#include "kernel/kernel.h" +#include "kernel/sync.h" +#include "interfaces/delays.h" +#include "interfaces/portability.h" +#include "interfaces/arch_registers.h" +#include "config/miosix_settings.h" +#include "kernel/logging.h" +#include "filesystem/file_access.h" +#include "filesystem/console/console_device.h" +#include "drivers/serial.h" +#include "drivers/sd_stm32f2_f4.h" +#include "board_settings.h" +#include "hwmapping.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; +} + +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 +} + +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 + + 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); + + spi2::sck::mode(Mode::ALTERNATE); + spi2::sck::alternateFunction(5); + spi2::miso::mode(Mode::ALTERNATE); + spi2::miso::alternateFunction(5); + spi2::mosi::mode(Mode::ALTERNATE); + spi2::mosi::alternateFunction(5); + + i2c::scl::mode(Mode::ALTERNATE_OD); + i2c::scl::alternateFunction(4); + i2c::sda::mode(Mode::ALTERNATE_OD); + i2c::sda::alternateFunction(4); + + uart4::rx::mode(Mode::ALTERNATE); + uart4::rx::alternateFunction(8); + uart4::tx::mode(Mode::ALTERNATE); + uart4::tx::alternateFunction(8); + + can::rx::mode(Mode::ALTERNATE); + can::rx::alternateFunction(9); + can::tx::mode(Mode::ALTERNATE); + can::tx::alternateFunction(9); + + using namespace sensors; + adis16405::cs::mode(Mode::OUTPUT); + adis16405::cs::high(); + adis16405::ckIn::mode(Mode::ALTERNATE); + adis16405::ckIn::alternateFunction(2); + adis16405::dio1::mode(Mode::INPUT); + + ad7994::ab::mode(Mode::INPUT); + ad7994::nconvst::mode(Mode::OUTPUT); + + mpu9250::cs::mode(Mode::OUTPUT); + mpu9250::cs::high(); + + ms5803::cs::mode(Mode::OUTPUT); + ms5803::cs::high(); + + lsm6ds3h::cs::mode(Mode::OUTPUT); + lsm6ds3h::cs::high(); + lsm6ds3h::int1::mode(Mode::INPUT); + lsm6ds3h::int2::mode(Mode::INPUT); + + using namespace inputs; + vbat::mode(Mode::INPUT_ANALOG); + lpDet::mode(Mode::INPUT); + btn1::mode(Mode::INPUT); + btn2::mode(Mode::INPUT); + + using namespace nosecone; + motEn::mode(Mode::OUTPUT); + motEn::low(); + + motP1::mode(Mode::ALTERNATE); + motP1::alternateFunction(3); + + motP2::mode(Mode::ALTERNATE); + motP2::alternateFunction(3); + + rogP1::mode(Mode::ALTERNATE); + rogP1::alternateFunction(2); + + rogP2::mode(Mode::ALTERNATE); + rogP2::alternateFunction(3); + + dtch::mode(Mode::INPUT); + + using namespace actuators; + tcPwm::mode(Mode::ALTERNATE); + tcPwm::alternateFunction(3); + + thCut1::ena::mode(Mode::OUTPUT); + thCut1::ena::low(); + thCut1::csens::mode(Mode::INPUT_ANALOG); + + thCut2::ena::mode(Mode::OUTPUT); + thCut2::ena::low(); + thCut2::csens::mode(Mode::INPUT_ANALOG); + + misc::buzz::mode(Mode::OUTPUT); + misc::buzz::low(); + + InAir9B::cs::mode(Mode::OUTPUT); + InAir9B::cs::high(); + //NOTE: in the InAir9B datasheet is specified that the nRSR line should be + //on hi-Z state when idle, thus we set the gpio as open drain + InAir9B::nrst::mode(Mode::OPEN_DRAIN); + InAir9B::nrst::high(); + InAir9B::dio0::mode(Mode::INPUT); + InAir9B::dio1::mode(Mode::INPUT); + InAir9B::dio2::mode(Mode::INPUT); + InAir9B::dio3::mode(Mode::INPUT); + +// _led::mode(Mode::OUTPUT); +// Removed led blink to speed up boot +// ledOn(); +// delayMs(100); +// ledOff(); + DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>( + new STM32Serial(defaultSerial,defaultSerialSpeed, + defaultSerialFlowctrl ? STM32Serial::RTSCTS : STM32Serial::NOFLOWCTRL))); +} + +void bspInit2() +{ + #ifdef WITH_FILESYSTEM + intrusive_ref_ptr<DevFs> devFs = basicFilesystemSetup(SDIODriver::instance()); + devFs->addDevice("gps", intrusive_ref_ptr<Device>(new STM32Serial(2,115200))); + #endif //WITH_FILESYSTEM +} + +// +// Shutdown and reboot +// + +/** + * For safety reasons, we never want the anakin to shutdown. + * When requested to shutdown, we reboot instead. + */ +void shutdown() +{ + reboot(); +} + +void reboot() +{ + ioctl(STDOUT_FILENO,IOCTL_SYNC,0); + + #ifdef WITH_FILESYSTEM + FilesystemManager::instance().umountAll(); + #endif //WITH_FILESYSTEM + + disableInterrupts(); + miosix_private::IRQsystemReboot(); +} + +} //namespace miosix diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/bsp_impl.h b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/bsp_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..cb54b3a941599a8d9d54411bd7ea0e727882c415 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/bsp_impl.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2014 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * 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 General * + * Public License. This exception does not invalidate any other reasons * + * 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/> * + ***************************************************************************/ + +/*********************************************************************** +* 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" +#include "drivers/stm32_hardware_rng.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() +{ + // No led for this board, unimplemented +} + +inline void ledOff() +{ + // No led for this board, unimplemented +} + +/** +\} +*/ + +} //namespace miosix + +#endif //BSP_IMPL_H diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/hwmapping.h b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/hwmapping.h new file mode 100644 index 0000000000000000000000000000000000000000..fc01121d1ef8069b8752afe7dd228249fb19d7b9 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/interfaces-impl/hwmapping.h @@ -0,0 +1,150 @@ +/*************************************************************************** + * Copyright (C) 2018 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * 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 General * + * Public License. This exception does not invalidate any other reasons * + * 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/> * + ***************************************************************************/ + +#ifndef HWMAPPING_H +#define HWMAPPING_H + +#include "interfaces/gpio.h" + +namespace miosix { + +namespace interfaces { + +namespace spi1 { +using sck = Gpio<GPIOA_BASE, 5>; +using miso = Gpio<GPIOA_BASE, 6>; +using mosi = Gpio<GPIOA_BASE, 7>; +} //namespace spi1 + +namespace spi2 { +using sck = Gpio<GPIOB_BASE, 13>; +using miso = Gpio<GPIOB_BASE, 14>; +using mosi = Gpio<GPIOB_BASE, 15>; +} //namespace spi2 + +namespace i2c { +using scl = Gpio<GPIOB_BASE, 8>; +using sda = Gpio<GPIOB_BASE, 9>; +} //namespace i2c + +namespace uart4 { +using tx = Gpio<GPIOA_BASE, 0>; +using rx = Gpio<GPIOA_BASE, 1>; +} //namespace uart4 + +namespace can { +using rx = Gpio<GPIOA_BASE, 11>; +using tx = Gpio<GPIOA_BASE, 12>; +} // namespace can +} //namespace interfaces + +namespace sensors { + +namespace adis16405 { +using cs = Gpio<GPIOA_BASE, 8>; +using dio1 = Gpio<GPIOB_BASE, 4>; +using dio2 = Gpio<GPIOD_BASE, 6>; +using dio3 = Gpio<GPIOD_BASE, 4>; +using ckIn = Gpio<GPIOA_BASE, 15>; +} //namespace adis16405 + +namespace ad7994 { +using ab = Gpio<GPIOB_BASE, 1>; +using nconvst = Gpio<GPIOG_BASE, 9>; +} //namespace ad7994 + +namespace mpu9250 { +using cs = Gpio<GPIOC_BASE, 3>; +using intr = Gpio<GPIOE_BASE, 5>; +} //namespace mpu9250 + +namespace ms5803 { +using cs = Gpio<GPIOD_BASE, 7>; +} //namespace ms5803 + +namespace lsm6ds3h { +using cs = Gpio<GPIOC_BASE, 1>; +using int1 = Gpio<GPIOB_BASE, 12>; +using int2 = Gpio<GPIOG_BASE, 3>; +} + +} //namespace sensors + +namespace inputs { + +using vbat = Gpio<GPIOF_BASE, 7>; +using lpDet = Gpio<GPIOC_BASE, 6>; //launchpad detach +using btn1 = Gpio<GPIOG_BASE, 11>; +using btn2 = Gpio<GPIOG_BASE, 13>; +} + +namespace nosecone { + +using motEn = Gpio<GPIOG_BASE, 14>; +using motP1 = Gpio<GPIOC_BASE, 7>; //Pwm motore 1 +using motP2 = Gpio<GPIOB_BASE, 0>; //Pwm motore 2 +using rogP1 = Gpio<GPIOD_BASE, 12>; //Pwm rogallina 1 +using rogP2 = Gpio<GPIOD_BASE, 13>; //Pwm rogallina 2 +using dtch = Gpio<GPIOB_BASE, 7>; //Nosecone detach +} + +namespace actuators { + +using tcPwm = Gpio<GPIOE_BASE, 6>; //Pwm thermal cutters + +namespace thCut1 { +using ena = Gpio<GPIOD_BASE, 11>; +using csens = Gpio<GPIOF_BASE, 8>; +} + +namespace thCut2 { +using ena = Gpio<GPIOG_BASE, 2>; +using csens = Gpio<GPIOF_BASE, 6>; +} +} //namespace actuators + +namespace misc { + +using buzz = Gpio<GPIOD_BASE, 3>; +using aux1 = Gpio<GPIOE_BASE, 2>; +using aux2 = Gpio<GPIOE_BASE, 3>; +using aux3 = Gpio<GPIOE_BASE, 4>; +using aux4 = Gpio<GPIOC_BASE, 14>; +using aux5 = Gpio<GPIOC_BASE, 15>; +} + +namespace InAir9B { +using dio0 = Gpio<GPIOB_BASE, 0>; +using dio1 = Gpio<GPIOC_BASE, 4>; +using dio2 = Gpio<GPIOA_BASE, 4>; +using dio3 = Gpio<GPIOC_BASE, 2>; +using cs = Gpio<GPIOF_BASE, 9>; +using nrst = Gpio<GPIOF_BASE, 7>; +} //namespace InAir9B +} //namespace miosix + +#endif //HWMAPPING_H diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/stm32_2m+256k_rom.ld b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/stm32_2m+256k_rom.ld new file mode 100644 index 0000000000000000000000000000000000000000..cfcc2ce53bd9e1b821cbfe90aeedd73fcdce1522 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/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/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/stm32_2m+8m_xram.ld b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/stm32_2m+8m_xram.ld new file mode 100644 index 0000000000000000000000000000000000000000..b6a0d26683cbff52ac66b7f275f9269d61dfbf41 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/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/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index 0f1fa2f01f099e7d974df7df2da6c6cfc7cc75af..89861740b947cb50207bf7081a01b8fd0b84076c 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -47,6 +47,7 @@ #OPT_BOARD := stm32f205_generic #OPT_BOARD := stm32f103cx_generic #OPT_BOARD := stm32f072rb_stm32f0discovery +#OPT_BOARD := stm32f429zi_skyward_death_stack ## ## Optimization flags, choose one. @@ -587,6 +588,35 @@ ifeq ($(OPT_BOARD),stm32f103cx_generic) endif +##--------------------------------------------------------------------------- +## stm32f429zi_skyward_death_stack +## +ifeq ($(OPT_BOARD),stm32f429zi_skyward_death_stack) + + ## 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. + LINKER_SCRIPT_PATH := arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/ + #LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_2m+256k_rom.ld + LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_2m+8m_xram.ld + + ## Uncommenting __ENABLE_XRAM enables the initialization of the external + ## 8MB SDRAM memory. + 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) + #CLOCK_FREQ := -DHSE_VALUE=8000000 -DSYSCLK_FREQ_180MHz=180000000 + CLOCK_FREQ := -DHSE_VALUE=8000000 -DSYSCLK_FREQ_168MHz=168000000 + #CLOCK_FREQ := -DHSE_VALUE=8000000 -DSYSCLK_FREQ_100MHz=100000000 + +endif + ############################################################################ ## From the options selected above, now fill all the variables needed to ## ## build Miosix. You should modify something here only if you are adding ## @@ -674,6 +704,8 @@ else ifeq ($(OPT_BOARD),stm32f103cx_generic) ARCH := cortexM3_stm32 else ifeq ($(OPT_BOARD),stm32f072rb_stm32f0discovery) ARCH := cortexM0_stm32f0 +else ifeq ($(OPT_BOARD),stm32f429zi_skyward_death_stack) + ARCH := cortexM4_stm32f4 else $(info Error: no board specified in miosix/config/Makefile.inc) $(error Error) @@ -1589,7 +1621,7 @@ else ifeq ($(ARCH),cortexM4_stm32f4) ## error message saying that 'make program' is not supported for that ## board. PROGRAM_CMDLINE := qstlink2 -cqewV ./main.bin - + ##------------------------------------------------------------------------- ## BOARD: stm32f407vg_thermal_test_chip ## @@ -1622,6 +1654,40 @@ else ifeq ($(ARCH),cortexM4_stm32f4) ## board. PROGRAM_CMDLINE := qstlink2 -cqewV ./main.bin + ##------------------------------------------------------------------------- + ## BOARD: stm32f429zi_skyward_death_stack + ## + else ifeq ($(OPT_BOARD),stm32f429zi_skyward_death_stack) + + ## Base directory with header files for this board + BOARD_INC := arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack + + ## Select linker script and boot file + ## Their path must be relative to the miosix directory. + BOOT_FILE := $(BOARD_INC)/core/stage_1_boot.o + #LINKER_SCRIPT := already selected in board options + + ## Select architecture specific files + ## These are the files in arch/<arch name>/<board name> + ARCH_SRC := \ + arch/common/drivers/stm32f2_f4_i2c.cpp \ + arch/common/drivers/stm32_hardware_rng.cpp \ + arch/common/drivers/stm32_sgm.cpp \ + arch/common/drivers/stm32_wd.cpp \ + $(BOARD_INC)/interfaces-impl/bsp.cpp + + ## Add a #define to allow querying board name + CFLAGS_BASE += -D_BOARD_STM32F429ZI_SKYWARD_DEATHST + CXXFLAGS_BASE += -D_BOARD_STM32F429ZI_SKYWARD_DEATHST + + ## Select programmer command line + ## This is the program that is invoked when the user types + ## 'make program' + ## The command must provide a way to program the board, or print an + ## error message saying that 'make program' is not supported for that + ## board. + #PROGRAM_CMDLINE := qstlink2 -cqewV ./main.bin + ##------------------------------------------------------------------------- ## End of board list ## diff --git a/miosix/config/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/board_settings.h b/miosix/config/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/board_settings.h new file mode 100644 index 0000000000000000000000000000000000000000..8bc4129f1d42277de7e6e874e5c448e23be47080 --- /dev/null +++ b/miosix/config/arch/cortexM4_stm32f4/stm32f429zi_skyward_death_stack/board_settings.h @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2014 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * 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 General * + * Public License. This exception does not invalidate any other reasons * + * 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/> * + ***************************************************************************/ + +#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 100 + +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=4*1024; + +/// Frequency of tick (in Hz). The frequency of the STM32F100RB timer in the +/// stm32vldiscovery board can be divided by 1000. This allows to use a 1KHz +/// tick and the minimun Thread::sleep value is 1ms +/// For the priority scheduler this is also the context switch frequency +const unsigned int TICK_FREQ=1000; + +///\internal Aux timer run @ 100KHz +///Note that since the timer is only 16 bits this imposes a limit on the +///burst measurement of 655ms. If due to a pause_kernel() or +///disable_interrupts() section a thread runs for more than that time, a wrong +///burst value will be measured +const unsigned int AUX_TIMER_CLOCK=100000; +const unsigned int AUX_TIMER_MAX=0xffff; ///<\internal Aux timer is 16 bits + +/// Serial port +const unsigned int defaultSerial=1; +const unsigned int defaultSerialSpeed=19200; +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=30; //Board powered @ 3.0V +#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 + +/** + * \} + */ + +} //namespace miosix + +#endif /* BOARD_SETTINGS_H */