Selaa lähdekoodia

can驱动与cli功能调试

樊春春 6 kuukautta sitten
vanhempi
sitoutus
05cd25037d
31 muutettua tiedostoa jossa 3463 lisäystä ja 280 poistoa
  1. 3 1
      CMakeLists.txt
  2. 11 3
      app/app_task.c
  3. 174 0
      cli/cli.c
  4. 35 0
      cli/cli.h
  5. 258 0
      cli/cli_inter_actor.c
  6. 18 0
      cli/cli_inter_actor.h
  7. 532 0
      cli/cli_inter_preter.c
  8. 50 0
      cli/cli_inter_preter.h
  9. 1 1
      cmsis/system_stm32f4xx.c
  10. 678 0
      dev/dev_can.c
  11. 28 0
      dev/dev_can.h
  12. 1 0
      dev/dev_conf.h
  13. 264 0
      dev/dev_iap.c
  14. 107 0
      dev/dev_iap.h
  15. 166 113
      hal/hal_can.c
  16. 11 10
      hal/hal_can.h
  17. 3 1
      hal/hal_conf.h
  18. 173 0
      hal/hal_flash.c
  19. 69 0
      hal/hal_flash.h
  20. 25 0
      hal/hal_systick.c
  21. 6 1
      hal/hal_systick.h
  22. 359 0
      hal/hal_uart.c
  23. 41 0
      hal/hal_uart.h
  24. 0 137
      hal/hal_uart1.c
  25. 0 11
      hal/hal_uart1.h
  26. 179 0
      hal/platform_queue.c
  27. 81 0
      hal/platform_queue.h
  28. 104 0
      hal/queue.c
  29. 70 0
      hal/queue.h
  30. 1 1
      project/gcc/STM32F417IG_FLASH.ld
  31. 15 1
      user/main.c

+ 3 - 1
CMakeLists.txt

@@ -7,7 +7,7 @@ enable_language(C CXX ASM)
 message("Build type: " ${CMAKE_BUILD_TYPE})
 
 # 编译脚本设置
-set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD 99)
 set(CMAKE_C_STANDARD_REQUIRED ON)
 set(CMAKE_C_EXTENSIONS ON)
 set(CMAKE_CXX_STANDARD 20)
