/* * uart_tasks.c * * Created on: Aug 14, 2024 * Author: jakubski */ #include "cmsis_os.h" #include "main.h" #include #include #include "interprocess_data.h" #include "measurements.h" #include "mock_tasks.h" #include "uart_tasks.h" enum SerialReceiverStates { srWaitForHeader, srCheckCrc, srRecieveData, srExecuteCmd, srFail, srFinish, srLast }; // osThreadId_t uart8RecieveTaskHandle; // osThreadId_t uart8TransmitTaskHandle; // osSemaphoreDef_t uart8RxSemaphoreDef; // osSemaphoreId_t uart8RxSemaphore = NULL; // osMessageQueueId_t uart8DecodedFrameDataTaskQueue; // osMessageQueueId_t uart8SendCmdToSlaveQueue; extern UART_HandleTypeDef huart8; extern DMA_HandleTypeDef hdma_uart8_rx; extern CRC_HandleTypeDef hcrc; uint8_t uart8RxBuffer[UART8_RX_BUFF_SIZE] = { 0 }; uint8_t uart8TxBuffer[UART8_TX_BUFF_SIZE] = { 0 }; uint8_t uart8TaskFrameData[INPUT_DATA_BUFF_SIZE] = { 0 }; uint8_t boardToUartNumberMap[SLAVES_COUNT] = { /*1*/ 8, 3, 6, 2 }; UartTaskData uart1TaskData = { 0 }; // Board 1 UartTaskData uart3TaskData = { 0 }; // Board 2 UartTaskData uart6TaskData = { 0 }; // Board 3 UartTaskData uart2TaskData = { 0 }; // Board 4 UartTaskData uart8TaskData = { 0 }; // Debug UartTaskData* uartTasks[] = { &uart8TaskData, NULL }; uint8_t outputDataBuffer[OUTPUT_DATA_BUFF_SIZE]; uint16_t outputDataBufferPos = 0; //extern uint32_t slaveLastSeen[SLAVES_COUNT]; //extern RESMeasurements resMeasurements[SLAVES_COUNT]; //extern SesnorsInfo sensorsInfo[SLAVES_COUNT]; //extern osMutexId_t resMeasurementsMutex; //extern osMutexId_t sensorsInfoMutex; RESMeasurements resMeasurements[SLAVES_COUNT] = { 0 }; SesnorsInfo sensorsInfo[SLAVES_COUNT] = { 0 }; uint32_t slaveLastSeen[SLAVES_COUNT] = { 0 }; osMutexId_t resMeasurementsMutex; osMutexId_t sensorsInfoMutex; extern RNG_HandleTypeDef hrng; void Uart8TasksInit (void) { osThreadAttr_t osThreadAttrRxUart = { 0 }; osThreadAttr_t osThreadAttrTxUart = { 0 }; #if 0 osMessageQueueAttr_t uartRxMsgQueueAttr = { 0 }; uartRxMsgQueueAttr.name = "uart8RxMsgQueue"; uart8DecodedFrameDataTaskQueue = osMessageQueueNew(4, sizeof(SerialProtocolFrameData), &uartRxMsgQueueAttr); uart8TaskData.processDataQueue = uart8DecodedFrameDataTaskQueue; #else // uart8TaskData.processDataQueue = NULL; #endif uart8TaskData.processRxDataMsgBuffer = xMessageBufferCreate( INPUT_DATA_BUFF_SIZE ); // uart8TaskData.processDataCb = Uart8ReceivedDataProcessCallback; uart8TaskData.processDataCb = NULL; osThreadAttrRxUart.name = "os_thread_uart8_rx"; osThreadAttrRxUart.stack_size = configMINIMAL_STACK_SIZE * 2; osThreadAttrRxUart.priority = (osPriority_t)osPriorityHigh; // uart8RxSemaphoreDef.name = "uart8RxSemaphore"; // uart8RxSemaphore = osSemaphoreNew(1, 1, NULL); uart8TaskData.uartRxBuffer = uart8RxBuffer; uart8TaskData.uartRxBufferLen = UART8_RX_BUFF_SIZE; uart8TaskData.uartTxBuffer = uart8TxBuffer; uart8TaskData.uartRxBufferLen = UART8_TX_BUFF_SIZE; uart8TaskData.frameData = uart8TaskFrameData; uart8TaskData.frameDataLen = UART8_RX_BUFF_SIZE; uart8TaskData.huart = &huart8; uart8TaskData.uartNumber = 8; uart8TaskData.uartRecieveTaskHandle = osThreadNew (UartRxTask, &uart8TaskData, &osThreadAttrRxUart); osMessageQueueAttr_t uartTxMsgQueueAttr = { 0 }; uartTxMsgQueueAttr.name = "uart8TxMsgQueue"; uart8TaskData.sendCmdToSlaveQueue = osMessageQueueNew (16, sizeof (InterProcessData), &uartTxMsgQueueAttr); osThreadAttrTxUart.name = "os_thread_uart8_tx"; osThreadAttrTxUart.stack_size = configMINIMAL_STACK_SIZE * 4; osThreadAttrTxUart.priority = (osPriority_t)osPriorityNormal; uart8TaskData.uartTransmitTaskHandle = osThreadNew (UartTxTask, &uart8TaskData, &osThreadAttrTxUart); } void HAL_UART_RxCpltCallback (UART_HandleTypeDef* huart) { // osSemaphoreRelease(uart8RxSemaphore); } void HAL_UARTEx_RxEventCallback (UART_HandleTypeDef* huart, uint16_t Size) { if (huart->Instance == UART8) { HandleUartRxCallback (&uart8TaskData, huart, Size); } } void HAL_UART_TxCpltCallback (UART_HandleTypeDef* huart) { if (huart->Instance == UART8) { } } void HandleUartRxCallback (UartTaskData* uartTaskData, UART_HandleTypeDef* huart, uint16_t Size) { BaseType_t pxHigherPriorityTaskWoken = pdFALSE; osMutexAcquire (uartTaskData->rxDataBufferMutex, osWaitForever); memcpy (&(uartTaskData->frameData[uartTaskData->frameBytesCount]), uartTaskData->uartRxBuffer, Size); uartTaskData->frameBytesCount += Size; osMutexRelease (uartTaskData->rxDataBufferMutex); xTaskNotifyFromISR (uartTaskData->uartRecieveTaskHandle, Size, eSetValueWithOverwrite, &pxHigherPriorityTaskWoken); // HAL_UARTEx_ReceiveToIdle_DMA(huart, uart8RxBuffer, UART8_RX_BUFF_SIZE); // __HAL_DMA_DISABLE_IT(&hdma_uart8_rx, DMA_IT_HT); HAL_UARTEx_ReceiveToIdle_IT (uartTaskData->huart, uartTaskData->uartRxBuffer, uartTaskData->uartRxBufferLen); portEND_SWITCHING_ISR (pxHigherPriorityTaskWoken); } void UartRxTask (void* argument) { UartTaskData* uartTaskData = (UartTaskData*)argument; SerialProtocolFrameData spFrameData = { 0 }; uint32_t bytesRec = 0; uint32_t crc = 0; uint16_t frameCommandRaw = 0x0000; uint16_t frameBytesCount = 0; uint16_t frameCrc = 0; uint16_t frameTotalLength = 0; uint16_t dataToSend = 0; portBASE_TYPE crcPass = pdFAIL; portBASE_TYPE proceed = pdFALSE; portBASE_TYPE frameTimeout = pdFAIL; enum SerialReceiverStates receverState = srWaitForHeader; uartTaskData->rxDataBufferMutex = osMutexNew (NULL); HAL_UARTEx_ReceiveToIdle_IT (uartTaskData->huart, uartTaskData->uartRxBuffer, uartTaskData->uartRxBufferLen); // HAL_UARTEx_ReceiveToIdle_DMA(&huart8, uart8RxBuffer, 32); while (pdTRUE) { // HAL_UART_Receive_IT(&huart8, uart8RxBuffer, 1); // if(osSemaphoreAcquire(uart8RxSemaphore, pdMS_TO_TICKS(1000)) != // osOK) if(xTaskNotifyWait(0, 0, &bytesRec, portMAX_DELAY) == pdTrue) frameTimeout = !(xTaskNotifyWait (0, 0, &bytesRec, pdMS_TO_TICKS (FRAME_TIMEOUT_MS))); osMutexAcquire (uartTaskData->rxDataBufferMutex, osWaitForever); frameBytesCount = uartTaskData->frameBytesCount; osMutexRelease (uartTaskData->rxDataBufferMutex); if ((frameTimeout == pdTRUE) && (frameBytesCount > 0)) { receverState = srFail; proceed = pdTRUE; } else { if (frameTimeout == pdFALSE) { proceed = pdTRUE; #if UART_TASK_LOGS printf ("Uart%d: RX bytes received: %ld\n", uartTaskData->uartNumber, bytesRec); #endif } else { if (uartTaskData->huart->RxState == HAL_UART_STATE_READY) { HAL_UARTEx_ReceiveToIdle_IT (uartTaskData->huart, uartTaskData->uartRxBuffer, uartTaskData->uartRxBufferLen); } } } while (proceed) { switch (receverState) { case srWaitForHeader: osMutexAcquire (uartTaskData->rxDataBufferMutex, osWaitForever); if (uartTaskData->frameData[0] == FRAME_INDICATOR) { if (frameBytesCount > FRAME_ID_LENGTH) { spFrameData.frameHeader.frameId = CONVERT_BYTES_TO_SHORT_WORD (&(uartTaskData->frameData[FRAME_HEADER_LENGTH - FRAME_RESP_STAT_LENGTH - FRAME_DATALEN_LENGTH - FRAME_ID_LENGTH - FRAME_COMMAND_LENGTH])); } if (frameBytesCount > FRAME_ID_LENGTH + FRAME_COMMAND_LENGTH) { frameCommandRaw = CONVERT_BYTES_TO_SHORT_WORD (&(uartTaskData->frameData[FRAME_HEADER_LENGTH - FRAME_RESP_STAT_LENGTH - FRAME_DATALEN_LENGTH - FRAME_COMMAND_LENGTH])); spFrameData.frameHeader.frameCommand = (SerialProtocolCommands)(frameCommandRaw & 0x7FFF); spFrameData.frameHeader.isResponseFrame = (frameCommandRaw & 0x8000) != 0 ? pdTRUE : pdFALSE; } if ((frameBytesCount > FRAME_ID_LENGTH + FRAME_COMMAND_LENGTH + FRAME_RESP_STAT_LENGTH) && ((spFrameData.frameHeader.frameCommand & 0x8000) != 0)) { spFrameData.frameHeader.respStatus = (SerialProtocolRespStatus)(uartTaskData->frameData[FRAME_ID_LENGTH + FRAME_COMMAND_LENGTH + FRAME_RESP_STAT_LENGTH]); } if (frameBytesCount >= FRAME_HEADER_LENGTH) { spFrameData.frameHeader.frameDataLength = CONVERT_BYTES_TO_SHORT_WORD (&(uartTaskData->frameData[FRAME_HEADER_LENGTH - FRAME_RESP_STAT_LENGTH - FRAME_DATALEN_LENGTH])); frameTotalLength = FRAME_HEADER_LENGTH + spFrameData.frameHeader.frameDataLength + FRAME_CRC_LENGTH; receverState = srRecieveData; } else { proceed = pdFALSE; } } else { if (frameBytesCount > 0) { receverState = srFail; } else { proceed = pdFALSE; } } osMutexRelease (uartTaskData->rxDataBufferMutex); break; case srRecieveData: if (frameBytesCount >= frameTotalLength) { receverState = srCheckCrc; } else { proceed = pdFALSE; } break; case srCheckCrc: osMutexAcquire (uartTaskData->rxDataBufferMutex, osWaitForever); frameCrc = CONVERT_BYTES_TO_SHORT_WORD (&(uartTaskData->frameData[frameTotalLength - FRAME_CRC_LENGTH])); crc = HAL_CRC_Calculate (&hcrc, (uint32_t*)(uartTaskData->frameData), frameTotalLength - FRAME_CRC_LENGTH); osMutexRelease (uartTaskData->rxDataBufferMutex); crcPass = frameCrc == crc; if (crcPass) { #if UART_TASK_LOGS printf ("Uart%d: Frame CRC PASS\n", uartTaskData->uartNumber); #endif receverState = srExecuteCmd; } else { receverState = srFail; } break; case srExecuteCmd: if (/*(uartTaskData->processDataQueue != NULL) || */(uartTaskData->processDataCb != NULL) || (uartTaskData->processRxDataMsgBuffer != NULL)) { osMutexAcquire (uartTaskData->rxDataBufferMutex, osWaitForever); memcpy (spFrameData.dataBuffer, &(uartTaskData->frameData[FRAME_HEADER_LENGTH]), spFrameData.frameHeader.frameDataLength); osMutexRelease (uartTaskData->rxDataBufferMutex); } // if (uartTaskData->processDataQueue != NULL) { // osMessageQueuePut (uartTaskData->processDataQueue, &spFrameData, 0, osWaitForever); // } if (uartTaskData->processRxDataMsgBuffer != NULL) { if(xMessageBufferSend (uartTaskData->processRxDataMsgBuffer, &spFrameData, sizeof (SerialProtocolFrameHeader) + spFrameData.frameHeader.frameDataLength, pdMS_TO_TICKS (200)) == pdFALSE) { receverState = srFail; break; } } if (uartTaskData->processDataCb != NULL) { uartTaskData->processDataCb (uartTaskData, &spFrameData); } receverState = srFinish; break; case srFail: dataToSend = 0; if ((frameTimeout == pdTRUE) && (frameBytesCount > 2)) { dataToSend = PrepareRespFrame (uart8TxBuffer, spFrameData.frameHeader.frameId, spFrameData.frameHeader.frameCommand, spTimeout, NULL, 0); #if UART_TASK_LOGS printf ("Uart%d: RX data receiver timeout!\n", uartTaskData->uartNumber); #endif } else if (!crcPass) { dataToSend = PrepareRespFrame (uart8TxBuffer, spFrameData.frameHeader.frameId, spFrameData.frameHeader.frameCommand, spCrcFail, NULL, 0); #if UART_TASK_LOGS printf ("Uart%d: Frame CRC FAIL\n", uartTaskData->uartNumber); #endif } else { dataToSend = PrepareRespFrame (uart8TxBuffer, spFrameData.frameHeader.frameId, spFrameData.frameHeader.frameCommand, spInternalError, NULL, 0); } if (dataToSend > 0) { HAL_UART_Transmit_IT (&huart8, uart8TxBuffer, dataToSend); } #if UART_TASK_LOGS printf ("Uart%d: TX bytes sent: %d\n", dataToSend, uartTaskData->uartNumber); #endif receverState = srFinish; break; case srFinish: default: osMutexAcquire (uartTaskData->rxDataBufferMutex, osWaitForever); uartTaskData->frameBytesCount = 0; osMutexRelease (uartTaskData->rxDataBufferMutex); spFrameData.frameHeader.frameCommand = spUnknown; frameTotalLength = 0; outputDataBufferPos = 0; receverState = srWaitForHeader; proceed = pdFALSE; break; } } } } void Uart8ReceivedDataProcessCallback (void* arg, SerialProtocolFrameData* spFrameData) { UartTaskData* uartTaskData = (UartTaskData*)arg; uint16_t dataToSend = 0; switch (spFrameData->frameHeader.frameCommand) { case spGetElectricalMeasurments: float slaveVoltage = 48.0 + rndflt (0.5); slaveVoltage = 48.0 + rndflt (1); WriteDataToBuffer (outputDataBuffer, &outputDataBufferPos, &slaveVoltage, sizeof (float)); WriteDataToBuffer (outputDataBuffer, &outputDataBufferPos, &slaveVoltage, sizeof (float)); slaveVoltage = 47.5 + rndflt (0.5); WriteDataToBuffer (outputDataBuffer, &outputDataBufferPos, &slaveVoltage, sizeof (float)); break; case spGetSensorMeasurments: break; default: break; } if (outputDataBufferPos > 0) { dataToSend = PrepareRespFrame (uart8TxBuffer, spFrameData->frameHeader.frameId, spFrameData->frameHeader.frameCommand, spOK, outputDataBuffer, outputDataBufferPos); } if (dataToSend > 0) { // HAL_UART_Transmit_DMA(&huart8, uart8TxBuffer, dataToSend); HAL_UART_Transmit_IT (uartTaskData->huart, uart8TxBuffer, dataToSend); } #if UART_TASK_LOGS printf ("Uart%d: TX bytes sent: %d\n", uartTaskData->uartNumber, dataToSend); #endif } void ReadMeasSetFromBuffer(uint8_t* buff, uint16_t* buffPos, float* dataSet) { for(uint8_t i = 0; i < 3; i++) { ReadFloatFromBuffer(buff, buffPos, &dataSet[i]); } } void UartTxTask (void* argument) { UartTaskData* const uartTaskData = (UartTaskData*)argument; InterProcessData data = { 0 }; SerialProtocolFrameData frameData = { 0 }; size_t bytesInMsg; uint16_t frameId = 0; uint32_t rndVal = 0; uint16_t bytesToSend = 0; SerialProtocolCommands frameCommand = spUnknown; uint16_t inputDataBufferPos = 0; uint8_t boardNumber = 0; while (pdTRUE) { if (uartTaskData->sendCmdToSlaveQueue != NULL) { osMessageQueueGet (uartTaskData->sendCmdToSlaveQueue, &data, 0, osWaitForever); HAL_RNG_GenerateRandomNumber (&hrng, &rndVal); frameId = (uint16_t)(rndVal & 0xFFFF); frameCommand = data.spCommand; outputDataBufferPos = 0; memset (outputDataBuffer, 0x00, OUTPUT_DATA_BUFF_SIZE); switch (frameCommand) { case spSetFanSpeed: case spSetMotorXOn: case spSetMotorYOn: WriteDataToBuffer (outputDataBuffer, &outputDataBufferPos, &data.values.integerValues.value[0], sizeof (float)); WriteDataToBuffer (outputDataBuffer, &outputDataBufferPos, &data.values.integerValues.value[1], sizeof (float)); break; case spSetDiodeOn: WriteDataToBuffer (outputDataBuffer, &outputDataBufferPos, &data.values.integerValues.value[0], sizeof (float)); break; case spSetmotorXMaxCurrent: case spSetmotorYMaxCurrent: WriteDataToBuffer (outputDataBuffer, &outputDataBufferPos, &data.values.flaotValues.value[0], sizeof (float)); break; case spGetElectricalMeasurments: case spGetSensorMeasurments: break; default: continue; break; } bytesToSend = PrepareReqFrame (uart8TxBuffer, frameId, frameCommand, outputDataBuffer, outputDataBufferPos); HAL_UART_Transmit_IT (uartTaskData->huart, uart8TxBuffer, bytesToSend); bytesInMsg = xMessageBufferReceive (uartTaskData->processRxDataMsgBuffer, &frameData, INPUT_DATA_BUFF_SIZE, pdMS_TO_TICKS (1000)); for(boardNumber = 0; boardNumber < SLAVES_COUNT; boardNumber++) { if(boardToUartNumberMap[boardNumber] == uartTaskData->uartNumber) { break; } } if (bytesInMsg == 0) { if (frameCommand == spGetElectricalMeasurments) { osMutexAcquire (resMeasurementsMutex, osWaitForever); slaveLastSeen[boardNumber]++; osMutexRelease(resMeasurementsMutex); } #if UART_TASK_LOGS printf ("Uart%d: Response timeout for frameId 0x%x\n", uartTaskData->uartNumber, frameId); #endif } else { if ((frameId == frameData.frameHeader.frameId) && (frameData.frameHeader.respStatus == spOK)) { #if UART_TASK_LOGS printf ("Uart%d: Response for frameId 0x%x OK\n", uartTaskData->uartNumber, frameId); #endif slaveLastSeen[boardNumber] = 0; switch(frameData.frameHeader.frameCommand) { case spGetElectricalMeasurments: osMutexAcquire (resMeasurementsMutex, osWaitForever); RESMeasurements *resMeas = &resMeasurements[boardNumber]; inputDataBufferPos = 0; ReadMeasSetFromBuffer(frameData.dataBuffer, &inputDataBufferPos, resMeas->voltageRMS); ReadMeasSetFromBuffer(frameData.dataBuffer, &inputDataBufferPos, resMeas->voltagePeak); ReadMeasSetFromBuffer(frameData.dataBuffer, &inputDataBufferPos, resMeas->currentRMS); ReadMeasSetFromBuffer(frameData.dataBuffer, &inputDataBufferPos, resMeas->currentPeak); ReadMeasSetFromBuffer(frameData.dataBuffer, &inputDataBufferPos, resMeas->power); osMutexRelease(resMeasurementsMutex); break; case spGetSensorMeasurments: osMutexAcquire (sensorsInfoMutex, osWaitForever); inputDataBufferPos = 0; SesnorsInfo* sensors = &sensorsInfo[boardNumber]; ReadFloatFromBuffer(frameData.dataBuffer, &inputDataBufferPos, &sensors->pvTemperature[0]); ReadFloatFromBuffer(frameData.dataBuffer, &inputDataBufferPos, &sensors->pvTemperature[1]); ReadFloatFromBuffer(frameData.dataBuffer, &inputDataBufferPos, &sensors->fanVoltage); ReadFloatFromBuffer(frameData.dataBuffer, &inputDataBufferPos, &sensors->pvEncoder); ReadByteFromBufer(frameData.dataBuffer, &inputDataBufferPos, &sensors->motorXStatus); ReadByteFromBufer(frameData.dataBuffer, &inputDataBufferPos, &sensors->motorYStatus); ReadFloatFromBuffer(frameData.dataBuffer, &inputDataBufferPos, &sensors->motorXAveCurrent); ReadFloatFromBuffer(frameData.dataBuffer, &inputDataBufferPos, &sensors->motorYAveCurrent); ReadFloatFromBuffer(frameData.dataBuffer, &inputDataBufferPos, &sensors->motorXPeakCurrent); ReadFloatFromBuffer(frameData.dataBuffer, &inputDataBufferPos, &sensors->motorYPeakCurrent); ReadByteFromBufer(frameData.dataBuffer, &inputDataBufferPos, &sensors->limitSwitchUp); ReadByteFromBufer(frameData.dataBuffer, &inputDataBufferPos, &sensors->limitSwitchDown); ReadByteFromBufer(frameData.dataBuffer, &inputDataBufferPos, &sensors->limitSwitchCenter); ReadByteFromBufer(frameData.dataBuffer, &inputDataBufferPos, &sensors->powerSupplyFailMask); osMutexRelease(sensorsInfoMutex); break; default: break; } } } } else { osDelay (pdMS_TO_TICKS (1000)); } } } void MeasurmentsReqSchedulerTaskInit (void) { osThreadAttr_t osThreadAttrMeasurmentsReqSchedulerTask = { 0 }; osThreadAttrMeasurmentsReqSchedulerTask.name = "os_thread_XXX"; osThreadAttrMeasurmentsReqSchedulerTask.stack_size = configMINIMAL_STACK_SIZE * 2; osThreadAttrMeasurmentsReqSchedulerTask.priority = (osPriority_t)osPriorityNormal; osThreadNew (MeasurmentsReqSchedulerTask, uartTasks, &osThreadAttrMeasurmentsReqSchedulerTask); } void MeasurmentsReqSchedulerTask (void* argument) { while (pdTRUE) { __uintptr_t* ptr = (__uintptr_t*)argument; while (*ptr != 0) { UartTaskData* uartTask = (UartTaskData*)*ptr; if (uartTask->sendCmdToSlaveQueue != NULL) { InterProcessData data = { 0 }; uint8_t boardNumber = 0; for(boardNumber = 0; boardNumber < SLAVES_COUNT; boardNumber++) { if(boardToUartNumberMap[boardNumber] == uartTask->uartNumber) { break; } } data.spCommand = spGetElectricalMeasurments; osMessageQueuePut (uartTask->sendCmdToSlaveQueue, &data, 0, (TickType_t)100); osMutexAcquire (resMeasurementsMutex, osWaitForever); if(slaveLastSeen[boardNumber] == 0) { data.spCommand = spGetSensorMeasurments; osMessageQueuePut (uartTask->sendCmdToSlaveQueue, &data, 0, (TickType_t)100); } osMutexRelease(resMeasurementsMutex); } ptr++; } osDelay (pdMS_TO_TICKS (1000)); } }