Files
zTC1/mico-os/MiCO/RTOS/FreeRTOS/mico/mico_rtos.c
2025-03-11 14:10:51 +08:00

870 lines
25 KiB
C

/**
******************************************************************************
* @file mico_rtos.c
* @author William Xu
* @version V1.0.0
* @date 05-Aug-2018
* @brief This file provide the MiCO RTOS abstract layer functions.
******************************************************************************
*
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
#include <string.h>
#include <stdlib.h>
#include "mico_rtos.h"
#include "qc_test.h"
#include "rtos.h"
#include "mico_rtos_common.h"
#include "FreeRTOS.h"
#include "projdefs.h"
#include "debug.h"
#include "platform_core.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
#include "mico_FreeRTOS_systick.h"
#include "FreeRTOSConfig.h"
#include "timers.h"
#include "crt0.h"
/******************************************************
* Macros
******************************************************/
#if FreeRTOS_VERSION_MAJOR == 7
#define _xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskCreate( pvTaskCode, (signed char*)pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask )
#define _xTimerCreate( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction ) xTimerCreate( (signed char*)pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction )
#else
#define _xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask )
#define _xTimerCreate( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction ) xTimerCreate( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction )
#endif
#define cmd_printf(...) do{\
if (xWriteBufferLen > 0) {\
snprintf(pcWriteBuffer, xWriteBufferLen, __VA_ARGS__);\
xWriteBufferLen-=strlen(pcWriteBuffer);\
pcWriteBuffer+=strlen(pcWriteBuffer);\
}\
}while(0)
/******************************************************
* Constants
******************************************************/
#ifndef TIMER_THREAD_STACK_SIZE
#define TIMER_THREAD_STACK_SIZE 1024 + 4*1024
#endif
#define TIMER_QUEUE_LENGTH 5
/*
* Macros used by vListTask to indicate which state a task is in.
*/
#define tskBLOCKED_CHAR ( 'B' )
#define tskREADY_CHAR ( 'R' )
#define tskDELETED_CHAR ( 'D' )
#define tskSUSPENDED_CHAR ( 'S' )
/******************************************************
* Enumerations
******************************************************/
/******************************************************
* Type Definitions
******************************************************/
typedef tmrTIMER_CALLBACK native_timer_handler_t;
typedef pdTASK_CODE native_thread_t;
/******************************************************
* Structures
******************************************************/
typedef struct
{
event_handler_t function;
void* arg;
} timer_queue_message_t;
typedef struct
{
event_handler_t function;
void* arg;
} mico_event_message_t;
/******************************************************
* Function Declarations
******************************************************/
extern void mico_rtos_stack_overflow(char *taskname);
extern bool MicoShouldEnterMFGMode(void);
static void application_thread_main( void *arg );
#ifdef __GNUC__
void __malloc_lock(struct _reent *ptr);
void __malloc_unlock(struct _reent *ptr);
#endif /* ifdef __GNUC__ */
/******************************************************
* Variables Definitions
******************************************************/
static xTaskHandle app_thread_handle;
static mico_time_t mico_time_offset = 0;
extern const uint32_t mico_tick_rate_hz;
extern uint32_t app_stack_size;
extern const int CFG_PRIO_BITS;
uint32_t max_syscall_int_prio;
uint32_t ms_to_tick_ratio = 1;
uint32_t mico_rtos_max_priorities = RTOS_HIGHEST_PRIORITY - RTOS_LOWEST_PRIORITY + 1;
/******************************************************
* Function Definitions
******************************************************/
/**
* Main function - starts FreeRTOS
* Called from the crt0 _start function
*
*/
int main( void )
{
max_syscall_int_prio = (1 << (8 - CFG_PRIO_BITS));
ms_to_tick_ratio = (uint32_t)( 1000 / mico_tick_rate_hz );
#if defined ( __IAR_SYSTEMS_ICC__ )
/* IAR allows init functions in __low_level_init(), but it is run before global
* variables have been initialised, so the following init still needs to be done.
* When using GCC, this is done in crt0_GCC.c
*/
init_architecture( );
init_platform( );
#endif /* #elif defined ( __IAR_SYSTEMS_ICC__ ) */
/* Create an initial thread */
_xTaskCreate( application_thread_main, "app_thread", (unsigned short)(app_stack_size/sizeof( portSTACK_TYPE )), NULL, MICO_PRIORITY_TO_NATIVE_PRIORITY(MICO_APPLICATION_PRIORITY), &app_thread_handle);
/* Start the FreeRTOS scheduler - this call should never return */
vTaskStartScheduler( );
/* Should never get here, unless there is an error in vTaskStartScheduler */
return 0;
}
static void application_thread_main( void *arg )
{
UNUSED_PARAMETER( arg );
if ( MicoShouldEnterMFGMode( ) )
mico_system_qc_test( );
else
application_start( );
vTaskDelete( NULL );
}
OSStatus mico_rtos_create_thread( mico_thread_t* thread, uint8_t priority, const char* name, mico_thread_function_t function, uint32_t stack_size, uint32_t arg )
{
/* Limit priority to default lib priority */
if ( priority > RTOS_HIGHEST_PRIORITY )
{
priority = RTOS_HIGHEST_PRIORITY;
}
if( pdPASS == _xTaskCreate( (native_thread_t)function, name, (unsigned short) (stack_size/sizeof( portSTACK_TYPE )), (void *)arg, MICO_PRIORITY_TO_NATIVE_PRIORITY(priority), thread ) )
{
return kNoErr;
}
else
{
return kGeneralErr;
}
}
OSStatus mico_rtos_delete_thread( mico_thread_t* thread )
{
if ( thread == NULL )
{
vTaskDelete( NULL );
}
else if ( xTaskIsTaskFinished( *thread ) != pdTRUE )
{
vTaskDelete( *thread );
}
return kNoErr;
}
OSStatus mico_rtos_thread_join( mico_thread_t* thread )
{
mico_thread_t tmp = *thread;
if ( (thread == NULL) || (tmp == NULL) )
return kNoErr;
while ( xTaskIsTaskFinished( tmp ) != pdTRUE )
{
mico_rtos_delay_milliseconds( 10 );
}
return kNoErr;
}
bool mico_rtos_is_current_thread( mico_thread_t* thread )
{
if ( xTaskGetCurrentTaskHandle( ) == *thread )
{
return true;
}
else
{
return false;
}
}
mico_thread_t* mico_rtos_get_current_thread( void )
{
return (mico_thread_t *)xTaskGetCurrentTaskHandle();
}
#if FreeRTOS_VERSION_MAJOR == 7
/* Old deployment, may has some problem */
OSStatus mico_rtos_print_thread_status( char* pcWriteBuffer, int xWriteBufferLen )
{
cmd_printf("%-30s Status Prio Stack TCB\r\n", "Name");
cmd_printf("------------------------------------------------------------");
if (xWriteBufferLen >= 256)
vTaskList((signed char *)pcWriteBuffer);
else {
char buf[256];
vTaskList((signed char *)buf);
strncpy(pcWriteBuffer, buf, xWriteBufferLen);
}
return kNoErr;
}
#else
static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
{
long x;
/* Start by copying the entire string. */
strcpy( pcBuffer, pcTaskName );
/* Pad the end of the string with spaces to ensure columns line up when
printed out. */
for( x = strlen( pcBuffer ); x < ( configMAX_TASK_NAME_LEN - 1 ); x++ )
{
pcBuffer[ x ] = ' ';
}
/* Terminate. */
pcBuffer[ x ] = 0x00;
/* Return the new end of string. */
return &( pcBuffer[ x ] );
}
/* Re-write vTaskList to add a buffer size parameter */
OSStatus mico_rtos_print_thread_status( char* pcWriteBuffer, int xWriteBufferLen )
{
TaskStatus_t *pxTaskStatusArray;
unsigned portBASE_TYPE uxCurrentNumberOfTasks = uxTaskGetNumberOfTasks();
volatile UBaseType_t uxArraySize, x;
char cStatus;
char pcTaskStatusStr[48];
char *pcTaskStatusStrTmp;
/* Make sure the write buffer does not contain a string. */
*pcWriteBuffer = 0x00;
/* Take a snapshot of the number of tasks in case it changes while this
function is executing. */
uxArraySize = uxCurrentNumberOfTasks;
/* Allocate an array index for each task. NOTE! if
configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
equate to NULL. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof(TaskStatus_t) );
cmd_printf("%-12s Status Prio Stack TCB\r\n", "Name");
cmd_printf("-------------------------------------------\r\n");
xWriteBufferLen-=strlen(pcWriteBuffer);
if ( pxTaskStatusArray != NULL )
{
/* Generate the (binary) data. */
uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
/* Create a human readable table from the binary data. */
for ( x = 0; x < uxArraySize; x++ )
{
switch ( pxTaskStatusArray[x].eCurrentState )
{
case eReady:
cStatus = tskREADY_CHAR;
break;
case eBlocked:
cStatus = tskBLOCKED_CHAR;
break;
case eSuspended:
cStatus = tskSUSPENDED_CHAR;
break;
case eDeleted:
cStatus = tskDELETED_CHAR;
break;
default: /* Should not get here, but it is included
to prevent static checking errors. */
cStatus = 0x00;
break;
}
/* Write the task name to the string, padding with spaces so it
can be printed in tabular form more easily. */
pcTaskStatusStrTmp = pcTaskStatusStr;
pcTaskStatusStrTmp = prvWriteNameToBuffer( pcTaskStatusStrTmp, pxTaskStatusArray[x].pcTaskName );
//pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[x].pcTaskName );
/* Write the rest of the string. */
sprintf( pcTaskStatusStrTmp, "\t%c\t%u\t%u\t%u\r\n", cStatus,
MICO_PRIORITY_TO_NATIVE_PRIORITY((unsigned int) pxTaskStatusArray[x].uxCurrentPriority),
(unsigned int) pxTaskStatusArray[x].usStackHighWaterMark,
(unsigned int) pxTaskStatusArray[x].xTaskNumber );
if( xWriteBufferLen < strlen( pcTaskStatusStr ) )
{
for ( x = 0; x < xWriteBufferLen; x++ )
{
*(pcWriteBuffer+x) = '.';
}
break;
}
else
{
strncpy( pcWriteBuffer, pcTaskStatusStr, xWriteBufferLen);
xWriteBufferLen -= strlen( pcTaskStatusStr );
pcWriteBuffer += strlen( pcWriteBuffer );
}
}
/* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
is 0 then vPortFree() will be #defined to nothing. */
vPortFree( pxTaskStatusArray );
}
else
{
mtCOVERAGE_TEST_MARKER( );
}
return kNoErr;
}
#endif
OSStatus mico_rtos_check_stack( void )
{
// TODO: Add stack checking here.
return kNoErr;
}
OSStatus mico_rtos_thread_force_awake( mico_thread_t* thread )
{
#if FreeRTOS_VERSION_MAJOR < 9
vTaskForceAwake(*thread);
#else
xTaskAbortDelay(*thread);
#endif
return kNoErr;
}
OSStatus mico_time_get_time(mico_time_t* time_ptr)
{
*time_ptr = (mico_time_t) ( xTaskGetTickCount( ) * ms_to_tick_ratio ) + mico_time_offset;
return kNoErr;
}
OSStatus mico_time_set_time(mico_time_t* time_ptr)
{
mico_time_offset = *time_ptr - (mico_time_t) ( xTaskGetTickCount( ) * ms_to_tick_ratio );
return kNoErr;
}
OSStatus mico_rtos_init_semaphore( mico_semaphore_t* semaphore, int count )
{
*semaphore = xSemaphoreCreateCounting( (unsigned portBASE_TYPE) count, (unsigned portBASE_TYPE) 0 );
return ( *semaphore != NULL ) ? kNoErr : kGeneralErr;
}
OSStatus mico_rtos_get_semaphore( mico_semaphore_t* semaphore, uint32_t timeout_ms )
{
if ( pdTRUE == xSemaphoreTake( *semaphore, (portTickType) ( timeout_ms / ms_to_tick_ratio ) ) )
{
return kNoErr;
}
else
{
return kTimeoutErr;
}
}
int mico_rtos_set_semaphore( mico_semaphore_t* semaphore )
{
signed portBASE_TYPE result;
if ( platform_is_in_interrupt_context( ) == MICO_TRUE )
{
signed portBASE_TYPE xHigherPriorityTaskWoken;
result = xSemaphoreGiveFromISR( *semaphore, &xHigherPriorityTaskWoken );
//check_string( result == pdTRUE, "Unable to set semaphore" );
/* If xSemaphoreGiveFromISR() unblocked a task, and the unblocked task has
* a higher priority than the currently executing task, then
* xHigherPriorityTaskWoken will have been set to pdTRUE and this ISR should
* return directly to the higher priority unblocked task.
*/
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
else
{
result = xSemaphoreGive( *semaphore );
//check_string( result == pdTRUE, "Unable to set semaphore" );
}
return ( result == pdPASS )? kNoErr : kGeneralErr;
}
OSStatus mico_rtos_deinit_semaphore( mico_semaphore_t* semaphore )
{
if (semaphore != NULL)
{
vQueueDelete( *semaphore );
*semaphore = NULL;
}
return kNoErr;
}
void mico_rtos_enter_critical( void )
{
vPortEnterCritical();
}
void mico_rtos_exit_critical( void )
{
vPortExitCritical();
}
OSStatus mico_rtos_init_mutex( mico_mutex_t* mutex )
{
check_string(mutex != NULL, "Bad args");
/* Mutex uses priority inheritance */
*mutex = xSemaphoreCreateMutex( );
if ( *mutex == NULL )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_lock_mutex( mico_mutex_t* mutex )
{
check_string(mutex != NULL, "Bad args");
if ( xSemaphoreTake( *mutex, MICO_WAIT_FOREVER ) != pdPASS )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_unlock_mutex( mico_mutex_t* mutex )
{
check_string(mutex != NULL, "Bad args");
if ( xSemaphoreGive( *mutex ) != pdPASS )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_deinit_mutex( mico_mutex_t* mutex )
{
check_string(mutex != NULL, "Bad args");
vSemaphoreDelete( *mutex );
*mutex = NULL;
return kNoErr;
}
OSStatus mico_rtos_init_queue( mico_queue_t* queue, const char* name, uint32_t message_size, uint32_t number_of_messages )
{
UNUSED_PARAMETER(name);
if ( ( *queue = xQueueCreate( number_of_messages, message_size ) ) == NULL )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_push_to_queue( mico_queue_t* queue, void* message, uint32_t timeout_ms )
{
signed portBASE_TYPE result;
if ( platform_is_in_interrupt_context( ) == MICO_TRUE )
{
signed portBASE_TYPE xHigherPriorityTaskWoken;
result = xQueueSendToBackFromISR( *queue, message, &xHigherPriorityTaskWoken );
/* If xQueueSendToBackFromISR() unblocked a task, and the unblocked task has
* a higher priority than the currently executing task, then
* xHigherPriorityTaskWoken will have been set to pdTRUE and this ISR should
* return directly to the higher priority unblocked task.
*/
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
else
{
result = xQueueSendToBack( *queue, message, (portTickType) ( timeout_ms / ms_to_tick_ratio ) );
}
return ( result == pdPASS )? kNoErr : kGeneralErr;
}
OSStatus mico_rtos_push_to_queue_front( mico_queue_t* queue, void* message, uint32_t timeout_ms )
{
signed portBASE_TYPE result;
if ( platform_is_in_interrupt_context( ) == MICO_TRUE )
{
signed portBASE_TYPE xHigherPriorityTaskWoken;
result = xQueueSendToFrontFromISR( *queue, message, &xHigherPriorityTaskWoken );
/* If xQueueSendToBackFromISR() unblocked a task, and the unblocked task has
* a higher priority than the currently executing task, then
* xHigherPriorityTaskWoken will have been set to pdTRUE and this ISR should
* return directly to the higher priority unblocked task.
*/
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
else
{
result = xQueueSendToFront( *queue, message, (portTickType) ( timeout_ms / ms_to_tick_ratio ) );
}
return ( result == pdPASS )? kNoErr : kGeneralErr;
}
OSStatus mico_rtos_pop_from_queue( mico_queue_t* queue, void* message, uint32_t timeout_ms )
{
if ( xQueueReceive( *queue, message, ( timeout_ms / ms_to_tick_ratio ) ) != pdPASS )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_deinit_queue( mico_queue_t* queue )
{
vQueueDelete( *queue );
*queue = NULL;
return kNoErr;
}
bool mico_rtos_is_queue_empty( mico_queue_t* queue )
{
signed portBASE_TYPE result;
taskENTER_CRITICAL();
result = xQueueIsQueueEmptyFromISR( *queue );
taskEXIT_CRITICAL();
return ( result != 0 ) ? true : false;
}
bool mico_rtos_is_queue_full( mico_queue_t* queue )
{
signed portBASE_TYPE result;
taskENTER_CRITICAL();
result = xQueueIsQueueFullFromISR( *queue );
taskEXIT_CRITICAL();
return ( result != 0 ) ? true : false;
}
static void timer_callback( xTimerHandle handle )
{
mico_timer_t* timer = (mico_timer_t*) pvTimerGetTimerID( handle );
if ( timer->function )
{
timer->function( timer->arg );
}
}
OSStatus mico_rtos_init_timer( mico_timer_t* timer, uint32_t time_ms, timer_handler_t function, void* arg )
{
check_string(timer != NULL, "Bad args");
timer->function = function;
timer->arg = arg;
timer->handle = _xTimerCreate( "", (portTickType)( time_ms / ms_to_tick_ratio ), pdTRUE, timer, (native_timer_handler_t) timer_callback );
if ( timer->handle == NULL )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_start_timer( mico_timer_t* timer )
{
signed portBASE_TYPE result;
if ( platform_is_in_interrupt_context( ) == MICO_TRUE ) {
signed portBASE_TYPE xHigherPriorityTaskWoken;
result = xTimerStartFromISR(timer->handle, &xHigherPriorityTaskWoken );
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
} else
result = xTimerStart( timer->handle, MICO_WAIT_FOREVER );
if ( result != pdPASS )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_stop_timer( mico_timer_t* timer )
{
signed portBASE_TYPE result;
if ( platform_is_in_interrupt_context( ) == MICO_TRUE ) {
signed portBASE_TYPE xHigherPriorityTaskWoken;
result = xTimerStopFromISR(timer->handle, &xHigherPriorityTaskWoken );
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
} else
result = xTimerStop( timer->handle, MICO_WAIT_FOREVER );
if ( result != pdPASS )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_reload_timer( mico_timer_t* timer )
{
signed portBASE_TYPE result;
if ( platform_is_in_interrupt_context( ) == MICO_TRUE ) {
signed portBASE_TYPE xHigherPriorityTaskWoken;
result = xTimerResetFromISR(timer->handle, &xHigherPriorityTaskWoken );
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
} else
result = xTimerReset( timer->handle, MICO_WAIT_FOREVER );
if ( result != pdPASS )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_deinit_timer( mico_timer_t* timer )
{
if ( xTimerDelete( timer->handle, MICO_WAIT_FOREVER ) != pdPASS )
{
return kGeneralErr;
}
return kNoErr;
}
bool mico_rtos_is_timer_running( mico_timer_t* timer )
{
return ( xTimerIsTimerActive( timer->handle ) != 0 ) ? true : false;
}
OSStatus mico_rtos_init_event_flags( mico_event_flags_t* event_flags )
{
UNUSED_PARAMETER( event_flags );
check_string( 0!=0, "Unsupported\r\n" );
return kUnsupportedErr;
}
OSStatus mico_rtos_wait_for_event_flags( mico_event_flags_t* event_flags, uint32_t flags_to_wait_for, uint32_t* flags_set, mico_bool_t clear_set_flags, mico_event_flags_wait_option_t wait_option, uint32_t timeout_ms )
{
UNUSED_PARAMETER( event_flags );
UNUSED_PARAMETER( flags_to_wait_for );
UNUSED_PARAMETER( flags_set );
UNUSED_PARAMETER( clear_set_flags );
UNUSED_PARAMETER( wait_option );
UNUSED_PARAMETER( timeout_ms );
check_string( 0!=0, "Unsupported\r\n" );
return kUnsupportedErr;
}
OSStatus mico_rtos_set_event_flags( mico_event_flags_t* event_flags, uint32_t flags_to_set )
{
UNUSED_PARAMETER( event_flags );
UNUSED_PARAMETER( flags_to_set );
check_string( 0!=0, "Unsupported\r\n" );
return kUnsupportedErr;
}
OSStatus mico_rtos_deinit_event_flags( mico_event_flags_t* event_flags )
{
UNUSED_PARAMETER( event_flags );
check_string( 0!=0, "Unsupported\r\n" );
return kUnsupportedErr;
}
#ifdef __GNUC__
void __malloc_lock(struct _reent *ptr)
{
UNUSED_PARAMETER( ptr );
vTaskSuspendAll();
return;
}
void __malloc_unlock(struct _reent *ptr)
{
UNUSED_PARAMETER( ptr );
xTaskResumeAll();
}
#endif /* __GNUC__ */
void mico_rtos_suspend_thread(mico_thread_t* thread)
{
if (thread == NULL)
vTaskSuspend(NULL);
else
vTaskSuspend(*thread);
}
void mico_rtos_resume_thread(mico_thread_t* thread)
{
if (thread == NULL)
vTaskResume(NULL);
else
vTaskResume(*thread);
}
/**
* Gets time in milliseconds since RTOS start
*
* @Note: since this is only 32 bits, it will roll over every 49 days, 17 hours.
*
* @returns Time in milliseconds since RTOS started.
*/
mico_time_t mico_rtos_get_time( void )
{
return (mico_time_t) ( xTaskGetTickCount( ) * ms_to_tick_ratio );
}
/**
* Delay for a number of milliseconds
*
* Processing of this function depends on the minimum sleep
* time resolution of the RTOS.
* The current thread sleeps for the longest period possible which
* is less than the delay required, then makes up the difference
* with a tight loop
*
* @return OSStatus : kNoErr if delay was successful
*
*/
OSStatus mico_rtos_delay_milliseconds( uint32_t num_ms )
{
uint32_t ticks;
ticks = num_ms / ms_to_tick_ratio;
if (ticks == 0)
ticks = 1;
vTaskDelay( (portTickType) ticks );
return kNoErr;
}
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )
{
/*@-noeffect@*/
UNUSED_PARAMETER( pxTask );
UNUSED_PARAMETER( pcTaskName ); /* unused parameter in release build */
/*@+noeffect@*/
//WPRINT_RTOS_DEBUG(("Stack Overflow Detected in task %s\r\n",pcTaskName));
//#ifdef MICO
mico_rtos_stack_overflow((char*)pcTaskName);
//#endif
}
void vApplicationMallocFailedHook( void )
{
//WPRINT_RTOS_DEBUG(("Heap is out of memory during malloc\r\n"));
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void *mico_malloc( size_t xWantedSize )
{
return pvPortMalloc(xWantedSize);
}
void mico_free( void *pv )
{
vPortFree(pv);
}
void *mico_realloc( void *pv, size_t xWantedSize )
{
return pvPortRealloc(pv, xWantedSize);
}
//#endif