379 lines
9.6 KiB
C
379 lines
9.6 KiB
C
|
#include "api.h"
|
||
|
|
||
|
#define API_RX_MAXSIZE 615
|
||
|
|
||
|
uint8_t api_upgrade_mode = 0;
|
||
|
|
||
|
static uint8_t version[24] = {SOFTWARE_VERSION};
|
||
|
|
||
|
static uint16_t api_rx_status = 0;
|
||
|
static uint16_t api_rx_length = 0;
|
||
|
static uint8_t api_rx_buffer[API_RX_MAXSIZE] = {0};
|
||
|
|
||
|
/* 升级包序号 */
|
||
|
static uint16_t upgrade_pack_index = 0;
|
||
|
/* 升级包总数 */
|
||
|
static uint16_t upgrade_pack_count = 0;
|
||
|
/* 升级包数据接收长度 */
|
||
|
static uint16_t upgrade_rx_length = 0;
|
||
|
/* 升级包数据接收长度 */
|
||
|
static uint16_t upgrade_rx_index = 0;
|
||
|
/* 升级包写入下标 */
|
||
|
static uint16_t upgrade_write_index = 0;
|
||
|
/* 升级包数据接收长度 */
|
||
|
static uint8_t upgrade_rx_buffer[1024] = {0};
|
||
|
|
||
|
static void api_notify_upgrade(uint8_t *buffer, uint16_t length);
|
||
|
static void api_notify_get_fhss_channel(void);
|
||
|
static void api_package(uint8_t type, uint8_t command, uint8_t *data, uint8_t length);
|
||
|
static void api_package_response(uint8_t command, uint8_t status, uint8_t *buffer, uint16_t length);
|
||
|
static void api_unpacking(uint8_t *buffer, uint16_t length);
|
||
|
|
||
|
/**
|
||
|
* @brief 应用程序初始化
|
||
|
*/
|
||
|
void api_init(void)
|
||
|
{
|
||
|
/* 加载设置信息 */
|
||
|
setting_load();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 应用程序处理任务
|
||
|
*/
|
||
|
void api_process(void)
|
||
|
{
|
||
|
if (api_rx_status & 0x8000)
|
||
|
{
|
||
|
#ifdef USE_LED
|
||
|
gpio_bit_toggle(LED_RX_PERIPH, LED_RX_PIN);
|
||
|
#endif
|
||
|
uint8_t buffer[API_RX_MAXSIZE] = {0};
|
||
|
uint16_t length = api_rx_status & 0x7FFF;
|
||
|
|
||
|
for (uint16_t i = 0; i < length; i++)
|
||
|
buffer[i] = api_rx_buffer[i];
|
||
|
|
||
|
api_rx_length = 0;
|
||
|
api_rx_status = 0;
|
||
|
|
||
|
api_unpacking(buffer, length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 数据组包
|
||
|
*/
|
||
|
void api_concat_byte(uint8_t data)
|
||
|
{
|
||
|
if (api_rx_status & 0x8000)
|
||
|
return;
|
||
|
|
||
|
if (api_rx_length > API_RX_MAXSIZE || api_rx_status > API_RX_MAXSIZE)
|
||
|
{
|
||
|
api_rx_status = 0;
|
||
|
api_rx_length = 0;
|
||
|
}
|
||
|
|
||
|
api_rx_buffer[api_rx_status++] = data;
|
||
|
|
||
|
if (api_rx_status == 1)
|
||
|
{
|
||
|
if (api_rx_buffer[0] != 0xA6)
|
||
|
api_rx_status = 0;
|
||
|
}
|
||
|
else if (api_rx_status == 5)
|
||
|
{
|
||
|
api_rx_length = (api_rx_buffer[3] << 8 & 0xFF00) | (api_rx_buffer[4] & 0xFF);
|
||
|
api_rx_length += 7;
|
||
|
}
|
||
|
else if (api_rx_status == api_rx_length)
|
||
|
{
|
||
|
if (api_rx_buffer[api_rx_status - 1] == 0x77)
|
||
|
{
|
||
|
api_rx_status |= 0x8000;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
api_rx_status = 0;
|
||
|
api_rx_length = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 上传数据
|
||
|
*/
|
||
|
__weak void api_notify_data_upload(uint8_t *buffer, uint16_t length) {}
|
||
|
|
||
|
/**
|
||
|
* @brief 返回成功执行指令
|
||
|
*/
|
||
|
void api_response_success(uint8_t command) { api_package_response(command, API_SUCCESS, nullptr, 0); }
|
||
|
|
||
|
/**
|
||
|
* @brief 上传心跳数据
|
||
|
*/
|
||
|
void api_upload_heart_beat(void)
|
||
|
{
|
||
|
uint8_t index = 0, buffer[40] = {0};
|
||
|
|
||
|
for (uint8_t i = 0; i < 12; i++)
|
||
|
buffer[index++] = uuid[i];
|
||
|
|
||
|
for (uint8_t i = 0; i < 24; i++)
|
||
|
buffer[index++] = version[i];
|
||
|
|
||
|
uint32_t runtime = timestamp / 1000;
|
||
|
|
||
|
buffer[index++] = runtime >> 24 % 0xFF;
|
||
|
buffer[index++] = runtime >> 16 % 0xFF;
|
||
|
buffer[index++] = runtime >> 8 % 0xFF;
|
||
|
buffer[index++] = runtime & 0xFF;
|
||
|
|
||
|
api_package(API_FRAME_NOTIFICATION, API_COMMAND_HEART_BEAT, buffer, index);
|
||
|
}
|
||
|
|
||
|
void api_upload_vehicle_status(uint8_t type, uint8_t value)
|
||
|
{
|
||
|
uint8_t buffer[2] = { type, value};
|
||
|
|
||
|
api_package(API_FRAME_NOTIFICATION, API_COMMAND_VEHICLE_STATUS, buffer, 2);
|
||
|
}
|
||
|
|
||
|
__weak void api_notify_set_strobe_light_mode(uint8_t mode) {}
|
||
|
|
||
|
void api_response_set_strobe_light_mode(uint8_t status)
|
||
|
{
|
||
|
api_package_response(API_COMMAND_SET_STROBE_LIGHT_MODE, status, nullptr, 0);
|
||
|
}
|
||
|
|
||
|
__weak void api_notify_get_strobe_light_mode(void) {}
|
||
|
|
||
|
__weak void api_response_get_strobe_light_mode(uint8_t status, uint8_t mode)
|
||
|
{
|
||
|
api_package_response(API_COMMAND_GET_STROBE_LIGHT_MODE, status, &mode, 1);
|
||
|
}
|
||
|
|
||
|
__weak void api_notify_set_volume_level(uint8_t level) {}
|
||
|
|
||
|
void api_response_set_volume_level(uint8_t status)
|
||
|
{
|
||
|
api_response_success(API_COMMAND_SET_VOLUME_LEVEL);
|
||
|
}
|
||
|
|
||
|
__weak void api_notify_get_volume_level(void){}
|
||
|
|
||
|
void api_response_get_volume_level(uint8_t status, uint8_t level)
|
||
|
{
|
||
|
api_package_response(API_COMMAND_GET_VOLUME_LEVEL, status, &level, 1);
|
||
|
}
|
||
|
|
||
|
__weak void api_notify_set_can_type(uint8_t type){}
|
||
|
|
||
|
void api_response_set_can_type(uint8_t status)
|
||
|
{
|
||
|
api_package_response(API_COMMAND_SET_CAN_TYPE, status, nullptr, 0);
|
||
|
}
|
||
|
|
||
|
__weak void api_notify_get_can_type(void){}
|
||
|
|
||
|
void api_response_get_can_type(uint8_t status, uint8_t type)
|
||
|
{
|
||
|
api_package_response(API_COMMAND_GET_CAN_TYPE, status, &type, 1);
|
||
|
}
|
||
|
|
||
|
__weak void api_notify_send_audio_pulse(uint8_t pulse_count){}
|
||
|
|
||
|
void api_response_send_audio_pulse(uint8_t status)
|
||
|
{
|
||
|
api_package_response(API_COMMAND_SEND_AUDIO_PULSE, status, nullptr, 0);
|
||
|
}
|
||
|
|
||
|
void api_upload_data_forwarding(uint8_t type, uint8_t value)
|
||
|
{
|
||
|
uint8_t buffer[2] = { type, value};
|
||
|
|
||
|
api_package(API_FRAME_NOTIFICATION, API_COMMAND_DATA_FORWARDING, buffer, 2);
|
||
|
}
|
||
|
|
||
|
__weak void api_notify_data_forwarding(uint8_t type, uint8_t value) { }
|
||
|
|
||
|
/**
|
||
|
* @brief 升级
|
||
|
*/
|
||
|
static void api_notify_upgrade(uint8_t *buffer, uint16_t length)
|
||
|
{
|
||
|
/* 升级数据包大小, 包编号+包总数+包数据 */
|
||
|
uint16_t pack_length = (((buffer[3] << 8) & 0xFF00) | (buffer[4] & 0xFF)) - 4;
|
||
|
/* 升级包总数 */
|
||
|
upgrade_pack_count = ((buffer[5] << 8) & 0xFF00) | (buffer[6] & 0xFF);
|
||
|
/* 当前下发下来的包序号 */
|
||
|
uint16_t index = ((buffer[7] << 8) & 0xFF00) | (buffer[8] & 0xFF);
|
||
|
|
||
|
if (pack_length > FMC_PAGE_SIZE)
|
||
|
{
|
||
|
api_package_response(API_COMMAND_UPGRADE, 0x02, nullptr, 0);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* 启动升级 初始化 */
|
||
|
if (index == 0x0001)
|
||
|
{
|
||
|
api_upgrade_mode = 1;
|
||
|
upgrade_rx_index = 0;
|
||
|
upgrade_rx_length = 0;
|
||
|
upgrade_pack_index = 0;
|
||
|
}
|
||
|
|
||
|
for (uint16_t i = 0; i < pack_length; i++)
|
||
|
upgrade_rx_buffer[upgrade_rx_index++] = buffer[i + 9];
|
||
|
|
||
|
if (index == upgrade_pack_index + 1)
|
||
|
{
|
||
|
/* 更改ARM接收到的升级包序号 */
|
||
|
upgrade_pack_index = index;
|
||
|
|
||
|
if (upgrade_rx_index >= 1024 || upgrade_pack_index == upgrade_pack_count)
|
||
|
{
|
||
|
/* 写入升级包数据 */
|
||
|
fmc_write_bytes(FMC_ADDRESS_UPGRADE_BUFFER + upgrade_write_index * FMC_PAGE_SIZE, upgrade_rx_buffer, upgrade_rx_index / 4 + (upgrade_rx_index % 4 ? 1 : 0));
|
||
|
|
||
|
upgrade_write_index++;
|
||
|
upgrade_rx_length += upgrade_rx_index;
|
||
|
upgrade_rx_index = 0;
|
||
|
}
|
||
|
|
||
|
/* 通知上位机当前升级包成功接收 */
|
||
|
api_response_success(API_COMMAND_UPGRADE);
|
||
|
|
||
|
if (upgrade_pack_index == upgrade_pack_count)
|
||
|
{
|
||
|
uint8_t upgrade_info[8] = {
|
||
|
0x00, 0x00, 0x00, 0x01,
|
||
|
upgrade_rx_length >> 24 & 0xFF,
|
||
|
upgrade_rx_length >> 16 & 0xFF,
|
||
|
upgrade_rx_length >> 8 & 0xFF,
|
||
|
upgrade_rx_length & 0xFF};
|
||
|
|
||
|
/* 写入需要升级的状态 */
|
||
|
fmc_write_bytes(FMC_ADDRESS_UPGRADE_INFO, upgrade_info, 2);
|
||
|
|
||
|
/* 延时以确保数据完整发送到上位机 */
|
||
|
delay_ms(1000);
|
||
|
|
||
|
/* 重启以完成升级 */
|
||
|
NVIC_SystemReset();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
api_upgrade_mode = 0;
|
||
|
/* 通知上位机丢包 */
|
||
|
api_package_response(API_COMMAND_UPGRADE, 0x03, nullptr, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 按协议方式组包
|
||
|
*
|
||
|
* @param type 帧类型
|
||
|
* @param command 指令代码
|
||
|
* @param data 指令参数
|
||
|
* @param length 指令参数长度
|
||
|
*/
|
||
|
static void api_package(uint8_t type, uint8_t command, uint8_t *data, uint8_t length)
|
||
|
{
|
||
|
uint8_t index = 0;
|
||
|
uint8_t buffer[128] = {0};
|
||
|
uint16_t check_sum = 0;
|
||
|
|
||
|
buffer[index++] = 0xA6;
|
||
|
buffer[index++] = type;
|
||
|
buffer[index++] = command;
|
||
|
buffer[index++] = length >> 8 & 0xFF;
|
||
|
buffer[index++] = length & 0xFF;
|
||
|
|
||
|
for (uint8_t i = 0; i < length; i++)
|
||
|
buffer[index++] = data[i];
|
||
|
|
||
|
for (uint8_t i = 1; i < index; i++)
|
||
|
check_sum += buffer[i];
|
||
|
|
||
|
buffer[index++] = check_sum & 0xFF;
|
||
|
buffer[index++] = 0x77;
|
||
|
|
||
|
api_notify_data_upload(buffer, index);
|
||
|
}
|
||
|
|
||
|
static void api_package_response(uint8_t command, uint8_t status, uint8_t *data, uint16_t length)
|
||
|
{
|
||
|
uint16_t index = 0;
|
||
|
uint8_t buffer[128] = {0};
|
||
|
|
||
|
buffer[index++] = status;
|
||
|
|
||
|
for (uint16_t i = 0; i < length; i++)
|
||
|
buffer[index++] = data[i];
|
||
|
|
||
|
api_package(API_FRAME_RESPONSE, command, buffer, index);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief 按协议方式拆包
|
||
|
*/
|
||
|
void api_unpacking(uint8_t *buffer, uint16_t length)
|
||
|
{
|
||
|
/* 判断校验是否正确 */
|
||
|
uint16_t crc = 0x00;
|
||
|
for (uint16_t i = 1; i < length - 2; i++)
|
||
|
crc += buffer[i];
|
||
|
|
||
|
switch (buffer[2])
|
||
|
{
|
||
|
/* 升级 */
|
||
|
case API_COMMAND_UPGRADE:
|
||
|
api_notify_upgrade(buffer, length);
|
||
|
break;
|
||
|
|
||
|
/* 重启 */
|
||
|
case API_COMMAND_REBOOT:
|
||
|
api_response_success(buffer[2]);
|
||
|
delay_ms(1000);
|
||
|
NVIC_SystemReset();
|
||
|
break;
|
||
|
|
||
|
/* 设置频闪灯工作方式 */
|
||
|
case API_COMMAND_SET_STROBE_LIGHT_MODE:
|
||
|
api_notify_set_strobe_light_mode(buffer[5]);
|
||
|
break;
|
||
|
|
||
|
case API_COMMAND_GET_STROBE_LIGHT_MODE:
|
||
|
api_notify_get_strobe_light_mode();
|
||
|
break;
|
||
|
|
||
|
case API_COMMAND_SET_VOLUME_LEVEL:
|
||
|
api_notify_set_volume_level(buffer[5]);
|
||
|
break;
|
||
|
|
||
|
case API_COMMAND_GET_VOLUME_LEVEL:
|
||
|
api_notify_get_volume_level();
|
||
|
break;
|
||
|
|
||
|
case API_COMMAND_SET_CAN_TYPE:
|
||
|
api_notify_set_can_type(buffer[5]);
|
||
|
break;
|
||
|
|
||
|
case API_COMMAND_GET_CAN_TYPE:
|
||
|
api_notify_get_can_type();
|
||
|
break;
|
||
|
|
||
|
case API_COMMAND_SEND_AUDIO_PULSE:
|
||
|
api_notify_send_audio_pulse(buffer[5]);
|
||
|
break;
|
||
|
|
||
|
case API_COMMAND_DATA_FORWARDING:
|
||
|
api_notify_data_forwarding(buffer[5], buffer[6]);
|
||
|
break;
|
||
|
}
|
||
|
}
|