XMC启动代码中stack_size 和 __initial_sp的问题

本文详细解析了英飞凌XMC4400单片机在DAVE集成环境下如何通过修改链接脚本中的__initial_sp值来调整启动代码中的SP值,进而设置栈顶和预置大小,以实现使用MPU硬件进行栈溢出陷阱的设置,增强程序的鲁棒性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

和启动代码卯了五天终于搞明白DAVE集成环境下启动代码是怎么修改sp值的了。

网上全是keil MDK集成环境的启动代码分析,这英飞凌太坑了。。。。。。,

言归正传:

        英飞凌XMC4400单片机的ROM固化引导程序中将SP的值赋为0x2000Fyyy(记不清了,用yyy代替),而进入main()后SP的值变为0x1FFFC800。这一过程是这样实现的:

Startup文件夹中有 startup_XMC4400.S这样一个汇编启动文件,其中有如下代码:

/* Reset Handler */
    .thumb_func
    .globl  Reset_Handler
    .type   Reset_Handler, %function
Reset_Handler:
    ldr sp,=__initial_sp

#ifndef __SKIP_SYSTEM_INIT
    ldr  r0, =SystemInit
    blx  r0
#endif

       标红句是经ROM固化引导程序后执行的第一条指令,其将SP的值设置为__initial_sp,__initial_sp是一个可被其它文件代码修改或赋值的符号,苦苦寻找了五天后(使用搜索工具无法搜到),终于在连接脚本文件linker_script.ld中找到了它,见如下脚本:

   /* DSRAM layout (Lowest to highest)*/
    Stack (NOLOAD) : 
    {
        __stack_start = .;
        . = . + stack_size;
        __stack_end = .;
        __initial_sp = .;
    } > SRAM_combined

        该连接脚本__initial_sp = .;这句话的意思是将当前计数器的数值付给符号__initial_sp,而当前计数器的数值为SRAM_combined首地址加上堆栈的大小。接脚本文件linker_script.ld的开始部分定义了SRAM_combinedstack_size,见如脚本:

MEMORY
{
    FLASH_1_cached(RX) : ORIGIN = 0x08000000, LENGTH = 0x80000
    FLASH_1_uncached(RX) : ORIGIN = 0x0C000000, LENGTH = 0x80000
    PSRAM_1(!RX) : ORIGIN = 0x1FFFC000, LENGTH = 0x4000
    DSRAM_1_system(!RX) : ORIGIN = 0x20000000, LENGTH = 0x8000
    DSRAM_2_comm(!RX) : ORIGIN = 0x20008000, LENGTH = 0x8000
    SRAM_combined(!RX) : ORIGIN = 0x1FFFC000, LENGTH = 0x14000
}

stack_size = DEFINED(stack_size) ? stack_size : 2048;

        故在标红处修改数值即可修改SP的栈顶和预置大小了。注意SRAM_combined还用于了其它存储区的分配,故修改SP的预置大小来修改栈顶比较妥当。

        当然我修改SP栈顶的目的是为了使用MPU硬件来设置栈溢出陷阱,保证程序的鲁棒性。作了如下修改:

  {
        __stack_start = .;
        . = . + stack_size;
        __stack_end = .;
        __initial_sp = . - 32;
    } > SRAM_combined

        将栈顶前移32个字节,使用MPU将这32个直接设为不可访问。

### XMC GPDMA Channel Transfer Documentation and Code Example The XMC General-Purpose Direct Memory Access (GPDMA) controller facilitates efficient data transfers between memory regions or peripherals without CPU intervention. For configuring a DMA channel transfer, the `XMC_GPDMA_CH_Transfer` function plays an essential role. A typical setup involves initializing the DMA module, configuring the specific channel parameters such as source address, destination address, block size, and enabling the channel to start the transfer process[^1]. Below is a simplified C code snippet demonstrating how one might configure and initiate a DMA transfer using the XMC library: ```c #include "xmc_gpdma.h" void dma_transfer_example(void) { /* Define DMA configuration structure */ XMC_DMA_CONFIG_t config; /* Initialize DMA with default settings */ XMC_DMA_Init(&config); /* Configure DMA channel specifics */ XMC_GPDMA_CH_CONFIG_t chConfig = { .src_addr = (uint32_t)&sourceBuffer, .dst_addr = (uint32_t)&destinationBuffer, .block_size = BUFFER_SIZE, .transfer_type = XMC_DMA_TRANSFER_TYPE_MEM_TO_PERIPH, .priority_level = XMC_DMA_PRIORITY_HIGH }; /* Setup DMA channel 0 with specified configurations */ XMC_GPDMA_CH_Setup(0U, &chConfig); /* Enable DMA channel 0 to begin transfer */ XMC_GPDMA_CH_Enable(0U); } ``` This example assumes that `sourceBuffer` contains data intended for transmission into `destinationBuffer`. The buffer sizes should match what's defined by `BUFFER_SIZE`, ensuring no overflow occurs during operation[^1].
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值