void vSerialClose( xComPortHandle xPort ) { uint8_t ucByte; /* The parameter is not used. */ ( void ) xPort; /* Turn off the interrupts. We may also want to delete the queues and/or re-install the original ISR. */ vPortFree (serialWorkBuffer); vQueueDelete(xRxedChars); vQueueDelete(xCharsForTx); portENTER_CRITICAL(); { vInterruptOff(); ucByte = UCSR0B; ucByte &= ~(_BV(RXCIE0)); UCSR0B = ucByte; } portEXIT_CRITICAL(); }
/* setup a timer so the Restart timer function can be used */ void SetupOneSecondTimer(tTimerId TimerId, unsigned int Timeout, unsigned char RepeatCount, unsigned char Qindex, eMessageType CallbackMsgType, unsigned char MsgOptions) { if (OneSecondTimers[TimerId].Allocated == 0 || TimerId < 0) { PrintString("Timer not Allocated\r\n"); return; } portENTER_CRITICAL(); OneSecondTimers[TimerId].RepeatCount = RepeatCount; OneSecondTimers[TimerId].Timeout = Timeout; OneSecondTimers[TimerId].Qindex = Qindex; OneSecondTimers[TimerId].CallbackMsgType = CallbackMsgType; OneSecondTimers[TimerId].CallbackMsgOptions = MsgOptions; portEXIT_CRITICAL(); }
/* ********************************************************************************************************* * UartReadByte() * * Description : Receive a single byte. * * Argument(s) : number of UART. * * Return(s) : The received byte. * * Caller(s) : Application. * * Note(s) : ********************************************************************************************************* */ void ValidatorPulseProcessing (u32 call_period) { static u32 puls_with_cnt = 0; if (!GPIO_ReadInputDataBit(VALIDATOR_PULS_IN)) { puls_with_cnt += call_period; } else if (puls_with_cnt > 0) { if ((puls_with_cnt > ValidatorNV9.PeriodCntMin) && (puls_with_cnt < ValidatorNV9.PeriodCntMax)) { // ValidatorNV9.SynchroFlag = SET; portENTER_CRITICAL(); ValidatorNV9.MoneyQuantity++; portEXIT_CRITICAL(); // ValidatorNV9.SynchroFlag = RESET; } puls_with_cnt = 0; } }
/* The preemptive scheduler is defined as "naked" as the full context is saved on entry as part of the context switch. */ __attribute__((__naked__)) static void vTick( void ) { /* Save the context of the interrupted task. */ portSAVE_CONTEXT_OS_INT(); #if( configTICK_USE_TC==1 ) /* Clear the interrupt flag. */ prvClearTcInt(); #else /* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ) clock cycles from now. */ prvScheduleNextTick(); #endif /* Because FreeRTOS is not supposed to run with nested interrupts, put all OS calls in a critical section . */ portENTER_CRITICAL(); xTaskIncrementTick(); portEXIT_CRITICAL(); /* Restore the context of the "elected task". */ portRESTORE_CONTEXT_OS_INT(); }
// // Set clock to new values. // static void rtcWrite (struct tm *newTime) { rtcWake (); portENTER_CRITICAL (); RTC_CCR &= ~RTC_CCR_CLKEN; RTC_CCR |= RTC_CCR_CTCRST; RTC_SEC = newTime->tm_sec; RTC_MIN = newTime->tm_min; RTC_HOUR = newTime->tm_hour; RTC_DOM = newTime->tm_mday; RTC_MONTH = newTime->tm_mon + 1; RTC_YEAR = newTime->tm_year + 1900; RTC_DOW = newTime->tm_wday; RTC_DOY = newTime->tm_yday + 1; RTC_CCR &= ~RTC_CCR_CTCRST; RTC_CCR |= RTC_CCR_CLKEN; portEXIT_CRITICAL (); rtcSleep (); }
static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters ) { uint16_t usData, usExpectedValue = ( uint16_t ) 0; BaseType_t xError = pdFALSE; for( ;; ) { /* Loop until the queue is empty. */ while( uxQueueMessagesWaiting( *( ( QueueHandle_t * ) pvParameters ) ) ) { if( xQueueReceive( *( ( QueueHandle_t * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS ) { if( usData != usExpectedValue ) { /* This is not what we expected to receive so an error has occurred. */ xError = pdTRUE; /* Catch-up to the value we received so our next expected value should again be correct. */ usExpectedValue = usData; } else { if( xError == pdFALSE ) { /* Only increment the check variable if no errors have occurred. */ portENTER_CRITICAL(); xPollingConsumerCount++; portEXIT_CRITICAL(); } } /* Next time round we would expect the number to be one higher. */ usExpectedValue++; } } /* Now the queue is empty we block, allowing the producer to place more items in the queue. */ vTaskDelay( pollqCONSUMER_DELAY ); } } /*lint !e818 Function prototype must conform to API. */
/*-----------------------------------------------------------*/ xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength ) { /* Initialise the hardware. */ portENTER_CRITICAL(); { /* Create the queues used by the com test task. */ xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof(signed char) ); xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof(signed char) ); if( xRxedChars == 0 ) { queueFail = pdTRUE; } if( xCharsForTx == 0 ) { queueFail = pdTRUE; } /* Initialize UART asynchronous mode */ BGR0 = configCLKP1_CLOCK_HZ / ulWantedBaud; SCR0 = 0x17; /* 8N1 */ SMR0 = 0x0d; /* enable SOT3, Reset, normal mode */ SSR0 = 0x02; /* LSB first, enable receive interrupts */ PIER08_IE2 = 1; /* enable input */ DDR08_D2 = 0; /* switch P08_2 to input */ DDR08_D3 = 1; /* switch P08_3 to output */ } portEXIT_CRITICAL(); /* Unlike other ports, this serial code does not allow for more than one com port. We therefore don't return a pointer to a port structure and can instead just return NULL. */ return NULL; }
static long prvMACB_ISR_NonNakedBehaviour( void ) { // Variable definitions can be made now. volatile unsigned long ulIntStatus, ulEventStatus; long xHigherPriorityTaskWoken = FALSE; // Find the cause of the interrupt. ulIntStatus = AVR32_MACB.isr; ulEventStatus = AVR32_MACB.rsr; if( ( ulIntStatus & AVR32_MACB_IDR_RCOMP_MASK ) || ( ulEventStatus & AVR32_MACB_REC_MASK ) ) { // A frame has been received, signal the IP task so it can process // the Rx descriptors. portENTER_CRITICAL(); #ifdef FREERTOS_USED xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); #else DataToRead = TRUE; #endif portEXIT_CRITICAL(); AVR32_MACB.rsr = AVR32_MACB_REC_MASK; AVR32_MACB.rsr; } if( ulIntStatus & AVR32_MACB_TCOMP_MASK ) { // A frame has been transmitted. Mark all the buffers used by the // frame just transmitted as free again. vClearMACBTxBuffer(); AVR32_MACB.tsr = AVR32_MACB_TSR_COMP_MASK; AVR32_MACB.tsr; } return ( xHigherPriorityTaskWoken ); }
static portTASK_FUNCTION( vPolledQueueProducer, pvParameters ) { unsigned short usValue = ( unsigned short ) 0; signed portBASE_TYPE xError = pdFALSE, xLoop; for( ;; ) { for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ ) { /* Send an incrementing number on the queue without blocking. */ if( xQueueSend( *( ( xQueueHandle * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS ) { /* We should never find the queue full so if we get here there has been an error. */ xError = pdTRUE; } else { if( xError == pdFALSE ) { /* If an error has ever been recorded we stop incrementing the check variable. */ portENTER_CRITICAL(); xPollingProducerCount++; portEXIT_CRITICAL(); } /* Update the value we are going to post next time around. */ usValue++; } } /* Wait before we start posting again to ensure the consumer runs and empties the queue. */ vTaskDelay( pollqPRODUCER_DELAY ); } } /*lint !e818 Function prototype must conform to API. */
void esp_task_wdt_delete() { TaskHandle_t handle=xTaskGetCurrentTaskHandle(); wdt_task_t *wdttask=wdt_task_list; portENTER_CRITICAL(&taskwdt_spinlock); //Wdt task list can't be empty if (!wdt_task_list) { ESP_LOGE(TAG, "task_wdt_delete: No tasks in list?"); portEXIT_CRITICAL(&taskwdt_spinlock); return; } if (handle==wdt_task_list) { //Current task is first on list. wdt_task_list=wdt_task_list->next; free(wdttask); } else { //Find current task in list if (wdt_task_list->task_handle==handle) { //Task is the very first one. wdt_task_t *freeme=wdt_task_list; wdt_task_list=wdt_task_list->next; free(freeme); portEXIT_CRITICAL(&taskwdt_spinlock); return; } while (wdttask->next!=NULL && wdttask->next->task_handle!=handle) wdttask=wdttask->next; if (!wdttask->next) { ESP_LOGE(TAG, "task_wdt_delete: Task never called task_wdt_feed!"); portEXIT_CRITICAL(&taskwdt_spinlock); return; } wdt_task_t *freeme=wdttask->next; wdttask->next=wdttask->next->next; free(freeme); } portEXIT_CRITICAL(&taskwdt_spinlock); }
/* * See the serial2.h header file. */ xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength ) { xComPortHandle xReturn = serHANDLE; /* Create the queues used to hold Rx and Tx characters. */ xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) ); xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed char ) ); /* If the queues were created correctly then setup the serial port hardware. */ if( ( xRxedChars != serINVALID_QUEUE ) && ( xCharsForTx != serINVALID_QUEUE ) ) { PMC_EnablePeripheral( AT91C_ID_US0 ); portENTER_CRITICAL(); { USART_Configure( serCOM0, ( AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE ), ulWantedBaud, configCPU_CLOCK_HZ ); /* Enable Rx and Tx. */ USART_SetTransmitterEnabled( serCOM0, pdTRUE ); USART_SetReceiverEnabled( serCOM0, pdTRUE ); /* Enable the Rx interrupts. The Tx interrupts are not enabled until there are characters to be transmitted. */ serCOM0->US_IER = AT91C_US_RXRDY; /* Enable the interrupts in the AIC. */ AIC_ConfigureIT( AT91C_ID_US0, AT91C_AIC_PRIOR_LOWEST, ( void (*)( void ) ) vSerialISR ); AIC_EnableIT( AT91C_ID_US0 ); } portEXIT_CRITICAL(); } else { xReturn = ( xComPortHandle ) 0; } /* This demo file only supports a single port but we have to return something to comply with the standard demo header file. */ return xReturn; }
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, portTickType xBlockTime ) { portBASE_TYPE xReturn = pdTRUE; portENTER_CRITICAL(); { /* If the UART FIFO is full we can block posting the new data on the Tx queue. */ if( XUartLite_mIsTransmitFull( XPAR_RS232_UART_BASEADDR ) ) { if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS ) { xReturn = pdFAIL; } } /* Otherwise, if there is data already in the queue we should add the new data to the back of the queue to ensure the sequencing is maintained. */ else if( uxQueueMessagesWaiting( xCharsForTx ) ) { if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS ) { xReturn = pdFAIL; } } /* If the UART FIFO is not full and there is no data already in the queue we can write directly to the FIFO without disrupting the sequence. */ else { XIo_Out32( XPAR_RS232_UART_BASEADDR + XUL_TX_FIFO_OFFSET, cOutChar ); } } portEXIT_CRITICAL(); return xReturn; }
xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength ) { unsigned long ulBaudRateCounter; unsigned char ucByte; portENTER_CRITICAL(); { /* Create the queues used by the com test task. */ xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) ); xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) ); /* Calculate the baud rate register value from the equation in the data sheet. */ ulBaudRateCounter = ( configCPU_CLOCK_HZ / ( serBAUD_DIV_CONSTANT * ulWantedBaud ) ) - ( unsigned long ) 1; /* Set the baud rate. */ ucByte = ( unsigned char ) ( ulBaudRateCounter & ( unsigned long ) 0xff ); outb( UBRRL, ucByte ); ulBaudRateCounter >>= ( unsigned long ) 8; ucByte = ( unsigned char ) ( ulBaudRateCounter & ( unsigned long ) 0xff ); outb( UBRRH, ucByte ); /* Enable the Rx interrupt. The Tx interrupt will get enabled later. Also enable the Rx and Tx. */ outb( UCSRB, serRX_INT_ENABLE | serRX_ENABLE | serTX_ENABLE ); /* Set the data bits to 8. */ outb( UCSRC, serUCSRC_SELECT | serEIGHT_DATA_BITS ); } portEXIT_CRITICAL(); /* Unlike other ports, this serial code does not allow for more than one com port. We therefore don't return a pointer to a port structure and can instead just return NULL. */ return NULL; }
void vParTestToggleLED( unsigned portBASE_TYPE uxLED ) { portENTER_CRITICAL(); { switch( uxLED ) { case 0: PTHD_PTHD3 = !PTHD_PTHD3; break; case 1: PTED_PTED5 = !PTED_PTED5; break; case 2: PTGD_PTGD5 = !PTGD_PTGD5; break; case 3: PTED_PTED3 = !!PTED_PTED3; break; default : /* There are no other LEDs. */ break; } } portEXIT_CRITICAL(); }
/** * \brief Creates and returns a new semaphore. * * \param count Initial state of the semaphore. * * \return ERR_OK for OK, other value indicates error. */ sys_sem_t sys_sem_new(u8_t count) { sys_sem_t xSemaphore = SYS_SEM_NULL; portENTER_CRITICAL(); vSemaphoreCreateBinary( xSemaphore ); if (xSemaphore != SYS_SEM_NULL) { #if SYS_STATS lwip_stats.sys.sem.used++; if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) { lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; } #endif /* SYS_STATS */ /* Means we want the sem to be unavailable at init state. */ if (0 == count) { xSemaphoreTake( xSemaphore, 1); } } portEXIT_CRITICAL(); return xSemaphore; }
static void AddUser(unsigned char User,unsigned int CrystalTicks) { portENTER_CRITICAL(); /* minimum value of 1 tick */ if ( CrystalTicks < 1 ) { CrystalTicks = 1; } unsigned int CaptureTime = TA0R + CrystalTicks; /* clear ifg, add to ccr register, enable interrupt */ switch (User) { case 0: TA0CCTL0 = 0; TA0CCR0 = CaptureTime; TA0CCTL0 = CCIE; break; case 1: TA0CCTL1 = 0; TA0CCR1 = CaptureTime; TA0CCTL1 = CCIE; break; case 2: TA0CCTL2 = 0; TA0CCR2 = CaptureTime; TA0CCTL2 = CCIE; break; case 3: TA0CCTL3 = 0; TA0CCR3 = CaptureTime; TA0CCTL3 = CCIE; break; case 4: TA0CCTL4 = 0; TA0CCR4 = CaptureTime; TA0CCTL4 = CCIE; break; default: break; } /* start counting up in continuous mode if not already doing so */ if ( Timer0Users == 0 ) { TA0CTL |= TASSEL_1 | MC_2 | ID_2; } /* keep track of users */ Timer0Users |= (1 << User); portEXIT_CRITICAL(); }
void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue ) { unsigned char ucLED = 1U; /* Only attempt to set the LED if it is in range. */ if( uxLED < partstMAX_LED ) { ucLED <<= ( unsigned char ) uxLED; portENTER_CRITICAL(); { if( xValue == pdFALSE ) { ucGPIOState &= ~ucLED; } else { ucGPIOState |= ucLED; } XGpio_DiscreteWrite( &xOutputGPIOInstance, uxGPIOOutputChannel, ucGPIOState ); } portEXIT_CRITICAL(); } }
void RxThread() { while (1) { os_sem_wait(&rxSem); portENTER_CRITICAL(); // we read the packet received to our assembly buffer bool result = readEP_NB(rxData, &rxSize); portEXIT_CRITICAL(); if (!result) { diewith(0x80000CCC); } for (uint32_t i = 0; i < rxSize; i++) { /// @todo (balazs.racz) this needs to be replaced with something /// that works in the new select based model. //os_mq_send(rxQ, rxData + i); } rxSize = 0; // We reactivate the endpoint to receive next characters // readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); } }
/******************************************************************************* * FUNCTION: vLogStackWatermark * * PARAMETERS: * ~ szTaskName - Task name. * ~ usWatermark - Value for watermark. * * RETURN: * ~ void * * DESCRIPTIONS: * Log the RTOS low stack error. * *******************************************************************************/ void vLogStackWatermark(const char* szTaskName, unsigned short usWatermark) { // Convert the watermark to string. char szWatermark[6]; prv_vUShortToString(usWatermark, szWatermark); // Open the log file. xSemaphoreTake(xSdCardMutex, portMAX_DELAY); portENTER_CRITICAL(); FSFILE *pxLogFile = FSfopen(pucLogFilePath, "a"); // Write the message. const char szTxt1[] = "[Stack Error] "; FSfwrite(szTxt1, 1, sizeof(szTxt1) - 1, pxLogFile); FSfwrite(szTaskName, 1, strlen(szTaskName), pxLogFile); const char szTxt2[] = " Watermark: "; FSfwrite(szTxt2, 1, sizeof(szTxt2) - 1, pxLogFile); FSfwrite(szWatermark, 1, strlen(szWatermark), pxLogFile); const char szTxt3[] = " Firmware: "; FSfwrite(szTxt3, 1, sizeof(szTxt3) - 1, pxLogFile); FSfwrite(szFirmwareVersion, 1, strlen(szFirmwareVersion), pxLogFile); const char szCrLf[] = "\r\n"; FSfwrite(szCrLf, 1, sizeof(szCrLf) - 1, pxLogFile); // Close the log file. FSfclose(pxLogFile); portEXIT_CRITICAL(); xSemaphoreGive(xSdCardMutex); }
signed portBASE_TYPE xMutexGive( xMutexHandle pxMutex, portBASE_TYPE Release ) { portENTER_CRITICAL( ); if ( pxMutex->pxOwner != xTaskGetCurrentTaskHandle( ) ) { portEXIT_CRITICAL( ); return pdFALSE; } if ( Release ) pxMutex->uxCount = 0; else { if ( --pxMutex->uxCount != 0 ) { portEXIT_CRITICAL( ); return pdFALSE; } } if( !listLIST_IS_EMPTY( &pxMutex->xTasksWaitingToTake ) ) { pxMutex->pxOwner = (xTaskHandle) listGET_OWNER_OF_HEAD_ENTRY( ( &pxMutex->xTasksWaitingToTake ) ); pxMutex->uxCount = 1; if( xTaskRemoveFromEventList( &pxMutex->xTasksWaitingToTake ) == pdTRUE ) taskYIELD( ); } else { pxMutex->pxOwner = NULL; } portEXIT_CRITICAL( ); return pdTRUE; }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // clear LCD screen MIOS32_LCD_Clear(); // endless loop: print status information on LCD while( 1 ) { // new message requested? // TODO: add FreeRTOS specific queue handling! u8 new_msg = PRINT_MSG_NONE; portENTER_CRITICAL(); // port specific FreeRTOS function to disable tasks (nested) if( print_msg ) { new_msg = print_msg; print_msg = PRINT_MSG_NONE; // clear request } portEXIT_CRITICAL(); // port specific FreeRTOS function to enable tasks (nested) switch( new_msg ) { case PRINT_MSG_INIT: MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintString("see README.txt "); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintString("for details "); break; case PRINT_MSG_STATUS: { MIOS32_LCD_CursorSet(0, 0); // request status screen again (will stop once a new screen is requested by another task) print_msg = PRINT_MSG_STATUS; } break; } } }
/* * Controller task as described above. */ static void vCounterControlTask( void * pvParameters ) { unsigned long ulLastCounter; short sLoops; short sError = pdFALSE; const char * const pcTaskStartMsg = "Priority manipulation tasks started.\r\n"; const char * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n"; /* Just to stop warning messages. */ ( void ) pvParameters; /* Queue a message for printing to say the task has started. */ vPrintDisplayMessage( &pcTaskStartMsg ); for( ;; ) { /* Start with the counter at zero. */ ulCounter = ( unsigned long ) 0; /* First section : */ /* Check the continuous count task is running. */ for( sLoops = 0; sLoops < priLOOPS; sLoops++ ) { /* Suspend the continuous count task so we can take a mirror of the shared variable without risk of corruption. */ vTaskSuspend( xContinuousIncrementHandle ); ulLastCounter = ulCounter; vTaskResume( xContinuousIncrementHandle ); /* Now delay to ensure the other task has processor time. */ vTaskDelay( priSLEEP_TIME ); /* Check the shared variable again. This time to ensure mutual exclusion the whole scheduler will be locked. This is just for demo purposes! */ vTaskSuspendAll(); { if( ulLastCounter == ulCounter ) { /* The shared variable has not changed. There is a problem with the continuous count task so flag an error. */ sError = pdTRUE; xTaskResumeAll(); vPrintDisplayMessage( &pcTaskFailMsg ); vTaskSuspendAll(); } } xTaskResumeAll(); } /* Second section: */ /* Suspend the continuous counter task so it stops accessing the shared variable. */ vTaskSuspend( xContinuousIncrementHandle ); /* Reset the variable. */ ulCounter = ( unsigned long ) 0; /* Resume the limited count task which has a higher priority than us. We should therefore not return from this call until the limited count task has suspended itself with a known value in the counter variable. The scheduler suspension is not necessary but is included for test purposes. */ vTaskSuspendAll(); vTaskResume( xLimitedIncrementHandle ); xTaskResumeAll(); /* Does the counter variable have the expected value? */ if( ulCounter != priMAX_COUNT ) { sError = pdTRUE; vPrintDisplayMessage( &pcTaskFailMsg ); } if( sError == pdFALSE ) { /* If no errors have occurred then increment the check variable. */ portENTER_CRITICAL(); usCheckVariable++; portEXIT_CRITICAL(); } #if configUSE_PREEMPTION == 0 taskYIELD(); #endif /* Resume the continuous count task and do it all again. */ vTaskResume( xContinuousIncrementHandle ); } }
static void prvChangePriorityWhenSuspendedTask( void *pvParameters ) { const char * const pcTaskStartMsg = "Priority change when suspended task started.\r\n"; const char * const pcTaskFailMsg = "Priority change when suspended task failed.\r\n"; /* Just to stop warning messages. */ ( void ) pvParameters; /* Queue a message for printing to say the task has started. */ vPrintDisplayMessage( &pcTaskStartMsg ); for( ;; ) { /* Start with the counter at 0 so we know what the counter should be when we check it next. */ ulPrioritySetCounter = ( unsigned long ) 0; /* Resume the helper task. At this time it has a priority lower than ours so no context switch should occur. */ vTaskResume( xChangePriorityWhenSuspendedHandle ); /* Check to ensure the task just resumed has not executed. */ portENTER_CRITICAL(); { if( ulPrioritySetCounter != ( unsigned long ) 0 ) { xPriorityRaiseWhenSuspendedError = pdTRUE; vPrintDisplayMessage( &pcTaskFailMsg ); } } portEXIT_CRITICAL(); /* Now try raising the priority while the scheduler is suspended. */ vTaskSuspendAll(); { vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, ( configMAX_PRIORITIES - 1 ) ); /* Again, even though the helper task has a priority greater than ours, it should not have executed yet because the scheduler is suspended. */ portENTER_CRITICAL(); { if( ulPrioritySetCounter != ( unsigned long ) 0 ) { xPriorityRaiseWhenSuspendedError = pdTRUE; vPrintDisplayMessage( &pcTaskFailMsg ); } } portEXIT_CRITICAL(); } xTaskResumeAll(); /* Now the scheduler has been resumed the helper task should immediately preempt us and execute. When it executes it will increment the ulPrioritySetCounter exactly once before suspending itself. We should now always find the counter set to 1. */ portENTER_CRITICAL(); { if( ulPrioritySetCounter != ( unsigned long ) 1 ) { xPriorityRaiseWhenSuspendedError = pdTRUE; vPrintDisplayMessage( &pcTaskFailMsg ); } } portEXIT_CRITICAL(); /* Delay until we try this again. */ vTaskDelay( priSLEEP_TIME * 2 ); /* Set the priority of the helper task back ready for the next execution of this task. */ vTaskSuspendAll(); vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, tskIDLE_PRIORITY ); xTaskResumeAll(); } }
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { // reset tap tempo if any encoder != GP16 has been pressed if( encoder != SEQ_UI_ENCODER_GP16 ) resetTapTempo(); switch( encoder ) { case SEQ_UI_ENCODER_GP1: ui_selected_item = ITEM_MODE; break; case SEQ_UI_ENCODER_GP2: ui_selected_item = ITEM_PRESET; break; case SEQ_UI_ENCODER_GP3: ui_selected_item = ITEM_BPM; // special feature: these two encoders increment *10 incrementer *= 10; break; case SEQ_UI_ENCODER_GP4: ui_selected_item = ITEM_BPM; break; case SEQ_UI_ENCODER_GP5: ui_selected_item = ITEM_RAMP; break; case SEQ_UI_ENCODER_GP6: case SEQ_UI_ENCODER_GP7: case SEQ_UI_ENCODER_GP8: return -1; // not mapped to encoder case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_MCLK_PORT; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_MCLK_IN; break; case SEQ_UI_ENCODER_GP11: ui_selected_item = ITEM_MCLK_OUT; break; case SEQ_UI_ENCODER_GP12: case SEQ_UI_ENCODER_GP13: return -1; // not used (yet) case SEQ_UI_ENCODER_GP14: case SEQ_UI_ENCODER_GP15: // external restart request should be atomic portENTER_CRITICAL(); seq_core_state.EXT_RESTART_REQ = 1; portEXIT_CRITICAL(); return 1; case SEQ_UI_ENCODER_GP16: SEQ_UI_BPM_TapTempo(); return 1; } // for GP encoders and Datawheel switch( ui_selected_item ) { case ITEM_MODE: { u8 value = SEQ_BPM_ModeGet(); if( SEQ_UI_Var8_Inc(&value, 0, 2, incrementer) ) { SEQ_BPM_ModeSet(value); store_file_required = 1; return 1; // value has been changed } else return 0; // value hasn't been changed } break; case ITEM_PRESET: { return SEQ_UI_Var8_Inc(&seq_core_bpm_preset_num, 0, SEQ_CORE_NUM_BPM_PRESETS-1, incrementer); } break; case ITEM_BPM: { u16 value = (u16)(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num]*10); if( SEQ_UI_Var16_Inc(&value, 25, 3000, incrementer) ) { // at 384ppqn, the minimum BPM rate is ca. 2.5 // set new BPM seq_core_bpm_preset_tempo[seq_core_bpm_preset_num] = (float)value/10.0; SEQ_CORE_BPM_Update(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num], seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]); store_file_required = 1; return 1; // value has been changed } else return 0; // value hasn't been changed } break; case ITEM_RAMP: { u16 value = (u16)seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]; if( SEQ_UI_Var16_Inc(&value, 0, 99, incrementer) ) { seq_core_bpm_preset_ramp[seq_core_bpm_preset_num] = (float)value; store_file_required = 1; return 1; // value has been changed } else return 0; // value hasn't been changed } break; case ITEM_MCLK_PORT: { u8 port_ix = SEQ_MIDI_PORT_ClkIxGet(selected_mclk_port); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_ClkNumGet()-1, incrementer) >= 0 ) { selected_mclk_port = SEQ_MIDI_PORT_ClkPortGet(port_ix); return 1; // value changed } return 0; // no change } break; case ITEM_MCLK_IN: { s32 status = SEQ_MIDI_ROUTER_MIDIClockInGet(selected_mclk_port); if( status < 0 ) return 0; // no change u8 enable = status; if( SEQ_UI_Var8_Inc(&enable, 0, 1, incrementer) >= 0 ) { SEQ_MIDI_ROUTER_MIDIClockInSet(selected_mclk_port, enable); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_MCLK_OUT: { s32 status = SEQ_MIDI_ROUTER_MIDIClockOutGet(selected_mclk_port); if( status < 0 ) return 0; // no change u8 enable = status; if( SEQ_UI_Var8_Inc(&enable, 0, 1, incrementer) >= 0 ) { SEQ_MIDI_ROUTER_MIDIClockOutSet(selected_mclk_port, enable); store_file_required = 1; return 1; // value changed } return 0; // no change } break; } return -1; // invalid or unsupported encoder }
/* * See the serial2.h header file. */ xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength ) { xComPortHandle xReturn; UART_InitTypeDef xUART1_Init; GPIO_InitTypeDef GPIO_InitStructure; /* Create the queues used to hold Rx characters. */ xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) ); /* Create the semaphore used to wake a task waiting for space to become available in the FIFO. */ vSemaphoreCreateBinary( xTxFIFOSemaphore ); /* If the queue/semaphore was created correctly then setup the serial port hardware. */ if( ( xRxedChars != serINVALID_QUEUE ) && ( xTxFIFOSemaphore != serINVALID_QUEUE ) ) { /* Pre take the semaphore so a task will block if it tries to access it. */ xSemaphoreTake( xTxFIFOSemaphore, 0 ); /* Configure the UART. */ xUART1_Init.UART_WordLength = UART_WordLength_8D; xUART1_Init.UART_StopBits = UART_StopBits_1; xUART1_Init.UART_Parity = UART_Parity_No; xUART1_Init.UART_BaudRate = ulWantedBaud; xUART1_Init.UART_HardwareFlowControl = UART_HardwareFlowControl_None; xUART1_Init.UART_Mode = UART_Mode_Tx_Rx; xUART1_Init.UART_FIFO = UART_FIFO_Enable; /* Enable the UART1 Clock */ SCU_APBPeriphClockConfig( __UART1, ENABLE ); /* Enable the GPIO3 Clock */ SCU_APBPeriphClockConfig( __GPIO3, ENABLE ); /* Configure UART1_Rx pin GPIO3.2 */ GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable; GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1 ; GPIO_Init( GPIO3, &GPIO_InitStructure ); /* Configure UART1_Tx pin GPIO3.3 */ GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable; GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2 ; GPIO_Init( GPIO3, &GPIO_InitStructure ); portENTER_CRITICAL(); { /* Configure the UART itself. */ UART_DeInit( UART1 ); UART_Init( UART1, &xUART1_Init ); UART_ITConfig( UART1, UART_IT_Receive | UART_IT_Transmit, ENABLE ); UART1->ICR = serCLEAR_ALL_INTERRUPTS; UART_LoopBackConfig( UART1, DISABLE ); UART_IrDACmd( IrDA1, DISABLE ); /* Configure the VIC for the UART interrupts. */ VIC_Config( UART1_ITLine, VIC_IRQ, 9 ); VIC_ITCmd( UART1_ITLine, ENABLE ); UART_Cmd( UART1, ENABLE ); lTaskWaiting = pdFALSE; } portEXIT_CRITICAL(); } else { xReturn = ( xComPortHandle ) 0; } /* This demo file only supports a single port but we have to return something to comply with the standard demo header file. */ return xReturn; }
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { uint32_t *pulUpperCSA = NULL; uint32_t *pulLowerCSA = NULL; /* 16 Address Registers (4 Address registers are global), 16 Data Registers, and 3 System Registers. There are 3 registers that track the CSAs. FCX points to the head of globally free set of CSAs. PCX for the task needs to point to Lower->Upper->NULL arrangement. LCX points to the last free CSA so that corrective action can be taken. Need two CSAs to store the context of a task. The upper context contains D8-D15, A10-A15, PSW and PCXI->NULL. The lower context contains D0-D7, A2-A7, A11 and PCXI->UpperContext. The pxCurrentTCB->pxTopOfStack points to the Lower Context RSLCX matching the initial BISR. The Lower Context points to the Upper Context ready for the return from the interrupt handler. The Real stack pointer for the task is stored in the A10 which is restored with the upper context. */ /* Have to disable interrupts here because the CSAs are going to be manipulated. */ portENTER_CRITICAL(); { /* DSync to ensure that buffering is not a problem. */ _dsync(); /* Consume two free CSAs. */ pulLowerCSA = portCSA_TO_ADDRESS( _mfcr( $FCX ) ); if( NULL != pulLowerCSA ) { /* The Lower Links to the Upper. */ pulUpperCSA = portCSA_TO_ADDRESS( pulLowerCSA[ 0 ] ); } /* Check that we have successfully reserved two CSAs. */ if( ( NULL != pulLowerCSA ) && ( NULL != pulUpperCSA ) ) { /* Remove the two consumed CSAs from the free CSA list. */ _disable(); _dsync(); _mtcr( $FCX, pulUpperCSA[ 0 ] ); _isync(); _enable(); } else { /* Simply trigger a context list depletion trap. */ _svlcx(); } } portEXIT_CRITICAL(); /* Clear the upper CSA. */ memset( pulUpperCSA, 0, portNUM_WORDS_IN_CSA * sizeof( uint32_t ) ); /* Upper Context. */ pulUpperCSA[ 2 ] = ( uint32_t )pxTopOfStack; /* A10; Stack Return aka Stack Pointer */ pulUpperCSA[ 1 ] = portSYSTEM_PROGRAM_STATUS_WORD; /* PSW */ /* Clear the lower CSA. */ memset( pulLowerCSA, 0, portNUM_WORDS_IN_CSA * sizeof( uint32_t ) ); /* Lower Context. */ pulLowerCSA[ 8 ] = ( uint32_t ) pvParameters; /* A4; Address Type Parameter Register */ pulLowerCSA[ 1 ] = ( uint32_t ) pxCode; /* A11; Return Address aka RA */ /* PCXI pointing to the Upper context. */ pulLowerCSA[ 0 ] = ( portINITIAL_PCXI_UPPER_CONTEXT_WORD | ( uint32_t ) portADDRESS_TO_CSA( pulUpperCSA ) ); /* Save the link to the CSA in the top of stack. */ pxTopOfStack = (uint32_t * ) portADDRESS_TO_CSA( pulLowerCSA ); /* DSync to ensure that buffering is not a problem. */ _dsync(); return pxTopOfStack; }
signed portBASE_TYPE uart0Init (unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxQueueLength) { unsigned portLONG ulDivisor; unsigned portLONG ulWantedClock; static unsigned portLONG sulWantedBaud = 9600; static unsigned portBASE_TYPE suxQueueLength = 64; if (!ulWantedBaud) ulWantedBaud = sulWantedBaud; sulWantedBaud = ulWantedBaud; if (!uxQueueLength) uxQueueLength = suxQueueLength; suxQueueLength = uxQueueLength; uart0ISRCreateQueues (uxQueueLength, &xRX0Queue, &xTX0Queue, &plTHREEmpty0); if ((xRX0Queue == serINVALID_QUEUE) || (xTX0Queue == serINVALID_QUEUE) || (ulWantedBaud == (unsigned portLONG) 0)) return 0; portENTER_CRITICAL (); { PCB_PINSEL0 = (PCB_PINSEL0 & ~(PCB_PINSEL0_P00_MASK | PCB_PINSEL0_P01_MASK)) | (PCB_PINSEL0_P00_TXD0 | PCB_PINSEL0_P01_RXD0); SCB_PCONP |= SCB_PCONP_PCUART0; // // Setup the baud rate: Calculate the divisor value // ulWantedClock = ulWantedBaud * serWANTED_CLOCK_SCALING; ulDivisor = configCPU_CLOCK_HZ / ulWantedClock; // // Set the DLAB bit so we can access the divisor // UART0_LCR |= UART_LCR_DLAB; // // Setup the divisor // UART0_DLL = (unsigned portCHAR) (ulDivisor & (unsigned portLONG) 0xff); ulDivisor >>= 8; UART0_DLM = (unsigned portCHAR) (ulDivisor & (unsigned portLONG) 0xff); // // Turn on the FIFO's and clear the buffers // UART0_FCR = UART_FCR_EN | UART_FCR_CLR; // // Setup transmission format // UART0_LCR = UART_LCR_NOPAR | UART_LCR_1STOP | UART_LCR_8BITS; // // Setup the VIC for the UART // VIC_IntSelect &= ~VIC_IntSelect_UART0; VIC_VectAddr2 = (portLONG) uart0ISR; VIC_VectCntl2 = VIC_VectCntl_ENABLE | VIC_Channel_UART0; VIC_IntEnable = VIC_IntEnable_UART0; // // Enable UART0 interrupts // UART0_IER |= UART_IER_EI; } portEXIT_CRITICAL (); return 1; }
void vuIP_Task( void *pvParameters ) { portBASE_TYPE i; uip_ipaddr_t xIPAddr; struct timer periodic_timer, arp_timer; extern void ( vEMAC_ISR_Wrapper )( void ); /* Create the semaphore used by the ISR to wake this task. */ vSemaphoreCreateBinary( xEMACSemaphore ); /* Initialise the uIP stack. */ timer_set( &periodic_timer, configTICK_RATE_HZ / 2 ); timer_set( &arp_timer, configTICK_RATE_HZ * 10 ); uip_init(); uip_ipaddr( xIPAddr, uipIP_ADDR0, uipIP_ADDR1, uipIP_ADDR2, uipIP_ADDR3 ); uip_sethostaddr( xIPAddr ); httpd_init(); /* Initialise the MAC. */ while( Init_EMAC() != pdPASS ) { vTaskDelay( uipINIT_WAIT ); } portENTER_CRITICAL(); { MAC_INTENABLE = INT_RX_DONE; VICIntEnable |= 0x00200000; VICVectAddr21 = ( portLONG ) vEMAC_ISR_Wrapper; prvSetMACAddress(); } portEXIT_CRITICAL(); for( ;; ) { /* Is there received data ready to be processed? */ uip_len = uiGetEMACRxData( uip_buf ); if( uip_len > 0 ) { /* Standard uIP loop taken from the uIP manual. */ if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) { uip_arp_ipin(); uip_input(); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if( uip_len > 0 ) { uip_arp_out(); prvENET_Send(); } } else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) ) { uip_arp_arpin(); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if( uip_len > 0 ) { prvENET_Send(); } } } else { if( timer_expired( &periodic_timer ) ) { timer_reset( &periodic_timer ); for( i = 0; i < UIP_CONNS; i++ ) { uip_periodic( i ); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if( uip_len > 0 ) { uip_arp_out(); prvENET_Send(); } } /* Call the ARP timer function every 10 seconds. */ if( timer_expired( &arp_timer ) ) { timer_reset( &arp_timer ); uip_arp_timer(); } } else { /* We did not receive a packet, and there was no periodic processing to perform. Block for a fixed period. If a packet is received during this period we will be woken by the ISR giving us the Semaphore. */ xSemaphoreTake( xEMACSemaphore, configTICK_RATE_HZ / 2 ); } } } }
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) { xExpectedIdleTime = xMaximumPossibleSuppressedTicks; } /* Stop the SysTick momentarily. The time the SysTick is stopped for is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; /* Calculate the reload value required to wait xExpectedIdleTime tick periods. -1 is used because this code will execute part way through one of the tick periods. */ ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); if( ulReloadValue > ulStoppedTimerCompensation ) { ulReloadValue -= ulStoppedTimerCompensation; } /* Enter a critical section but don't use the taskENTER_CRITICAL() method as that will mask interrupts that should exit sleep mode. */ __disable_irq(); /* If a context switch is pending or a task is waiting for the scheduler to be unsuspended then abandon the low power entry. */ if( eTaskConfirmSleepModeStatus() == eAbortSleep ) { /* Restart from whatever is left in the count register to complete this tick period. */ portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; /* Restart SysTick. */ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Reset the reload register to the value required for normal tick periods. */ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; /* Re-enable interrupts - see comments above __disable_irq() call above. */ __enable_irq(); } else { /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; /* Clear the SysTick count flag and set the count value back to zero. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains its own wait for interrupt or wait for event instruction, and so wfi should not be executed again. However, the original expected idle time variable must remain unmodified, so a copy is taken. */ xModifiableIdleTime = xExpectedIdleTime; configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); if( xModifiableIdleTime > 0 ) { __dsb( portSY_FULL_READ_WRITE ); __wfi(); __isb( portSY_FULL_READ_WRITE ); } configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); /* Stop SysTick. Again, the time the SysTick is stopped for is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); /* Re-enable interrupts - see comments above __disable_irq() call above. */ __enable_irq(); if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; /* The tick interrupt has already executed, and the SysTick count reloaded with ulReloadValue. Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick period. */ ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); /* Don't allow a tiny value, or values that have somehow underflowed because the post sleep hook did something that took too long. */ if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) { ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); } portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; /* The tick interrupt handler will already have pended the tick processing in the kernel. As the pending tick will be processed as soon as this function exits, the tick value maintained by the tick is stepped forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; } else { /* Something other than the tick interrupt ended the sleep. Work out how long the sleep lasted rounded to complete tick periods (not the ulReload value which accounted for part ticks). */ ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; /* How many complete tick periods passed while the processor was waiting? */ ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; /* The reload value is set to whatever fraction of a single tick period remains. */ portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, then set portNVIC_SYSTICK_LOAD_REG back to its standard value. The critical section is used to ensure the tick interrupt can only execute once in the case that the reload register is near zero. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portENTER_CRITICAL(); { portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; vTaskStepTick( ulCompleteTickPeriods ); portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; } portEXIT_CRITICAL(); } }
// 受信 bool clBTLUSB::Rx(PACKET_t &packet) { if (m_Rx.Size <= 0) return false; // クリティカルセクションは時間がかかるため、最初に一度チェックする portENTER_CRITICAL(); unsigned int size = m_Rx.Size; if (size <= 0) { // 二重にチェック portEXIT_CRITICAL(); return false; } bool result = false; // キュー内のインデックスを計算 unsigned int next = m_Rx.Next; unsigned int index = LowerWrap(next - size, RX_QUEUELEVEL); //xprintf("rx(idx=%X)\n", index); // 最初のパケットを取得 unsigned int dest, msg, frame; const SPACKET_t *spacket = (const SPACKET_t*)m_Rx.Buf[index]; dest = spacket->Dest; msg = spacket->Msg; frame = spacket->Frame; //xprintf("rx(sp=%08X)\n", spacket); if (frame < size) { if (frame < RX_MAX_DIVISION) { //xprintf("rx(dest=%X)\n", dest); // キューの中に一連のパケットが納まっているか unsigned int cnt = 0; unsigned int total_length = 0; signed int start_index = index; while(cnt <= frame) { spacket = (const SPACKET_t*)m_Rx.Buf[index]; if (spacket->Dest != dest) break; if (spacket->Msg != msg) break; if (spacket->Frame != (frame - cnt)) break; total_length += spacket->Length; cnt++; index = IncAndWrap(index, RX_QUEUELEVEL); } if ((frame < cnt) && (total_length <= MAX_PAYLOADSIZE)) { index = start_index; // 実際にコピー packet.Dest = dest; packet.Msg = msg; packet.Length = total_length; frame++; size -= frame; char *data = packet.Data; do { spacket = (const SPACKET_t*)m_Rx.Buf[index]; memcpy(data, spacket->Data, spacket->Length); data += spacket->Length; index = IncAndWrap(index, RX_QUEUELEVEL); } while(0 < --frame); /*xprintf("rx(%d,%d,%d)[", spacket->Dest, spacket->Msg, spacket->Length); put_dump(packet.Data, 0, spacket->Length, DW_CHAR); xputs("]\n");*/ //xprintf("rx(%X,%X)(%d)[%08X]\n", dest, msg, total_length, Adler32(packet.Data, total_length)); //xprintf("%d rx(%X,%X)(%d)\n", xTaskGetTickCount(), dest, msg, total_length); result = true; } else { // データが異常なので廃棄 size--; xprintf("rx(err1)\n"); } } else { // データが異常なので廃棄 size--; xprintf("rx(err2)\n"); } m_Rx.Size = size; // データが受信できることを通知 USB::Data::RxReady(); } else { m_Rx.FrameLacking = true; //xprintf("rx(lack)\n"); } portEXIT_CRITICAL(); return result; }