惯性导航程序(OpenShoe)移植
任务:惯性导航程序从avr32(开发工具AtmelStudio6)移植到stm32f4xx(开发工具keil5_11)。
分析:将程序移植到不同微控制器,将源程序分成硬件相关和硬件不相关(算法、控制方式等)两部分。
以惯性导航源码为例:
1. 惯性导航硬件不相关代码移植
Step1:将去掉微控制器相关驱动后的惯性导航源码加入到keil5工程序中,从main函数中开始,然后注示掉硬件相关的函数。
Step2: 惯性导航源码中使用了inline等C++关键字(开c99)和开硬件浮点单元(FPU),在keil5开发工具中配制如下:
所有inline函数前加static,因为keil5开发工具必须这样做。
Step3: 编译,根据出错信息来解决错误;比如:
1) #define M_PI 3.14159265358979323846
//atmelStudio6中math.h中有,但在keil5 math.h中无,所以要自己添加
2) #define Bool bool //++
3) #define max(a,b) ((a)>(b)? (a):(b)) //++
4) #include <stdbool.h>
等等.....
Step4: avr32是大端地址,而stm32f4xx小端地址,上位机要修改,而源码中修改的部分如下:
小端地址:
#define MSB(u16) (((uint8_t *)&(u16))[1]) //!< Most significant byte of \a u16.
#define LSB(u16) (((uint8_t *)&(u16))[0]) //!< Least significant byte of \a u16.
大端地址:
#define MSB(u16) (((uint8_t *)&(u16))[0]) //!< Most significant byte of \a u16.
#define LSB(u16) (((uint8_t *)&(u16))[1]) //!< Least significant byte of \a u16.
2. 惯性导航硬件相关代码移植
通过分析惯性导航源码,可以知道使用的硬件相关配制:
- 系统时钟初始化;
- 定时器中断;
- 串口通信,接收数据和发送数据都使用了中断方式,但可以考虑接收采用中断;
- 获取程序运行时间dt, dt用于惯性导航算法的参数(avr32 使用32位递增计时器)。
- 模拟I2C
Step1: 新建工程,实现a~c(1~3)功能,并测试。
Step2:d功能,采用stm32中systick,systick在Cortex M4内核编程手册中有说明;systick是24位递减计时器,不占用CPU。
修改inertial_frontend.c文件中代码,深黑色为修改后的:
frontend_postproc函数中:
未修改:
dt_k = ((precision)(t_int_k - t_int_km1))*TIME_SCALE;
t_int_km1 = t_int_k;
修改后:
if (t_int_km1 < t_int_k)
dt_k = ((precision)(0x00ffffff - t_int_k + t_int_km1))*TIME_SCALE;
else
dt_k = ((precision)(t_int_km1 - t_int_k))*TIME_SCALE;
t_int_km1 = t_int_k;
修改i2c.c中代码:(深黑色为修改后)
未修改前:
inline static void half_tick(void){
int32_t wait_to = last_tick + 2*QUATER_CC_COUNT;
while (Get_system_register(AVR32_COUNT) - wait_to < 0);
last_tick = Get_system_register(AVR32_COUNT);
}
inline static void quater_tick(void){ //++
int32_t wait_to = last_tick + QUATER_CC_COUNT;
while (Get_system_register(AVR32_COUNT) - wait_to < 0);
last_tick = Get_system_register(AVR32_COUNT);
}
修改后:
int32_t temp;
inline static void half_tick(void){
int32_t wait_to = last_tick - 2*QUATER_CC_COUNT;
if (wait_to & 0x80000000) wait_to = -wait_to;
do{
temp = Get_system_register();
}while (temp - wait_to > 0 && temp < last_tick);
last_tick = Get_system_register();
}
inline static void quater_tick(void){
int32_t wait_to = last_tick - QUATER_CC_COUNT;
if (wait_to & 0x80000000) wait_to = -wait_to;
do{
temp = Get_system_register();
}while (temp - wait_to > 0 && temp < last_tick);
last_tick = Get_system_register();
}
Step3:使用stm32f4xx模拟I2C,或者将惯性导航中的模拟I2C移植过来。