北方西门吹雪 发表于 2025-8-4 14:07

【APM32E030R Micro-EVB开发板评测】rtthread移植开发板BSP的步骤

#申请原创# 1 rtthread移植开发板BSP的步骤需要从以下四个步骤逐步完成。
这个过程大致相当于绣花的过程,需要不少耐心和改错的过程。

2 第一步,对比分析芯片的存储地址分布和底层数据参数
在下载官方的rtthead库之后,从现有的bsp中寻找最接近的芯片作为母版。经过对比APM32F030R8T6和本开发板的APM32E030R8T6最为接近

对比后大致内存一致,外设有一些数量上侧差别,主频有所提升,同时最重要的,都是M0架构。内存地址分布也要对比一下,比较幸运的是几乎一样。这样在后面的修改中能减少不少的工作量。


3 第二步,修改各级kconfig文件 ,这个是scons用来进行硬件和软件定义的文件。
这个是驱动中的kconfig

这个是工程中的kconfig


这个kconfig文件是可以通过menuconfig的UI界面启动并嵌入式分层修改的,不过,直接用文本编辑器修改效率更高。

4 第三步, 修改
sconstruct文件,这样注意是配置引用驱动的引入和定义不同kconfig下,如何配置驱动

典型的代码如下
Import('RTT_ROOT')
Import('rtconfig')
from building import *

cwd = GetCurrentDir()

# add the general drivers.
src = Split("""
""")

if GetDepend(['RT_USING_PIN']):
    src += ['drv_gpio.c']

if GetDepend(['RT_USING_SERIAL']):
    if GetDepend(['RT_USING_SERIAL_V2']):
      src += ['drv_usart_v2.c']
    else:
      src += ['drv_usart.c']

if GetDepend(['RT_USING_ADC']):
    src += ['drv_adc.c']

if GetDepend(['RT_USING_DAC']):
    src += ['drv_dac.c']

if GetDepend('BSP_USING_ONCHIP_RTC'):
    src += ['drv_rtc.c']

if GetDepend(['RT_USING_I2C']):
    if GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3') or GetDepend('BSP_USING_I2C4'):
      src += ['drv_soft_i2c.c']

if GetDepend(['RT_USING_SPI']):
    src += ['drv_spi.c']

if GetDepend(['RT_USING_HWTIMER']):
    src += ['drv_hwtimer.c']

if GetDepend(['RT_USING_PWM']):
    src += ['drv_pwm.c']

if GetDepend(['BSP_USING_WDT']):
    src += ['drv_wdt.c']

if GetDepend(['BSP_USING_ETH', 'RT_USING_LWIP']):
    src += ['drv_eth.c']

if GetDepend(['BSP_USING_SDIO']):
    src += ['drv_sdio.c']

if GetDepend(['RT_USING_CAN']):
    src += ['drv_can.c']

if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_APM32F0']):
    src += ['drv_flash/drv_flash_f0.c']

src += ['drv_common.c']

path =
path +=

if GetDepend('BSP_USING_ON_CHIP_FLASH'):
    path +=

group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)

Return('group')
以及引入link链接库的代码如下,这个就是第一步中所分析所用到的数据要进行修改
import os
import rtconfig
from building import *

Import('SDK_LIB')

cwd = GetCurrentDir()

# add general drivers
src = Split('''
board.c
''')

path =

startup_path_prefix = SDK_LIB

if rtconfig.PLATFORM in ['armcc', 'armclang']:
    src +=

if rtconfig.PLATFORM in ['iccarm']:
    src +=

if rtconfig.PLATFORM in ['gcc']:
    src +=

# APM32E030x6 || APM32E030x8 || APM32E030xC
# You can select chips from the list above
CPPDEFINES = ['APM32F030x8']
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
Return('group')
这个是启动startup的asm汇编代码所在

.syntax unified
.cpu cortex-m0plus
.fpu softvfp
.thumb

