gscoolink:gsv2001的sdk移植

1 前言

  以gsv2001的sdk的应用代码为例,将gsv2001 sdk代码移植到stm32f1xx的hal库的sdk上;

  因为gsv2001的sdk也是使用stm32,也是使用hal库;所以移植起来改个头文件和iic gpio就行了;

  stm32和gd32都是cm核,cm核的代码可以直接pin2pin互相运行,需要注意一下地址访问不越界,堆栈和rtos的m核配置;

2 修改项目名

  很多项目在之前的项目基础上改改代码就行了,但是项目名和代码变量名都不匹配;

  所以呀,注释可以不写,但命名务必正确;

  所以呀,新的项目先不急着移植,先把项目代码框架的项目名和配置改好;

  首先修改xx.uvprojx的名字为project名;然后打开keil5工程;

  manage project items >> project targets >> 修改target名为project,移植就不用再命名了;

  options for target >> target >> 勾选microLIB,核对IROM和IRAM的size匹配;

  options for target >> output >> select folder for objects >> 选择output目录;

  options for target >> output >> name for execucutable >> 命名改为output.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/output.axf

    fromelf.exe --bin -o ./releaseFile/Test2_Z_SP12CS-V2_V1.0.0a_0691_08009000.bin   "#L"

  options for target >> c/c++ >> 勾选c99 mode,消除'declaration may not appear after executable statement in block.'

3 sdk source代码移植

  3.1 gsv2001_sdk_source目录复制到目标磁盘下

    看一下gsv2001_sdk的代码和代码磁盘目录;source目录是gsv运行需要的代码,project目录是mcu和keil运行需要的代码;

    确认要移植的代码是source目录下的代码,复制source目录到'dst_sdk'项目的磁盘下待移植;

  3.2 在keil工程中包含gsv2001_sdk_source目录的xx.c和xx.h的文件

    project目录下的xx.c文件在编译的时候分先后,所以要按原sdk工程的顺序包含;

    IncludePaths框内的头文件在包含的时候也分先后,所以也要按原sdk工程的顺序包含;

    如果不按原有目录的顺序包含,会打乱编译顺序,然后会报错很多undefined的问题;这里卡了一天;

  3.3 点击编译,根据error报错大概修改如下,要修改的并不多

    修改av_main.h和bsp.h的那几个#include "stm32f0xx.h" >> #include "stm32f1xx.h",

    修改iic的gpio为cm3核的gpio寄存器,

    sdk自带的key和uart通过宏不启用,这部分代码有的和cm0核相关注释起来地方挺多干脆不用,用已有的代码;

    这样的话sdk基本就可以编译通过了,编译通过之后在具体修改一些细节;

4 sdk source代码修改

  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的读写操作函数地址赋值,这样就可以用函数指针访问;作为一层封装;

    然后再用宏二次封装,用二次封装的宏进行调用;

    所以需要修改bsp回调代码的话,就直接修改一层封装的注册函数接口即可;

/** 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的打印函数重新映射printf;

    对于按键而言,注释掉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_list类型的指针变量ap,存储可变参数列表
va_start(ap, stringToFormat); //初始化ap,指向stringToFormat之后的第一个可变参数地址
vprintf(stringToFormat, ap); //使用vprintf直接打印字符串stringToFormat,以及它的可变参数列表指针ap
va_end(ap);
printf("\r\n");
#endif
return ret;
}
//vsprintf((char *)dtsbuff,pString,ap);
//vsprintf函数可以接受一个pString字符串指针,一个ap可变参数列表指针,然后把他们组合打印到dtsBuff数组中;

  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 小结

  问题想清楚之后执行就好了,行动才是生产力;

  这个东西移植起来事后复盘还是比较简单的,但是移植了好几天,因为还用了一半以上时间去确认有没有遗漏;

  今天移植6k7代码用了一天;因为没有把串口打印出来,没有及时调试导致早早就飞了野指针;

  写代码还是要及时调试;

  所以总结一下gsv2001的移植需要干嘛呢?

  首先按顺序包含一下xx.c和xx.h文件;然后修改头文件和iic gpio,然后把按键和串口回调注释掉并且重映射printf即可;

posted @   rls_v  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示