CDK芯片SDK制作例程

背景

SmartL平台的基本资料在OCC的SmartL平台链接中。

本文使用的SDK的源代码,是基于SmartL平台的旧版本的非组件化的SDK工程,源代码也OCC的E802SDK链接中。

目标

本文通过SmartL平台SDK的制作过程,展示CDK中制作一个SDK的通用做法,为其他SDK制作人员提供一些使用引导。

第一章节描述了如何通过CDK创建一个初始的方案,并且新建基于自身平台的相关组件。

第二章节描述了对于一些需要Flash烧写的平台,如何创建一个Flash算法文件,从而达到使用CDK进行Flash烧写、调试的目标。

第三章节描述了如何将之前创建的初始方案进一步修改,实现真正平台SDK的目标。

第四章节描述了如何将制作完成的SDK发布给其他开发者使用。

第五章节是Q&A

1 创建初始组件化SDK工程

1.1 新建工程结构简介

菜单栏Project->New SOC Project窗口提供创建一个初始组件化的SDK工程的入口。

在打开的窗口中输入需要的SDK工程名称,Project Type类型选择Solution Package,Package Path设置正确的路径,该路径用来保存工程使用到的组件。

配置完成以后,点击OK,即完成了一个初始的组件化的SDK工程。

整个视图,包含三个部分:

  1. my_solution工程节点,包含main文件,以及可以配置的调试初始化脚本和Flash初始化脚本。
  2. _SDK_CK802名称的sdk类型的组件,该组件依赖了一个chip组件。该组件的保存路径是之前新建工程时,配置的Package Path指定的路径。
  3. _Chip_CK802名称的chip类型的组件,该组件包含了CPU的初始化启动代码,以及链接脚本文件。该组件的保存路径是之前新建工程时,配置的Package Path指定的路径。

至此,完成了一个初始的SDK工程。

1.2 新建平台相关的组件

这里的芯片和SDK组件都是CDK默认的组件,这里需要创建自己的组件。可以根据当前组件,创建自己平台的组件。

右击mysolution工程节点,弹出菜单中选择Create a new SDK,弹出窗口填写需要的SDK名称,以及使用\_SDK_CK802的组件创建自己的新组件。

点击OK,完成SDK组件创建,然后右击工程视图的SDK组件,选择Create a new package选项,然后弹出的窗口中,填写新建的芯片组件名,SmartLChip,并选择\_SDK_CK802作为基础组件去创建。

1.3 修改链接脚本文件,与平台存储空间相符

根据SmartL平台手册,将默认的LD文件的存储区域修改为与SmartL平台一致的区间。

CDK默认的LD配置了图形文本修改的方式,如果平台存储区域与默认配置不能匹配(例如超过两段Flash或RAM),那么此时需要根据GCC官方的语法要求,完成对应LD文件的配置。需要注意的地方在于,默认LD文件中的以下符号,不要去随意改动:

符号名 功能/作用
__s_ram_data_1 定义了程序数据区的起始位置
__e_rom 定义了程序只读数据区以后,4对其的位置
__e_ram_data_1 定义了程序数据区的结束位置
__e_ram_bss_1 定义了程序的BSS区域的结束位置
__s_ram_bss_1 定义了程序的BSS区域的开始位置

这些符号,在组件SmartL_Chip中的src/ck802.c文件中使用到。

2 制作SDK工程算法文件

CDK支持Flash烧写功能,为了能够适配不同的Flash器件的编程逻辑,CDK允许开发人员通过Flash算法文件的适配,实现Flash器件的编程,从而实现对某个芯片平台的Flash烧写。

2.1 配置算法初始信息

要在CDK中制作一个特定芯片的方案,需要通过New SOC Project创建一个Flash类型的CDK工程。

此时Project Type选为Flash,并在RAM1中填写SmartL的RAM区域。CPU和对应SDK的CPU要完全一致。

完成工程创建以后,工程视图显示内容如下:

FlashDev.c文件用来对算法基本信息进行描述。

//structure to describe flash device
struct FlashDevice const FlashDevices  INDEVSECTION =  {
    6,                      // Reserved version description, do not modify!!!
    "SmartL_Flash",              // Flash name
    "ck802",              // CPU name, must in low case
    0x123456,               // Flash ID
    "NorFlash",             // type
    512*1024,               // Reserved
    1,                      // Access directly
    1,                      // RangeNumbers
    // {start address, the flash size, sector size}
    {{0x0, 0x80000, 0x200}}
};

将默认的内容修改为SmartL硬件信息相匹配即可。

2.2 实现算法接口

Driver.c文件用来实现算法逻辑,针对具体的硬件信息,实现对应的接口。

