Menu
FreeRTOS is an advance queue API, which provide more functionality. See the QUEUE API here. Note: the more important part which is the data is inserted at the queue is. Java Project Tutorial - Make Login and Register Form Step by Step Using NetBeans And MySQL Database - Duration: 3:43:32. 1BestCsharp blog 5,778,126 views.
PermalinkJoin GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign up Find file Copy path
gbmhunterFixed comments (see .c to .h).d3141d6Nov 7, 2012
1 contributor
//! |
//! @file UartComms.c |
//! @author Geoffrey Hunter <[email protected]> (www.cladlab.com) |
//! @date 12/09/2012 |
//! @brief See UartComms.h |
//! @details |
//! <b>Last Modified: </b> 07/11/2012 n |
//! <b>Version: </b> v1.0.2 n |
//! <b>Company: </b> CladLabs n |
//! <b>Project: </b> Free Code Modules n |
//! <b>Language: </b> C n |
//! <b>Compiler: </b> GCC n |
//! <b>uC Model: </b> PSoC5 n |
//! <b>Computer Architecture: </b> ARM n |
//! <b>Operating System: </b> FreeRTOS v7.2.0 n |
//! <b>Documentation Format: </b> Doxygen n |
//! <b>License: </b> GPLv3 n |
//! |
//! See the Doxygen documentation or UartComms.h for a detailed description on this module. |
//! |
//// |
// INCLUDES // |
//// |
// Standard PSoC includes |
#include<device.h> |
// FreeRTOS includes |
#include'FreeRTOS.h' |
#include'task.h' |
#include'queue.h' |
#include'semphr.h' |
// User includes |
#include'PublicDefinesAndTypeDefs.h' |
#include'Config.h' |
#include'UartComms.h' |
#include'UartDebug.h' |
//// |
// GUARDS // |
//// |
#ifdef __cplusplus |
extern'C' { |
#endif |
#ifndef configENABLE_TASK_UART_COMMS |
#error Please define the switch configENABLE_TASK_UART_COMMS |
#endif |
#ifndef configPRINT_DEBUG_UART_COMMS |
#error Please define the switch configPRINT_DEBUG_UART_COMMS |
#endif |
#ifndef configALLOW_SLEEP_UART_COMMS |
#error Please define the switch configALLOW_SLEEP_UART_COMMS |
#endif |
//// |
// PRIVATE DEFINES // |
//// |
#defineTX_QUEUE_SIZE (1) //!< Queue size is 1, messages are sent byte by byte across the queue. |
#defineRX_QUEUE_SIZE (1) //!< Queue size is 1, messages are sent byte by byte across the queue. |
#defineTX_QUEUE_MAX_WAIT_TIME_MS (1000) //!< Max time (in ms) to wait for putting character onto tx queue before error occurs |
//! Max time (in ms) to wait for another task to finish putting a string onto the tx queue |
//! Since only the DEBUG task is using this UART, the semaphore should never have to be |
//! waited on. |
#defineTX_SEMAPHORE_MAX_WAIT_TIME_MS (1000) |
//! Time to wait for another char to arrive on tx queue before the UART module is slept. |
#defineTIME_TO_WAIT_FOR_ANOTHER_CHAR_BEFORE_SLEEPING_MS (5) |
//// |
// PRIVATE TYPEDEF's // |
//// |
// none |
//// |
// PRIVATE VARIABLES/STRUCTURES // |
//// |
static xTaskHandle _txTaskHandle = 0; //!< Handle for the TX task |
static xSemaphoreHandle _xTxMutexSemaphore = 0; //!< Mutex semaphore for allowing only one task to write to the tx buffer at once |
static uint8 _uartDebugSleepLockCount = 0; //! Used by the functions UartComms_SleepLock() and UartComms_SleepUnlock() to keep track of how many time the uart has been locked from sleeping. |
//! RX queue. Uart interrupt places characters on this queue as soon as they are received. |
static xQueueHandle _xRxQueue; |
//! Tx queue. Place characters on here to send them to the DEBUG module. |
static xQueueHandle _xTxQueue; |
//! Variable is TRUE if uart is asleep, otherwise FALSE. |
staticbool_t _isAsleep = FALSE; |
//! Holds configurable UART parameters |
struct{ |
bool_t allowUartSleep; |
} _uartCommsParameters = |
{ |
.allowUartSleep = configALLOW_SLEEP_UART_COMMS |
}; |
//// |
// PRIVATE FUNCTION PROTOTYPES // |
//// |
// General functions |
voidUartComms_TxTask(void *pvParameters); |
// ISR's |
CY_ISR_PROTO(UartComms_UartRxIsr); |
//// |
// PUBLIC FUNCTIONS // |
//// |
voidUartComms_Start(uint32 txTaskStackSize, uint8 txTaskPriority) |
{ |
#if(configENABLE_TASK_UART_COMMS 1) |
// Create the tx task |
xTaskCreate( &vUartComms_TxTask, |
(signed portCHAR *) 'Comms Uart TX Task', |
txTaskStackSize, |
NULL, |
txTaskPriority, |
&_txTaskHandle); |
#endif |
// Create TX Queue |
_xTxQueue = xQueueCreate(configUART_COMMS_TX_QUEUE_LENGTH, TX_QUEUE_SIZE); |
// Create RX Queue |
_xRxQueue = xQueueCreate(configUART_COMMS_RX_QUEUE_LENGTH, RX_QUEUE_SIZE); |
// Create TX mutex semaphore |
_xTxMutexSemaphore = xSemaphoreCreateMutex(); |
// Start the debug UART. This is a Cpyress API call. |
UartCpComms_Start(); |
} |
xTaskHandle UartComms_ReturnTxTaskHandle(void) |
{ |
return _txTaskHandle; |
} |
bool_tUartComms_PutString(constchar* string) |
{ |
// Take semaphore to allow placing things on queue |
if(xSemaphoreTake(_xTxMutexSemaphore, TX_SEMAPHORE_MAX_WAIT_TIME_MS/portTICK_RATE_MS) pdFAIL) |
{ |
#if(configPRINT_DEBUG_UART_COMMS 1) |
staticchar *msgTimeoutWaitingForTxQueueSemaphore = 'UART_COMMS: Timeout waiting for tx queue semaphore.rn'; |
UartComms_PutString(msgTimeoutWaitingForTxQueueSemaphore); |
#endif |
returnFALSE; |
} |
//! @todo Add error handling |
// Put characters onto tx queue one-by-one |
while(*string != '0') |
{ |
// Put char on back of queue one-by-one |
xQueueSendToBack(_xTxQueue, string, TX_QUEUE_MAX_WAIT_TIME_MS/portTICK_RATE_MS); |
// Increment string |
string++; |
//! @todo Add error handling if queue fail |
} |
// Return semaphore |
xSemaphoreGive(_xTxMutexSemaphore); |
returnTRUE; |
} |
voidUartComms_GetChar(char* singleChar) |
{ |
xQueueReceive(_xRxQueue, singleChar, portMAX_DELAY); |
} |
bool_tUartComms_IsAsleep(void) |
{ |
if(_isAsleep TRUE) |
returnTRUE; |
else |
returnFALSE; |
} |
voidUartComms_SleepLock(void) |
{ |
// Stop context switch since UART_COMMS_Wakeup() is not thread-safe |
taskENTER_CRITICAL(); |
//vTaskSuspendAll(); |
// Wakeup UART if sleep lock was on 0 (a hence sleeping) as long as sleep is allowed |
if((_isAsleep TRUE) && (_uartCommsParameters.allowUartSleepTRUE)) |
{ |
// Set flag to false to prevent multiple wake-ups |
_isAsleep = FALSE; |
// Cypress APU call |
UartCpComms_Wakeup(); |
#if(configPRINT_DEBUG_UART_COMMS 1) |
staticchar *msgWakingUartComms = 'UART_COMMS: Woke up comms UART.rn'; |
UartComms_PutString(msgWakingUartComms); |
#endif |
} |
// Increment sleep lock count. If statement should never be false, but added just as a |
// precaution. |
if(_uartDebugSleepLockCount != 255) |
_uartDebugSleepLockCount++; |
// Allow context switch again |
//xTaskResumeAll(); |
taskEXIT_CRITICAL(); |
} |
voidUartComms_SleepUnlock(void) |
{ |
// Prevent contect switch since UART_COMMS_Sleep() is not thread-safe |
taskENTER_CRITICAL(); |
//vTaskSuspendAll(); |
// Decrement sleep lock count. If statement should never be false, but added just as a |
// precaution |
if(_uartDebugSleepLockCount != 0) |
_uartDebugSleepLockCount--; |
// Sleep UART if sleepLockCount has reached 0 |
if((_uartDebugSleepLockCount 0) && (_isAsleep FALSE)) |
{ |
if(_uartCommsParameters.allowUartSleepTRUE) |
{ |
/* |
#if(configPRINT_DEBUG_UART_COMMS 1) |
static char *msgSleepingUartComms = 'UART_COMMS: Sleeping UART DEBUG.rn'; |
UartComms_PutString(msgSleepingUartComms); |
// Wait for message to complete since sleeping itself |
while(!(UART_COMMS_ReadTxStatus() & UART_COMMS_TX_STS_COMPLETE)); |
#endif |
*/ |
// Sleep UART. Cypress API call. |
UartCpComms_Sleep(); |
// Set flag to true so UartComms_SleepLock() knows to wake up device |
_isAsleep = TRUE; |
} |
else |
{ |
/* @debug Repeatedly prints itself |
#if(configPRINT_DEBUG_UART_COMMS 1) |
static char *msgUartCommsSleepDisabled = 'UART_COMMS: UART DEBUG sleep disabled. Keeping awake.rn'; |
UartComms_PutString(msgUartCommsSleepDisabled); |
#endif |
*/ |
} |
} |
// Allow context switch again |
//xTaskResumeAll(); |
taskEXIT_CRITICAL(); |
} |
//// |
// PRIVATE FUNCTIONS // |
//// |
// TASK FUNCTIONS // |
//! @brief DEBUG UART TX task |
//! @param *pvParameters Void pointer (not used) |
//! @note Not thread-safe. Do not call from any task, this function is a task that |
//! is called by the FreeRTOS kernel |
//! @private |
voidUartComms_TxTask(void *pvParameters) |
{ |
#if(configPRINT_DEBUG_UART_COMMS 1) |
staticchar* msgUartCommsTxTaskStarted = 'UART_COMMS: Comms Uart TX task started.rn'; |
UartDebug_PutString(msgUartCommsTxTaskStarted); |
#endif |
// Start USART RX interrupt, store in vector table the function address of UartComms_UartRxISR() |
// This must be done in the task, since the interrupt calls xQueueSendToBackFromISR() which |
// must not be called before the scheduler starts (freeRTOS restriction). |
IsrCpUartCommsRx_StartEx(UartComms_UartRxIsr); |
typedefenum |
{ |
ST_INIT, //!< Initial state |
ST_IDLE, //!< Idle state. UART could be asleep in this state |
ST_SENDING //!< Sending state. UART is prevented from sleeping in this state until timeout |
}txTaskState_t; |
txTaskState_t txTaskState = ST_INIT; |
// Infinite task loop |
for(;;) |
{ |
//! Holds received character from the #xUartCommsTxQueue |
char singleChar; |
// State machine |
switch(txTaskState) |
{ |
case ST_INIT: |
{ |
// Allow UART to initially sleep if allowed to |
//UartComms_SleepLock(); |
UartComms_SleepUnlock(); |
// Go to idle state |
txTaskState = ST_IDLE; |
break; |
} |
case ST_IDLE: |
{ |
// Now UART is asleep, wait indefinetly for next char |
xQueueReceive(_xTxQueue, &singleChar, portMAX_DELAY); |
// Prevent UART from sleeping and wake-up if neccessary |
UartComms_SleepLock(); |
// Goto sending state |
txTaskState = ST_SENDING; |
break; |
} |
case ST_SENDING: |
{ |
// Send char using Cypress API. |
// This function will not return untill there is room to put character on buffer |
//! @todo Implement this in a blocking fashion? |
UartCpComms_PutChar(singleChar); |
if(xQueueReceive(_xTxQueue, &singleChar, TIME_TO_WAIT_FOR_ANOTHER_CHAR_BEFORE_SLEEPING_MS/portTICK_RATE_MS) pdFAIL) |
{ |
// Wait until UART has completely finished sending the message |
// (both the hardware buffer and the byte sent flag are set) |
//while(!(UART_COMMS_ReadTxStatus() & (UART_COMMS_TX_STS_FIFO_EMPTY | UART_COMMS_TX_STS_COMPLETE))); //(software wait) |
while(!(UartCpComms_ReadTxStatus() & UartCpComms_TX_STS_COMPLETE)); |
//CyDelay(95); |
// Now it is safe to unlock the UART to allow for sleeping |
UartComms_SleepUnlock(); |
// Go back to idle state |
txTaskState = ST_IDLE; |
} |
break; |
} |
} |
// Finished, now loop for next message |
} |
} |
//// |
// ISR's // |
//// |
//! @brief ISR called when UART rx buffer has new character |
//! @private |
CY_ISR(UartComms_UartRxIsr) |
{ |
// Check to see if we just slept, if so, wake up peripherals |
//! @todo Get rid of this |
//if(PowerMgmt_AreWeSleeping() TRUE) |
// PowerMgmt_WakeUp(); |
static portBASE_TYPE xHigherPriorityTaskWoken; |
// Set to false on interrupt entry |
xHigherPriorityTaskWoken = FALSE; |
// Get received byte (lower 8-bits) and error info from UART (higher 8-bits) (total 16-bits) |
do |
{ |
uint16_t byte = UartCpComms_GetByte(); |
// Mask error info |
uint8_t status = (byte >> 8); |
// Check for error |
if(status (UartCpComms_RX_STS_BREAK | UartCpComms_RX_STS_PAR_ERROR | UartCpComms_RX_STS_STOP_ERROR |
| UartCpComms_RX_STS_OVERRUN | UartCpComms_RX_STS_SOFT_BUFF_OVER)) |
{ |
// UART error has occured |
//Main_SetErrorLed(); |
#if(configPRINT_DEBUG_UartCpComms 1) |
if(status UartCpComms_RX_STS_MRKSPC) |
{ |
staticchar* msgErrorMarkOrSpaceWasReceivedInParityBit = 'DEBUG_RX_INT: Error: Mark or space was received in parity bit.rn'; |
UartDebug_PutString(msgErrorMarkOrSpaceWasReceivedInParityBit); |
} |
elseif(status UartCpComms_RX_STS_BREAK) |
{ |
staticchar* msgBreakWasDetected = 'DEBUG_RX_INT: Error: Break was detected.rn'; |
UartDebug_PutString(msgBreakWasDetected); |
} |
elseif(status UartCpComms_RX_STS_PAR_ERROR) |
{ |
staticchar* msgErorrParity = 'DEBUG_RX_INT: Error: Parity error was detected.rn'; |
UartDebug_PutString(msgErorrParity); |
} |
elseif(status UartCpComms_RX_STS_STOP_ERROR) |
{ |
staticchar* msgErorrStop = 'DEBUG_RX_INT: Error: Stop error was detected.rn'; |
UartDebug_PutString(msgErorrStop); |
} |
elseif(status UartCpComms_RX_STS_OVERRUN) |
{ |
staticchar* msgErrorFifoRxBufferOverrun = 'DEBUG_RX_INT: Error: FIFO RX buffer was overrun.rn'; |
UartDebug_PutString(msgErrorFifoRxBufferOverrun); |
} |
elseif(status UartCpComms_RX_STS_FIFO_NOTEMPTY) |
{ |
staticchar* msgErrorRxBufferNotEmpty = 'DEBUG_RX_INT: Error: RX buffer not empty.rn'; |
UartDebug_PutString(msgErrorRxBufferNotEmpty); |
} |
elseif(status UartCpComms_RX_STS_ADDR_MATCH) |
{ |
staticchar* msgErrorAddressMatch = 'DEBUG_RX_INT: Error: Address match.rn'; |
UartDebug_PutString(msgErrorAddressMatch); |
} |
elseif(status UartCpComms_RX_STS_SOFT_BUFF_OVER) |
{ |
staticchar* msgErrorSoftwareBufferOverflowed = 'DEBUG_RX_INT: Error: RX software buffer ovverflowed.rn'; |
UartDebug_PutString(msgErrorSoftwareBufferOverflowed); |
} |
#endif |
} |
else |
{ |
// Put byte in queue (ISR safe function) |
xQueueSendToBackFromISR(_xRxQueue, &byte, &xHigherPriorityTaskWoken); |
} |
} |
while((UartCpComms_ReadRxStatus() & UartCpComms_RX_STS_FIFO_NOTEMPTY) != 0x00); |
// Force a context swicth if interrupt unblocked a task with a higher or equal priority |
// to the currently running task |
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); |
} |
//// |
// GRAVEYARD // |
//// |
// none |
#ifdef __cplusplus |
} // extern 'C' { |
#endif |
// EOF |
Copy lines Copy permalink
Active5 months ago
I am working on STM32L152VB-A controller. I am using FreeRTOS.
I used CubeMX to generate the code and I configured USART1 with global interrupts.
The non interrupt RX and TX (HAL_UART_Receive and HAL_UART_Transmit) is working.
But I am trying to make it work with interrupts.
I used CubeMX to generate the code and I configured USART1 with global interrupts.
The non interrupt RX and TX (HAL_UART_Receive and HAL_UART_Transmit) is working.
But I am trying to make it work with interrupts.
Only after I called HAL_UART_Receive_IT, I am getting interrupt.
Since I couldn't know the receive data size, I am planning to receive characters one by one.
Since I couldn't know the receive data size, I am planning to receive characters one by one.
Since I use RTOS, I am confused about where to write HAL_UART_Receive_IT, as the message can come at any time. can anybody guide me??
PS: I tried calling the HAL_UART_Receive_IT inside ISR, but it is also not working.
HarikrishnanHarikrishnan2,15022 gold badges3232 silver badges5656 bronze badges
1 Answer
I think you're confusing HAL_UART_Receive_IT with a function which actually receives anything. This is not the case. This function merely enables the UART peripheral and its receive interrupt.
If you want to stick with the HAL library you need to pass a struct of type UART_HandleTypeDef as parameter to HAL_UART_Receive_IT which contains Fiqh us sunnah pdf.
- a uint8_t* pointer to a receive buffer
- a transfer counter for the number of elements you'd like to receive
As far as I know there is no way for receiving elements indefinitely with this framework because once the transfer counter reaches zero the receive interrupt gets disabled automatically. So if you need this you're probably better of writing the ISR yourself by overwriting the weak function defined by ST (most likely called 'UARTx_IRQHandler').
https://maletree437.weebly.com/download-project-igi-2-setup.html. Igi 2 provides opportunity to the player to choose difficulty level at the start of game.The player can also get help from map that appears on the screen.The player has many weapons to use like riffle,shotgun,light machine gun etc. Project IGI Covert Strike 2 was developed by inner loop studios and published by code masters. Igi 2 was released in march 2003.Unlike igi 1 it is not only a single player game.It is both single player as well as multi player game.It is first person shooter game.The game consists of 19 missions.Every mission have their objective and you have to complete these objectives in order to end missions.In every mission large group of enemies will be in front of you.
Freertos Queue Uart Download
To finally integrate the receive interrupt in FreeRTOS you've got two options:
Freertos Spi
- Receive data inside the ISR into a raw (uint8_t*) buffer like HAL does and use a critical section which temporarily disables the receive interrupt when accessing it.
- Receive data inside the ISR into a FreeRTOS queue using the interrupt safe API. The official FreeRTOS book chapter 6 explains this very well.
Freertos Queue Uart Code
VinciVinci