Просмотр исходного кода

!225 update: 完善airlink-spi主机驱动
* add: 增加airlink从机延时统计
* fix: 修改rdy中断队列信息为1
* fix: 修复airlink主机spi传输不稳定的问题

Wendal 7 месяцев назад
Родитель
Сommit
9cf6039181

+ 1 - 1
components/airlink/include/luat_airlink.h

@@ -79,7 +79,7 @@ void luat_airlink_task_start(void);
 void luat_airlink_print_buff(const char* tag, uint8_t* buff, size_t len);
 void luat_airlink_on_data_recv(uint8_t *data, size_t len);
 
-void airlink_wait_for_slave_ready(size_t timeout_ms);
+void airlink_wait_for_slave_reply(size_t timeout_ms);
 void airlink_transfer_and_exec(uint8_t *txbuff, uint8_t *rxbuff);
 void airlink_wait_and_prepare_data(uint8_t *txbuff);
 

+ 1 - 1
components/airlink/src/luat_airlink_fota.c

@@ -60,8 +60,8 @@ static void pack_and_send(uint16_t cmd_id, uint8_t *data, size_t len)
 
     luat_airlink_data_pack(cmd, sizeof(luat_airlink_cmd_t) + len, s_airlink_fota_txbuff);
     // LLOGD("发送sFOTA %d %d", cmd->cmd, cmd->len);
-    airlink_wait_for_slave_ready(5000);
     airlink_transfer_and_exec(s_airlink_fota_txbuff, s_airlink_fota_rxbuff);
+    airlink_wait_for_slave_reply(5000); // 等待从机回复完成接收
 
     memset(s_airlink_fota_txbuff, 0, AIRLINK_SFOTA_BUFF_SIZE);
 }

+ 90 - 26
components/airlink/src/task/luat_airlink_spi_master_task.c

@@ -45,6 +45,7 @@ static uint8_t basic_info[256];
 // static uint32_t is_waiting_queue = 0;
 
 static luat_rtos_queue_t evt_queue;
+static luat_rtos_queue_t rdy_evt_queue;  // 专门用于RDY事件(id=6)的队列
 
 extern luat_airlink_irq_ctx_t g_airlink_irq_ctx;
 extern luat_airlink_irq_ctx_t g_airlink_wakeup_irq_ctx;
@@ -52,6 +53,23 @@ extern luat_airlink_irq_ctx_t g_airlink_wakeup_irq_ctx;
 luat_airlink_irq_ctx_t g_airlink_irq_ctx;
 luat_airlink_irq_ctx_t g_airlink_wakeup_irq_ctx;
 
