In OSLIB binary semaphores are built on underlying counting semaphores using very efficient inline code. The counter of binary semaphores is not allowed to count beyond one thus the semaphore has only two possible states:
OSLIB implements an extended version of the binary semaphores, there are several enhancements over the usual definition:
MSG_OK
. The thread has taken the resource normally.MSG_RESET
. The thread was queued and a Reset operation has been performed on the semaphore.MSG_TIMEOUT
. The thread was queued and a timeout occurred.binary_semaphore_t | Type of a binary semaphore object. |
BSEMAPHORE_DECL() | Semaphore static initializer. |
chBSemObjectInit() | Initializes a semaphore object of type binary_semaphore_t . |
chBSemWait() | Performs a Wait operation on the semaphore. |
chBSemWaitS() | Performs a Wait operation on the semaphore (S-Class variant). |
chBSemWaitTimeout() | Performs a Wait operation on the semaphore with timeout specification. |
chBSemWaitTimeoutS() | Performs a Wait operation on the semaphore with timeout specification (S-Class variant). |
chBSemSignal() | Performs a Signal operation on the semaphore. |
chBSemSignalI() | Performs a Signal operation on the semaphore (I-Class variant). |
chBSemReset() | Performs a Reset operation on the semaphore. |
chBSemResetI() | Performs a Reset operation on the semaphore (I-Class variant). |
chBSemGetStateI() | Return true if the semaphore is taken (I-Class variant). |
Thread Serving an IRQ.
/* * Synchronization semaphore. */ binary_semaphore_t uart_bsem; /* * ISR serving the UART RX FIFO interrupt. */ CH_IRQ_HANDLER(UART_RX_IRQ) { CH_IRQ_PROLOGUE(); /* If there is data available in the UART RX FIFO.*/ if ((UART->SR & UART_SR_DATA_AVAILABLE) != 0) { /* Entering I-Locked state and signaling the semaphore.*/ chSysLockFromISR(); chBSemSignalI(&uart_bsem); chSysUnlockFromISR(); /* Resetting interrupt source.*/ UART->SR &= ~UART_SR_DATA_AVAILABLE; } CH_IRQ_EPILOGUE(); } /* * IRQ serving thread, communication timeouts are handled. */ static THD_WORKING_AREA(waUartReceiveThread, 128); static THD_FUNCTION(UartReceiveThread, arg) { while (true) { /* Waiting for an interrupt. If the interrupt has already occurred then the thread will not stop into chBSemWaitTimeout() because the binary semaphore would be in the "not taken" state. A 500mS timeout is programmed.*/ msg_t msg = chBSemWaitTimeout(&uart_bsem, TIME_MS2ST(500)); /* If a communication timeout occurred then some special handling is required.*/ if (msg == MSG_TIMEOUT) { handle_comm_timeout(); continue; } /* Empties the UART RX FIFO and processes all data before attempting taking the semaphore again.*/ while ((UART->SR & UART_SR_RXFIFO_CNT) > 0) { process_data(UART->DR); } } } /* * Initialization. */ void main(void) { /* * System initializations. * - Kernel initialization, the main() function becomes a thread and the * RTOS is active. */ chSysInit(); /* Initializing the UART semaphore in the "taken" state then starting the communication.*/ chBSemObjectInit(&uart_bsem, true); uart_init(); /* Starting the UART thread.*/ chThdCreateStatic(waUartReceiveThread, sizeof(waUartReceiveThread), NORMALPRIO + 1, UartReceiveThread, NULL); /* Continuing.*/ ...; }
Note that a counter semaphore should not used like in this example because the counter would count up after each interrupt and it could overflow if not decremented fast enough by the thread. The binary semaphore is safe because there is only a single “not taken” state, multiple signaling has no effect.