This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Cannot init heap using scatter file and C++ startup (Cortex-M4)

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,
        &ETHHandler,
        &ETH_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.

Parents
  • Hi,

    I see that you have defined __user_setup_stackheap(), but in the usualy startup code the function to setup stack and heap is called __user_initial_stackheap()

    ;*******************************************************************************
    ; User Stack and Heap initialization
    ;*******************************************************************************
                     IF      :DEF:__MICROLIB
                   
                     EXPORT  __initial_sp
                     EXPORT  __heap_base
                     EXPORT  __heap_limit
                   
                     ELSE
                   
                     IMPORT  __use_two_region_memory
                     EXPORT  __user_initial_stackheap
                    
    __user_initial_stackheap
                     LDR     R0, =  Heap_Mem
                     LDR     R1, =(Stack_Mem + Stack_Size)
                     LDR     R2, = (Heap_Mem +  Heap_Size)
                     LDR     R3, = Stack_Mem
                     BX      LR
                     ALIGN
                     ENDIF
                     END

    So perhaps that's why your heap setup is never called?

Reply
  • Hi,

    I see that you have defined __user_setup_stackheap(), but in the usualy startup code the function to setup stack and heap is called __user_initial_stackheap()

    ;*******************************************************************************
    ; User Stack and Heap initialization
    ;*******************************************************************************
                     IF      :DEF:__MICROLIB
                   
                     EXPORT  __initial_sp
                     EXPORT  __heap_base
                     EXPORT  __heap_limit
                   
                     ELSE
                   
                     IMPORT  __use_two_region_memory
                     EXPORT  __user_initial_stackheap
                    
    __user_initial_stackheap
                     LDR     R0, =  Heap_Mem
                     LDR     R1, =(Stack_Mem + Stack_Size)
                     LDR     R2, = (Heap_Mem +  Heap_Size)
                     LDR     R3, = Stack_Mem
                     BX      LR
                     ALIGN
                     ENDIF
                     END

    So perhaps that's why your heap setup is never called?

Children