我目前正在嘗試開發一個代理程式,將資料從 SPI 總線傳輸到 tcp,反之亦然。我想知道我打算做的方法是否是利用 freertos 庫的好/有意的方法。如果從機想要發送資料,則程式作為 SPI 主機運行,從機觸發 GPIO 引腳,因為 SPI 只能從主機啟動。
char buffer1 [128];
char buffer2[128];
static QueueHandle_t rdySem1 //semaphore
static QueueHandle_t rdySem2 //semaphore
volatile atomic int GPIO_interrupt_pin;
void SPI_task(void* arg)
{
while(1)
{
if (GPIO_interrupt_pin)
{
//TODO:read data from SPI bus and place in buffer1
xSemaphoreGive(rdySem1);
GPIO_interrupt_pin = 0;
}
xSemaphoreTake(rdySem2, portMAX_DELAY);
//TODO:send data from buffer2[] to SPI bus
}
}
void tcp_task(void* arg)
{
while(1)
{
int len;
char rx_buffer[128];
len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
if (len>0)
{
//TODO:process data from TCP socket and place in buffer2
xSemaphoreGive(rdySem2);
}
xSemaphoreTake(rdySem1, portMAX_DELAY);
//TODO:send data from buffer1[] to TCP
}
}
//only run when GPIO pin interrupt triggers
static void isr_handler(void* arg)
{
GPIO_interrupt_pin = 1;
}
另外,我對 freeRTOS 的作業原理不是很熟悉,但我相信 xSemaphoreTake 是一個阻塞呼叫,除非我在 xSemaphoreTake() 中使用非阻塞呼叫版本,否則它不會在這種情況下作業。任何善良的靈魂可以為我指明正確的方向嗎?非常感謝。
uj5u.com熱心網友回復:
您當前的模式存在一些問題,但使用信號量的基本思想可以解決部分問題。但是,我認為值得考慮重構您的代碼,以便每個執行緒只等待其各自的接收并在接收時進行補充傳輸,而不是嘗試將其傳遞給另一個執行緒。例如,通過嘗試傳遞 TCP-recv 等待和 SPI-packet-to-TCP-send 等待,除非您保證首先通過 TCP 獲取資料以發送到 SPI,然后再獲取資料,否則不會t 真的很好用;真正的異步通信涉及準備好在任一事件上喚醒(即,當 SPI 資料包進入時tcp_task不能等待recv,或者它可能永遠不會 TCP 發送該 SPI 資料包,直到接收到 TCP 資料包)。
相反,讓任務只等待各自的接收函式,并立即將資料發送到另一端。如果存在互斥問題,請使用互斥鎖來保護實際事務。另請注意,即使它是原子的,GPIO_interrupt_pin如果在測驗和清除變數之間發生中斷,則不使用 test 和 set 可能會錯誤地設定為 0。幸運的是,FreeRTOS 以任務通知的形式提供了更好的機制來做同樣的事情(我在這里使用的 API 非常像信號量)。
void SPI_task(void *arg)
{
while (1) {
// Wait on SPI data ready pin
ulTaskNotifyTake(0, portMAX_DELAY);
// There is spi data, can grab a mutex to avoid conflicting SPI transactions
xSemaphoreTake(spi_mutex, portMAX_DELAY);
char data[128];
spi_recv(data, sizeof(data)); //whatever the spi function is, maybe get length out of it
xSemaphoreGive(spi_mutex);
// Send the data from this thread, no need to have the other thread handle (probably)
send(sock, data, sizeof(data));
}
}
void tcp_task(void *arg)
{
while (1) {
char data[128];
int len = recv(sock, data, sizeof(data));
if (len > 0) {
// Just grab the spi mutex and do the transfer here
xSemaphoreTake(spi_mutex, portMAX_DELAY);
spi_send(data, len);
xSemaphoreGive(spi_mutex);
}
}
}
static void isr_handler(void *arg)
{
vTaskNotifyGiveFromISR(SPI_task_handle, NULL);
}
以上是一個簡化的示例,您可以在此處閱讀有關任務通知的更深入的內容: https ://www.freertos.org/RTOS-task-notifications.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/525459.html
上一篇:在C宏中賦值
下一篇:如何將&arr傳遞給c中的函式
