#include "sertrf.h" //设置日志打印类型 #define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF #define SYS_LOG_DOMAIN "Seryrf" sertrf_t sertrf; void sertrf_init(void) { uint8_t res = 0; res = device_init(&sertrf.device); if(res) { SYS_LOG_WRN("device init error"); } // 打开SYS_LOG打印 app_cfg_set_sys_log(true); // 协议初始化 Protocol_init(PORT_LINUX_SBDATA, sertrf.device.embedded_device); //RGB灯 work_rgb_led_start(); //按键初始化 button_work_init(); // 协议初始化 sertrf.resend_read_mutex = xSemaphoreCreateMutex(); resend_init(&sertrf.resend_device, resend_send, resend_recv, resend_get_length,resend_user_parse); // stmisp协议初始化 stmisp_init(&sertrf.stmisp_device,stmisp_send,stmisp_recv,stmisp_get_length); //OAT信息获取 get_partition_status(&sertrf.otau); //获取飞控代码地址 sertrf.fc_address = parse_hex_or_dec(FC_ADDRESS); //获取加密后的efuse MAC 地址 if(!esp_efuse_mac_get_default_id(sertrf.efuse_mac)) { sertrf_aes_ctr_encrypt(sertrf.efuse_mac, 6, sertrf.efuse_mac_encrypt); } //初始化环形buff rb_init(&sertrf.data_handle_buffer, DATA_HANDLE_BUFFER_SIZE, sizeof(uint8_t)); // 判断飞控是否进入 飞控固件强刷模式 sertrf.force_update = key_get_status(); //线程启动 sertrf_start(); SYS_LOG_INF("sertrf init ok"); } void sertrf_start(void) { os_thread_create(&sertrf.embedded_thread, "embedded_thread", embedded_thread, NULL, 4096, 20); os_thread_create(&sertrf.pc_thread, "pc_thread", pc_thread, NULL, 4096, 20); os_thread_create(&sertrf.app_thread, "app_thread", app_thread, NULL, 4096, 15); os_thread_create(&sertrf.task_thread, "task_thread", task_thread, NULL, 2048, 10); os_thread_create(&sertrf.data_handle_thread, "data_handle_thread", data_handle_thread, NULL, 4096, 10); } void sertrf_rf_switch(uint8_t on) { switch(on) { case 1: rf_start(&sertrf.device); break; case 0: rf_stop(&sertrf.device); break; } } //因为 串口 void embedded_thread(void* arg) { while(true) { uint32_t embedded_size = embedded_device_get_rx_length(&sertrf.device); if(embedded_size > 0) { uint8_t data[embedded_size ]; // data[embedded_size] = '\0'; if(!sertrf.stmisp_device.flag && !sertrf.force_update) embedded_device_read(&sertrf.device, data, embedded_size,0); Protocol_buf_decode(data, embedded_size); // SYS_LOG_INF("data : %s", data); pc_device_write(&sertrf.device, data, embedded_size); } // printf_chill_time(10,1000); //需要添加一些延时,否则会卡死,导致看门狗复位 // vTaskDelay(( TickType_t ) 1000 / configTICK_RATE_HZ); os_thread_sleep(1); } } void pc_thread(void* arg) { static bool app_pc_discard = true; while(true) { uint32_t pc_size = pc_device_get_rx_length(&sertrf.device); if(pc_size > 0) { uint8_t data[pc_size]; pc_device_read(&sertrf.device, data, pc_size); // SYS_LOG_INF("data : %s", data); // 由于APP连接上后,会发送一串我用不到的数据,需要丢弃掉,不然会影响我异常飞控固件升级 if(sertrf.device.ble_one_connect_flag == 1) { sertrf.device.ble_one_connect_flag = 0; continue; } if(!sertrf.stmisp_device.flag && !sertrf.force_update) embedded_device_write(&sertrf.device, data, pc_size); } // printf_chill_time(10,1000); //需要添加一些延时,否则会卡死,导致看门狗复位 // vTaskDelay(( TickType_t ) 1000 / configTICK_RATE_HZ); os_thread_sleep(1); } } void app_thread(void* arg) { while (true) { switch(sertrf.resend_device.handle_flag) { case RESEND_CMD_GET_PARAM: sertrf_stauct_t sertrf_stauct; strcpy(sertrf_stauct.ble_name, g_cfg_app->device_name_ble); strcpy(sertrf_stauct.wifi_ap_ssid, g_cfg_app->app_config_wifi_para.wifi_ap_ssid); strcpy(sertrf_stauct.wifi_ap_password, g_cfg_app->app_config_wifi_para.wifi_ap_password); strcpy(sertrf_stauct.wifi_sta_ssid, g_cfg_app->app_config_wifi_para.wifi_sta_ssid); strcpy(sertrf_stauct.wifi_sta_password, g_cfg_app->app_config_wifi_para.wifi_sta_password); memcpy(sertrf_stauct.efuse_mac_encrypt, sertrf.efuse_mac_encrypt, 6); resend_send_data(&sertrf.resend_device, RESEND_CMD_GET_PARAM, &sertrf_stauct, sizeof(sertrf_stauct_t), 1000); sertrf.resend_device.handle_flag = 0;//标志位清零 break; case RESEND_CMD_OTA_GET_PARAM: printf("RESEND_CMD_OTA_GET_PARAM\r\n"); ota_parm_t ota_parm; resend_send_data(&sertrf.resend_device, RESEND_CMD_OTA_GET_PARAM, &ota_parm, sizeof(ota_parm_t), 1000); sertrf.resend_device.handle_flag = 0;//标志位清零 break; case RESEND_CMD_FC_ISP_GET_PARAM: printf("RESEND_CMD_FC_ISP_GET_PARAM\r\n"); stmisp_parm_t stmisp_parm; resend_send_data(&sertrf.resend_device, RESEND_CMD_FC_ISP_GET_PARAM, &stmisp_parm, sizeof(stmisp_parm), 1000); sertrf.resend_device.handle_flag = 0;//标志位清零 break; default: break; } resend_recv_data(&sertrf.resend_device, 0); // static uint8_t count = 0; // count++; // if(count > 100) // { // // resend_send_cmd(&sertrf.resend_device, RESEND_CMD_ACK, 0); // resend_send_data(&sertrf.resend_device, RESEND_CMD_GET_PARAM, NULL, 0, 0); // // count = 0; // } // uint32_t app_size = app_device_get_rx_length(&sertrf.device); // if(app_size > 0) // { // uint8_t data[app_size]; // app_device_read(&sertrf.device, data, app_size,0); // printf("data:%d:%s\n", app_size,data); // } os_thread_sleep(1); } } void task_thread(void* arg) { while(true) { size_t start_time = os_get_sys_time(); pc_link_rgb_color(&sertrf.device); if(sertrf.device.connect_pc > DISCONNECT) { static size_t end_time = 0; if(start_time - end_time > 2000) { sertrf.fc_protocol_status = get_protocol_status(); switch(sertrf.fc_protocol_status) { case PROTOCOL_STATUS_OK: // rgb_color_change(1, sertrf.device.last_color); rgb_color_change(1, RGB_COLOR_ORANGE); break; case PROTOCOL_STATUS_NO_DATA: rgb_color_change(1, RGB_COLOR_RAD); break; case PROTOCOL_STATUS_TYPE_IDLE: rgb_color_change(1, RGB_COLOR_RAD); break; case PROTOCOL_STATUS_ANALYSIS_ERROR: rgb_color_change(1, RGB_COLOR_RAD); break; case PROTOCOL_STATUS_IN_OTA: rgb_color_change(1, RGB_COLOR_BLUE); default: break; } end_time = os_get_sys_time(); } } os_thread_sleep(100); } } void data_handle_thread(void* arg) { while(true) { switch(sertrf.mode_status.task_state) { case DATA_HANDLE_OTA_DATA: { size_t data_size = rb_size(&sertrf.data_handle_buffer); if(data_size > 1024) { uint8_t data[data_size]; rb_get_bulk(&sertrf.data_handle_buffer, data, data_size); if(otau_write(&sertrf.otau, data, data_size)) { SYS_LOG_DBG("stmisp write error"); } else { SYS_LOG_DBG("stmisp write ok"); } } } break; case DATA_HANDLE_OTA_DATA_END: { size_t data_size = rb_size(&sertrf.data_handle_buffer); if(data_size > 0) { uint8_t data[data_size]; rb_get_bulk(&sertrf.data_handle_buffer, data, data_size); if(otau_write(&sertrf.otau, data, data_size)) { SYS_LOG_DBG("stmisp write error"); } else { SYS_LOG_DBG("stmisp write ok"); sertrf.mode_status.task_state = DATA_HANDLE_IDLE; } } } break; case DATA_HANDLE_ISP_DATA: { size_t data_size = rb_size(&sertrf.data_handle_buffer); if(data_size > 0) { uint8_t data[data_size]; rb_get_bulk(&sertrf.data_handle_buffer, data, data_size); uint32_t addr = sertrf.fc_address + sertrf.stmisp_device.adder_offset; if(cmd_write_memory(&sertrf.stmisp_device, addr, data, data_size, false)) { resend_send_cmd(&sertrf.resend_device, RESEND_CMD_ACK, 0); sertrf.stmisp_device.adder_offset += data_size; SYS_LOG_INF("stmisp write ok %d %d\n",data_size, sertrf.stmisp_device.adder_offset); } else { sertrf.stmisp_device.adder_offset = 0; sertrf.mode_status.task_state = DATA_HANDLE_IDLE; SYS_LOG_DBG("stmisp write error"); } } } break; case DATA_HANDLE_ISP_DATA_END: { size_t data_size = rb_size(&sertrf.data_handle_buffer); if(data_size > 0) { uint8_t data[data_size]; rb_get_bulk(&sertrf.data_handle_buffer, data, data_size); uint32_t addr = sertrf.fc_address + sertrf.stmisp_device.adder_offset; if(cmd_write_memory(&sertrf.stmisp_device, addr, data, data_size, true)) { sertrf.stmisp_device.adder_offset = 0; sertrf.mode_status.task_state = DATA_HANDLE_IDLE; } else { SYS_LOG_DBG("stmisp write end error"); } } else { sertrf.stmisp_device.adder_offset = 0; sertrf.mode_status.task_state = DATA_HANDLE_IDLE; } } break; default: break; } os_thread_sleep(1); } } void pc_link_rgb_color(device_t* device) { static uint8_t last_connect = 255, last_wifi_mode = 0; uint8_t new_color = 0; if(device->connect_pc != last_connect || last_wifi_mode != device->init_device.wifi_mode) { switch (device->connect_pc) { case DISCONNECT: { if(device->init_device.wifi_mode == WIFI_NETIF_MODE_AP) new_color = NO_CONNECT_COLOR_BLE_AP; else if(device->init_device.wifi_mode == WIFI_NETIF_MODE_STA) new_color = NO_CONNECT_COLOR_BLE_STA; else if(device->init_device.wifi_mode == RC_OFF_NONE) new_color = RF_OFF_COLOR; break; } case CONNECT_WIFI_TCP: { if(device->init_device.wifi_mode == WIFI_NETIF_MODE_AP) new_color = WIFI_AP_COLOR; else if(device->init_device.wifi_mode == WIFI_NETIF_MODE_STA) new_color = WIFI_STA_COLOR; else if(device->init_device.wifi_mode == RC_OFF_NONE) new_color = RF_OFF_COLOR; break; } case CONNECT_WIFI_UDP: { if(device->init_device.wifi_mode == WIFI_NETIF_MODE_AP) new_color = WIFI_AP_COLOR; else new_color = WIFI_STA_COLOR; break; } case CONNECT_BLE: { new_color = BLE_COLOR; } break; case CONNECT_RF_OFF: { new_color = RF_OFF_COLOR; } break; } if(device->last_color != new_color) rgb_color_change(0,new_color); device->last_color = new_color; last_connect = device->connect_pc; last_wifi_mode = device->init_device.wifi_mode; if(device->connect_pc == DISCONNECT) { rgb_update_cyle(0,50); } else if(device->connect_pc){ rgb_update_cyle(0,888); }else{ rgb_update_cyle(0,500); } } } int resend_send(void* data, uint16_t len, int timeout) { return app_device_write(&sertrf.device, data, len); } int resend_recv(void* data, uint16_t len, int timeout) { int ret = 0; if (xSemaphoreTake(sertrf.resend_read_mutex, portMAX_DELAY) == pdTRUE) { ret = app_device_read(&sertrf.device, data, len,timeout); xSemaphoreGive(sertrf.resend_read_mutex); } return ret; } int resend_get_length(void) { return app_device_get_rx_length(&sertrf.device); } void resend_user_parse(void *resend_device) { resend_device_t* resend_parse = (resend_device_t*)resend_device; switch(resend_parse->rx_frame.cmd) { case RESEND_CMD_SET_PARAM: // 减6的目的是因为华哥没对MAC进行处理,所以也不返回 if(sizeof(sertrf_stauct_t) - 6 != resend_parse->rx_frame.len) { printf("RESEND_CMD_SET_PARAM len error\r\n"); } sertrf_stauct_t* sertrf_stauct = (sertrf_stauct_t*)resend_parse->rx_frame.payload; app_cfg_set_device_name_ble(sertrf_stauct->ble_name, strlen(sertrf_stauct->ble_name)); app_cfg_set_wifi_ap_ssid(sertrf_stauct->wifi_ap_ssid); app_cfg_set_wifi_ap_password(sertrf_stauct->wifi_ap_password); app_cfg_set_wifi_sta_ssid(sertrf_stauct->wifi_sta_ssid); app_cfg_set_wifi_sta_password(sertrf_stauct->wifi_sta_password); resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); os_thread_sleep(1000); esp_restart(); break; case RESEND_CMD_OTA_GET_PARAM: { if(sizeof(ota_parm_t) != resend_parse->rx_frame.len) { printf("RESEND_CMD_OTA_GET_PARAM len error\r\n"); } ota_parm_t* ota_parm = (ota_parm_t*)resend_parse->rx_frame.payload; printf("RESEND_CMD_OTA_GET_PARAM %d\n", ota_parm->ota_file_size); resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); } break; case RESEND_CMD_OTA_START: { //设置协议状态,为了后续灯颜色变化 protocol_set_message_status(MESSAGE_OTA); // if(!sertrf.resend_device.status.resend_flag) //初始化ota会占用大量系统资源,需要先把飞控获取数据关闭,不然会导致栈溢出 sb_data_port_stop(sertrf.device.embedded_device); otau_init(&sertrf.otau); sertrf.mode_status.task_state = DATA_HANDLE_OTA_DATA; resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); } break; case RESEND_CMD_OTA_DATA: { protocol_set_message_status(MESSAGE_OTA); // 使用环形buff if(rb_size(&sertrf.data_handle_buffer) + sertrf.resend_device.rx_frame.len <= DATA_HANDLE_BUFFER_SIZE) { rb_put_bulk(&sertrf.data_handle_buffer, sertrf.resend_device.rx_frame.payload, sertrf.resend_device.rx_frame.len); } else { SYS_LOG_DBG("RESEND_CMD_OTA_DATA buffer full"); } resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); } break; case RESEND_CMD_OTA_END: { sertrf.mode_status.task_state = DATA_HANDLE_OTA_DATA_END; while (sertrf.mode_status.task_state != DATA_HANDLE_IDLE){ os_thread_sleep(10);} otau_end(&sertrf.otau); resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); os_thread_sleep(2); esp_restart(); } break; case RESEND_CMD_FC_ISP_GET_PARAM: if(sizeof(stmisp_parm_t) != resend_parse->rx_frame.len) { printf("RESEND_CMD_FC_ISP_GET_PARAM len error\r\n"); } stmisp_parm_t* stmisp_parm = (stmisp_parm_t*)resend_parse->rx_frame.payload; printf("RESEND_CMD_FC_ISP_GET_PARAM %d\n", stmisp_parm->stmisp_file_size); resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); break; case RESEND_CMD_FC_ISP_START: /*关闭其他线程中相同串口的使用,并复位飞控,使其进入isp烧录模式,串口切换为偶校验模式 使用sync与isp确定通讯波特率,并建立联系 解除其写保护 并重新sync建立连接后擦除全部区域内存*/ //关闭其他线程中相同串口的使用 sertrf.stmisp_device.flag = 1; // 修改灯珠颜色 protocol_set_message_status(MESSAGE_FC_ISP); // 重启飞控,并使其进入isp烧录模式 需要在能够识别飞控的情况下才需要重启 // if(sertrf.fc_protocol_status != PROTOCOL_STATUS_TYPE_IDLE && sertrf.fc_protocol_status != PROTOCOL_STATUS_NO_DATA) fc_reboot(); boot_set_2(0); os_thread_sleep(1000); //串口切换为偶校验模式,并清除缓存 uart_set_parity_switch(sertrf.device.embedded_device, 0x02); os_thread_sleep(100); // 与isp确定通讯波特率,并建立联系 if(!send_sync(&sertrf.stmisp_device, 5)) { printf("stmisp: sync error\n"); // app_send_error_code(SERTRF_ERROR_FC_ISP_SYNC); break; } else printf("stmisp: sync ok\n"); os_thread_sleep(100); // 解除写保护 if(!cmd_write_unprotect(&sertrf.stmisp_device)) printf("stmisp: write unprotect error\n"); else printf("stmisp: write unprotect ok\n"); os_thread_sleep(100); if(!send_sync(&sertrf.stmisp_device, 5)) printf("stmisp: sync error\n"); else printf("stmisp: sync ok\n"); os_thread_sleep(100); boot_set_high_z_2(); // 全盘擦除 if(!cmd_extended_erase_mass(&sertrf.stmisp_device)) printf("stmisp: erase mass error\n"); else printf("stmisp: erase mass ok\n"); os_thread_sleep(10); printf("stmisp: isp start\n"); sertrf.mode_status.task_state = DATA_HANDLE_ISP_DATA; resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); break; case RESEND_CMD_FC_ISP_DATA: // 使用环形buff if(rb_size(&sertrf.data_handle_buffer) + sertrf.resend_device.rx_frame.len <= DATA_HANDLE_BUFFER_SIZE) { rb_put_bulk(&sertrf.data_handle_buffer, sertrf.resend_device.rx_frame.payload, sertrf.resend_device.rx_frame.len); } else { SYS_LOG_DBG("RESEND_CMD_FC_ISP_DATA buffer full"); } // resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); break; case RESEND_CMD_FC_ISP_END: // 告诉数据处理线程,ISP烧录数据传输完成 sertrf.mode_status.task_state = DATA_HANDLE_ISP_DATA_END; // 等待数据处理线程写入完成 SYS_LOG_INF("RESEND_CMD_FC_ISP_END1"); while(sertrf.mode_status.task_state != DATA_HANDLE_IDLE){ os_thread_sleep(10);} // ISP下跳转到应用层运行地址 if(cmd_go(&sertrf.stmisp_device, sertrf.fc_address)) { printf("stmisp: go ok\n"); } else { printf("stmisp: go error\n"); } //开启其他线程中相同串口的使用 sertrf.stmisp_device.flag = 0; // 将串口切换为无校验模式 uart_set_parity_switch(sertrf.device.embedded_device, 0x00); SYS_LOG_INF("RESEND_CMD_FC_ISP_END2"); resend_send_cmd(resend_device, RESEND_CMD_ACK, 0); esp_restart(); break; default: break; } } void Examples_run(void) { // // //关闭其他线程中相同串口的使用 sertrf.stmisp_device.flag = 1; // // // 重启飞控,并使其进入isp烧录模式 fc_reboot(); boot_set(0); os_thread_sleep(500); uart_set_parity_switch(sertrf.device.embedded_device, 0x02); os_thread_sleep(500); // 与isp确定通讯波特率,并建立联系 if(!send_sync(&sertrf.stmisp_device, 5)) printf("stmisp: sync error\n"); else printf("stmisp: sync ok\n"); os_thread_sleep(100); // 解除写保护 if(!cmd_write_unprotect(&sertrf.stmisp_device)) printf("stmisp: write unprotect error\n"); else printf("stmisp: write unprotect ok\n"); os_thread_sleep(100); if(!send_sync(&sertrf.stmisp_device, 5)) printf("stmisp: sync error\n"); else printf("stmisp: sync ok\n"); os_thread_sleep(100); boot_set_high_z(); // 全盘擦除 if(!cmd_extended_erase_mass(&sertrf.stmisp_device)) printf("stmisp: erase mass error\n"); else printf("stmisp: erase mass ok\n"); os_thread_sleep(10); printf("stmisp: isp start\n"); } int stmisp_send(void* data, uint16_t len, int timeout) { return embedded_device_write(&sertrf.device, data, len); } int stmisp_recv(void* data, uint16_t len, int timeout) { uint32_t time_start = os_get_sys_time(); int size = 0; while(os_get_sys_time() - time_start < timeout) { size = embedded_device_read(&sertrf.device, data, len, 0); if(size > 0) return size; os_thread_sleep(1); } return size; } int stmisp_get_length(void) { return embedded_device_get_rx_length(&sertrf.device); } int app_send_error_code(uint8_t error_code) { sertrf.mode_status.sertrf_error_code = error_code; return resend_send_data(&sertrf.resend_device, RESEND_CMD_ERROR_CODE, &sertrf.mode_status.sertrf_error_code, sizeof(sertrf_mode_status_t), 1000); }