EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) { EventBits_t uxOriginalBitValue, uxReturn; EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; BaseType_t xAlreadyYielded; BaseType_t xTimeoutOccurred = pdFALSE; configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( uxBitsToWaitFor != 0 ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) { configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); } #endif vTaskSuspendAll(); { uxOriginalBitValue = pxEventBits->uxEventBits; ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) { /* All the rendezvous bits are now set - no need to block. */ uxReturn = ( uxOriginalBitValue | uxBitsToSet ); /* Rendezvous always clear the bits. They will have been cleared already unless this is the only task in the rendezvous. */ pxEventBits->uxEventBits &= ~uxBitsToWaitFor; xTicksToWait = 0; } else { if( xTicksToWait != ( TickType_t ) 0 ) { traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); /* Store the bits that the calling task is waiting for in the task's event list item so the kernel knows when a match is found. Then enter the blocked state. */ vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); /* This assignment is obsolete as uxReturn will get set after the task unblocks, but some compilers mistakenly generate a warning about uxReturn being returned without being set if the assignment is omitted. */ uxReturn = 0; } else { /* The rendezvous bits were not set, but no block time was specified - just return the current event bit value. */ uxReturn = pxEventBits->uxEventBits; } } } xAlreadyYielded = xTaskResumeAll(); if( xTicksToWait != ( TickType_t ) 0 ) { if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } /* The task blocked to wait for its required bits to be set - at this point either the required bits were set or the block time expired. If the required bits were set they will have been stored in the task's event list item, and they should now be retrieved then cleared. */ uxReturn = uxTaskResetEventItemValue(); if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) { /* The task timed out, just return the current event bit value. */ taskENTER_CRITICAL(); { uxReturn = pxEventBits->uxEventBits; /* Although the task got here because it timed out before the bits it was waiting for were set, it is possible that since it unblocked another task has set the bits. If this is the case then it needs to clear the bits before exiting. */ if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) { pxEventBits->uxEventBits &= ~uxBitsToWaitFor; } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); xTimeoutOccurred = pdTRUE; } else { /* The task unblocked because the bits were set. */ } /* Control bits might be set as the task had blocked should not be returned. */ uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; } traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); return uxReturn; }
static void prvCheckReceivedValue( uint32_t ulReceived ) { static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE; /* Values are received in tasks and interrupts. It is likely that the receiving task will sometimes get preempted by the receiving interrupt between reading a value from the queue and calling this function. When that happens, if the receiving interrupt calls this function the values will get passed into this function slightly out of order. For that reason the value passed in is tested against a small range of expected values, rather than a single absolute value. To make the range testing easier values in the range limits are ignored. */ /* If the received value is equal to or greater than queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */ if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE ) { /* The value was sent from the ISR. */ if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY ) { /* The value received is at the lower limit of the expected range. Don't test it and expect to receive one higher next time. */ } else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY ) { /* The value received is at the higher limit of the expected range. Don't test it and expect to wrap soon. */ } else { /* Check the value against its expected value range. */ if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromISR ) != pdPASS ) { xQueueSetTasksStatus = pdFAIL; } } configASSERT( xQueueSetTasksStatus ); /* It is expected to receive an incrementing number. */ ulExpectedReceivedFromISR++; if( ulExpectedReceivedFromISR == 0 ) { ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE; } } else { /* The value was sent from the Tx task. */ if( ulReceived < queuesetIGNORED_BOUNDARY ) { /* The value received is at the lower limit of the expected range. Don't test it, and expect to receive one higher next time. */ } else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY ) { /* The value received is at the higher limit of the expected range. Don't test it and expect to wrap soon. */ } else { /* Check the value against its expected value range. */ if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromTask ) != pdPASS ) { xQueueSetTasksStatus = pdFAIL; } } configASSERT( xQueueSetTasksStatus ); /* It is expected to receive an incrementing number. */ ulExpectedReceivedFromTask++; if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE ) { ulExpectedReceivedFromTask = 0; } } }
static void prvCreateDemoFileUsing_f_putc( void ) { unsigned char ucReturn; int iByte, iReturned; F_FILE *pxFile; char cFileName[ fsMAX_FILE_NAME_LEN ]; /* Obtain and print out the working directory. */ f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); printf( "In directory %s\r\n", cRAMBuffer ); /* Create a sub directory. */ ucReturn = f_mkdir( pcDirectory1 ); configASSERT( ucReturn == F_NO_ERROR ); /* Move into the created sub-directory. */ ucReturn = f_chdir( pcDirectory1 ); configASSERT( ucReturn == F_NO_ERROR ); /* Obtain and print out the working directory. */ f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); printf( "In directory %s\r\n", cRAMBuffer ); /* Create a subdirectory in the new directory. */ ucReturn = f_mkdir( pcDirectory2 ); configASSERT( ucReturn == F_NO_ERROR ); /* Move into the directory just created - now two directories down from the root. */ ucReturn = f_chdir( pcDirectory2 ); configASSERT( ucReturn == F_NO_ERROR ); /* Obtain and print out the working directory. */ f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); printf( "In directory %s\r\n", cRAMBuffer ); configASSERT( strcmp( cRAMBuffer, pcFullPath ) == 0 ); /* Generate the file name. */ sprintf( cFileName, "%s.txt", pcDirectory2 ); /* Print out the file name and the directory into which the file is being written. */ printf( "Writing file %s in %s\r\n", cFileName, cRAMBuffer ); pxFile = f_open( cFileName, "w" ); /* Create a file 1 byte at a time. The file is filled with incrementing ascii characters starting from '0'. */ for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ ) { iReturned = f_putc( ( ( int ) '0' + iByte ), pxFile ); configASSERT( iReturned == ( ( int ) '0' + iByte ) ); } /* Finished so close the file. */ f_close( pxFile ); /* Move back to the root directory. */ ucReturn = f_chdir( "../.." ); configASSERT( ucReturn == F_NO_ERROR ); /* Obtain and print out the working directory. */ f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); printf( "Back in root directory %s\r\n", cRAMBuffer ); configASSERT( strcmp( cRAMBuffer, pcRoot ) == 0 ); }
void vPortEndScheduler( void ) { /* Not implemented in ports where there is nothing to return to. Artificially force an assert. */ configASSERT( pxCurrentTCB == NULL ); }
static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { static F_FIND *pxFindStruct = NULL; unsigned char ucReturned; BaseType_t xReturn = pdFALSE; /* This assumes pcWriteBuffer is long enough. */ ( void ) pcCommandString; /* Ensure the buffer leaves space for the \r\n. */ configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) ); xWriteBufferLen -= strlen( cliNEW_LINE ); if( pxFindStruct == NULL ) { /* This is the first time this function has been executed since the Dir command was run. Create the find structure. */ pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) ); if( pxFindStruct != NULL ) { ucReturned = f_findfirst( "*.*", pxFindStruct ); if( ucReturned == F_NO_ERROR ) { prvCreateFileInfoString( pcWriteBuffer, pxFindStruct ); xReturn = pdPASS; } else { snprintf( pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." ); } } else { snprintf( pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." ); } } else { /* The find struct has already been created. Find the next file in the directory. */ ucReturned = f_findnext( pxFindStruct ); if( ucReturned == F_NO_ERROR ) { prvCreateFileInfoString( pcWriteBuffer, pxFindStruct ); xReturn = pdPASS; } else { /* There are no more files. Free the find structure. */ vPortFree( pxFindStruct ); pxFindStruct = NULL; /* No string to return. */ pcWriteBuffer[ 0 ] = 0x00; } } strcat( pcWriteBuffer, cliNEW_LINE ); return xReturn; }
/** * \ingroup freertos_usart_peripheral_control_group * \brief Initiate a completely multi-byte read operation on a USART peripheral. * * The FreeRTOS ASF USART driver uses the PDC to transfer data from a peripheral * to a circular buffer. Reception happens in the background, while the * microcontroller is executing application code.* freertos_usart_read_packet() * copies bytes from the DMA buffer into the buffer passed as a * freertos_usart_read_packet() parameter. * * Readers are recommended to also reference the application note and examples * that accompany the FreeRTOS ASF drivers. * * The FreeRTOS ASF driver both installs and handles the USART PDC interrupts. * Users do not need to concern themselves with interrupt handling, and must * not install their own interrupt handler. * * \param p_usart The handle to the USART port returned by the * freertos_usart_serial_init() call used to initialise the port. * \param data A pointer to the buffer into which received data is to be * copied. * \param len The number of bytes to copy. * \param block_time_ticks Defines the maximum combined time the function * will wait to get exclusive access to the peripheral and receive the * requested number of bytes. Other tasks will execute during any waiting * time. * * The FreeRTOS ASF USART driver is initialized using a * call to freertos_usart_serial_init(). The * freertos_driver_parameters.options_flags parameter passed to the * initialization function defines the driver behavior. If * freertos_driver_parameters.options_flags had the USE_RX_ACCESS_MUTEX bit * set, then the driver will only read from the USART buffer if it has * first gained exclusive access to it. block_time_ticks specifies the * maximum amount of time the driver will wait to get exclusive access * before aborting the read operation. * * If the number of bytes available is less than the number requested then * freertos_usart_serial_read_packet() will wait for more bytes to become * available. block_time_ticks specifies the maximum amount of time the * driver will wait before returning fewer bytes than were requested. * * block_time_ticks is specified in RTOS tick periods. To specify a block * time in milliseconds, divide the milliseconds value by portTICK_RATE_MS, * and pass the result in block_time_ticks. portTICK_RATE_MS is defined by * FreeRTOS. * * \return The number of bytes that were copied into data. This will be * less than the requested number of bytes if a time out occurred. */ uint32_t freertos_usart_serial_read_packet(freertos_usart_if p_usart, uint8_t *data, uint32_t len, portTickType block_time_ticks) { portBASE_TYPE usart_index, attempt_read; Usart *usart_base; xTimeOutType time_out_definition; uint32_t bytes_read = 0; usart_base = (Usart *) p_usart; usart_index = get_pdc_peripheral_details(all_usart_definitions, MAX_USARTS, (void *) usart_base); /* It is possible to initialise the peripheral to only use Tx and not Rx. Check that Rx has been initialised. */ configASSERT(rx_buffer_definitions[usart_index].next_byte_to_read); configASSERT(rx_buffer_definitions[usart_index].next_byte_to_read != RX_NOT_USED); /* Only do anything if the USART is valid. */ if (usart_index < MAX_USARTS) { /* Must not request more bytes than will fit in the buffer. */ if (len <= (rx_buffer_definitions[usart_index].past_rx_buffer_end_address - rx_buffer_definitions[usart_index].rx_buffer_start_address)) { /* Remember the time on entry. */ vTaskSetTimeOutState(&time_out_definition); /* If an Rx mutex is in use, attempt to obtain it. */ if (rx_buffer_definitions[usart_index].rx_access_mutex != NULL) { /* Attempt to obtain the mutex. */ attempt_read = xSemaphoreTake( rx_buffer_definitions[usart_index].rx_access_mutex, block_time_ticks); if (attempt_read == pdTRUE) { /* The semaphore was obtained, adjust the block_time_ticks to take into account the time taken to obtain the semaphore. */ if (xTaskCheckForTimeOut(&time_out_definition, &block_time_ticks) == pdTRUE) { attempt_read = pdFALSE; /* The port is not going to be used, so return the mutex now. */ xSemaphoreGive(rx_buffer_definitions[usart_index].rx_access_mutex); } } } else { attempt_read = pdTRUE; } if (attempt_read == pdTRUE) { do { /* Wait until data is available. */ xSemaphoreTake(rx_buffer_definitions[usart_index].rx_event_semaphore, block_time_ticks); /* Copy as much data as is available, up to however much a maximum of the total number of requested bytes. */ bytes_read += freertos_copy_bytes_from_pdc_circular_buffer( &(rx_buffer_definitions[usart_index]), all_usart_definitions[usart_index].pdc_base_address->PERIPH_RPR, &(data[bytes_read]), (len - bytes_read)); /* The Rx DMA will have stopped if the Rx buffer had become full before this read operation. If bytes were removed by this read then there is guaranteed to be space in the Rx buffer and the Rx DMA can be restarted. */ if (bytes_read > 0) { taskENTER_CRITICAL(); { if(rx_buffer_definitions[usart_index].rx_pdc_parameters.ul_size == 0UL) { configure_rx_dma(usart_index, data_removed); } } taskEXIT_CRITICAL(); } /* Until all the requested bytes are received, or the function runs out of time. */ } while ((bytes_read < len) && (xTaskCheckForTimeOut( &time_out_definition, &block_time_ticks) == pdFALSE)); if (rx_buffer_definitions[usart_index].rx_access_mutex != NULL) { /* Return the mutex. */ xSemaphoreGive(rx_buffer_definitions[usart_index].rx_access_mutex); } } } } return bytes_read; }
/* * For internal use only. * A common USART interrupt handler that is called for all USART peripherals. */ static void local_usart_handler(const portBASE_TYPE usart_index) { portBASE_TYPE higher_priority_task_woken = pdFALSE; uint32_t usart_status; freertos_pdc_rx_control_t *rx_buffer_definition; usart_status = usart_get_status( all_usart_definitions[usart_index].peripheral_base_address); usart_status &= usart_get_interrupt_mask( all_usart_definitions[usart_index].peripheral_base_address); rx_buffer_definition = &(rx_buffer_definitions[usart_index]); /* Has the PDC completed a transmission? */ if ((usart_status & US_CSR_ENDTX) != 0UL) { usart_disable_interrupt( all_usart_definitions[usart_index].peripheral_base_address, US_IER_ENDTX); /* If the driver is supporting multi-threading, then return the access mutex. */ if (tx_dma_control[usart_index].peripheral_access_mutex != NULL) { xSemaphoreGiveFromISR( tx_dma_control[usart_index].peripheral_access_mutex, &higher_priority_task_woken); } /* if the sending task supplied a notification semaphore, then notify the task that the transmission has completed. */ if (tx_dma_control[usart_index].transaction_complete_notification_semaphore != NULL) { xSemaphoreGiveFromISR( tx_dma_control[usart_index].transaction_complete_notification_semaphore, &higher_priority_task_woken); } } if ((usart_status & US_CSR_ENDRX) != 0UL) { /* It is possible to initialise the peripheral to only use Tx and not Rx. Check that Rx has been initialised. */ configASSERT(rx_buffer_definition->next_byte_to_read); configASSERT(rx_buffer_definition->next_byte_to_read != RX_NOT_USED); /* Out of DMA buffer, configure the next buffer. Start by moving the DMA buffer start address up to the end of the previously defined buffer. */ rx_buffer_definition->rx_pdc_parameters.ul_addr += rx_buffer_definition->rx_pdc_parameters.ul_size; /* If the end of the buffer has been reached, wrap back to the start. */ if (rx_buffer_definition->rx_pdc_parameters.ul_addr >= rx_buffer_definition->past_rx_buffer_end_address) { rx_buffer_definition->rx_pdc_parameters.ul_addr = rx_buffer_definition->rx_buffer_start_address; } /* Reset the Rx DMA to receive data into whatever free space remains in the Rx buffer. */ configure_rx_dma(usart_index, data_added); if (rx_buffer_definition->rx_event_semaphore != NULL) { /* Notify that new data is available. */ xSemaphoreGiveFromISR( rx_buffer_definition->rx_event_semaphore, &higher_priority_task_woken); } } if ((usart_status & US_IER_TIMEOUT) != 0UL) { /* More characters have been placed into the Rx buffer. Restart the timeout after more data has been received. */ usart_start_rx_timeout(all_usart_definitions[usart_index].peripheral_base_address); if (rx_buffer_definition->rx_event_semaphore != NULL) { /* Notify that new data is available. */ xSemaphoreGiveFromISR( rx_buffer_definition->rx_event_semaphore, &higher_priority_task_woken); } } if ((usart_status & SR_ERROR_INTERRUPTS) != 0) { /* An error occurred in either a transmission or reception. Abort, and ensure the peripheral access mutex is made available to tasks. */ usart_reset_status( all_usart_definitions[usart_index].peripheral_base_address); if (tx_dma_control[usart_index].peripheral_access_mutex != NULL) { xSemaphoreGiveFromISR( tx_dma_control[usart_index].peripheral_access_mutex, &higher_priority_task_woken); } } /* If giving a semaphore caused a task to unblock, and the unblocked task has a priority equal to or higher than the currently running task (the task this ISR interrupted), then higher_priority_task_woken will have automatically been set to pdTRUE within the semaphore function. portEND_SWITCHING_ISR() will then ensure that this ISR returns directly to the higher priority unblocked task. */ portEND_SWITCHING_ISR(higher_priority_task_woken); }
static void prvTestAbortingQueueSend( void ) { TickType_t xTimeAtStart; BaseType_t xReturn; const UBaseType_t xQueueLength = ( UBaseType_t ) 1; QueueHandle_t xQueue; uint8_t ucItemToQueue; #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { static StaticQueue_t xQueueBuffer; static uint8_t ucQueueStorage[ sizeof( uint8_t ) ]; /* Create the queue. Statically allocated memory is used so the creation cannot fail. */ xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer ); } #else { xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) ); configASSERT( xQueue ); } #endif /* This function tests aborting when in the blocked state waiting to send, so the queue must be full. There is only one space in the queue. */ xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime ); if( xReturn != pdPASS ) { xErrorOccurred = pdTRUE; } /* Note the time before the delay so the length of the delay is known. */ xTimeAtStart = xTaskGetTickCount(); /* This first delay should just time out. */ xReturn = xQueueSend( xQueue, &ucItemToQueue, 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 = xQueueSend( xQueue, &ucItemToQueue, 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 = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime ); if( xReturn != pdFALSE ) { xErrorOccurred = pdTRUE; } prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime ); /* Not really necessary in this case, but for completeness. */ vQueueDelete( xQueue ); }
// A required FreeRTOS function. // ---------------------------------------------------------------------------- void vApplicationMallocFailedHook( void ) { configASSERT( 0 ); // Latch on any failure / error. }
void main_full( void ) { xTimerHandle xTimer = NULL; /* The register test tasks are asm functions that don't use a stack. The stack allocated just has to be large enough to hold the task context, and for the additional required for the stack overflow checking to work (if configured). */ const size_t xRegTestStackSize = 25U; /* Create the standard demo tasks */ vCreateBlockTimeTasks(); vStartDynamicPriorityTasks(); vStartCountingSemaphoreTasks(); vStartRecursiveMutexTasks(); vStartQueueOverwriteTask( tskIDLE_PRIORITY ); vStartQueueSetTasks(); vStartGenericQueueTasks( tskIDLE_PRIORITY ); vStartQueuePeekTasks(); /* Start the task that manages the command console for FreeRTOS+CLI. */ vUARTCommandConsoleStart( ( configMINIMAL_STACK_SIZE * 3 ), tskIDLE_PRIORITY ); /* Create the register test tasks as described at the top of this file. These are naked functions that don't use any stack. A stack still has to be allocated to hold the task context. */ xTaskCreate( vRegTest1Task, /* Function that implements the task. */ "Reg1", /* Text name of the task. */ xRegTestStackSize, /* Stack allocated to the task. */ NULL, /* The task parameter is not used. */ tskIDLE_PRIORITY, /* The priority to assign to the task. */ NULL ); /* Don't receive a handle back, it is not needed. */ xTaskCreate( vRegTest2Task, /* Function that implements the task. */ "Reg2", /* Text name of the task. */ xRegTestStackSize, /* Stack allocated to the task. */ NULL, /* The task parameter is not used. */ tskIDLE_PRIORITY, /* The priority to assign to the task. */ NULL ); /* Don't receive a handle back, it is not needed. */ /* Create the software timer that performs the 'check' functionality, as described at the top of this file. */ xTimer = xTimerCreate( "CheckTimer", /* A text name, purely to help debugging. */ ( mainCHECK_TIMER_PERIOD_MS ), /* The timer period, in this case 3000ms (3s). */ pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */ ( void * ) 0, /* The ID is not used, so can be set to anything. */ prvCheckTimerCallback /* The callback function that inspects the status of all the other tasks. */ ); /* If the software timer was created successfully, start it. It won't actually start running until the scheduler starts. A block time of zero is used in this call, although any value could be used as the block time will be ignored because the scheduler has not started yet. */ configASSERT( xTimer ); if( xTimer != NULL ) { xTimerStart( xTimer, mainDONT_BLOCK ); } /* Start the kernel. From here on, only tasks and interrupts will run. */ vTaskStartScheduler(); /* If all is well, the scheduler will now be running, and the following line will never be reached. If the following line does execute, then there was insufficient FreeRTOS heap memory available for the idle and/or timer tasks to be created. See the memory management section on the FreeRTOS web site, or the FreeRTOS tutorial books for more details. */ for( ;; ); }
int FF_FS_Add( const char *pcPath, FF_Disk_t *pxDisk ) { int ret = 0; configASSERT( pxDisk ); if (*pcPath != '/') { FF_PRINTF( "FF_FS_Add: Need a \"/\": '%s'\n", pcPath ); } else { int index = -1; int len = ( int ) strlen (pcPath); if( file_systems.fsCount == 0 ) { FF_FS_Init(); } if( len == 1 ) { /* This is the "/" path * and will be put at index 0 */ index = 0; } else { int i; FF_SubSystem_t *pxSubSystem = file_systems.systems + 1; /* Skip the root entry */ for( i = 1; i < file_systems.fsCount; i++, pxSubSystem++ ) { if( ( pxSubSystem->xPathlen == len ) && ( memcmp( pxSubSystem->pcPath, pcPath, ( size_t )len ) == 0 ) ) { index = i; /* A system is updated with a new handler. */ break; } } } if( index < 0 && file_systems.fsCount >= ARRAY_SIZE( file_systems.systems ) ) { FF_PRINTF( "FF_FS_Add: Table full '%s' (max = %d)\n", pcPath, (int)ARRAY_SIZE( file_systems.systems ) ); } else { vTaskSuspendAll(); { if( index < 0 ) { index = file_systems.fsCount++; } strncpy( file_systems.systems[ index ].pcPath, pcPath, sizeof file_systems.systems[ index ].pcPath ); file_systems.systems[ index ].xPathlen = len; file_systems.systems[ index ].pxManager = pxDisk->pxIOManager; } xTaskResumeAll( ); ret = 1; } } return ret; }
/** * In this function, the hardware should be initialized. * Called from ethernetif_init(). * * @param pxNetIf the already initialized lwip network interface structure * for this etherpxNetIf */ static void prvLowLevelInit( struct netif *pxNetIf ) { portBASE_TYPE xStatus; extern void vInitialisePHY( XEmacLite *xemaclitep ); unsigned portBASE_TYPE uxOriginalPriority; /* Hardware initialisation can take some time, so temporarily lower the task priority to ensure other functionality is not adversely effected. The priority will get raised again before this function exits. */ uxOriginalPriority = uxTaskPriorityGet( NULL ); vTaskPrioritySet( NULL, tskIDLE_PRIORITY ); /* set MAC hardware address length */ pxNetIf->hwaddr_len = ETHARP_HWADDR_LEN; /* set MAC hardware address */ pxNetIf->hwaddr[ 0 ] = configMAC_ADDR0; pxNetIf->hwaddr[ 1 ] = configMAC_ADDR1; pxNetIf->hwaddr[ 2 ] = configMAC_ADDR2; pxNetIf->hwaddr[ 3 ] = configMAC_ADDR3; pxNetIf->hwaddr[ 4 ] = configMAC_ADDR4; pxNetIf->hwaddr[ 5 ] = configMAC_ADDR5; /* device capabilities */ pxNetIf->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; /* maximum transfer unit */ pxNetIf->mtu = netifMAX_MTU; /* Broadcast capability */ pxNetIf->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; /* Initialize the mac */ xStatus = XEmacLite_Initialize( &xEMACInstance, XPAR_EMACLITE_0_DEVICE_ID ); if( xStatus == XST_SUCCESS ) { /* Set mac address */ XEmacLite_SetMacAddress( &xEMACInstance, ( Xuint8* )( pxNetIf->hwaddr ) ); /* Flush any frames already received */ XEmacLite_FlushReceive( &xEMACInstance ); /* Set Rx, Tx interrupt handlers */ XEmacLite_SetRecvHandler( &xEMACInstance, ( void * ) pxNetIf, prvRxHandler ); XEmacLite_SetSendHandler( &xEMACInstance, NULL, prvTxHandler ); /* Enable Rx, Tx interrupts */ XEmacLite_EnableInterrupts( &xEMACInstance ); /* Install the standard Xilinx library interrupt handler itself. *NOTE* The xPortInstallInterruptHandler() API function must be used for this purpose. */ xStatus = xPortInstallInterruptHandler( XPAR_INTC_0_EMACLITE_0_VEC_ID, ( XInterruptHandler ) XEmacLite_InterruptHandler, &xEMACInstance ); vInitialisePHY( &xEMACInstance ); /* Enable the interrupt in the interrupt controller. *NOTE* The vPortEnableInterrupt() API function must be used for this purpose. */ vPortEnableInterrupt( XPAR_INTC_0_EMACLITE_0_VEC_ID ); } /* Reset the task priority back to its original value. */ vTaskPrioritySet( NULL, uxOriginalPriority ); configASSERT( xStatus == pdPASS ); }
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) { ListItem_t *pxListItem, *pxNext; ListItem_t const *pxListEnd; List_t *pxList; EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; BaseType_t xMatchFound = pdFALSE; /* Check the user is not attempting to set the bits used by the kernel itself. */ configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); pxList = &( pxEventBits->xTasksWaitingForBits ); pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ vTaskSuspendAll(); { traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); pxListItem = listGET_HEAD_ENTRY( pxList ); /* Set the bits. */ pxEventBits->uxEventBits |= uxBitsToSet; /* See if the new bit value should unblock any tasks. */ while( pxListItem != pxListEnd ) { pxNext = listGET_NEXT( pxListItem ); uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); xMatchFound = pdFALSE; /* Split the bits waited for from the control bits. */ uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) { /* Just looking for single bit being set. */ if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) { xMatchFound = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) { /* All bits are set. */ xMatchFound = pdTRUE; } else { /* Need all bits to be set, but not all the bits were set. */ } if( xMatchFound != pdFALSE ) { /* The bits match. Should the bits be cleared on exit? */ if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) { uxBitsToClear |= uxBitsWaitedFor; } else { mtCOVERAGE_TEST_MARKER(); } /* Store the actual event flag value in the task's event list item before removing the task from the event list. The eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows that is was unblocked due to its required bits matching, rather than because it timed out. */ ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); } /* Move onto the next list item. Note pxListItem->pxNext is not used here as the list item may have been removed from the event list and inserted into the ready/pending reading list. */ pxListItem = pxNext; } /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT bit was set in the control word. */ pxEventBits->uxEventBits &= ~uxBitsToClear; } ( void ) xTaskResumeAll(); return pxEventBits->uxEventBits; }
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) { EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; EventBits_t uxReturn, uxControlBits = 0; BaseType_t xWaitConditionMet, xAlreadyYielded; BaseType_t xTimeoutOccurred = pdFALSE; /* Check the user is not attempting to wait on the bits used by the kernel itself, and that at least one bit is being requested. */ configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( uxBitsToWaitFor != 0 ); #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) { configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); } #endif vTaskSuspendAll(); { const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; /* Check to see if the wait condition is already met or not. */ xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); if( xWaitConditionMet != pdFALSE ) { /* The wait condition has already been met so there is no need to block. */ uxReturn = uxCurrentEventBits; xTicksToWait = ( TickType_t ) 0; /* Clear the wait bits if requested to do so. */ if( xClearOnExit != pdFALSE ) { pxEventBits->uxEventBits &= ~uxBitsToWaitFor; } else { mtCOVERAGE_TEST_MARKER(); } } else if( xTicksToWait == ( TickType_t ) 0 ) { /* The wait condition has not been met, but no block time was specified, so just return the current value. */ uxReturn = uxCurrentEventBits; } else { /* The task is going to block to wait for its required bits to be set. uxControlBits are used to remember the specified behaviour of this call to xEventGroupWaitBits() - for use when the event bits unblock the task. */ if( xClearOnExit != pdFALSE ) { uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; } else { mtCOVERAGE_TEST_MARKER(); } if( xWaitForAllBits != pdFALSE ) { uxControlBits |= eventWAIT_FOR_ALL_BITS; } else { mtCOVERAGE_TEST_MARKER(); } /* Store the bits that the calling task is waiting for in the task's event list item so the kernel knows when a match is found. Then enter the blocked state. */ vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); /* This is obsolete as it will get set after the task unblocks, but some compilers mistakenly generate a warning about the variable being returned without being set if it is not done. */ uxReturn = 0; traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); } } xAlreadyYielded = xTaskResumeAll(); if( xTicksToWait != ( TickType_t ) 0 ) { if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } /* The task blocked to wait for its required bits to be set - at this point either the required bits were set or the block time expired. If the required bits were set they will have been stored in the task's event list item, and they should now be retrieved then cleared. */ uxReturn = uxTaskResetEventItemValue(); if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) { taskENTER_CRITICAL(); { /* The task timed out, just return the current event bit value. */ uxReturn = pxEventBits->uxEventBits; /* It is possible that the event bits were updated between this task leaving the Blocked state and running again. */ if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) { if( xClearOnExit != pdFALSE ) { pxEventBits->uxEventBits &= ~uxBitsToWaitFor; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); /* Prevent compiler warnings when trace macros are not used. */ xTimeoutOccurred = pdFALSE; } else { /* The task unblocked because the bits were set. */ } /* The task blocked so control bits may have been set. */ uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; } traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); return uxReturn; }
static portBASE_TYPE prvParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { const char *pcParameter; portBASE_TYPE xParameterStringLength, xReturn; static portBASE_TYPE lParameterNumber = 0; /* Remove compile time warnings about unused parameters, and check the write buffer is not NULL. NOTE - for simplicity, this example assumes the write buffer length is adequate, so does not check for buffer overflows. */ ( void ) pcCommandString; ( void ) xWriteBufferLen; configASSERT( pcWriteBuffer ); if( lParameterNumber == 0 ) { /* The first time the function is called after the command has been entered just a header string is returned. */ sprintf( pcWriteBuffer, "The parameters were:\r\n" ); /* Next time the function is called the first parameter will be echoed back. */ lParameterNumber = 1L; /* There is more data to be returned as no parameters have been echoed back yet. */ xReturn = pdPASS; } else { /* Obtain the parameter string. */ pcParameter = FreeRTOS_CLIGetParameter ( pcCommandString, /* The command string itself. */ lParameterNumber, /* Return the next parameter. */ &xParameterStringLength /* Store the parameter string length. */ ); if( pcParameter != NULL ) { /* Return the parameter string. */ memset( pcWriteBuffer, 0x00, xWriteBufferLen ); sprintf( pcWriteBuffer, "%d: ", ( int ) lParameterNumber ); strncat( pcWriteBuffer, pcParameter, xParameterStringLength ); strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) ); /* There might be more parameters to return after this one. */ xReturn = pdTRUE; lParameterNumber++; } else { /* No more parameters were found. Make sure the write buffer does not contain a valid string. */ pcWriteBuffer[ 0 ] = 0x00; /* No more data to return. */ xReturn = pdFALSE; /* Start over the next time this command is executed. */ lParameterNumber = 0; } } return xReturn; }
/* * See header file for description. */ portBASE_TYPE xPortStartScheduler( void ) { /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); #if( configASSERT_DEFINED == 1 ) { volatile unsigned long ulOriginalPriority; volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile unsigned char ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API functions can be called. ISR safe functions are those that end in "FromISR". FreeRTOS maintains separate thread and ISR API functions to ensure interrupt entry is as fast and simple as possible. Save the interrupt priority value that is about to be clobbered. */ ulOriginalPriority = *pcFirstUserPriorityRegister; /* Determine the number of priority bits available. First write to all possible bits. */ *pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE; /* Read the value back to see how many bits stuck. */ ucMaxPriorityValue = *pcFirstUserPriorityRegister; /* configMAX_SYSCALL_INTERRUPT_PRIORITY should be set to a value within the range of valid priorities */ configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & (~ucMaxPriorityValue) ) == 0 ); /* Use the same mask on the maximum system call priority. */ ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; /* Calculate the maximum acceptable priority group value for the number of bits read back. */ ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { ulMaxPRIGROUPValue--; ucMaxPriorityValue <<= ( unsigned char ) 0x01; } /* Shift the priority group value back to its position within the AIRCR register. */ ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; /* Restore the clobbered interrupt priority register to its original value. */ *pcFirstUserPriorityRegister = ulOriginalPriority; } #endif /* conifgASSERT_DEFINED */ /* WICED: Moved interrupt priority setup to platform_init_rtos_irq_priorities(). * Enforce consistency by setting interrupt priority using NVIC_SetPriority() function * from CMSIS. This approach ensures that different __NVIC_PRIO_BITS values from different * MCU vendors are taken care of properly */ /* Make PendSV and SysTick the lowest priority interrupts. */ /* portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; */ /* portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; */ /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; /* Start the first task. */ prvPortStartFirstTask(); /* Should not get here! */ return 0; }
/** * \ingroup freertos_usart_peripheral_control_group * \brief Initializes the FreeRTOS ASF USART driver for the specified USART * port. * * freertos_usart_serial_init() is an ASF specific FreeRTOS driver function. It * must be called before any other ASF specific FreeRTOS driver functions * attempt to access the same USART port. * * If freertos_driver_parameters->operation_mode equals USART_RS232 then * freertos_usart_serial_init() will configure the USART port for standard RS232 * operation. If freertos_driver_parameters->operation_mode equals any other * value then freertos_usart_serial_init() will not take any action. * * Other ASF USART functions can be called after freertos_usart_serial_init() * has completed successfully. * * The FreeRTOS ASF driver both installs and handles the USART PDC interrupts. * Users do not need to concern themselves with interrupt handling, and must * not install their own interrupt handler. * * This driver is provided with an application note, and an example project that * demonstrates the use of this function. * * \param p_usart The USART peripheral being initialized. * \param uart_parameters Structure that defines the USART bus and transfer * parameters, such the baud rate and the number of data bits. * sam_usart_opt_t is a standard ASF type (it is not FreeRTOS specific). * \param freertos_driver_parameters Defines the driver behavior. See the * freertos_peripheral_options_t documentation, and the application note that * accompanies the ASF specific FreeRTOS functions. * * \return If the initialization completes successfully then a handle that can * be used with FreeRTOS USART read and write functions is returned. If * the initialisation fails then NULL is returned. */ freertos_usart_if freertos_usart_serial_init(Usart *p_usart, const sam_usart_opt_t *const uart_parameters, const freertos_peripheral_options_t *const freertos_driver_parameters) { portBASE_TYPE usart_index; bool is_valid_operating_mode; freertos_usart_if return_value; const enum peripheral_operation_mode valid_operating_modes[] = {USART_RS232}; /* Find the index into the all_usart_definitions array that holds details of the p_usart peripheral. */ usart_index = get_pdc_peripheral_details(all_usart_definitions, MAX_USARTS, (void *) p_usart); /* Check the requested operating mode is valid for the peripheral. */ is_valid_operating_mode = check_requested_operating_mode( freertos_driver_parameters->operation_mode, valid_operating_modes, sizeof(valid_operating_modes) / sizeof(enum peripheral_operation_mode)); /* Don't do anything unless a valid p_usart pointer was used, and a valid operating mode was requested. */ if ((usart_index < MAX_USARTS) && (is_valid_operating_mode == true)) { /* This function must be called exactly once per supported USART. Check it has not been called before. */ configASSERT(rx_buffer_definitions[usart_index].next_byte_to_read == NULL); /* Disable everything before enabling the clock. */ usart_disable_tx(p_usart); usart_disable_rx(p_usart); pdc_disable_transfer(all_usart_definitions[usart_index].pdc_base_address, (PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS)); #if (SAMG55) /* Enable the peripheral and set USART mode. */ uint32_t temp = (uint32_t)all_usart_definitions[usart_index].peripheral_base_address - 0x200; Flexcom *p_flexcom = (Flexcom *)temp; flexcom_enable(p_flexcom); flexcom_set_opmode(p_flexcom, FLEXCOM_USART); #else /* Enable the peripheral clock in the PMC. */ pmc_enable_periph_clk( all_usart_definitions[usart_index].peripheral_id); #endif switch (freertos_driver_parameters->operation_mode) { case USART_RS232: /* Call the standard ASF init function. */ usart_init_rs232(p_usart, uart_parameters, sysclk_get_cpu_hz()); break; default: /* Other modes are not currently supported. */ break; } /* Disable all the interrupts. */ usart_disable_interrupt(p_usart, MASK_ALL_INTERRUPTS); /* Create any required peripheral access mutexes and transaction complete semaphores. This peripheral is full duplex so only the Tx semaphores are created in the following function. The the Rx semaphores are created separately. */ create_peripheral_control_semaphores( freertos_driver_parameters->options_flags, &(tx_dma_control[usart_index]), NULL /* The rx structures are not created in this function. */); /* Is the driver also going to receive? */ if (freertos_driver_parameters->receive_buffer != NULL) { /* rx_event_semaphore is used to signal the arival of new data. It must be a counting semaphore for the following reason: If the Rx DMA places data at the end of its circular buffer it will give the semaphore to indicate the presence of unread data. If it then receives more data, it will write this to the start of the circular buffer, then give the semaphore again. Now, if a task reads data out of the same circular buffer, and requests less data than is available, but more than is available between the next read pointer and the end of the buffer, the actual amount returned will be capped to that available up to the end of the buffer only. If this semaphore was a binary semaphore, it would then be 'taken' even though, unknown to the reading task, unread and therefore available data remained at the beginning of the buffer. */ rx_buffer_definitions[usart_index].rx_event_semaphore = xSemaphoreCreateCounting(portMAX_DELAY, 0); configASSERT(rx_buffer_definitions[usart_index].rx_event_semaphore); /* Set the timeout to 5ms, then start waiting for a character (the timeout is not started until characters have started to be received). */ usart_set_rx_timeout(p_usart, (uart_parameters->baudrate / BITS_PER_5_MS)); usart_start_rx_timeout(p_usart); /* The receive buffer is currently empty, so the DMA has control over the entire buffer. */ rx_buffer_definitions[usart_index].rx_pdc_parameters.ul_addr = (uint32_t)freertos_driver_parameters->receive_buffer; rx_buffer_definitions[usart_index].rx_pdc_parameters.ul_size = freertos_driver_parameters->receive_buffer_size; pdc_rx_init( all_usart_definitions[usart_index].pdc_base_address, &(rx_buffer_definitions[usart_index].rx_pdc_parameters), NULL); /* Set the next byte to read to the start of the buffer as no data has yet been read. */ rx_buffer_definitions[usart_index].next_byte_to_read = freertos_driver_parameters->receive_buffer; /* Remember the limits of entire buffer. */ rx_buffer_definitions[usart_index].rx_buffer_start_address = rx_buffer_definitions[usart_index].rx_pdc_parameters.ul_addr; rx_buffer_definitions[usart_index].past_rx_buffer_end_address = rx_buffer_definitions[usart_index].rx_buffer_start_address + freertos_driver_parameters->receive_buffer_size; /* If the rx driver is to be thread aware, create an access control mutex. */ if ((freertos_driver_parameters->options_flags & USE_RX_ACCESS_MUTEX) != 0) { rx_buffer_definitions[usart_index].rx_access_mutex = xSemaphoreCreateMutex(); configASSERT(rx_buffer_definitions[usart_index].rx_access_mutex); } /* Catch the DMA running out of Rx space, and gaps in the reception. These events are both used to signal that there is data available in the Rx buffer. */ usart_enable_interrupt(p_usart, US_IER_ENDRX | US_IER_TIMEOUT); /* The Rx DMA is running all the time, so enable it now. */ pdc_enable_transfer( all_usart_definitions[usart_index].pdc_base_address, PERIPH_PTCR_RXTEN); } else { /* next_byte_to_read is used to check to see if this function has been called before, so it must be set to something, even if it is not going to be used. The value it is set to is not important, provided it is not zero (NULL). */ rx_buffer_definitions[usart_index].next_byte_to_read = RX_NOT_USED; } /* Configure and enable the USART interrupt in the interrupt controller. */ configure_interrupt_controller(all_usart_definitions[usart_index].peripheral_irq, freertos_driver_parameters->interrupt_priority); /* Error interrupts are always enabled. */ usart_enable_interrupt( all_usart_definitions[usart_index].peripheral_base_address, IER_ERROR_INTERRUPTS); /* Finally, enable the receiver and transmitter. */ usart_enable_tx(p_usart); usart_enable_rx(p_usart); return_value = (freertos_usart_if) p_usart; } else { return_value = NULL; } return return_value; }
/* * See header file for description. */ BaseType_t xPortStartScheduler( void ) { /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); #if( configASSERT_DEFINED == 1 ) { volatile uint32_t ulOriginalPriority; volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API functions can be called. ISR safe functions are those that end in "FromISR". FreeRTOS maintains separate thread and ISR API functions to ensure interrupt entry is as fast and simple as possible. Save the interrupt priority value that is about to be clobbered. */ ulOriginalPriority = *pucFirstUserPriorityRegister; /* Determine the number of priority bits available. First write to all possible bits. */ *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; /* Read the value back to see how many bits stuck. */ ucMaxPriorityValue = *pucFirstUserPriorityRegister; /* Use the same mask on the maximum system call priority. */ ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; /* Calculate the maximum acceptable priority group value for the number of bits read back. */ ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { ulMaxPRIGROUPValue--; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } /* Shift the priority group value back to its position within the AIRCR register. */ ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; /* Restore the clobbered interrupt priority register to its original value. */ *pucFirstUserPriorityRegister = ulOriginalPriority; } #endif /* conifgASSERT_DEFINED */ /* Make PendSV and SysTick the lowest priority interrupts. */ portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; /* Start the first task. */ prvPortStartFirstTask(); /* Should never get here as the tasks will now be executing! Call the task exit error function to prevent compiler warnings about a static function not being called in the case that the application writer overrides this functionality by defining configTASK_RETURN_ADDRESS. */ prvTaskExitError(); /* Should not get here! */ return 0; }
/* * For internal use only. * Configures the Rx DMA to receive data into free space within the Rx buffer. */ static void configure_rx_dma(uint32_t usart_index, enum buffer_operations operation_performed) { freertos_pdc_rx_control_t *rx_buffer_definition; rx_buffer_definition = &(rx_buffer_definitions[usart_index]); /* How much space is there between the start of the DMA buffer and the current read pointer? */ if (((uint32_t)rx_buffer_definition->next_byte_to_read) == rx_buffer_definition->rx_pdc_parameters.ul_addr) { /* The read pointer and the write pointer are equal. If this function was called because data was added to the buffer, then there is no free space in the buffer remaining. If this function was called because data was removed from the buffer, then the space remaining is from the write pointer up to the end of the buffer. */ if (operation_performed == data_added) { rx_buffer_definition->rx_pdc_parameters.ul_size = 0UL; } else { rx_buffer_definition->rx_pdc_parameters.ul_size = rx_buffer_definition->past_rx_buffer_end_address - rx_buffer_definition->rx_pdc_parameters.ul_addr; } } else if (((uint32_t)rx_buffer_definition->next_byte_to_read) > rx_buffer_definition->rx_pdc_parameters.ul_addr) { /* The read pointer is ahead of the write pointer. The space available is up to the write pointer to ensure unread data is not overwritten. */ rx_buffer_definition->rx_pdc_parameters.ul_size = ((uint32_t) rx_buffer_definition->next_byte_to_read) - rx_buffer_definition->rx_pdc_parameters.ul_addr; } else { /* The write pointer is ahead of the read pointer so the space available is up to the end of the buffer. */ rx_buffer_definition->rx_pdc_parameters.ul_size = rx_buffer_definition->past_rx_buffer_end_address - rx_buffer_definition->rx_pdc_parameters.ul_addr; } configASSERT((rx_buffer_definition->rx_pdc_parameters.ul_addr + rx_buffer_definition->rx_pdc_parameters.ul_size) <= rx_buffer_definition->past_rx_buffer_end_address); if (rx_buffer_definition->rx_pdc_parameters.ul_size > 0) { /* Restart the DMA to receive into whichever space was calculated as remaining. First clear any characters that might already be in the registers. */ pdc_rx_init( all_usart_definitions[usart_index].pdc_base_address, &rx_buffer_definition->rx_pdc_parameters, NULL); pdc_enable_transfer( all_usart_definitions[usart_index].pdc_base_address, PERIPH_PTCR_RXTEN); usart_enable_interrupt( all_usart_definitions[usart_index].peripheral_base_address, US_IER_ENDRX | US_IER_TIMEOUT); } else { /* The write pointer has reached the read pointer. There is no more room so the DMA is not re-enabled until a read has created space. */ usart_disable_interrupt( all_usart_definitions[usart_index].peripheral_base_address, US_IER_ENDRX | US_IER_TIMEOUT); } }
static BaseType_t prvPingCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { char * pcParameter; BaseType_t lParameterStringLength, xReturn; uint32_t ulIPAddress, ulBytesToPing; const uint32_t ulDefaultBytesToPing = 8UL; char cBuffer[ 16 ]; /* Remove compile time warnings about unused parameters, and check the write buffer is not NULL. NOTE - for simplicity, this example assumes the write buffer length is adequate, so does not check for buffer overflows. */ ( void ) pcCommandString; ( void ) xWriteBufferLen; configASSERT( pcWriteBuffer ); /* Start with an empty string. */ pcWriteBuffer[ 0 ] = 0x00; /* Obtain the number of bytes to ping. */ pcParameter = ( char * ) FreeRTOS_CLIGetParameter ( pcCommandString, /* The command string itself. */ 2, /* Return the second parameter. */ &lParameterStringLength /* Store the parameter string length. */ ); if( pcParameter == NULL ) { /* The number of bytes was not specified, so default it. */ ulBytesToPing = ulDefaultBytesToPing; } else { ulBytesToPing = atol( pcParameter ); } /* Obtain the IP address string. */ pcParameter = ( char * ) FreeRTOS_CLIGetParameter ( pcCommandString, /* The command string itself. */ 1, /* Return the first parameter. */ &lParameterStringLength /* Store the parameter string length. */ ); /* Sanity check something was returned. */ configASSERT( pcParameter ); /* Attempt to obtain the IP address. If the first character is not a digit, assume the host name has been passed in. */ if( ( *pcParameter >= '0' ) && ( *pcParameter <= '9' ) ) { ulIPAddress = FreeRTOS_inet_addr( pcParameter ); } else { /* Terminate the host name. */ pcParameter[ lParameterStringLength ] = 0x00; /* Attempt to resolve host. */ ulIPAddress = FreeRTOS_gethostbyname( pcParameter ); } /* Convert IP address, which may have come from a DNS lookup, to string. */ FreeRTOS_inet_ntoa( ulIPAddress, cBuffer ); if( ulIPAddress != 0 ) { xReturn = FreeRTOS_SendPingRequest( ulIPAddress, ( uint16_t ) ulBytesToPing, portMAX_DELAY ); } else { xReturn = pdFALSE; } if( xReturn == pdFALSE ) { sprintf( pcWriteBuffer, "%s", "Could not send ping request\r\n" ); } else { sprintf( pcWriteBuffer, "Ping sent to %s with identifier %d\r\n", cBuffer, xReturn ); } return pdFALSE; }
void *pvPortMalloc( size_t xWantedSize ) { BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; void *pvReturn = NULL; vTaskSuspendAll(); { /* If this is the first call to malloc then the heap will require initialisation to setup the list of free blocks. */ if( pxEnd == NULL ) { prvHeapInit(); } else { mtCOVERAGE_TEST_MARKER(); } /* Check the requested block size is not so large that the top bit is set. The top bit of the block size member of the BlockLink_t structure is used to determine who owns the block - the application or the kernel, so it must be free. */ if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) { /* The wanted size is increased so it can contain a BlockLink_t structure in addition to the requested amount of bytes. */ if( xWantedSize > 0 ) { xWantedSize += xHeapStructSize; /* Ensure that blocks are always aligned to the required number of bytes. */ if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until one of adequate size is found. */ pxPreviousBlock = &xStart; pxBlock = xStart.pxNextFreeBlock; while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) { pxPreviousBlock = pxBlock; pxBlock = pxBlock->pxNextFreeBlock; } /* If the end marker was reached then a block of adequate size was not found. */ if( pxBlock != pxEnd ) { /* Return the memory space pointed to - jumping over the BlockLink_t structure at its start. */ pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize ); /* This block is being returned for use so must be taken out of the list of free blocks. */ pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; /* If the block is larger than required it can be split into two. */ if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) { /* This block is to be split into two. Create a new block following the number of bytes requested. The void cast is used to prevent byte alignment warnings from the compiler. */ pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); /* Calculate the sizes of two blocks split from the single block. */ pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; pxBlock->xBlockSize = xWantedSize; /* Insert the new block into the list of free blocks. */ prvInsertBlockIntoFreeList( pxNewBlockLink ); } else { mtCOVERAGE_TEST_MARKER(); } xFreeBytesRemaining -= pxBlock->xBlockSize; if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) { xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; } else { mtCOVERAGE_TEST_MARKER(); } /* The block is being returned - it is allocated and owned by the application and has no "next" block. */ pxBlock->xBlockSize |= xBlockAllocatedBit; pxBlock->pxNextFreeBlock = NULL; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } traceMALLOC( pvReturn, xWantedSize ); } ( void ) xTaskResumeAll(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { extern void vApplicationMallocFailedHook( void ); vApplicationMallocFailedHook(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 ); return pvReturn; }
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) { BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock; uint8_t *pucAlignedHeap; size_t xTotalRegionSize, xTotalHeapSize = 0; BaseType_t xDefinedRegions = 0; size_t xAddress; const HeapRegion_t *pxHeapRegion; /* Can only call once! */ configASSERT( pxEnd == NULL ); pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); while( pxHeapRegion->xSizeInBytes > 0 ) { xTotalRegionSize = pxHeapRegion->xSizeInBytes; /* Ensure the heap region starts on a correctly aligned boundary. */ xAddress = ( size_t ) pxHeapRegion->pucStartAddress; if( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) { xAddress += ( portBYTE_ALIGNMENT - 1 ); xAddress &= ~portBYTE_ALIGNMENT_MASK; /* Adjust the size for the bytes lost to alignment. */ xTotalRegionSize -= xAddress - ( size_t ) pxHeapRegion->pucStartAddress; } pucAlignedHeap = ( uint8_t * ) xAddress; /* Set xStart if it has not already been set. */ if( xDefinedRegions == 0 ) { /* xStart is used to hold a pointer to the first item in the list of free blocks. The void cast is used to prevent compiler warnings. */ xStart.pxNextFreeBlock = ( BlockLink_t * ) pucAlignedHeap; xStart.xBlockSize = ( size_t ) 0; } else { /* Should only get here if one region has already been added to the heap. */ configASSERT( pxEnd != NULL ); /* Check blocks are passed in with increasing start addresses. */ configASSERT( xAddress > ( size_t ) pxEnd ); } /* Remember the location of the end marker in the previous region, if any. */ pxPreviousFreeBlock = pxEnd; /* pxEnd is used to mark the end of the list of free blocks and is inserted at the end of the region space. */ xAddress = ( ( size_t ) pucAlignedHeap ) + xTotalRegionSize; xAddress -= xHeapStructSize; xAddress &= ~portBYTE_ALIGNMENT_MASK; pxEnd = ( BlockLink_t * ) xAddress; pxEnd->xBlockSize = 0; pxEnd->pxNextFreeBlock = NULL; /* To start with there is a single free block in this region that is sized to take up the entire heap region minus the space taken by the free block structure. */ pxFirstFreeBlockInRegion = ( BlockLink_t * ) pucAlignedHeap; pxFirstFreeBlockInRegion->xBlockSize = xAddress - ( size_t ) pxFirstFreeBlockInRegion; pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd; /* If this is not the first region that makes up the entire heap space then link the previous region to this region. */ if( pxPreviousFreeBlock != NULL ) { pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion; } xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; /* Move onto the next HeapRegion_t structure. */ xDefinedRegions++; pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); } xMinimumEverFreeBytesRemaining = xTotalHeapSize; xFreeBytesRemaining = xTotalHeapSize; /* Check something was actually defined before it is accessed. */ configASSERT( xTotalHeapSize ); /* Work out the position of the top bit in a size_t variable. */ xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); }
static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { const char *pcParameter; BaseType_t xParameterStringLength, xReturn = pdTRUE; static F_FILE *pxFile = NULL; int iChar; size_t xByte; size_t xColumns = 50U; /* Ensure there is always a null terminator after each character written. */ memset( pcWriteBuffer, 0x00, xWriteBufferLen ); /* Ensure the buffer leaves space for the \r\n. */ configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) ); xWriteBufferLen -= strlen( cliNEW_LINE ); if( xWriteBufferLen < xColumns ) { /* Ensure the loop that uses xColumns as an end condition does not write off the end of the buffer. */ xColumns = xWriteBufferLen; } if( pxFile == NULL ) { /* The file has not been opened yet. Find the file name. */ pcParameter = FreeRTOS_CLIGetParameter ( pcCommandString, /* The command string itself. */ 1, /* Return the first parameter. */ &xParameterStringLength /* Store the parameter string length. */ ); /* Sanity check something was returned. */ configASSERT( pcParameter ); /* Attempt to open the requested file. */ pxFile = f_open( pcParameter, "r" ); } if( pxFile != NULL ) { /* Read the next chunk of data from the file. */ for( xByte = 0; xByte < xColumns; xByte++ ) { iChar = f_getc( pxFile ); if( iChar == -1 ) { /* No more characters to return. */ f_close( pxFile ); pxFile = NULL; break; } else { pcWriteBuffer[ xByte ] = ( char ) iChar; } } } if( pxFile == NULL ) { /* Either the file was not opened, or all the data from the file has been returned and the file is now closed. */ xReturn = pdFALSE; } strcat( pcWriteBuffer, cliNEW_LINE ); return xReturn; }
static void prvSimpleZeroCopyUDPClientTask( void *pvParameters ) { xSocket_t xClientSocket; uint8_t *pucUDPPayloadBuffer; struct freertos_sockaddr xDestinationAddress; BaseType_t lReturned; uint32_t ulCount = 0UL, ulIPAddress; const uint32_t ulLoopsPerSocket = 10UL; const char *pcStringToSend = "Server received (using zero copy): Message number "; const TickType_t x150ms = 150UL / portTICK_RATE_MS; /* 15 is added to ensure the number, \r\n and terminating zero fit. */ const size_t xStringLength = strlen( pcStringToSend ) + 15; /* Remove compiler warning about unused parameters. */ ( void ) pvParameters; /* It is assumed that this task is not created until the network is up, so the IP address can be obtained immediately. store the IP address being used in ulIPAddress. This is done so the socket can send to a different port on the same IP address. */ FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); /* This test sends to itself, so data sent from here is received by a server socket on the same IP address. Setup the freertos_sockaddr structure with this nodes IP address, and the port number being sent to. The strange casting is to try and remove compiler warnings on 32 bit machines. */ xDestinationAddress.sin_addr = ulIPAddress; xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL; xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port ); for( ;; ) { /* Create the socket. */ xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET ); /* The count is used to differentiate between different messages sent to the server, and to break out of the do while loop below. */ ulCount = 0UL; do { /* This task is going to send using the zero copy interface. The data being sent is therefore written directly into a buffer that is passed into, rather than copied into, the FreeRTOS_sendto() function. First obtain a buffer of adequate length from the IP stack into which the string will be written. Although a max delay is used, the actual delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence the do while loop is used to ensure a buffer is obtained. */ do { } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xStringLength, portMAX_DELAY ) ) == NULL ); /* A buffer was successfully obtained. Create the string that is sent to the server. First the string is filled with zeros as this will effectively be the null terminator when the string is received at the other end. Note that the string is being written directly into the buffer obtained from the IP stack above. */ memset( ( void * ) pucUDPPayloadBuffer, 0x00, xStringLength ); sprintf( ( char * ) pucUDPPayloadBuffer, "%s%lu\r\n", pcStringToSend, ulCount ); /* Pass the buffer into the send function. ulFlags has the FREERTOS_ZERO_COPY bit set so the IP stack will take control of the buffer rather than copy data out of the buffer. */ lReturned = FreeRTOS_sendto( xClientSocket, /* The socket being sent to. */ ( void * ) pucUDPPayloadBuffer, /* A pointer to the the data being sent. */ strlen( ( const char * ) pucUDPPayloadBuffer ) + 1, /* The length of the data being sent - including the string's null terminator. */ FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */ &xDestinationAddress, /* Where the data is being sent. */ sizeof( xDestinationAddress ) ); if( lReturned == 0 ) { /* The send operation failed, so this task is still responsible for the buffer obtained from the IP stack. To ensure the buffer is not lost it must either be used again, or, as in this case, returned to the IP stack using FreeRTOS_ReleaseUDPPayloadBuffer(). pucUDPPayloadBuffer can be safely re-used after this call. */ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); } else { /* The send was successful so the IP stack is now managing the buffer pointed to by pucUDPPayloadBuffer, and the IP stack will return the buffer once it has been sent. pucUDPPayloadBuffer can be safely re-used. */ } ulCount++; } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) ); FreeRTOS_closesocket( xClientSocket ); /* A short delay to prevent the messages scrolling off the screen too quickly. */ vTaskDelay( x150ms ); } }
static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { char *pcSourceFile; const char *pcDestinationFile; BaseType_t xParameterStringLength; long lSourceLength, lDestinationLength = 0; /* Obtain the name of the destination file. */ pcDestinationFile = FreeRTOS_CLIGetParameter ( pcCommandString, /* The command string itself. */ 2, /* Return the second parameter. */ &xParameterStringLength /* Store the parameter string length. */ ); /* Sanity check something was returned. */ configASSERT( pcDestinationFile ); /* Obtain the name of the source file. */ pcSourceFile = ( char * ) FreeRTOS_CLIGetParameter ( pcCommandString, /* The command string itself. */ 1, /* Return the first parameter. */ &xParameterStringLength /* Store the parameter string length. */ ); /* Sanity check something was returned. */ configASSERT( pcSourceFile ); /* Terminate the string. */ pcSourceFile[ xParameterStringLength ] = 0x00; /* See if the source file exists, obtain its length if it does. */ lSourceLength = f_filelength( pcSourceFile ); if( lSourceLength == 0 ) { sprintf( pcWriteBuffer, "Source file does not exist" ); } else { /* See if the destination file exists. */ lDestinationLength = f_filelength( pcDestinationFile ); if( lDestinationLength != 0 ) { sprintf( pcWriteBuffer, "Error: Destination file already exists" ); } } /* Continue only if the source file exists and the destination file does not exist. */ if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) ) { if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS ) { sprintf( pcWriteBuffer, "Copy made" ); } else { sprintf( pcWriteBuffer, "Error during copy" ); } } strcat( pcWriteBuffer, cliNEW_LINE ); return pdFALSE; }
void FreeRTOS_SetupTickInterrupt( void ) { BaseType_t xStatus; XTtcPs_Config *pxTimerConfiguration; XInterval usInterval; uint8_t ucPrescale; const uint8_t ucLevelSensitive = 1; XScuGic_Config *pxInterruptControllerConfig; /* Initialize the interrupt controller driver. */ pxInterruptControllerConfig = XScuGic_LookupConfig( configINTERRUPT_CONTROLLER_DEVICE_ID ); XScuGic_CfgInitialize( &xInterruptController, pxInterruptControllerConfig, pxInterruptControllerConfig->CpuBaseAddress ); /* Connect the interrupt controller interrupt handler to the hardware interrupt handling logic in the ARM processor. */ Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_IRQ_INT, ( Xil_ExceptionHandler ) XScuGic_InterruptHandler, &xInterruptController); /* Enable interrupts in the ARM. */ Xil_ExceptionEnable(); pxTimerConfiguration = XTtcPs_LookupConfig( configTIMER_ID ); /* Initialise the device. */ xStatus = XTtcPs_CfgInitialize( &xTimerInstance, pxTimerConfiguration, pxTimerConfiguration->BaseAddress ); if( xStatus != XST_SUCCESS ) { /* Not sure how to do this before XTtcPs_CfgInitialize is called as *xRTOSTickTimerInstance is set within XTtcPs_CfgInitialize(). */ XTtcPs_Stop( &xTimerInstance ); xStatus = XTtcPs_CfgInitialize( &xTimerInstance, pxTimerConfiguration, pxTimerConfiguration->BaseAddress ); configASSERT( xStatus == XST_SUCCESS ); } /* Set the options. */ XTtcPs_SetOptions( &xTimerInstance, ( XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE ) ); /* Derive values from the tick rate. */ XTtcPs_CalcIntervalFromFreq( &xTimerInstance, configTICK_RATE_HZ, &( usInterval ), &( ucPrescale ) ); /* Set the interval and prescale. */ XTtcPs_SetInterval( &xTimerInstance, usInterval ); XTtcPs_SetPrescaler( &xTimerInstance, ucPrescale ); /* The priority must be the lowest possible. */ XScuGic_SetPriorityTriggerType( &xInterruptController, configTIMER_INTERRUPT_ID, portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, ucLevelSensitive ); /* Connect to the interrupt controller. */ XScuGic_Connect( &xInterruptController, configTIMER_INTERRUPT_ID, ( Xil_InterruptHandler ) FreeRTOS_Tick_Handler, ( void * ) &xTimerInstance ); /* Enable the interrupt in the GIC. */ XScuGic_Enable( &xInterruptController, configTIMER_INTERRUPT_ID ); /* Enable the interrupts in the timer. */ XTtcPs_EnableInterrupts( &xTimerInstance, XTTCPS_IXR_INTERVAL_MASK ); /* Start the timer. */ XTtcPs_Start( &xTimerInstance ); }
static void prvSetupTest( void ) { BaseType_t x; uint32_t ulValueToSend = 0; /* Ensure the queues are created and the queue set configured before the sending task is unsuspended. First Create the queue set such that it will be able to hold a message for every space in every queue in the set. */ xQueueSet = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ); for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ ) { /* Create the queue and add it to the set. The queue is just holding uint32_t value. */ xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( uint32_t ) ); configASSERT( xQueues[ x ] ); if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS ) { xQueueSetTasksStatus = pdFAIL; } else { /* The queue has now been added to the queue set and cannot be added to another. */ if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL ) { xQueueSetTasksStatus = pdFAIL; } } } /* Attempt to remove a queue from a queue set it does not belong to (NULL being passed as the queue set in this case). */ if( xQueueRemoveFromSet( xQueues[ 0 ], NULL ) != pdFAIL ) { /* It is not possible to successfully remove a queue from a queue set it does not belong to. */ xQueueSetTasksStatus = pdFAIL; } /* Attempt to remove a queue from the queue set it does belong to. */ if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS ) { /* It should be possible to remove the queue from the queue set it does belong to. */ xQueueSetTasksStatus = pdFAIL; } /* Add an item to the queue before attempting to add it back into the set. */ xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 ); if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL ) { /* Should not be able to add a non-empty queue to a set. */ xQueueSetTasksStatus = pdFAIL; } /* Remove the item from the queue before adding the queue back into the set so the dynamic tests can begin. */ xQueueReceive( xQueues[ 0 ], &ulValueToSend, 0 ); if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS ) { /* If the queue was successfully removed from the queue set then it should be possible to add it back in again. */ xQueueSetTasksStatus = pdFAIL; } /* The task that sends to the queues is not running yet, so attempting to read from the queue set should fail. */ if( xQueueSelectFromSet( xQueueSet, queuesetSHORT_DELAY ) != NULL ) { xQueueSetTasksStatus = pdFAIL; } /* Resume the task that writes to the queues. */ vTaskResume( xQueueSetSendingTask ); /* Let the ISR access the queues also. */ xSetupComplete = pdTRUE; }
static portBASE_TYPE prvThreeParameterEchoCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString ) { int8_t *pcParameter; portBASE_TYPE lParameterStringLength, xReturn; static portBASE_TYPE lParameterNumber = 0; /* Remove compile time warnings about unused parameters, and check the write buffer is not NULL. NOTE - for simplicity, this example assumes the write buffer length is adequate, so does not check for buffer overflows. */ ( void ) pcCommandString; ( void ) xWriteBufferLen; configASSERT( pcWriteBuffer ); if( lParameterNumber == 0 ) { /* The first time the function is called after the command has been entered just a header string is returned. */ sprintf( ( char * ) pcWriteBuffer, "The three parameters were:\r\n" ); /* Next time the function is called the first parameter will be echoed back. */ lParameterNumber = 1L; /* There is more data to be returned as no parameters have been echoed back yet. */ xReturn = pdPASS; } else { /* Obtain the parameter string. */ pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter ( pcCommandString, /* The command string itself. */ lParameterNumber, /* Return the next parameter. */ &lParameterStringLength /* Store the parameter string length. */ ); /* Sanity check something was returned. */ configASSERT( pcParameter ); /* Return the parameter string. */ memset( pcWriteBuffer, 0x00, xWriteBufferLen ); sprintf( ( char * ) pcWriteBuffer, "%d: ", lParameterNumber ); strncat( ( char * ) pcWriteBuffer, ( const char * ) pcParameter, lParameterStringLength ); strncat( ( char * ) pcWriteBuffer, "\r\n", strlen( "\r\n" ) ); /* If this is the last of the three parameters then there are no more strings to return after this one. */ if( lParameterNumber == 3L ) { /* If this is the last of the three parameters then there are no more strings to return after this one. */ xReturn = pdFALSE; lParameterNumber = 0L; } else { /* There are more parameters to return after this one. */ xReturn = pdTRUE; lParameterNumber++; } } return xReturn; }
void vPortEndScheduler( void ) { /* Not implemented in ports where there is nothing to return to. Artificially force an assert. */ configASSERT( uxCriticalNesting == 1000UL ); }
static DWORD WINAPI prvSimulatedPeripheralTimer( LPVOID lpParameter ) { TickType_t xMinimumWindowsBlockTime; TIMECAPS xTimeCaps; /* Set the timer resolution to the maximum possible. */ if( timeGetDevCaps( &xTimeCaps, sizeof( xTimeCaps ) ) == MMSYSERR_NOERROR ) { xMinimumWindowsBlockTime = ( TickType_t ) xTimeCaps.wPeriodMin; timeBeginPeriod( xTimeCaps.wPeriodMin ); /* Register an exit handler so the timeBeginPeriod() function can be matched with a timeEndPeriod() when the application exits. */ SetConsoleCtrlHandler( prvEndProcess, TRUE ); } else { xMinimumWindowsBlockTime = ( TickType_t ) 20; } /* Just to prevent compiler warnings. */ ( void ) lpParameter; for( ;; ) { /* Wait until the timer expires and we can access the simulated interrupt variables. *NOTE* this is not a 'real time' way of generating tick events as the next wake time should be relative to the previous wake time, not the time that Sleep() is called. It is done this way to prevent overruns in this very non real time simulated/emulated environment. */ if( portTICK_PERIOD_MS < xMinimumWindowsBlockTime ) { Sleep( xMinimumWindowsBlockTime ); } else { Sleep( portTICK_PERIOD_MS ); } configASSERT( xPortRunning ); WaitForSingleObject( pvInterruptEventMutex, INFINITE ); /* The timer has expired, generate the simulated tick event. */ ulPendingInterrupts |= ( 1 << portINTERRUPT_TICK ); /* The interrupt is now pending - notify the simulated interrupt handler thread. */ if( ulCriticalNesting == 0 ) { SetEvent( pvInterruptEvent ); } /* Give back the mutex so the simulated interrupt handler unblocks and can access the interrupt handler variables. */ ReleaseMutex( pvInterruptEventMutex ); } #ifdef __GNUC__ /* Should never reach here - MingW complains if you leave this line out, MSVC complains if you put it in. */ return 0; #endif }