@@ -33,6 +33,7 @@ file(GLOB_RECURSE C_SRCS
         ${CMAKE_CURRENT_SOURCE_DIR}/libraries/STM32F4xx_StdPeriph_Driver/src/*.c
         ${CMAKE_CURRENT_SOURCE_DIR}/packages/multi_button/multi_button.c
         ${CMAKE_CURRENT_SOURCE_DIR}/app/*.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/cli/*.c
         ${CMAKE_CURRENT_SOURCE_DIR}/dev/*.c
         ${CMAKE_CURRENT_SOURCE_DIR}/hal/*.c
         )
@@ -54,6 +55,7 @@ set(INC_C_DIRS
         ${CMAKE_CURRENT_SOURCE_DIR}/libraries/STM32F4xx_StdPeriph_Driver/inc
         ${CMAKE_CURRENT_SOURCE_DIR}/packages/multi_button
         ${CMAKE_CURRENT_SOURCE_DIR}/app
+        ${CMAKE_CURRENT_SOURCE_DIR}/cli
         ${CMAKE_CURRENT_SOURCE_DIR}/dev
         ${CMAKE_CURRENT_SOURCE_DIR}/hal
         )

+ 11 - 3
app/app_task.c

@@ -1,11 +1,16 @@
 #include "app_task.h"
 #include "app_eeprom.h"
+#include "cli.h"
 #include "dev_at24cxx.h"
+#include "dev_can.h"
+#include "hal_systick.h"
 #include <stdint.h>
 #include <stdio.h>
 
 uint8_t beep_status = 1;
 
+static uint32_t systick_ms_clock = 0;
+
 /*----------------------------------------
 * @函数名: app_task_5ms
 * @描述:
@@ -18,10 +23,11 @@ uint8_t beep_status = 1;
 * 作者     创建时间          操作
  樊春春   2023/11/13    Create/Modify
 ----------------------------------------*/
-static void
-app_task_5ms(void)
+static void app_task_5ms(void)
 {
     dev_key_button_task();
+    can_process();
+    cli_loop();
 }
 
 /*----------------------------------------
@@ -152,7 +158,8 @@ static void app_task_1000ms(void)
     dev_led_on_off(1, state);
     state = !state;
     dev_led_on_off(0, state);
-
+    systick_ms_clock++;
+    // printf("debug\r\n");
     // dev_led_on_off(1, !state);
 }
 /*----------------------------------------
@@ -176,6 +183,7 @@ void SysTick_Handler(void)
     dev_task_clock();
     dev_systick_decrement();
     dev_systick_increase();
+    systick_handler();
 }
 
 void app_task_schdule(void)

+ 174 - 0
cli/cli.c

@@ -0,0 +1,174 @@
+#include "cli.h"
+#include "cli_inter_actor.h"
+#include "cli_inter_preter.h"
+#include "hal_flash.h"
+#include <stdint.h>
+#include <stdio.h>
+// #include "hal_led.h"
+// #include "hal_usart.h"
+// #include <stdio.h>
+
+#define CLI_ANSI_ENABLE 1
+
+void command_help(void);
+void command_version(void);
+void command_clear(void);
+void command_reset(void);
+void command_ps(void);
+void command_led_control(void);
+
+command_entry main_table[] = {
+    CLI_COMPONENTS_LIST
+
+        command_entry_action_with_detail("help", command_help, "", "help infomation", (const char *const *)NULL),
+    command_entry_action_with_detail("version", command_version, "", "show version", (const char *const *)NULL),
+    command_entry_action_with_detail("reset", command_reset, "", "reset system", (const char *const *)NULL),
+    command_entry_action_with_detail("clear", command_clear, "", "clear screen", (const char *const *)NULL),
+    command_entry_action_with_detail("ps", command_ps, "", "print string", (const char *const *)NULL),
+
+    command_entry_terminator()};
+
+command_entry command_debug_table[] = {
+    command_entry_action_with_detail("led", command_led_control, "u", "led_control", (const char *const *)0),
+    command_entry_terminator()};
+
+uint8_t led_states;
+void    command_led_control(void)
+{
+    if (cli_ipt_arg_list[0][0] == 1)
+    {
+        // LED2;
+        led_states = 1;
+    }
+    else if (cli_ipt_arg_list[0][0] == 2)
+    {
+        led_states = 2;
+    }
+    else
+    {
+        led_states = 0;
+    }
+}
+
+command_entry command_ble_table[] = {
+    command_entry_terminator()};
+
+command_entry command_eeprom_table[] = {
+    command_entry_terminator()};
+
+void command_flash_read(void)
+{
+    uint32_t read_byte     = 0;
+    uint16_t read_buf[100] = {0};
+    if (cli_ipt_arg_list[0][0] == 1)
+    {
+        fmc_clear_flag_star();
+        read_byte = fmc_read_byte(cli_ipt_arg_list[1][0]);
+        fmc_clear_flag_end();
+        CLI_PRINTF("%x\r\n", read_byte);
+    }
+    else if (cli_ipt_arg_list[0][0] == 2)
+    {
+        fmc_clear_flag_star();
+        read_byte = fmc_read_half_word(cli_ipt_arg_list[1][0]);
+        fmc_clear_flag_end();
+        CLI_PRINTF("%x\r\n", read_byte);
+    }
+    else if (cli_ipt_arg_list[0][0] == 3)
+    {
+        fmc_clear_flag_star();
+        read_byte = fmc_read_n_half_word(cli_ipt_arg_list[1][0], read_buf, 10);
+        fmc_clear_flag_end();
+        CLI_PRINTF("%x\r\n", read_buf);
+    }
+    else
+    {
+        led_states = 0;
+    }
+}
+
+void command_flash_write(void)
+{
+    uint32_t read_byte     = 0;
+    uint16_t read_buf[100] = {0};
+    if (cli_ipt_arg_list[0][0] == 1)
+    {
+        fmc_clear_flag_star();
+        read_buf[0] = cli_ipt_arg_list[2][0] >> 8;
+        read_buf[1] = cli_ipt_arg_list[2][0];
+        read_byte   = fmc_erase_pages(cli_ipt_arg_list[1][0], cli_ipt_arg_list[3][0]);
+        CLI_PRINTF("%x\r\n", read_byte);
+        read_byte = fmc_write_n_half_word(cli_ipt_arg_list[1][0], read_buf, cli_ipt_arg_list[3][0]);
+        fmc_clear_flag_end();
+        CLI_PRINTF("%x\r\n", read_byte);
+    }
+    // else if (cli_ipt_arg_list[0][0] == 2)
+    // {
+    //     fmc_clear_flag_star();
+    //     read_byte = fmc_read_half_word(cli_ipt_arg_list[1][0]);
+    //     fmc_clear_flag_end();
+    //     CLI_PRINTF("%x\r\n", read_byte);
+    // }
+    // else if (cli_ipt_arg_list[0][0] == 3)
+    // {
+    //     fmc_clear_flag_star();
+    //     read_byte = fmc_read_n_half_word(cli_ipt_arg_list[1][0], read_buf, 10);
+    //     fmc_clear_flag_end();
+    //     CLI_PRINTF("%x\r\n", read_buf);
+    // }
+}
+
+command_entry command_flash_table[] = {
+    command_entry_action_with_detail("r", command_flash_read, "uu", "command_flash_read", (const char *const *)0),
+    command_entry_action_with_detail("w", command_flash_write, "uuuu", "command_flash_write", (const char *const *)0),
+    command_entry_terminator()};
+
+void command_version(void)
+{
+    CLI_PRINTF("version 3.0.16. CC by[" __DATE__ " " __TIME__ "] \r\n");
+}
+
+void command_reset(void)
+{
+    cli_reset();
+}
+
+void command_help(void)
+{
+    print_entry(main_table);
+}
+
+void command_clear(void)
+{
+#if CLI_ANSI_ENABLE == 1
+    CLI_PRINTF("%c[2J", '\033');
+    CLI_PRINTF("%c[41A", '\033');
+#else
+    for (uint8_t i = 0; i < 40; i++)
+    {
+        CLI_PRINTF("# \r\n");
+    }
+#endif
+}
+
+void command_ps(void)
+{
+    CLI_PRINTF("%s\r\n", &cli_ipt_arg_list[0][0]);
+}
+
+void cli_init(void)
+{
+    // CLI_COMPONENTS_INIT
+}
+
+int  ch = 0;
+void cli_loop(void)
+{
+    // CLI_COMPONENTS_LOOP
+
+    ch = getchar();
+    if (ch != -1)
+    {
+        cli_itt_input(CLI_CHL_COM, ch);
+    }
+}

+ 35 - 0
cli/cli.h

@@ -0,0 +1,35 @@
+#ifndef __CLI_H
+#define __CLI_H
+
+#include "cli_inter_actor.h"
+#include "cli_inter_preter.h"
+#include <stm32f4xx.h>
+
+#define cli_reset() NVIC_SystemReset()
+
+extern void light_lib_cli_input(void);
+extern void light_lib_cli_loop(void);
+
+extern command_entry command_debug_table[];
+extern command_entry command_ble_table[];
+extern command_entry command_eeprom_table[];
+extern command_entry command_flash_table[];
+
+#define CLI_COMPONENTS_LIST                                                     \
+    command_entry_sub_menu("debug", command_debug_table, "debug_table"),        \
+        command_entry_sub_menu("ble", command_ble_table, "ble_table"),          \
+        command_entry_sub_menu("eeprom", command_eeprom_table, "eeprom_table"), \
+        command_entry_sub_menu("flash", command_flash_table, "flash_table"),
+
+#define CLI_COMPONENTS_INIT \
+    // light_lib_cli_init();
+
+#define CLI_COMPONENTS_LOOP \
+    // light_lib_cli_loop();
+
+extern command_entry main_table[];
+
+extern void cli_init(void);
+extern void cli_loop(void);
+
+#endif // __CLI_H

+ 258 - 0
cli/cli_inter_actor.c

@@ -0,0 +1,258 @@
+#include "cli_inter_actor.h"
+#include "cli.h"
+#include "cli_inter_preter.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/_types.h>
+
+#define CLI_ITT_ANSI_ENABLE O
+
+static char          cli_itt_list[CLI_ITT_LIST_NUM][CLI_ITT_LIST_LEN] = {0};
+static char          cli_itt_list_hint_index = 0, cli_itt_list_his_cnt = 0;
+static unsigned char cli_itt_list_index = 0;
+unsigned char        g_cli_chl          = CLI_CHL_COM;
+
+void eoch(char c)
+{
+    if (g_cli_chl == CLI_CHL_COM)
+        CLI_PRINTF("%c", c);
+}
+
+void cli_itt_list_add(unsigned char *item)
+{
+    strcpy(cli_itt_list[cli_itt_list_index], (const char *)item);
+    cli_itt_list_index = (cli_itt_list_index + 1) % CLI_ITT_LIST_NUM;
+    cli_itt_list_his_cnt++;
+    if (cli_itt_list_his_cnt >= CLI_ITT_LIST_NUM)
+        cli_itt_list_his_cnt = CLI_ITT_LIST_NUM;
+}
+
+unsigned char diff_num(unsigned char a, unsigned char b)
+{
+    return a > b ? a - b : b - a;
+}
+
+unsigned char cli_itt_list_index_last(void)
+{
+    unsigned char index;
+    index = (cli_itt_list_hint_index + CLI_ITT_LIST_NUM - 1) % CLI_ITT_LIST_NUM;
+
+    if ((index != cli_itt_list_index) && (diff_num(cli_itt_list_hint_index, cli_itt_list_index) < cli_itt_list_his_cnt))
+    {
+        cli_itt_list_hint_index = index;
+    }
+    return cli_itt_list_hint_index;
+}
+
+unsigned char cli_itt_list_index_next(void)
+{
+    unsigned char index;
+    index = (cli_itt_list_hint_index + 1) % CLI_ITT_LIST_NUM;
+
+    if ((index != cli_itt_list_index) && (diff_num(cli_itt_list_hint_index, cli_itt_list_index) < cli_itt_list_his_cnt))
+    {
+        cli_itt_list_hint_index = index;
+    }
+    else
+    {
+        // cli_itt_list_hint_index = cli_itt_list_index;
+    }
+    return cli_itt_list_hint_index;
+}
+
+void clear_line(void)
+{
+    CLI_PRINTF("\r");
+    for (char i = 0; i < CLI_ITT_LIST_LEN; i++)
+    {
+        CLI_PRINTF(" ");
+    }
+    CLI_PRINTF("\r");
+}
+
+void clear_line_ansi(unsigned int cursor)
+{
+    CLI_PRINTF("%c[%dD", '\033', cursor);
+    CLI_PRINTF("%c[K", '\033');
+}
+
+void cli_printf(char *msg, ...)
+{
+    va_list vl;
+    // char    s[10];
+    if (g_cli_chl == CLI_CHL_COM)
+    {
+        va_start(vl, msg);
+        // vsprintf(s, msg, vl);
+        vprintf(msg, vl);
+        va_end(vl);
+    }
+    else
+    {
+#ifdef TELNET
+        va_start(vl, msg);
+        telnet_esp32_vprintf(msg, vl);
+        va_end(vl);
+#endif
+    }
+}
+
+void cli_itt_input(CLI_CHL chl, char c)
+{
+    // static unsigned char enter = 0;
+    static unsigned char dir = 0, ch;
+    static char          item[CLI_ITT_LIST_LEN];
+    static unsigned char item_index = 0;
+    int                  res;
+    char                 hint[CLI_ITT_LIST_LEN];
+
+    ch = (unsigned char)c;
+    // CLI_PRINTF("%02x", ch);
+    // return;
+
+    switch (ch)
+    {
+    case '\r':
+#define OS_MAC
+#ifdef OS_MAC:
+        item[item_index] = '\0';
+        if (g_cli_chl == CLI_CHL_COM)
+            CLI_PRINTF("\r\n");
+        if (strlen(item) != 0)
+        {
+            cli_itt_list_add((unsigned char *)item);
+            cli_itt_list_hint_index = cli_itt_list_index;
+        }
+        command_entry_match(main_table, item);
+        memset(item, 0, CLI_ITT_LIST_LEN);
+        // emter = 0;
+        item_index = 0;
+        break;
+#else
+        // enter = 1;
+        return;
+#endif
+    case '\n':
+        item[item_index] = '\0';
+        if (g_cli_chl == CLI_CHL_COM)
+            CLI_PRINTF("\r\n");
+        if (strlen(item) != 0)
+        {
+            cli_itt_list_add((unsigned char *)item);
+            cli_itt_list_hint_index = cli_itt_list_index;
+        }
+        command_entry_match(main_table, item);
+        memset(item, 0, CLI_ITT_LIST_LEN);
+        // emter = 0;
+        item_index = 0;
+        break;
+    case '\t': // Tab
+        res = command_entry_hint(main_table, item, hint);
+        if (res == 0)
+        {
+        }
+        else if (res == 1)
+        {
+            CLI_PRINTF("\r\n%s\r\n# %s", hint, item);
+        }
+        else if (res == 2)
+        {
+#if CLI_ITT_ANSI_ENABLE == 0
+            clear_line();
+#else
+            clear_line_ansi(item_index);
+#endif
+            CLI_PRINTF("\r# %s", hint);
+            strcpy(item, hint);
+            item_index = strlen(item);
+        }
+        else if (res == 3)
+        {
+#if CLI_ITT_ANSI_ENABLE == 0
+            clear_line();
+#else
+            clear_line_ansi(item_index);
+#endif
+            CLI_PRINTF("\r# %s", hint);
+            strcpy(item, hint);
+            item_index = strlen(item);
+        }
+        else
+        {
+        }
+        break;
+    case 0x1b: // ESC/UP-1
+        dir = 1;
+        break;
+    case 0x5b:
+        dir = 2;
+        break;
+    // case 0x1b: // ESC
+    //     memcpy(item, 0, sizeof(item));
+    //     item_index = 0;
+    //     CLI_PRINTF("\r%s", item);
+    //     break;
+    case 8: // BackSpace
+        if (item_index > 0)
+        {
+            item_index--;
+#if CLI_ITT_ANSI_ENABLE == 1
+            CLI_PRINTF("%c[1D", '\033');
+            CLI_PRINTF("%c[K", '\033');
+#endif
+            item[item_index] = '\0';
+#if CLI_ITT_ANSI_ENABLE == 0
+            clear_line();
+            CLI_PRINTF("\r# %s", item);
+#endif
+            break;
+        }
+    default:
+        if ((ch == 0x41 || ch == 0x42) && (dir == 2))
+        {
+            if (ch == 0x41) // UP
+            {
+                strcpy(item, cli_itt_list[cli_itt_list_index_last()]);
+            }
+            else // DOWN
+            {
+                if (cli_itt_list_hint_index == cli_itt_list_index)
+                {
+                }
+                else if (((cli_itt_list_hint_index + CLI_ITT_LIST_NUM + 1) % CLI_ITT_LIST_NUM) == cli_itt_list_index)
+                {
+                    cli_itt_list_hint_index = cli_itt_list_index;
+                    memset(item, 0, CLI_ITT_LIST_NUM);
+                }
+                else
+                {
+                    strcpy(item, cli_itt_list[cli_itt_list_index_next()]);
+                }
+            }
+
+#if CLI_ITT_ANSI_ENABLE == 1
+            clear_line_ansi(item_index);
+#endif
+            item_index = strlen(item);
+#if CLI_ITT_ANSI_ENABLE == 0
+            clear_line();
+#endif
+            CLI_PRINTF("\r# %s", item);
+            dir = 0;
+            break;
+        }
+
+        if ((ch == 0x43 || ch == 0x44) && (dir == 2))
+        {
+            break;
+        }
+
+        eoch(c);
+
+        if (item_index <= (CLI_ITT_LIST_LEN - 2))
+        {
+            item[item_index++] = c;
+        }
+        break;
+    }
+}

+ 18 - 0
cli/cli_inter_actor.h

@@ -0,0 +1,18 @@
+#ifndef __CLI_INTER_ACTOR_H
+#define __CLI_INTER_ACTOR_H
+
+#include "cli_inter_preter.h"
+
+#define CLI_ITT_LIST_NUM 10 // 历史记录命令个数
+
+#define CLI_ITT_LIST_LEN CLI_IPT_ARG_STR_LEN // 每个命令的最大长度
+
+typedef enum
+{
+    CLI_CHL_COM = 0,
+    CLI_CHL_TELNET,
+} CLI_CHL;
+
+extern void cli_itt_input(CLI_CHL chl, char c);
+
+#endif // __CLI_INTERACTOR_H

+ 532 - 0
cli/cli_inter_preter.c

@@ -0,0 +1,532 @@
+#include "cli_inter_preter.h"
+
+static char  arg_str_list[CLI_IPT_ARG_NUM][CLI_IPT_ARG_STR_LEN];
+unsigned int cli_ipt_arg_list[CLI_IPT_ARG_NUM][CLI_IPT_ARG_LEN];
+
+void print_main_menu(command_entry *main_table);
+
+void array_map_input_to_byte(unsigned char *b, unsigned int *i, unsigned int len)
+{
+    if (len > CLI_IPT_ARG_LEN)
+        return;
+
+    for (unsigned char index = 0; index < len; index++)
+    {
+        b[index] = i[index];
+    }
+}
+
+int len_of_menu(command_entry *entry)
+{
+    int i, len = 0;
+    for (i = 0; i < CLI_IPT_ENTRY_NUM_MAX; i++)
+    {
+        if (entry->action == NULL && entry->arg_desp == NULL && entry->arg_type == NULL && entry->desp == NULL && entry->name == NULL)
+        {
+            return len;
+        }
+        else
+        {
+            len++;
+            entry++;
+        }
+    }
+    return 0;
+}
+
+int cmd_to_param(const char *cmd, char *param, int param_len_max)
+{
+    int   state = 0, row = 0;
+    char *base;
+
+    base = param;
+
+    while (*cmd != '\0')
+    {
+        if (*cmd != ' ')
+        {
+            if (state == 2 || state == 0)
+            {
+                row++;
+                if (row > CLI_IPT_ARG_NUM)
+                    return row;
+                param = base + param_len_max * (row - 1);
+                memset(param, 0, param_len_max);
+                state = 1;
+            }
+            state  = 1;
+            *param = *cmd;
+            param++;
+            if (param > base + param_len_max * (row)-1)
+            {
+                return 0;
+            }
+        }
+        else
+        {
+            if (state == 1)
+            {
+                state = 2;
+            }
+        }
+        cmd++;
+    }
+    return row;
+}
+
+void print_entry(command_entry *entry)
+{
+    int len, i;
+    len = len_of_menu(entry);
+    for (i = 0; i < len; i++)
+    {
+        if (entry[i].action != NULL)
+        {
+            CLI_PRINTF("%-30s- (%s)%s\r\n", entry[i].name, entry[i].arg_type, entry[i].desp);
+        }
+        else
+        {
+            CLI_PRINTF("%-30s- (sub_menu)%s\r\n", entry[i].name, entry[i].desp);
+        }
+    }
+}
+
+void print_arg_desp(command_entry *entry)
+{
+    int   len, i;
+    char *d[] = {"<one-byte 1 or 0x01>", "<two-byte 1 or 0x01>", "<four-byte 1 or 0x01>", "<string \"abc\" >", "<array, {1,2,3}>"};
+    char *desp;
+
+    len = strlen(entry->arg_type);
+
+    if (len == 0)
+    {
+        return;
+    }
+    for (i = 0; i < len; i++)
+    {
+        if (entry->arg_type[i] == 'u')
+            desp = d[0];
+        else if (entry->arg_type[i] == 'v')
+            desp = d[1];
+        else if (entry->arg_type[i] == 'w')
+            desp = d[2];
+        else if (entry->arg_type[i] == 's')
+            desp = d[3];
+        else if (entry->arg_type[i] == 'a')
+            desp = d[4];
+        else
+            desp = "";
+
+        if (entry->arg_desp == NULL)
+        {
+            CLI_PRINTF("arg%d   -   %c%s\r\n", i, entry->arg_type[i], desp);
+        }
+        else
+        {
+            CLI_PRINTF("arg%d   -   %c%s %s\r\n", i, entry->arg_type[i], desp, entry->arg_desp[i]);
+        }
+    }
+}
+
+static unsigned char hex_to_int(unsigned char ch)
+{
+    return ch - (ch >= 'a' ? 'a' - 10 : (ch >= 'A' ? 'A' - 10 : (ch <= '9' ? '0' : 0)));
+}
+
+static unsigned int string_to_unsigned_int(char *str, unsigned int *array, int param_len_max)
+{
+    int result = 0;
+    int base   = 10;
+    int i;
+    int length;
+    int pflag = 0;
+
+    length = strlen(str);
+
+    if (length == 0)
+        return 1;
+    if (str[0] == '-')
+        pflag = 1;
+
+    for (i = 0; i < length; i++)
+    {
+        unsigned char next = str[i];
+        if (i == 0 && next == '-')
+        {
+            // do noting
+        }
+        else if ((next == 'x' || next == 'X') && result == 0 && (i == 1 || i == 2))
+        {
+            base = 16;
+        }
+        else
+        {
+            unsigned char value = hex_to_int(next);
+            if (value < base)
+            {
+                result = result * base + value;
+            }
+            else
+            {
+                return 1;
+            }
+        }
+    }
+    if (pflag == 1)
+    {
+        result = ~result + 1;
+    }
+    *array = result;
+    return 0;
+}
+
+//"s" "abc"
+// "str\r\n"
+int string_to_s(char *str, unsigned int *array, int param_len_max)
+{
+    int   i = 0, j = 0; /*, bs=0*/
+    char *ps = (char *)array;
+
+    if (str[0] != '"')
+        return 1;
+
+    j = 0;
+
+    for (i = 0; str[i + 1] != '"';)
+    {
+        if (str[i + 1] == '\\')
+        {
+            if (str[i + 1 + 2] == 'n')
+            {
+                ps[j] = '\n';
+                i++;
+            }
+            else if (str[i + 1 + 2] == 'r')
+            {
+                ps[j] = '\r';
+                i++;
+            }
+            else
+            {
+                ps[j] = '\\';
+            }
+        }
+        else
+        {
+            ps[j] = str[i + 1];
+        }
+
+        j++;
+
+        if (j + 1 > param_len_max)
+        {
+            return 1;
+        }
+        i++;
+    }
+    ps[j] = 0;
+
+    return 0;
+}
+
+// "a" {1,2,3}
+int string_to_a(char *str, unsigned int *array, int param_len_max)
+{
+    int  i, index = 0, count = 0, flag = 0;
+    char s[CLI_IPT_ARG_LEN] = {0};
+
+    if (str[0] != '{')
+        return 1;
+
+    for (i = 0; str[i] != '\0'; i++)
+    {
+        if (str[i] == '{')
+        {
+            index = 0;
+        }
+        else if (str[i] == ',')
+        {
+            s[index] = 0;
+            if (string_to_unsigned_int(s, array + count, CLI_IPT_ARG_LEN) != 0)
+                return 1;
+            index = 0;
+            count++;
+        }
+        else if (str[i] == '}')
+        {
+            flag     = 1;
+            s[index] = 0;
+            if (string_to_unsigned_int(s, array + count, CLI_IPT_ARG_LEN) != 0)
+                return 1;
+        }
+        else
+        {
+            s[index++] = str[i];
+        }
+    }
+    if (flag == 0)
+        return 1;
+
+    return 0;
+}
+
+int command_action_exec(command_entry *entry, char *param, int param_len_max)
+{
+    int len, i, res = 0;
+    len = strlen(entry->arg_type);
+
+    // CLI_PRINTF("arg is:");
+
+    for (i = 0; i < len; i++)
+    {
+        if (entry->arg_type[i] == 'u')
+            res = string_to_unsigned_int(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN);
+        else if (entry->arg_type[i] == 'v')
+            res = string_to_unsigned_int(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN);
+        else if (entry->arg_type[i] == 'w')
+            res = string_to_unsigned_int(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN);
+        else if (entry->arg_type[i] == 's')
+            res = string_to_s(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN * sizeof(unsigned int));
+        else if (entry->arg_type[i] == 'a')
+            res = string_to_a(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN);
+        else
+        {
+        }
+
+        if (res == 1)
+        {
+            return res;
+        }
+        // CLI_PRINTF("%d ", cli_ipt_arg_list[i][0]);
+    }
+
+    // CLI_PRINTF("\r\n");
+    return res;
+}
+
+int stricmp(const char *a, const char *b)
+{
+    int i, len;
+    if (strlen(a) != strlen(b))
+        return 1;
+
+    len = strlen(a);
+    for (i = 0; i < len; i++)
+    {
+        if (toupper((unsigned int)a[i]) != toupper((unsigned int)b[i]))
+        {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+int command_match(const char *cmd, int param_len_max, int num, command_entry **entry_in, command_entry **entry_out)
+{
+    int i, len, res = 0;
+    len = len_of_menu(*entry_in);
+
+    for (i = 0; i < len; i++)
+    {
+        if (stricmp(cmd, (*entry_in)->name) == 0)
+        {
+            if ((*entry_in)->action != NULL)
+            {
+                *entry_out = *entry_in;
+                res        = 1;
+            }
+            else
+            {
+                *entry_out = (command_entry *)((*entry_in)->arg_type);
+                res        = 2;
+            }
+            break;
+        }
+        (*entry_in)++;
+    }
+
+    if (i == len)
+    {
+        res = 0;
+    }
+    return res;
+}
+
+int command_entry_match(command_entry *main_table, const char *cmd)
+{
+    static command_entry *ein, *eout, *ehint;
+    int                   num, res = 2;
+    char                 *plist;
+
+    ein   = main_table;
+    eout  = (command_entry *)NULL;
+    ehint = ein;
+
+    memset(arg_str_list, 0, sizeof(arg_str_list));
+    num = cmd_to_param(cmd, (char *)arg_str_list, CLI_IPT_ARG_STR_LEN);
+
+    if (num == 0)
+    {
+        // print_main_menu(main_table);
+        CLI_PRINTF("# ");
+        return 0;
+    }
+
+    plist = (char *)arg_str_list;
+    while (res == 2)
+    {
+        res = command_match((const char *)plist, CLI_IPT_ARG_STR_LEN, num, &ein, &eout);
+
+        if (res == 0)
+        {
+            // printf("commands or params unmatched!\r\n");
+            print_entry(ehint);
+            CLI_PRINTF("# ");
+            return 0;
+        }
+        else if (res == 1)
+        {
+            if (command_action_exec(eout, plist + CLI_IPT_ARG_STR_LEN, CLI_IPT_ARG_STR_LEN) == 0)
+            {
+                eout->action();
+            }
+            else
+            {
+                // printf("argument error!\r\n");
+                print_arg_desp(eout);
+            }
+        }
+        else
+        {
+            plist = plist + CLI_IPT_ARG_STR_LEN;
+            ein   = eout;
+            ehint = ein;
+        }
+    }
+    CLI_PRINTF("# ");
+    return 1;
+}
+
+void print_main_menu(command_entry *main_table)
+{
+    print_entry(main_table);
+}
+
+int case_chg(char a)
+{
+    if (a >= 'A' && a <= 'Z')
+        a = a - 'A' + 'a';
+
+    return a;
+}
+
+int str_include(const char *s, const char *str)
+{
+    int i;
+
+    if (strlen(s) > strlen(str))
+        return -1;
+
+    for (i = 0; i < strlen(s); i++)
+    {
+        if (case_chg(s[i]) != case_chg(str[i]))
+            return -1;
+    }
+
+    return 0;
+}
+
+int command_entry_hint(command_entry *main_table, const char *cmd, char *out)
+{
+
+    static command_entry *ein, *eout;
+    int                   num, res = 2, i, len, cnt;
+    char                 *plist, tmp[CLI_IPT_ARG_STR_LEN];
+
+    ein  = main_table;
+    eout = ein;
+
+    memset(arg_str_list, 0, sizeof(arg_str_list));
+    num = cmd_to_param(cmd, (char *)arg_str_list, CLI_IPT_ARG_STR_LEN);
+
+    if (num == 0)
+    {
+        // print_main_menu(main_table);
+        // CLI_PRINTF("# ");
+        return 0;
+    }
+
+    plist = (char *)arg_str_list;
+    while (res == 2)
+    {
+        res = command_match((const char *)plist, CLI_IPT_ARG_STR_LEN, num, &ein, &eout);
+
+        if (res == 0)
+        {
+            if (strlen(plist) == 0)
+            {
+                if (cmd[strlen(cmd) - 1] != ' ') //"s1" "s2"
+                {
+                    strcpy(out, cmd);
+                    strcat(out, " ");
+                    return 3;
+                }
+            }
+
+            len = len_of_menu(eout);
+            cnt = 0;
+            strcpy(out, "");
+
+            for (i = 0; i < len; i++)
+            {
+                if (str_include(plist, eout[i].name) == 0)
+                {
+                    cnt++;
+                    strcpy(out, eout[i].name);
+                    strcat(out, " ");
+                }
+            }
+            if (cnt == 1)
+            {
+                strcpy(tmp, out);
+                strcpy(out, "");
+                for (i = 0; i < (num - 1); i++)
+                {
+                    strcat(out, arg_str_list[i]);
+                    strcat(out, " ");
+                }
+                strcat(out, tmp);
+                return 2;
+            }
+            else
+            {
+                return 1;
+            }
+        }
+        else if (res == 1) // action
+        {
+            strcpy(out, "");
+            for (i = 0; i < num; i++)
+            {
+                strcat(out, arg_str_list[i]);
+                strcat(out, " ");
+
+                if (strlen(out) >= ((unsigned int)CLI_IPT_ARG_STR_LEN >> 1))
+                {
+                    strcat(out, "...");
+                    break;
+                }
+            }
+            return 3;
+        }
+        else // sub_menu
+        {
+            plist = plist + CLI_IPT_ARG_STR_LEN;
+            ein   = eout;
+        }
+    }
+
+    return 1;
+}

+ 50 - 0
cli/cli_inter_preter.h

@@ -0,0 +1,50 @@
+#ifndef __CLI_INTER_PRETER_H
+#define __CLI_INTER_PRETER_H
+
+#include "stddef.h"
+#include <ctype.h>
+#include <string.h>
+
+extern void cli_printf(char *msg, ...);
+
+#define CLI_PRINTF(info, args...) cli_printf(info, ##args);
+
+#define CLI_IPT_ARG_NUM       12  // 支持解析后的参数个数
+#define CLI_IPT_ARG_LEN       50  // 每个参数解析后的最大长度
+#define CLI_IPT_ARG_STR_LEN   100 // 每个参数解析前字符串形式的最大长度
+#define CLI_IPT_ENTRY_NUM_MAX 100 // 菜单中子菜单最大个数(不用内存
+
+typedef void (*command_action)();
+
+#define command_entry_action_with_detail(name, action, arg_type, desp, arg_desp) \
+    {                                                                            \
+        (name), (command_action)(action), (arg_type), (desp), (arg_desp)         \
+    }
+
+#define command_entry_sub_menu(name, sub_menu, desp)                                              \
+    {                                                                                             \
+        (name), (command_action)NULL, (const char *)(sub_menu), (desp), (const char *const *)NULL \
+    }
+
+#define command_entry_terminator()                                                                                  \
+    {                                                                                                               \
+        (const char *)NULL, (command_action)NULL, (const char *)NULL, (const char *)NULL, (const char *const *)NULL \
+    }
+
+typedef const struct
+{
+    const char        *name;
+    command_action     action; // action==NULL means argumentTypes is a subentry
+    const char        *arg_type;
+    const char        *desp;
+    const char *const *arg_desp;
+} command_entry;
+
+extern unsigned int cli_ipt_arg_list[CLI_IPT_ARG_NUM][CLI_IPT_ARG_LEN];
+
+extern void array_map_input_to_byte(unsigned char *b, unsigned int *i, unsigned int len);
+extern int  command_entry_match(command_entry *main_table, const char *cmd); // return 0: fail, 1: success
+extern int  command_entry_hint(command_entry *main_table, const char *cmd, char *out);
+extern void print_entry(command_entry *entry);
+
+#endif // __CLI_INTER_PRETER_H

+ 1 - 1
cmsis/system_stm32f4xx.c

@@ -361,7 +361,7 @@
 /*!< Uncomment the following line if you need to relocate your vector Table in
      Internal SRAM. */
 /* #define VECT_TAB_SRAM */
-#define VECT_TAB_OFFSET 0x10000 /*!< Vector Table base offset field. \
+#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. \
                                   This value must be a multiple of 0x200. */
 /******************************************************************************/
 

+ 678 - 0
dev/dev_can.c

@@ -0,0 +1,678 @@
+#include "dev_can.h"
+#include "hal_can.h"
+#include "hal_conf.h"
+#include "queue.h"
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+double pow_branch(double x, long long N)
+{
+    double ans = 1.0;
+    // 贡献的初始值为 x
+    double x_contribute = x;
+    // 在对 N 进行二进制拆分的同时计算答案
+    while (N > 0)
+    {
+        if (N % 2 == 1)
+        {
+            // 如果 N 二进制表示的最低位为 1,那么需要计入贡献
+            ans *= x_contribute;
+        }
+        // 将贡献不断地平方
+        x_contribute *= x_contribute;
+        // 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可
+        N = N >> 1;
+    }
+    return ans;
+}
+double pow(double x, double N)
+{
+    return N >= 0 ? pow_branch(x, N) : 1.0 / pow_branch(x, -N);
+}
+
+uint8_t recv_can_id = 0;
+
+static uint64_t base_data;
+
+void data_bit_move(uint8_t start_bit, uint8_t bit_len, uint64_t data)
+{
+    uint64_t mask        = 0;
+    uint64_t source_data = (uint64_t)data;
+    mask                 = pow(2, bit_len) - 1;
+    base_data |= (mask & source_data) << start_bit;
+}
+
+void product_array(uint8_t send_array[8])
+{
+    send_array[0] = (uint8_t)base_data;
+    send_array[1] = (uint8_t)(base_data >> 8);
+    send_array[2] = (uint8_t)(base_data >> 16);
+    send_array[3] = (uint8_t)(base_data >> 24);
+    send_array[4] = (uint8_t)(base_data >> 32);
+    send_array[5] = (uint8_t)(base_data >> 40);
+    send_array[6] = (uint8_t)(base_data >> 48);
+    send_array[7] = (uint8_t)(base_data >> 56);
+    base_data     = 0;
+}
+
+uint8_t push_can_message_to_queue(uint32_t id, uint8_t len, uint8_t *p_data)
+{
+    pdu_tag response_msg;
+    response_msg.id.r    = id;
+    response_msg.reg.dlc = len;
+    memcpy(&response_msg.data.u8_buf[0], p_data, len);
+
+    if (id > 0x7FF)
+    {
+        response_msg.reg.ide = CAN_Id_Extended;
+    }
+    else
+    {
+        response_msg.reg.ide = CAN_Id_Standard;
+    }
+
+#if 1
+    if (en_queue(&can_tx_queue, response_msg) != Q_OK)
+    {
+        return 0;
+    }
+#else
+    en_queue(can_tx, &response_msg, 1);
+#endif
+    return 1;
+}
+
+static uint8_t can_tx_frame(pdu_tag can_message)
+{
+    uint8_t result = CAN_TxStatus_NoMailBox;
+    result         = hal_can_msg_tx(can_message.id.r, can_message.reg.ide, can_message.data.u8_buf, can_message.reg.dlc);
+    return result;
+}
+
+// void can_tx_stop(CAN_TypeDef *can_perpiph, u8 mailbox_number)
+// {
+//     can_tx_mail_box_stop(can_perpiph, mailbox_number);
+// }
+
+// QUEUE_STATUS can_tx_process(p_can_queue_tag p_queue)
+// {
+//     u8 mailbox_number = 0;
+//     u8 query_result   = CAN_TxStatus_NoMailBox;
+
+//     if (queue_empty(p_queue))
+//         return Q_OK;
+//     mailbox_number = can_tx_frame(p_queue->can_message[p_queue->tail]);
+//     if (mailbox_number == CAN_TxStatus_NoMailBox)
+//         return Q_OK;
+//     query_result = can_tx_mail_box_state(CAN1, mailbox_number);
+//     if (query_result == CAN_TxStatus_Ok || query_result == CAN_TxStatus_Pending)
+//     {
+//         p_queue->tail = (p_queue->tail + 1) % MAX_QSIZE;
+//         p_queue->count--;
+//         return Q_OK;
+//     }
+//     return Q_ERR;
+// }
+
+void can_tx_callback(void)
+{
+    pdu_tag tx_data;
+    // de_queue(can_tx, &tx_data);
+    if (de_queue(&can_tx_queue, &tx_data) == Q_OK) // 返回值为1代表读取成功
+    {
+        can_tx_frame(tx_data);
+        CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
+    }
+    else
+    {
+        CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE);
+    }
+}
+
+void can_rx_callback(CanRxMsg rx_message)
+{
+    pdu_tag data;
+    uint8_t ps;
+    uint8_t pf;
+    switch (rx_message.ExtId)
+    {
+    case 0x18011801:
+        data.id.r    = 0x18011801;
+        data.reg.dlc = rx_message.DLC;
+        memcpy(&data.data.u8_buf[0], rx_message.Data, rx_message.DLC);
+        en_queue(&can_rx_queue, data);
+    case 0x18CFD0EF:
+        data.id.r    = 0x18CFD0EF;
+        data.reg.dlc = rx_message.DLC;
+        memcpy(&data.data.u8_buf[0], rx_message.Data, rx_message.DLC);
+        en_queue(&can_rx_queue, data);
+    case 0x18011802:
+        data.id.r    = 0x18011802;
+        data.reg.dlc = rx_message.DLC;
+        memcpy(&data.data.u8_buf[0], rx_message.Data, rx_message.DLC);
+#if 1
+        en_queue(&can_rx_queue, data);
+#else
+        en_queue(can_rx, &data, 1);
+#endif
+        break;
+    default:
+        pf = (rx_message.ExtId & CAN_PGN_PF) >> 16;
+        if (pf >= 0xF0)
+        {
+            data.id.r   = rx_message.ExtId;
+            recv_can_id = data.id.b.sa;
+            memcpy(&data.data.u8_buf[0], rx_message.Data, rx_message.DLC);
+#if 1
+            en_queue(&can_rx_queue, data);
+#else
+            en_queue(can_rx, &data, 1);
+#endif
+        }
+        else
+        {
+            // ps = (rx_message.ExtId & CAN_PGN_PS) >> 8;
+            // if (ps == 0xF4)
+            // {
+            // }
+#if 1
+            en_queue(&can_rx_queue, data);
+#else
+            en_queue(can_rx, &data, 1);
+#endif
+        }
+    }
+}
+uint8_t tx_flag = 0;
+
+void can_rx_ctl(pdu_tag rec_msg)
+{
+    // rec_msg.data.u8_buf[0];
+    // LED2    = !LED2;
+    tx_flag = 1;
+}
+uint8_t tx_data[8] = {0};
+uint8_t flag       = 0;
+void    can_rx_param(pdu_tag rec_msg)
+{
+    // LED2 = !LED2;
+
+    tx_data[0] = rec_msg.data.u8_buf[0];
+    tx_data[1] = rec_msg.data.u8_buf[1];
+    tx_data[2] = rec_msg.data.u8_buf[2];
+    tx_data[3] = rec_msg.data.u8_buf[3];
+    if (tx_data[1] = 0xFF)
+    {
+        tx_flag = 1;
+    }
+    else
+    {
+        flag = 1;
+    }
+
+    // push_can_message_to_queue(rec_msg.id.r, rec_msg.reg.dlc, rec_msg.data.u8_buf);
+}
+
+void can_rx_update(pdu_tag rec_msg)
+{
+    if ((rec_msg.data.u8_buf[0] == 'A') && (rec_msg.data.u8_buf[1] == 'P') && (rec_msg.data.u8_buf[2] == 'P') && (rec_msg.data.u8_buf[3] == 'L') && (rec_msg.data.u8_buf[4] == 'O') && (rec_msg.data.u8_buf[5] == 'A') && (rec_msg.data.u8_buf[6] == 'D') && (rec_msg.data.u8_buf[7] == 0x01))
+    {
+        __set_FAULTMASK(1); //  关闭所有中断
+        NVIC_SystemReset(); //  复位
+    }
+}
+
+can_rx_tab can_tab[] = {
+    0x18011802,
+    can_rx_param,
+    0x18011801,
+    can_rx_ctl,
+    0x18CFD0EF,
+    can_rx_update,
+
+};
+
+void can_start_send(void)
+{
+    pdu_tag tx_msg;
+    if (RESET == CAN_GetITStatus(CAN1, CAN_IT_TME))
+    {
+#if 0
+        de_queue(can_tx, &tx_msg);
+        if (can_tx.ret == 1) // 返回值为1代表读取成功
+        {
+            can_tx_frame(tx_msg);
+            CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
+        }
+#else
+        if (de_queue(&can_tx_queue, &tx_msg) == Q_OK) // 返回值为1代表读取成功
+        {
+            can_tx_frame(tx_msg);
+            CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
+        }
+
+#endif
+    }
+}
+
+static uint8_t can_rx_process(void)
+{
+    uint8_t i;
+    uint8_t flg = 0;
+    pdu_tag rec_msg;
+
+    for (uint8_t j = 0; j < 15; j++)
+    {
+#if 1
+        if (Q_OK == de_queue(&can_rx_queue, &rec_msg))
+        {
+            for (i = 0; i < ARR_SIZE(can_tab); i++)
+            {
+                if (can_tab[i].id == rec_msg.id.r)
+                {
+                    can_tab[i].p_func(rec_msg);
+                    break;
+                }
+            }
+        }
+#else
+        de_queue(can_rx, &rec_msg);
+        if (can_rx.ret == 1) // 返回值为1代表读取成功
+        {
+            for (i = 0; i < ARR_SIZE(can_tab); i++)
+            {
+                if (can_tab[i].id == rec_msg.id.r)
+                {
+                    can_tab[i].p_func(rec_msg);
+                    break;
+                }
+            }
+        }
+#endif
+    }
+}
+
+void can_tx_0x18010000_message(void)
+{
+    uint8_t data[8] = {0};
+    data[2]         = 0xFF;
+    push_can_message_to_queue(0x18010000, 8, data);
+}
+
+void can_tx_0x18010001_message(void)
+{
+    uint8_t data[8] = {0};
+    push_can_message_to_queue(0x18010001, 8, data);
+}
+
+void can_tx_0x18030001_message(void)
+{
+    uint8_t data[8] = {0};
+    data[1]         = 8;
+    push_can_message_to_queue(0x18030001, 8, data);
+}
+
+void can_tx_0x18010002_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 0x02;
+    push_can_message_to_queue(0x18010002, 8, data);
+}
+
+void can_tx_0x18030003_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 0x02;
+    push_can_message_to_queue(0x18030003, 8, data);
+}
+
+void can_tx_0x18010004_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x18010004, 8, data);
+}
+
+void can_tx_0x18010005_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x18010005, 8, data);
+}
+
+void can_tx_0x18010006_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x18010006, 8, data);
+}
+
+void can_tx_0x18010007_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x18010007, 8, data);
+}
+
+void can_tx_0x18010008_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x18010008, 8, data);
+}
+
+void can_tx_0x18010009_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x18010009, 8, data);
+}
+
+void can_tx_0x1801000F_message(void)
+{
+    uint8_t data[8] = {0};
+
+    data[0] = 1;
+    data[1] = 5;
+    data[2] = 3000 & 0xFF;
+    data[3] = 3000 >> 8;
+    data[4] = 3000 & 0xFF;
+    data[5] = 3000 >> 8;
+    push_can_message_to_queue(0x1801000F, 8, data);
+}
+
+void can_tx_0x18010010_message(void)
+{
+    uint8_t data[8] = {0};
+    // data_bit_move(0, 8, 1);
+    // data_bit_move(8, 8, 1);
+    // data_bit_move(32, 8, 0);
+    // data_bit_move(40, 8, 0);
+    // product_array(data);
+    data[0] = 1;
+    data[1] = 1;
+    data[4] = 0;
+    data[5] = 0;
+    push_can_message_to_queue(0x18010010, 8, data);
+    data[1] = 5;
+    push_can_message_to_queue(0x18010010, 8, data);
+    data[1] = 10;
+    push_can_message_to_queue(0x18010010, 8, data);
+}
+
+void can_tx_0x1801000A_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x1801000A, 8, data);
+}
+
+void can_tx_0x1801000B_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x1801000B, 8, data);
+}
+
+void can_tx_0x1801000C_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x1801000C, 8, data);
+}
+
+void can_tx_0x1801000D_message(void)
+{
+    uint8_t data[8] = {0};
+    data[4]         = 33;
+    data[5]         = 22;
+    push_can_message_to_queue(0x1801000D, 8, data);
+}
+
+void can_tx_0x18010012_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 24;
+    data[1]         = 1;
+    data[2]         = 3;
+    data[3]         = 11;
+    data[4]         = 12;
+    data[5]         = 13;
+    data[6]         = 12;
+    data[7]         = 13;
+    push_can_message_to_queue(0x18010012, 8, data);
+}
+
+void can_tx_0x18010017_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 24;
+    data[1]         = 1;
+    data[0]         = 3;
+    data[1]         = 11;
+    data[0]         = 12;
+    data[1]         = 13;
+    push_can_message_to_queue(0x18010017, 8, data);
+}
+
+void can_tx_0x18010018_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 2;
+    data[1]         = 0xFF;
+    push_can_message_to_queue(0x18010018, 8, data);
+}
+
+void can_tx_0x18010019_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 2;
+    data[1]         = 0xFF;
+    push_can_message_to_queue(0x18010019, 8, data);
+}
+
+void can_tx_0x1801001A_message(void)
+{
+    volatile static int i       = 0;
+    uint8_t             data[8] = {0};
+
+    data[0] = 2 + i;
+    data[1] = 0x12 >> i;
+    i++;
+    if (i > 7)
+    {
+        i = 0;
+    }
+    push_can_message_to_queue(0x1801001A, 8, data);
+}
+
+void can_tx_0x1801001B_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 2;
+    data[1]         = 0xFF;
+    push_can_message_to_queue(0x1801001B, 8, data);
+}
+
+void can_tx_0x1801001C_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 2;
+    data[4]         = 0xFF;
+    push_can_message_to_queue(0x1801001C, 8, data);
+}
+
+void can_tx_0x1801001D_message(void)
+{
+    uint8_t data[8] = {0};
+    data[0]         = 3;
+    data[2]         = 0xFF;
+    push_can_message_to_queue(0x1801001D, 8, data);
+}
+
+void can_tx_0x18010023_message(void)
+{
+    uint8_t send_data[8] = {0};
+    // data[0]    = 'A';
+    // data[1]    = 'A';
+    // data[2]    = 'A';
+    // data[3]    = 'A';
+    // data[4]    = 'A';
+    // data[5]    = 'A';
+    // data[6]    = 'A';
+    // data[7]    = 'A';
+    data_bit_move(0, 8, 'A');
+    data_bit_move(8, 8, 'A');
+    data_bit_move(16, 8, 'A');
+    data_bit_move(24, 8, 'C');
+    data_bit_move(32, 8, 'A');
+    data_bit_move(40, 8, '-');
+    data_bit_move(48, 8, 'A');
+    data_bit_move(56, 8, 'B');
+    product_array(send_data);
+    push_can_message_to_queue(0x18010023, 8, send_data);
+}
+
+void can_tx_0x18011802_message(void)
+{
+    static uint8_t fdf = 0;
+    if (flag == 1)
+    {
+        push_can_message_to_queue(0x18011802, 8, tx_data);
+        flag = 0;
+    }
+    uint8_t  data[8] = {0};
+    uint16_t addr    = 0xA000;
+    if (tx_flag == 1)
+    {
+        data[0] = (addr + fdf) & 0xFF;
+        data[1] = (addr + fdf) >> 8;
+        data[2] = rand() & 0xFF;
+        data[3] = rand() >> 8;
+        fdf++;
+        if (fdf == 80)
+        {
+            tx_flag = 0;
+        }
+        push_can_message_to_queue(0x18011802, 8, data);
+    }
+}
+
+void can_tx_0x18011803_message(void)
+{
+    uint8_t        data[8] = {0};
+    uint16_t       addr    = 0xB000;
+    static uint8_t fdf     = 0;
+    static int16_t a       = -263;
+    data[0]                = (addr + fdf) & 0xFF;
+    data[1]                = (addr + fdf) >> 8;
+    data[2]                = a & 0xFF;
+    data[3]                = a >> 8;
+    fdf++;
+    a++;
+    if (fdf > 6)
+    {
+        fdf = 0;
+    }
+    push_can_message_to_queue(0x18011803, 8, data);
+}
+
+void can_tx_0x18011803_2_message(void)
+{
+    uint8_t        data[8] = {0};
+    static uint8_t fdf_2   = 0;
+
+    uint16_t addr_vol = 0xB110;
+    data[0]           = (addr_vol + fdf_2) & 0xFF;
+    data[1]           = (addr_vol + fdf_2) >> 8;
+    data[2]           = 1;
+    data[3]           = -2 & 0xFF;
+    data[4]           = -2 >> 8;
+    fdf_2++;
+    if (fdf_2 > 80)
+    {
+        fdf_2 = 0;
+    }
+    push_can_message_to_queue(0x18011803, 8, data);
+}
+
+void send_message(void)
+{
+    static volatile uint8_t times = 0;
+    times++;
+    if (times % 100 == 1)
+    {
+        can_tx_0x18010001_message();
+        can_tx_0x18010002_message();
+        can_tx_0x18010004_message();
+        can_tx_0x18010005_message();
+    }
+    else if (times % 100 == 5)
+    {
+        can_tx_0x18010006_message();
+        can_tx_0x18010007_message();
+        can_tx_0x18010008_message();
+        can_tx_0x18010009_message();
+        can_tx_0x1801000A_message();
+    }
+    else if (times % 100 == 10)
+    {
+        can_tx_0x1801000B_message();
+        can_tx_0x1801000C_message();
+        can_tx_0x1801000D_message();
+        can_tx_0x18010023_message();
+        can_tx_0x18010010_message();
+    }
+    else if (times % 100 == 15)
+    {
+        can_tx_0x18010018_message();
+        can_tx_0x18010019_message();
+        can_tx_0x1801001A_message();
+        can_tx_0x1801001B_message();
+        can_tx_0x1801001C_message();
+    }
+    else if (times % 100 == 20)
+    {
+        can_tx_0x1801001D_message();
+        can_tx_0x1801000F_message();
+        can_tx_0x18030003_message();
+        can_tx_0x18030001_message();
+        can_tx_0x18010000_message();
+    }
+    else if (times % 100 == 25)
+    {
+        can_tx_0x18010017_message();
+        can_tx_0x18010012_message();
+        can_tx_0x18011802_message();
+        can_tx_0x18011803_message();
+        can_tx_0x18011803_2_message();
+    }
+    else
+    {
+        return;
+    }
+}
+
+void dev_can_network_init(void)
+{
+    hal_can_init();
+    hal_can_rx_back_init(can_rx_callback);
+    hal_can_tx_back_init(can_tx_callback);
+}
+
+void can_process(void)
+{
+    can_rx_process();
+    send_message();
+    can_start_send();
+}

