Files
zTC1/mico-os/MiCO/RTOS/mico_rtos_common.c
2025-03-11 15:54:45 +08:00

407 lines
10 KiB
C

/**
******************************************************************************
* @file mico_rtos_common.c
* @author William Xu
* @version V1.0.0
* @date 22-Aug-2016
* @brief Definitions of the MiCO Common RTOS abstraction 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.
*
******************************************************************************
*/
/** @file
*
*/
#include <string.h>
#include <stdlib.h>
#include "debug.h"
#include "rtos.h"
#include "platform_core.h"
#include "mico_rtos.h"
#include "common.h"
#include "mico_rtos_common.h"
#include "platform_config.h"
/******************************************************
* Macros
******************************************************/
/******************************************************
* Constants
******************************************************/
#define CPU_CYCLES_PER_MICROSECOND ( MCU_CLOCK_HZ / 1000000 )
/******************************************************
* Enumerations
******************************************************/
/******************************************************
* Type Definitions
******************************************************/
/******************************************************
* Structures
******************************************************/
typedef struct
{
event_handler_t function;
void* arg;
} mico_event_message_t;
/******************************************************
* Static Function Declarations
******************************************************/
static void timed_event_handler( void* arg );
/******************************************************
* Variable Definitions
******************************************************/
mico_worker_thread_t mico_hardware_io_worker_thread;
mico_worker_thread_t mico_worker_thread;
/******************************************************
* Function Definitions
******************************************************/
OSStatus mico_rtos_init( void )
{
OSStatus result = kNoErr;
rtos_log("Started MiCO RTOS interface for %s %s", RTOS_NAME, RTOS_VERSION );
/*
result = mico_rtos_create_worker_thread( MICO_HARDWARE_IO_WORKER_THREAD, MICO_DEFAULT_WORKER_PRIORITY, HARDWARE_IO_WORKER_THREAD_STACK_SIZE, HARDWARE_IO_WORKER_THREAD_QUEUE_SIZE );
if ( result != kNoErr )
{
rtos_log("Failed to create MICO_NETWORKING_WORKER_THREAD");
}
*/
result = mico_rtos_create_worker_thread( MICO_NETWORKING_WORKER_THREAD, MICO_NETWORK_WORKER_PRIORITY, NETWORKING_WORKER_THREAD_STACK_SIZE, NETWORKING_WORKER_THREAD_QUEUE_SIZE );
if ( result != kNoErr )
{
rtos_log("Failed to create MICO_NETWORKING_WORKER_THREAD");
}
return result;
}
OSStatus mico_rtos_deinit( void )
{
OSStatus result = mico_rtos_delete_worker_thread( MICO_HARDWARE_IO_WORKER_THREAD );
if ( result == kNoErr )
{
result = mico_rtos_delete_worker_thread( MICO_NETWORKING_WORKER_THREAD );
}
return result;
}
OSStatus mico_rtos_delay_microseconds( uint32_t microseconds )
{
uint32_t current_time;
uint32_t duration;
uint32_t elapsed_time = 0;
current_time = platform_get_cycle_count( );
duration = ( microseconds * CPU_CYCLES_PER_MICROSECOND );
while ( elapsed_time < duration )
{
elapsed_time = platform_get_cycle_count( ) - current_time;
}
return kNoErr;
}
static void worker_thread_main( uint32_t arg )
{
mico_worker_thread_t* worker_thread = (mico_worker_thread_t*) arg;
while ( 1 )
{
mico_event_message_t message;
if ( mico_rtos_pop_from_queue( &worker_thread->event_queue, &message, MICO_WAIT_FOREVER ) == kNoErr )
{
message.function( message.arg );
}
}
}
OSStatus mico_rtos_create_worker_thread( mico_worker_thread_t* worker_thread, uint8_t priority, uint32_t stack_size, uint32_t event_queue_size )
{
memset( worker_thread, 0, sizeof( *worker_thread ) );
if ( mico_rtos_init_queue( &worker_thread->event_queue, "worker queue", sizeof(mico_event_message_t), event_queue_size ) != kNoErr )
{
return kGeneralErr;
}
if ( mico_rtos_create_thread( &worker_thread->thread, priority , "worker thread", worker_thread_main, stack_size, (mico_thread_arg_t) worker_thread ) != kNoErr )
{
mico_rtos_deinit_queue( &worker_thread->event_queue );
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_delete_worker_thread( mico_worker_thread_t* worker_thread )
{
if ( mico_rtos_delete_thread( &worker_thread->thread ) != kNoErr )
{
return kGeneralErr;
}
if ( mico_rtos_deinit_queue( &worker_thread->event_queue ) != kNoErr )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_register_timed_event( mico_timed_event_t* event_object, mico_worker_thread_t* worker_thread, event_handler_t function, uint32_t time_ms, void* arg )
{
if( worker_thread->thread == NULL )
return kNotInitializedErr;
if ( mico_rtos_init_timer( &event_object->timer, time_ms, timed_event_handler, (void*) event_object ) != kNoErr )
{
return kGeneralErr;
}
event_object->function = function;
event_object->thread = worker_thread;
event_object->arg = arg;
if ( mico_rtos_start_timer( &event_object->timer ) != kNoErr )
{
mico_rtos_deinit_timer( &event_object->timer );
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_deregister_timed_event( mico_timed_event_t* event_object )
{
if ( mico_rtos_deinit_timer( &event_object->timer ) != kNoErr )
{
return kGeneralErr;
}
return kNoErr;
}
OSStatus mico_rtos_send_asynchronous_event( mico_worker_thread_t* worker_thread, event_handler_t function, void* arg )
{
mico_event_message_t message;
if( worker_thread->thread == NULL )
return kNotInitializedErr;
message.function = function;
message.arg = arg;
return mico_rtos_push_to_queue( &worker_thread->event_queue, &message, MICO_NO_WAIT );
}
static void timed_event_handler( void* arg )
{
mico_timed_event_t* event_object = (mico_timed_event_t*) arg;
mico_event_message_t message;
message.function = event_object->function;
message.arg = event_object->arg;
mico_rtos_push_to_queue( &event_object->thread->event_queue, &message, MICO_NO_WAIT );
}
void mico_rtos_thread_sleep(uint32_t seconds)
{
mico_rtos_delay_milliseconds(seconds*1000);
}
void mico_rtos_thread_msleep(uint32_t mseconds)
{
mico_rtos_delay_milliseconds(mseconds);
}
void sleep(uint32_t seconds)
{
mico_rtos_delay_milliseconds(seconds*1000);
}
void msleep(uint32_t mseconds)
{
mico_rtos_delay_milliseconds(mseconds);
}
/////////////////////////
///
#if 1
struct mxchip_timer {
uint32_t timeout;
void (*handler)(void);
struct mxchip_timer *next;
int valid;
};
struct mxchip_timer *timer_head = NULL;
static mico_semaphore_t timer_sem;
static int mxchip_timer_inited = 0;
static uint32_t timer_thread_wait = MICO_NEVER_TIMEOUT;
static void timer_thread_func(void* arg);
int mxchip_timer_init(void)
{
int ret;
if (mxchip_timer_inited)
return 0;
ret = mico_rtos_init_semaphore(&timer_sem, 1);
if (ret != 0)
return -1;
ret = mico_rtos_create_thread(NULL, MICO_DEFAULT_WORKER_PRIORITY, "mxchipTimer", (mico_thread_function_t)timer_thread_func, 2048, 0);
if (ret != 0)
return -1;
mxchip_timer_inited = 1;
return 0;
}
int SetTimer(unsigned long ms, void (*psysTimerHandler)(void))
{
struct mxchip_timer *timer, *p;
if (mxchip_timer_inited == 0) {
if (mxchip_timer_init() != 0)
return -1;
}
timer = (struct mxchip_timer *)malloc(sizeof(struct mxchip_timer));
if (timer == NULL)
return -1;
timer->timeout = mico_rtos_get_time() + ms;
timer->handler = psysTimerHandler;
timer->valid = 1;
timer->next = NULL;
if (timer_head == NULL)
timer_head = timer;
else {
p = timer_head;
while(p->next != NULL)
p = p->next;
p->next = timer;
}
mico_rtos_set_semaphore(&timer_sem);
return 0;
}
/* find in the timer list, if find the same handler ignore, else create new timer */
int SetTimer_uniq(unsigned long ms, void (*psysTimerHandler)(void))
{
struct mxchip_timer *p;
p = timer_head;
while(p != NULL) {
if (p->handler == psysTimerHandler) {
p->timeout = mico_rtos_get_time() + ms; // update time
p->valid = 1;
return 0;
} else
p = p->next;
}
return SetTimer(ms, psysTimerHandler);
}
/* Remove all timers which handler is psysTimerHandler */
int UnSetTimer(void (*psysTimerHandler)(void))
{
struct mxchip_timer *p;
p = timer_head;
while (p != NULL) {
if (p->handler == psysTimerHandler) {
p->valid = 0;
}
p = p->next;
}
return 0;
}
static void mxchip_timer_tick(void)
{
struct mxchip_timer *p, *q;
uint32_t next_time = MICO_NEVER_TIMEOUT, cur_time;
q = timer_head;
p = timer_head;
while (p != NULL) {
if (next_time > p->timeout)
next_time = p->timeout;
if (p->timeout < mico_rtos_get_time()) {
if (p == timer_head) {
timer_head = timer_head->next;
if (p->valid == 1)
p->handler();
free(p);
p = timer_head; // time_head may be changed by handler().
continue;
} else {
q->next = p->next;
if (p->valid == 1)
p->handler();
free(p);
break;
}
}
q = p;
p = p->next;
}
cur_time = mico_rtos_get_time();
if (next_time <= cur_time)
timer_thread_wait = 1;
else
timer_thread_wait = next_time - cur_time;
return;
}
static void timer_thread_func(void* arg)
{
while(1) {
mico_rtos_get_semaphore(&timer_sem, timer_thread_wait);
mxchip_timer_tick();
}
}
#endif