I am implementing a uart communication, where i have various functions and/or tasks which may want to perform transmission using uart. Hence prior to new transmission on uart, i want to ensure that the resource (uart) is not already in use. this can be achieved by a binary semaphore whose value can be checked prior to new transmissions. But keil RTOS doesnt have sem_getvalue, in absence of which i am unable to think of any way of implementation.
one way around is to have a global flag. But currently trying to use any idea by which i can avoid using a global flag. In case of no other way, will have to use global flag.
any suggestions?
Note that you have code that does the following:
if (!CurTxflg) { //Check if any transmission is going on currently switch(rx_event) { case EVENT_TXCMD: ... CurTxflg = 1;
You have no critical section that makes sure that not another thread also tries to look at CurTxflg and then decide that the UART is free to use.
This is actually the new implemented code, which i wrote as a way around, in absence of sem_getvalue(). and i am sry. that doesnt work as the uart interrupt cant clear the CurTxflg. hence the implementation changes to:
switch(rx_event) { case EVENT_TXCMD: if(!CurTxflg) //Check if any transmission is going on currently { os_mbx_wait(&MailTxBuf, &ptx, 0xFFFF); //Wait for the Transmission Data strcpy(DISPLAY_PORT_TXBUF, (uint8_t*)ptx); CurTxflg = 1; UTILS_AppendLRC(DISPLAY_PORT_TXBUF, UTILS_CalcLRC(DISPLAY_PORT_TXBUF)); UART_SendByte(DISPLAY_PORT_UART, *DISPLAY_PORT_TXBUF); } break; case EVENT_COMPLETE: CurTxflg = 0; break; }
Note that you have never described exactly in what way the UART is shared.
If the goal is just to make sure that printouts from different tasks doesn't get intermixed, then you have many other options available.
One potential way: - let the UART ISR consume data from a single transmit buffer. - have multiple threads that want to print generate their output into individual, static buffers. - have the printing threads send mail with the individual prints. - let a common master thread wait for mails, pick up a mail, wait until the transmit buffer has enough free space to hold the mailed text - use some signalling to report back to the sender thread that the thread-specific send buffer has been consumed so it is free to generate and send a new mail with more UART data.
Then you get a situation where multiple printouts never have the individual characters interleaved.
And you have a way of sharing the use of the UART - the order of the mails will control the order data gets sent to the UART. So no printing thread will lock the UART indefinitely and starve other prints.
Note also that the isr_xxx() functions allows the UART transmit ISR to look for a new mail if running out of serial data. So the UART could run with no global transmit buffer - it picks up the data directly from the mail-supplied buffer before releasing the mail and looking for next mail. Having the ISR directly picking up any mails will require that you have some other code to kick-start the UART transmit interrupt after the interrupt have run out of data to send and had to deactivate the UART TX interrupt. So you might need something like:
os_mbx_send(...); if (!uart_running) kickstart_uart(); // enable UART TX interrupt to have the ISR start consuming mails again.