#include #include "app/iap.h" #include "app/nv_storage.h" #include "bsp/fmc_flash.h" static int iap_write_image(uint8_t *data, int len); static int iap_check_image(uint8_t *data, int len); void _reboot_timer_handler(shark_timer_t *t); void iap_read_string(can_frame_t *frame); static u8 _write_success = 0; static int _write_position = 0; static shark_timer_t _reboot_timer = {.handler = _reboot_timer_handler,}; void process_iap_message(can_frame_t *frame, int len){ uint8_t *data = NULL; int data_len = 0; switch(frame->key) { case CAN_KEY_IAP_ENTER: if (gd32_flash_size() < 128 * 1024){ wdog_reload(); fmc_iap_write_magic(0xFFFFFFFF); NVIC_SystemReset(); while(1); } protocol_send_ack(frame->head.can_addr, frame->key, 0); break; case CAN_KEY_IAP_BEGIN: if (gd32_flash_size() < 128 * 1024){ protocol_send_ack(frame->head.can_addr, frame->key, 1); break; } fmc_write_image_begin(); _write_position = 0; _write_success = 0; protocol_send_ack(frame->head.can_addr, frame->key, 0); break; case CAN_KEY_IAP_WRITE: _write_success = 0; data_len = iap_write_image(frame->data, len); data = frame->data; break; case CAN_KEY_IAP_CHECK: fmc_write_image_end(); data_len = iap_check_image(frame->data, len); data = frame->data; break; case CAN_KEY_IAP_BOOT: if (_write_success) { NVIC_SystemReset(); while(1); } else { protocol_send_ack(frame->head.can_addr, frame->key, 0); } break; case CAN_KEY_IAP_STAT: protocol_send_ack(frame->head.can_addr, frame->key, 0); break; case CAN_EEY_IAP_READ_STRING: iap_read_string(frame); break; case CAN_KEY_REBOOT: if (len == 4 && shark_decode_u32(frame->data) == SHARK_IAP_MAGIC_SUCCESS) { fmc_iap_write_magic(0xFFFFFFFF); } shark_timer_post(&_reboot_timer, 100); protocol_send_ack(frame->head.can_addr, frame->key, 1); break; case CAN_KET_ERASE_NV: nv_erase(); shark_timer_post(&_reboot_timer, 100); protocol_send_ack(frame->head.can_addr, frame->key, 1); break; } if (data != NULL && data_len > 0){ protocol_send_bms_info(frame->head.can_addr, frame->key, frame->data, data_len); } } void _reboot_timer_handler(shark_timer_t *t){ NVIC_SystemReset(); } static int iap_write_image(uint8_t *data, int len){ int w_pos = shark_decode_u24(data); if (w_pos == _write_position && len > 3) { fmc_write_image_continue(data + 3, len - 3); _write_position += len - 3; } data[0] = 0; shark_encode_u24(data+1, _write_position); return 4; } void iap_read_string(can_frame_t *frame) { uint8_t buff[64]; const char *text; uint32_t addr; uint32_t len; addr = ((uint32_t) frame->data[2]) << 16 | ((uint32_t) frame->data[1]) << 8 | frame->data[0]; text = (const char *) (0x08000000 + addr); len = strlen(text); if (len > (sizeof(buff)-4)) { len = sizeof(buff) - 4; } buff[0] = 0; memcpy(buff+1, frame->data, 3); memcpy(buff + 4, text, len); protocol_send_bms_info(frame->head.can_addr, frame->key, buff, len + 4); } static int iap_check_image(uint8_t *data, int len) { uint32_t size, checksum; size = shark_decode_u24(data); checksum = shark_decode_u32(data + 3); uint32_t d_checksum = shark_iap_checksum_init(); d_checksum = shark_iap_checksum_put(d_checksum, (const u8 *)fmc_iap_image_addr(), size); d_checksum = shark_iap_checksum_finish(d_checksum); if (checksum != d_checksum) { data[0] = 1; return 1; } fmc_write_magic(size, checksum, SHARK_IAP_MAGIC_FLASH); _write_success = 1; data[0] = 0; return 1; }