+ 28 - 0
dev/dev_can.h

@@ -0,0 +1,28 @@
+#ifndef __APP_CAN_H
+#define __APP_CAN_H
+
+#include "hal_conf.h"
+#include "queue.h"
+
+#define CAN_PGN_PF 0xFF
+#define CAN_PGN_PS 0xFF
+extern uint8_t recv_can_id;
+
+typedef struct
+{
+    uint32_t id;
+    void (*p_func)(pdu_tag);
+} can_rx_tab;
+
+// #define ARR_SIZE(a) sizeof(a) / a[0]
+
+#define ARR_SIZE(a) sizeof(a) / sizeof((a)[0])
+
+// #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+
+void can_rx_callback(CanRxMsg rx_message);
+void can_tx_callback();
+void can_process(void);
+void dev_can_network_init();
+
+#endif // __APP_CAN_H

+ 1 - 0
dev/dev_conf.h

@@ -2,6 +2,7 @@
 #define __DEV_CONF_H
 
 #include "dev_at24cxx.h"
+#include "dev_can.h"
 #include "dev_key.h"
 #include "dev_led.h"
 #include "dev_systick.h"

+ 264 - 0
dev/dev_iap.c

@@ -0,0 +1,264 @@
+/************************************************************************************************
+ *                                          Include                                              *
+ ************************************************************************************************/
+#include "dev_iap.h"
+#include "dev_at24cxx.h"
+#include "hal_conf.h"
+#include "hal_flash.h"
+#include "queue.h"
+#include <stdint.h>
+#include <string.h>
+
+/************************************************************************************************
+ *                                          Config                                                *
+ ************************************************************************************************/
+extern uint8_t jump_flag;
+uint8_t        can_rx_flag;
+// extern can_receive_message receive_iap_message;
+static uint16_t jump_boot_time = 0;
+uint8_t         send_buff[8]   = {0, 0, 0, 0, 0, 0, 0, 0};
+unsigned char   recv_crc[2];
+unsigned char   recvdata_ema[204];
+unsigned char   recvdata_buffer[210];
+
+uint16_t firm_ver[UPGRADE_APP_DATA_SIZE]       = {IAP_CMD_JUMP_OVER};
+uint16_t firm_ver_buff[UPGRADE_BUFF_DATA_SIZE] = {0};
+uint8_t  iap_disconnect_count                  = 0;
+/************************************************************************************************
+ *                                          Data structs                                         *
+ ************************************************************************************************/
+iap_type      g_iap;
+upgrade_param upgrade;
+/************************************************************************************************
+ *                                          implements                                           *
+ ************************************************************************************************/
+void invert_uint8()
+{
+}
+
+void iap_connect_clear(void)
+{
+    iap_disconnect_count = 0;
+    send_buff[0]         = 0x00;
+    send_buff[1]         = 0x00;
+    send_buff[2]         = 0x00;
+    send_buff[3]         = 0x00;
+    send_buff[4]         = 0x00;
+    send_buff[5]         = 0x00;
+    send_buff[6]         = 0x00;
+    send_buff[7]         = 0x00;
+}
+
+void iap_disconnect_check(void)
+{
+    if (++iap_disconnect_count >= 5)
+    {
+        iap_disconnect_count = 5;
+    }
+}
+
+// iap相关参数初始化
+void iap_param_init(void)
+{
+    g_iap.recv_len         = 0;
+    g_iap.total_packages   = 0;
+    g_iap.current_packages = 0;
+    g_iap.crc16            = 0xFFFF;
+    g_iap.total_bytes      = 0;
+    g_iap.count_bytes      = 0;
+    g_iap.count_packages   = 0;
+    g_iap.firmware_crc16   = 0;
+    g_iap.firmware_ver     = 0;
+}
+
+// 清除升级信息标志位
+void set_firmver(void)
+{
+    fmc_clear_flag_star();
+    fmc_read_n_half_word(UPGRADE_FLAG_START_ADDR, firm_ver_buff, UPGRADE_BUFF_DATA_SIZE);
+    fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1);
+
+    fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR, firm_ver_buff, UPGRADE_BUFF_DATA_SIZE);
+    fmc_clear_flag_end();
+}
+
+void iap_flag_release(void)
+{
+    fmc_read_n_half_word(UPGRADE_FLAG_START_ADDR, upgrade.infor_buf, UPGRADE_FLAG_DATA_SIZE);
+
+    if (upgrade.param.sign == UPGRADE_SIGN)
+    {
+        fmc_clear_flag_star();
+        fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1);
+        fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_DATA_SIZE * 2), firm_ver, UPGRADE_APP_DATA_SIZE);
+        fmc_clear_flag_end();
+        for (uint8_t i = 0; i < (UPGRADE_APP_DATA_SIZE * 2); i++)
+        {
+            send_buff[i] = fmc_read_byte(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_DATA_SIZE * 2) + i);
+        }
+        hal_can_msg_tx(0x180000001, CAN_Id_Extended, send_buff, 8);
+        CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);
+    }
+}
+
+uint8_t erase_app_flash(uint32_t start_address, uint32_t end_addr)
+{
+    uint8_t  status   = 0;
+    uint16_t page_len = 0;
+    page_len          = (end_addr - start_address) / FMC_PAGE_SIZE;
+    status            = fmc_erase_pages(start_address, page_len);
+    return status;
+}
+
+void write_app_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num)
+{
+    static uint32_t w_start_addr = 0;
+
+    w_start_addr = pack_num * 6 + APP_START_ADDR;
+    fmc_write_n_half_word(w_start_addr, buf, pack_len);
+}
+
+void read_app_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num)
+{
+    static uint32_t w_start_addr = 0;
+
+    w_start_addr = pack_num * 6 + APP_START_ADDR;
+    fmc_read_n_half_word(w_start_addr, buf, pack_len);
+}
+
+uint8_t write_download_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num)
+{
+    uint8_t         status       = 0;
+    static uint32_t w_start_addr = 0;
+
+    w_start_addr = pack_num * 6 + DOWNLOAD_START_ADDR;
+    status       = fmc_write_n_half_word(w_start_addr, buf, pack_len);
+    return status;
+}
+
+void read_download_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num)
+{
+    static uint32_t w_start_addr = 0;
+
+    w_start_addr = pack_num * 6 + DOWNLOAD_START_ADDR;
+    fmc_read_n_half_word(w_start_addr, buf, pack_len);
+}
+
+void iap_rec_handler(pdu_tag rec_msg)
+{
+    uint8_t erase_flag = 0x01;
+
+    // ota_can_id = rec_msg.id.r;
+    if (rec_msg.data.u8_buf[0] != IAP_CMD_VERSION)
+        iap_connect_clear();
+
+    if (rec_msg.data.u8_buf[0] >> 7)
+    {
+        if (rec_msg.id.b.sa == 0xE1)
+        {
+            g_iap.recv_len         = rec_msg.reg.dlc - 2;
+            g_iap.current_packages = ((uint16_t)(rec_msg.data.u8_buf[0] & 0x7F) << 8) | rec_msg.data.u8_buf[1];
+            memcpy(g_iap.flash_data.u8_buf, &rec_msg.data.u8_buf[2], g_iap.recv_len);
+
+            if ((g_iap.count_packages == g_iap.current_packages) && (g_iap.current_packages < g_iap.total_packages))
+            {
+                g_iap.count_bytes += g_iap.recv_len;
+
+                if ((g_iap.recv_len % 2) != 0)
+                {
+                    g_iap.flash_data.u8_buf[g_iap.recv_len] = 0xFF;
+                    g_iap.recv_len++;
+                }
+
+                fmc_clear_flag_star();
+                erase_flag = write_download_flash(g_iap.flash_data.u16_buf, g_iap.recv_len / 2, g_iap.count_packages);
+                fmc_clear_flag_end();
+
+                g_iap.crc16 = firmware_crc16_ccitt_false(g_iap.crc16, g_iap.flash_data.u8_buf, g_iap.recv_len);
+
+                send_buff[0] = IAP_CMD_DATA;
+                send_buff[1] = !erase_flag;
+                g_iap.count_packages++;
+            }
+            else
+            {
+                send_buff[0] = IAP_CMD_DATA;
+                send_buff[1] = 0x06;
+            }
+
+            send_buff[2] = rec_msg.data.u8_buf[0] & 0x7F;
+            send_buff[3] = rec_msg.data.u8_buf[1];
+
+            send_buff[4] = g_iap.count_packages >> 8;
+            send_buff[5] = g_iap.count_packages & 0xFF;
+        }
+        else
+        {
+            switch (rec_msg.data.u8_buf[0])
+            {
+            case IAP_CMD_VERSION:
+                iap_param_init();
+                for (uint8_t i = 0; i < (UPGRADE_APP_DATA_SIZE * 2); i++)
+                {
+                    send_buff[i] = fmc_read_byte(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_START_ADDR * 2) + i);
+                }
+
+                send_buff[0] = IAP_CMD_VERSION;
+                send_buff[1] = 0x01;
+                break;
+            case IAP_CMD_INFO:
+                g_iap.total_bytes = (uint16_t)rec_msg.data.u8_buf[1] << 8 | rec_msg.data.u8_buf[2];
+                g_iap.total_bytes <<= 16;
+                g_iap.total_bytes |= (uint16_t)rec_msg.data.u8_buf[3] << 8 | rec_msg.data.u8_buf[4];
+                g_iap.total_packages = (uint16_t)rec_msg.data.u8_buf[5] << 8 | rec_msg.data.u8_buf[6];
+                send_buff[0]         = IAP_CMD_INFO;
+                send_buff[1]         = 0x01;
+                break;
+            case IAP_CMD_ERASE:
+                g_iap.firmware_crc16 = (uint16_t)rec_msg.data.u8_buf[2] << 8 | rec_msg.data.u8_buf[3];
+                if (rec_msg.data.u8_buf[1])
+                {
+                    // 喂狗
+                    fmc_clear_flag_star();
+                    erase_flag = erase_app_flash(DOWNLOAD_START_ADDR, DOWNLOAD_END_ADDR / 2);
+                    fmc_clear_flag_end();
+                    // 喂狗
+                    g_iap.count_bytes    = 0;
+                    g_iap.count_packages = 0;
+                }
+                send_buff[0] = IAP_CMD_ERASE;
+                send_buff[1] = !erase_flag;
+            case IAP_CMD_CRC:
+                send_buff[0] = IAP_CMD_CRC;
+                send_buff[1] = (g_iap.crc16 == g_iap.firmware_crc16 ? 1 : 0);
+                break;
+            case IAP_CMD_JUMP:
+                if (g_iap.crc16 != g_iap.firmware_crc16)
+                {
+                    send_buff[1] = 0x00;
+                }
+                else
+                {
+                    fmc_clear_flag_star();
+                    fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1);
+                    upgrade.param.sign        = UPGRADE_SIGN;
+                    upgrade.param.crc16       = g_iap.crc16;
+                    upgrade.param.moving_size = g_iap.total_bytes;
+                    fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR, upgrade.infor_buf, UPGRADE_FLAG_DATA_SIZE);
+                    fmc_clear_flag_end();
+                    jump_boot_time = 10;
+                    send_buff[1]   = 0x01;
+                }
+                break;
+            case IAP_CMD_MODEL_TYPE:
+                send_buff[0] = IAP_CMD_MODEL_TYPE;
+                send_buff[1] = 0x01;
+
+                send_buff[2] = DEVICE_ID >> 8;
+                send_buff[3] = DEVICE_ID & 0xFF;
+            }
+        }
+
+        // push_can_message_to_queue(IAP, 8, send_buff);
+    }
+}

