【技术干货】TuyaOS(NB-IoT)新平台移植指导:适配tkl_nbiot_misc.c
本章介绍对tkl_nbiot_misc.c的接口相关适配
芯片信息相关
Code: Select all
/** * @brief get the chip type * * @param[inout] out_type :output the chip type * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_chip_type(TKL_MISC_CHIP_TYPE_E *out_type) { *out_type = TKL_CHIP_MAX; return OPRT_OK; }
该接口返回芯片类型:
typedef enum {
TKL_CHIP_MTK2625 = 0, //适配涂鸦标准的差分升级流程!!!
TKL_CHIP_EC616 = 1,
TKL_CHIP_XY1100 = 2,
TKL_CHIP_MAX = 3, //支持通用三方芯片FOTA升级流程
} TKL_MISC_CHIP_TYPE_E;
默认输出为:TKL_CHIP_MAX,SDK只负责下载固件及获取升级结果
AT口操作相关:
Code: Select all
/** * @brief if AT serial port is on or off * * @param[in] null * * @return true: on Other: off */ BOOL_T tkl_nbiot_is_atcmd_serial_port_on(void) { // --- BEGIN: user implements --- return true; // --- END: user implements --- }
判断AT口是否打开,已打开状态返回true,否则返回false.
Code: Select all
/** * @brief set AT serial port off * * @param[in] null * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_atcmd_serial_port_off(VOID) { // --- BEGIN: user implements --- return OPRT_NOT_SUPPORTED; // --- END: user implements --- }
关闭AT口操作,成功关闭返回OPRT_OK,否则返回OPRT_COM_ERROR.
Code: Select all
/** * @brief set AT serial port on * * @param[in] null * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_atcmd_serial_port_on(VOID) { // --- BEGIN: user implements --- return OPRT_NOT_SUPPORTED; // --- END: user implements --- }
打开AT口操作,成功打开返回OPRT_OK,否则返回OPRT_COM_ERROR.
Code: Select all
typedef void (*serial_port_uart_virtaul_at_cb_t)(char *resp_str, unsigned int str_len); /** * @brief execute AT common command * * @param[in] pbuf: at command string * @param[in] len: at command string length * @param[in] cb: at command executed callback func * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_atcmd_common(PCHAR_T pbuf, UCHAR_T len, serial_port_uart_virtaul_at_cb_t cb) { // --- BEGIN: user implements --- return OPRT_NOT_SUPPORTED; // --- END: user implements --- }
通用AT指令执行操作,执行成功返回OPRT_OK,否则返回OPRT_COM_ERROR
(如果硬件平台不支持通用AT指令操作,返回 OPRT_NOT_SUPPORTED)输入:
pbuf:标准AT指令字符串内存指针,如"AT+CSQ\r\n",
len:pbuf字符串的长度,
输出回调函数定义:
typedef void (*serial_port_uart_virtaul_at_cb_t)(char *resp_str, unsigned int str_len)
resp_str:AT执行后输出回显字符串内存指针,
str_len:resp_str回显字符串长度
OTA升级相关
Code: Select all
/** * @brief get the offset address of app firmware * * @param[inout] out_addr :output the offset address * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_get_app_offset(UINT_T *out_addr) { *out_addr = TUYA_APP_ADDR; return OPRT_OK; }
返回当前应用固件保存在flash中的起始空间相对地址,如TUYA_APP_ADDR(用户根据平台定义)
Code: Select all
/** * @brief get the app firmware space length * * @param[inout] out_addr :output the offset address * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_get_app_len(UINT_T *out_len) { *out_len = TUYA_APP_LENGTH; return OPRT_OK; }
返回当前应用固件所占用的最大flash空间长度TUYA_APP_LENGTH(用户根据平台定义)
Code: Select all
/** * @brief notify fota update start, some platform need acquire this info then restart system,such as NX1, others return directly * * @param[in] null * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_fota_update_start(void) { return OPRT_OK; }
直接返回OPRT_OK,不用做处理。
Code: Select all
/** * @brief notify fota update end, some platform need acquire this info to clear update status,such as NX1, others return directly * * @param[in] null * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_fota_update_end(void) { return OPRT_OK; }
SDK升级完成并已经将升级状态同步到云平台,硬件平台侧此时可以在该功能中清除相关的升级状态(如在ota_get_update_result()中保存的升级状态)信息后,直接返回OPRT_OK。
Code: Select all
/** * @brief some upgrade status needs to be obtained from the platform,such as NX1, others return directly * * @param[in] null * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_fota_status_acquire(void) { // 获取升级结果,并构造升级信息 fota_update_info_t up_info = {0}; UINT_T trigger_addr = 0, upinfo_addr = 0; OPERATE_RET ret = OPRT_OK; tkl_nbiot_get_fota_update_info_offset(&upinfo_addr); tkl_nbiot_get_fota_trigger_flag_offset(&trigger_addr); ret = tkl_flash_read(trigger_addr, (UCHAR_T *)&up_info, sizeof(fota_update_info_t)); if ((ret == OPRT_OK) && ((up_info.m_ver & 0x00FFFFFF) == 0x004D4D4D)) { //已标识升级开始状态! ret = ota_get_update_result(); //硬件平台侧实现:获取当前的升级状态 if (ret == OK) { TAL_PR_DEBUG("fota success"); up_info.m_error_code = 0; } else { TAL_PR_DEBUG("fota fail"); up_info.m_error_code = 1; } tkl_flash_erase(upinfo_addr, (1 << 12)); tkl_flash_write(trigger_addr, (const UCHAR_T *)&up_info, sizeof(fota_update_info_t));//将升级信息写入指定flash地址 return OPRT_OK; } return OPRT_COM_ERROR; }
以下为FOTA升级过程:
SDK下载完成FOTA固件包,会将标识0x004D4D4D记录在结构体fota_update_info_t的成员m_ver中,并写入tkl_nbiot_get_fota_trigger_flag_offset指定的地址,同时通过应用层的注册tuya_user_api_fota_notify_register回调event_notify,将事件OTA_EVENT_DOWNLOAD_COMPLETE发送给应用层;
系统重启(SDK会执行系统重启操作,硬件平台侧不要主动重启!!!)
进入bootloader,硬件平台侧可以通过判断tkl_nbiot_get_fota_trigger_flag_offset地址中fota_update_info_t的成员m_ver是否为0x004D4D4D时,决定是否接管固件升级(注意,升级全程不要擦除标识0x004D4D4D)
bootloader升级执行结束后,将升级结果保存(以便进入系统后 ota_get_update_result()能够获取),接着跳转到应用程序固件起始地址
初始化期间SDK会调用tkl_nbiot_fota_status_acquire,获取当前升级状态信息(硬件平台侧需要构建在tuya_fota_downloader.h中定义的结构体fota_update_info_t,并写入以下函数tkl_nbiot_get_fota_trigger_flag_offset所指的起始空间),成功返回OPRT_OK,否则返回错误。
(以上是一个实现例程)SDK中主要通过该接口将升级结果返回给APP,以便同步当前的升级信息。
Code: Select all
/** * @brief get the offset address to save firmware * * @param[inout] out_addr :output the offset address * @param[inout] _1st_data :the first fota data pointer * @param[inout] _1st_data_size :the first fota data length * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_get_fota_offset(UINT_T *out_addr, UCHAR_T *_1st_data, UINT32_T _1st_data_size) { *out_addr = TUYA_FOTA_ADDR; return OPRT_OK; }
(输入形参out_addr,_1st_data, _1st_data_size除芯翼平台外,可以不用处理)
返回FOTA固件下载后保存在flash中的起始相对地址TUYA_FOTA_ADDR(用户根据平台定义)
Code: Select all
/** * @brief get the space legth to save firmware * * @param[inout] out_addr :output the offset address * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_get_fota_len(UINT_T *out_len) { *out_len = TUYA_FOTA_LENGTH; return OPRT_OK; }
返回FOTA固件保存在flash中所占用的最大空间长度
Code: Select all
/** * @brief get the offset address to save update info * * @param[inout] out_addr :output the offset address * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_get_fota_update_info_offset(UINT_T *out_addr) { *out_addr = TUYA_FOTA_UPDATE_INFO_ADDR; return OPRT_OK; }
该函数功能返回升级标识相关及升级结果信息在flash中保存扇区的相对起始地址 TUYA_FOTA_UPDATE_INFO_ADDR,长度预留一个扇区大小即1024*4(4KB)
Code: Select all
/** * @brief get the offset address to save trigger fota indicator * * @param[inout] out_addr :output the offset address * * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h */ OPERATE_RET tkl_nbiot_get_fota_trigger_flag_offset(UINT_T *out_addr) { *out_addr = TUYA_FOTA_TRIGGER_FLAG_ADDR; return OPRT_OK; }
该函数功能返回升级标识相关及升级结果信息(为fota_update_info_t数据结构)在flash中保存扇区的实际相对起始地址TUYA_FOTA_TRIGGER_FLAG_ADDR
函数tkl_nbiot_get_fota_update_info_offset及tkl_nbiot_get_fota_trigger_flag_offset所返回在flash中所指定的地址建议如下:
硬件周边配置信息
Code: Select all
/** * @brief get the AT uart number * * @param[] null * * @return the AT uart number */ UINT_T tkl_nbiot_get_uart_at_number(VOID) { return 0; // AT 串口 }
返回硬件平台侧AT串口号
Code: Select all
/** * @brief get the user uart number of communication * * @param[] null * * @return the user uart number */ UINT_T tkl_nbiot_get_uart_user_number(VOID) { return 1; // 用户通讯及产测串口 }
返回硬件平台侧用户通讯及产测串口号
Code: Select all
/** * @brief get the log uart number of communication * * @param[] null * * @return the log uart number */ UINT_T tkl_nbiot_get_uart_log_number(VOID) { return 2; // 日志串口 }
返回硬件平台侧日志输出串口
Code: Select all
/** * @brief get the net led gpio number * * @param[] null * * @return the number */ UINT_T tkl_nbiot_get_net_led_gpio_number(VOID) { return 20; // NET_LED_GPIO }
返回硬件平台侧驱动LED对应的GPIO号
Code: Select all
/** * @brief get the psm wake up gpio number * * @param[] null * * @return the number */ UINT_T tkl_nbiot_get_psm_wake_up_gpio_number(VOID) { return 0; // PSM_WAKE_UP_GPIO }
返回硬件平台侧PSM外部唤醒脚对应的GPIO号
Code: Select all
/** * @brief get the adc channel number * * @param[] null * * @return the number */ UINT_T tkl_nbiot_get_adc_channel_number(VOID) { return HAL_ADC_CHANNEL_0; // TUYA_NB_ADC_CHANNEL }
返回硬件平台侧ADC对应的通道号
Code: Select all
/** * @brief get the adc channel sample deviation value: mv(单位) * * @param[] null * * @return the val :mv(单位) */ UINT_T tkl_nbiot_get_adc_sample_deviation_val(VOID) { ////采样容许偏差范围单位:mv return 50; // TUYA_NB_ADC_SAMPLE_DEVIATION }
返回ADC采样容许偏差范围
Code: Select all
/** * @brief get message ring gpio number * * @param[] null * * @return the number */ UINT_T tkl_nbiot_get_message_ri_gpio_number(VOID) { // MESSAGE_RI_GPIO return 0xff; //NM1:unsupport! }
返回ring对应的GPIO口.(当云端有数据下发时,通过该GPIO口触发200ms的低电平脉冲)不支持则返回0xff.