接口定义 功能说明
int flashInit() @brief Flash编程初始化接口,运行Flash程序,开始编程之前会执行该接口; @return 返回0表示成功,否则失败;
int flashUnInit() @brief Flash编程结束接口,CDK在Flash操作结束之后,会默认执行此接口; @return 返回0表示成功,否则失败;
int flashID(unsigned int* flashID) @brief 获取Flash ID接口; @param flashID 返回flash ID; @return 返回0表示成功,否则失败;
int flashProgram(char dst, char src, int length) @brief Flash烧写接口; @param dst 烧写目标地址; @param src 烧写源数据地址; @param length 烧写源数据长度; @return 返回0表示成功,否则失败;
int flashRead(char dst, char src, int length) @brief Flash数据读取接口;当该Flash不是直接可读的Flash属性时,CDK会调用该接口读取数据; @param dst 读取目标地址; @param src 数据保存地址; @param length 读取数据长度; @return 返回0表示成功,否则失败;
int flashErase(char* dst, int length) @brief Flash擦除接口;用于擦除指定空间的数据; @param dst 待擦除目标地址;该地址始终是后续FlashDev.c文件中描述的PageSize对齐的地址; @param length 待擦除数据长度;该长度始终是后续FlashDev.c文件中描述的PageSize的倍数; @return 返回0表示成功,否则失败;
int flashChipErase() @brief Flash整片擦除接口; @return 返回0表示成功,否则失败;
int flashChecksum(char*dst, int length, int checksum) @brief Flash快速校验接口; @param dst 待校验目标地址; @param length待校验数据长度; @param checksum烧写镜像中的checksum值

2.3 调试算法逻辑

main.c文件是算法工程的主控逻辑,main函数完成此功能。

int main(){    
  // call nor flash drivers to program
    g_error = flashInit();
    // for debug flash driver
    flashTest();
    do {
        __bkpt_label();
        switch (g_func) {
        case 0:
            g_error = flashID(&g_flashID);
            break;
        case 1:
            g_error = flashProgram((char *) g_dstAddress, (char *) g_rwBuffer,
                    g_length);
            break;
        case 2:
            g_error = flashRead((char *) g_rwBuffer, (char *) g_dstAddress,
                    g_length);
            break;
        case 3:
            g_error = flashErase((char *) g_dstAddress, g_length);
            break;
        case 4:
            g_error = flashChipErase();
            break;
        case 5:
            g_error = flashUnInit();
            break;
        case 6:
            g_error = flashChecksum((char*)g_dstAddress, g_length, g_checksum);
            break;
        default:
            break;
        }
    } while (1)
}

CDK通过下载次算法工程到芯片RAM的g_rwBuffer[]数组中,然后通过控制g_func,g_dstAddress,g_length,g_checksum这些全局变量,实现对特定Flash器件的编程功能。这里需要调试算法文件,就是模拟整个烧写的过程,将每个函数调试通过即可。

为了能够更方便的调试算法文件,右击算法工程,在Compiler配置中,修改Optimization修改为 -O0 ,然后再次编译算法工程。

双击工程视图的算法工程节点,设置为active project,然后点击调试按钮,启动调试,运行到main函数以后,全速运行,发现算法文件停止在__bkpt_label函数处。

然后,我们这里根据调试需求,设置相应的全局变量,进行验证。

例如,这里我们调试flashProgram接口的正确性,首先在CDK Watch界面将g_func设置为1,g_dstAddress设置为要进行编程的Flash区域的地址,g_length设置为要烧写的数据长度,g_rwBuffer设置为具体的烧写数据内容,一般来说,对于调试,g_length数据量不需要太长。

这里我们设置向Flash区域0x0---0x8区域烧写0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8特征数据,来验证算法文件的正确性。CDK中设置好这些变量以后,把PC的值设置为当前lr(r15)的值,然后点击单步运行,

点击单步运行,程序运行在main.c文件的flashProgram入口,然后通过常规的调试手段,进入该函数内部,运行函数完成以后,验证是否正确烧写。

按照上诉手段,分别验证每个函数的正确性即可。

2.4 配置算法文件到SDK工程

当完成整个算法文件调试以后,为了更好的提升算法文件的性能,这里我们将算法工程的Compiler编译选项由 -O0 修改为 -O2,然后重新编译,编译完成以后,将SmartL_Flash工程根路径下Obj/目录中生成的SmartL_Flash.elf算法文件copy到my_solution工程使用的SmartL_Chip组件的目录中去,CDK工程视图右击菜单Open Containing Folder选项,可以直接打开工程、组件所在的目录。

