1 前言
以gsv的sdk的应用代码为例,将应用代码从m0核移植到m1核的mcu上;
因为用的是hal库,所以互相移植修改的并不多;实际改个头文件就可以编译了;
虽然我hal库用的是m1核的hal库,但是实际上我直接啥也没改,跑在m4核的gdf303上也没啥问题;
2 修改项目名
修改.uprojx的名字,为project名;
manage project items >> project targets >> 修改target名;
options for target >> output >> select folder for objects >> 选择output目录;
options for target >> output >> name for execucutable >> xx.axf改成项目名;
options for target >> listing >> select folder for listing >> 选择listing目录,和output目录一起省的多个文件;
options for target >>user >> run >>
fromelf.exe --bin -o ./releaseFile/Test1_Z_SP12CS-V2_V1.0.0a_0691_08009000.bin ./outputFile/SP12.axf
fromelf.exe --bin -o ./releaseFile/Test2_Z_SP12CS-V2_V1.0.0a_0691_08009000.bin "#L"
3 源码包含
3.1 包含xx.c和xx.h的文件;
project目录下的xx.c文件在编译的时候分先后,所以要按顺序包含;
IncludePaths框内的头文件在包含的时候也分先后,所以要按顺序包含;
如果不按原有目录的顺序包含,会打乱编译顺序,然后会报错很多undefined的问题;这里卡了一天;
3.2 包含gsvSDK的文件
m0,m3,m4核的架构差别不大,加上sdk代码相当于应用层代码,和mcu的hal库以及cm核耦合性并不高;
把那几个#include "stm32f0xx.h" >> #include "stm32f1xx.h",还有代码中的一些GPIO寄存器设置注释掉;
这样的话sdk基本就可以编译通过了,先编译通过先,后面再具体修改;
4 gsvSDK修改
gsv的sdk将音视频的应用代码和bsp板间外设进行了分离,代码移植到不同板子上时只需要修改对应bsp,方便移植;
gsv给用户封装了两个接口用来作为bsp的回调注册,那么这两个函数都是如何工作的呢?如果要移植我们都需要改啥呢?
/* 1.2 init software package and hookup user's bsp functions */
AvApiInit();
AvApiHookBspFunctions(&BspI2cRead, &BspI2cWrite, &BspUartSendByte,&BspUartGetByte, &BspGetMilliSecond, &BspGetKey, &BspIrdaGetByte);
AvApiHookUserFunctions(&ListenToKeyCommand, &ListenToUartCommand, &ListenToIrdaCommand);
4.1 AvApiHookBspFunctions函数
/** bsp 函数指针定义 ***************************************************************************/
//hal.h hardware access functions; cae:I would like to store definitions into uapi.h
typedef AvRet (*AvFpI2cRead)(uint32, uint32, uint8 *, uint16);
typedef AvRet (*AvFpI2cWrite)(uint32, uint32, uint8 *, uint16);
typedef AvRet (*AvFpUartSendByte)(uint8 *, uint16);
typedef AvRet (*AvFpUartGetByte)(uint8 *);
typedef AvRet (*AvFpGetMilliSecond)(uint32 *);
typedef AvRet (*AvFpGetKey)(uint8 *);
typedef AvRet (*AvFpGetIrda)(uint8 *);
//uapi.c hal functions variables
AvFpI2cRead AvHookI2cRead;
AvFpI2cWrite AvHookI2cWrite;
AvFpUartSendByte AvHookUartTxByte;
AvFpUartGetByte AvHookUartRxByte;
AvFpGetMilliSecond AvHookGetMilliSecond;
AvFpGetKey AvHookGetKey;
AvFpGetIrda AvHookGetIrda;
//uapi.h 下面的kapi.h就没有用extern;这个gsv的代码对称性不好;
extern AvFpI2cRead AvHookI2cRead;
extern AvFpI2cWrite AvHookI2cWrite;
extern AvFpUartSendByte AvHookUartTxByte;
extern AvFpUartGetByte AvHookUartRxByte;
extern AvFpGetMilliSecond AvHookGetMilliSecond;
extern AvFpGetKey AvHookGetKey;
extern AvFpGetIrda AvHookGetIrda;
/**av_main.c >> bsp 函数指针注册 *****************************************************************/
//uapi.c @brief hookup user's hardware access functions
uapi AvRet AvUapiHookBspFunctions(pin AvFpI2cRead i2cRd, pin AvFpI2cWrite i2cWr, pin AvFpUartSendByte uartTxB, pin AvFpUartGetByte uartRxB, pin AvFpGetMilliSecond getMs, pin AvFpGetKey getKey,pin AvFpGetIrda getIrda)
{
AvRet ret = AvOk;
AvHookI2cRead = i2cRd;
AvHookI2cWrite = i2cWr;
AvHookUartTxByte = uartTxB;
AvHookUartRxByte = uartRxB;
AvHookGetMilliSecond = getMs;
AvHookGetKey = getKey;
AvHookGetIrda = getIrda;
AvUapiOutputDebugMessage(" ");
AvUapiOutputDebugMessage("-------------------------------------------------------------------");
AvUapiOutputDebugMessage(" |> Audio/Video Software %s", AvVersion);
AvUapiOutputDebugMessage("-------------------------------------------------------------------");
return ret;
}
//av_main.c
AvApiHookBspFunctions(&BspI2cRead, &BspI2cWrite, &BspUartSendByte,&BspUartGetByte, &BspGetMilliSecond, &BspGetKey, &BspIrdaGetByte);
/** bsp 函数指针回调******************************************************************************/
//hal.h
#define AvI2cRead AvHookI2cRead
#define AvI2cWrite AvHookI2cWrite
#define AvUartTxByte AvHookUartTxByte
#define AvUartRxByte AvHookUartRxByte
#define AvGetMilliSecond AvHookGetMilliSecond
#define AvGetKey AvHookGetKey
#define AvIrdaRxByte AvHookGetIrda
//hal.c 以重新封装的Avxx宏去调用,这样就实现了bsp隔离;
AvRet AvHalI2cRead(pin uint32 devAddress, pin uint32 regAddress, pout uint8 *avdata, pin uint16 count)
{
AvRet ret = AvOk;
ret = AvI2cRead(devAddress, regAddress, avdata, count);
return ret;
}
//把 &BspI2cRead 封装成 AvHookI2cRead,然后又封装成AvI2cRead; 双重封印;
//如果是我我只会封一层,这玩意干嘛要封两层?
4.2 AvApiHookUserFunctions函数
/**kapi.h userFunction 函数指针定义 *****************************************************************/
typedef void (*AvFpKeyCommand) (AvPort *port);
typedef void (*AvFpUartCommand) (AvPort *port);
typedef void (*AvFpIrdaCommand) (AvPort *port);
//kapi.c
AvFpKeyCommand AvHookKeyCmd;
AvFpUartCommand AvHookUartCmd;
AvFpIrdaCommand AvHookIrdaCmd;
/**kapi.h userFunction 函数指针注册 *****************************************************************/
//kapi.c @brief hookup user layer access functions
kapi AvRet AvKapiHookUserFunctions(pin AvFpKeyCommand keyCmd, pin AvFpUartCommand uartCmd,pin AvFpIrdaCommand IrdaCmd)
{
AvRet ret = AvOk;
AvHookKeyCmd = keyCmd;
AvHookUartCmd = uartCmd;
AvHookIrdaCmd = IrdaCmd;
return ret;
}
//av_main.c
AvApiHookUserFunctions(&ListenToKeyCommand, &ListenToUartCommand, &ListenToIrdaCommand);
/**kapi.h userFunction 函数指针回调 *****************************************************************/
//kapi.h
#define AvUserUartCmd AvHookUartCmd
#define AvUserKeyCmd AvHookKeyCmd
#define AvUserIrdaCmd AvHookIrdaCmd
//kapi.c
while(TempPort){
/* Make Key Response and Uart Response faster */
AvUserUartCmd(FirstPort);
AvUserKeyCmd(FirstPort);
AvUserIrdaCmd(FirstPort);
//...
}
4.3 bsp修改
对于iic而言,软件模拟的,可以直接用gsv写的;只要改一下GPIO寄存器操作; 参考修改GPIO的IIC的CRH或CRL寄存器
对于uart而言,注释掉gsv的bsp回调函数,使用已有的uartBsp回调;
对于按键而言,注释掉gsv的bsp回调函数;
//kapi.h 下面的监听回调是封装在kapi.h中的;而bsp的调用宏是封装在hal.h中;
#define AvUserUartCmd //AvHookUartCmd
#define AvUserKeyCmd //AvHookKeyCmd
#define AvUserIrdaCmd //AvHookIrdaCmd
//i2c.c
#define SET_SCL0_1 GPIOB->BSRR = GPIO_PIN_13 // Pin I2C_SCL
#define SET_SDA0_1 GPIOB->BSRR = GPIO_PIN_14 // Pin I2C_SDA
#define SET_SCL0_0 GPIOB->BSRR = GPIO_PIN_13<<16U // Pin I2C_SCL
#define SET_SDA0_0 GPIOB->BSRR = GPIO_PIN_14<<16U // Pin I2C_SDA
#define GET_SDA0 ((GPIOB->IDR & GPIO_PIN_14)? 1:0) // Pin I2C_SDA
#define SCL0_IN GPIOB->CRH = ( ((GPIOB->CRH)&0xff0fffff)|0x00400000 )
#define SCL0_OUT GPIOB->CRH = ( ((GPIOB->CRH)&0xff0fffff)|0x00700000 )
#define SDA0_IN GPIOB->CRH = ( ((GPIOB->CRH)&0xf0ffffff)|0x04000000 )
#define SDA0_OUT GPIOB->CRH = ( ((GPIOB->CRH)&0xf0ffffff)|0x07000000 )
4.4 printf修改
//uapi.c 本来的打印函数使用gsv的bsp的uart,改一下用printf;这样关个宏就可以了,不用改bsp;
uapi AvRet AvUapiOuputDbgMsg(pin schar *stringToFormat, ...){
AvRet ret = AvOk;
#if AvEnableDebugFsm
va_list ap;
va_start(ap, stringToFormat);
vprintf(stringToFormat, ap); // 使用vprintf直接打印格式化字符串
va_end(ap);
printf("\r\n");
#endif
return ret;
}
4.5 gsvMain
函数改成case语句,然后搞个while(1)或者task来调用即可;这样就移植完成了;
void gsv2k1_Main(void){
static uint8_t state = 0;
switch(state){
case 0:
CAE("gsv2k1_Main() ");
GsvMain();
state++;
break;
case 1:
AvApiUpdate();
AvPortConnectUpdate(&devices[0]);
break;
}
}
5 小结
问题想清楚之后执行就好了,行动才是生产力;
这个东西移植起来事后复盘还是比较简单的,但是移植了好几天,因为还用了一半以上时间去确认有没有遗漏;
标签:pin,bsp,GPIOB,AvRet,sdk,gsv2001,kapi,gscoolink,define From: https://www.cnblogs.com/caesura-k/p/18222492