.global g_apm32_Vectors
.global Default_Handler

.word _start_address_init_data
.word _start_address_data
.word _end_address_data
.word _start_address_bss
.word _end_address_bss

.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function

// Reset handler routine
Reset_Handler:
// User Stack and Heap initialization
ldr   r0, =_end_stack
mov   sp, r0

ldr r0, =_start_address_data
ldr r1, =_end_address_data
ldr r2, =_start_address_init_data
movs r3, #0
b L_loop0_0

L_loop0:
ldr r4,
str r4,
adds r3, r3, #4

L_loop0_0:
adds r4, r0, r3
cmp r4, r1
bcc L_loop0

ldr r2, =_start_address_bss
ldr r4, =_end_address_bss
movs r3, #0
b L_loop1

L_loop2:
strr3,
adds r2, r2, #4

L_loop1:
cmp r2, r4
bcc L_loop2

blSystemInit
bl __libc_init_array
bl main

L_loop3:
    b L_loop3

.size Reset_Handler, .-Reset_Handler

// This is the code that gets called when the processor receives an unexpected interrupt.
    .section .text.Default_Handler,"ax",%progbits
Default_Handler:
L_Loop_infinite:
b L_Loop_infinite
.size Default_Handler, .-Default_Handler

// The minimal vector table for a Cortex M0 Plus.
   .section .apm32_isr_vector,"a",%progbits
.type g_apm32_Vectors, %object
.size g_apm32_Vectors, .-g_apm32_Vectors

// Vector Table Mapped to Address 0 at Reset
g_apm32_Vectors:
.word_end_stack
.wordReset_Handler                      // Reset Handler
.wordNMI_Handler                        // NMI Handler
.wordHardFault_Handler                  // Hard Fault Handler
.word0                                  // Reserved
.word0                                  // Reserved
.word0                                  // Reserved
.word0                                  // Reserved
.word0                                  // Reserved
.word0                                  // Reserved
.word0                                  // Reserved
.wordSVC_Handler                        // SVCall Handler
.word0                                  // Reserved
.word0                                  // Reserved
.wordPendSV_Handler                     // PendSV Handler
.wordSysTick_Handler                  // SysTick Handler

// External Interrupts
.wordWWDT_IRQHandler                  // Window Watchdog
.word0                                  // Reserved
.wordRTC_IRQHandler                     // RTC through EINT Line
.wordFLASH_IRQHandler                   // FLASH
.wordRCM_IRQHandler                     // RCM
.wordEINT0_1_IRQHandler               // EINT Line 0 and 1
.wordEINT2_3_IRQHandler               // EINT Line 2 and 3
.wordEINT4_15_IRQHandler                // EINT Line 4 to 15
.word0                                  // Reserved
.wordDMA1_CH1_IRQHandler                // DMA1 Channel 1
.wordDMA1_CH2_3_IRQHandler            // DMA1 Channel 2 and Channel 3
.wordDMA1_CH4_5_IRQHandler            // DMA1 Channel 4 and Channel 5
.wordADC1_IRQHandler                  // ADC1
.wordTMR1_BRK_UP_TRG_COM_IRQHandler   // TMR1 Break, Update, Trigger and Commutation
.wordTMR1_CC_IRQHandler               // TMR1 Capture Compare
.word0                                  // Reserved
.wordTMR3_IRQHandler                  // TMR3
.wordTMR6_IRQHandler                  // TMR6
.word0                                  // Reserved
.wordTMR14_IRQHandler                   // TMR14
.wordTMR15_IRQHandler                   // TMR15
.wordTMR16_IRQHandler                   // TMR16
.wordTMR17_IRQHandler                   // TMR17
.wordI2C1_IRQHandler                  // I2C1
.wordI2C2_IRQHandler                  // I2C2
.wordSPI1_IRQHandler                  // SPI1
.wordSPI2_IRQHandler                  // SPI2
.wordUSART1_IRQHandler                  // USART1
.wordUSART2_IRQHandler                  // USART2