+ 107 - 0
dev/dev_iap.h

@@ -0,0 +1,107 @@
+#ifndef __DEV_IAP_H
+#define __DEV_IAP_H
+
+#ifdef __cplusplus
+extern 'C'
+{
+#endif
+#ifdef __DEV_IAP_H_GLOBAL
+#define __DEV_IAP_H_EXTERN
+#else
+#define __DEV_IAP_H_EXTERN extern
+#endif
+
+/************************************************************************************************
+ *                                          Version                                              *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          How to use                                           *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Enable config                                         *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Includes                                             *
+ ************************************************************************************************/
+#include <stdint.h>
+
+    /************************************************************************************************
+     *                                          Defines                                              *
+     ************************************************************************************************/
+
+#define UPGRADE_FLAG_DATA_SIZE 4                                                // 升级参数数组元素个数
+#define UPGRADE_APP_DATA_SIZE  4                                                // 升级参数数组元素个数
+#define UPGRADE_BUFF_DATA_SIZE (UPGRADE_FLAG_DATA_SIZE + UPGRADE_APP_DATA_SIZE) // 升级参数数组元素个数
+
+#define APP_START_ADDR ((uint32_t)0x08007000)
+#define APP_END_ADDR   ((uint32_t)0x08039000)
+
+#define UPGRADE_FLAG_START_ADDR ((uint32_t)0x08039000)
+#define UPGRADE_FLAG_END_ADDR   ((uint32_t)0x0803A000)
+
+#define DOWNLOAD_START_ADDR ((uint32_t)0x0803A000)
+#define DOWNLOAD_END_ADDR   ((uint32_t)0x0806C000)
+
+// 升级命令
+#define IAP_CMD_VERSION    0x71   // 查询版本号
+#define IAP_CMD_INFO       0x72   // 包信息
+#define IAP_CMD_ERASE      0x73   // 擦除命令
+#define IAP_CMD_DATA       0x80   // 数据帧 IAP_CMD_DATA |帧号
+#define IAP_CMD_CRC        0x74   // 传输结果校验
+#define IAP_CMD_JUMP       0x75   // 执行跳转
+#define IAP_CMD_JUMP_OVER  0x0175 // 执行跳转
+#define IAP_CMD_MODEL_TYPE 0x76   // 执行跳转
+
+#define UPGRADE_SIGN 0x5AA5
+#define DEVICE_ID    0x5AA4
+
+    typedef union
+    {
+        uint16_t u8_buf[8];
+        uint16_t u16_buf[4];
+    } u16_u8;
+
+    typedef union
+    {
+        uint16_t u8_save[200];
+        uint16_t u16_save[100];
+    } u16save_u8save;
+
+    typedef struct
+    {
+        uint16_t       total_packages;
+        uint16_t       current_packages;
+        uint16_t       count_packages;
+        uint16_t       recv_len;
+        uint16_t       crc16;
+        uint16_t       firmware_crc16;
+        uint16_t       firmware_ver;
+        uint16_t       total_bytes;
+        uint16_t       count_bytes;
+        u16_u8         flash_data;
+        u16_u8         recheck_data;
+        u16save_u8save save_data;
+    } iap_type;
+
+    typedef union
+    {
+        struct
+        {
+            uint16_t sign;        // 首地址 buf[0]
+            uint16_t crc16;       // 中地址 buf[1]
+            uint32_t moving_size; // 高地址 buf[2] buf[3]
+        } param;
+        uint16_t infor_buf[UPGRADE_FLAG_DATA_SIZE];
+    } upgrade_param; // 升级参数使用
+
+/************************************************************************************************
+ *                                          Defines                                              *
+ ************************************************************************************************/
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __DEV_IAP_H

+ 166 - 113
hal/hal_can.c

@@ -1,101 +1,121 @@
-// #include "hal_can.h"
-
-// CanRxMsg RxMessageImportant;
-// CanRxMsg RxMessageNormal;
-
-// CanData_TypeDef CanDataNormal; // 普通数据
-
-// // CAN初始化
-// // tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
-// // tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
-// // tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
-// // brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1
-// // 波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
-// // mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
-// // Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
-// // 则波特率为:42M/((6+7+1)*6)=500Kbps
-
-// // CanRxMsg RxMessage1;
-// uint8_t CanBuffer[128] = "USAR2T DMA Example: Communication between two USART using DMA";
-
-// uint32_t result;
-
-// u8 hal_can1_mode_init(uint8_t tsjw, uint8_t tbs2, uint8_t tbs1, uint16_t brp, uint8_t mode)
-// {
-//     CAN_InitTypeDef       CAN_InitStructure;
-//     CAN_FilterInitTypeDef CAN_FilterInitStructure;
-//     NVIC_InitTypeDef      NVIC_InitStructure;
-
-//     // CAN单元设置
-//     CAN_InitStructure.CAN_TTCM      = DISABLE; // 非时间触发通信模式
-//     CAN_InitStructure.CAN_ABOM      = DISABLE; // 软件自动离线管理
-//     CAN_InitStructure.CAN_AWUM      = DISABLE; // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
-//     CAN_InitStructure.CAN_NART      = DISABLE; // 禁止报文自动传送
-//     CAN_InitStructure.CAN_RFLM      = DISABLE; // 报文不锁定,新的覆盖旧的
-//     CAN_InitStructure.CAN_TXFP      = DISABLE; // 优先级由报文标识符决定
-//     CAN_InitStructure.CAN_Mode      = mode;    // 模式设置
-//     CAN_InitStructure.CAN_SJW       = tsjw;    // 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
-//     CAN_InitStructure.CAN_BS1       = tbs1;    // Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
-//     CAN_InitStructure.CAN_BS2       = tbs2;    // Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tq
-//     CAN_InitStructure.CAN_Prescaler = brp;     // 分频系数(Fdiv)为brp+1
-//     CAN_Init(CAN1, &CAN_InitStructure);        // 初始化CAN1
-
-//     // 配置过滤器0
-//     CAN_FilterInitStructure.CAN_FilterNumber = 0; // 过滤器0
-//     CAN_FilterInitStructure.CAN_FilterMode   = CAN_FilterMode_IdMask;
-//     CAN_FilterInitStructure.CAN_FilterScale  = CAN_FilterScale_32bit; // 32位
-
-//     // 只接收标识符位0x0666报文  注意:RTR  IDE  SRR也参与构成标识符
-//     CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; //(((u32)0x0666<<3)&0xFFFF0000)>>16;				//要过滤的ID高位
-//     CAN_FilterInitStructure.CAN_FilterIdLow  = 0x0000; //(((u32)0x0666<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要过滤的ID低位
-
-//     CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; // 32位MASK
-//     //    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xfff8; // 最后3位不管
-//     CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; // 最后3位不管
-
-//     CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; // 过滤器0关联到FIFO0
-//     CAN_FilterInitStructure.CAN_FilterActivation     = ENABLE;           // 激活过滤器0
-//     CAN_FilterInit(&CAN_FilterInitStructure);                            // 滤波器初始化
-
-//     CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // FIFO0消息挂号中断允许.
-
-//     NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_RX0_IRQn;
-//     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; // 主优先级为
-//                                                               // 	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
-//     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-//     NVIC_Init(&NVIC_InitStructure);
-//     ////////////////////////////////////////////////
-
-//     return 0;
-// }
-
-// /**********************************************************************************************************
-//  *	函 数 名: CAN1_Init
-//  *	功能说明: CAN1初始化
-//  *	形    参: 无
-//  *	返 回 值: 无
-//  **********************************************************************************************************/
-// void CAN1_Init(void)
-// {
-// #if defined(__CAN_BAUD_500K)
-//     hal_can1_mode_init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 6, CAN_Mode_Normal); // CAN1初始化环回模式,波特率500Kbps
-// #elif defined(__CAN_BAUD_250K)
-//     hal_can1_mode_init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 12, CAN_Mode_Normal); // CAN1初始化环回模式,波特率250Kbps
-// #else
-// #error no can baud macro!;
-// #endif
-// }
-
-// //(固定格式:ID为0X12,标准帧,数据帧)
-// // len:数据长度(最大为8)
-// // msg:数据指针,最大为8个字节.
-// // 返回值:0,成功;
-// //		 其他,失败;
-// /****************************************************
-//  *  函数功能:can1发送一组数据
-//  *  入口参数:msg 数据  len  数据长度  can_id  CAN id
-//  *  说    明:group_id 从1开始
-//  *****************************************************/
+#include "hal_can.h"
+#include "stm32f4xx.h"
+#include "stm32f4xx_gpio.h"
+#include <string.h>
+
+CanTxMsg tx_message;
+CanRxMsg rx_message;
+pcan_rx  pcan_rx_back = NULL;
+pcan_tx  pcan_tx_back = NULL;
+
+// CAN初始化
+// tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
+// tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
+// tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
+// brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1
+// 波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
+// mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
+// Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
+// 则波特率为:42M/((6+7+1)*6)=500Kbps
+
+u8 hal_can1_mode_init(uint8_t tsjw, uint8_t tbs2, uint8_t tbs1, uint16_t brp, uint8_t mode)
+{
+    GPIO_InitTypeDef      GPIO_InitStructure;
+    CAN_InitTypeDef       CAN_InitStructure;
+    CAN_FilterInitTypeDef CAN_FilterInitStructure;
+    NVIC_InitTypeDef      NVIC_InitStructure;
+
+    CAN_DeInit(CAN1);
+
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 使能PORTA时钟
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);  // 使能CAN1时钟
+
+    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
+    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
+    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11 | GPIO_Pin_12;
+    GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化IO
+
+    GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1);
+    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1);
+
+    // CAN单元设置
+    CAN_InitStructure.CAN_TTCM      = DISABLE; // 非时间触发通信模式
+    CAN_InitStructure.CAN_ABOM      = DISABLE; // 软件自动离线管理
+    CAN_InitStructure.CAN_AWUM      = DISABLE; // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
+    CAN_InitStructure.CAN_NART      = DISABLE; // 禁止报文自动传送
+    CAN_InitStructure.CAN_RFLM      = DISABLE; // 报文不锁定,新的覆盖旧的
+    CAN_InitStructure.CAN_TXFP      = DISABLE; // 优先级由报文标识符决定
+    CAN_InitStructure.CAN_Mode      = mode;    // 模式设置
+    CAN_InitStructure.CAN_SJW       = tsjw;    // 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
+    CAN_InitStructure.CAN_BS1       = tbs1;    // Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
+    CAN_InitStructure.CAN_BS2       = tbs2;    // Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tq
+    CAN_InitStructure.CAN_Prescaler = brp;     // 分频系数(Fdiv)为brp+1
+    CAN_Init(CAN1, &CAN_InitStructure);        // 初始化CAN1
+
+    // 配置过滤器0
+    CAN_FilterInitStructure.CAN_FilterNumber = 0; // 过滤器0
+    CAN_FilterInitStructure.CAN_FilterMode   = CAN_FilterMode_IdMask;
+    CAN_FilterInitStructure.CAN_FilterScale  = CAN_FilterScale_32bit; // 32位
+
+    // 只接收标识符位0x0666报文  注意:RTR  IDE  SRR也参与构成标识符
+    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; //(((u32)0x0666<<3)&0xFFFF0000)>>16;				//要过滤的ID高位
+    CAN_FilterInitStructure.CAN_FilterIdLow  = 0x0000; //(((u32)0x0666<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要过滤的ID低位
+
+    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; // 32位MASK
+    //    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xfff8; // 最后3位不管
+    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; // 最后3位不管
+
+    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; // 过滤器0关联到FIFO0
+    CAN_FilterInitStructure.CAN_FilterActivation     = ENABLE;           // 激活过滤器0
+    CAN_FilterInit(&CAN_FilterInitStructure);                            // 滤波器初始化
+
+    CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // FIFO0消息挂号中断允许.
+    NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_RX0_IRQn;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0; // 次优先级为0
+    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+
+    CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); // FIFO0消息挂号中断允许.
+    NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_TX_IRQn;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0; // 次优先级为0
+    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+    ////////////////////////////////////////////////
+
+    return 0;
+}
+
+/**********************************************************************************************************
+ *	函 数 名: CAN1_Init
+ *	功能说明: CAN1初始化
+ *	形    参: 无
+ *	返 回 值: 无
+ **********************************************************************************************************/
+void hal_can_init(void)
+{
+#if defined(__CAN_BAUD_500K)
+    hal_can1_mode_init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 6, CAN_Mode_Normal); // CAN1初始化环回模式,波特率500Kbps
+#elif defined(__CAN_BAUD_250K)
+    hal_can1_mode_init(CAN_SJW_1tq, CAN_BS2_6tq, CAN_BS1_7tq, 12, CAN_Mode_Normal); // CAN1初始化环回模式,波特率250Kbps
+#else
+#error no can baud macro!;
+#endif
+}
+
+//(固定格式:ID为0X12,标准帧,数据帧)
+// len:数据长度(最大为8)
+// msg:数据指针,最大为8个字节.
+// 返回值:0,成功;
+//		 其他,失败;
+/****************************************************
+ *  函数功能:can1发送一组数据
+ *  入口参数:msg 数据  len  数据长度  can_id  CAN id
+ *  说    明:group_id 从1开始
+ *****************************************************/
 // u8 CAN1_Send_Msg(u8 *msg, u8 len, u32 can_id)
 // {
 //     u16      mbox, i;
