Hello,
I need help with heap initialization using scatter file and C++ startup.
MCU is STM32F407VGT6 (Cortex-M4).
Compiler is ARM Compiler 6.7, C++14.
The problem is that all variables which I create dinamically on the heap have wrong addresses. My HEAP locates in CCM (starts from 0x10000000) but those variables have address from 0x08000000. And it is a FLASH memory! And I don't understand how it is happened. While initialization of stack performs in correct way... Below are my C++ startup and scatter file.
#ifndef STARTUP_HPP #define STARTUP_HPP #include <common/core.hpp> #include <registers/Scb.hpp> #include <registers/Rcc.hpp> #define ATTR_DEFAULT_HANDLER __attribute__((weak, alias ("_ZN5mylib3mcu10interrupts14defaultHandlerEv"))) int main(); extern int Image$$STACK$$ZI$$Limit; int &__initial_sp = Image$$STACK$$ZI$$Limit; extern "C" { __attribute__((naked, used)) void __user_setup_stackheap() { asm( "LDR sp, =__initial_sp\n" "LDR r0, =Image$$HEAP$$ZI$$Base\n" "LDR r2, =Image$$HEAP$$ZI$$Limit\n" "BX lr" ); } [[noreturn]] void _sys_exit(int ch) { forever; } char *_sys_command_string(char *cmd, int length) { return cmd; } void _ttywrch(int ch) { using namespace xmcu::mcu::core::registers; $ITM.$PORT0.wait(); $ITM.$PORT0.setValue(ch); } } BEGIN_NAMESPACE(mylib) BEGIN_NAMESPACE(mcu) void initializeSystem() { using namespace registers; using namespace core::registers; #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) $SCB.$CPACR.setAccess(SCB::CPACR::Full, SCB::CPACR::CP10, SCB::CPACR::CP11); #endif $RCC.$CR.setBits<true>(RCC::CR::WBit::HSION); $RCC.$CFGR.reset(); $RCC.$CR.setBits<false>(RCC::CR::WBit::HSEON, RCC::CR::WBit::CSSON, RCC::CR::WBit::PLLON); $RCC.$PLLCFGR.reset(); $RCC.$CR.setBits<false>(RCC::CR::WBit::HSEBYP); $RCC.$CIR.reset(); #ifdef STM32F407_STARTUP_VTOR_SRAM $SCB.$VTOR.setTable(SCB::VTOR::SRAM, periphery::SRAM_BASE); #else $SCB.$VTOR.setTable(SCB::VTOR::Flash, periphery::FLASH_BASE); #endif } BEGIN_NAMESPACE(interrupts) [[noreturn]] void ResetHandler() { initializeSystem(); main(); forever; } [[noreturn]] void defaultHandler() { forever; } void NMIHandler() ATTR_DEFAULT_HANDLER; void HardFaultHandler() ATTR_DEFAULT_HANDLER; void MemManageHandler() ATTR_DEFAULT_HANDLER; void BusFaultHandler() ATTR_DEFAULT_HANDLER; void UsageFaultHandler() ATTR_DEFAULT_HANDLER; void SVCHandler() ATTR_DEFAULT_HANDLER; void DebugMonHandler() ATTR_DEFAULT_HANDLER; void PendSVHandler() ATTR_DEFAULT_HANDLER; void SysTickHandler() ATTR_DEFAULT_HANDLER; void WWDGHandler() ATTR_DEFAULT_HANDLER; void PVDHandler() ATTR_DEFAULT_HANDLER; void TAMP_STAMPHandler() ATTR_DEFAULT_HANDLER; void RTC_WKUPHandler() ATTR_DEFAULT_HANDLER; void FLASHHandler() ATTR_DEFAULT_HANDLER; void RCCHandler() ATTR_DEFAULT_HANDLER; void EXTI0Handler() ATTR_DEFAULT_HANDLER; void EXTI1Handler() ATTR_DEFAULT_HANDLER; void EXTI2Handler() ATTR_DEFAULT_HANDLER; void EXTI3Handler() ATTR_DEFAULT_HANDLER; void EXTI4Handler() ATTR_DEFAULT_HANDLER; void DMA1_Stream0Handler() ATTR_DEFAULT_HANDLER; void DMA1_Stream1Handler() ATTR_DEFAULT_HANDLER; void DMA1_Stream2Handler() ATTR_DEFAULT_HANDLER; void DMA1_Stream3Handler() ATTR_DEFAULT_HANDLER; void DMA1_Stream4Handler() ATTR_DEFAULT_HANDLER; void DMA1_Stream5Handler() ATTR_DEFAULT_HANDLER; void DMA1_Stream6Handler() ATTR_DEFAULT_HANDLER; void ADCHandler() ATTR_DEFAULT_HANDLER; void CAN1_TXHandler() ATTR_DEFAULT_HANDLER; void CAN1_RX0Handler() ATTR_DEFAULT_HANDLER; void CAN1_RX1Handler() ATTR_DEFAULT_HANDLER; void CAN1_SCEHandler() ATTR_DEFAULT_HANDLER; void EXTI9_5Handler() ATTR_DEFAULT_HANDLER; void TIM1_BRK_TIM9Handler() ATTR_DEFAULT_HANDLER; void TIM1_UP_TIM10Handler() ATTR_DEFAULT_HANDLER; void TIM1_TRG_COM_TIM11Handler() ATTR_DEFAULT_HANDLER; void TIM1_CCHandler() ATTR_DEFAULT_HANDLER; void TIM2Handler() ATTR_DEFAULT_HANDLER; void TIM3Handler() ATTR_DEFAULT_HANDLER; void TIM4Handler() ATTR_DEFAULT_HANDLER; void I2C1_EVHandler() ATTR_DEFAULT_HANDLER; void I2C1_ERHandler() ATTR_DEFAULT_HANDLER; void I2C2_EVHandler() ATTR_DEFAULT_HANDLER; void I2C2_ERHandler() ATTR_DEFAULT_HANDLER; void SPI1Handler() ATTR_DEFAULT_HANDLER; void SPI2Handler() ATTR_DEFAULT_HANDLER; void USART1Handler() ATTR_DEFAULT_HANDLER; void USART2Handler() ATTR_DEFAULT_HANDLER; void USART3Handler() ATTR_DEFAULT_HANDLER; void EXTI15_10Handler() ATTR_DEFAULT_HANDLER; void RTC_AlarmHandler() ATTR_DEFAULT_HANDLER; void OTG_FS_WKUPHandler() ATTR_DEFAULT_HANDLER; void TIM8_BRK_TIM12Handler() ATTR_DEFAULT_HANDLER; void TIM8_UP_TIM13Handler() ATTR_DEFAULT_HANDLER; void TIM8_TRG_COM_TIM14Handler() ATTR_DEFAULT_HANDLER; void TIM8_CCHandler() ATTR_DEFAULT_HANDLER; void DMA1_Stream7Handler() ATTR_DEFAULT_HANDLER; void FSMCHandler() ATTR_DEFAULT_HANDLER; void SDIOHandler() ATTR_DEFAULT_HANDLER; void TIM5Handler() ATTR_DEFAULT_HANDLER; void SPI3Handler() ATTR_DEFAULT_HANDLER; void UART4Handler() ATTR_DEFAULT_HANDLER; void UART5Handler() ATTR_DEFAULT_HANDLER; void TIM6_DACHandler() ATTR_DEFAULT_HANDLER; void TIM7Handler() ATTR_DEFAULT_HANDLER; void DMA2_Stream0Handler() ATTR_DEFAULT_HANDLER; void DMA2_Stream1Handler() ATTR_DEFAULT_HANDLER; void DMA2_Stream2Handler() ATTR_DEFAULT_HANDLER; void DMA2_Stream3Handler() ATTR_DEFAULT_HANDLER; void DMA2_Stream4Handler() ATTR_DEFAULT_HANDLER; void ETHHandler() ATTR_DEFAULT_HANDLER; void ETH_WKUPHandler() ATTR_DEFAULT_HANDLER; void CAN2_TXHandler() ATTR_DEFAULT_HANDLER; void CAN2_RX0Handler() ATTR_DEFAULT_HANDLER; void CAN2_RX1Handler() ATTR_DEFAULT_HANDLER; void CAN2_SCEHandler() ATTR_DEFAULT_HANDLER; void OTG_FSHandler() ATTR_DEFAULT_HANDLER; void DMA2_Stream5Handler() ATTR_DEFAULT_HANDLER; void DMA2_Stream6Handler() ATTR_DEFAULT_HANDLER; void DMA2_Stream7Handler() ATTR_DEFAULT_HANDLER; void USART6Handler() ATTR_DEFAULT_HANDLER; void I2C3_EVHandler() ATTR_DEFAULT_HANDLER; void I2C3_ERHandler() ATTR_DEFAULT_HANDLER; void OTG_HS_EP1_OUTHandler() ATTR_DEFAULT_HANDLER; void OTG_HS_EP1_INHandler() ATTR_DEFAULT_HANDLER; void OTG_HS_WKUPHandler() ATTR_DEFAULT_HANDLER; void OTG_HSHandler() ATTR_DEFAULT_HANDLER; void DCMIHandler() ATTR_DEFAULT_HANDLER; void HASH_RNGHandler() ATTR_DEFAULT_HANDLER; void FPUHandler() ATTR_DEFAULT_HANDLER; using Handler = void (*)(); const Handler vectors[] __attribute__ ((section("interrupts"), used)) = { reinterpret_cast<Handler>(&__initial_sp), &ResetHandler, &NMIHandler, &HardFaultHandler, &MemManageHandler, &BusFaultHandler, &UsageFaultHandler, nullptr, nullptr, nullptr, nullptr, &SVCHandler, &DebugMonHandler, nullptr, &PendSVHandler, &SysTickHandler, &WWDGHandler, &PVDHandler, &TAMP_STAMPHandler, &RTC_WKUPHandler, &FLASHHandler, &RCCHandler, &EXTI0Handler, &EXTI1Handler, &EXTI2Handler, &EXTI3Handler, &EXTI4Handler, &DMA1_Stream0Handler, &DMA1_Stream1Handler, &DMA1_Stream2Handler, &DMA1_Stream3Handler, &DMA1_Stream4Handler, &DMA1_Stream5Handler, &DMA1_Stream6Handler, &ADCHandler, &CAN1_TXHandler, &CAN1_RX0Handler, &CAN1_RX1Handler, &CAN1_SCEHandler, &EXTI9_5Handler, &TIM1_BRK_TIM9Handler, &TIM1_UP_TIM10Handler, &TIM1_TRG_COM_TIM11Handler, &TIM1_CCHandler, &TIM2Handler, &TIM3Handler, &TIM4Handler, &I2C1_EVHandler, &I2C1_ERHandler, &I2C2_EVHandler, &I2C2_ERHandler, &SPI1Handler, &SPI2Handler, &USART1Handler, &USART2Handler, &USART3Handler, &EXTI15_10Handler, &RTC_AlarmHandler, &OTG_FS_WKUPHandler, &TIM8_BRK_TIM12Handler, &TIM8_UP_TIM13Handler, &TIM8_TRG_COM_TIM14Handler, &TIM8_CCHandler, &DMA1_Stream7Handler, &FSMCHandler, &SDIOHandler, &TIM5Handler, &SPI3Handler, &UART4Handler, &UART5Handler, &TIM6_DACHandler, &TIM7Handler, &DMA2_Stream0Handler, &DMA2_Stream1Handler, &DMA2_Stream2Handler, &DMA2_Stream3Handler, &DMA2_Stream4Handler, ÐHandler, Ð_WKUPHandler, &CAN2_TXHandler, &CAN2_RX0Handler, &CAN2_RX1Handler, &CAN2_SCEHandler, &OTG_FSHandler, &DMA2_Stream5Handler, &DMA2_Stream6Handler, &DMA2_Stream7Handler, &USART6Handler, &I2C3_EVHandler, &I2C3_ERHandler, &OTG_HS_EP1_OUTHandler, &OTG_HS_EP1_INHandler, &OTG_HS_WKUPHandler, &OTG_HSHandler, &DCMIHandler, nullptr, &HASH_RNGHandler, &FPUHandler }; END_NAMESPACE END_NAMESPACE END_NAMESPACE #undef ATTR_DEFAULT_HANDLER #endif //STARTUP_HPP
FLASH 0x08000000 0x00100000 { ER_IROM1 +0 0x00100000 { *.o (interrupts, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } } SRAM 0x20000000 0x00020000 { ZI +0 ZEROPAD { .ANY (+ZI, +RW) } } CCM 0x10000000 0x00010000 { STACK +0 ALIGN 8 EMPTY 0x4000 {} HEAP +0 ALIGN 8 EMPTY 0x0200 {} }
As you see - these files use the same logic like in standart startup_stm32f407xx.s.But standart file works and my - no...
I also want to note that if I eneble MICROLIB in settings of Keil, add ARM_LIB_STACK and ARM_LIB_HEAP to scatter file, my implementation begins to work correctly.
But I want to do my startup without MICROLIB.
If you know where I am wrong in my code, please help.
Best regards, Andrey.