本次做業主體由三個任務組成,分別是Sender,Receiver,Monitor。分別完成發送,接收和監控的任務。git
Sender做爲數據生產者,要求每隔2ms生成一個逐次遞增的數。當增長到10000時,返回1繼續累加。github
Receiver做爲數據消費者,要求每隔1s統計一次生成的數的總和。數據結構
Monitor做爲監控者,要求每隔10s檢查一次數據是否成功接收。函數
vTaskDelay()
來完成周期性的任務。xQueueCreate()
等一系列函數。並且這種隊列也支持多任務同時讀寫。xSemaphoreCreateMutex()
做爲鎖。/** * Sender_Task: Product the number */ void SenderTask(void* arg) { traceString stLogger = xTraceRegisterString("Sender Task"); uint32_t uiNum = 1; TickType_t xLastWakeTime = xTaskGetTickCount(); while (1) { if (pdPASS != xQueueSend(g_hNumberBuff, &uiNum, 0)) { vTracePrintF(stLogger, "Send to queue failed."); if (pdPASS == xSemaphoreTake(g_uiMutexSL, 1)) { g_uiFailed++; vTracePrintF(stLogger, "Fail: %d", g_uiFailed); xSemaphoreGive(g_uiMutexSL); } } uiNum += 1; if (uiNum > 10000) { uiNum = 1; } vTaskDelayUntil(&xLastWakeTime, 2 / portTICK_RATE_MS); } } /** * Receiver_Task: Produce the number */ void ReceiverTask(void* arg) { traceString stLogger = xTraceRegisterString("Receiver Task"); uint64_t ulTmpSum = 0; uint32_t uiNumber = 0; uint32_t uiLast = 0; uint32_t uiTmpDiff; uint32_t uiTmpLoopCnt; TickType_t xLastWakeTime = xTaskGetTickCount(); while (1) { uiTmpDiff = 0; uiTmpLoopCnt = 0; ulTmpSum = 0; while (pdPASS == xQueueReceive(g_hNumberBuff, &uiNumber, 0)) { ulTmpSum += uiNumber; if (uiNumber > uiLast) { uiTmpDiff += uiNumber - uiLast - 1; } else { uiTmpDiff += uiNumber + 10000 - uiLast - 1; uiTmpLoopCnt += 1; } uiLast = uiNumber; } if (pdPASS == xSemaphoreTake(g_uiMutexRML, 10 / portTICK_RATE_MS)) { g_uiDiff += uiTmpDiff; g_uiLoopCnt += uiTmpLoopCnt; g_ulSum += ulTmpSum; xSemaphoreGive(g_uiMutexRML); } vTracePrintF(stLogger, "The sum of this round is %u\n", ulTmpSum); vTaskDelayUntil(&xLastWakeTime, 1000 / portTICK_RATE_MS); } } /** * Monitor_Task: Check the task */ void MonitorTask(void* arg) { traceString stLogger = xTraceRegisterString("Monitor Task"); uint32_t uiTmpDiff; uint32_t uiTmpLoopCnt; uint32_t uiTmpState; TickType_t xLastWakeTime = xTaskGetTickCount(); while (1) { uiTmpState = 0; if (pdPASS == xSemaphoreTake(g_uiMutexRML, 10)) { uiTmpDiff = g_uiDiff; uiTmpLoopCnt = g_uiLoopCnt; g_uiState = (uiTmpDiff != 0); xSemaphoreGive(g_uiMutexRML); } if (uiTmpDiff == 0) { vTracePrintF(stLogger, "OK, %d loops are done.", uiTmpLoopCnt); } else { STM_EVAL_LEDOn(LED4); STM_EVAL_LEDOff(LED3); vTracePrintF(stLogger, "Wrong, difference is %d.", uiTmpDiff); } vTaskDelayUntil(&xLastWakeTime, 10000 / portTICK_RATE_MS); } }
https://github.com/89yanyu/STM32F429I-Discoveryoop
開始是綠燈,一段時間後變爲紅燈。
由於只有在第二次運行Monitor的時候纔會檢查到有錯誤,將燈的狀態改變。ui
標準模式
正常運行中:
出現錯誤但未被Monitor檢測到:
Monitor檢測到錯誤:
Record模式
等待開始指令
this
由於仿真的時候用的是BSRR寄存器。
這個寄存器的功能是把要改變的Bit寫入,由MCU去改變相應的數據。
而Qemu在仿真的時候彷佛同步沒有作好,就出現了以上狀況
將訪問BSRR的操做改成ODR,這個寄存器就是直接操做io。
具體操做好比:
Set: GPIOx->ODR |= GPIO_Pin_xx;
ReSet:GPIOx->ODR &= ~GPIO_Pin_xx;
3d
緣由未知
在trcConfig.h的151行上方的空格添加
#define TRC_CFG_ARM_CM_USE_SYSTICK
code
好比,現實生活7s至關於板子裏的20s
由於FreeRTOS設置了MCU的主頻,默認是62500000
而FreeRTOS的定時都是基於MCU主頻,即內部是根據MCU主頻來肯定Tick(能夠認爲是一個CPU週期),而定時都是將ms轉化爲Tick。
好比,20s * 62500000Hz / 180000000Hz = 6.944s
修改FreeRTOSConfig.h的第98行,改成:
#define configCPU_CLOCK_HZ ( ( unsigned long ) 180000000 )
blog
緣由未知
因此提供正常模式和Record模式。
開機時按住USER_BUTTON(藍色按鈕),或者按住USER_BUTTON,再按RESET(黑色按鈕)能夠進入Record模式
此時,會等待Traceanlyzer啓動。
可能須要多點幾回Start