@@ -118,18 +138,51 @@
 //     return 0;
 // }
 
-// // CAN1中断服务函数
-// void CAN1_RX0_IRQHandler(void)
-// {
-//     // 国轩协议,接收1-6电池簇数据
-//     CAN_Receive(CAN1, CAN_FIFO0, &RxMessageImportant); // 1.6us  ucos时间戳、示波器测量都是1.6us
-
-//     memcpy(CanDataImportant.buf, RxMessageImportant.Data, RxMessageImportant.DLC);
-//     CanDataImportant.can_id = RxMessageImportant.ExtId;
-//     if (InsertQueue(&CanQueueImportant, CanDataImportant) == ERROR) // 队列插入数据
-//     {
-//         LED_FAULT_TOGGLE();
-//         // return;
-//     }
-//     isr_sem_send(&can1_semaphore); // 发送信号量
-// }
+uint8_t hal_can_msg_tx(uint32_t id, uint8_t id_type, uint8_t *p_data, uint8_t len)
+{
+    uint8_t flg = 0;
+    if (id_type)
+    {
+        tx_message.ExtId = id; // 设置扩展标示符(29位)
+    }
+    else
+    {
+        tx_message.StdId = id_type; // 标准标识符为0
+    }
+
+    tx_message.IDE = id_type;      // 使用扩展标识符
+    tx_message.RTR = CAN_RTR_Data; // 消息类型为数据帧
+    tx_message.DLC = len;          // 发送两帧信息
+
+    memcpy(tx_message.Data, p_data, len);
+    flg = CAN_Transmit(CAN1, &tx_message);
+
+    return flg;
+}
+
+void hal_can_rx_back_init(pcan_rx p_fun)
+{
+    pcan_rx_back = p_fun;
+}
+
+void hal_can_tx_back_init(pcan_tx p_fun)
+{
+    pcan_tx_back = p_fun;
+}
+
+void CAN1_TX_IRQHandler(void)
+{
+    if (pcan_tx_back != NULL)
+    {
+        pcan_tx_back();
+    }
+}
+
+void CAN1_RX0_IRQHandler(void)
+{
+    CAN_Receive(CAN1, CAN_FIFO0, &rx_message);
+    if (pcan_rx_back != NULL)
+    {
+        pcan_rx_back(rx_message);
+    }
+}

