//------------------------------------------------------------------- //read date time void RTC_Read_datetime(uint8_t * data,uint8_t flag) { uint8_t temp[3]; //first read tiem ,then read date, or not time is not run; RTC_DateTypeDef sdatestructureget; RTC_TimeTypeDef stimestructureget; HAL_RTCStateTypeDef status; if(data!=NULL) { osMutexWait(rtc_mutex, osWaitForever); /* Get the RTC current Time */ HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN); temp[0]=stimestructureget.Hours; temp[1]=stimestructureget.Minutes; temp[2]=stimestructureget.Seconds; memcpy(¤t_datetime[3],temp,3); /* Get the RTC current Date */ HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN); data[0]=sdatestructureget.Year; data[1]=sdatestructureget.Month; data[2]=sdatestructureget.Date; current_datetime[6]=sdatestructureget.WeekDay; memcpy(¤t_datetime[0],data,3); if(flag==1) { memcpy(data,temp,3); } osMutexRelease(rtc_mutex); } }
/** * @brief Function that receives data and performs Triple Modular Redundancy. This is a blocking call. * @param *receiver: pointer to a Receiver structure. * @retval None. */ void wireless_RX(struct Receiver *receiver) { uint8_t i=0; uint8_t temp_data=0; osMutexWait(receiver->mutexID, osWaitForever); uint8_t raw_data[sizeof(receiver->data)/sizeof(receiver->data[0]) * 3]; CC2500_StrobeSend(SRX_R,&(receiver->state),&(receiver->buffer_space)); osMutexRelease(receiver->mutexID); osDelay(STROBE_DELAY); while (i<(sizeof(receiver->data)/sizeof(receiver->data[0]) * 3)) { osMutexWait(receiver->mutexID, osWaitForever); CC2500_StrobeSend(SNOP_R,&(receiver->state),&(receiver->buffer_space)); if (receiver->buffer_space>0) { CC2500_Read(&temp_data, 0x3F, 1); if ((temp_data&0xF0)==0xF0) { raw_data[0]=temp_data&0x0F; i=1; } else if (i>0) { if ((temp_data&0xF0)==i<<4) { raw_data[i]=temp_data&0x0F; i++; } else { i=0; } } } osMutexRelease(receiver->mutexID); osDelay(STROBE_DELAY); } osMutexWait(receiver->mutexID, osWaitForever); for(uint32_t j=0;j<sizeof(receiver->data)/sizeof(receiver->data[0]);j++){ receiver->data[j] = ((raw_data[3*j]&raw_data[3*j+1]) | (raw_data[3*j]&raw_data[3*j+2]) | (raw_data[3*j+2]&raw_data[3*j+1])); } CC2500_StrobeSend(SIDLE_R,&(receiver->state),&(receiver->buffer_space)); osMutexRelease(receiver->mutexID); osDelay(STROBE_DELAY); osMutexWait(receiver->mutexID, osWaitForever); CC2500_StrobeSend(SNOP_R,&(receiver->state),&(receiver->buffer_space)); osMutexRelease(receiver->mutexID); osDelay(STROBE_DELAY); }
/* State behaviour */ void behaviour_welcome(state_ptr state) { /* Set events to react to */ /* Do state actions */ /* Set menu */ osMutexWait(mutex_menuHandle, osWaitForever); menu_copy(&menu_welcome, ¤t_menu); osMutexRelease(mutex_menuHandle); /* Display menu */ uint32_t i; for (i = 0; i < menu_welcome.item_num; i++) { while (osMailPut(queue_lcdHandle, (void *) &menu_welcome.items[i]) != osOK) { osDelay(1); } } /* Do state actions */ bluetooth_init(); osDelay(2500); entry_to_running(state); }
/** * @brief Set value to be displayed on the seven-segment display. * @param float angle: angle to be displayed * @retval None */ void SevenSegment_SetDisplayValue_Angle(float angle) { /* We have race conditions. Need to use mutexes to protect these global flags. */ osMutexWait(segment_mutex, osWaitForever); displayed_angle = angle; osMutexRelease(segment_mutex); }
/** * @brief Set value to be displayed on the seven-segment display. * @param float angle: angle to be displayed * @retval None */ void SevenSegment_SetDisplayValue_Temp(float temp) { /* We have race conditions. Need to use mutexes to protect these global flags. */ osMutexWait(segment_mutex, osWaitForever); displayed_temp = temp; osMutexRelease(segment_mutex); }
/*---------------------------------------------------------------------------- * Thread 'SEGMENT': Display values on 7-segment display *---------------------------------------------------------------------------*/ void Thread_SEGMENT (void const *argument) { int counter = 0; DisplayMode mode; while(1) { osSignalWait(SEGMENT_SIGNAL, osWaitForever); if (counter % FLASH_PERIOD == 0) { if (SevenSegment_GetFlashing()) { osMutexWait(segment_mutex, osWaitForever); activated = !activated; osMutexRelease(segment_mutex); } } mode = SevenSegment_GetDisplayMode(); if (mode == TEMP_MODE) { SevenSegment_ToggleDisplayedDigit_Angle(); } else if (mode == ANGLE_MODE) { SevenSegment_ToggleDisplayedDigit_Temp(); } counter++; } }
/** * @brief Sets seven-segment display mode (ANGLE_MODE, TEMP_MODE). * @param None * @retval None */ void SevenSegment_SetDisplayMode(DisplayMode mode) { /* We have race conditions. Need to use mutexes to protect these global flags. */ osMutexWait(segment_mutex, osWaitForever); display_mode = mode; osMutexRelease(segment_mutex); }
/** * @brief Starts flashing the display. * @param None * @retval None */ void SevenSegment_StartFlashing(void) { /* We have race conditions. Need to use mutexes to protect these global flags. */ osMutexWait(segment_mutex, osWaitForever); flashing = 1; osMutexRelease(segment_mutex); }
bool spifs_unlink(const char *filename) { int16_t fileId; char cleanname[SPIFS_FILENAME_LEN]; SPIFlash handler; // Clean the filename of problem characters. if (!clean_filename(filename, cleanname)) return false; // Wait for exclusive access to the SPI master bus. osMutexWait(spiMasterMutex, osWaitForever); // Open the SPI flash device. spi_flash_open(SPI0, SPI_MODE0, false, Freq_1Mbps, &handler); // Find a file id associated with the filename. fileId = spifs_find_filename(&handler, cleanname); // Erase each fileblock associated with the file. if (SPIFS_FILEID_VALID(fileId)) spifs_erase_blocks(&handler, fileId); // Close the SPI flash device. spi_flash_close(&handler); // Release exclusive access to the SPI master bus. osMutexRelease(spiMasterMutex); return true; }
//Send data in specified format. Same syntax as printf util_ErrTd xb_SendF(char *format, ...){ util_ErrTd Status = util_ErrTd_Ok; va_list va; int32_t i; if( osMutexWait(xb_MutexId, 100) == osOK ){ //Wait for shared resource (tx buffer access) HAL_NVIC_DisableIRQ(XB_DMA_TX_IRQN); //Disable DMA interrupts (TXC could acces TxBuffer in the middle of writing data to it va_start(va, format); //Start reading of parameters vsnprintf(xb_TmpStr, sizeof(xb_TmpStr), format, va); //Format new string and save its length va_end(va); //End of reading parameters // if( Cnt <= 0 || Cnt >= sizeof(com_TmpStr) ){ //If formatted string doesnt fit into buffer // snprintf(com_TmpStr, sizeof(com_TmpStr), "<erre %d %d>\r\n", (int)Cnt, (int)sizeof(com_TmpStr)); //Format error message instead // Status = util_ErrTd_Overflow; // } for( i=0; i<strlen(xb_TmpStr); i++ ){ //Copy byte by byte into tx buffer xb_TxBuffer[ xb_TxHead++ ] = xb_TmpStr[i]; xb_TxHead &= XB_TXBUFHEADMASK; } HAL_NVIC_EnableIRQ(XB_DMA_TX_IRQN); //Enable DMA interrupts again xb_TransmitTxBuffer(); //Transmit TX buffer osMutexRelease(xb_MutexId); //Release shared resource } return Status; }
/*--------------------------------------------------------------------------- TITLE : cmd_bluetooth_check WORK : ARG : void RET : void ---------------------------------------------------------------------------*/ void cmd_bluetooth_check( void ) { uint32_t time_out; uint8_t ch; uint8_t ch_array[2]; uint8_t ch_i; osStatus ret; ret = osMutexWait( Mutex_Loop, 1000 ); if( ret != osOK ) { _menu_printf("Fail to osMutexWait\r\n"); return; } core.blueport = uartOpen(USART2, NULL, 115200, MODE_RXTX); _menu_printf("\r\n"); _menu_printf("AT -> "); serialPrint(core.blueport, "AT"); ch_array[0] = 0; ch_array[1] = 0; ch_i = 0; //-- 응답이 올때까지 기다림 time_out = 1000; while(time_out--) { if( serialTotalBytesWaiting(core.blueport) ) { ch = serialRead(core.blueport); _menu_putch(ch); ch_array[ch_i++] = ch; if( ch_i >= 2 ) break; } osDelay(1); } if( ch_array[0] == 'O' && ch_array[1] == 'K' ) { _menu_printf("\r\nBluetooth OK"); } else { _menu_printf("\r\nBluetooth Fail"); } _menu_printf("\r\n"); serialInit(mcfg.serial_baudrate); osMutexRelease( Mutex_Loop ); }
/*----------------------------------------------------------------------------- * High priority job used for priority inversion test *----------------------------------------------------------------------------*/ void Th_HighPrioJob (void const *arg) { osThreadId *ctrl_id = (osThreadId *)arg; uint32_t i; osStatus stat; /* Allow control thread to be executed while this thread waits */ osSignalSet (*ctrl_id, 0x01); /* Wait for a mutex object */ stat = osMutexWait (G_MutexId, 200); ASSERT_TRUE (stat == osOK); if (stat == osOK) { /* Set mark into execution array */ for (i = 0; i < 3; i++) { if (G_ExecArr[i] == 0) { G_ExecArr[i] = 'H'; /* H as High priority job */ /* Inform control thread */ osSignalSet (*ctrl_id, (1 << 3)); break; } } } }
/** * @brief Activates 7-segment display. * @param None * @retval None */ void SevenSegment_TurnOn(void) { /* We have race conditions. Need to use mutexes to protect these global flags. */ osMutexWait(segment_mutex, osWaitForever); activated = 1; osMutexRelease(segment_mutex); }
/** *@brief A function that starts a DMA transfer using the buffers provided, on SPI1 using the passed chip select port *@param[inout] rx A pointer to the receive buffer in Bytes *@param[in] tx A pointer to the transmit buffer in Bytes *@param[in] bufferSize The size of the rx and tx buffer *@param[in] csPort The GPIO port that has the CS line for SPI1 *@param[in] csPin The GPIO pin that the CS line is connected to for SPI1 *@retval None */ void SPI_DMA_Transfer(const uint8_t* rx, const uint8_t* tx, const uint8_t bufferSize, GPIO_TypeDef* csPort, uint8_t csPin){ osMutexWait(dmaId, osWaitForever);//Check that DMA is avaible using mutex if((csPort == GPIOE) && (csPin == 0x0008)){ dmaFromAccFlag = 1; } if((csPort == WIRELESS_CS_PORT) && (csPin == WIRELESS_CS_PIN)){ dmaFromWirelessFlag = 1; } //Configure DMA DMA2_Stream0->NDTR = bufferSize; DMA2_Stream0->M0AR = (uint32_t)rx; DMA2_Stream3->NDTR = bufferSize; DMA2_Stream3->M0AR = (uint32_t)tx; GPIO_ResetBits(csPort, csPin); //lower CS line //Enable DMA DMA_Cmd(DMA2_Stream0, ENABLE); // RX DMA_Cmd(DMA2_Stream3, ENABLE); // TX }
/** \brief Test case: TC_MutexNestedAcquire \details - Create a mutex object - Obtain a mutex object - Create a high priority thread that waits for the same mutex - Recursively acquire and release a mutex object - Release a mutex - Verify that every subsequent call released the mutex - Delete a mutex object - Mutex object must be released after each acquisition */ void TC_MutexNestedAcquire (void) { osStatus stat; /* - Create a mutex object */ G_MutexId = osMutexCreate (osMutex (Mutex_Nest)); ASSERT_TRUE (G_MutexId != NULL); if (G_MutexId != NULL) { /* - Obtain a mutex object */ stat = osMutexWait (G_MutexId, 0); ASSERT_TRUE (stat == osOK); if (stat == osOK) { /* - Create a high priority thread that will wait for the same mutex */ G_Mutex_ThreadId = osThreadCreate (osThread (Th_MutexWait), NULL); ASSERT_TRUE (G_Mutex_ThreadId != NULL); /* - Recursively acquire and release a mutex object */ RecursiveMutexAcquire (5, 5); /* - Release a mutex */ stat = osMutexRelease (G_MutexId); ASSERT_TRUE (stat == osOK); /* - Verify that every subsequent call released the mutex */ ASSERT_TRUE (osMutexRelease (G_MutexId) == osErrorResource); } /* - Delete a mutex object */ ASSERT_TRUE (osMutexDelete (G_MutexId) == osOK); } }
/*----------------------------------------------------------------------------- * Recursive mutex acquisition *----------------------------------------------------------------------------*/ static void RecursiveMutexAcquire (uint32_t depth, uint32_t ctrl) { static uint32_t acq; /* Mutex acquisition counter */ osStatus stat; /* Acquire a mutex */ stat = osMutexWait (G_MutexId, 100); ASSERT_TRUE (stat == osOK); if (stat == osOK) { if (ctrl == depth) { /* - Verify that mutex was aqcuired at count zero */ ASSERT_TRUE (acq == 0); } acq++; if (depth) { RecursiveMutexAcquire (depth - 1, ctrl); } acq--; /* Release a mutex */ stat = osMutexRelease (G_MutexId); ASSERT_TRUE (stat == osOK); } }
/*----------------------------------------------------------------------------- * Low priority job used for priority inversion test *----------------------------------------------------------------------------*/ void Th_LowPrioJob (void const *arg) { osThreadId *ctrl_id = (osThreadId *)arg; osStatus stat; uint32_t i; /* Obtain a mutex object */ stat = osMutexWait (G_MutexId, 0); ASSERT_TRUE (stat == osOK); if (stat == osOK) { /* Mutex acquired, inform control thread */ osSignalSet (*ctrl_id, (1 << 0)); /* Set mark into execution array */ for (i = 0; i < 3; i++) { if (G_ExecArr[i] == 0) { G_ExecArr[i] = 'L'; /* L as Low priority job */ /* Inform control thread */ osSignalSet (*ctrl_id, (1 << 1)); break; } } ASSERT_TRUE (osMutexRelease (G_MutexId) == osOK); } }
void Thread_DISP2(void const *argument){ float roll_temp, pitch_temp; while(1){ // osDelay(10); osMutexWait(mems_mutex_id, osWaitForever); roll_temp = roll; osMutexRelease(mems_mutex_id); // printf("mems: roll= %f\n", roll_temp); printf("mems: temp= %f\n", output); if(roll_temp < 100){ Parse_Mems(parsed, roll_temp); // printf("disp2: %d %d %d %d %d\n", parsed[3], parsed[2], parsed[1], parsed[0], parsed[4]); } else{ parsed[0] = (int) roll_temp % 10; parsed[2] = ((int) roll_temp / 10) % 10; parsed[3] = ((int) roll_temp / 100) % 10; parsed[1] = 0; parsed[4] = 0; // printf("disp2: %d %d %d %d %d\n", parsed[3], parsed[2], parsed[1], parsed[0], parsed[4]); } if(parsed[4] < 0 || parsed[3] < 0 || parsed[2] < 0 || parsed[1] < 0 || parsed[0] < 0) Show_Negative(); else Show(); } }
void Thread_Mutex(void const *argument) { osStatus status; while(1) { ; // Insert thread code here... status = osMutexWait(mid_Thread_Mutex, NULL); switch(status) { case osOK: ; // Use protected code here... osMutexRelease(mid_Thread_Mutex); break; case osErrorTimeoutResource: break; case osErrorResource: break; case osErrorParameter: break; case osErrorISR: break; default: break; } osThreadYield(); // suspend thread } }
/** * @brief Deactivates 7-segment display and turn off the LEDs. * @param None * @retval None */ void SevenSegment_TurnOff(void) { osMutexWait(segment_mutex, osWaitForever); GPIOE->ODR &= 0x000F; /* Clear the bits corresponding to GPIO_PIN_4 to GPIO_PIN_15 */ activated = 0; osMutexRelease(segment_mutex); }
/** \brief Test case: TC_MutexTimeout \details - Create and initialize a mutex object - Create a thread that acquires a mutex but never release it - Wait for mutex release until timeout */ void TC_MutexTimeout (void) { osThreadId ctrl_id, lock_id; osEvent evt; /* Get control thread id */ ctrl_id = osThreadGetId (); ASSERT_TRUE (ctrl_id != NULL); if (ctrl_id != NULL) { /* - Create and initialize a mutex object */ G_MutexId = osMutexCreate (osMutex (MutexTout)); ASSERT_TRUE (G_MutexId != NULL); if (G_MutexId != NULL) { /* - Create a thread that acquires a mutex but never release it */ lock_id = osThreadCreate (osThread (Th_MutexLock), &ctrl_id); ASSERT_TRUE (lock_id != NULL); if (lock_id != NULL) { /* - Wait for mutex release until timeout */ ASSERT_TRUE (osMutexWait (G_MutexId, 10) == osErrorTimeoutResource); /* - Release a mutex */ osSignalSet (lock_id, 0x01); evt = osSignalWait (0x01, 100); ASSERT_TRUE (evt.status == osEventSignal); /* - Terminate locking thread */ ASSERT_TRUE (osThreadTerminate (lock_id) == osOK); } /* Delete mutex object */ ASSERT_TRUE (osMutexDelete (G_MutexId) == osOK); } } }
/*---------------------------------------------------------------------------- * Thread 'LED_Thread': Toggles LED *---------------------------------------------------------------------------*/ void Thread_keypad (void const *argument) { while(1){ osMutexWait(mutex, 100); keypad_value = read_keypad(); osMutexRelease(mutex); osDelay(1000); } }
/** * @brief Worker thread main superloop that defines how the thread will always display values * depending on the relevant mode of operation * @param void* * @retval void */ void Thread_MEMS(void const *argument){ float read_acc[] = {0, 0, 0}; double output_x, output_y, output_z; Reset_MEMS(&kstate_x); Reset_MEMS(&kstate_y); Reset_MEMS(&kstate_z); // double den_pitch, den_roll; while(1){ osDelay(200); // printf("mems: works\n\r"); // printf("mems: interrupt = %d\n\r", interrupt); if(interrupt != 0){ interrupt = 0; // printf("mems: now interrupt = %d\n\r", interrupt); LIS3DSH_ReadACC(read_acc); // printf("%f | %f | %f\n", read_acc[0], read_acc[1], read_acc[2]); if(!Kalmanfilter_C(read_acc[0], &output_x, &kstate_x) && !Kalmanfilter_C(read_acc[1], &output_y, &kstate_y) && !Kalmanfilter_C(read_acc[2], &output_z, &kstate_z)){ // printf("x = %f out = %f\n", read_acc[0], output_x); // printf("y = %f out = %f\n", read_acc[1], output_y); // printf("z = %f out = %f\n", read_acc[2], output_z); output_x = output_x + 0.10493; output_y = output_y + 0.143217; output_z = output_z + 0.665265; osMutexWait(mems_mutex_id, osWaitForever); // roll = (atan2(-fYg, fZg)*180.0)/M_PI; roll = (atan2(-output_y, output_z) * 180.0) / 3.1416; osMutexRelease(mems_mutex_id); // printf("mems: roll= %f\n", roll); osMutexWait(mems_mutex_id, osWaitForever); // pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg))*180.0)/M_PI; pitch = (atan2(output_x, sqrt(output_y * output_y + output_z * output_z))*180.0) / 3.1416; osMutexRelease(mems_mutex_id); // printf("mems: roll= %f\n", pitch); } else printf("mems: Kalman filter returned error!\n"); } } }
/** * @brief Stops flashing the display. * @param None * @retval None */ void SevenSegment_StopFlashing(void) { /* We have race conditions. Need to use mutexes to protect these global flags. */ osMutexWait(segment_mutex, osWaitForever); flashing = 0; activated = 1; /* set activated to one to avoid edge case where when seven segment stops flashing but activated is still disabled */ osMutexRelease(segment_mutex); }
/*---------------------------------------------------------------------------- switch LED off *---------------------------------------------------------------------------*/ void LED_off (unsigned char led) { LED_Off(led); osMutexWait(mut_GLCD, osWaitForever); GLCD_SetBackColor(White); GLCD_SetTextColor(Green); GLCD_DisplayChar(4, 5+led, __FI, 0x80+0); /* Circle Empty */ osMutexRelease(mut_GLCD); }
/*--------------------------------------------------------------------------- Set Lights function controls LEDs and LCD display *---------------------------------------------------------------------------*/ void SetLights (uint32_t light, uint32_t on) { osMutexWait(mut_GLCD, osWaitForever); GLCD_SetBackColor(White); if (light == RED) { GLCD_SetTextColor(Red); if (on == 0) { GLCD_DisplayChar(4, 15, __FI, 0x80+0); } else { GLCD_DisplayChar(4, 15, __FI, 0x80+1); } } if (light == YELLOW) { GLCD_SetTextColor(Yellow); if (on == 0) { GLCD_DisplayChar(5, 15, __FI, 0x80+0); } else { GLCD_DisplayChar(5, 15, __FI, 0x80+1); } } if (light == GREEN) { GLCD_SetTextColor(Green); if (on == 0) { GLCD_DisplayChar(6, 15, __FI, 0x80+0); } else { GLCD_DisplayChar(6, 15, __FI, 0x80+1); } } if (light == STOP) { GLCD_SetTextColor(Red); if (on == 0) { GLCD_DisplayChar(5, 13, __FI, 0x80+12); } else { GLCD_DisplayChar(5, 13, __FI, 0x80+13); } } if (light == WALK) { GLCD_SetTextColor(Green); if (on == 0) { GLCD_DisplayChar(6, 13, __FI, 0x80+14); } else { GLCD_DisplayChar(6, 13, __FI, 0x80+15); } } osMutexRelease(mut_GLCD); if (on == 0) { LED_Off (light); } else { LED_On (light); } }
bool spifs_read_dir(SPIFSDir *dir) { bool retval; uint32_t sectorOffset; SPIFSFileBlock fileBlock; SPIFlash handler; // Increment the file id. dir->fileId += 1; // Wait for exclusive access to the SPI master bus. osMutexWait(spiMasterMutex, osWaitForever); // Open the SPI flash device. spi_flash_open(SPI0, SPI_MODE0, false, Freq_1Mbps, &handler); // We haven't found the next file yet. retval = false; // Loop over each sector to check for the file. while (!retval && SPIFS_FILEID_VALID(dir->fileId)) { // Get the byte offset of the sector. sectorOffset = SPIFS_SECTORID_TO_BYTEOFFSET(dir->fileId); // Read the fileblock at the start of the sector. spi_flash_read(&handler, sectorOffset, (uint8_t *) &fileBlock, sizeof(fileBlock)); // Is this the first block in a file? if (SPIFS_FILEID_VALID(fileBlock.fileId) && (fileBlock.blockId == 0)) { // Yes. Set the sector offset to the file name. sectorOffset += sizeof(fileBlock); // Read the filename. spi_flash_read(&handler, sectorOffset, (uint8_t *) dir->fileName, SPIFS_FILENAME_LEN); // Read the file size. dir->fileSize = spifs_get_file_size(&handler, dir->fileId); // We found the next filename. retval = true; } else { // No. Increment to the next file id. dir->fileId += 1; } } // Close the SPI flash device. spi_flash_close(&handler); // Release exclusive access to the SPI master bus. osMutexRelease(spiMasterMutex); return retval; }
/** * @brief Is segment activated? * @param None * @retval int activated flag. */ int SevenSegment_IsActivated(void) { int act; osMutexWait(segment_mutex, osWaitForever); act = activated; osMutexRelease(segment_mutex); return act; }
int os_usart1_gets(char *pBuffer){ osMutexWait(usart1_rx_mutex_id, osWaitForever); usart1_rx_owner = osThreadGetId(); osSignalClear(usart1_rx_owner, USART_SIGNAL); usart1_async_gets(pBuffer, _os_usart1_rx_callback); osSignalWait(USART_SIGNAL, osWaitForever); osMutexRelease(usart1_rx_mutex_id); return usart1_rx_nBytesRead; }
/** * @brief Mutex Medium Priority Thread. * @param argument: Not used * @retval None */ static void MutexMeduimPriorityThread(void const *argument) { /* Just to remove compiler warning */ (void) argument; for(;;) { /* This thread will run while the high-priority thread is blocked, and the high-priority thread will block only once it has the mutex - therefore this call should block until the high-priority thread has given up the mutex, and not actually execute past this call until the high-priority thread is suspended. */ if(osMutexWait(osMutex, osWaitForever) == osOK) { if(osThreadGetState(osHighPriorityThreadHandle) != osThreadSuspended) { /* Did not expect to execute until the high priority thread was suspended. Toggle LED 3 to indicate error */ BSP_LED_Toggle(LED3); } else { /* Give the mutex back before suspending ourselves to allow the low priority thread to obtain the mutex. */ if(osMutexRelease(osMutex) != osOK) { /* Toggle LED 3 to indicate error */ BSP_LED_Toggle(LED3); } osThreadSuspend(NULL); } } else { /* We should not leave the osMutexWait() function until the mutex was obtained. Toggle LED 3 to indicate error */ BSP_LED_Toggle(LED3); } /* The High and Medium priority threads should be in lock step. */ if(HighPriorityThreadCycles != (MediumPriorityThreadCycles + 1)) { /* Toggle LED 3 to indicate error */ BSP_LED_Toggle(LED3); } /* Keep count of the number of cycles this task has performed so a stall can be detected. */ MediumPriorityThreadCycles++; BSP_LED_Toggle(LED2); } }