【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]