本次做业主体由三个任务组成,分别是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