+ 11 - 10
hal/hal_can.h

@@ -1,15 +1,16 @@
-// #ifndef __CAN_H
-// #define __CAN_H
+#ifndef __HAL_CAN_H
+#define __HAL_CAN_H
 
-// #include "queue.h"
-// #include "stm32f4xx.h"
+#include "stm32f4xx.h"
 
-// #define __CAN_BAUD_250K
+#define __CAN_BAUD_250K
 
-// void    hal_can1_init(void);                                       // CAN1初始化
-// uint8_t can1_send_msg(uint8_t *msg, uint8_t len, uint32_t can_id); //  CAN1发送数据
-// uint8_t CAN1_Receive_Msg(uint8_t *buf);                            //  CAN1接收数据
+typedef void (*pcan_tx)(void);
+typedef void (*pcan_rx)(CanRxMsg);
 
-// #define CAN_BUF1_BLOCK_LEN 100 //  CAN1缓冲块数量
+void    hal_can_init(); // CAN初始化
+uint8_t hal_can_msg_tx(uint32_t id, uint8_t id_type, uint8_t *p_data, uint8_t len);
+void    hal_can_rx_back_init(pcan_rx p_fun);
+void    hal_can_tx_back_init(pcan_tx p_fun);
 
-// #endif
+#endif

+ 3 - 1
hal/hal_conf.h

@@ -1,9 +1,11 @@
 #ifndef __HAL_CONF_H
 #define __HAL_CONF_H
 
+#include "hal_can.h"
+#include "hal_flash.h"
 #include "hal_gpio.h"
 #include "hal_i2c1.h"
 #include "hal_systick.h"
-#include "hal_uart1.h"
+#include "hal_uart.h"
 
 #endif // __APP_TASK_H

+ 173 - 0
hal/hal_flash.c

@@ -0,0 +1,173 @@
+/************************************************************************************************
+ *                                          Include                                              *
+ ************************************************************************************************/
+
+#include "hal_flash.h"
+#include "stm32f4xx.h"
+#include <stdint.h>
+
+/************************************************************************************************
+ *                                          Config                                                *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Data structs                                         *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          implements                                           *
+ ************************************************************************************************/
+uint16_t fmc_get_flash_sector(u32 addr)
+{
+    if (addr < ADDR_FLASH_SECTOR_1)
+        return FLASH_Sector_0;
+    else if (addr < ADDR_FLASH_SECTOR_2)
+        return FLASH_Sector_1;
+    else if (addr < ADDR_FLASH_SECTOR_3)
+        return FLASH_Sector_2;
+    else if (addr < ADDR_FLASH_SECTOR_4)
+        return FLASH_Sector_3;
+    else if (addr < ADDR_FLASH_SECTOR_5)
+        return FLASH_Sector_4;
+    else if (addr < ADDR_FLASH_SECTOR_6)
+        return FLASH_Sector_5;
+    else if (addr < ADDR_FLASH_SECTOR_7)
+        return FLASH_Sector_6;
+    else if (addr < ADDR_FLASH_SECTOR_8)
+        return FLASH_Sector_7;
+    else if (addr < ADDR_FLASH_SECTOR_9)
+        return FLASH_Sector_8;
+    else if (addr < ADDR_FLASH_SECTOR_10)
+        return FLASH_Sector_9;
+    else if (addr < ADDR_FLASH_SECTOR_11)
+        return FLASH_Sector_10;
+    return FLASH_Sector_11;
+}
+
+// 解除写保护,清除fmc特定寄存器
+void fmc_clear_flag_star(void)
+{
+    FLASH_Unlock();              // 解锁
+    FLASH_DataCacheCmd(DISABLE); // FLASH擦除期间,必须禁止数据缓存
+    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
+}
+
+// 设置写保护,清除fmc特定寄存器
+void fmc_clear_flag_end(void)
+{
+    FLASH_DataCacheCmd(ENABLE); // FLASH擦除结束,开启数据缓存
+    FLASH_Lock();               // 上锁
+}
+
+// 读取一字节, 读取无需考虑字节对齐
+uint8_t fmc_read_byte(uint32_t read_addr)
+{
+    return *(vu8 *)read_addr;
+}
+
+// 读取两字节, 读取需考虑字节对齐
+uint16_t fmc_read_half_word(uint32_t read_addr)
+{
+    return *(vu16 *)read_addr;
+}
+
+// 读取N字节, 读取必须需考虑字节对齐
+uint8_t fmc_read_n_half_word(uint32_t read_addr, uint16_t *buff, uint16_t count)
+{
+    uint16_t i = 0;
+
+    vu16 *addr = (vu16 *)read_addr;
+
+    if (read_addr % 2 != 0)
+        return 1; // 错误返回
+
+    for (i = 0; i < count; i++)
+    {
+        *buff++ = *addr++;
+    }
+    return 0;
+}
+
+// 读取1页, 地址必须对齐页首
+uint8_t fmc_read_one_page(uint32_t read_addr, uint16_t *buff)
+{
+    uint16_t i = 0;
+
+    vu16 *addr = (vu16 *)read_addr;
+
+    if (read_addr % FMC_PAGE_SIZE != 0)
+        return 1; // 错误返回
+
+    for (i = 0; i < 1024; i++)
+    {
+        *buff++ = *addr++;
+    }
+    return 0;
+}
+
+// 擦出N页, 地址必须对齐页首
+uint8_t fmc_erase_pages(uint32_t erase_addr, uint16_t len)
+{
+    uint16_t i = 0, j = 0;
+
+    uint32_t *addr = (uint32_t *)erase_addr;
+
+    if (erase_addr % FMC_PAGE_SIZE != 0)
+        return 1; // 错误返回
+
+    for (i = 0; i < len; i++)
+    {
+        FLASH_EraseSector(fmc_get_flash_sector(erase_addr), VoltageRange_3);
+        for (j = 0; j < 512; j++)
+        {
+            if (*addr != 0xFFFFFFFF)
+                return 1;
+            else
+                addr++;
+        }
+    }
+    return 0;
+}
+
+// 只写入,写入前需擦除,地址必须两字节对齐
+uint8_t fmc_write_n_half_word(uint32_t write_addr, uint16_t *buff, uint16_t len)
+{
+
+    uint32_t end_addr = write_addr + len * 2;
+
+    if (write_addr % 2 != 0)
+        return 1;
+
+    while (write_addr < end_addr)
+    {
+
+        FLASH_ProgramHalfWord(write_addr, *buff); // 写入数据
+        if (*(vu16 *)write_addr != *buff)
+        {
+            return 1;
+        }
+        write_addr += 2;
+        buff++;
+    }
+    return 0;
+}
+
+uint16_t firmware_crc16_ccitt_false(uint16_t init_value, uint8_t *pbuff, uint32_t len)
+{
+    uint16_t temp = 0;
+    uint16_t crc  = init_value;
+
+    for (int i = 0; i < len; i++)
+    {
+        for (int j = 0; j < 8; j++)
+        {
+            temp = ((pbuff[i] << j) & 0x80) ^ ((crc & 0x8000) >> 8);
+            crc <<= 1;
+            if (temp != 0)
+            {
+                crc ^= 0x1021;
+            }
+        }
+    }
+    return crc;
+}

+ 69 - 0
hal/hal_flash.h

@@ -0,0 +1,69 @@
+#ifndef __HAL_FLASH_H
+#define __HAL_FLASH_H
+
+#ifdef __cplusplus
+extern 'C'
+{
+#endif
+#ifdef __HAL_FLASH_H_GLOBAL
+#define __HAL_FLASH_H_EXTERN
+#else
+#define __HAL_FLASH_H_EXTERN extern
+#endif
+
+/************************************************************************************************
+ *                                          Version                                              *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          How to use                                           *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Enable config                                         *
+ ************************************************************************************************/
+
+/************************************************************************************************
+ *                                          Includes                                             *
+ ************************************************************************************************/
+#include "stm32f4xx_flash.h"
+/************************************************************************************************
+ *                                          Defines                                              *
+ ************************************************************************************************/
+#define FMC_PAGE_SIZE     ((uint16_t)0x800)
+#define FMC_PAGE_SIZE_U16 ((uint16_t)0x400)
+#define FMC_FLASH_BASE    ((uint32_t)0x08000000)
+
+// FLASH 扇区的起始地址
+#define ADDR_FLASH_SECTOR_0   ((u32)0x08000000) // 扇区0起始地址, 16 Kbytes
+#define ADDR_FLASH_SECTOR_1   ((u32)0x08004000) // 扇区1起始地址, 16 Kbytes
+#define ADDR_FLASH_SECTOR_2   ((u32)0x08008000) // 扇区2起始地址, 16 Kbytes
+#define ADDR_FLASH_SECTOR_3   ((u32)0x0800C000) // 扇区3起始地址, 16 Kbytes
+#define ADDR_FLASH_SECTOR_4   ((u32)0x08010000) // 扇区4起始地址, 64 Kbytes
+#define ADDR_FLASH_SECTOR_5   ((u32)0x08020000) // 扇区5起始地址, 128 Kbytes
+#define ADDR_FLASH_SECTOR_6   ((u32)0x08040000) // 扇区6起始地址, 128 Kbytes
+#define ADDR_FLASH_SECTOR_7   ((u32)0x08060000) // 扇区7起始地址, 128 Kbytes
+#define ADDR_FLASH_SECTOR_8   ((u32)0x08080000) // 扇区8起始地址, 128 Kbytes
+#define ADDR_FLASH_SECTOR_9   ((u32)0x080A0000) // 扇区9起始地址, 128 Kbytes
+#define ADDR_FLASH_SECTOR_10  ((u32)0x080C0000) // 扇区10起始地址,128 Kbytes
+#define ADDR_FLASH_SECTOR_11  ((u32)0x080E0000) // 扇区11起始地址,128 Kbytes
+#define ADDR_FLASH_SECTOR_END ((u32)0x080FFFFF)
+    /************************************************************************************************
+     *                                          Defines                                              *
+     ************************************************************************************************/
+
+    void     fmc_clear_flag_star(void);
+    void     fmc_clear_flag_end(void);
+    uint8_t  fmc_read_byte(uint32_t read_addr);
+    uint16_t fmc_read_half_word(uint32_t read_addr);
+    uint8_t  fmc_read_n_half_word(uint32_t read_addr, uint16_t * buff, uint16_t count);
+    uint8_t  fmc_read_one_page(uint32_t read_addr, uint16_t * buff);
+    uint8_t  fmc_erase_pages(uint32_t erase_addr, uint16_t len);
+    uint8_t  fmc_write_n_half_word(uint32_t write_addr, uint16_t * buff, uint16_t len);
+    uint16_t firmware_crc16_ccitt_false(uint16_t init_value, uint8_t * pbuff, uint32_t len);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __HAL_FLASH_H

+ 25 - 0
hal/hal_systick.c

@@ -1,7 +1,13 @@
 #include "hal_systick.h"
 
+static u8  fac_us = 0; // us延时倍乘数
+static u16 fac_ms = 0; // ms延时倍乘数
+
+volatile uint32_t systick_ms = 0;
+
 void hal_systick_init(void)
 {
+    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
     if (SysTick_Config(SystemCoreClock / 1000))
     {
         while (1)
@@ -9,4 +15,23 @@ void hal_systick_init(void)
         }
     }
     NVIC_SetPriority(SysTick_IRQn, 0x00);
+}
+
+uint32_t get_systick_ms(void)
+{
+    uint32_t tick, tick_ms;
+    __disable_irq();
+    tick    = (SYSTICK_EXT_CLOCK_1MS_CNT - SysTick->VAL);
+    tick_ms = tick / (SYSTICK_EXT_CLOCK_1MS_CNT);
+    tick_ms = tick_ms + systick_ms;
+    __enable_irq();
+
+    return tick_ms;
+}
+
+void systick_handler(void)
+{
+    __disable_irq();
+    systick_ms += 1;
+    __enable_irq();
 }

+ 6 - 1
hal/hal_systick.h

@@ -3,6 +3,11 @@
 
 #include "stm32f4xx.h"
 
-void hal_systick_init(void);
+void     hal_systick_init(void);
+uint32_t get_systick_ms(void);
+
+#define SYSTICK_EXT_CLOCK_1MS_CNT (SystemCoreClock / 1000)
+
+void systick_handler(void);
 
 #endif // __HAL_SYSTICK_H

+ 359 - 0
hal/hal_uart.c