+// RDY引脚中断等待相关变量
+static volatile uint8_t rdy_ready_flag = 0;           // RDY就绪标志
+
+// RDY引脚下降沿中断处理函数,设置就绪标志并发送事件
+__AIRLINK_CODE_IN_RAM__ static int rdy_pin_irq_handler(void* param)
+{
+    // 设置RDY就绪标志
+    rdy_ready_flag = 1;
+    
+    // 发送通知事件,告知任务RDY已就绪
+    luat_event_t evt = {.id = 6};
+    luat_rtos_queue_send(rdy_evt_queue, &evt, sizeof(evt), 0);
+    
+    // LLOGD("RDY中断触发,设置就绪标志");
+    return 0;
+}
+
 __AIRLINK_CODE_IN_RAM__ static int slave_irq_cb(void *data, void *args)
 {
     uint32_t len = 0;
@@ -123,12 +141,24 @@ static void spi_gpio_setup(void)
     luat_gpio_cfg_t gpio_cfg = {0};
 
     // 从机准备好脚
+    // luat_gpio_set_default_cfg(&gpio_cfg);
+    // gpio_cfg.pin = AIRLINK_SPI_RDY_PIN;
+    // gpio_cfg.mode = LUAT_GPIO_INPUT;
+    // gpio_cfg.irq_type = LUAT_GPIO_FALLING_IRQ;
+    // gpio_cfg.pull = 0;
+    // luat_gpio_open(&gpio_cfg);
+
+    // 设置RDY引脚中断,
     luat_gpio_set_default_cfg(&gpio_cfg);
     gpio_cfg.pin = AIRLINK_SPI_RDY_PIN;
-    gpio_cfg.mode = LUAT_GPIO_INPUT;
-    gpio_cfg.irq_type = LUAT_GPIO_FALLING_IRQ;
-    gpio_cfg.pull = 0;
+    gpio_cfg.mode = LUAT_GPIO_IRQ;
+    gpio_cfg.irq_type = LUAT_GPIO_FALLING_IRQ;  // 下降沿中断
+    gpio_cfg.pull = LUAT_GPIO_PULLUP;
+    gpio_cfg.irq_cb = rdy_pin_irq_handler;
     luat_gpio_open(&gpio_cfg);
+    if (g_airlink_debug) {
+        LLOGD("RDY引脚中断模式已启用");
+    }
 
     // CS片选脚
     luat_gpio_set_default_cfg(&gpio_cfg);
@@ -178,6 +208,8 @@ static uint8_t slave_is_irq_ready = 0;
 
 __AIRLINK_CODE_IN_RAM__ void airlink_transfer_and_exec(uint8_t *txbuff, uint8_t *rxbuff)
 {
+    // 拉低片选, 准备发送数据
+    luat_gpio_set(AIRLINK_SPI_CS_PIN, 0);
     // 清除link
     memset(&s_link, 0, sizeof(airlink_link_data_t));
     airlink_link_data_t *link = NULL;
@@ -205,30 +237,57 @@ __AIRLINK_CODE_IN_RAM__ void airlink_transfer_and_exec(uint8_t *txbuff, uint8_t
     }
 }
 
-__AIRLINK_CODE_IN_RAM__ void airlink_wait_for_slave_ready(size_t timeout_ms)
+__AIRLINK_CODE_IN_RAM__ void airlink_wait_for_slave_reply(size_t timeout_ms)
 {
-    luat_gpio_set(AIRLINK_SPI_CS_PIN, 0); // 拉低片选, 等待从机就绪
-    int tmpval = 0;
-    for (size_t i = 0; i < timeout_ms; i++)
-    {
-        tmpval = luat_gpio_get(AIRLINK_SPI_RDY_PIN);
-        if (tmpval == 1)
-        {
-            g_airlink_statistic.wait_rdy.total++;
-            if (g_airlink_debug)
-            {
-                tnow = luat_mcu_tick64_ms();
-                if (tnow - warn_slave_no_ready > 1000)
-                {
-                    warn_slave_no_ready = tnow;
-                    LLOGD("从机未就绪,等1ms");
+    // 低速发送情况下:直接检查RDY flag
+    if (rdy_ready_flag) {
+        rdy_ready_flag = 0;  // 使用完后清除标志
+        // LLOGD("RDY已就绪,快速通过");
+        return;
+    }
+
+    // 高速发送情况下:RDY flag未就绪,使用事件等待机制等待RDY flag好了
+    uint32_t start_time = luat_mcu_tick64_ms();
+    uint32_t remaining_timeout = timeout_ms;
+    
+    while (remaining_timeout > 0) {
+        // 等待RDY就绪事件
+        luat_event_t event = {0};
+        int ret = luat_rtos_queue_recv(rdy_evt_queue, &event, sizeof(luat_event_t), remaining_timeout);
+        
+        if (ret == 0 && event.id == 6) {
+            // 收到RDY事件,检查flag(中断中已设置)
+            if (rdy_ready_flag) {
+                rdy_ready_flag = 0;  // 使用完后清除标志
+                uint32_t elapsed = luat_mcu_tick64_ms() - start_time;
+                if (elapsed > 1) {
+                    // 等待时间超过1ms, 计入统计
+                    g_airlink_statistic.wait_rdy.total++;
+                }
+                // LLOGD("RDY事件触发,flag已就绪");
+                return;
+            } else {
+                if (g_airlink_debug) {
+                    // 一般是之前慢速接收没有消耗队列信息, 导致RDY事件没有被处理,会在这里被消耗掉,然后等待真正有效的rdy时刻
+                    LLOGW("收到RDY事件但flag未设置,继续等待");
                 }
             }
-            luat_rtos_task_sleep(1);
-            continue;
         }
-        // LLOGD("从机已就绪!! %s %s", __DATE__, __TIME__);
-        break;
+        
+        // 更新剩余超时时间
+        uint32_t elapsed = luat_mcu_tick64_ms() - start_time;
+        if (elapsed >= timeout_ms) {
+            break;
+        }
+        remaining_timeout = timeout_ms - elapsed;
+    }
+    
+    // 超时处理
+    g_airlink_statistic.wait_rdy.total++;
+    if (remaining_timeout == 0) {
+        g_airlink_statistic.wait_rdy.err++;
+        LLOGW("等待RDY超时: timeout=%dms, flag=%d", 
+              (int)timeout_ms, rdy_ready_flag);
     }
 }
 
@@ -367,10 +426,12 @@ __AIRLINK_CODE_IN_RAM__ static void spi_master_task(void *param)
 
         memset(s_txbuff, 0, TEST_BUFF_SIZE);
         airlink_wait_and_prepare_data(s_txbuff);
-        // slave_rdy = 0;
-        airlink_wait_for_slave_ready(1000); // 最多等1秒
-
+        
+        // 立即发送数据给从机
         airlink_transfer_and_exec(s_txbuff, s_rxbuff);
+        
+        // 发送完成后,等待从机的响应/确认
+        airlink_wait_for_slave_reply(1000); // 最多等1秒
 
         memset(s_rxbuff, 0, TEST_BUFF_SIZE);
         // start = 0;
@@ -388,7 +449,10 @@ void luat_airlink_start_master(void)
     s_txbuff = luat_heap_opt_malloc(AIRLINK_MEM_TYPE, TEST_BUFF_SIZE);
     s_rxbuff = luat_heap_opt_malloc(AIRLINK_MEM_TYPE, TEST_BUFF_SIZE);
 
+    // 创建通用事件队列 (id=2,3等)
     luat_rtos_queue_create(&evt_queue, 4 * 1024, sizeof(luat_event_t));
+    // 创建专门的RDY事件队列 (id=6)
+    luat_rtos_queue_create(&rdy_evt_queue, 1, sizeof(luat_event_t));
     luat_rtos_task_create(&spi_task_handle, 8 * 1024, 50, "spi", spi_master_task, NULL, 0);
 }