然后在工程视图SmartL_Chip组件节点的配置窗口中,配置SmartL_Flash.elf作为算法文件。

【情况2】

对于没有使用芯片组件或者使用旧版本的组件的情况,则需要将SmartL_Flash.elf拷贝到my_solution工程根路径下(与my_solution.ckdproj文件同目录),然后在工程配置的Flash Tab的算法选择中,选择该组件即可。

3 修改初始SDK工程

根据第一章节的内容,my_solution目前是根据初始组件化工程而来,这里需要根据SmartL平台的内容,对当前SDK工程进行必要的更新和修改。

3.1 新增一个开发板组件

在SmartL_SDK节点下新增一个SmartL_Board的开发板组件。

然后右击工程视图的SmartL_Board节点,点击Add Source Folder选项,选中已经存在的代码目录,点击OK,此时将开发板组件的代码完全导入到新建的组件中了。

右击开发板组件SmartL_Board,在配置选项中,完成组件的编译配置:

  1. 在Compiler选项Global Config中,配置开发板组件需要提供给外部的头文件搜索路径;然后配置Debug. Level也要配置包含调试信息的选项。

  1. 在Linker选项卡中配置使用的链接描述文件。

【备注】关于链接描述文件,solution、board、chip类型的组件的配置窗口的Linker选项卡中都可以配置,CDK会按照solution > board > chip的优先级,选择合适的链接文件使用。

在本例中,CDK会使用board组件配置的gcc_csky.ld文件作为链接描述文件。

3.2 更新当前的芯片组件

芯片组件的更新,主要包含芯片外设驱动的代码的编写,如果没有现成代码,需要逐个添加,编写代码,如果存在驱动代码,可以右击SmartL_Chip组件节点,选择Add Source Folder,将芯片组件需要包含的内容添加到芯片组件中。

本例中,将SmartL_Chip组件使用的csi_core接口和驱动代码,通过Add Source Folder的方式添加到芯片组件中。

完成源代码的添加以后,需要将使用的头文件路径配置到芯片组件配置对话框中的Compiler选项卡中。

由于我们添加的芯片组件代码中,包含了CPU的初始化和启动逻辑,所以,我们把之前SmartL_Chip组件包含的默认提供的芯片初始化的代码逻辑删除。

SmartL的SDK的硬件部分已经完成。

3.3 增加两个硬件无关的common组件

此外,我们还有两个代码模块需要添加,一个是RTOS的kernel部分,另外一个是一些工具函数。两部分的添加逻辑类似,这里介绍RTOS的kernel的添加。

右击my_solution工程节点,选择Create a Common Package选项,选择Clone from为\,然后输入组件名称,点击OK

完成创建以后,工程视图会出现Packages节点,该节点表示直接被solution工程依赖的组件。该节点下面包含了刚刚创建出来的组件。

然后右击该节点,选择Add Source Folder,将需要添加的代码加入到组件中。然后在组件配置中的Compiler Tab中配置需要提供的全局头文件搜索路径。

至此,工程依赖的组件的添加和修改工作完成。

3.4 更新当前solution工程

对于工程本身,也是一个solution类型的组件,这里我们添加一些solution组件需要的代码,由于这些代码包含了main函数,所以,我们需要将工程默认的main函数所在的文件删除。

右击工程,通过New Folder创建新的目录,通过Add an Existing File添加已经存在的某个源文件。

然后根据solution具体的编译需要,在工程节点的配置窗口中,对Compiler、Linker等选项卡中的内容进行配置。

【备注】如果想要了解这些选项卡中的每个字段的节点的含义,在界面显示该节点时,点击Help按钮,就会直接显示配置含义。

至此,完成了主要代码的编写和工程编译的配置工作。

3.5 调试和Flash配置

调试相关配置,SmartL包含了Flash区间的调试,需要将工程配置窗口Debug选项卡中的ICE Settings子窗口中的Download to Flash勾选。

这样,工程就可以在Flash区间进行调试了。

对于Flash的配置,需要在工程配置窗口的Flash选项卡中进行配置,其中Options for Target Deriver区域需要配置Flash烧写的操作。

这里SmartL使用Erase Sectors的擦除方式,并在烧写完成进行Verify验证。

4 发布SDK工程

完成SmartL SDK制作以后,需要将该工程发布给开发者使用,这里有两种发布方式:离线发布和在线发布。

4.1 离线发布SDK工程

工程clean完成以后,打开工程所在目录,关闭CDK,然后将工程目录以及章节一中创建的Package Path设置的目录,共同打包。