// Default exception/interrupt handler

.weak      NMI_Handler
.thumb_set NMI_Handler,Default_Handler

.weak      HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler

.weak      SVC_Handler
.thumb_set SVC_Handler,Default_Handler

.weak      PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler

.weak      SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler

.weak      WWDT_IRQHandler
.thumb_set WWDT_IRQHandler,Default_Handler

.weak      RTC_IRQHandler
.thumb_set RTC_IRQHandler,Default_Handler

.weak      FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler

.weak      RCM_IRQHandler
.thumb_set RCM_IRQHandler,Default_Handler

.weak      EINT0_1_IRQHandler
.thumb_set EINT0_1_IRQHandler,Default_Handler

.weak      EINT2_3_IRQHandler
.thumb_set EINT2_3_IRQHandler,Default_Handler

.weak      EINT4_15_IRQHandler
.thumb_set EINT4_15_IRQHandler,Default_Handler

.weak      DMA1_CH1_IRQHandler
.thumb_set DMA1_CH1_IRQHandler,Default_Handler

.weak      DMA1_CH2_3_IRQHandler
.thumb_set DMA1_CH2_3_IRQHandler,Default_Handler

.weak      DMA1_CH4_5_IRQHandler
.thumb_set DMA1_CH4_5_IRQHandler,Default_Handler

.weak      ADC1_IRQHandler
.thumb_set ADC1_IRQHandler,Default_Handler

.weak      TMR1_BRK_UP_TRG_COM_IRQHandler
.thumb_set TMR1_BRK_UP_TRG_COM_IRQHandler,Default_Handler

.weak      TMR1_CC_IRQHandler
.thumb_set TMR1_CC_IRQHandler,Default_Handler

.weak      TMR3_IRQHandler
.thumb_set TMR3_IRQHandler,Default_Handler

.weak      TMR6_IRQHandler
.thumb_set TMR6_IRQHandler,Default_Handler

.weak      TMR14_IRQHandler
.thumb_set TMR14_IRQHandler,Default_Handler

.weak      TMR15_IRQHandler
.thumb_set TMR15_IRQHandler,Default_Handler

.weak      TMR16_IRQHandler
.thumb_set TMR16_IRQHandler,Default_Handler

.weak      TMR17_IRQHandler
.thumb_set TMR17_IRQHandler,Default_Handler

.weak      I2C1_IRQHandler
.thumb_set I2C1_IRQHandler,Default_Handler

.weak      I2C2_IRQHandler
.thumb_set I2C2_IRQHandler,Default_Handler

.weak      SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler

.weak      SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler

.weak      USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler

.weak      USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
5 到此,基本代码和结构调试完整,在虚拟环境中输入scons进行工程构建,应该可以如下,形成二进制文件

最后,也就是第四步,进行调试器下载的配置。这个和keil一样需要选择安装包的配置,首先查看以下是否支持芯片
使用pyord pack list命令

可以看到,本次评测的APM32E030并不在支持的范围内。那么需要安装一下
pyocd pack install

这里显示是安装成功了,但是反复多次,发现并没有安装成功。对照官网的docs介绍,发现新的安装方法已经升级,本地安装不包括在本命令中。
但是可以在每次下载中,都用引用的方式,加载这个安装包,同样可以完成下载的任务。

这个使用的是
pyocd flash xxxx.bin文件的方式。
6 小结
这个过程花费了很长的时间,也在代码库中需要增加很多配置和调试的工作。而且,对应于rtthread的驱动代码,都需要有比较大的修订。因此,具体的步骤就不能容纳在这个帖子中了,但是经过上述4个步骤,可以完成bsp代码构建,为后续更多外部驱动的构建创造比较好的基础。





页: [1]
查看完整版本: 【APM32E030R Micro-EVB开发板评测】rtthread移植开发板BSP的步骤