@@ -0,0 +1,359 @@
+#include "hal_uart.h"
+#include "stm32f4xx.h"
+// #include <stdint.h>
+#include <sys/unistd.h>
+
+static uint8_t usart1_tx_buf[256];
+static uint8_t usart1_rx_buf[256];
+
+#define HAL_UART1_TX_PORT   GPIOA
+#define HAL_UART1_TX_PIN    GPIO_Pin_9
+#define HAL_UART1_TX_SOURCE GPIO_PinSource9
+#define HAL_UART1_RX_PORT   GPIOA
+#define HAL_UART1_RX_PIN    GPIO_Pin_10
+#define HAL_UART1_RX_SOURCE GPIO_PinSource10
+
+int usart1_snd_tx_cnt = 0;
+
+// 加入以下代码,支持printf函数,而不需要选择use MicroLIB
+// 确保没有从 C 库链接使用半主机的函数
+#pragma import(__use_no_semihosting)
+#pragma import(__use_no_semihosting_swi)
+// 定义_sys_exit() 以避免使用半主机模式
+void _sys_exit(int x)
+{
+    x = x;
+}
+
+// 加入以下代码,支持printf函数,而不需要选择use MicroLIB
+// 标准库需要的支持函数
+struct __FILE
+{
+    int handle;
+};
+/* FILE is typedef ’ d in stdio.h. */
+FILE __stdout;
+FILE __stdin;
+
+int _ttywrch(int ch)
+{
+    ch = ch;
+    return ch;
+}
+
+// && !defined(__clang__)
+#if defined(__GNUC__)
+#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
+#define GETCHAR_PROTOTYPE int __io_getchar(void)
+#else
+#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
+#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
+#endif
+
+PUTCHAR_PROTOTYPE
+{
+    uint32_t tick;
+    usart1_snd_tx_cnt++;
+
+    usart_send_it(&usart1_context, &ch, 1);
+    tick = get_systick_ms();
+
+    while (RESET == USART_GetFlagStatus(USART1, USART_FLAG_TXE))
+    {
+        if (get_systick_ms() - tick > 10)
+            break;
+    }
+    return ch;
+}
+
+GETCHAR_PROTOTYPE
+{
+    uint8_t ch;
+    if (0 != usart_receive_read(&usart1_context, &ch, 1))
+    {
+        return ch;
+    }
+    return -1;
+}
+
+// &&!defined(__clang__)
+#if defined(__GNUC__)
+__attribute__((weak)) int _write(int file, char *ptr, int len)
+{
+    (void)file;
+    if ((file != STDOUT_FILENO) && (file != STDERR_FILENO))
+    {
+        return -1;
+    }
+
+    for (int index = 0; index < len; index++)
+        __io_putchar(*ptr++);
+    return len;
+}
+
+__attribute__((weak)) int _read(int file, char *ptr, int len)
+{
+    (void)file;
+    if (file != STDIN_FILENO)
+    {
+        return -1;
+    }
+
+    uint8_t ch;
+    for (int index = 0; index < len; index++)
+    {
+        // *ptr++ = __io_getchar();
+        if (0 != usart_receive_read(&usart1_context, &ch, 1))
+        {
+            return ch;
+        }
+        return -1;
+    }
+    return len;
+}
+#endif
+
+#if 0
+int getchar(void)
+{
+    char c = 0;
+
+    // ssize_t
+    int bytes_read = read(STDIN_FILENO, &c, sizeof(char));
+
+    if (bytes_read == -1)
+    {
+        // 读取错误
+        return EOF;
+    }
+    else if (bytes_read == 0)
+    {
+        // 读取结束
+        return EOF;
+    }
+    else
+    {
+        // 返回读取的字符
+        return (int)c;
+    }
+}
+#else
+int getchar(void)
+{
+    uint8_t ch;
+    if (0 != usart_receive_read(&usart1_context, &ch, 1))
+    {
+        return ch;
+    }
+    return -1;
+}
+#endif
+
+static void usart1_config(void)
+{
+    GPIO_InitTypeDef GPIO_StructInit;
+    NVIC_InitTypeDef NVIC_InitStructure;
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
+
+    GPIO_StructInit.GPIO_Mode  = GPIO_Mode_AF;
+    GPIO_StructInit.GPIO_OType = GPIO_OType_PP;
+    GPIO_StructInit.GPIO_Speed = GPIO_Speed_100MHz;
+    GPIO_StructInit.GPIO_PuPd  = GPIO_PuPd_UP;
+    GPIO_StructInit.GPIO_Pin   = HAL_UART1_TX_PIN;
+    GPIO_PinAFConfig(HAL_UART1_TX_PORT, HAL_UART1_TX_SOURCE, GPIO_AF_USART1);
+    GPIO_Init(HAL_UART1_TX_PORT, &GPIO_StructInit);
+
+    GPIO_StructInit.GPIO_Pin = HAL_UART1_RX_PIN;
+    GPIO_PinAFConfig(HAL_UART1_RX_PORT, HAL_UART1_RX_SOURCE, GPIO_AF_USART1);
+    GPIO_Init(HAL_UART1_RX_PORT, &GPIO_StructInit);
+
+    // Usart1 NVIC 配置
+    NVIC_InitStructure.NVIC_IRQChannel                   = USART1_IRQn; // 串口1中断通道
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           // 抢占优先级
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;           // 子优先级
+    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // IRQ通道使能
+    NVIC_Init(&NVIC_InitStructure);
+}
+
+static void usart1_deconfig(void)
+{
+}
+
+usart_context_t usart1_context = {
+    USART1,
+    usart1_tx_buf,
+    sizeof(usart1_tx_buf),
+    0,
+    0,
+    0,
+    usart1_rx_buf,
+    sizeof(usart1_rx_buf),
+    0,
+    0,
+    0,
+    usart1_config,
+    usart1_deconfig};
+
+void usart_config_init(usart_context_t *p_usart_content, uint32_t band_rate)
+{
+    p_usart_content->config();
+
+    USART_InitTypeDef USART_InitStructure;
+
+    USART_InitStructure.USART_BaudRate            = band_rate;
+    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
+    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
+    USART_InitStructure.USART_Parity              = USART_Parity_No;
+    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;
+    USART_Init(p_usart_content->usart_periph, &USART_InitStructure); // 初始化串口1
+
+    USART_ITConfig(p_usart_content->usart_periph, USART_IT_RXNE, ENABLE);
+
+    USART_Cmd(USART1, ENABLE); // 使能串口1
+}
+
+void usart_config_deinit(usart_context_t *p_usart_content)
+{
+    USART_DeInit(p_usart_content->usart_periph);
+    p_usart_content->deconfig();
+}
+
+void usart_send(usart_context_t *p_usart_content, const void *_send_buf, const uint16_t send_count)
+{
+    const uint8_t *send_buf = (const uint8_t *)_send_buf;
+    uint16_t       i;
+    for (i = 0; i < send_count; i++)
+    {
+        while (RESET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TXE))
+            ;
+        USART_SendData(p_usart_content->usart_periph, (uint8_t)send_buf[i]);
+    }
+    while (RESET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TC))
+        ;
+}
+
+void usart_send_it(usart_context_t *p_usart_content, const void *_send_buf, const uint16_t send_count)
+{
+    const uint8_t *send_buf = (const uint8_t *)_send_buf;
+    uint16_t       i;
+    uint16_t       left;
+
+    // 空间不够直接返回
+    if (p_usart_content->tx_wr >= p_usart_content->tx_rd)
+    {
+        left = p_usart_content->tx_buf_size - (p_usart_content->tx_wr - p_usart_content->tx_rd);
+    }
+    else
+    {
+        left = p_usart_content->tx_rd - p_usart_content->tx_wr;
+        if (send_count > left)
+        {
+            p_usart_content->tx_err++;
+            return;
+        }
+    }
+
+    // 内存拷贝
+    for (i = 0; i < send_count; i++)
+    {
+        // send buffer overflow just wait
+        p_usart_content->tx_buf[p_usart_content->tx_wr++] = send_buf[i];
+        p_usart_content->tx_wr %= p_usart_content->tx_buf_size;
+    }
+
+    // 使能发送缓存空中断
+    USART_ITConfig(p_usart_content->usart_periph, USART_IT_TXE, ENABLE);
+}
+
+void usart_wait_send_finished(usart_context_t *p_usart_content)
+{
+    while (p_usart_content->tx_wr != p_usart_content->tx_rd)
+        ;
+    while (RESET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TC))
+        ;
+}
+
+int usart_receive_read(usart_context_t *p_usart_context, void *_receive_buf, const int receive_count)
+{
+    uint8_t *receive_buf = (uint8_t *)_receive_buf;
+    int      i, receive_count_real;
+
+    /* Read data from receive buffer.
+     *The buffer have data that received from usart.
+     */
+    for (i = 0, receive_count_real = 0; i < receive_count; i++)
+    {
+        if (p_usart_context->rx_rd == p_usart_context->rx_wr)
+        {
+            return receive_count_real;
+        }
+        else
+        {
+            receive_buf[i] = p_usart_context->rx_buf[p_usart_context->rx_rd++];
+            p_usart_context->rx_rd %= p_usart_context->rx_buf_size;
+            receive_count_real++;
+        }
+    }
+    return receive_count_real;
+}
+
+static void usart_rxne_it(usart_context_t *p_usart_content)
+{
+    p_usart_content->rx_buf[p_usart_content->rx_wr++] = USART_ReceiveData(p_usart_content->usart_periph);
+    p_usart_content->rx_wr %= p_usart_content->rx_buf_size;
+
+    // overflow handle
+    if (p_usart_content->rx_wr == p_usart_content->rx_rd)
+    {
+        p_usart_content->rx_rd++;
+        p_usart_content->rx_rd %= p_usart_content->rx_buf_size;
+    }
+}
+
+static void usart_txe_it(usart_context_t *p_usart_content)
+{
+    if (p_usart_content->tx_rd != p_usart_content->tx_wr)
+    {
+        USART_SendData(p_usart_content->usart_periph, p_usart_content->tx_buf[p_usart_content->tx_rd++]);
+        p_usart_content->tx_rd %= p_usart_content->tx_buf_size;
+    }
+    else
+    {
+        USART_ITConfig(p_usart_content->usart_periph, USART_IT_TXE, DISABLE);
+    }
+}
+
+void usart_it(usart_context_t *p_usart_content)
+{
+    // 读取缓沖区非空中断
+    if (SET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_RXNE))
+    {
+        USART_ClearFlag(p_usart_content->usart_periph, USART_FLAG_RXNE);
+        usart_rxne_it(p_usart_content);
+    }
+
+    // 发送缓沖区空中断
+    if (SET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TXE))
+    {
+        USART_ClearFlag(p_usart_content->usart_periph, USART_FLAG_TXE);
+        usart_txe_it(p_usart_content);
+    }
+
+    // // 发送完成中断
+    // if (RESET != USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TC))
+    // {
+    //     USART_ITConfig(p_usart_content->usart_periph, USART_FLAG_TC, DISABLE);
+    //     USART_ITConfig(p_usart_content->usart_periph, USART_FLAG_RXNE, ENABLE);
+    // }
+
+    // 发送错误
+    if (RESET != USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_ORE))
+        USART_ClearFlag(p_usart_content->usart_periph, USART_FLAG_ORE);
+}
+
+void USART1_IRQHandler(void)
+{
+    usart_it(&usart1_context);
+}

+ 41 - 0
hal/hal_uart.h

@@ -0,0 +1,41 @@
+#ifndef __UART_H
+#define __UART_H
+#include "hal_systick.h"
+#include "stdio.h"
+
+#pragma pack(0)
+typedef struct
+{
+    USART_TypeDef *usart_periph;
+    uint8_t       *tx_buf;
+    uint16_t       tx_buf_size;
+    uint16_t       tx_rd;
+    uint16_t       tx_wr;
+    uint16_t       tx_err;
+    uint8_t       *rx_buf;
+    uint16_t       rx_buf_size;
+    uint16_t       rx_rd;
+    uint16_t       rx_wr;
+    uint16_t       rx_err;
+    void (*config)(void);
+    void (*deconfig)(void);
+} usart_context_t;
+#pragma pack()
+
+void    usart_config_init(usart_context_t *p_usart_content, uint32_t band_rate);
+void    usart_config_deinit(usart_context_t *p_usart_content);
+void    usart_send_it(usart_context_t *p_usart_content, const void *_send_buf, const uint16_t send_count);
+void    usart_wait_send_finished(usart_context_t *p_usart_content);
+int32_t usart_read_until_char(usart_context_t *p_usart_content, char c);
+int32_t usart_read_until_mem(usart_context_t *p_usart_content, char mem, int len);
+int32_t usart_read_ble_format(usart_context_t *p_usart_content);
+int32_t usart_read_update(usart_context_t *p_usart_content, int rlen, char *data);
+int32_t usart_read_drop(usart_context_t *p_usart_content);
+void    usart_it(usart_context_t *p_usart_content);
+int     usart_receive_read(usart_context_t *p_usart_context, void *_receive_buf, const int receive_count);
+void    usart_printf(usart_context_t *p_usart_context, char *args, ...);
+void    u_tm_log(char *args, ...);
+void    u_log(char *arg, ...);
+
+extern usart_context_t usart1_context;
+#endif

+ 0 - 137
hal/hal_uart1.c

@@ -1,137 +0,0 @@
-#include "hal_uart1.h"
-
-#define HAL_UART1_TX_PORT   GPIOA
-#define HAL_UART1_TX_PIN    GPIO_Pin_9
-#define HAL_UART1_TX_SOURCE GPIO_PinSource9
-#define HAL_UART1_RX_PORT   GPIOA
-#define HAL_UART1_RX_PIN    GPIO_Pin_10
-#define HAL_UART1_RX_SOURCE GPIO_PinSource10
-
-static uint8_t uart1_tx_buf[UART1_TX_LEN]  = {0};
-static uint8_t uart1_rx_buf[UART1_REC_LEN] = {0};
-
-__IO uint8_t rx_index = 0x00;
-
-__IO uint8_t tx_index = 0x00;
-
-__IO uint8_t TimeOut = 0x00;
-
-//  重定义fputc函数
-#ifdef __GNUC__
-
-int _write(int fd, char *buffer, int size)
-{
-    /* 写一个字节到USART1 */
-    for (int i = 0; i < size; i++)
-    {
-        USART_SendData(USART1, buffer[i]);
-        /* 等待发送结束 */
-        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
-            ;
-    }
-
-    return size;
-}
-int _read(int fd, char *buffer, int size)
-{
-
-    for (int i = 0; i < size; i++)
-    {
-        /* 等待串口1输入数据 */
-        while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
-            ;
-        buffer[i] = USART_ReceiveData(USART1);
-    }
-    return size;
-}
-#endif
-
-void hal_uart1_nvic_config(void)
-{
-    NVIC_InitTypeDef NVIC_InitStructure;
-    // Usart1 NVIC 配置
-    NVIC_InitStructure.NVIC_IRQChannel                   = USART1_IRQn; // 串口1中断通道
-    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;           // 抢占优先级
-    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;           // 子优先级
-    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // IRQ通道使能
-    NVIC_Init(&NVIC_InitStructure);                                     // 根据指定的参数初始化VIC寄存器
-}
-
-void hal_uart1_gpio_config(void)
-{
-    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
-    GPIO_InitTypeDef GPIO_StructInit;
-    GPIO_StructInit.GPIO_Mode  = GPIO_Mode_AF;
-    GPIO_StructInit.GPIO_OType = GPIO_OType_PP;
-    GPIO_StructInit.GPIO_Speed = GPIO_Speed_100MHz;
-    GPIO_StructInit.GPIO_PuPd  = GPIO_PuPd_UP;
-    GPIO_StructInit.GPIO_Pin   = HAL_UART1_TX_PIN;
-    GPIO_PinAFConfig(HAL_UART1_TX_PORT, HAL_UART1_TX_SOURCE, GPIO_AF_USART1);
-    GPIO_Init(HAL_UART1_TX_PORT, &GPIO_StructInit);
-
-    GPIO_StructInit.GPIO_Pin = HAL_UART1_RX_PIN;
-    GPIO_PinAFConfig(HAL_UART1_RX_PORT, HAL_UART1_RX_SOURCE, GPIO_AF_USART1);
-    GPIO_Init(HAL_UART1_RX_PORT, &GPIO_StructInit);
-}
-void hal_uart1_config(void)
-{
-
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
-
-    USART_InitTypeDef USART_InitStructure;
-    I2C_DeInit(I2C1);
-
-    USART_InitStructure.USART_BaudRate            = 9600;
-    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
-    USART_InitStructure.USART_WordLength          = USART_StopBits_1;
-    USART_InitStructure.USART_Parity              = USART_Parity_No;
-    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
-    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;
-
-    USART_Init(USART1, &USART_InitStructure);
-
-    /* 使能 USART */
-    USART_Cmd(USART1, ENABLE);
-}
-
-void hal_uart1_init(void)
-{
-    hal_uart1_gpio_config();
-    hal_uart1_config();
-    hal_uart1_nvic_config();
-
-    USART_ClearFlag(USART1, USART_FLAG_TC);
-}
-
-void USART1_IRQHandler(void)
-{
-    /* 处理接收中断 */
-    if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
-    {
-        if (rx_index < UART1_REC_LEN)
-        {
-            /* 接收数据 */
-            uart1_rx_buf[rx_index++] = USART_ReceiveData(USART1);
-        }
-        else
-        {
-            /* 禁止接收中断 */
-            USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
-        }
-    }
-    /* 处理发送缓冲区空中断 */
-    if (USART_GetITStatus(USART1, USART_IT_TXE) == SET)
-
-    {
-        if (tx_index < UART1_TX_LEN)
-        {
-            /* 发送数据 */
-            USART_SendData(USART1, uart1_tx_buf[tx_index++]);
-        }
-        else
-        {
-            /* 禁止发送缓冲区空中断 */
-            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
-        }
-    }
-}

+ 0 - 11
hal/hal_uart1.h

@@ -1,11 +0,0 @@
-#ifndef __HAL_UART1_H
-#define __HAL_UART1_H
-
-#include "stm32f4xx.h"
-
-#define UART1_REC_LEN 128
-#define UART1_TX_LEN  128
-
-void hal_uart1_init(void);
-
-#endif // __HAL_UART1_H

+ 179 - 0
hal/platform_queue.c

