Call Open(Stream)
if writing, call putch(Char) as many times as required
If reading, call getch() as many times as required
Call Close(). Open() sets a variable that is used by putch() and getch() to define the port to be used. This generally sends data to or from a buffer. If reading,Close() simply releases the port.
If writing, Close() initialises the relevant driver then enables an interrupt so the data in the buffer is sent on the relevant port. It then waits until the data has been sent before releasing the port. To detect when the data has been sent, Close() uses xSemaphoreTake() and the interrupt routines use xSemaphoreGiveFromISR() to synchronise. So far so good. However, I also need mutual exclusion to ensure two tasks cannot simultaneously access the resource. This is complicated by a number of considerations: 1) At any given time only one task can be writing.
2) At any given time only one task can be reading.
3) It is permissible for a task to simultaneously read from one port and write to another, or for one task to be reading while another is writing.
4) It is not possible to simultaneously read from and write the I2C, SPI or USB ports. To address this I have implemented a Session mutex for each port, a Write mutex and a Read Mutex. Open() will therefore take two mutexes, a Session mutex and either the Write mutex or the Read mutex. However, I find that very occasionally (maybe after several hours of running) the system hangs at the dreaded FreRTOS routine:
/* *** NOTE ***********************************************************
If you find your application is crashing here then likely causes are:
1) Stack overflow -
see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
2) Incorrect interrupt priority assignment, especially on Cortex-M3
parts where numerically high priority values denote low actual
interrupt priories, which can seem counter intuitive. See
configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html
3) Calling an API function from within a critical section or when
the scheduler is suspended.
4) Using a queue or semaphore before it has been initialised or
before the scheduler has been started (are interrupts firing
before vTaskStartScheduler() has been called?).
See http://www.freertos.org/FAQHelp.html for more tips.
**********************************************************************/
for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext )
{
/* There is nothing to do here, we are just iterating to the
wanted insertion position. */
}
This always happens while the Close() routine is waiting for the interrupt semaphore to indicate that a message has been sent. It appears that interrupts are disabled, since the system hangs midway through the send process, but I can’t see anywhere in my code that would do this.
I have just seen that the API function manual description of vSemaphoreCreateBinary() states:
A fast and simple priority inheritance mechanism is implemented that assumes a task will only ever hold a single mutex at any one time.Could the problem be caused by the fact that in my application a task hold two mutexes, a Session mutex and a Put/Get mutex?