static void prvExerciseTaskNotificationAPI( void ) { uint32_t ulNotificationValue; BaseType_t xReturned; /* The task should not yet have a notification pending. */ xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK ); configASSERT( xReturned == pdFAIL ); configASSERT( ulNotificationValue == 0UL ); /* Exercise the 'give' and 'take' versions of the notification API. */ xTaskNotifyGive( xTaskGetCurrentTaskHandle() ); xTaskNotifyGive( xTaskGetCurrentTaskHandle() ); ulNotificationValue = ulTaskNotifyTake( pdTRUE, mainDONT_BLOCK ); configASSERT( ulNotificationValue == 2 ); /* Exercise the 'notify' and 'clear' API. */ ulNotificationValue = 20; xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite ); ulNotificationValue = 0; xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotificationValue == 20 ); xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite ); xReturned = xTaskNotifyStateClear( NULL ); configASSERT( xReturned == pdTRUE ); /* First time a notification was pending. */ xReturned = xTaskNotifyStateClear( NULL ); configASSERT( xReturned == pdFALSE ); /* Second time the notification was already clear. */ }
static void example_task(void *p) { example_event_data_t *arg = (example_event_data_t *) p; timer_isr_handle_t inth; ESP_LOGI(TAG, "%p: run task", xTaskGetCurrentTaskHandle()); esp_err_t res = timer_isr_register(arg->group, arg->timer, example_timer_isr, arg, 0, &inth); if (res != ESP_OK) { ESP_LOGE(TAG, "%p: failed to register timer ISR", xTaskGetCurrentTaskHandle()); } else { res = timer_start(arg->group, arg->timer); if (res != ESP_OK) { ESP_LOGE(TAG, "%p: failed to start timer", xTaskGetCurrentTaskHandle()); } } while (1) { uint32_t event_val; SYSVIEW_EXAMPLE_WAIT_EVENT_START(); xTaskNotifyWait(0, 0, &event_val, portMAX_DELAY); SYSVIEW_EXAMPLE_WAIT_EVENT_END(event_val); ESP_LOGI(TAG, "Task[%p]: received event %d", xTaskGetCurrentTaskHandle(), event_val); } }
// notifies user (currently via buzzer, maybe via vibrator motor in the future) static portTASK_FUNCTION(notify_task, param) { (void) param; uint32_t beep_idx; uint32_t cycles; while (true) { // wait for someone to request a notification //ulTaskNotifyTake(pdTRUE, portMAX_DELAY); xTaskNotifyWait(UINT32_MAX,UINT32_MAX,&beep_idx,portMAX_DELAY); cycles = beeps[beep_idx].num_cycles; while(cycles--) { BUZZER_EN(buzz_en); vTaskDelay(beeps[beep_idx].beep_on_time/portTICK_PERIOD_MS); BUZZER_EN(0); vTaskDelay(beeps[beep_idx].beep_off_time/portTICK_PERIOD_MS); } } }
static void MidiPlayTask(void *pvParameters) { uint32_t flags; BaseType_t res; FLOPPY_InitDrives(); /* init */ for(;;) { res = xTaskNotifyWait((uint32_t)(-1), (uint32_t)(-1), &flags, portMAX_DELAY); /* check flags */ if (res==pdPASS && (flags&MIDI_SONG_START)) { FLOPPY_InitDrives(); if (flags&MIDI_SONG_GET_READY) { MM_Play(MIDI_SONG_GET_READY); } else if (flags&MIDI_SONG_PIRATES_OF_CARIBIAN) { MM_Play(MIDI_SONG_PIRATES_OF_CARIBIAN); } else if (flags&MIDI_SONG_HADDAWAY_WHAT_IS_LOVE) { MM_Play(MIDI_SONG_HADDAWAY_WHAT_IS_LOVE); } else if (flags&MIDI_SONG_GAME_OF_THRONES) { MM_Play(MIDI_SONG_GAME_OF_THRONES); } else if (flags&MIDI_SONG_TETRIS) { MM_Play(MIDI_SONG_TETRIS); } else if (flags&MIDI_SONG_AXEL_F) { MM_Play(MIDI_SONG_AXEL_F); } else if (flags&MIDI_SONG_GHOSTBUSTERS) { MM_Play(MIDI_SONG_GHOSTBUSTERS); } else if (flags&MIDI_SONG_JAMES_BOND) { MM_Play(MIDI_SONG_JAMES_BOND); } } } }
void vnoticer( void * pvParameters ) { uint32_t ulNotifiedValue=0x01; while(1) { if( xTaskNotifyWait( 0x00,0xffff,&ulNotifiedValue,1000 )==pdTRUE) { if( ( ulNotifiedValue | 0x01 ) == 0x01 ) //checking if the received message is same as the sent { UART0_SendStr("Received MSG from N1 \n"); } else if( ( ulNotifiedValue | 0x02 ) == 0x02 ) { UART0_SendStr("Received MSG from N2\n"); } else if( ( ulNotifiedValue | 0x03 ) == 0x03 ) { UART0_SendStr("Received MSG from N3\n"); } else if( ( ulNotifiedValue | 0x04 ) == 0x04 ) { UART0_SendStr("Received MSG from N4\n"); } else { UART0_SendStr("Learn Programming !\n");} } else { UART0_SendStr("No Notice\n"); } } }
void AudioHandler::_audio_task() { std::array<int16_t, 512> audioBuffer; while(true) { while(currentCassettes.empty()) xTaskNotifyWait(0, 0, nullptr, portMAX_DELAY); audioBuffer.fill(0); for(uint16_t i=0; i<audioBuffer.size(); i++) { for(auto &c : currentCassettes) audioBuffer[i] += c.get_chunk(); } size_t written_samples = 0; i2s_write(i2s_port, audioBuffer.data(), 1024, &written_samples, portMAX_DELAY); for(auto i=currentCassettes.begin(); i<currentCassettes.end(); i++) { if(i->is_done()) currentCassettes.erase(i); } if(currentCassettes.empty()) i2s_zero_dma_buffer(i2s_port); } }
static void prvBlockingTask( void *pvParameters ) { TaskHandle_t xControllingTask; uint32_t ulNotificationValue; const uint32_t ulMax = 0xffffffffUL; /* Just to remove compiler warnings. */ ( void ) pvParameters; xControllingTask = xTaskGetHandle( pcControllingTaskName ); configASSERT( xControllingTask ); for( ;; ) { /* Wait to be notified of the test that is to be performed next. */ xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY ); switch( ulNotificationValue ) { case abtNOTIFY_WAIT_ABORTS: prvTestAbortingTaskNotifyWait(); break; case abtNOTIFY_TAKE_ABORTS: prvTestAbortingTaskNotifyTake(); break; case abtDELAY_ABORTS: prvTestAbortingTaskDelay(); break; case abtDELAY_UNTIL_ABORTS: prvTestAbortingTaskDelayUntil(); break; case abtSEMAPHORE_TAKE_ABORTS: prvTestAbortingSemaphoreTake(); break; case abtEVENT_GROUP_ABORTS: prvTestAbortingEventGroupWait(); break; case abtQUEUE_SEND_ABORTS: prvTestAbortingQueueSend(); break; default: /* Should not get here. */ break; } /* Let the primary task know the test is complete. */ xTaskNotifyGive( xControllingTask ); /* To indicate this task is still executing. */ xBlockingCycles++; } }
BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) { BaseType_t xReturn; BaseType_t xRunningPrivileged = xPortRaisePrivilege(); xReturn = xTaskNotifyWait( ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ); vPortResetPrivilege( xRunningPrivileged ); return xReturn; }
void LittleConsole::callUpdate(void *args) { puts("Started updater thread!"); uint32_t dummy; while(true) { xTaskNotifyWait(0, 0, &dummy, 2000/portTICK_PERIOD_MS); reinterpret_cast<LittleConsole *>(args)->raw_update(); vTaskDelay(100/portTICK_PERIOD_MS); } }
//-------------------------------------------------------------------------------------- void tkAnalogIn(void * pvParameters) { ( void ) pvParameters; BaseType_t xResult; uint32_t ulNotifiedValue; while ( !startTask ) vTaskDelay( ( TickType_t)( 100 / portTICK_RATE_MS ) ); snprintf_P( aIn_printfBuff,sizeof(aIn_printfBuff),PSTR("starting tkAnalogIn..\r\n\0")); FreeRTOS_write( &pdUART1, aIn_printfBuff, sizeof(aIn_printfBuff) ); tkAIN_state = anST_A00; // Estado inicial. AN_flags.msgReload = FALSE; // No tengo ningun mensaje de reload pendiente. AN_flags.msgPollNow = FALSE; // Arranco el timer de poleo. // Interrumpe c/1s. if ( xTimerStart( pollingTimer, 0 ) != pdPASS ) u_panic(P_AIN_TIMERSTART); // for( ;; ) { u_clearWdg(WDG_AIN); // Espero hasta 100ms por un mensaje. xResult = xTaskNotifyWait( 0x00, ULONG_MAX, &ulNotifiedValue, ((TickType_t) 100 / portTICK_RATE_MS ) ); // Si llego un mensaje, prendo la flag correspondiente. if ( xResult == pdTRUE ) { if ( ( ulNotifiedValue & TK_PARAM_RELOAD ) != 0 ) { // Mensaje de reload configuration. AN_flags.msgReload = TRUE; } if ( ( ulNotifiedValue & TK_READ_FRAME ) != 0 ) { // Mensaje de polear un frame ( estando en modo servicio ) if ( systemVars.wrkMode == WK_SERVICE ) AN_flags.msgPollNow = TRUE; } } // Analizo los eventos. pv_ANgetNextEvent(); // Corro la maquina de estados. pv_AINfsm(); } }
static void prvTestAbortingTaskNotifyWait( void ) { TickType_t xTimeAtStart; BaseType_t xReturn; /* Note the time before the delay so the length of the delay is known. */ xTimeAtStart = xTaskGetTickCount(); /* This first delay should just time out. */ xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime ); if( xReturn != pdFALSE ) { xErrorOccurred = pdTRUE; } prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime ); /* Note the time before the delay so the length of the delay is known. */ xTimeAtStart = xTaskGetTickCount(); /* This second delay should be aborted by the primary task half way through. */ xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime ); if( xReturn != pdFALSE ) { xErrorOccurred = pdTRUE; } prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime ); /* Note the time before the delay so the length of the delay is known. */ xTimeAtStart = xTaskGetTickCount(); /* This third delay should just time out again. */ xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime ); if( xReturn != pdFALSE ) { xErrorOccurred = pdTRUE; } prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime ); }
void frequency_calculator(void* pvParameters){ uint32_t ulNotificationValue, frequency_previous; double frequency_delta, abs_delta; struct freq_struct freq; static int activate_load_management = 0; while(1){ //printf("Current Frequecny TASK: %d \n", frequency_value); // ulNotificationValue = ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); xTaskNotifyWait(0x00, /* Don't clear any bits on entry. */ ULONG_MAX, /* Clear all bits on exit. */ &ulNotificationValue, /* Receives the notification value. */ portMAX_DELAY ); /* Block indefinitely. */ frequency_previous = frequency_value; frequency_value = 16000.0 / ulNotificationValue; frequency_delta = (frequency_value - frequency_previous) * 2.0 * frequency_value * frequency_previous / (frequency_value + frequency_previous); freq.current = frequency_value; freq.delta = frequency_delta; abs_delta = frequency_delta < 0 ? frequency_delta * -1 : frequency_delta; //printf("activate_load_management %d \n", activate_load_management); //printf("frequency_delta %f \n", (frequency_delta)); if (((frequency_value < thres_freq) || (abs_delta > thres_delta) ) && activate_load_management == 0){ activate_load_management = 1; xQueueSendToBack( stability_queue, (void *)&activate_load_management, (TickType_t)0 ); }else if ((frequency_value >= thres_freq && abs_delta <= thres_delta ) && activate_load_management == 1){ activate_load_management = 0; xQueueSendToBack( stability_queue, (void *)&activate_load_management, (TickType_t)0 ); } //printf("Frequency %.2f Hz \n", frequency_value); //printf("dF/dt %.2f \n", frequency_delta); xQueueSendToBack( Q_freq_data, (void *)&freq, (TickType_t)0 ); //if (frequency_previous != frequency_value) // printf("Frequency %.2f Hz \n", frequency_value); } }
static void Play(MIDI_MusicTrack *tracks, unsigned int nofTracks, uint32_t tempoUS) { int itemNo; uint8_t channel; uint32_t currTimeMs; TickType_t startTicks; unsigned int nofFinished; uint32_t flags; /* init defaults */ for(channel=0;channel<nofTracks;channel++) { FLOPPY_MIDI_SetBank(channel, 0); FLOPPY_MIDI_SetInstrument(channel, 0); FLOPPY_MIDI_SetVolume(channel, 127); } startTicks = FRTOS1_xTaskGetTickCount(); itemNo = 0; for(;;) { /* breaks */ (void)xTaskNotifyWait(0UL, MIDI_SONG_STOP, &flags, 0); /* check flags */ if (flags&MIDI_SONG_STOP) { CLS1_SendStr((uint8_t*)"Stopping song!\r\n", CLS1_GetStdio()->stdOut); for(channel=0;channel<nofTracks;channel++) { FLOPPY_MIDI_AllSoundOff(channel); } break; } currTimeMs = (FRTOS1_xTaskGetTickCount()-startTicks)/portTICK_RATE_MS; nofFinished = 0; for(channel=0;channel<nofTracks;channel++) { if (!PlayTrackItem(&tracks[channel], currTimeMs, channel, tempoUS)) { nofFinished++; } } if (nofFinished==nofTracks) { /* all finished */ break; } FRTOS1_vTaskDelay(1/portTICK_RATE_MS); itemNo++; } }
/** * @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. * @param signals wait until all specified signal flags set or 0 for any single signal flag. * @param millisec timeout value or 0 in case of no time-out. * @retval event flag information or error code. * @note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS. */ osEvent osSignalWait (int32_t signals, uint32_t millisec) { osEvent ret; TickType_t ticks; ret.value.signals = 0; ticks = 0; if (millisec == osWaitForever) { ticks = portMAX_DELAY; } else if (millisec != 0) { ticks = millisec / portTICK_PERIOD_MS; if (ticks == 0) { ticks = 1; } } if (inHandlerMode()) { ret.status = osErrorISR; /*Not allowed in ISR*/ } else { if(xTaskNotifyWait( 0,(uint32_t) signals, (uint32_t *)&ret.value.signals, ticks) != pdTRUE) { if(ticks == 0) ret.status = osOK; else ret.status = osEventTimeout; } else if(ret.value.signals >= 0x80000000) { ret.status = osErrorValue; } else ret.status = osEventSignal; } return ret; }
//------------------------------------------------------------------------------------- void tkGprsTx(void * pvParameters) { ( void ) pvParameters; BaseType_t xResult; uint32_t ulNotifiedValue; while ( !startTask ) vTaskDelay( ( TickType_t)( 100 / portTICK_RATE_MS ) ); snprintf_P( gprs_printfBuff,sizeof(gprs_printfBuff),PSTR("starting tkGprsTx..\r\n\0")); FreeRTOS_write( &pdUART1, gprs_printfBuff, sizeof(gprs_printfBuff) ); GPRS_stateVars.flags.msgFlooding = FALSE; // Fijo el modo para arrancar pv_cambiarEstado(gST_INICIAL,gST_MODEMAPAGADO); // Arranco el timer if ( xTimerStart( gprsTimer, 0 ) != pdPASS ) u_panic(P_GPRS_TIMERSTART); // for( ;; ) { u_clearWdg(WDG_GPRSTX); // Espero hasta 100ms por un mensaje. xResult = xTaskNotifyWait( 0x00, ULONG_MAX, &ulNotifiedValue, ((TickType_t) 100 / portTICK_RATE_MS ) ); // Si llego un mensaje, prendo la flag correspondiente. if ( xResult == pdTRUE ) { if ( ( ulNotifiedValue & TK_PARAM_RELOAD ) != 0 ) { GPRS_stateVars.flags.msgReload = TRUE; } if ( ( ulNotifiedValue & TKC_FLOODING ) != 0 ) { GPRS_stateVars.flags.msgFlooding = TRUE; } } // El manejar la FSM con un switch por estado y no por transicion me permite // priorizar las transiciones. // Luego de c/transicion debe venir un break así solo evaluo de a 1 transicion por loop. // switch ( GPRS_stateVars.state.state ) { case gST_MODEMAPAGADO: sm_APAGADO(); break; case gST_MODEMPRENDIENDO: sm_MODEMPRENDIENDO(); break; case gST_CONFIGURAR: sm_CONFIGURAR(); break; case gST_STANDBY: sm_STANDBY(); break; case gST_OPENSOCKET: sm_SOCKET(); break; case gST_INITFRAME: sm_INITFRAME(); break; case gST_DATAFRAME: sm_DATAFRAME(); break; default: snprintf_P( gprs_printfBuff,sizeof(gprs_printfBuff),PSTR("tkGprs::ERROR state NOT DEFINED\r\n\0")); FreeRTOS_write( &pdUART1, gprs_printfBuff, sizeof(gprs_printfBuff) ); // Estado inicial. pv_cambiarEstado(gST_MODEMAPAGADO,gST_MODEMAPAGADO); break; } } }
void tkControl(void * pvParameters) { ( void ) pvParameters; BaseType_t xResult; uint32_t ulNotifiedValue; MCP_init(); // TERMINAL: Debe ser lo primero que incia para poder mandar mensajes de log. ac_terminal(INIT_TERM, NULL); loadSystemParams(); // WATCHDOG ac_wdg( INIT_WDG ); // LEDS ac_systemLeds( INIT_LED ); // EXITWRKMODE2NORMAL ac_exitWrkMode2Normal(INIT_EWM2N); // MEMORIA MEM_init(); snprintf_P( ctl_printfBuff,CHAR256,PSTR("Init memory: pWr=%d,pRd=%d,pDel=%d,free=%d,4rd=%d,4del=%d \r\n"), MEM_getWrPtr(), MEM_getRdPtr(), MEM_getDELptr(), MEM_getRcdsFree(),MEM_getRcds4rd(),MEM_getRcds4del() ); TERMrprintfStr( ctl_printfBuff ); // Habilito arrancar otras tareas startToken = STOK_TIMERS; // Espero la notificacion para arrancar while ( startToken != STOK_CTL ) { vTaskDelay( ( TickType_t)( 100 / portTICK_RATE_MS ) ); } TERMrprintfProgStrM("starting tkControl..\r\n"); startToken++; // Loop for( ;; ) { clearWdg(WDG_CTL); // LED ac_systemLeds(TOGGLE_LED); // WATCHDOG ac_wdg(CHECK_WDG); // TERMINAL ac_terminal(CHECK_TERM, NULL); // EXITWRKMODE2NORMAL ac_exitWrkMode2Normal(CHECK_EWM2N); // Genero una espera de 100ms por algun mensaje para hacer algo. xResult = xTaskNotifyWait( 0x00, /* Don't clear bits on entry. */ ULONG_MAX, /* Clear all bits on exit. */ &ulNotifiedValue, /* Stores the notified value. */ (100 / portTICK_RATE_MS ) ); if( xResult == pdTRUE ) { // Arrancar el timer y control de modo service/monitor if ( ( ulNotifiedValue & CTLMSG_STARTEWM2N ) != 0 ) { ac_exitWrkMode2Normal(START_EWM2N); } } } }
static void prvSingleTaskTests( void ) { const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL ); BaseType_t xReturned; uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue, ulPreviousValue, ulExpectedValue; TickType_t xTimeOnEntering; const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL; const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL; /* ------------------------------------------------------------------------- Check blocking when there are no notifications. */ xTimeOnEntering = xTaskGetTickCount(); xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, xTicksToWait ); /* Should have blocked for the entire block time. */ if( ( xTaskGetTickCount() - xTimeOnEntering ) < xTicksToWait ) { xErrorStatus = pdFAIL; } configASSERT( xReturned == pdFAIL ); configASSERT( ulNotifiedValue == 0UL ); /* ------------------------------------------------------------------------- Check no blocking when notifications are pending. First notify itself - this would not be a normal thing to do and is done here for test purposes only. */ xReturned = xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue ); /* Even through the 'without overwrite' action was used the update should have been successful. */ configASSERT( xReturned == pdPASS ); /* No bits should have been pending previously. */ configASSERT( ulPreviousValue == 0 ); /* The task should now have a notification pending, and so not time out. */ xTimeOnEntering = xTaskGetTickCount(); xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, xTicksToWait ); if( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToWait ) { xErrorStatus = pdFAIL; } /* The task should have been notified, and the notified value should be equal to ulFirstNotifiedConst. */ configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ulFirstNotifiedConst ); /* Incremented to show the task is still running. */ ulNotifyCycleCount++; /*-------------------------------------------------------------------------- Check the non-overwriting functionality. The notification is done twice using two different notification values. The action says don't overwrite so only the first notification should pass and the value read back should also be that used with the first notification. */ xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite ); configASSERT( xReturned == pdPASS ); xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite ); configASSERT( xReturned == pdFAIL ); /* Waiting for the notification should now return immediately so a block time of zero is used. */ xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ulFirstNotifiedConst ); /*-------------------------------------------------------------------------- Do the same again, only this time use the overwriting version. This time both notifications should pass, and the value written the second time should overwrite the value written the first time, and so be the value that is read back. */ xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite ); configASSERT( xReturned == pdPASS ); xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithOverwrite ); configASSERT( xReturned == pdPASS ); xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst ); /*-------------------------------------------------------------------------- Check notifications with no action pass without updating the value. Even though ulFirstNotifiedConst is used as the value the value read back should remain at ulSecondNotifiedConst. */ xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction ); configASSERT( xReturned == pdPASS ); xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst ); /*-------------------------------------------------------------------------- Check incrementing values. Send ulMaxLoop increment notifications, then ensure the received value is as expected - which should be ulSecondNotificationValueConst plus how ever many times to loop iterated. */ for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ ) { xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement ); configASSERT( xReturned == pdPASS ); } xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) ); /* Should not be any notifications pending now. */ xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdFAIL ); /*-------------------------------------------------------------------------- Check all bits can be set by notifying the task with one additional bit set on each notification, and exiting the loop when all the bits are found to be set. As there are 32-bits the loop should execute 32 times before all the bits are found to be set. */ ulNotifyingValue = 0x01; ulLoop = 0; /* Start with all bits clear. */ xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); do { /* Set the next bit in the task's notified value. */ xTaskNotify( xTaskToNotify, ulNotifyingValue, eSetBits ); /* Wait for the notified value - which of course will already be available. Don't clear the bits on entry or exit as this loop is exited when all the bits are set. */ xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); ulLoop++; /* Use the next bit on the next iteration around this loop. */ ulNotifyingValue <<= 1UL; } while ( ulNotifiedValue != ULONG_MAX ); /* As a 32-bit value was used the loop should have executed 32 times before all the bits were set. */ configASSERT( ulLoop == 32 ); /*-------------------------------------------------------------------------- Check bits are cleared on entry but not on exit when a notification fails to arrive before timing out - both with and without a timeout value. Wait for the notification again - but this time it is not given by anything and should return pdFAIL. The parameters are set to clear bit zero on entry and bit one on exit. As no notification was received only the bit cleared on entry should actually get cleared. */ xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait ); configASSERT( xReturned == pdFAIL ); /* Notify the task with no action so as not to update the bits even though ULONG_MAX is used as the notification value. */ xTaskNotify( xTaskToNotify, ULONG_MAX, eNoAction ); /* Reading back the value should should find bit 0 is clear, as this was cleared on entry, but bit 1 is not clear as it will not have been cleared on exit as no notification was received. */ xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ( ULONG_MAX & ~ulBit0 ) ); /*-------------------------------------------------------------------------- Now try clearing the bit on exit. For that to happen a notification must be received, so the task is notified first. */ xTaskNotify( xTaskToNotify, 0, eNoAction ); xTaskNotifyWait( 0x00, ulBit1, &ulNotifiedValue, 0 ); /* However as the bit is cleared on exit, after the returned notification value is set, the returned notification value should not have the bit cleared... */ configASSERT( ulNotifiedValue == ( ULONG_MAX & ~ulBit0 ) ); /* ...but reading the value back again should find that the bit was indeed cleared internally. The returned value should be pdFAIL however as nothing has notified the task in the mean time. */ xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdFAIL ); configASSERT( ulNotifiedValue == ( ULONG_MAX & ~( ulBit0 | ulBit1 ) ) ); /*-------------------------------------------------------------------------- Now try querying the previous value while notifying a task. */ xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue ); configASSERT( ulNotifiedValue == ( ULONG_MAX & ~( ulBit0 | ulBit1 ) ) ); /* Clear all bits. */ xTaskNotifyWait( 0x00, ULONG_MAX, &ulNotifiedValue, 0 ); xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue ); configASSERT( ulPreviousValue == 0 ); ulExpectedValue = 0; for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL ) { /* Set the next bit up, and expect to receive the last bits set (so the previous value will not yet have the bit being set this time around). */ xTaskNotifyAndQuery( xTaskToNotify, ulLoop, eSetBits, &ulPreviousValue ); configASSERT( ulExpectedValue == ulPreviousValue ); ulExpectedValue |= ulLoop; } /* ------------------------------------------------------------------------- Clear the previous notifications. */ xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); /* The task should not have any notifications pending, so an attempt to clear the notification state should fail. */ configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE ); /* Get the task to notify itself. This is not a normal thing to do, and is only done here for test purposes. */ xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue ); /* Now the notification state should be eNotified, so it should now be possible to clear the notification state. */ configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE ); configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE ); /* Incremented to show the task is still running. */ ulNotifyCycleCount++; /* Leave all bits cleared. */ xTaskNotifyWait( ULONG_MAX, 0, NULL, 0 ); }
void ProgramManager::runManager(){ uint32_t ulNotifiedValue = 0; // TickType_t xMaxBlockTime = pdMS_TO_TICKS( 1000 ); TickType_t xMaxBlockTime = portMAX_DELAY; /* Block indefinitely. */ for(;;){ /* Block indefinitely (without a timeout, so no need to check the function's return value) to wait for a notification. Bits in this RTOS task's notification value are set by the notifying tasks and interrupts to indicate which events have occurred. */ xTaskNotifyWait(pdFALSE, /* Don't clear any notification bits on entry. */ UINT32_MAX, /* Reset the notification value to 0 on exit. */ &ulNotifiedValue, /* Notified value pass out in ulNotifiedValue. */ xMaxBlockTime ); if(ulNotifiedValue & STOP_PROGRAM_NOTIFICATION){ // stop audioStatus = AUDIO_EXIT_STATUS; codec.softMute(true); if(xProgramHandle != NULL){ programVector = &staticVector; vTaskDelete(xProgramHandle); xProgramHandle = NULL; } } // allow idle task to garbage collect if necessary vTaskDelay(20); // vTaskDelay(pdMS_TO_TICKS(200)); if(ulNotifiedValue & START_PROGRAM_NOTIFICATION){ // start PatchDefinition* def = getPatchDefinition(); if(xProgramHandle == NULL && def != NULL){ BaseType_t ret; if(def->getStackBase() != 0 && def->getStackSize() > configMINIMAL_STACK_SIZE*sizeof(portSTACK_TYPE)){ ret = xTaskGenericCreate(runProgramTask, "Program", def->getStackSize()/sizeof(portSTACK_TYPE), NULL, PROGRAM_TASK_PRIORITY, &xProgramHandle, def->getStackBase(), NULL); }else{ ret = xTaskCreate(runProgramTask, "Program", PROGRAM_TASK_STACK_SIZE, NULL, PROGRAM_TASK_PRIORITY, &xProgramHandle); } if(ret != pdPASS) setErrorMessage(PROGRAM_ERROR, "Failed to start program task"); } #ifdef BUTTON_PROGRAM_CHANGE }else if(ulNotifiedValue & PROGRAM_CHANGE_NOTIFICATION){ // program change if(xProgramHandle == NULL){ BaseType_t ret = xTaskCreate(programChangeTask, "Program Change", PC_TASK_STACK_SIZE, NULL, PC_TASK_PRIORITY, &xProgramHandle); if(ret != pdPASS) setErrorMessage(PROGRAM_ERROR, "Failed to start Program Change task"); } #endif /* BUTTON_PROGRAM_CHANGE */ }else if(ulNotifiedValue & PROGRAM_FLASH_NOTIFICATION){ // program flash BaseType_t ret = xTaskCreate(programFlashTask, "Flash Write", FLASH_TASK_STACK_SIZE, NULL, FLASH_TASK_PRIORITY, &xFlashTaskHandle); if(ret != pdPASS){ setErrorMessage(PROGRAM_ERROR, "Failed to start Flash Write task"); } }else if(ulNotifiedValue & ERASE_FLASH_NOTIFICATION){ // erase flash BaseType_t ret = xTaskCreate(eraseFlashTask, "Flash Erase", FLASH_TASK_STACK_SIZE, NULL, FLASH_TASK_PRIORITY, &xFlashTaskHandle); if(ret != pdPASS) setErrorMessage(PROGRAM_ERROR, "Failed to start Flash Erase task"); // }else if(ulNotifiedValue & MIDI_SEND_NOTIFICATION){ // erase flash // TaskHandle_t handle = NULL; // BaseType_t ret = xTaskCreate(sendMidiDataTask, "MIDI", PC_TASK_STACK_SIZE, NULL, PC_TASK_PRIORITY, &handle); // if(ret != pdPASS){ // setErrorMessage(PROGRAM_ERROR, "Failed to start MIDI Send task"); // } } } }