打包需要注意,在打包的目录结构中,工程目录与Package Path目录的相对路径关系,应该与SDK制作的时候保持一致。例如,当前例子中,SmartL工程在桌面的project/my_solution/目录下,而使用的Package Path目录是桌面的project/my_pack_pool/目录,那么发布的时候,将桌面project/my_solution/目录和桌面project/my_pack_pool/目录共同拷贝到同一个目录SmartLSDK目录下,然后压缩该目录作为一个SDK即可。

4.2 在线发布SDK工程

CDK自动对接了芯片开放社区(Open Chip Community)网络平台(以下简称OCC),能够帮助开发者将自己开发完成的SDK,上传到OCC中,并选择对外发布与否。

以SmartL为例,需要把当前平台使用的组件逐个发布到OCC平台中。

首先需要在OCC平台申请一个账号,并申请企业入驻资质,然后在CDK中打开welcome页面。

然后点击"账号登录",在CDK中登录OCC账号。

选择"我的发布",进入发布页面。

组件的发布中,需要先提交被依赖的组件,然后才能提交依赖的组件,以本工程为例,提交组件的顺序为:

首先是:csi_kernel、utils、SmartL_Board、SmartL_Chip,提交完成以后,才可以提交SmartL_SDK,当这些组件全部提交完成,最后提交工程my_solution

【备注】

1 除了welcome页面可以提供上传组件的入口,每个组件节点右击菜单栏中,Upload for xxx 也可以上传该组件。

2 目前OCC账号管理中,对于上传方案 、开发板、芯片类型的组件,要求该账号必须为企业账号资质。

4.2.1 在线发布验证

当完成这些组件的上传以后,需要验证是否正确上传,在welcome页面的首页中,"新建工程"入口,会有上传成功的方案工程。

选择该工程,点击"创建工程",然后输入工程名,并选择对应的版本号,完成工程的创建,创建完成以后,在CDK中该工程应该是可以正确编译和运行的。

5 常见问题以及解答

  1. 问题:Package Path是否可以设置多个?

    回答:可以。在New SOC Project对话框中,Package Path只允许设置一个,工程设置完成以后,可以在工程节点右击,选择Packages path setting,就可以设置多个Package Path,并且可以设置每个Package Path的优先级,CDK根据优先级去查找、使用组件。

  2. 问题:为何工程视图有代码文件,但是CDK没有编译该文件?

    回答:确认该文件是否正确添加到CDK的编译规则中。目前,CDK识别组件源文件的编译与否,是在组件对应的package.yaml文件中的source_file节点,正常情况下,CDK不建议用户去手动修改该yaml文件,用户通过工程视图,Add Source Folder,Add an Existing File,Add a new File等操作中,CDK会自动更新该节点。如果遇到问题中提及的情况,可以直接检查一下该文件是否在yaml文件的source_file节点中,如果没有,可以根据yaml语法规则,手动添加进去,然后重新打开CDK即可。

  3. 问题:Flash下载需要下载的内容不仅仅是工程elf文件本身,怎么将额外的内容下载到目标中?

    回答:工程配置的Debug、Flash选项卡中,包含了Init File的配置:

​ 该文件会在烧写工程elf文件之前被执行,文件规则可以参考用户文档,即上图中点击Help即可查看。

​ 该脚本download命令支持Flash的区域的烧写,支持的文件类型有elf、hex和bin三种:

【elf格式和hex格式】

​ download \ [verify=yes/no] \

 <format\>:格式说明,根据下载的文件类型,这里填写elf或者ihex

​ [verify=yes/no]:选择是否对download的文件进行verify操作;可选,如果不写,则默认使用工程配置中的Flash配置中的Verify选项的 值;

 <filename\>:文件名称,支持\$(ProjectPath)表示工程根路径。

​ 【bin格式】

​ download bin [verify=yes/no] address=hex number \

 [verify=yes/no\]:选择是否对download的文件进行verify操作;可选,如果不写,则默认使用工程配置中的Flash配置中的Verify选项的值;

​ address:设置bin文件烧录的起始地址,必须为16进制数据;

:文件名称,支持$(ProjectPath)表示工程根路径。

  1. 问题:如何支持Flash区域的调试,如何自动的设置硬断点?

    回答:在工程配置的Debug选项卡中的ICE Settings子选项卡中,勾选了Download to Flash,即开启了Flash区域调试的功能,同时,CDK中设置的断点默认情况下都是硬断点。

  1. 问题:上传组件提示"组件名已经其他账户xxx"的错误提示?

    回答:组件名是稀缺的,如果一个组件名被某个账号使用,那么其他账户将无权限使用该组件名。解决方式:修改本地组件名,重新上传。

【其他待补充】

  1. 问题:

回答:

results matching ""

    No results matching ""