单片机GD32F303RCT6 (Macos环境)开发 (五)—— IAP代码架构工程

IAP代码架构工程

1、IAP一般分两个工程,一个Bootloader工程,一个Application工程。
这两个工程的差异后面会讲。
IAP架构工程的好处在于产品上线以后,想要升级的话,不用借助烧录器,就可以完成产品的软件升级。
2、Bootloader的跳转
一般bootloader工程从0x8000000处运行,跑到main函数以后,通过一个跳转函数,跳到Applicaiton的地址,运行Application程序。本实验Application烧录到0x8007000地址,所以在代码中直接 jump_app(0x08007000)。

typedef void (*jump_callback) (void);


uint8_t jump_app(uint32_t app_addr) 
{
    uint32_t jump_addr;
    jump_callback cb;

    if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000 ) == 0x20000000) 
    {  
        jump_addr = *(__IO uint32_t*) (app_addr + 4);  
        cb = (jump_callback)jump_addr;  
        __set_MSP(*(__IO uint32_t*)app_addr);  
        //__set_CONTROL(0);
        cb();
        return 1;
    } 
    return 0;
}

修改GD32F303RCTx_FLASH.ld,将Bootloader.bin大小限制在20K。

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 48K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 20k
}

3、Application工程。开始可以直接copyBootloader工程,然后再修改即可。
1⃣️、修改Application的GD32F303RCTx_FLASH.ld文件,将起始地址修改为0x8007000、大小修改为50K

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 48K
FLASH (rx)      : ORIGIN = 0x8007000, LENGTH = 50K
}

2⃣️、在main函数的最开始修改中断向量表。
这两句话是一样的

//设置中断向量表 	    
nvic_vector_table_set(NVIC_VECTTAB_FLASH,0x7000);
//SCB->VTOR = 0x08007000; //设置中断向量表

4、烧录的差异。

boot烧录命令:

pyocd flash --erase auto --target GD32F303RC  --base-address 0x8000000   ./Bootloader/build/Bootloader.bin

Application烧录命令:

pyocd flash --erase auto --target GD32F303RC  --base-address 0x8007000   ./Application/build/Application.bin

5、代码里可以使用make gdboot或者make gdapp烧录。
6、启动打印如下。先打印boot,在打印Application。
在这里插入图片描述
7、代码路径:https://gitee.com/xiaoguo-tec_0/gd32-iap-code.git

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GD32F303RCT6是一款基于ARM Cortex-M4内核的微控制器,适用于电磁循迹等应用。以下是一个简单的GD32F303RCT6电磁循迹代码的示例: ```c #include "gd32f30x.h" #define SENSOR_NUM 5 #define THRESHOLD 1000 uint16_t sensorValues[SENSOR_NUM]; void setup() { // 初始化IO口和ADC模块 rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_ADC0); gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4); adc_mode_config(ADC_MODE_FREE); adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, SENSOR_NUM); adc_inserted_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_239POINT5); adc_inserted_channel_config(ADC0, 1, ADC_CHANNEL_1, ADC_SAMPLETIME_239POINT5); adc_inserted_channel_config(ADC0, 2, ADC_CHANNEL_2, ADC_SAMPLETIME_239POINT5); adc_inserted_channel_config(ADC0, 3, ADC_CHANNEL_3, ADC_SAMPLETIME_239POINT5); adc_inserted_channel_config(ADC0, 4, ADC_CHANNEL_4, ADC_SAMPLETIME_239POINT5); adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, ADC0_1_EXTTRIG_INSERTED_NONE); adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE); adc_calibration_enable(ADC0); adc_enable(ADC0); } void loop() { // 读取传感器值 adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); while(!adc_flag_get(ADC0, ADC_FLAG_EOC)); for(int i = 0; i < SENSOR_NUM; i++) { sensorValues[i] = adc_inserted_data_get(ADC0, i); } // 判断循迹状态 int sum = 0; for(int i = 0; i < SENSOR_NUM; i++) { sum += sensorValues[i]; } if(sum > THRESHOLD) { // 循迹动作 // ... } else { // 停止动作 // ... } } int main(void) { setup(); while(1) { loop(); } } ``` 这段代码使用了GD32F303RCT6的ADC模块来读取电磁传感器的值,并根据阈值判断循迹状态。你可以根据具体的电磁传感器和循迹算法进行适当的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值