• 正文
  • 相关推荐
申请入驻 产业图谱

【教程】CW32L012串行flash下载项目移植教程

08/21 08:01
183
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

项目移植

例程下载:

通过网盘分享的文件:cw32l012_serial_flash_prog_v2.rar

链接: https://pan.baidu.com/s/19AiNYkDXNBuqPAaoCWjxWQ?pwd=L012 提取码: L012

上位机下载:

通过网盘分享的文件:serial-flash-prog_v1.3.1.exe

链接: https://pan.baidu.com/s/12QMAex-y_3XgMx17ifGcKw?pwd=L012 提取码: L012


本期的串口flash下载库是依赖simple_queue队列库和sliding_window_parse滑动窗口解析库的,这里不对这两个库进行介绍,不懂的请看往期文章。

【教程】CW32L012滑动窗口解析库

SFP库仅包含4个文件:sfp_core.c、sfp_core.h、comm_fmt.c、comm_fmt.h。使用时将其加入工程,然后按以下步骤在自己代码中完成移植。

配置参数

在 sfp_core.h 中根据实际硬件配置相关宏:

 

#define SFP_USE_ASSERT                      0#define SFP_USE_PRINTF                      0#define SFP_USE_CHECK_FRAME_INSIDE          0               // 是否在内部校验数据帧(一般情况下不校验,强烈推荐用户验证好完整帧信息再调用解码函数)#define SFP_USE_READ_AFTER_WRITE_CHECK      0               // 是否在写入后读出数据来校验(开启更加安全,关闭占用资源更少)#define SFP_USE_CHECK_FRAME_LEN             0               // 是否校验命令帧长度(开启更加安全,关闭占用资源更少)#define SFP_IO_LEN_DEFAULT                  1024             // 单次读写最大长度#define SFP_FLASH_SIZE                      (16*1024*1024)  // 物理存储介质大小 16MB#define SFP_PRINTF                          printf

实现底层接口

在自己的 .c 文件中实现 sfp_ops_t 声明的全部接口函数(以下以CW32平台为例,其他平台类似):

// CRC16-CCITT 校验接口static uint16_t sfp_crc16_ccitt(void *pdata, uint16_t len){    // user code begin    returnproto_parser_crc16_ccitt(pdata, len);    // user code end    // return 0;}// 串口数据发送接口staticvoidsfp_data_tx_port(const sfp_download_info_t* download_info,uint8_t *pdata, uint16_t len){    cw32_uart3_send_data(pdata, len);}// flash 擦除接口static sfp_err_code_t sfp_erase_port(const sfp_download_info_t* download_info, uint32_t start_addr, uint32_t len){    if(start_addr + len > SFP_FLASH_SIZE)    {        return SFP_ERR_OPERATION_ADDRESS;    }    // user code begin    nor_flash_erase_auto(start_addr, len);    // user code end    return SFP_ERR_NONE;}// flash 写入接口static sfp_err_code_t sfp_write_port(const sfp_download_info_t* download_info, uint32_t start_addr, uint8_t *pdata, uint16_t len){    if(start_addr + len > SFP_FLASH_SIZE)    {        return SFP_ERR_OPERATION_ADDRESS;    }    elseif(len > download_info->io_len || len == 0)    {        return SFP_ERR_OPERATION_LEN;    }    // user code begin    nor_flash_write(start_addr, pdata, len);    // user code end    return SFP_ERR_NONE;}// flash 读取接口#if SFP_USE_READ_AFTER_WRITE_CHECKstatic sfp_err_code_t sfp_read_port(const sfp_download_info_t* download_info, uint32_tstart_addr, uint8_t *pdata, uint16_tlen){    if(start_addr + len > SFP_FLASH_SIZE)    {        return SFP_ERR_OPERATION_ADDRESS;    }    elseif(len > download_info->io_len || len == 0)    {        return SFP_ERR_OPERATION_LEN;    }    // user code begin    nor_flash_read(start_addr, pdata, len);    // user code end    return SFP_ERR_NONE;}#endif// 下载开始接口static sfp_err_code_t sfp_download_start_port(const sfp_download_info_t* download_info){    // you can check file size, version, file name, io len    if(download_info->file_size > SFP_FLASH_SIZE)    {        return SFP_ERR_FILE_TOO_LARGE;    }    elseif(download_info->io_len > SFP_IO_LEN_DEFAULT || download_info->io_len == 0)    {        return SFP_ERR_IO_LEN;    }    // else if(strcmp(download_info->file_name, "xxx.bin") == 0)    // {    //     return SFP_ERR_FILE_NAME;    // }        // else if(download_info->version == 0x00000000)    // {    //     return SFP_ERR_VERSION;    // }    // user code begin    // user code end    return SFP_ERR_NONE;}// 下载完成接口static sfp_err_code_t sfp_download_stop_port(const sfp_download_info_t* download_info){    // user code begin    // user code end    return SFP_ERR_NONE; }

实例化并初始化

先构建ops操作表,然后定义 sfp_module_t 实例和发送缓冲区,在系统初始化时调用 sfp_module_init

const sfp_ops_t sfp_ops =     .crc16_ccitt = sfp_crc16_ccitt,    .data_tx_port = sfp_data_tx_port,    .flash_erase_port = sfp_erase_port,    .flash_write_port = sfp_write_port,    #if SFP_USE_READ_AFTER_WRITE_CHECK    .flash_read_port = sfp_read_port,    #endif    .download_start_port = sfp_download_start_port,    .download_stop_port = sfp_download_stop_port,};uint8_t sfp_tx_buf[SFP_TX_BUF_SIZE_MIN] = {0};sfp_module_t sfp_module = {0};voidservice_sfp_init(void){    sfp_init_t init = {0};    init.ops = &sfp_ops;    init.tx_buf = sfp_tx_buf;    init.tx_buf_size = sizeof(sfp_tx_buf);    init.self_dev_addr = 1;    if(!sfp_module_init(&sfp_module,&init))    {        // init failed        // user code begin        // user code end        while(1);    }}

对接滑动串口解析层

对sfp层解析函数进行封装

voidservice_sfp_decode_full_frame(sfp_frame_msg_t* sfp_msg,uint8_t* frame_buf,uint16_t frame_len){    sfp_decode_full_frame(&sfp_module,sfp_msg,frame_buf,frame_len);}在滑动窗口解析一帧的回调函数中调用我们刚刚写的函数voidparser_frame_dispose(frame_msg_t *msg,uint8_t* frame_buf, uint16_t len){    /*        frame_msg_t 与 sfp_frame_msg_t 结构体元素是相同的,为了降低依赖,将其区分了        实际使用时强制类型转换即可    */    service_sfp_decode_full_frame((sfp_frame_msg_t*)msg,frame_buf,len);}

 

至此,移植完成。核心工作就是配置宏 + 实现接口函数,后续收到完整命令帧后调用 sfp_decode_full_frame 即可自动完成命令处理、Flash操作和应答发送。

扫码加入QQ群,3群| 610403240

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

以开放、共享、互助为理念,致力于构建武汉芯源半导体CW32系列MCU生态社区。无论是嵌入式MCU小自还是想要攻破技术难题的工程师,亦或是需求解决方案的产品经理都可在CW32生态社区汲取营养、共同成长。