@@ -0,0 +1,179 @@
+// #include "platform_queue.h"
+
+// t_queue can_rx;
+// t_queue can_tx;
+
+// void queue_mode(t_queue *this, uint8_t mode)
+// {
+//     this->mode = mode;
+// }
+
+// void queue_empty_one(t_queue *this, pdu_tag **head, pdu_tag **tail, pdu_tag (*buff)[DATA_BUFF_NUM], uint8_t lock)
+// {
+//     *(head + lock)   = buff[lock];
+//     *(tail + lock)   = buff[lock];
+//     this->full[lock] = 0;
+// }
+
+// // 清空队列
+// void queue_empty(t_queue *this, pdu_tag **head, pdu_tag **tail, pdu_tag (*buff)[DATA_BUFF_NUM])
+// {
+//     for (int i = 0; i < QUEUE_BUFFER_SUM; i++)
+//     {
+//         *(head + i)   = this->buff[i];
+//         *(tail + i)   = buff[i];
+//         this->full[i] = 0;
+//     }
+//     this->lock = 0;
+//     this->idle = 0;
+// }
+
+// void qudeue_empty(t_queue *this, pdu_tag **head, pdu_tag **tail, pdu_tag (*buff)[DATA_BUFF_NUM])
+// {
+//     for (int i = 0; i < QUEUE_BUFFER_SUM; i++)
+//     {
+//         *(head + i)   = this->buff[i];
+//         *(tail + i)   = buff[i];
+//         this->full[i] = 0;
+//     }
+//     this->lock = 0;
+//     this->idle = 0;
+// }
+
+// // 队列长度计算
+// void length_queue(t_queue *this, pdu_tag **head, pdu_tag **tail, uint8_t len)
+// {
+//     for (int i = 0; i < QUEUE_BUFFER_SUM; i++)
+//     {
+//         if (*(tail + i) > *(head + i))
+//         {
+//             this->length[i] = *(tail + i) - *(head + i);
+//         }
+//         if (*(tail + i) < *(head + i))
+//         {
+//             this->length[i] = *(tail + i) + len - *(head + i);
+//         }
+//         if (*(tail + i) == *(head + i) && this->full[i])
+//         {
+//             this->length[i] = len;
+//         }
+//         if (*(tail + i) == *(head + i) && !this->full[i])
+//         {
+//             this->length[i] = 0;
+//         }
+//     }
+// }
+
+// // 入队
+// void push_queue(t_queue *this, pdu_tag **head, pdu_tag **tail, pdu_tag (*buff)[DATA_BUFF_NUM], uint8_t len, pdu_tag *data, uint8_t data_len)
+// {
+//     if (this->mode)
+//     {
+//         // 空闲清除读队列
+//         if (this->idle == 0)
+//         {
+//             empty_one_queue((*this), !this->lock);
+//         }
+//         // 非空闲清除写队列
+//         empty_one_queue((*this), this->lock);
+//     }
+
+//     for (int num = 0; num < data_len; num++, data++)
+//     {
+//         if (!this->mode)
+//         {
+//             queue_update((*this));
+//             if ((this->length[0] + this->length[1]) >= 4 && !this->idle)
+//             {
+//                 if (this->length[!this->lock] == 0)
+//                 {
+//                     this->lock              = !this->lock;
+//                     this->full[!this->lock] = 0;
+//                 }
+
+//                 for (int i = 0; i <= ((this->length[this->lock] + this->length[!this->lock]) - 4); i++)
+//                 {
+//                     if (++(*(head + !this->lock)) == buff[!this->lock] + len)
+//                     {
+//                         *(head + !this->lock) = buff[!this->lock];
+//                     }
+//                     if (*(tail + !this->lock) == *(head + !this->lock) && this->full[!this->lock] == 0)
+//                     {
+//                         break;
+//                     }
+//                 }
+//             }
+//         }
+//         // 队列长度更新
+//         queue_update((*this));
+//         /*单纯的数据存储*/
+//         **(tail + this->lock) = *data;
+//         // 队列满
+//         if (this->full[this->lock] == 1)
+//         {
+//             if (++(*(head + this->lock)) == buff[this->lock] + len)
+//             {
+//                 *(head + this->lock) = buff[this->lock];
+//             }
+//             if (++(*(tail + this->lock)) == buff[this->lock] + len)
+//             {
+//                 *(tail + this->lock) = buff[this->lock];
+//             }
+//         }
+//         // 队列未满
+//         else
+//         {
+//             if (++(*(tail + this->lock)) == buff[this->lock] + len)
+//             {
+//                 *(tail + this->lock) = buff[this->lock];
+//             }
+//             if (*(tail + this->lock) == *(head + this->lock))
+//             {
+//                 this->full[this->lock] = 1;
+//             }
+//         }
+//     }
+//     // 队列长度更新
+//     queue_update((*this));
+// }
+
+// // 出队
+// void pull_queue(t_queue *this, pdu_tag **head, pdu_tag **tail, pdu_tag (*buff)[DATA_BUFF_NUM], uint8_t len, pdu_tag *data)
+// {
+//     this->idle = 1;
+//     this->ret  = 0;
+//     // 非空队列
+//     if (!(*(tail + !this->lock) == *(head + !this->lock) && this->full[!this->lock] == 0))
+//     {
+//         *data = **(head + !this->lock);
+//         // 指针指向溢出,指向数组首地址
+//         if (++(*(head + !this->lock)) == buff[!this->lock] + len)
+//         {
+//             *(head + !this->lock) = buff[!this->lock];
+//         }
+//         this->full[!this->lock] = 0;
+//         this->ret               = 1;
+//     }
+//     queue_update((*this));
+//     // 出队时判断当前队列是否为空队列,若为空队列且从队列不为空队列,则跳转,若前面没有获取到数据,重新到跳转队列获取数据
+//     if (this->length[this->lock] != 0 && this->length[!this->lock] == 0)
+//     {
+//         this->lock = !this->lock;
+//         if (this->ret == 0)
+//         {
+//             de_queue((*this), data);
+//         }
+//     }
+//     // 这里结束 队列为空闲态
+//     this->idle = 0;
+// }
+
+// void can_queue_init(void)
+// {
+//     // 提前初始化,否则由于指针问题,HardFault_Handler()
+//     empty_queue(can_rx);
+//     mode_queue(can_rx, TASKQUEUE);
+//     // 提前初始化,否则由于指针问题,HardFault_Handler()
+//     empty_queue(can_tx);
+//     mode_queue(can_tx, TASKQUEUE);
+// }

+ 81 - 0
hal/platform_queue.h

@@ -0,0 +1,81 @@
+// #ifndef __PLATFROM_QUEUE_H
+// #define __PLATFROM_QUEUE_H
+// #include "stdio.h"
+
+// #define MAX_QSIZE (60u) /* 最大队列长度 */
+
+// typedef unsigned long long uint64_t;
+
+// typedef struct
+// {
+//     struct
+//     {
+//         uint8_t ide;
+//         uint8_t rtr;
+//         uint8_t dlc;
+//     } reg;
+//     union
+//     {
+//         uint32_t r;
+//         struct
+//         {
+//             uint8_t sa : 8;
+//             uint8_t ps : 8;
+//             uint8_t pf : 8;
+//             uint8_t dp : 1;
+//             uint8_t r  : 1;
+//             uint8_t p  : 3;
+//         } b;
+//     } id;
+//     union
+//     {
+//         uint8_t  u8_buf[8];
+//         uint16_t u16_buf[4];
+//         uint32_t u32_buf[2];
+//         uint64_t u64_buf;
+//     } data;
+// } pdu_tag, *p_pdu_tag;
+
+// typedef struct
+// {
+//     uint16_t head;
+//     uint16_t tail;
+//     uint16_t count;
+//     pdu_tag  can_message[MAX_QSIZE];
+// } can_queue_tag, *p_can_queue_tag;
+
+// typedef enum
+// {
+//     DATEQUEUE = 0,
+//     TASKQUEUE = 1,
+// } queuemode_e;
+
+// typedef struct
+// {
+// #define QUEUE_BUFFER_SUM 2
+// #define DATA_BUFF_NUM    5
+//     uint8_t  full[QUEUE_BUFFER_SUM];
+//     uint8_t  length[QUEUE_BUFFER_SUM];
+//     uint8_t  ret, lock, idle, mode;
+//     pdu_tag *head[QUEUE_BUFFER_SUM];
+//     pdu_tag *tail[QUEUE_BUFFER_SUM];
+//     pdu_tag  buff[QUEUE_BUFFER_SUM][DATA_BUFF_NUM];
+// } t_queue;
+
+// void queue_mode(t_queue *this, uint8_t mode);
+// void push_queue(t_queue *this, pdu_tag **head, pdu_tag **tail, pdu_tag (*buff)[DATA_BUFF_NUM], uint8_t len, pdu_tag *data, uint8_t data_len);
+// void pull_queue(t_queue *this, pdu_tag **head, pdu_tag **tail, pdu_tag (*buff)[DATA_BUFF_NUM], uint8_t len, pdu_tag *data);
+
+// #define queue_update(this)             length_queue(&this, this.head, this.tail, sizeof((this).buff[0]))
+// #define empty_queue(this)              queue_empty(&this, this.head, this.tail, this.buff)
+// #define empty_one_queue(this, lock)    queue_empty_one(&this, this.head, this.tail, this.buff, (lock))
+// #define en_queue(this, data, data_len) push_queue(&this, this.head, this.tail, this.buff, sizeof((this).buff[0]), (data), (data_len))
+// #define de_queue(this, data)           pull_queue(&this, this.head, this.tail, this.buff, sizeof((this).buff[0]), (data))
+// #define mode_queue(this, mode)         queue_mode(&this, (mode));
+
+// extern t_queue can_tx;
+// extern t_queue can_rx;
+
+// void can_queue_init(void);
+
+// #endif

+ 104 - 0
hal/queue.c

@@ -0,0 +1,104 @@
+#include "queue.h"
+
+///   front   ...         rear      数据方向 ->
+/* 队列的顺序存储结构(循环队列) */
+
+can_queue_tag can_tx_queue;
+can_queue_tag can_rx_queue;
+
+/****************************************************
+ *  函 数 名:init_queue
+ *  函数功能:初始化队列
+ *  入口参数:无
+ *  说    明:
+ ****************************************************/
+void queue_init(p_can_queue_tag p_queue)
+{                                      /* 构造一个空队列Q */
+    p_queue->head = p_queue->tail = 0; /*空队列*/
+    p_queue->count                = 0;
+}
+
+/****************************************************
+ *  函 数 名:is_queue_empty
+ *  函数功能:查询队列是否为空
+ *  入口参数:Q 队列
+ *  说    明:空队列,返回SUCCESS;否则返回ERROR
+ ****************************************************/
+uint8_t queue_empty(p_can_queue_tag p_queue)
+{ /* 若*/
+    return p_queue->count == 0;
+}
+
+uint8_t queue_full(p_can_queue_tag p_queue)
+{ /* 若*/
+    return p_queue->count == MAX_QSIZE;
+}
+
+/****************************************************
+ *  函 数 名:queue_length
+ *  函数功能:初始化长度
+ *  入口参数:Q 队列
+ *  说    明:
+ ****************************************************/
+uint16_t queue_length(can_queue_tag p_queue)
+{ /* 返回Q的元素个数,即队列的长度 */
+    return (p_queue.tail - p_queue.head + MAX_QSIZE) % MAX_QSIZE;
+}
+
+/****************************************************
+ *  函 数 名:get_head
+ *  函数功能:获取对头数据
+ *  入口参数:Q 队列
+ *  说    明:
+ ****************************************************/
+uint8_t get_head(
+    can_queue_tag *p_queue,
+    pdu_tag       *e)
+{                                       /* 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR*/
+    if (p_queue->head == p_queue->tail) /* 队列空 */
+        return Q_ERR;
+    *e = p_queue->can_message[p_queue->head];
+
+    p_queue->head = (p_queue->head + 1) % MAX_QSIZE;
+    return Q_OK;
+}
+
+/****************************************************
+ *  函 数 名:insert_queue
+ *  函数功能:队列插入数据
+ *  入口参数:Q 待插入队列    e 待插入数据
+ *  说    明:
+ ****************************************************/
+QUEUE_STATUS en_queue(p_can_queue_tag p_queue,
+                      pdu_tag         data)
+{
+    if (queue_full(p_queue))
+        return Q_FULL;
+    p_queue->count++;
+    p_queue->can_message[p_queue->head] = data;
+    p_queue->head                       = (p_queue->head + 1) % MAX_QSIZE;
+    return Q_OK;
+    /* 插入元素e为Q的新的队尾元素 */
+    // if ((p_queue->tail + 1) % MAX_QSIZE == p_queue->head) /* 队列满 */
+    //     return ERROR;
+    // p_queue->can_message[p_queue->tail] = e;
+    // p_queue->tail                       = (p_queue->tail + 1) % MAX_QSIZE;
+    // return SUCCESS;
+}
+
+QUEUE_STATUS de_queue(p_can_queue_tag p_queue,
+                      p_pdu_tag       p_data)
+{ /* 插入元素e为Q的新的队尾元素 */
+    // if ((p_queue->tail + 1) % MAX_QSIZE == p_queue->head) /* 队列满 */
+    //     return ERROR;
+    // p_queue->can_message[p_queue->tail] = e;
+    // p_queue->tail                       = (p_queue->tail + 1) % MAX_QSIZE;
+    // return SUCCESS;
+    if (queue_empty(p_queue))
+        return Q_EMPTY;
+    *p_data       = p_queue->can_message[p_queue->tail];
+    p_queue->tail = (p_queue->tail + 1) % MAX_QSIZE;
+    p_queue->count--;
+
+    return Q_OK;
+}

+ 70 - 0
hal/queue.h

@@ -0,0 +1,70 @@
+#ifndef __QUEUE_H
+#define __QUEUE_H
+#include "stdio.h"
+
+#define MAX_QSIZE (60u) /* 最大队列长度 */
+
+typedef unsigned long long u64;
+
+typedef struct
+{
+    struct
+    {
+        uint8_t ide;
+        uint8_t rtr;
+        uint8_t dlc;
+    } reg;
+    union
+    {
+        uint32_t r;
+        struct
+        {
+            uint8_t sa : 8;
+            uint8_t ps : 8;
+            uint8_t pf : 8;
+            uint8_t dp : 1;
+            uint8_t r  : 1;
+            uint8_t p  : 3;
+        } b;
+    } id;
+    union
+    {
+        uint8_t  u8_buf[8];
+        uint16_t u16_buf[4];
+        uint32_t u32_buf[2];
+        u64      u64_buf;
+    } data;
+} pdu_tag, *p_pdu_tag;
+
+typedef struct
+{
+    uint8_t  buf[8];
+    uint32_t can_id;
+} CanData_TypeDef;
+
+typedef struct
+{
+    uint16_t head;
+    uint16_t tail;
+    uint16_t count;
+    pdu_tag  can_message[MAX_QSIZE];
+} can_queue_tag, *p_can_queue_tag;
+
+typedef enum
+{
+    Q_OK,
+    Q_ERR,
+    Q_FULL,
+    Q_EMPTY,
+} QUEUE_STATUS;
+
+extern can_queue_tag can_tx_queue;
+extern can_queue_tag can_rx_queue;
+
+void         queue_init(p_can_queue_tag);  // 初始化队列
+uint8_t      queue_empty(p_can_queue_tag); // 查询队列是否为空
+uint8_t      queue_full(p_can_queue_tag);
+uint8_t      get_head(can_queue_tag *p_queue, pdu_tag *data); // 获取对头数据
+QUEUE_STATUS en_queue(p_can_queue_tag, pdu_tag);              // 队列插入数据
+QUEUE_STATUS de_queue(p_can_queue_tag, p_pdu_tag);
+#endif

+ 1 - 1
project/gcc/STM32F417IG_FLASH.ld

@@ -40,7 +40,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
 /* Specify the memory areas */
 MEMORY
 {
-  FLASH (rx)      : ORIGIN = 0x08010000, LENGTH = 960K
+  FLASH (rx)      : ORIGIN = 0x08007000, LENGTH = 960K
   RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
   MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
   CCMRAM (rw)     : ORIGIN = 0x10000000, LENGTH = 64K

+ 15 - 1
user/main.c

@@ -1,13 +1,27 @@
 
 #include "app_conf.h"
+#include "core_cmFunc.h"
 #include "dev_conf.h"
+#include "hal_can.h"
 #include "hal_conf.h"
+#include "misc.h"
+
+#define APP_FLASH_OFFSET 0x7000
+#define BOOT_EN          1
 
 int main(void)
 {
+#if (BOOT_EN == 1)
+    NVIC_SetVectorTable(NVIC_VectTab_FLASH, APP_FLASH_OFFSET);
+    __set_PRIMASK(0);
+#endif
+
+    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
     hal_systick_init();
     hal_gpio_init();
-    hal_uart1_init();
+    // can_queue_init();
+    dev_can_network_init();
+    usart_config_init(&usart1_context, 115200);
     hal_i2c1_init();
     dev_key_button_init();