Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources

This commit is contained in:
2026-07-06 11:30:13 +08:00
commit e76462eeb7
3451 changed files with 1415300 additions and 0 deletions

View File

@@ -0,0 +1,641 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file csi_kernel.h
* @brief header file for kernel definition
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CSI_KERNEL_
#define _CSI_KERNEL_
#include <stdint.h>
#include <errno.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct osTimespec {
long tv_sec;
long tv_msec;
} osTimespec_t;
/* =================================================================================== */
/* Enumerations, structures, defines */
/* =================================================================================== */
/// Status code values returned by CSI-kernel functions. 0 - success, negative represents error code ,see errno.h
typedef int32_t k_status_t;
/// Kernel scheduler state.
typedef enum {
KSCHED_ST_INACTIVE = 0, ///< Inactive: The kernel is not ready yet. csi_kernel_init needs to be executed successfully.
KSCHED_ST_READY = 1, ///< Ready: The kernel is not yet running. csi_kernel_start transfers the kernel to the running state.
KSCHED_ST_RUNNING = 2, ///< Running: The kernel is initialized and running.
KSCHED_ST_LOCKED = 3, ///< Locked: The kernel was locked with csi_kernel_sched_lock. The functions csi_kernel_sched_unlock or csi_kernel_sched_restore_lock unlocks it.
KSCHED_ST_SUSPEND = 4, ///< Suspended: The kernel was suspended using csi_kernel_sched_suspend. The function csi_kernel_sched_resume returns to normal operation
KSCHED_ST_ERROR = 5 ///< Error: An error occurred.
} k_sched_stat_t;
/// task state.
typedef enum {
KTASK_ST_INACTIVE = 0, ///< Inactive.
KTASK_ST_READY = 1, ///< Ready.
KTASK_ST_RUNNING = 2, ///< Running.
KTASK_ST_BLOCKED = 3, ///< Blocked.
KTASK_ST_TERMINATED = 4, ///< Terminated.
KTASK_ST_ERROR = 5 ///< Error: An error occurred.
} k_task_stat_t;
/// timer state.
typedef enum {
KTIMER_ST_INACTIVE = 0, ///< not running
KTIMER_ST_ACTIVE = 1, ///< running
} k_timer_stat_t;
/// Timer type.
typedef enum {
KTIMER_TYPE_ONCE = 0, ///< One-shot timer.
KTIMER_TYPE_PERIODIC = 1 ///< Repeating timer.
} k_timer_type_t;
/// event option.
typedef enum {
KEVENT_OPT_SET_ANY = 0, ///< Check any bit in flags to be 1.
KEVENT_OPT_SET_ALL = 1, ///< Check all bits in flags to be 1.
KEVENT_OPT_CLR_ANY = 2, ///< Check any bit in flags to be 0.
KEVENT_OPT_CLR_ALL = 3 ///< Check all bits in flags to be 0.
} k_event_opt_t;
/// Priority definition.
typedef enum {
KPRIO_IDLE = 0, ///< priority: idle (lowest)
KPRIO_LOW0 , ///< priority: low
KPRIO_LOW1 , ///< priority: low + 1
KPRIO_LOW2 , ///< priority: low + 2
KPRIO_LOW3 , ///< priority: low + 3
KPRIO_LOW4 , ///< priority: low + 4
KPRIO_LOW5 , ///< priority: low + 5
KPRIO_LOW6 , ///< priority: low + 6
KPRIO_LOW7 , ///< priority: low + 7
KPRIO_NORMAL_BELOW0 , ///< priority: below normal
KPRIO_NORMAL_BELOW1 , ///< priority: below normal + 1
KPRIO_NORMAL_BELOW2 , ///< priority: below normal + 2
KPRIO_NORMAL_BELOW3 , ///< priority: below normal + 3
KPRIO_NORMAL_BELOW4 , ///< priority: below normal + 4
KPRIO_NORMAL_BELOW5 , ///< priority: below normal + 5
KPRIO_NORMAL_BELOW6 , ///< priority: below normal + 6
KPRIO_NORMAL_BELOW7 , ///< priority: below normal + 7
KPRIO_NORMAL , ///< priority: normal (default)
KPRIO_NORMAL1 , ///< priority: normal + 1
KPRIO_NORMAL2 , ///< priority: normal + 2
KPRIO_NORMAL3 , ///< priority: normal + 3
KPRIO_NORMAL4 , ///< priority: normal + 4
KPRIO_NORMAL5 , ///< priority: normal + 5
KPRIO_NORMAL6 , ///< priority: normal + 6
KPRIO_NORMAL7 , ///< priority: normal + 7
KPRIO_NORMAL_ABOVE0 , ///< priority: above normal + 1
KPRIO_NORMAL_ABOVE1 , ///< priority: above normal + 2
KPRIO_NORMAL_ABOVE2 , ///< priority: above normal + 3
KPRIO_NORMAL_ABOVE3 , ///< priority: above normal + 4
KPRIO_NORMAL_ABOVE4 , ///< priority: above normal + 5
KPRIO_NORMAL_ABOVE5 , ///< priority: above normal + 6
KPRIO_NORMAL_ABOVE6 , ///< priority: above normal + 7
KPRIO_NORMAL_ABOVE7 , ///< priority: above normal + 8
KPRIO_HIGH0 , ///< priority: high
KPRIO_HIGH1 , ///< priority: high + 1
KPRIO_HIGH2 , ///< priority: high + 2
KPRIO_HIGH3 , ///< priority: high + 3
KPRIO_HIGH4 , ///< priority: high + 4
KPRIO_HIGH5 , ///< priority: high + 5
KPRIO_HIGH6 , ///< priority: high + 6
KPRIO_HIGH7 , ///< priority: high + 7
KPRIO_REALTIME0 , ///< priority: realtime + 1
KPRIO_REALTIME1 , ///< priority: realtime + 2
KPRIO_REALTIME2 , ///< priority: realtime + 3
KPRIO_REALTIME3 , ///< priority: realtime + 4
KPRIO_REALTIME4 , ///< priority: realtime + 5
KPRIO_REALTIME5 , ///< priority: realtime + 6
KPRIO_REALTIME6 , ///< priority: realtime + 7
KPRIO_REALTIME7 , ///< priority: realtime + 8
KPRIO_ISR , ///< priority: Reserved for ISR deferred thread
KPRIO_ERROR ///< Illegal priority
} k_priority_t;
/// Entry point of a task.
typedef void (*k_task_entry_t)(void *arg);
/// Entry point of a timer call back function.
typedef void (*k_timer_cb_t)(void *arg);
/// \details Task handle identifies the task.
typedef void *k_task_handle_t;
/// \details Timer handle identifies the timer.
typedef void *k_timer_handle_t;
/// \details Event Flags handle identifies the event flags.
typedef void *k_event_handle_t;
/// \details Mutex handle identifies the mutex.
typedef void *k_mutex_handle_t;
/// \details Semaphore handle identifies the semaphore.
typedef void *k_sem_handle_t;
/// \details Memory Pool handle identifies the memory pool.
typedef void *k_mpool_handle_t;
/// \details Message Queue handle identifies the message queue.
typedef void *k_msgq_handle_t;
/* =================================================================================== */
/* Kernel Management Functions */
/* =================================================================================== */
/// Initialize the Kernel. Before it is successfully executed, no RTOS function should be called
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_init(void);
/// Start the kernel .It will not return to its calling function in case of success
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_start(void);
/// Get the current kernel state.
/// \return current kernel state \ref k_sched_stat_t .
k_sched_stat_t csi_kernel_get_stat(void);
/* =================================================================================== */
/* scheduler Management Functions */
/* =================================================================================== */
/// Lock the scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t csi_kernel_sched_lock(void);
/// Unlock the scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t csi_kernel_sched_unlock(void);
/// Restore the scheduler lock state.
/// \param[in] lock lock state obtained by \ref csi_kernel_sched_lock or \ref csi_kernel_sched_unlock.
/// \return new lock state (1 - locked, 0 - not locked, error code if negative).
int32_t csi_kernel_sched_restore_lock(int32_t lock);
/// Suspend the scheduler.
/// \return time in ticks, for how long the system can sleep or power-down.
uint32_t csi_kernel_sched_suspend(void);
/// Resume the scheduler.
/// \param[in] sleep_ticks time in ticks for how long the system was in sleep or power-down mode.
void csi_kernel_sched_resume(uint32_t sleep_ticks);
/* =================================================================================== */
/* Task Management Functions */
/* =================================================================================== */
/// Create a task and add it to Active Tasks.
/// \param[in] task task function.
/// \param[in] name the name of task.
/// \param[in] arg pointer that is passed to the task function as start argument.
/// \param[in] prio task priority.
/// \param[in] time_quanta the amount of time (in clock ticks) for the time quanta when round robin is enabled,if Zero, then use FIFO sched
/// \param[in] stack stack base.
/// \param[in] stack_size stack size.
/// \param[in] task_handle reference to a task handle.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_task_new(k_task_entry_t task, const char *name, void *arg,
k_priority_t prio, uint32_t time_quanta,
void *stack, uint32_t stack_size, k_task_handle_t *task_handle);
/// Delete a task.
/// \param[in] task_handle task handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_task_del(k_task_handle_t task_handle);
/// Return the task handle of the current running task.
/// \return task handle for reference by other functions or NULL in case of error.
k_task_handle_t csi_kernel_task_get_cur(void);
/// Get current task state of a task.
/// \param[in] task_handle task handle to operate.
/// \return current task state of the specified task.
k_task_stat_t csi_kernel_task_get_stat(k_task_handle_t task_handle);
/// Change priority of a task.
/// \param[in] task_handle task handle to operate.
/// \param[in] priority new priority value for the task function.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_task_set_prio(k_task_handle_t task_handle, k_priority_t priority);
k_status_t csi_kernel_task_set_lprun(k_task_handle_t task_handle, uint8_t run);
void csi_kernel_lpower_mode(uint8_t enable);
/// Get current priority of a task.
/// \param[in] task_handle task handle to operate.
/// \return current priority value of the specified task.negative indicates error code.
k_priority_t csi_kernel_task_get_prio(k_task_handle_t task_handle);
/// Get name of a task.
/// \param[in] task_handle task handle to operate.
/// \return name of the task.
const char *csi_kernel_task_get_name(k_task_handle_t task_handle);
/// Suspend execution of a task.
/// \param[in] task_handle task handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_task_suspend(k_task_handle_t task_handle);
/// Resume execution of a task.
/// \param[in] task_handle task handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_task_resume(k_task_handle_t task_handle);
/// Terminate execution of a task.
/// \param[in] task_handle task handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_task_terminate(k_task_handle_t task_handle);
void csi_kernel_task_dump(k_task_handle_t task_handle, void* stack);
/// Exit from the calling task.
/// \return none
void csi_kernel_task_exit(void);
/// Pass control to next task that is in state \b READY.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_task_yield(void);
/// Get number of active tasks.
/// \return number of active tasks.
uint32_t csi_kernel_task_get_count(void);
/// Get stack size of a task.
/// \param[in] task_handle task handle to operate.
/// \return stack size in bytes.
uint32_t csi_kernel_task_get_stack_size(k_task_handle_t task_handle);
/// Get available stack space of a thread based on stack watermark recording during execution.
/// \param[in] task_handle task handle to operate.
/// \return remaining stack space in bytes.
uint32_t csi_kernel_task_get_stack_space(k_task_handle_t task_handle);
/// Enumerate active tasks.
/// \param[out] task_array pointer to array for retrieving task handles.
/// \param[in] array_items maximum number of items in array for retrieving task handles.
/// \return number of enumerated tasks.
uint32_t csi_kernel_task_list(k_task_handle_t *task_array, uint32_t array_items);
/// System enter interrupt status.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_intrpt_enter(void);
/// System exit interrupt status.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_intrpt_exit(void);
/* =================================================================================== */
/* Generic time Functions */
/* =================================================================================== */
/// Waits for a time period specified in kernel ticks.
/// \param[in] ticks time ticks value
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_delay(uint32_t ticks);
/// Waits until an absolute time (specified in kernel ticks) is reached.
/// \param[in] ticks absolute time in ticks
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_delay_until(uint64_t ticks);
/// Convert kernel ticks to ms.
/// \param[in] ticks ticks which will be converted to ms
/// \return the ms of the ticks.
uint64_t csi_kernel_tick2ms(uint32_t ticks);
/// Convert ms to kernel ticks.
/// \param[in] ms ms which will be converted to ticks
/// \return the ticks of the ms.
uint64_t csi_kernel_ms2tick(uint32_t ms);
/// Waits for a time period specified in ms.
/// \param[in] ms time to be delayed in ms
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_delay_ms(uint32_t ms);
/// Get kernel ticks.
/// \return kernel ticks number
uint64_t csi_kernel_get_ticks(void);
/// Get the RTOS kernel tick frequency.
/// \return frequency of the kernel tick.
uint32_t csi_kernel_get_tick_freq(void);
/// Get the RTOS kernel system timer frequency.
/// \return frequency of the system timer.
uint32_t csi_kernel_get_systimer_freq(void);
/* =================================================================================== */
/* Timer Management Functions */
/* =================================================================================== */
/// Create and Initialize a timer.
/// \param[in] func start address of a timer call back function.
/// \param[in] type time type, \ref k_timer_type_t.
/// \param[in] arg argument to the timer call back function.
/// \return timer handle for reference by other functions or NULL in case of error.
k_timer_handle_t csi_kernel_timer_new(k_timer_cb_t func, k_timer_type_t type, void *arg);
/// Delete a timer.
/// \param[in] timer_handle timer handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_timer_del(k_timer_handle_t timer_handle);
/// Start or restart a timer.
/// \param[in] timer_handle timer handle to operate.
/// \param[in] ticks time out value in ticks
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_timer_start(k_timer_handle_t timer_handle, uint32_t ticks);
/// Stop a timer.
/// \param[in] timer_handle timer handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_timer_stop(k_timer_handle_t timer_handle);
/// Check if a timer is running.
/// \param[in] timer_handle timer handle to operate.
/// \return \ref k_timer_stat_t.
k_timer_stat_t csi_kernel_timer_get_stat(k_timer_handle_t timer_handle);
/* =================================================================================== */
/* Event Management Functions */
/* =================================================================================== */
/// Create and Initialize an Event Flags object.
/// \return event flags handle for reference by other functions or NULL in case of error.
k_event_handle_t csi_kernel_event_new(void);
/// Delete an Event Flags object.
/// \param[in] ev_handle event flags handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_event_del(k_event_handle_t ev_handle);
/// Set the specified Event Flags.
/// \param[in] ev_handle event flags handle to operate.
/// \param[in] flags specifies the flags that shall be set.
/// \param[out] ret_flags The value of the event after setting.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_event_set(k_event_handle_t ev_handle, uint32_t flags, uint32_t *ret_flags);
/// Clear the specified Event Flags.
/// \param[in] ev_handle event flags handle to operate.
/// \param[in] flags specifies the flags that shall be clear.
/// \param[out] ret_flags event flags before clearing.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_event_clear(k_event_handle_t ev_handle, uint32_t flags, uint32_t *ret_flags);
/// Get the current Event Flags. This function allows the user to know “Who did it!”
/// \param[in] ev_handle event flags handle to operate.
/// \param[out] ret_flags The value of the current event.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_event_get(k_event_handle_t ev_handle, uint32_t *ret_flags);
/// Wait for one or more Event Flags to become signaled.
/// \param[in] ev_handle event flags handle to operate.
/// \param[in] flags specifies the flags to wait for.
/// \param[in] options specifies flags options, \ref k_event_opt_t.
/// \param[in] clr_on_exit 1 - event flags will be cleared before exit, otherwise event flags are not altered
/// \param[out] actl_flags The value of the event at the time either the bits being waited for became set, or the block time expired.
/// \param[in] timeout time out value in ticks if > 0, 0 in case of no time-out, negative in case of wait forever
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_event_wait(k_event_handle_t ev_handle, uint32_t flags,
k_event_opt_t options, uint8_t clr_on_exit,
uint32_t *actl_flags, int32_t timeout);
/* =================================================================================== */
/* Mutex Management Functions */
/* =================================================================================== */
/// Create and Initialize a Mutex object.
/// \return mutex handle for reference by other functions or NULL in case of error.
k_mutex_handle_t csi_kernel_mutex_new(void);
/// Delete a Mutex object.
/// \param[in] mutex_handle mutex handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_mutex_del(k_mutex_handle_t mutex_handle);
/// Acquire a Mutex or timeout if it is locked.
/// \param[in] mutex_handle mutex handle to operate.
/// \param[in] timeout time out value in ticks if > 0, 0 in case of no time-out, negative in case of wait forever
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_mutex_lock(k_mutex_handle_t mutex_handle, int32_t timeout, uint32_t lr);
/// Release a Mutex that was acquired by \ref csi_kernel_mutex_new.
/// \param[in] mutex_handle mutex handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_mutex_unlock(k_mutex_handle_t mutex_handle);
/// Get Thread which owns a Mutex object.
/// \param[in] mutex_handle mutex handle to operate.
/// \return task handle or NULL when mutex was not acquired.
k_task_handle_t csi_kernel_mutex_get_owner(k_mutex_handle_t mutex_handle);
/* =================================================================================== */
/* Semaphore Management Functions */
/* =================================================================================== */
/// Create and Initialize a Semaphore object.
/// \param[in] max_count maximum number of available tokens.
/// \param[in] initial_count initial number of available tokens.
/// \return semaphore handle for reference by other functions or NULL in case of error.
k_sem_handle_t csi_kernel_sem_new(int32_t max_count, int32_t initial_count);
/// Delete a Semaphore object.
/// \param[in] sem_handle semaphore handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_sem_del(k_sem_handle_t sem_handle);
/// Acquire a Semaphore token or timeout if no tokens are available.
/// \param[in] sem_handle semaphore handle to operate.
/// \param[in] timeout time out value in ticks if > 0, 0 in case of no time-out, negative in case of wait forever
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_sem_wait(k_sem_handle_t sem_handle, int32_t timeout);
/// Release a Semaphore token that was acquired by \ref csi_kernel_sem_wait.
/// \param[in] sem_handle semaphore handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_sem_post(k_sem_handle_t sem_handle);
/// Get current Semaphore token count.
/// \param[in] sem_handle semaphore handle to operate.
/// \return number of tokens available. negative indicates error code.
int32_t csi_kernel_sem_get_count(k_sem_handle_t sem_handle);
/* =================================================================================== */
/* Memory Pool Management Functions */
/* =================================================================================== */
/// Create and Initialize a Memory Pool object.
/// \param[in] p_addr memory block base address.
/// \param[in] block_count maximum number of memory blocks in memory pool.
/// \param[in] block_size memory block size in bytes.
/// \return memory pool handle for reference by other functions or NULL in case of error.
k_mpool_handle_t csi_kernel_mpool_new(void *p_addr, int32_t block_count, int32_t block_size);
/// Delete a Memory Pool object.
/// \param[in] mp_handle memory pool handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_mpool_del(k_mpool_handle_t mp_handle);
/// Allocate a memory block from a Memory Pool.
/// \param[in] mp_handle memory pool handle to operate.
/// \param[in] timeout time out value in ticks if > 0, 0 in case of no time-out, negative in case of wait forever
/// \return address of the allocated memory block or NULL in case of no memory is available.
void *csi_kernel_mpool_alloc(k_mpool_handle_t mp_handle, int32_t timeout);
/// Return an allocated memory block back to a Memory Pool.
/// \param[in] mp_handle memory pool handle to operate.
/// \param[in] block address of the allocated memory block to be returned to the memory pool.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_mpool_free(k_mpool_handle_t mp_handle, void *block);
/// Get number of memory blocks used in a Memory Pool.
/// \param[in] mp_handle memory pool handle to operate.
/// \return number of memory blocks used. negative indicates error code.
int32_t csi_kernel_mpool_get_count(k_mpool_handle_t mp_handle);
/// Get maximum number of memory blocks in a Memory Pool.
/// \param[in] mp_handle memory pool handle to operate.
/// \return maximum number of memory blocks.
uint32_t csi_kernel_mpool_get_capacity(k_mpool_handle_t mp_handle);
/// Get memory block size in a Memory Pool.
/// \param[in] mp_handle memory pool handle to operate.
/// \return memory block size in bytes.
uint32_t csi_kernel_mpool_get_block_size(k_mpool_handle_t mp_handle);
/* =================================================================================== */
/* Message Queue Management Functions */
/* =================================================================================== */
/// Create and Initialize a Message Queue object.
/// \param[in] msg_count maximum number of messages in queue.
/// \param[in] msg_size maximum message size in bytes.
/// \return message queue handle for reference by other functions or NULL in case of error.
k_msgq_handle_t csi_kernel_msgq_new(int32_t msg_count, int32_t msg_size);
/// Delete a Message Queue object.
/// \param[in] mq_handle message queue handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_msgq_del(k_msgq_handle_t mq_handle);
/// Put a Message into a Queue or timeout if Queue is full.
/// \param[in] mq_handle message queue handle to operate.
/// \param[in] msg_ptr pointer to buffer with message to put into a queue.
/// \param[in] front_or_back specify this msg to be put to front or back. 1 - front, 0 -back
/// \param[in] timeout time out value in ticks if > 0, 0 in case of no time-out, negative in case of wait forever
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_msgq_put(k_msgq_handle_t mq_handle, const void *msg_ptr, uint8_t front_or_back, int32_t timeout);
/// Get a Message from a Queue or timeout if Queue is empty.
/// \param[in] mq_handle message queue handle to operate.
/// \param[out] msg_ptr pointer to buffer for message to get from a queue.
/// \param[in] timeout time out value in ticks if > 0, 0 in case of no time-out, negative in case of wait forever
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_msgq_get(k_msgq_handle_t mq_handle, void *msg_ptr, int32_t timeout);
/// Get number of queued messages in a message queue.
/// \param[in] mq_handle message queue handle to operate.
/// \return number of queued messages.negative indicates error code.
int32_t csi_kernel_msgq_get_count(k_msgq_handle_t mq_handle);
/// Get maximum number of messages in a message queue.
/// \param[in] mq_handle message queue handle to operate.
/// \return maximum number of messages.
uint32_t csi_kernel_msgq_get_capacity(k_msgq_handle_t mq_handle);
/// Get maximum message size in a message queue.
/// \param[in] mq_handle message queue handle to operate.
/// \return maximum message size in bytes.
uint32_t csi_kernel_msgq_get_msg_size(k_msgq_handle_t mq_handle);
/// Reset a Message Queue to initial empty state.
/// \param[in] mq_handle message queue handle to operate.
/// \return execution status code. \ref k_status_t
k_status_t csi_kernel_msgq_flush(k_msgq_handle_t mq_handle);
/* =================================================================================== */
/* Heap Management Functions */
/* =================================================================================== */
/// Allocates size bytes and returns a pointer to the allocated memory.
/// \param[in] size Allocates size bytes.
/// \param[in] caller the function who call this interface or NULL.
/// \return a pointer to the allocated memory.
void *csi_kernel_malloc(int32_t size, void *caller);
/// Frees the memory space pointed to by ptr
/// \param[in] ptr a pointer to memory block, return by csi_kernel_malloc or csi_kernel_realloc.
/// \param[in] caller the function who call this interface or NULL.
/// \return void
void csi_kernel_free(void *ptr, void *caller);
/// Changes the size of the memory block pointed to by ptr to size bytes
/// \param[in] ptr a pointer to memory block, return by csi_kernel_malloc or csi_kernel_realloc.
/// \param[in] size Allocates size bytes.
/// \param[in] caller the function who call this interface or NULL.
/// \return a pointer to the allocated memory.
void *csi_kernel_realloc(void *ptr, int32_t size, void *caller);
/// Get csi memory used info.
/// \param[out] total the total memory can be use.
/// \param[out] used the used memory by malloc.
/// \param[out] free the free memory can be use.
/// \param[out] peak the peak memory used.
/// \return execution status code. \ref k_status_t.
k_status_t csi_kernel_get_mminfo(int32_t *total, int32_t *used, int32_t *free, int32_t *peak);
/// Dump csi memory .
/// \param void
/// \return execution status code. \ref k_status_t.
k_status_t csi_kernel_mm_dump(void);
void csi_kernel_blklist_suspend(void *hdl, k_task_handle_t task_hdl);
void csi_kernel_blklist_wakeup(void *hdl);
void *csi_kernel_blklist_new();
void csi_kernel_blklist_del(void *hdl);
uint64_t krhino_curr_nanosec(void);
#ifdef __cplusplus
}
#endif
#endif // _CSI_KERNEL_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#include "csi_core.h"
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
temp &= 0xfffffffc;
stk = (cpu_stack_t *)temp;
*(--stk) = (uint32_t)0x28282828L; /* R28 */
*(--stk) = (uint32_t)entry; /* entry point */
*(--stk) = (uint32_t)0x80000140L; /* PSR */
*(--stk) = (uint32_t)krhino_task_deathbed; /* R15 (LR) */
*(--stk) = (uint32_t)0x13131313L; /* R13 */
*(--stk) = (uint32_t)0x12121212L; /* R12 */
*(--stk) = (uint32_t)0x11111111L; /* R11 */
*(--stk) = (uint32_t)0x10101010L; /* R10 */
*(--stk) = (uint32_t)0x09090909L; /* R9 */
*(--stk) = (uint32_t)0x00000000L; /* R8 */
*(--stk) = (uint32_t)0x07070707L; /* R7 */
*(--stk) = (uint32_t)0x06060606L; /* R6 */
*(--stk) = (uint32_t)0x05050505L; /* R5 */
*(--stk) = (uint32_t)0x04040404L; /* R4 */
*(--stk) = (uint32_t)0x03030303L; /* R3 */
*(--stk) = (uint32_t)0x02020202L; /* R2 */
*(--stk) = (uint32_t)0x01010101L; /* R1 */
*(--stk) = (uint32_t)arg; /* R0 : argument */
return stk;
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_config.h>
#define VIC_TSPDR 0XE000EC08
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_task_sched_stats_get
.extern krhino_stack_ovf_check
/******************************************************************************
* EXPORT FUNCTIONS
******************************************************************************/
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global tspend_handler
/******************************************************************************
* EQUATES
******************************************************************************/
/******************************************************************************
* CODE GENERATION DIRECTIVES
******************************************************************************/
.text
.align 2
/******************************************************************************
* Functions:
* size_t cpu_intrpt_save(void);
* void cpu_intrpt_restore(size_t psr);
******************************************************************************/
.type cpu_intrpt_save, %function
cpu_intrpt_save:
mfcr r0, psr
psrclr ie
rts
.type cpu_intrpt_restore, %function
cpu_intrpt_restore:
mtcr r0, psr
btsti r0, 6
bf .Lret
lrw r1, 0x00ff0000
and r1, r0
cmpnei r1, 0
bt .Lret
lrw r1, VIC_TSPDR
.Lloop:
ldw r2, (r1)
btsti r2, 0
bt .Lloop
.Lret:
rts
/******************************************************************************
* Functions:
* void cpu_intrpt_switch(void);
* void cpu_task_switch(void);
******************************************************************************/
.type cpu_task_switch, %function
cpu_task_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
.type cpu_intrpt_switch, %function
cpu_intrpt_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
/******************************************************************************
* Functions:
* void cpu_first_task_start(void);
******************************************************************************/
.type cpu_first_task_start, %function
cpu_first_task_start:
psrclr ie
jbr __tspend_handler_nosave
/******************************************************************************
* Functions:
* void __task_switch(void);
******************************************************************************/
.type tspend_handler, %function
tspend_handler:
#ifdef __CK803__
subi sp, 72
#else
subi sp, 68
#endif
stm r0-r13, (sp)
stw r15, (sp, 56)
mfcr r0, epsr
stw r0, (sp, 60)
mfcr r0, epc
stw r0, (sp, 64)
#ifdef __CK803__
stw r28, (sp, 68)
#endif
lrw r0, g_sched_lock
ldb r1, (r0)
cmpnei r1, 0
bt .Lnot_switch
lrw r2, g_active_task
ldw r2, (r2)
stw sp, (r2)
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
jbsr krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
jbsr krhino_task_sched_stats_get
#endif
__tspend_handler_nosave:
lrw r4, g_active_task
lrw r5, g_preferred_ready_task
ldw r6, (r5)
stw r6, (r4)
#ifdef CONFIG_STACK_GUARD
jbsr csky_set_stackbound
#endif
ldw sp, (r6)
#ifdef CONFIG_STACK_GUARD
mfcr r3, cr<0, 4>
bseti r3, 0
bseti r3, 1
mtcr r3, cr<0, 4>
#endif
.Lnot_switch:
#ifdef __CK803__
ldw r28, (sp, 68)
#endif
ldw r0, (sp, 64)
mtcr r0, epc
ldw r0, (sp, 60)
mtcr r0, epsr
ldw r15, (sp, 56)
ldm r0-r13, (sp)
#ifdef __CK803__
addi sp, 72
#else
addi sp, 68
#endif
rte

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#include <k_config.h>
#if (RHINO_CONFIG_STACK_OVF_CHECK_HW != 0)
void cpu_intrpt_stack_protect(void)
{
}
void task_stack_crash_warning(void)
{
printf("****The task stack base has been broken !!!****\n");
}
void cpu_task_stack_protect(cpu_stack_t *base, size_t size)
{
uint32_t base_addr = (uint32_t)base;
int num_return = wp_register(base_addr, AWATCH, task_stack_crash_warning);
if (num_return == 1) {
wp_enable(1);
} else if (num_return == 2 || num_return == -1) {
wp_unregister(1);
int number_tmp = wp_register(base_addr, AWATCH, task_stack_crash_warning);
if (number_tmp == 1){
wp_enable(1);
}
}
}
#endif
#ifdef CONFIG_STACK_GUARD
void csky_set_stackbound(void)
{
uint32_t size;
cpu_stack_t *base;
ktask_t *get_task = (ktask_t *)g_active_task;
base = get_task->task_stack_base;
size = get_task->stack_size;
asm volatile(
"mfcr r9, cr<0, 4>\n\r"
"bclri r9, 0\n\r"
"mtcr r9, cr<0, 4>\n\r"
"mtcr %0, cr<2, 4>\n\r"
"lsli %1, %1, 2\n\r"
"add %0, %0, %1\n\r"
"mtcr %0, cr<1, 4>\n\r"
::"r"(base), "r"(size):"r9");
}
int stack_guard_save(void)
{
int value;
asm volatile(
"mfcr %0, cr<0, 4>\n\t"
"mov r0, %0\n\t"
"bclri r0, 0\n\t"
"mtcr r0, cr<0, 4>\n\t"
:"=r"(value)
::"r0");
return value;
}
void stack_guard_restore(int value)
{
asm volatile(
"mtcr %0, cr<0, 4>\n\t"
::"r"(value):
);
}
#endif

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#undef PSR_SP
#define PSR_SP (1UL << 29)
static ktask_t *tee_caller_task = NULL;
static inline uint32_t getcurrentpsr(void)
{
uint32_t flags;
__asm__ __volatile__(
"mfcr %0, psr \n"
:"=r"(flags)
:
:
);
return flags;
}
static inline void clear_psr_sp(void)
{
__asm__ __volatile__ (
"mfcr r0, psr \n"
"bclri r0, 29 \n"
"mtcr r0, psr \n"
:
:
:"r0"
);
}
static inline void set_psr_sp(void)
{
__asm__ __volatile__ (
"mfcr r0, psr \n"
"bseti r0, 29 \n"
"mtcr r0, psr \n"
:
:
:"r0"
);
}
void csky_get_tee_caller_task(void)
{
uint32_t temp_psr;
temp_psr = getcurrentpsr();
if (temp_psr & PSR_SP) {
tee_caller_task = (tee_caller_task == NULL) ? g_active_task[cpu_cur_get()] : tee_caller_task;
}
}
void csky_deal_tee_caller_task(void)
{
uint32_t temp_psr;
temp_psr = getcurrentpsr();
if (temp_psr & PSR_SP) {
if (tee_caller_task != NULL) {
if (tee_caller_task == g_active_task[cpu_cur_get()]) {
tee_caller_task = NULL;
} else {
clear_psr_sp();
}
}
} else {
if (tee_caller_task != NULL) {
if (tee_caller_task == g_active_task[cpu_cur_get()]) {
tee_caller_task = NULL;
set_psr_sp();
}
}
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <csi_config.h>
#ifdef CONFIG_BACKTRACE
#include <stdio.h>
#include <stdlib.h>
#include <backtrace.h>
#define BT_SIZE 40
void *g_bt_buffer[BT_SIZE];
#define BT_STACK_SIZE 600
int g_bt_stack[BT_STACK_SIZE / 4];
char *g_dumpbuf = NULL;
int g_dump_len = 0;
int g_dump_max = 0;
void dump_backtrace(void)
{
int i;
int nptr;
g_dump_len = 0;
nptr = backtrace(g_bt_buffer, BT_SIZE);
if (nptr <= 0) {
printf("error: backtrace_symbols\n");
return;
}
for (i = 0; i < nptr; i++) {
if (g_dumpbuf == NULL) {
printf("[<%p>]\n", g_bt_buffer[i]);
} else {
g_dump_len += snprintf(&g_dumpbuf[g_dump_len], g_dump_max - g_dump_len, "[<%p>]\n", g_bt_buffer[i]);
if (g_dump_len >= g_dump_max) {
printf("error, user buffer no space \n");
return;
}
}
}
}
void __attribute__((naked))csky_show_backtrace(void *stack)
{
asm volatile(
"subi sp, 68\n\t"
"stm r0-r13, (sp)\n\t"
"mtcr sp, cr<14, 1>\n\t"
"stw r15, (sp, 56)\n\t"
"mov sp, %0\n\t"
"lrw r0, g_bt_stack\n\t"
"mov r1, sp\n\t"
"sub r1, %1\n\t"
"mov r2, %1\n\t"
"mov r4, %1\n\t"
"jbsr memcpy\n\t"
"ldw r8, (sp, 32)\n\t"
"ldw r15, (sp, 64)\n\t"
"subi sp, 16\n\t"
"stw r8, (sp, 0)\n\t"
"stw r15, (sp, 4)\n\t"
"mov r8, sp\n\t"
"jbsr dump_backtrace\n\t"
"addi sp, 16\n\t"
"lrw r1, g_bt_stack\n\t"
"mov r0, sp\n\t"
"sub r0, r4\n\t"
"mov r2, r4\n\t"
"jbsr memcpy\n\t"
"mfcr sp, cr<14, 1>\n\t"
"ldw r15, (sp, 56)\n\t"
"ldm r0-r13, (sp)\n\t"
"addi sp, 68\n\t"
"jmp r15\n\t"
::"r"(stack), "r"(BT_STACK_SIZE):);
}
int csky_task_backtrace(void *stack, void *buf, int len)
{
g_dumpbuf = buf;
g_dump_max = len;
csky_show_backtrace(stack);
return g_dump_len;
}
#endif

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <csi_core.h>
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
temp &= 0xfffffffc;
stk = (cpu_stack_t *)temp;
*(--stk) = (uint32_t)entry; /* entry point */
*(--stk) = (uint32_t)0x80000140L; /* PSR */
*(--stk) = (uint32_t)krhino_task_deathbed; /* R15 (LR) */
*(--stk) = (uint32_t)0x13131313L; /* R13 */
*(--stk) = (uint32_t)0x12121212L; /* R12 */
*(--stk) = (uint32_t)0x11111111L; /* R11 */
*(--stk) = (uint32_t)0x10101010L; /* R10 */
*(--stk) = (uint32_t)0x09090909L; /* R9 */
*(--stk) = (uint32_t)0x00000000L; /* R8 */
*(--stk) = (uint32_t)0x07070707L; /* R7 */
*(--stk) = (uint32_t)0x06060606L; /* R6 */
*(--stk) = (uint32_t)0x05050505L; /* R5 */
*(--stk) = (uint32_t)0x04040404L; /* R4 */
*(--stk) = (uint32_t)0x03030303L; /* R3 */
*(--stk) = (uint32_t)0x02020202L; /* R2 */
*(--stk) = (uint32_t)0x01010101L; /* R1 */
*(--stk) = (uint32_t)arg; /* R0 : argument */
return stk;
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_config.h>
#define VIC_TSPDR 0XE000EC08
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_task_sched_stats_get
.extern krhino_stack_ovf_check
/******************************************************************************
* EXPORT FUNCTIONS
******************************************************************************/
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global tspend_handler
/******************************************************************************
* EQUATES
******************************************************************************/
/******************************************************************************
* CODE GENERATION DIRECTIVES
******************************************************************************/
.text
.align 2
/******************************************************************************
* Functions:
* size_t cpu_intrpt_save(void);
* void cpu_intrpt_restore(size_t psr);
******************************************************************************/
.type cpu_intrpt_save, %function
cpu_intrpt_save:
mfcr r0, psr
psrclr ie
rts
.type cpu_intrpt_restore, %function
cpu_intrpt_restore:
mtcr r0, psr
btsti r0, 6
bf .Lret
lrw r1, 0x00ff0000
and r1, r0
cmpnei r1, 0
bt .Lret
lrw r1, VIC_TSPDR
.Lloop:
ldw r2, (r1)
btsti r2, 0
bt .Lloop
.Lret:
rts
/******************************************************************************
* Functions:
* void cpu_intrpt_switch(void);
* void cpu_task_switch(void);
******************************************************************************/
.type cpu_task_switch, %function
cpu_task_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
.type cpu_intrpt_switch, %function
cpu_intrpt_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
/******************************************************************************
* Functions:
* void cpu_first_task_start(void);
******************************************************************************/
.type cpu_first_task_start, %function
cpu_first_task_start:
psrclr ie
jbr __tspend_handler_nosave
/******************************************************************************
* Functions:
* void __task_switch(void);
******************************************************************************/
.type tspend_handler, %function
tspend_handler:
#ifdef __CK803__
subi sp, 72
#else
subi sp, 68
#endif
stm r0-r13, (sp)
stw r15, (sp, 56)
mfcr r0, epsr
stw r0, (sp, 60)
mfcr r0, epc
stw r0, (sp, 64)
#ifdef __CK803__
stw r28, (sp, 68)
#endif
lrw r0, g_sched_lock
ldb r1, (r0)
cmpnei r1, 0
bt .Lnot_switch
lrw r2, g_active_task
ldw r2, (r2)
stw sp, (r2)
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
jbsr krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
jbsr krhino_task_sched_stats_get
#endif
__tspend_handler_nosave:
lrw r4, g_active_task
lrw r5, g_preferred_ready_task
ldw r6, (r5)
stw r6, (r4)
#ifdef CONFIG_STACK_GUARD
jbsr csky_set_stackbound
#endif
ldw sp, (r6)
#ifdef CONFIG_STACK_GUARD
mfcr r3, cr<0, 4>
bseti r3, 0
bseti r3, 1
mtcr r3, cr<0, 4>
#endif
.Lnot_switch:
#ifdef __CK803__
ldw r28, (sp, 68)
#endif
ldw r0, (sp, 64)
mtcr r0, epc
ldw r0, (sp, 60)
mtcr r0, epsr
ldw r15, (sp, 56)
ldm r0-r13, (sp)
#ifdef __CK803__
addi sp, 72
#else
addi sp, 68
#endif
rte

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#include <core_804.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
temp &= 0xFFFFFFFCUL;
stk = (cpu_stack_t *)temp;
*(--stk) = (uint32_t)entry; /* entry point */
*(--stk) = (uint32_t)0x80000340L; /* PSR */
*(--stk) = (uint32_t)0x31313131L; /* R31 */
*(--stk) = (uint32_t)0x30303030L; /* R30 */
*(--stk) = (uint32_t)0x29292929L; /* R29 */
*(--stk) = (uint32_t)0x28282828L; /* R28 */
*(--stk) = (uint32_t)0x27272727L; /* R27 */
*(--stk) = (uint32_t)0x26262626L; /* R26 */
*(--stk) = (uint32_t)0x25252525L; /* R25 */
*(--stk) = (uint32_t)0x24242424L; /* R24 */
*(--stk) = (uint32_t)0x23232323L; /* R23 */
*(--stk) = (uint32_t)0x22222222L; /* R22 */
*(--stk) = (uint32_t)0x21212121L; /* R21 */
*(--stk) = (uint32_t)0x20202020L; /* R20 */
*(--stk) = (uint32_t)0x19191919L; /* R19 */
*(--stk) = (uint32_t)0x18181818L; /* R18 */
*(--stk) = (uint32_t)0x17171717L; /* R17 */
*(--stk) = (uint32_t)0x16161616L; /* R16 */
*(--stk) = (uint32_t)krhino_task_deathbed; /* R15 (LR) */
*(--stk) = (uint32_t)0x13131313L; /* R13 */
*(--stk) = (uint32_t)0x12121212L; /* R12 */
*(--stk) = (uint32_t)0x11111111L; /* R11 */
*(--stk) = (uint32_t)0x10101010L; /* R10 */
*(--stk) = (uint32_t)0x09090909L; /* R9 */
*(--stk) = (uint32_t)0x00000000L; /* R8 */
*(--stk) = (uint32_t)0x07070707L; /* R7 */
*(--stk) = (uint32_t)0x06060606L; /* R6 */
*(--stk) = (uint32_t)0x05050505L; /* R5 */
*(--stk) = (uint32_t)0x04040404L; /* R4 */
*(--stk) = (uint32_t)0x03030303L; /* R3 */
*(--stk) = (uint32_t)0x02020202L; /* R2 */
*(--stk) = (uint32_t)0x01010101L; /* R1 */
*(--stk) = (uint32_t)arg; /* R0 : argument */
return stk;
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_config.h>
#define VIC_TSPDR 0XE000EC08
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_task_sched_stats_get
.extern krhino_stack_ovf_check
/******************************************************************************
* EXPORT FUNCTIONS
******************************************************************************/
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global tspend_handler
/******************************************************************************
* EQUATES
******************************************************************************/
/******************************************************************************
* CODE GENERATION DIRECTIVES
******************************************************************************/
.text
.align 2
/******************************************************************************
* Functions:
* size_t cpu_intrpt_save(void);
* void cpu_intrpt_restore(size_t psr);
******************************************************************************/
.type cpu_intrpt_save, %function
cpu_intrpt_save:
mfcr r0, psr
psrclr ie
rts
.type cpu_intrpt_restore, %function
cpu_intrpt_restore:
mtcr r0, psr
rts
/******************************************************************************
* Functions:
* void cpu_intrpt_switch(void);
* void cpu_task_switch(void);
******************************************************************************/
.type cpu_task_switch, %function
cpu_task_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
.type cpu_intrpt_switch, %function
cpu_intrpt_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
/******************************************************************************
* Functions:
* void cpu_first_task_start(void);
******************************************************************************/
.type cpu_first_task_start, %function
cpu_first_task_start:
psrclr ie
jbr __tspend_handler_nosave
/******************************************************************************
* Functions:
* void __task_switch(void);
******************************************************************************/
.type tspend_handler, %function
tspend_handler:
subi sp, 132
stm r0-r13, (sp)
stw r15, (sp, 56)
addi r0, sp, 60
stm r16-r31, (r0)
mfcr r1, epsr
stw r1, (r0, 64)
mfcr r1, epc
stw r1, (r0, 68)
lrw r2, g_active_task
ldw r2, (r2)
stw sp, (r2)
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
jbsr krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
jbsr krhino_task_sched_stats_get
#endif
__tspend_handler_nosave:
lrw r4, g_active_task
lrw r5, g_preferred_ready_task
ldw r6, (r5)
stw r6, (r4)
#ifdef CONFIG_STACK_GUARD
jbsr csky_set_stackbound
#endif
ldw sp, (r6)
#ifdef CONFIG_STACK_GUARD
mfcr r3, cr<0, 4>
bseti r3, 0
bseti r3, 1
mtcr r3, cr<0, 4>
#endif
ldw r0, (sp, 128)
mtcr r0, epc
ldw r0, (sp, 124)
mtcr r0, epsr
ldm r0-r13, (sp)
ldw r15, (sp, 56)
addi sp, 60
ldm r16-r31, (sp)
addi sp, 72
rte

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#include <core_804.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
temp &= 0xFFFFFFFCUL;
stk = (cpu_stack_t *)temp;
*(--stk) = (uint32_t)entry; /* Entry Point */
*(--stk) = (uint32_t)0x80000340L; /* PSR */
*(--stk) = (uint32_t)0x12345678L; /* VR15 */
*(--stk) = (uint32_t)0x12345678L; /* VR14 */
*(--stk) = (uint32_t)0x12345678L; /* VR13 */
*(--stk) = (uint32_t)0x12345678L; /* VR12 */
*(--stk) = (uint32_t)0x12345678L; /* VR11 */
*(--stk) = (uint32_t)0x12345678L; /* VR10 */
*(--stk) = (uint32_t)0x12345678L; /* VR9 */
*(--stk) = (uint32_t)0x12345678L; /* VR8 */
*(--stk) = (uint32_t)0x12345678L; /* VR7 */
*(--stk) = (uint32_t)0x12345678L; /* VR6 */
*(--stk) = (uint32_t)0x12345678L; /* VR5 */
*(--stk) = (uint32_t)0x12345678L; /* VR4 */
*(--stk) = (uint32_t)0x12345678L; /* VR3 */
*(--stk) = (uint32_t)0x12345678L; /* VR2 */
*(--stk) = (uint32_t)0x12345678L; /* VR1 */
*(--stk) = (uint32_t)0x12345678L; /* VR0 */
*(--stk) = (uint32_t)0x31313131L; /* R31 */
*(--stk) = (uint32_t)0x30303030L; /* R30 */
*(--stk) = (uint32_t)0x29292929L; /* R29 */
*(--stk) = (uint32_t)0x28282828L; /* R28 */
*(--stk) = (uint32_t)0x27272727L; /* R27 */
*(--stk) = (uint32_t)0x26262626L; /* R26 */
*(--stk) = (uint32_t)0x25252525L; /* R25 */
*(--stk) = (uint32_t)0x24242424L; /* R24 */
*(--stk) = (uint32_t)0x23232323L; /* R23 */
*(--stk) = (uint32_t)0x22222222L; /* R22 */
*(--stk) = (uint32_t)0x21212121L; /* R21 */
*(--stk) = (uint32_t)0x20202020L; /* R20 */
*(--stk) = (uint32_t)0x19191919L; /* R19 */
*(--stk) = (uint32_t)0x18181818L; /* R18 */
*(--stk) = (uint32_t)0x17171717L; /* R17 */
*(--stk) = (uint32_t)0x16161616L; /* R16 */
*(--stk) = (uint32_t)krhino_task_deathbed; /* R15 (LR) */
*(--stk) = (uint32_t)0x13131313L; /* R13 */
*(--stk) = (uint32_t)0x12121212L; /* R12 */
*(--stk) = (uint32_t)0x11111111L; /* R11 */
*(--stk) = (uint32_t)0x10101010L; /* R10 */
*(--stk) = (uint32_t)0x09090909L; /* R9 */
*(--stk) = (uint32_t)0x00000000L; /* R8 */
*(--stk) = (uint32_t)0x07070707L; /* R7 */
*(--stk) = (uint32_t)0x06060606L; /* R6 */
*(--stk) = (uint32_t)0x05050505L; /* R5 */
*(--stk) = (uint32_t)0x04040404L; /* R4 */
*(--stk) = (uint32_t)0x03030303L; /* R3 */
*(--stk) = (uint32_t)0x02020202L; /* R2 */
*(--stk) = (uint32_t)0x01010101L; /* R1 */
*(--stk) = (uint32_t)arg; /* R0 : Argument */
return stk;
}

View File

@@ -0,0 +1,157 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_config.h>
#define VIC_TSPDR 0XE000EC08
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_task_sched_stats_get
.extern krhino_stack_ovf_check
/******************************************************************************
* EXPORT FUNCTIONS
******************************************************************************/
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global tspend_handler
/******************************************************************************
* EQUATES
******************************************************************************/
/******************************************************************************
* CODE GENERATION DIRECTIVES
******************************************************************************/
.text
.align 2
/******************************************************************************
* Functions:
* size_t cpu_intrpt_save(void);
* void cpu_intrpt_restore(size_t psr);
******************************************************************************/
.type cpu_intrpt_save, %function
cpu_intrpt_save:
mfcr r0, psr
psrclr ie
rts
.type cpu_intrpt_restore, %function
cpu_intrpt_restore:
mtcr r0, psr
rts
/******************************************************************************
* Functions:
* void cpu_intrpt_switch(void);
* void cpu_task_switch(void);
******************************************************************************/
.type cpu_task_switch, %function
cpu_task_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
.type cpu_intrpt_switch, %function
cpu_intrpt_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
/******************************************************************************
* Functions:
* void cpu_first_task_start(void);
******************************************************************************/
.type cpu_first_task_start, %function
cpu_first_task_start:
psrclr ie
jbr __tspend_handler_nosave
/******************************************************************************
* Functions:
* void __task_switch(void);
******************************************************************************/
.type tspend_handler, %function
tspend_handler:
subi sp, 196
stm r0-r13, (sp)
stw r15, (sp, 56)
addi r0, sp, 60
stm r16-r31, (r0)
addi r0, 64
fstms vr0-vr15, (r0)
mfcr r1, epsr
stw r1, (r0, 64)
mfcr r1, epc
stw r1, (r0, 68)
lrw r2, g_active_task
ldw r2, (r2)
stw sp, (r2)
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
jbsr krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
jbsr krhino_task_sched_stats_get
#endif
__tspend_handler_nosave:
lrw r4, g_active_task
lrw r5, g_preferred_ready_task
ldw r6, (r5)
stw r6, (r4)
#ifdef CONFIG_STACK_GUARD
jbsr csky_set_stackbound
#endif
ldw sp, (r6)
#ifdef CONFIG_STACK_GUARD
mfcr r3, cr<0, 4>
bseti r3, 0
bseti r3, 1
mtcr r3, cr<0, 4>
#endif
ldw r0, (sp, 192)
mtcr r0, epc
ldw r0, (sp, 188)
mtcr r0, epsr
ldm r0-r13, (sp)
ldw r15, (sp, 56)
addi sp, 60
ldm r16-r31, (sp)
addi sp, 64
fldms vr0-vr15, (sp)
addi sp, 72
rte

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CONFIG_H
#define CONFIG_H
#include <csi_config.h>
#if defined (__CSKY_DSP__) || defined(__CSKY_DSPV2__) || defined(__CSKY_VDSPV2__) || defined (__CSKY_HARD_FLOAT__) || defined(__C807__)
#define CSK_CPU_STACK_EXTRAL 68
#elif defined (__I805__)
#define CSK_CPU_STACK_EXTRAL 260
#else
#define CSK_CPU_STACK_EXTRAL 0
#endif
#define RHINO_CONFIG_STD_MALLOC 1
#define K_MM_STATISTIC 1
/* chip level conf */
#define RHINO_CONFIG_LITTLE_ENDIAN 1
#define RHINO_CONFIG_CPU_STACK_DOWN 1
/* kernel feature conf */
#define RHINO_CONFIG_SEM 1
#define RHINO_CONFIG_QUEUE 1
#define RHINO_CONFIG_TASK_SEM 1
#define RHINO_CONFIG_EVENT_FLAG 1
#define RHINO_CONFIG_TIMER 1
#define RHINO_CONFIG_BUF_QUEUE 1
#define RHINO_CONFIG_MM_BLK 1
#define RHINO_CONFIG_MM_TLF_BLK_SIZE 4096
#ifdef CONFIG_DEBUG_MM
#define RHINO_CONFIG_MM_DEBUG 1
#define RHINO_CONFIG_GCC_RETADDR 1
#else
#define RHINO_CONFIG_MM_DEBUG 0
#define RHINO_CONFIG_GCC_RETADDR 0
#endif
#define RHINO_CONFIG_KOBJ_SET 1
#define RHINO_CONFIG_RINGBUF_VENDOR 0
/* kernel dynamic tick conf */
#ifdef CONFIG_KERNEL_PWR_MGMT
#define RHINO_CONFIG_CPU_PWR_MGMT 1
#else
#define RHINO_CONFIG_CPU_PWR_MGMT 0
#endif
/*
#define RHINO_CONFIG_TICKS_PER_SECOND 100
#define RHINO_CONFIG_TICK_HEAD_ARRAY 1
#define RHINO_CONFIG_SCHED_RR 0
#define RHINO_CONFIG_TIMER_RATE 1
#define RHINO_CONFIG_TIMER 1
*/
/* kernel task conf */
#define RHINO_CONFIG_TASK_SUSPEND 1
#define RHINO_CONFIG_TASK_INFO 0
#define RHINO_CONFIG_TASK_DEL 1
#define RHINO_CONFIG_TASK_WAIT_ABORT 0
#define RHINO_CONFIG_TASK_STACK_OVF_CHECK 1
#define RHINO_CONFIG_SCHED_RR 1
#define RHINO_CONFIG_TIME_SLICE_DEFAULT 5
#define RHINO_CONFIG_PRI_MAX 62
#define RHINO_CONFIG_USER_PRI_MAX (RHINO_CONFIG_PRI_MAX - 2)
#define RHINO_CONFIG_MM_REGION_MUTEX 0
/* kernel workqueue conf */
#ifdef CONFIG_KERNEL_WORKQUEUE
#define RHINO_CONFIG_WORKQUEUE 1
#else
#define RHINO_CONFIG_WORKQUEUE 0
#endif
/* kernel timer&tick conf */
#define RHINO_CONFIG_HW_COUNT 0
#define RHINO_CONFIG_TICK_TASK 1
#if (RHINO_CONFIG_TICK_TASK > 0)
#define RHINO_CONFIG_TICK_TASK_STACK_SIZE (50 + CSK_CPU_STACK_EXTRAL)
#define RHINO_CONFIG_TICK_TASK_PRI 1
#endif
#ifdef CONFIG_SYSTICK_HZ
#define RHINO_CONFIG_TICKS_PER_SECOND CONFIG_SYSTICK_HZ
#else
#define RHINO_CONFIG_TICKS_PER_SECOND 100
#endif
/* must be 2^n size!, such as 1, 2, 4, 8, 16,32, etc....... */
#define RHINO_CONFIG_TICK_HEAD_ARRAY 1
#ifdef CONFIG_TIMER_TASK_STACK_SIZE
#define RHINO_CONFIG_TIMER_TASK_STACK_SIZE (CONFIG_TIMER_TASK_STACK_SIZE + CSK_CPU_STACK_EXTRAL)
#else
#define RHINO_CONFIG_TIMER_TASK_STACK_SIZE (200 + CSK_CPU_STACK_EXTRAL)
#endif
#define RHINO_CONFIG_TIMER_RATE 1
#define RHINO_CONFIG_TIMER_TASK_PRI 5
/* kernel intrpt conf */
#define RHINO_CONFIG_INTRPT_STACK_REMAIN_GET 1
#define RHINO_CONFIG_INTRPT_STACK_OVF_CHECK 0
#define RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL 188u
#define RHINO_CONFIG_INTRPT_GUARD 0
#define RHINO_CONFIG_STACK_OVF_CHECK_HW 0
#define RHINO_CONFIG_KOBJ_DYN_ALLOC 1
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
#define RHINO_CONFIG_K_DYN_QUEUE_MSG 30
#define RHINO_CONFIG_K_DYN_TASK_STACK (64 + CSK_CPU_STACK_EXTRAL)
#define RHINO_CONFIG_K_DYN_MEM_TASK_PRI RHINO_CONFIG_USER_PRI_MAX
#endif
/* kernel idle conf */
#ifdef CONFIG_IDLE_TASK_STACK_SIZE
#define RHINO_CONFIG_IDLE_TASK_STACK_SIZE CONFIG_IDLE_TASK_STACK_SIZE
#else
#define RHINO_CONFIG_IDLE_TASK_STACK_SIZE (256 + CSK_CPU_STACK_EXTRAL)
#endif
/* kernel hook conf */
#define RHINO_CONFIG_USER_HOOK 1
//#define RHINO_CONFIG_ISR_TASK 1
/* kernel stats conf */
#define RHINO_CONFIG_SYSTEM_STATS 1
#define RHINO_CONFIG_DISABLE_SCHED_STATS 0
#define RHINO_CONFIG_DISABLE_INTRPT_STATS 0
#define RHINO_CONFIG_CPU_USAGE_STATS 0
#define RHINO_CONFIG_CPU_USAGE_TASK_PRI (RHINO_CONFIG_PRI_MAX - 2)
#define RHINO_CONFIG_TASK_SCHED_STATS 0
#define RHINO_CONFIG_CPU_USAGE_TASK_STACK (50 + CSK_CPU_STACK_EXTRAL)
#ifdef RHINO_CONFIG_ISR_TASK
#ifndef RHINO_CONFIG_ISR_BUFF_SIZE
#define RHINO_CONFIG_ISR_BUFF_SIZE (16)
#endif
#ifndef RHINO_CONFIG_ISR_TASK_PRI
#define RHINO_CONFIG_ISR_TASK_PRI (1)
#endif
#ifndef RHINO_CONFIG_ISR_TASK_STACK_SIZE
#define RHINO_CONFIG_ISR_TASK_STACK_SIZE (1024)
#endif
#endif
#endif /* CONFIG_H */

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_NO_WAIT 0u
//#define RHINO_WAIT_FOREVER 0xffffffffu /* 32 bit value, if tick type is 64 bit, you need change it to 64 bit */
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_FRAG_ALLOCATED 0xabcddcabu /* 32 bit value, if 64 bit system, you need change it to 64 bit */
#define RHINO_MM_FRAG_FREE 0xfefdecdbu /* 32 bit value, if 64 bit system, you need change it to 64 bit */
#define RHINO_INLINE static __inline /* inline keyword, it may change under different compilers */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t cpu_cpsr_t;
/* you may change here depend on your hardware timer */
typedef uint32_t hr_timer_t; /* 32 bit or 64 bit unsigned value */
typedef uint32_t lr_timer_t; /* 32 bit or 64 bit unsigned value */
//typedef uint64_t tick_t; /* 32 bit or 64 bit unsigned value */
//typedef uint64_t idle_count_t; /* 64 bit unsigned value */
//typedef uint64_t sys_time_t; /* 64 bit unsigned value */
typedef uint32_t mutex_nested_t; /* 8 bit or 16bit or 32bit unsigned value */
typedef uint8_t suspend_nested_t; /* 8 bit normally */
typedef uint64_t ctx_switch_t; /* 32 bit or 64 bit unsigned value */
//typedef int32_t ssize_t;
#endif /* TYPES_H */

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PORT_H
#define PORT_H
#include <k_types.h>
#include <k_task.h>
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t psr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size,
void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t psr
#define RHINO_CPU_INTRPT_DISABLE() { psr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(psr); }
#endif /* PORT_H */

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#include <k_config.h>
#if (RHINO_CONFIG_STACK_OVF_CHECK_HW != 0)
void cpu_intrpt_stack_protect(void)
{
}
void task_stack_crash_warning(void)
{
printf("****The task stack base has been broken !!!****\n");
}
void cpu_task_stack_protect(cpu_stack_t *base, size_t size)
{
uint32_t base_addr = (uint32_t)base;
int num_return = wp_register(base_addr, AWATCH, task_stack_crash_warning);
if (num_return == 1) {
wp_enable(1);
} else if (num_return == 2 || num_return == -1) {
wp_unregister(1);
int number_tmp = wp_register(base_addr, AWATCH, task_stack_crash_warning);
if (number_tmp == 1){
wp_enable(1);
}
}
}
#endif

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#undef PSR_SP
#define PSR_SP (1UL << 29)
static ktask_t *tee_caller_task = NULL;
static inline uint32_t getcurrentpsr(void)
{
uint32_t flags = 0;
__asm__ __volatile__(
"ebreak\n" /* TODO */
);
return flags;
}
static inline void clear_psr_sp(void)
{
__asm__ __volatile__ (
"ebreak\n" /* TODO */
);
}
static inline void set_psr_sp(void)
{
__asm__ __volatile__ (
"ebreak\n" /* TODO */
);
}
void csky_get_tee_caller_task(void)
{
uint32_t temp_psr;
temp_psr = getcurrentpsr();
if (temp_psr & PSR_SP) {
tee_caller_task = (tee_caller_task == NULL) ? g_active_task[cpu_cur_get()] : tee_caller_task;
}
}
void csky_deal_tee_caller_task(void)
{
uint32_t temp_psr;
temp_psr = getcurrentpsr();
if (temp_psr & PSR_SP) {
if (tee_caller_task != NULL) {
if (tee_caller_task == g_active_task[cpu_cur_get()]) {
tee_caller_task = NULL;
} else {
clear_psr_sp();
}
}
} else {
if (tee_caller_task != NULL) {
if (tee_caller_task == g_active_task[cpu_cur_get()]) {
tee_caller_task = NULL;
set_psr_sp();
}
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
register int *gp asm("x3");
uint32_t temp = (uint32_t)(stack_base + stack_size);
temp &= 0xFFFFFFF8UL;
stk = (cpu_stack_t *)temp;
*(--stk) = (uint32_t)entry; /* PC */
*(--stk) = (uint32_t)0x31313131L; /* X31 */
*(--stk) = (uint32_t)0x30303030L; /* X30 */
*(--stk) = (uint32_t)0x29292929L; /* X29 */
*(--stk) = (uint32_t)0x28282828L; /* X28 */
*(--stk) = (uint32_t)0x27272727L; /* X27 */
*(--stk) = (uint32_t)0x26262626L; /* X26 */
*(--stk) = (uint32_t)0x25252525L; /* X25 */
*(--stk) = (uint32_t)0x24242424L; /* X24 */
*(--stk) = (uint32_t)0x23232323L; /* X23 */
*(--stk) = (uint32_t)0x22222222L; /* X22 */
*(--stk) = (uint32_t)0x21212121L; /* X21 */
*(--stk) = (uint32_t)0x20202020L; /* X20 */
*(--stk) = (uint32_t)0x19191919L; /* X19 */
*(--stk) = (uint32_t)0x18181818L; /* X18 */
*(--stk) = (uint32_t)0x17171717L; /* X17 */
*(--stk) = (uint32_t)0x16161616L; /* X16 */
*(--stk) = (uint32_t)0x15151515L; /* X15 */
*(--stk) = (uint32_t)0x14141414L; /* X14 */
*(--stk) = (uint32_t)0x13131313L; /* X13 */
*(--stk) = (uint32_t)0x12121212L; /* X12 */
*(--stk) = (uint32_t)0x11111111L; /* X11 */
*(--stk) = (uint32_t)arg; /* X10 */
*(--stk) = (uint32_t)0x09090909L; /* X9 */
*(--stk) = (uint32_t)0x08080808L; /* X8 */
*(--stk) = (uint32_t)0x07070707L; /* X7 */
*(--stk) = (uint32_t)0x06060606L; /* X6 */
*(--stk) = (uint32_t)0x05050505L; /* X5 */
*(--stk) = (uint32_t)0x04040404L; /* X4 */
*(--stk) = (uint32_t)gp; /* X3 */
*(--stk) = (uint32_t)krhino_task_deathbed; /* X1 */
return stk;
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Enable interrupts when returning from the handler */
#define MSTATUS_PRV1 0x1880
/******************************************************************************
* Functions:
* size_t cpu_intrpt_save(void);
* void cpu_intrpt_restore(size_t psr);
******************************************************************************/
.global cpu_intrpt_save
.type cpu_intrpt_save, %function
cpu_intrpt_save:
csrr a0, mstatus
csrc mstatus, 8
ret
.global cpu_intrpt_restore
.type cpu_intrpt_restore, %function
cpu_intrpt_restore:
csrw mstatus, a0
ret
/******************************************************************************
* Functions:
* void cpu_intrpt_switch(void);
* void cpu_task_switch(void);
******************************************************************************/
.global cpu_task_switch
.type cpu_task_switch, %function
cpu_task_switch:
li t0, 0xE080100C
lb t1, (t0)
li t2, 0x01
or t1, t1, t2
sb t1, (t0)
ret
.global cpu_intrpt_switch
.type cpu_intrpt_switch, %function
cpu_intrpt_switch:
li t0, 0xE080100C
lb t1, (t0)
li t2, 0x01
or t1, t1, t2
sb t1, (t0)
ret
/******************************************************************************
* Functions:
* void cpu_first_task_start(void);
******************************************************************************/
.global cpu_first_task_start
.type cpu_first_task_start, %function
cpu_first_task_start:
j __task_switch_nosave
/******************************************************************************
* Functions:
* void tspend_handler(void);
******************************************************************************/
.global tspend_handler
.type tspend_handler, %function
tspend_handler:
csrrw sp, mscratch, sp
addi sp, sp, -124
sw x1, 0(sp)
sw x3, 4(sp)
sw x4, 8(sp)
sw x5, 12(sp)
sw x6, 16(sp)
sw x7, 20(sp)
sw x8, 24(sp)
sw x9, 28(sp)
sw x10, 32(sp)
sw x11, 36(sp)
sw x12, 40(sp)
sw x13, 44(sp)
sw x14, 48(sp)
sw x15, 52(sp)
sw x16, 56(sp)
sw x17, 60(sp)
sw x18, 64(sp)
sw x19, 68(sp)
sw x20, 72(sp)
sw x21, 76(sp)
sw x22, 80(sp)
sw x23, 84(sp)
sw x24, 88(sp)
sw x25, 92(sp)
sw x26, 96(sp)
sw x27, 100(sp)
sw x28, 104(sp)
sw x29, 108(sp)
sw x30, 112(sp)
sw x31, 116(sp)
csrr t0, mepc
sw t0, 120(sp)
la a1, g_active_task
lw a1, (a1)
sw sp, (a1)
__task_switch_nosave:
la a0, g_preferred_ready_task
la a1, g_active_task
lw a2, (a0)
sw a2, (a1)
lw sp, (a2)
/* Run in machine mode */
li t0, MSTATUS_PRV1
csrs mstatus, t0
lw t0, 120(sp)
csrw mepc, t0
lw x1, 0(sp)
lw x3, 4(sp)
lw x4, 8(sp)
lw x5, 12(sp)
lw x6, 16(sp)
lw x7, 20(sp)
lw x8, 24(sp)
lw x9, 28(sp)
lw x10, 32(sp)
lw x11, 36(sp)
lw x12, 40(sp)
lw x13, 44(sp)
lw x14, 48(sp)
lw x15, 52(sp)
lw x16, 56(sp)
lw x17, 60(sp)
lw x18, 64(sp)
lw x19, 68(sp)
lw x20, 72(sp)
lw x21, 76(sp)
lw x22, 80(sp)
lw x23, 84(sp)
lw x24, 88(sp)
lw x25, 92(sp)
lw x26, 96(sp)
lw x27, 100(sp)
lw x28, 104(sp)
lw x29, 108(sp)
lw x30, 112(sp)
lw x31, 116(sp)
addi sp, sp, 124
csrrw sp, mscratch, sp
mret

View File

@@ -0,0 +1,155 @@
#include "k_api.h"
#include "cpu_pwr_config.h"
//#if RHINO_CONFIG_CPU_PWR_MGMT
#include "cpu_pwr_hal_lib.h"
#include "pwr_debug.h"
#include "soc.h"
#if RHINO_CONFIG_CPU_TICKLESS
#include "cpu_tickless.h"
#endif /*RHINO_CONFIG_CPU_TICKLESS*/
#ifdef CONFIG_TEE_CA
#include "drv_tee.h"
#endif
/* forward declarations */
extern cpu_pwr_t *p_cpu_pwr_root_node;
#if RHINO_CONFIG_CPU_TICKLESS
extern one_shot_timer_t tim_one_shot; /* wakeup source for C1 */
#endif /* RHINO_CONFIG_CPU_TICKLESS */
static cpu_pwr_t cpu_pwr_node_package_0;
static cpu_pwr_t cpu_pwr_node_core_0;
static kstat_t board_cpu_c_state_set
(
uint32_t cpuCState,
int master
)
{
switch (cpuCState) {
case CPU_CSTATE_C0:
//printf("enter C0\n");
if (master) {
}
break;
case CPU_CSTATE_C1:
/*
* put CPU into C1 state
* to put CPU into C1 state.
*/
//printf("enter C1\n");
#ifdef CONFIG_CHIP_CH2201
*(volatile unsigned int *)(0xe000e1c0) = 0xffffffff; // reload wakeup_IRQ
//*(volatile unsigned int *)(0xe000e280) = 0xffffffff; // clear pend IRQ
csi_vic_set_wakeup_irq(RTC_IRQn);
csi_vic_set_wakeup_irq(UART2_IRQn);
csi_vic_set_wakeup_irq(UART1_IRQn);
csi_vic_set_wakeup_irq(UART0_IRQn);
csi_vic_set_wakeup_irq(CORET_IRQn);
csi_vic_set_wakeup_irq(GPIOA_IRQn);
csi_vic_set_wakeup_irq(GPIOB_IRQn);
csi_vic_set_wakeup_irq(TIMA0_IRQn);
#ifdef CONFIG_TEE_CA
csi_tee_enter_lpm(0, 0, TEE_LPM_MODE_WAIT);
#else
__WFI();
#endif
#endif
break;
default:
PWR_DBG(DBG_ERR, "invalid C state: C%d\n", cpuCState);
break;
}
return RHINO_SUCCESS;
}
kstat_t board_cpu_pwr_topo_create(void)
{
cpu_pwr_t *pCpuNode = NULL;
cpu_pwr_t *pParentL1 = NULL; /* parent of level 1 */
cpu_pwr_t *pParentL2 = NULL; /* parent of level 2 */
kstat_t retVal = RHINO_SUCCESS;
uint32_t cpuIndex = 0; /* 0 for UP */
if (p_cpu_pwr_root_node == NULL) {
return RHINO_PWR_MGMT_ERR;
}
pParentL1 = p_cpu_pwr_root_node;
pCpuNode = &cpu_pwr_node_package_0;
retVal = cpu_pwr_node_init_static(CPU_PWR_TOPO_LEVEL_1, "package", 0, pCpuNode);
if (retVal != RHINO_SUCCESS) {
return RHINO_PWR_MGMT_ERR;
}
/* add this node as a child of p_cpu_pwr_root_node */
cpu_pwr_child_add(pParentL1, pCpuNode);
pParentL2 = pCpuNode;
pCpuNode = &cpu_pwr_node_core_0;
retVal = cpu_pwr_node_init_static(CPU_PWR_TOPO_LEVEL_2, "core", 0, pCpuNode);
if (retVal != RHINO_SUCCESS) {
return RHINO_PWR_MGMT_ERR;
}
cpu_pwr_child_add(pParentL2, pCpuNode);
/* record this node as leaf node in the topology */
retVal = cpu_pwr_leaf_node_record(pCpuNode, cpuIndex);
if (retVal == RHINO_PWR_MGMT_ERR) {
return RHINO_PWR_MGMT_ERR;
}
retVal = cpu_pwr_c_method_set_by_level(CPU_PWR_TOPO_LEVEL_2,
board_cpu_c_state_set);
if (retVal == RHINO_PWR_MGMT_ERR) {
return RHINO_PWR_MGMT_ERR;
}
retVal = cpu_pwr_c_state_capability_set_by_level(CPU_PWR_TOPO_LEVEL_2,
CPU_STATE_BIT(CPU_CSTATE_C0)
| CPU_STATE_BIT(CPU_CSTATE_C1)
);
if (retVal == RHINO_PWR_MGMT_ERR) {
return RHINO_PWR_MGMT_ERR;
}
cpu_pwr_c_state_latency_save(cpuIndex, CPU_CSTATE_C0, 0);
cpu_pwr_c_state_latency_save(cpuIndex, CPU_CSTATE_C1, 0);
tickless_one_shot_timer_save(CPU_CSTATE_C1, &tim_one_shot);
#if RHINO_CONFIG_CPU_TICKLESS
tickless_c_states_add(CPU_STATE_BIT(CPU_CSTATE_C0)
| CPU_STATE_BIT(CPU_CSTATE_C1)
);
#endif /* RHINO_CONFIG_CPU_TICKLESS */
return retVal;
}
//#endif /* RHINO_CONFIG_CPU_PWR_MGMT */

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
* This file supplied RTC one-shot start/stop services for CPU tickless
* module, verifyied on STM32L496-DISCOVERY with C3/C4 mode.
* C3: stop mode.
* C4: standby mode.
*/
#include "k_api.h"
#include "cpu_pwr_config.h"
//#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
//#if (RHINO_CONFIG_CPU_TICKLESS > 0)
#include "cpu_tickless.h"
#include "drv_rtc.h"
#define RTC_ONE_SHOT_DBG
extern void SystemClock_Config(void);
#define RTC_WAKEUP_SOURCE_FREQ_2000HZ
//#define RTC_WAKEUP_SOURCE_FREQ_1HZ
/* According reference manual of STM32496G, RTC_WUTR is 16bit */
#define RTC_WAKE_UP_RGE_MAX 0xffff
//static uint32_t one_shot_enabled = 0;
//static uint32_t one_shot_start_value = 0;
static uint32_t one_shot_max_period = 0;/* seconds */
//static kspinlock_t rtc_spin;
//static RTC_HandleTypeDef RtcHandle;
#ifdef RTC_ONE_SHOT_DBG
//static int rtc_wakeup_irq_count = 0;
#endif /* RTC_ONE_SHOT_DBG */
static kstat_t rtc_init(void);
static uint32_t rtc_one_shot_max_seconds(void);
static kstat_t rtc_one_shot_start(uint64_t planUs);
static kstat_t rtc_one_shot_stop(uint64_t *pPassedUs);
one_shot_timer_t rtc_one_shot = {
rtc_init,
rtc_one_shot_max_seconds,
rtc_one_shot_start,
rtc_one_shot_stop,
};
static uint32_t rtc_one_shot_max_seconds(void)
{
return one_shot_max_period;
}
static kstat_t rtc_init(void)
{
return RHINO_SUCCESS;
}
/*******************************************************************************
*
* rtc_one_shot_start - enable the timer in oneshot mode
*
* This function enables the timer in oneshot mode, the interrupt will be fired
* after servral microseconds which is indicated by planUs.
*
* RETURNS: RHINO_SUCCESS or RHINO_PWR_MGMT_ERR if timer is not enabled
*
* ERRNO
*/
static kstat_t rtc_one_shot_start(uint64_t planUs)
{
return RHINO_SUCCESS;
}
/*******************************************************************************
*
* one_shot_planed_cnt - cancel the timer which was in oneshot mode
*
* This function is called to cancel the timer which was in oneshot mode.
* the time has passed(microseconds) will be return in pPassedUs.
*
* RETURNS: RHINO_SUCCESS or RHINO_PWR_MGMT_ERR if timer is not disabled
*
* ERRNO: N/A
*/
static kstat_t rtc_one_shot_stop
(
uint64_t *pPassedUs /* OUT */
)
{
return RHINO_SUCCESS;
}
/*******************************************************************************
*
* RTC_WKUP_IRQHandler - ISR handle of RTC wakeup interrupt
*
* This function will replace weak one which is defined in
* startup_stm32l496xx_keil.s
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
void RTC_WKUP_IRQHandler(void)
{
}
#ifdef RTC_ONE_SHOT_DBG
void rtc_info_show(void)
{
}
#endif /* RTC_ONE_SHOT_DBG */
//#endif /* RHINO_CONFIG_CPU_TICKLESS */
//#endif /* RHINO_CONFIG_CPU_PWR_MGMT */

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
DESCRIPTION
This file provides two fundtions systick_suspend()/systick_resume()
which is used by cpu tickless module to suspend/resume system tick
interrupt.
Differrent board may has different way to suspend/resume system tick
interrupt, please reference your board/soc user manual to find the
detail for how to implement these two functions.
*/
#include "k_api.h"
#include "cpu_pwr_config.h"
#include "port.h"
#include "csi_core.h"
#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
extern uint32_t csi_coret_suspend();
extern uint32_t csi_coret_resume();
void systick_suspend(void)
{
CORET->CTRL = CORET_CTRL_CLKSOURCE_Msk | CORET_CTRL_TICKINT_Msk;
}
void systick_resume(void)
{
CORET->CTRL = CORET_CTRL_CLKSOURCE_Msk |
CORET_CTRL_TICKINT_Msk |
CORET_CTRL_ENABLE_Msk; /* Enable CORET IRQ and CORET Timer */
}
#else
void systick_suspend(void)
{
}
void systick_resume(void)
{
}
#endif /* RHINO_CONFIG_CPU_PWR_MGMT */

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
* According user manual of STM32L496-DISCOVERY
* TIM2 and TIM5 are 32-bit timer, other timer is 16-bit.
* This file will use TIM5 to supply one-shot start/stop service
* for CPU tickless module.
* verifyied on STM32L496-DISCOVERY with C1/C2 mode.
* C1: sleep mode.
* C2: low power sleep mode.
*/
#include "k_api.h"
#include "cpu_pwr_config.h"
//#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
//#if (RHINO_CONFIG_CPU_TICKLESS > 0)
#include "cpu_tickless.h"
//#include "drv_timer.h"
#include "soc.h"
//#define TIM_DBG
#ifndef CONFIG_LPM_TICKLESS_SYSTIM
#define CONFIG_LPM_TICKLESS_SYSTIM 0
#endif
extern int aos_lpm_register_device(uint8_t level, void *func, void *param);
timer_handle_t wakeup_timer;
static uint32_t init_flag = 0;
static kspinlock_t tim_spin;
static kstat_t tim_timer_init(void);
static uint32_t tim_one_shot_max_seconds(void);
static kstat_t tim_one_shot_start(uint64_t planUs);
static kstat_t tim_one_shot_stop(uint64_t *pPassedUs);
one_shot_timer_t tim_one_shot = {
tim_timer_init,
tim_one_shot_max_seconds,
tim_one_shot_start,
tim_one_shot_stop,
};
void timer_event_cb(int32_t idx, timer_event_e event)
{
#ifdef TIM_DBG
printf("time out\n");
#endif
}
kstat_t tim_timer_init(void)
{
if (init_flag == 1) {
return RHINO_SUCCESS;
}
krhino_spin_init(&tim_spin);
wakeup_timer = csi_timer_initialize(CONFIG_LPM_TICKLESS_SYSTIM, timer_event_cb);
csi_timer_config(wakeup_timer, TIMER_MODE_FREE_RUNNING);
#ifdef CONFIG_LPM
aos_lpm_register_device(0, csi_timer_power_control, wakeup_timer);
#endif
init_flag = 1;
return RHINO_SUCCESS;
}
/* return the max period(in second) that could trigger interrupt */
uint32_t tim_one_shot_max_seconds(void)
{
/* the max 32 bit value / count frequency */
return 0xffffffff / drv_get_sys_freq();
}
/*******************************************************************************
*
* tim_one_shot_start - enable the timer in oneshot mode
*
* This function enables the timer in oneshot mode, the interrupt will be fired
* after servral microseconds which is indicated by planUs.
*
* RETURNS: RHINO_SUCCESS or RHINO_PWR_MGMT_ERR if timer is not enabled
*
* ERRNO
*/
kstat_t tim_one_shot_start
(
uint64_t planUs /* IN */
)
{
krhino_spin_lock_irq_save(&tim_spin);
#ifdef TIM_DBG
printf("tim_one_shot_start %d\n", planUs);
#endif
csi_timer_set_timeout(wakeup_timer, planUs);
csi_timer_start(wakeup_timer);
krhino_spin_unlock_irq_restore(&tim_spin);
return RHINO_SUCCESS;
}
/*******************************************************************************
*
* tim_one_shot_stop - cancel the timer which was in oneshot mode
*
* This function is called to cancel the timer which was in oneshot mode.
* the time has passed(microseconds) will be return in pPassedUs.
*
* RETURNS: RHINO_SUCCESS or RHINO_PWR_MGMT_ERR if timer is not disabled
*
* ERRNO: N/A
*/
kstat_t tim_one_shot_stop
(
uint64_t *pPassedUs /* OUT */
)
{
uint32_t load_val = 0;
uint32_t current_val = 0;
*pPassedUs = 0;
krhino_spin_lock_irq_save(&tim_spin);
csi_timer_get_load_value(wakeup_timer, &load_val);
csi_timer_get_current_value(wakeup_timer, &current_val);
*pPassedUs = (load_val - current_val) ? (load_val - current_val) : 0;
*pPassedUs = *pPassedUs * 1000000 / drv_get_sys_freq();
#ifdef TIM_DBG
printf("tim_one_shot_stop, pPassedUs %u, load_val %u, current_val %u\n", *pPassedUs, load_val, current_val);
#endif
csi_timer_stop(wakeup_timer);
krhino_spin_unlock_irq_restore(&tim_spin);
return RHINO_SUCCESS;
}
//#endif /* RHINO_CONFIG_CPU_TICKLESS */
//#endif /* RHINO_CONFIG_CPU_PWR_MGMT */

View File

@@ -0,0 +1,333 @@
/*
* Copyright (C) 2017 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
2017_12_27,WangMin(Rocky) created.
*/
/*
* DESCRIPTION
* This library is used to provide the atomic operators for CPU
* which do not support native atomic operations.
*
* The design principle is disable the interrupt when execute the
* atomic operations and enable the interrupt after finish the
* operation.
*/
#include "k_api.h"
#include "k_atomic.h"
/**
* This routine atomically adds <*target> and <value>, placing the result in
* <*target>. The operation is done using unsigned integer arithmetic.
*
* This routine can be used from both task and interrupt context.
*
* @param target memory location to add to
* @param value the value to add
*
* @return The previous value from <target>
*/
atomic_val_t rhino_atomic_add(atomic_t *target, atomic_val_t value)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
*target += value;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine atomically subtracts <value> from <*target>, result is placed
* in <*target>. The operation is done using unsigned integer arithmetic.
*
* This routine can be used from both task and interrupt context.
*
* @param target the memory location to subtract from
* @param value the value to subtract
*
* @return The previous value from <target>
*/
atomic_val_t rhino_atomic_sub(atomic_t *target, atomic_val_t value)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
*target -= value;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine atomically increments the value in <*target>. The operation is
* done using unsigned integer arithmetic.
*
* This routine can be used from both task and interrupt context.
*
* @return The value from <target> before the increment
*/
atomic_val_t rhino_atomic_inc(atomic_t *target)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
(*target)++;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine atomically decrement the value in <*target>. The operation is
* done using unsigned integer arithmetic.
*
* This routine can be used from both task and interrupt context.
*
* @return The value from <target> before the increment
*/
atomic_val_t rhino_atomic_dec(atomic_t *target)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
(*target)--;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine atomically sets <*target> to <value> and returns the old value
* that was in <*target>. Normally all CPU architectures can atomically write
* to a variable of size atomic_t without the help of this routine.
* This routine is intended for software that needs to atomically fetch and
* replace the value of a memory location.
*
* This routine can be used from both task and interrupt context.
*
* @param target the memory location to write to
* @param value the value to write
*
* @return The previous value from <target>
*/
atomic_val_t rhino_atomic_set(atomic_t *target, atomic_val_t value)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
*target = value;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine atomically read a value from <target>.
* This routine can be used from both task and interrupt context.
*
* @return The value read from <target>
*/
atomic_val_t rhino_atomic_get(const atomic_t *target)
{
return *target;
}
/**
* This routine atomically performs a bitwise OR operation of <*target>
* and <value>, placing the result in <*target>.
*
* This routine can be used from both task and interrupt context.
*
* @param target the memory location to be modified
* @param value the value to OR
*
* @return The previous value from <target>
*/
atomic_val_t rhino_atomic_or(atomic_t *target, atomic_val_t value)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
*target |= value;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine atomically performs a bitwise XOR operation of <*target> and
* <value>, placing the result in <*target>.
*
* This routine can be used from both task and interrupt context.
*
* @param target the memory location to be modified
* @param value the value to XOR
*
* @return The previous value from <target>
*/
atomic_val_t rhino_atomic_xor(atomic_t *target, atomic_val_t value)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
*target ^= value;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine atomically performs a bitwise AND operation of <*target> and
* <value>, placing the result in <*target>.
*
* This routine can be used from both task and interrupt context.
*
* @param target the memory location to be modified
* @param value the value to AND
*
* @return The previous value from <target>
*/
atomic_val_t rhino_atomic_and(atomic_t *target, atomic_val_t value)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
*target &= value;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine atomically performs a bitwise NAND operation of <*target> and
* <value>, placing the result in <*target>.
*
* This routine can be used from both task and interrupt context.
*
* @param target the memory location to be modified
* @param value the value to NAND
*
* @return The previous value from <target>
*/
atomic_val_t rhino_atomic_nand(atomic_t *target, atomic_val_t value)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
*target = ~(*target & value);
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine provides the atomic clear operator. The value of 0 is atomically
* written at <target> and the previous value at <target> is returned.
*
* This routine can be used from both task and interrupt context.
*
* @param target the memory location to write
*
* @return The previous value from <target>
*/
atomic_val_t rhino_atomic_clear(atomic_t *target)
{
CPSR_ALLOC();
atomic_val_t old_value;
RHINO_CPU_INTRPT_DISABLE();
old_value = *target;
*target = 0;
RHINO_CPU_INTRPT_ENABLE();
return old_value;
}
/**
* This routine performs an atomic compare-and-swap, it test that whether
* <*target> equal to <oldValue>, and if TRUE, setting the value of <*target>
* to <newValue> and return 1.
*
* If the original value at <target> does not equal <oldValue>, then the target
* will not be updated and return 0.
*
* @param target address to be tested
* @param old_value value to compare against
* @param new_value value to compare against
* @return Returns 1 if <new_value> is written, 0 otherwise.
*/
int rhino_atomic_cas(atomic_t *target, atomic_val_t old_value,
atomic_val_t new_value)
{
CPSR_ALLOC();
int ret = 0;
RHINO_CPU_INTRPT_DISABLE();
if (*target == old_value)
{
*target = new_value;
ret = 1;
}
RHINO_CPU_INTRPT_ENABLE();
return ret;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2017 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
2017_12_27,WangMin(Rocky) created.
*/
#ifndef K_ATOMIC_H
#define K_ATOMIC_H
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int atomic_t;
typedef atomic_t atomic_val_t;
extern atomic_val_t rhino_atomic_add(atomic_t *target, atomic_val_t value);
extern atomic_val_t rhino_atomic_sub(atomic_t *target, atomic_val_t value);
extern atomic_val_t rhino_atomic_inc(atomic_t *target);
extern atomic_val_t rhino_atomic_dec(atomic_t *target);
extern atomic_val_t rhino_atomic_set(atomic_t *target, atomic_val_t value);
extern atomic_val_t rhino_atomic_get(const atomic_t *target);
extern atomic_val_t rhino_atomic_or(atomic_t *target, atomic_val_t value);
extern atomic_val_t rhino_atomic_xor(atomic_t *target, atomic_val_t value);
extern atomic_val_t rhino_atomic_and(atomic_t *target, atomic_val_t value);
extern atomic_val_t rhino_atomic_nand(atomic_t *target, atomic_val_t value);
extern atomic_val_t rhino_atomic_clear(atomic_t *target);
extern int rhino_atomic_cas(atomic_t *target, atomic_val_t old_value,
atomic_val_t new_value);
#ifdef __cplusplus
}
#endif
#endif /* K_ATOMIC_H */

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
21jan2018,WangMin writen.
*/
/*
DESCRIPTION
This file provides base type of cpu set and method for cpu set.
*/
#ifndef __cpuset_h__
#define __cpuset_h__
#include "k_atomic.h"
#ifdef __cplusplus
extern "C" {
#endif
/* typedefs */
typedef unsigned int cpuset_t;
#define CPUSET_ATOMIC_SET(cpuset, n) \
(void) rhino_atomic_or ((atomic_t *) &(cpuset), 1 << (n))
#define CPUSET_ATOMIC_CLR(cpuset, n) \
(void) rhino_atomic_and ((atomic_t *) &(cpuset), ~((1 << (n))))
#define CPUSET_ATOMIC_COPY(cpusetDst, cpusetSrc) \
(void) rhino_atomic_set ((atomic_t *) &(cpusetDst), (atomic_t) (cpusetSrc))
#define CPUSET_CLR(cpuset, n) ((cpuset) &= ~(1 << (n)))
#define CPUSET_ZERO(cpuset) ((cpuset) = 0)
#define CPUSET_IS_ZERO(cpuset) ((cpuset) == 0)
#define CPUSET_SET(cpuset, n) ((cpuset) |= (1 << (n)))
#define CPUSET_ISSET(cpuset, n) ((cpuset) & (1 << (n)))
#ifdef __cplusplus
}
#endif
#endif /* __cpuset_h__ */

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
DESCRIPTION
This file provides method to find the least/most significant bit in 32 bit
fields.
*/
#include "k_api.h"
#include "k_ffs.h"
#include "k_bitmap.h"
/* find most significant bit set */
int ffs32_msb(uint32_t bitmap)
{
if (bitmap == 0)
{
return 0;
}
return 32 - krhino_find_first_bit(&bitmap);
}
/* find least significant bit set */
int ffs32_lsb(uint32_t bitmap)
{
uint32_t x;
int lsbit;
if (bitmap == 0)
{
return 0;
}
x = bitmap & -bitmap;
lsbit = krhino_find_first_bit((uint32_t *)(&x));
return 32 - lsbit;
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
#ifndef __k_ffs_h__
#define __k_ffs_h__
#ifdef __cplusplus
extern "C" {
#endif
/* function declarations */
extern int ffs32_lsb (uint32_t i);
extern int ffs32_msb (uint32_t i);
#define FFS_LSB(i) ffs32_lsb(i)
#define FFS_MSB(i) ffs32_msb(i)
#ifdef __cplusplus
}
#endif
#endif /* __k_ffs_h__ */

View File

@@ -0,0 +1,177 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
/*
* internal helper to calculate the unused elements in a fifo
*/
static uint32_t fifo_unused(struct k_fifo *fifo)
{
return (fifo->mask + 1) - (fifo->in - fifo->out);
}
static int8_t is_power_of_2(uint32_t n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
int8_t fifo_init(struct k_fifo *fifo, void *buffer, uint32_t size)
{
/*
* round down to the next power of 2, since our 'let the indices
* wrap' technique works only in this case.
*/
if (!is_power_of_2(size)) {
return 1;
}
fifo->in = 0;
fifo->out = 0;
fifo->data = buffer;
if (size < 2) {
fifo->mask = 0;
return 1;
}
fifo->mask = size - 1;
fifo->free_bytes = size;
fifo->size = size;
return 0;
}
static void fifo_copy_in(struct k_fifo *fifo, const void *src,
uint32_t len, uint32_t off)
{
uint32_t l;
uint32_t size = fifo->mask + 1;
off &= fifo->mask;
l = fifo_min(len, size - off);
memcpy((unsigned char *)fifo->data + off, src, l);
memcpy(fifo->data, (unsigned char *)src + l, len - l);
}
uint32_t fifo_in(struct k_fifo *fifo, const void *buf, uint32_t len)
{
uint32_t l;
CPSR_ALLOC();
RHINO_CRITICAL_ENTER();
l = fifo_unused(fifo);
if (len > l) {
len = l;
}
fifo_copy_in(fifo, buf, len, fifo->in);
fifo->in += len;
fifo->free_bytes -= len;
RHINO_CRITICAL_EXIT();
return len;
}
static void kfifo_copy_out(struct k_fifo *fifo, void *dst,
uint32_t len, uint32_t off)
{
uint32_t l;
uint32_t size = fifo->mask + 1;
off &= fifo->mask;
l = fifo_min(len, size - off);
memcpy(dst, (unsigned char *)fifo->data + off, l);
memcpy((unsigned char *)dst + l, fifo->data, len - l);
}
static uint32_t internal_fifo_out_peek(struct k_fifo *fifo,
void *buf, uint32_t len)
{
uint32_t l;
l = fifo->in - fifo->out;
if (len > l) {
len = l;
}
kfifo_copy_out(fifo, buf, len, fifo->out);
return len;
}
uint32_t fifo_out_peek(struct k_fifo *fifo,
void *buf, uint32_t len)
{
uint32_t ret_len;
CPSR_ALLOC();
RHINO_CRITICAL_ENTER();
ret_len = internal_fifo_out_peek(fifo, buf, len);
RHINO_CRITICAL_EXIT();
return ret_len;
}
uint32_t fifo_out(struct k_fifo *fifo, void *buf, uint32_t len)
{
CPSR_ALLOC();
RHINO_CRITICAL_ENTER();
len = internal_fifo_out_peek(fifo, buf, len);
fifo->out += len;
fifo->free_bytes += len;
RHINO_CRITICAL_EXIT();
return len;
}
uint32_t fifo_out_all(struct k_fifo *fifo, void *buf)
{
uint32_t len;
CPSR_ALLOC();
RHINO_CRITICAL_ENTER();
len = fifo->size - fifo->free_bytes;
if (len == 0) {
RHINO_CRITICAL_EXIT();
return 0;
}
len = internal_fifo_out_peek(fifo, buf, len);
fifo->out += len;
fifo->free_bytes += len;
RHINO_CRITICAL_EXIT();
return len;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_API_H
#define K_API_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <k_config.h>
#include <k_default_config.h>
#include <k_types.h>
#include <k_err.h>
#include <k_critical.h>
#include <k_sys.h>
#include <k_bitmap.h>
#include <k_list.h>
#include <k_obj.h>
#include <k_sched.h>
#include <k_task.h>
#include <k_ringbuf.h>
#include <k_queue.h>
#include <k_buf_queue.h>
#include <k_sem.h>
#include <k_task_sem.h>
#include <k_mutex.h>
#include <k_timer.h>
#include <k_time.h>
#include <k_event.h>
#include <k_stats.h>
#include <k_mm_debug.h>
#include <k_mm_blk.h>
#include <k_mm_region.h>
#include <k_mm.h>
#include <k_workqueue.h>
#include <k_internal.h>
#include <k_trace.h>
#include <k_soc.h>
#include <k_hook.h>
#include <port.h>
#include <k_endian.h>
#include <k_fifo.h>
#ifndef __at_section
#define __at_section(sec) __attribute__((section(sec)))
#endif
#ifndef __bobj
#define __bobj
#endif
#ifndef __init
#define __init
#endif
extern void assert_internal(const char *__function, unsigned int __line, const char *__assertion, void *lr);
#ifdef __cplusplus
}
#endif
#endif /* K_API_H */

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_BITMAP_H
#define K_BITMAP_H
#define BITMAP_UNIT_SIZE 32U
#define BITMAP_UNIT_MASK 0X0000001F
#define BITMAP_UNIT_BITS 5U
#define BITMAP_MASK(nr) (1UL << (BITMAP_UNIT_SIZE - 1U - ((nr) & BITMAP_UNIT_MASK)))
#define BITMAP_WORD(nr) ((nr) >> BITMAP_UNIT_BITS)
#define LITTLE_TO_BIG_ENDIAN(x) ((uint32_t)(((x) & 0x000000ffUL) << 24u) | \
(((x) & 0x0000ff00UL) << 8u) | \
(((x) & 0x00ff0000UL) >> 8u) | \
(((x) & 0xff000000UL) >> 24u))
/**
** This MACRO will declare a bitmap
** @param[in] name the name of the bitmap to declare
** @param[in] bits the bits of the bitmap
** @return no return
**/
#define BITMAP_DECLARE(name, bits) uint32_t name[((bits) + (BITMAP_UNIT_SIZE - 1U)) >> BITMAP_UNIT_BITS]
#if (RHINO_CONFIG_BITMAP_HW != 0)
extern int32_t cpu_bitmap_clz(uint32_t val);
#endif
/**
** This function will set a bit of the bitmap
** @param[in] bitmap pointer to the bitmap
** @param[in] nr position of the bitmap to set
** @return no return
**/
RHINO_INLINE void krhino_bitmap_set(uint32_t *bitmap, int32_t nr)
{
bitmap[BITMAP_WORD(nr)] |= BITMAP_MASK(nr);
}
/**
** This function will clear a bit of the bitmap
** @param[in] bitmap pointer to the bitmap
** @param[in] nr position of the bitmap to clear
** @return no return
**/
RHINO_INLINE void krhino_bitmap_clear(uint32_t *bitmap, int32_t nr)
{
bitmap[BITMAP_WORD(nr)] &= ~BITMAP_MASK(nr);
}
/**
** This function will find the first bit(1) of the bitmap
** @param[in] bitmap pointer to the bitmap
** @return the first bit position
**/
RHINO_INLINE int krhino_find_first_bit(uint32_t *bitmap)
{
int32_t nr = 0;
uint32_t tmp = 0;
while (*bitmap == 0UL) {
nr += BITMAP_UNIT_SIZE;
bitmap++;
}
tmp = *bitmap;
#if (RHINO_CONFIG_LITTLE_ENDIAN == 0)
tmp = LITTLE_TO_BIG_ENDIAN(tmp);
#endif
#if (RHINO_CONFIG_BITMAP_HW == 0)
if (!(tmp & 0XFFFF0000)) {
tmp <<= 16;
nr += 16;
}
if (!(tmp & 0XFF000000)) {
tmp <<= 8;
nr += 8;
}
if (!(tmp & 0XF0000000)) {
tmp <<= 4;
nr += 4;
}
if (!(tmp & 0XC0000000)) {
tmp <<= 2;
nr += 2;
}
if (!(tmp & 0X80000000)) {
nr += 1;
}
#else
nr += cpu_bitmap_clz(tmp);
#endif
return nr;
}
#endif /* K_BITMAP_H */

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_BUF_QUEUE_H
#define K_BUF_QUEUE_H
typedef struct {
blk_obj_t blk_obj;
blk_obj_t sblk_obj;
void *buf;
k_ringbuf_t ringbuf;
size_t max_msg_size;
size_t cur_num;
size_t peak_num;
size_t min_free_buf_size;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t buf_queue_item;
#endif
uint8_t mm_alloc_flag;
} kbuf_queue_t;
typedef struct {
size_t buf_size;
size_t max_msg_size;
size_t cur_num;
size_t peak_num;
size_t free_buf_size;
size_t min_free_buf_size;
} kbuf_queue_info_t;
/**
* This function will create a buf-queue
* @param[in] queue pointer to the queue(the space is provided by user)
* @param[in] name name of the queue
* @param[in] buf pointer to the buf
* @param[in] size size of the buf
* @param[in] max_msg max size of one msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf,
size_t size, size_t max_msg);
/**
* This function will create a fix buf-queue
* @param[in] queue pointer to the queue(the space is provided by user)
* @param[in] name name of the queue
* @param[in] buf pointer to the buf
* @param[in] msg_size size of the msg
* @param[in] msg_num number of msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_fix_buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf, size_t msg_size, size_t msg_num);
/**
* This function will delete a queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_del(kbuf_queue_t *queue);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn-queue
* @param[out] queue pointer to the queue(The space is provided by kernel)
* @param[in] name pointer to the nam
* @param[in] size size of the buf
* @param[in] max_msg max size of one msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_dyn_create(kbuf_queue_t **queue, const name_t *name,
size_t size, size_t max_msg);
/**
* This function will delete a dyn-queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_dyn_del(kbuf_queue_t *queue);
#endif
/**
* This function will send a msg at the end of queue
* @param[in] queue pointer to the queue
* @param[in] msg pointer to msg to be send
* @param[in] size size of the msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_send(kbuf_queue_t *queue, void *msg, size_t size, tick_t ticks);
/**
* This function will receive msg form aqueue
* @param[in] queue pointer to the queue
* @param[in] ticks ticks to wait before receiving msg
* @param[out] msg pointer to the buf to save msg
* @param[out] size size of received msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_recv(kbuf_queue_t *queue, tick_t ticks, void *msg,
size_t *size);
/**
* This function will reset queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_flush(kbuf_queue_t *queue);
/**
* This function will get information of a queue
* @param[in] queue pointer to the queue
* @param[out] free free size of the queue buf
* @param[out] total total size of the queue buf
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_info_get(kbuf_queue_t *queue, kbuf_queue_info_t *info);
#endif /* K_BUF_QUEUE_H */

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_CRITICAL_H
#define K_CRITICAL_H
typedef struct {
#if (RHINO_CONFIG_CPU_NUM > 1)
uint32_t owner; /* cpu index of owner */
#endif
uint32_t cnt;
cpu_cpsr_t cpsr; /* the int key for this lock */
} kspinlock_t;
#if (RHINO_CONFIG_CPU_NUM > 1)
/* SMP spin lock */
#define krhino_spin_lock(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
cpu_spin_lock((lock)); \
s->cnt++; \
} while (0) \
#define krhino_spin_unlock(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cnt--; \
if (s->cnt == 0u) { \
cpu_spin_unlock((lock)); \
} \
} while (0)
#define krhino_spin_lock_irq_save(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cpsr = cpu_intrpt_save(); \
cpu_spin_lock((lock)); \
s->cnt++; \
} while (0)
#define krhino_spin_unlock_irq_restore(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cnt--; \
if (s->cnt == 0u) { \
cpu_spin_unlock((lock)); \
cpu_intrpt_restore(s->cpsr); \
} \
} while (0)
#define krhino_spin_init(lock) do{ \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->owner = (uint32_t)-1; \
s->cnt = 0u; \
} while(0)
#else
/* UP spin lock */
#define krhino_spin_lock(lock) krhino_sched_disable();
#define krhino_spin_unlock(lock) krhino_sched_enable();
#define krhino_spin_lock_irq_save(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cpsr = cpu_intrpt_save(); \
s->cnt++; \
} while (0)
#define krhino_spin_unlock_irq_restore(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cnt--; \
if (s->cnt == 0u) { \
cpu_intrpt_restore(s->cpsr); \
} \
} while (0)
#define krhino_spin_init(lock)
#endif
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
#define RHINO_CRITICAL_ENTER() \
do { \
RHINO_CPU_INTRPT_DISABLE(); \
intrpt_disable_measure_start(); \
} while (0)
#define RHINO_CRITICAL_EXIT() \
do { \
intrpt_disable_measure_stop(); \
RHINO_CPU_INTRPT_ENABLE(); \
} while (0)
#if (RHINO_CONFIG_CPU_NUM > 1)
#define RHINO_CRITICAL_EXIT_SCHED() \
do { \
intrpt_disable_measure_stop(); \
core_sched(); \
RHINO_CPU_INTRPT_ENABLE(); \
} while (0)
#else
#define RHINO_CRITICAL_EXIT_SCHED() \
do { \
intrpt_disable_measure_stop(); \
RHINO_CPU_INTRPT_ENABLE(); \
core_sched(); \
} while (0)
#endif
#else /* RHINO_CONFIG_DISABLE_INTRPT_STATS */
#define RHINO_CRITICAL_ENTER() \
do { \
RHINO_CPU_INTRPT_DISABLE(); \
} while (0)
#define RHINO_CRITICAL_EXIT() \
do { \
RHINO_CPU_INTRPT_ENABLE(); \
} while (0)
#if (RHINO_CONFIG_CPU_NUM > 1)
#define RHINO_CRITICAL_EXIT_SCHED() \
do { \
core_sched(); \
RHINO_CPU_INTRPT_ENABLE(); \
} while (0)
#else
#define RHINO_CRITICAL_EXIT_SCHED() \
do { \
RHINO_CPU_INTRPT_ENABLE(); \
core_sched(); \
} while (0)
#endif
#endif /* RHINO_CONFIG_DISABLE_INTRPT_STATS */
#endif /* K_CRITICAL_H */

View File

@@ -0,0 +1,314 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_DEFAULT_CONFIG_H
#define K_DEFAULT_CONFIG_H
#ifndef RHINO_CONFIG_CPU_PWR_MGMT
#define RHINO_CONFIG_CPU_PWR_MGMT 0
#endif
/* leave this option as default unless your compiler does not support 64 bit data such as uint64_t */
#ifndef RHINO_CONFIG_64_BIT_TYPE
#define RHINO_CONFIG_64_BIT_TYPE 1
#endif
/* chip level conf */
#ifndef RHINO_CONFIG_LITTLE_ENDIAN
#define RHINO_CONFIG_LITTLE_ENDIAN 1
#endif
#ifndef RHINO_CONFIG_CPU_STACK_DOWN
#define RHINO_CONFIG_CPU_STACK_DOWN 1
#endif
#ifndef RHINO_CONFIG_BITMAP_HW
#define RHINO_CONFIG_BITMAP_HW 0
#endif
/* kernel feature conf */
#ifndef RHINO_CONFIG_SEM
#define RHINO_CONFIG_SEM 0
#endif
#ifndef RHINO_CONFIG_QUEUE
#define RHINO_CONFIG_QUEUE 0
#endif
#ifndef RHINO_CONFIG_TASK_SEM
#define RHINO_CONFIG_TASK_SEM 0
#endif
#ifndef RHINO_CONFIG_WORKQUEUE
#define RHINO_CONFIG_WORKQUEUE 0
#endif
#ifndef RHINO_CONFIG_WORKQUEUE_STACK_SIZE
#define RHINO_CONFIG_WORKQUEUE_STACK_SIZE 512
#endif
#ifndef RHINO_CONFIG_WORKQUEUE_TASK_PRIO
#define RHINO_CONFIG_WORKQUEUE_TASK_PRIO 9
#endif
#ifndef RHINO_CONFIG_EVENT_FLAG
#define RHINO_CONFIG_EVENT_FLAG 0
#endif
#ifndef RHINO_CONFIG_TIMER
#define RHINO_CONFIG_TIMER 0
#endif
#ifndef RHINO_CONFIG_BUF_QUEUE
#define RHINO_CONFIG_BUF_QUEUE 0
#endif
#ifndef RHINO_CONFIG_MM_BLK
#define RHINO_CONFIG_MM_BLK 1
#endif
#ifndef RHINO_CONFIG_MM_TLF
#define RHINO_CONFIG_MM_TLF 1
#endif
#ifndef RHINO_CONFIG_MM_MAXMSIZEBIT
#define RHINO_CONFIG_MM_MAXMSIZEBIT 20
#endif
#ifndef RHINO_CONFIG_MM_TLF_BLK_SIZE
#define RHINO_CONFIG_MM_TLF_BLK_SIZE 8192
#endif
#ifndef RHINO_CONFIG_MM_DEBUG
#define RHINO_CONFIG_MM_DEBUG 0
#endif
#ifndef RHINO_CONFIG_GCC_RETADDR
#define RHINO_CONFIG_GCC_RETADDR 0
#endif
#ifndef RHINO_CONFIG_MM_LEAKCHECK
#define RHINO_CONFIG_MM_LEAKCHECK 0
#endif
#ifndef K_MM_STATISTIC
#define K_MM_STATISTIC 0
#endif
#ifndef RHINO_CONFIG_TASK_SEM
#define RHINO_CONFIG_TASK_SEM 0
#endif
/* kernel task conf */
#ifndef RHINO_CONFIG_TASK_PRI_CHG
#define RHINO_CONFIG_TASK_PRI_CHG 1
#endif
#ifndef RHINO_CONFIG_TASK_INFO
#define RHINO_CONFIG_TASK_INFO 0
#endif
#ifndef RHINO_CONFIG_TASK_INFO_NUM
#define RHINO_CONFIG_TASK_INFO_NUM 2
#endif
#ifndef RHINO_CONFIG_TASK_DEL
#define RHINO_CONFIG_TASK_DEL 0
#endif
#ifndef RHINO_CONFIG_TASK_STACK_CUR_CHECK
#define RHINO_CONFIG_TASK_STACK_CUR_CHECK 0
#endif
#ifndef RHINO_CONFIG_TASK_WAIT_ABORT
#define RHINO_CONFIG_TASK_WAIT_ABORT 0
#endif
#ifndef RHINO_CONFIG_SCHED_RR
#define RHINO_CONFIG_SCHED_RR 0
#endif
#ifndef RHINO_CONFIG_TIME_SLICE_DEFAULT
#define RHINO_CONFIG_TIME_SLICE_DEFAULT 50
#endif
#ifndef RHINO_CONFIG_PRI_MAX
#define RHINO_CONFIG_PRI_MAX 62
#endif
#ifndef RHINO_CONFIG_USER_PRI_MAX
#define RHINO_CONFIG_USER_PRI_MAX (RHINO_CONFIG_PRI_MAX - 2)
#endif
#ifndef RHINO_CONFIG_RINGBUF_VENDOR
#define RHINO_CONFIG_RINGBUF_VENDOR 0
#endif
/* kernel mm_region conf */
#ifndef RHINO_CONFIG_MM_REGION_MUTEX
#define RHINO_CONFIG_MM_REGION_MUTEX 1
#endif
/* kernel timer&tick conf */
#ifndef RHINO_CONFIG_HW_COUNT
#define RHINO_CONFIG_HW_COUNT 0
#endif
#ifndef RHINO_CONFIG_TICKS_PER_SECOND
#define RHINO_CONFIG_TICKS_PER_SECOND 100
#endif
#ifndef RHINO_CONFIG_TIMER_TASK_STACK_SIZE
#define RHINO_CONFIG_TIMER_TASK_STACK_SIZE 200
#endif
#ifndef RHINO_CONFIG_TIMER_RATE
#define RHINO_CONFIG_TIMER_RATE 1
#endif
#ifndef RHINO_CONFIG_TIMER_TASK_PRI
#define RHINO_CONFIG_TIMER_TASK_PRI 5
#endif
#ifndef RHINO_CONFIG_TIMER_MSG_NUM
#define RHINO_CONFIG_TIMER_MSG_NUM 20
#endif
/* kernel intrpt conf */
#ifndef RHINO_CONFIG_INTRPT_STACK_REMAIN_GET
#define RHINO_CONFIG_INTRPT_STACK_REMAIN_GET 0
#endif
#ifndef RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL
#define RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL 188u
#endif
#ifndef RHINO_CONFIG_INTRPT_GUARD
#define RHINO_CONFIG_INTRPT_GUARD 0
#endif
/* kernel stack ovf check */
#ifndef RHINO_CONFIG_INTRPT_STACK_OVF_CHECK
#define RHINO_CONFIG_INTRPT_STACK_OVF_CHECK 0
#endif
#ifndef RHINO_CONFIG_TASK_STACK_OVF_CHECK
#define RHINO_CONFIG_TASK_STACK_OVF_CHECK 0
#endif
/* kernel dyn alloc conf */
#ifndef RHINO_CONFIG_KOBJ_DYN_ALLOC
#define RHINO_CONFIG_KOBJ_DYN_ALLOC 0
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
#ifndef RHINO_CONFIG_K_DYN_QUEUE_MSG
#define RHINO_CONFIG_K_DYN_QUEUE_MSG 30
#endif
#ifndef RHINO_CONFIG_K_DYN_TASK_STACK
#define RHINO_CONFIG_K_DYN_TASK_STACK 256
#endif
#ifndef RHINO_CONFIG_K_DYN_MEM_TASK_PRI
#define RHINO_CONFIG_K_DYN_MEM_TASK_PRI RHINO_CONFIG_USER_PRI_MAX
#endif
#endif /* RHINO_CONFIG_KOBJ_DYN_ALLOC */
/* kernel idle conf */
#ifndef RHINO_CONFIG_IDLE_TASK_STACK_SIZE
#define RHINO_CONFIG_IDLE_TASK_STACK_SIZE 100
#endif
/* kernel hook conf */
#ifndef RHINO_CONFIG_USER_HOOK
#define RHINO_CONFIG_USER_HOOK 1
#endif
/* kernel stats conf */
#ifndef RHINO_CONFIG_SYSTEM_STATS
#define RHINO_CONFIG_SYSTEM_STATS 0
#endif
#ifndef RHINO_CONFIG_DISABLE_SCHED_STATS
#define RHINO_CONFIG_DISABLE_SCHED_STATS 0
#endif
#ifndef RHINO_CONFIG_DISABLE_INTRPT_STATS
#define RHINO_CONFIG_DISABLE_INTRPT_STATS 0
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_STATS
#define RHINO_CONFIG_CPU_USAGE_STATS 0
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_TASK_PRI
#define RHINO_CONFIG_CPU_USAGE_TASK_PRI (RHINO_CONFIG_PRI_MAX - 2)
#endif
#ifndef RHINO_CONFIG_TASK_SCHED_STATS
#define RHINO_CONFIG_TASK_SCHED_STATS 0
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_TASK_STACK
#define RHINO_CONFIG_CPU_USAGE_TASK_STACK 256
#endif
/* kernel trace conf */
#ifndef RHINO_CONFIG_TRACE
#define RHINO_CONFIG_TRACE 0
#endif
#ifndef RHINO_CONFIG_CPU_NUM
#define RHINO_CONFIG_CPU_NUM 1
#endif
#ifdef RHINO_CONFIG_ISR_TASK
#ifndef RHINO_CONFIG_ISR_BUFF_SIZE
#define RHINO_CONFIG_ISR_BUFF_SIZE (16)
#endif
#ifndef RHINO_CONFIG_ISR_TASK_PRI
#define RHINO_CONFIG_ISR_TASK_PRI (1)
#endif
#ifndef RHINO_CONFIG_ISR_TASK_STACK_SIZE
#define RHINO_CONFIG_ISR_TASK_STACK_SIZE (1024)
#endif
#endif
#if ((RHINO_CONFIG_TIMER >= 1) && (RHINO_CONFIG_BUF_QUEUE == 0))
#error "RHINO_CONFIG_BUF_QUEUE should be 1 when RHINO_CONFIG_TIMER is enabled."
#endif
#if ((RHINO_CONFIG_MM_TLF >= 1) && (RHINO_CONFIG_MM_BLK == 0))
#error "RHINO_CONFIG_MM_BLK should be 1 when RHINO_CONFIG_MM_TLF is enabled."
#endif
#if ((RHINO_CONFIG_KOBJ_DYN_ALLOC >= 1) && (RHINO_CONFIG_MM_TLF == 0))
#error "RHINO_CONFIG_MM_TLF should be 1 when RHINO_CONFIG_KOBJ_DYN_ALLOC is enabled."
#endif
#if (RHINO_CONFIG_PRI_MAX >= 256)
#error "RHINO_CONFIG_PRI_MAX must be <= 255."
#endif
#if ((RHINO_CONFIG_SEM == 0) && (RHINO_CONFIG_TASK_SEM >= 1))
#error "you need enable RHINO_CONFIG_SEM as well."
#endif
#if ((RHINO_CONFIG_HW_COUNT == 0) && (RHINO_CONFIG_TASK_SCHED_STATS >= 1))
#error "you need enable RHINO_CONFIG_HW_COUNT as well."
#endif
#if ((RHINO_CONFIG_HW_COUNT == 0) && (RHINO_CONFIG_DISABLE_SCHED_STATS >= 1))
#error "you need enable RHINO_CONFIG_HW_COUNT as well."
#endif
#if ((RHINO_CONFIG_HW_COUNT == 0) && (RHINO_CONFIG_DISABLE_INTRPT_STATS >= 1))
#error "you need enable RHINO_CONFIG_HW_COUNT as well."
#endif
#endif /* K_DEFAULT_CONFIG_H */

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_ENDIAN_H
#define K_ENDIAN_H
#if (RHINO_CONFIG_LITTLE_ENDIAN != 1)
#define krhino_htons(x) x
#define krhino_htonl(x) x
#define krhino_ntohl(x) x
#define krhino_ntohs(x) x
#else
#ifndef krhino_htons
#define krhino_htons(x) ((uint16_t)(((x) & 0x00ffU) << 8)| \
(((x) & 0xff00U) >> 8))
#endif
#ifndef krhino_htonl
#define krhino_htonl(x) ((uint32_t)(((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24))
#endif
#ifndef krhino_ntohs
#define krhino_ntohs(x) ((uint16_t)((x & 0x00ffU) << 8) | \
((x & 0xff00U) >> 8))
#endif
#ifndef krhino_ntohl
#define krhino_ntohl(x) ((uint32_t)(((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24))
#endif
#endif /*RHINO_CONFIG_LITTLE_ENDIAN*/
#endif

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_ERR_H
#define K_ERR_H
typedef enum {
RHINO_SUCCESS = 0u,
RHINO_SYS_FATAL_ERR,
RHINO_SYS_SP_ERR,
RHINO_RUNNING,
RHINO_STOPPED,
RHINO_INV_PARAM,
RHINO_NULL_PTR,
RHINO_INV_ALIGN,
RHINO_KOBJ_TYPE_ERR,
RHINO_KOBJ_DEL_ERR,
RHINO_KOBJ_DOCKER_EXIST,
RHINO_KOBJ_BLK,
RHINO_KOBJ_SET_FULL,
RHINO_NOTIFY_FUNC_EXIST,
RHINO_MM_POOL_SIZE_ERR = 100u,
RHINO_MM_ALLOC_SIZE_ERR,
RHINO_MM_FREE_ADDR_ERR,
RHINO_MM_CORRUPT_ERR,
RHINO_DYN_MEM_PROC_ERR,
RHINO_NO_MEM,
RHINO_RINGBUF_FULL,
RHINO_RINGBUF_EMPTY,
RHINO_SCHED_DISABLE = 200u,
RHINO_SCHED_ALREADY_ENABLED,
RHINO_SCHED_LOCK_COUNT_OVF,
RHINO_INV_SCHED_WAY,
RHINO_TASK_INV_STACK_SIZE = 300u,
RHINO_TASK_NOT_SUSPENDED,
RHINO_TASK_DEL_NOT_ALLOWED,
RHINO_TASK_SUSPEND_NOT_ALLOWED,
RHINO_SUSPENDED_COUNT_OVF,
RHINO_BEYOND_MAX_PRI,
RHINO_PRI_CHG_NOT_ALLOWED,
RHINO_INV_TASK_STATE,
RHINO_IDLE_TASK_EXIST,
RHINO_NO_PEND_WAIT = 400u,
RHINO_BLK_ABORT,
RHINO_BLK_TIMEOUT,
RHINO_BLK_DEL,
RHINO_BLK_INV_STATE,
RHINO_BLK_POOL_SIZE_ERR,
RHINO_TIMER_STATE_INV = 500u,
RHINO_NO_THIS_EVENT_OPT = 600u,
RHINO_BUF_QUEUE_INV_SIZE = 700u,
RHINO_BUF_QUEUE_SIZE_ZERO,
RHINO_BUF_QUEUE_FULL,
RHINO_BUF_QUEUE_MSG_SIZE_OVERFLOW,
RHINO_QUEUE_FULL,
RHINO_QUEUE_NOT_FULL,
RHINO_SEM_OVF = 800u,
RHINO_SEM_TASK_WAITING,
RHINO_MUTEX_NOT_RELEASED_BY_OWNER = 900u,
RHINO_MUTEX_OWNER_NESTED,
RHINO_MUTEX_NESTED_OVF,
RHINO_INTRPT_NESTED_LEVEL_OVERFLOW = 1000u,
RHINO_INV_INTRPT_NESTED_LEVEL,
RHINO_NOT_CALLED_BY_INTRPT,
RHINO_TRY_AGAIN,
RHINO_WORKQUEUE_EXIST = 1100u,
RHINO_WORKQUEUE_NOT_EXIST,
RHINO_WORKQUEUE_WORK_EXIST,
RHINO_WORKQUEUE_BUSY,
RHINO_WORKQUEUE_WORK_RUNNING,
RHINO_TASK_STACK_OVF = 1200u,
RHINO_INTRPT_STACK_OVF,
RHINO_INTRPT_ISR_OVF,
} kstat_t;
typedef void (*krhino_err_proc_t)(kstat_t err);
extern krhino_err_proc_t g_err_proc;
#endif /* K_ERR_H */

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_EVENT_H
#define K_EVENT_H
typedef struct {
blk_obj_t blk_obj;
uint32_t flags;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t event_item;
#endif
uint8_t mm_alloc_flag;
} kevent_t;
#define RHINO_FLAGS_AND_MASK 0x2u
#define RHINO_FLAGS_CLEAR_MASK 0x1u
#define RHINO_AND 0x02u
#define RHINO_AND_CLEAR 0x03u
#define RHINO_OR 0x00u
#define RHINO_OR_CLEAR 0x01u
/**
* This function will create a event
* @param[in] event pointer to the event
* @param[in] name name of the event
* @param[in] flags flags to be init
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_create(kevent_t *event, const name_t *name, uint32_t flags);
/**
* This function will delete a event
* @param[in] event pointer to a event
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_del(kevent_t *event);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn-event
* @param[out] event pointer to the event
* @param[in] name name of the semaphore
* @param[in] flags flags to be init
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_dyn_create(kevent_t **event, const name_t *name,
uint32_t flags);
/**
* This function will delete a dyn created event
* @param[in] event pointer to a event
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_dyn_del(kevent_t *event);
#endif
/**
* This function will get event
* @param[in] event pointer to the event
* @param[in] flags which is provided by users
* @param[in] opt could be RHINO_AND, RHINO_AND_CLEAR, RHINO_OR, RHINO_OR_CLEAR
* @param[out] actl_flags the actually flag where flags is satisfied
* @param[in] ticks ticks to wait
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_get(kevent_t *event, uint32_t flags, uint8_t opt,
uint32_t *actl_flags, tick_t ticks);
/**
* This function will set a event
* @param[in] event pointer to a event
* @param[in] flags which users want to be set
* @param[in] opt could be RHINO_AND, RHINO_OR
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_set(kevent_t *event, uint32_t flags, uint8_t opt);
#endif /* K_EVENT_H */

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef FIFO_H
#define FIFO_H
#ifdef __cplusplus
extern "C" {
#endif
struct k_fifo {
uint32_t in;
uint32_t out;
uint32_t mask;
void *data;
uint32_t free_bytes;
uint32_t size;
};
#define fifo_min(x, y) ((x) > (y)?(y):(x))
#define fifo_max(x, y) ((x) > (y)?(x):(y))
/**
* This function will init the fifo.
* @param[in] fifo pointer to fifo
* @param[in] buffer pointer to fifo buffer
* @param[in] size size of fifo buffer
* @return the operation status, 0 is OK, others is error
*/
int8_t fifo_init(struct k_fifo *fifo, void *buffer, uint32_t size);
/**
* This function will write buf to fifo.
* @param[in] fifo pointer to fifo
* @param[in] buf pointer to buffer write
* @param[in] size size of buffer
* @return the size has been written to the fifo
*/
uint32_t fifo_in(struct k_fifo *fifo, const void *buf, uint32_t len);
/**
* This function will read fifo data to buf
* @param[in] fifo pointer to fifo
* @param[in] buf pointer to buffer read
* @param[in] len len of buffer
* @return the size has read
*/
uint32_t fifo_out(struct k_fifo *fifo, void *buf, uint32_t len);
/**
* This function will read fifo data to bufbut data remain in fifo
* @param[in] fifo pointer to fifo
* @param[in] buf pointer to buffer read
* @param[in] len len of buffer
* @return the size has read
*/
uint32_t fifo_out_peek(struct k_fifo *fifo,
void *buf, uint32_t len);
/**
* This function will read fifo all data
* @param[in] fifo pointer to fifo
* @param[in] buf pointer to buffer read
* @return the size has read
*/
uint32_t fifo_out_all(struct k_fifo *fifo, void *buf);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_HOOK_H
#define K_HOOK_H
#if (RHINO_CONFIG_USER_HOOK > 0)
/**
* This function will provide init hook
*/
void krhino_init_hook(void);
/**
* This function will provide system start hook
*/
void krhino_start_hook(void);
/**
* This function will provide task create hook
* @param[in] task pointer to the task
*/
void krhino_task_create_hook(ktask_t *task);
/**
* This function will provide task delete hook
* @param[in] task pointer to the task
*/
void krhino_task_del_hook(ktask_t *task, res_free_t *arg);
/**
* This function will provide task abort hook
* @param[in] task pointer to the task
*/
void krhino_task_abort_hook(ktask_t *task);
/**
* This function will provide task switch hook
*/
void krhino_task_switch_hook(ktask_t *orgin, ktask_t *dest);
/**
* This function will provide system tick hook
*/
void krhino_tick_hook(void);
/**
* This function will provide idle hook
*/
void krhino_idle_hook(void);
/**
* This function will provide idle pre hook
*/
void krhino_idle_pre_hook(void);
/**
* This function will provide krhino_mm_alloc hook
*/
void krhino_mm_alloc_hook(void *mem, size_t size);
#endif
#endif /* K_HOOK_H */

View File

@@ -0,0 +1,193 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_INTERNAL_H
#define K_INTERNAL_H
extern kstat_t g_sys_stat;
extern uint8_t g_idle_task_spawned[RHINO_CONFIG_CPU_NUM];
extern runqueue_t g_ready_queue;
/* System lock */
extern uint8_t g_sched_lock[RHINO_CONFIG_CPU_NUM];
extern uint8_t g_intrpt_nested_level[RHINO_CONFIG_CPU_NUM];
/* highest pri ready task object */
extern ktask_t *g_preferred_ready_task[RHINO_CONFIG_CPU_NUM];
/* current active task */
extern ktask_t *g_active_task[RHINO_CONFIG_CPU_NUM];
/* idle attribute */
extern ktask_t g_idle_task[RHINO_CONFIG_CPU_NUM];
extern idle_count_t g_idle_count[RHINO_CONFIG_CPU_NUM];
extern cpu_stack_t g_idle_task_stack[RHINO_CONFIG_CPU_NUM][RHINO_CONFIG_IDLE_TASK_STACK_SIZE];
/* tick attribute */
extern tick_t g_tick_count;
extern klist_t g_tick_head;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
extern kobj_list_t g_kobj_list;
#endif
#if (RHINO_CONFIG_TIMER > 0)
extern klist_t g_timer_head;
extern sys_time_t g_timer_count;
extern ktask_t g_timer_task;
extern cpu_stack_t g_timer_task_stack[RHINO_CONFIG_TIMER_TASK_STACK_SIZE];
extern kbuf_queue_t g_timer_queue;
extern k_timer_queue_cb timer_queue_cb[RHINO_CONFIG_TIMER_MSG_NUM];
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
extern hr_timer_t g_sched_disable_time_start;
extern hr_timer_t g_sched_disable_max_time;
extern hr_timer_t g_cur_sched_disable_max_time;
#endif
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
extern uint16_t g_intrpt_disable_times;
extern hr_timer_t g_intrpt_disable_time_start;
extern hr_timer_t g_intrpt_disable_max_time;
extern hr_timer_t g_cur_intrpt_disable_max_time;
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
extern hr_timer_t g_sys_measure_waste;
#endif
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
extern ktask_t g_cpu_usage_task;
extern cpu_stack_t g_cpu_task_stack[RHINO_CONFIG_CPU_USAGE_TASK_STACK];
extern idle_count_t g_idle_count_max;
extern uint32_t g_cpu_usage;
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
extern ctx_switch_t g_sys_ctx_switch_times;
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
extern ksem_t g_res_sem;
extern klist_t g_res_list;
extern ktask_t g_dyn_task;
extern cpu_stack_t g_dyn_task_stack[RHINO_CONFIG_K_DYN_TASK_STACK];
#endif
#if (RHINO_CONFIG_WORKQUEUE > 0)
extern klist_t g_workqueue_list_head;
extern kmutex_t g_workqueue_mutex;
extern kworkqueue_t g_workqueue_default;
extern cpu_stack_t g_workqueue_stack[RHINO_CONFIG_WORKQUEUE_STACK_SIZE];
#endif
#if (RHINO_CONFIG_MM_TLF > 0)
extern k_mm_head *g_kmm_head;
#endif
#ifdef RHINO_CONFIG_ISR_TASK
extern ktask_t g_isr_task;
extern ksem_t g_isr_sem;
extern uint32_t g_isr_buff[4+2*RHINO_CONFIG_ISR_BUFF_SIZE];
extern cpu_stack_t g_isr_task_stack[RHINO_CONFIG_ISR_TASK_STACK_SIZE];
#endif
extern kspinlock_t g_sys_lock;
extern uint8_t g_in_interrupt;
#define K_OBJ_STATIC_ALLOC 1u
#define K_OBJ_DYN_ALLOC 2u
#define NULL_PARA_CHK(para) \
do { \
if (para == NULL) { \
return RHINO_NULL_PTR; \
} \
} while (0)
#define INTRPT_NESTED_LEVEL_CHK()\
do { \
if (g_intrpt_nested_level[cpu_cur_get()] > 0u) { \
RHINO_CRITICAL_EXIT(); \
return RHINO_NOT_CALLED_BY_INTRPT; \
} \
} while (0)
#define RES_FREE_NUM 4
typedef struct {
uint8_t cnt;
void *res[RES_FREE_NUM];
klist_t res_list;
} res_free_t;
void preferred_cpu_ready_task_get(runqueue_t *rq, uint8_t cpu_num);
void core_sched(void);
void runqueue_init(runqueue_t *rq);
void ready_list_add(runqueue_t *rq, ktask_t *task);
void ready_list_add_head(runqueue_t *rq, ktask_t *task);
void ready_list_add_tail(runqueue_t *rq, ktask_t *task);
void ready_list_rm(runqueue_t *rq, ktask_t *task);
void ready_list_head_to_tail(runqueue_t *rq, ktask_t *task);
void time_slice_update(void);
void timer_task_sched(void);
void pend_list_reorder(ktask_t *task);
void pend_task_wakeup(ktask_t *task);
void pend_to_blk_obj(blk_obj_t *blk_obj, ktask_t *task, tick_t timeout, uint32_t psr);
void pend_task_rm(ktask_t *task);
kstat_t pend_state_end_proc(ktask_t *task);
void idle_task(void *p_arg);
void idle_count_set(idle_count_t value);
idle_count_t idle_count_get(void);
void tick_list_init(void);
void tick_task_start(void);
void tick_list_rm(ktask_t *task);
void tick_list_insert(ktask_t *task, tick_t time);
void tick_list_update(tick_i_t ticks);
uint8_t mutex_pri_limit(ktask_t *tcb, uint8_t pri);
void mutex_task_pri_reset(ktask_t *tcb);
uint8_t mutex_pri_look(ktask_t *tcb, kmutex_t *mutex_rel);
kstat_t task_pri_change(ktask_t *task, uint8_t new_pri);
void k_err_proc(kstat_t err);
void ktimer_init(void);
void kisr_init(void);
void intrpt_disable_measure_start(void);
void intrpt_disable_measure_stop(void);
void dyn_mem_proc_task_start(void);
void cpu_usage_stats_start(void);
void dym_mem_proc_hdl(void);
kstat_t ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len, size_t type,
size_t block_size);
kstat_t ringbuf_reset(k_ringbuf_t *p_ringbuf);
kstat_t ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len);
kstat_t ringbuf_head_push(k_ringbuf_t *p_ringbuf, void *data, size_t len);
kstat_t ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen);
uint8_t ringbuf_is_full(k_ringbuf_t *p_ringbuf);
uint8_t ringbuf_is_empty(k_ringbuf_t *p_ringbuf);
void workqueue_init(void);
//void k_mm_init(void);
#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
void cpu_pwr_down(void);
void cpu_pwr_up(void);
#endif
#endif /* K_INTERNAL_H */

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_LIST_H
#define K_LIST_H
typedef struct klist_s {
struct klist_s *next;
struct klist_s *prev;
} klist_t;
#define krhino_list_entry(node, type, member) ((type *)((uint8_t *)(node) - (size_t)(&((type *)0)->member)))
RHINO_INLINE void klist_init(klist_t *list_head)
{
list_head->next = list_head;
list_head->prev = list_head;
}
RHINO_INLINE uint8_t is_klist_empty(klist_t *list)
{
return (list->next == list);
}
RHINO_INLINE void klist_insert(klist_t *head, klist_t *element)
{
element->prev = head->prev;
element->next = head;
head->prev->next = element;
head->prev = element;
}
RHINO_INLINE void klist_add(klist_t *head, klist_t *element)
{
element->prev = head;
element->next = head->next;
head->next->prev = element;
head->next = element;
}
RHINO_INLINE void klist_rm(klist_t *element)
{
element->prev->next = element->next;
element->next->prev = element->prev;
}
RHINO_INLINE void klist_rm_init(klist_t *element)
{
element->prev->next = element->next;
element->next->prev = element->prev;
element->next = element->prev = element;
}
#endif /* K_LIST_H */

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MM_H
#define K_MM_H
#ifdef HAVE_VALGRIND_H
#include <valgrind.h>
#include <memcheck.h>
#define VGF(X) X
#elif defined(HAVE_VALGRIND_VALGRIND_H)
#include <valgrind/valgrind.h>
#include <valgrind/memcheck.h>
#define VGF(X) X
#else
#define VGF(X)
#endif
/*use two level bit map to find free memory block*/
#if (RHINO_CONFIG_MM_TLF > 0)
#define MAX_MM_BIT RHINO_CONFIG_MM_MAXMSIZEBIT
#define MAX_MM_SIZE (1<<MAX_MM_BIT)
#define FIX_BLK_BIT 5 /*32 bytes*/
#define DEF_FIX_BLK_SIZE (1<<FIX_BLK_BIT) /*32 bytes*/
#define MIN_FLT_BIT 7 /*<2^7 only need one level mapping */
#define MIN_FLT_SIZE (1<<MIN_FLT_BIT)
#define MAX_LOG2_SLT 5
#define SLT_SIZE (1<<MAX_LOG2_SLT)
#define FLT_SIZE (MAX_MM_BIT - MIN_FLT_BIT + 1)
#define MM_ALIGIN_SIZE (1<<(MIN_FLT_BIT - MAX_LOG2_SLT))
#define MM_ALIGN_MASK (sizeof(void*)-1)
#define MM_ALIGN_UP(a) (((a) + MM_ALIGN_MASK) & ~MM_ALIGN_MASK)
#define MM_ALIGN_DOWN(a) ((a) & ~MM_ALIGN_MASK)
#define RHINO_MM_BLKSIZE_MASK (0xFFFFFFFF - MM_ALIGN_MASK)
#define DEF_TOTAL_FIXEDBLK_SIZE 8192 /*by default, total 2k momory fo fix size block */
#define MIN_FREE_MEMORY_SIZE 1024 /*at least need 1k for user alloced*/
/*bit 0 and bit 1 mask*/
#define RHINO_MM_CURSTAT_MASK 0x1
#define RHINO_MM_PRESTAT_MASK 0x2
/*bit 0*/
#define RHINO_MM_FREE 1
#define RHINO_MM_ALLOCED 0
/*bit 1*/
#define RHINO_MM_PREVFREE 2
#define RHINO_MM_PREVALLOCED 0
#define NEXT_MM_BLK(_addr, _r) ((k_mm_list_t *) ((uint8_t *) (_addr) + (_r)))
#define MMLIST_HEAD_SIZE (sizeof(k_mm_list_t) - sizeof(free_ptr_t))
/*
-------------------------------------------------------------------
| k_mm_list_t |k_mm_region_info_t|k_mm_list_t|free space |k_mm_list_t|
-------------------------------------------------------------------
*/
#define MMREGION_USED_SIZE (MM_ALIGN_UP(sizeof(k_mm_region_info_t)) + 3 * MMLIST_HEAD_SIZE )
/*struct of memory list ,every memory block include this information*/
typedef struct free_ptr_struct {
struct k_mm_list_struct *prev;
struct k_mm_list_struct *next;
} free_ptr_t;
typedef struct k_mm_list_struct {
#if (RHINO_CONFIG_MM_DEBUG > 0)
size_t dye;
size_t owner;
#endif
struct k_mm_list_struct *prev;
size_t size;
/* bit 0 indicates whether the block is used and */
/* bit 1 allows to know whether the previous block is free */
union {
struct free_ptr_struct free_ptr;
uint8_t buffer[1];
} mbinfo;
} k_mm_list_t;
typedef struct k_mm_region_info_struct {
k_mm_list_t *end;
struct k_mm_region_info_struct *next;
} k_mm_region_info_t;
typedef struct {
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
kmutex_t mm_mutex;
#endif
k_mm_region_info_t *regioninfo;
k_mm_list_t *fixedmblk;
#if (K_MM_STATISTIC > 0)
size_t used_size;
size_t maxused_size;
size_t free_size;
size_t mm_size_stats[MAX_MM_BIT];
#endif
uint32_t fl_bitmap;
uint32_t sl_bitmap[FLT_SIZE]; /* the second-level bitmap */
k_mm_list_t *mm_tbl[FLT_SIZE][SLT_SIZE];
} k_mm_head;
kstat_t krhino_init_mm_head(k_mm_head **ppmmhead, void *addr, size_t len );
kstat_t krhino_deinit_mm_head(k_mm_head *mmhead);
kstat_t krhino_add_mm_region(k_mm_head *mmhead, void *addr, size_t len);
void *k_mm_alloc(k_mm_head *mmhead, size_t size);
void k_mm_free(k_mm_head *mmhead, void *ptr);
void *k_mm_realloc(k_mm_head *mmhead, void *oldmem, size_t new_size);
#endif
/**
* This function is wrapper of mm allocation
* @param[in] size size of the mem to malloc
* @return the operation status, NULL is error, others is memory address
*/
void *krhino_mm_alloc(size_t size, void *caller);
/**
* This function is wrapper of mm free
* @param[in] ptr address point of the mem
*/
void krhino_mm_free(void *ptr);
/**
* This function is wrapper of mm rallocation
* @param[in] oldmem oldmem address
* @param[in] size size of the mem to malloc
* @return the operation status, NULL is error, others is realloced memory address
*/
void *krhino_mm_realloc(void *oldmem, size_t newsize, void *caller);
#endif /* K_MM_BESTFIT_H */

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MM_BLK_H
#define K_MM_BLK_H
typedef struct {
kobj_type_t obj_type;
const name_t *pool_name;
size_t blk_size;
size_t blk_avail;
size_t blk_whole;
uint8_t *avail_list;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t mblkpool_stats_item;
#endif
} mblk_pool_t;
/**
* This function will init a blk-pool
* @param[in] pool pointer to the pool
* @param[in] name name of the pool
* @param[in] pool_start start addr of the pool
* @param[in] blk_size size of the blk
* @param[in] pool_size size of the pool
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mblk_pool_init(mblk_pool_t *pool, const name_t *name,
void *pool_start,
size_t blk_size, size_t pool_size);
/**
* This function will alloc a blk-pool
* @param[in] pool pointer to a pool
* @param[in] blk pointer to a blk
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mblk_alloc(mblk_pool_t *pool, void **blk);
/**
* This function will free a blk-pool
* @param[in] pool pointer to the pool
* @param[in] blk pointer to the blk
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mblk_free(mblk_pool_t *pool, void *blk);
#endif /* K_MM_BLK_H */

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef RHINO_MM_DEBUG_H
#define RHINO_MM_DEBUG_H
#if (RHINO_CONFIG_MM_DEBUG > 0)
#ifdef __cplusplus
extern "C" {
#endif
#define AOS_MM_SCAN_REGION_MAX 10
typedef struct {
void *start;
void *end;
} mm_scan_region_t;
#if (RHINO_CONFIG_GCC_RETADDR > 0u)
#include <k_mm.h>
#define AOS_UNSIGNED_INT_MSB (1u << (sizeof(unsigned int) * 8 - 1))
void krhino_owner_attach(k_mm_head *mmhead, void *addr, size_t allocator);
#endif
uint32_t krhino_mm_leak_region_init(void *start, void *end);
uint32_t dumpsys_mm_info_func(char *buf, uint32_t len);
uint32_t dump_mmleak(void);
#ifdef __cplusplus
}
#endif
#endif /* RHINO_CONFIG_MM_DEBUG */
#endif /* YSH_H */

View File

@@ -0,0 +1,14 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MM_REGION_H
#define K_MM_REGION_H
typedef struct {
uint8_t *start;
size_t len;
} k_mm_region_t;
#endif /* K_MM_REGION_H */

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MUTEX_H
#define K_MUTEX_H
typedef struct mutex_s {
blk_obj_t blk_obj;
ktask_t *mutex_task; /* mutex owner task */
struct mutex_s *mutex_list; /* task mutex list */
mutex_nested_t owner_nested;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t mutex_item;
#endif
uint8_t mm_alloc_flag;
} kmutex_t;
/**
* This function will create a mutex
* @param[in] mutex pointer to the mutex(the space is provided by user)
* @param[in] name name of the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_create(kmutex_t *mutex, const name_t *name);
/**
* This function will delete a mutex
* @param[in] mutex pointer to the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_del(kmutex_t *mutex);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn mutex
* @param[in] mutex pointer to the mutex(the space is provided by user)
* @param[in] name name of the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_dyn_create(kmutex_t **mutex, const name_t *name);
/**
* This function will delete a dyn mutex
* @param[in] mutex pointer to the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_dyn_del(kmutex_t *mutex);
#endif
/**
* This function will lock mutex
* @param[in] mutex pointer to the mutex
* @param[in] ticks ticks to be wait for before lock
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_lock(kmutex_t *mutex, tick_t ticks, uint32_t lr);
/**
* This function will unlock a mutex
* @param[in] mutex pointer to the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_unlock(kmutex_t *mutex);
#endif /* K_MUTEX_H */

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_OBJ_H
#define K_OBJ_H
typedef enum {
BLK_POLICY_PRI = 0u,
BLK_POLICY_FIFO
} blk_policy_t;
typedef enum {
BLK_FINISH = 0,
BLK_ABORT,
BLK_TIMEOUT,
BLK_DEL,
BLK_INVALID
} blk_state_t;
typedef enum {
RHINO_OBJ_TYPE_NONE = 0,
RHINO_SEM_OBJ_TYPE,
RHINO_MUTEX_OBJ_TYPE,
RHINO_QUEUE_OBJ_TYPE,
RHINO_BUF_QUEUE_OBJ_TYPE,
RHINO_TIMER_OBJ_TYPE,
RHINO_EVENT_OBJ_TYPE,
RHINO_MM_BLK_OBJ_TYPE,
RHINO_MM_OBJ_TYPE,
RHINO_BLKLIST_OBJ_TYPE,
} kobj_type_t;
typedef struct blk_obj {
klist_t blk_list;
const name_t *name;
uint8_t blk_policy; // blk_policy_t
uint8_t obj_type; // blk_state_t
} blk_obj_t;
typedef struct {
klist_t task_head;
klist_t mutex_head;
#if (RHINO_CONFIG_MM_BLK > 0)
klist_t mblkpool_head;
#endif
#if (RHINO_CONFIG_SEM > 0)
klist_t sem_head;
#endif
#if (RHINO_CONFIG_QUEUE > 0)
klist_t queue_head;
#endif
#if (RHINO_CONFIG_EVENT_FLAG > 0)
klist_t event_head;
#endif
#if (RHINO_CONFIG_BUF_QUEUE > 0)
klist_t buf_queue_head;
#endif
} kobj_list_t;
#endif /* K_OBJ_H */

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_QUEUE_H
#define K_QUEUE_H
#define WAKE_ONE_TASK 0u
#define WAKE_ALL_TASK 1u
typedef struct {
void **queue_start;
size_t size;
size_t cur_num;
size_t peak_num;
} msg_q_t;
typedef struct {
msg_q_t msg_q;
klist_t *pend_entry;
} msg_info_t;
typedef struct queue_s {
blk_obj_t blk_obj;
k_ringbuf_t ringbuf;
msg_q_t msg_q;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t queue_item;
#endif
uint8_t mm_alloc_flag;
} kqueue_t;
/**
* This function will create a queue
* @param[in] queue pointer to the queue(the space is provided by user)
* @param[in] name name of the queue
* @param[in] start start address of the queue internal space
* @param[in] msg_num num of the msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_create(kqueue_t *queue, const name_t *name, void **start,
size_t msg_num);
/**
* This function will delete a queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_del(kqueue_t *queue);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn queue
* @param[in] queue pointer to the queue
* @param[in] name name of the queue
* @param[in] msg_num num of the msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_dyn_create(kqueue_t **queue, const name_t *name,
size_t msg_num);
/**
* This function will delete a dyn created queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_dyn_del(kqueue_t *queue);
#endif
/**
* This function will send a msg to the back of a queue
* @param[in] queue pointer to the queue
* @param[in] msg msg to send
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_back_send(kqueue_t *queue, void *msg);
/**
* This function will send a msg to a queue and wake all tasks
* @param[in] queue pointer to the queue
* @param[in] msg msg to send
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_all_send(kqueue_t *queue, void *msg);
/**
* This function will receive msg from a queue
* @param[in] queue pointer to the queue
* @param[in] ticks ticks to wait before receive
* @param[out] msg buf to save msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_recv(kqueue_t *queue, tick_t ticks, void **msg);
/**
* This function will detect a queue full or not
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_QUEUE_FULL/RHINO_QUEUE_NOT_FULL
*/
kstat_t krhino_queue_is_full(kqueue_t *queue);
/**
* This function will reset a queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_flush(kqueue_t *queue);
/**
* This function will get information of a queue
* @param[in] queue pointer to the queue
* @param[out] info buf to save msg-info
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_info_get(kqueue_t *queue, msg_info_t *info);
#endif /* K_QUEUE_H */

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MM_RINGBUF_H
#define K_MM_RINGBUF_H
#define RINGBUF_TYPE_FIX 0
#define RINGBUF_TYPE_DYN 1
#define RINGBUF_LEN_MAX_SIZE 3
#define RINGBUF_LEN_MASK_ONEBIT 0x80 //1000 0000
#define RINGBUF_LEN_MASK_TWOBIT 0xC0 //1100 0000
#define RINGBUF_LEN_MASK_CLEAN_TWOBIT 0x3f //0011 1111
#define RINGBUF_LEN_VLE_2BYTES 0x80 //1000 0000
#define RINGBUF_LEN_VLE_3BYTES 0xC0 //1100 0000
#define RINGBUF_LEN_1BYTE_MAXVALUE 0x7f //0111 1111; 127
#define RINGBUF_LEN_2BYTES_MAXVALUE 0x3fff // 16383
#define RINGBUF_LEN_3BYTES_MAXVALUE 0x3fffff //4194303
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
typedef struct {
uint8_t *buf;
uint8_t *end;
uint8_t *head;
uint8_t *tail;
size_t freesize;
size_t type;
size_t blk_size;
} k_ringbuf_t;
#define COMPRESS_LEN(x) ((x) <= RINGBUF_LEN_1BYTE_MAXVALUE ? 1: (x) <= RINGBUF_LEN_2BYTES_MAXVALUE ? 2: \
(x) <= RINGBUF_LEN_3BYTES_MAXVALUE ? 3 : RHINO_INV_PARAM)
#if (RHINO_CONFIG_RINGBUF_VENDOR > 0)
/**
* This function will init the mm ring buffer.
* @param[in] p_ringbuf pointer to ring buffer
* @param[in] buf pointer to memory buffer
* @param[in] len length of memory buffer
* @param[in] type type of ring buffer, fix length or dynamic length
* @param[in] block_size block size of fix length ringbuf, if dynamic ringbuffer, ignore this parameter
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_ringbuf_init (k_ringbuf_t *p_ringbuf, void *buf, size_t len,
size_t type, size_t block_size);
/**
* This function will clean all data in mm ring buffer.
* @param[in] p_ringbuf pointer to ring buffer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_ringbuf_reset(k_ringbuf_t *p_ringbuf);
/**
* This function will push the data to ring buffer end.
* @param[in] p_ringbuf pointer to ring buffer
* @param[in] data pointer to data
* @param[in] len length of data
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len);
/**
* This function will pop the data from ring buffer head.
* @param[in] p_ringbuf pointer to ring buffer
* @param[out] pdata pointer to data
* @param[out] plen length of data
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen);
/**
* This function will check if the ring buffer is full.
* @param[in] p_ringbuf pointer to ring buffer
* @return the ringbuf status, true is full. else is not.
*/
uint8_t krhino_ringbuf_is_full(k_ringbuf_t *p_ringbuf);
/**
* This function will check if the ring buffer is empty.
* @param[in] p_ringbuf pointer to ring buffer
* @return the ringbuf status, true is empty. else is not.
*/
uint8_t krhino_ringbuf_is_empty(k_ringbuf_t *p_ringbuf);
#endif
#endif

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_SCHED_H
#define K_SCHED_H
#define KSCHED_FIFO 0u
#define KSCHED_RR 1u
#define SCHED_MAX_LOCK_COUNT 200u
#define NUM_WORDS ((RHINO_CONFIG_PRI_MAX + 31) / 32)
typedef struct {
klist_t *cur_list_item[RHINO_CONFIG_PRI_MAX];
uint32_t task_bit_map[NUM_WORDS];
uint8_t highest_pri;
} runqueue_t;
/**
* This function will disable schedule
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sched_disable(void);
/**
* This function will enable schedule
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sched_enable(void);
#endif /* K_SCHED_H */

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_SEM_H
#define K_SEM_H
#define WAKE_ONE_SEM 0u
#define WAKE_ALL_SEM 1u
typedef struct sem_s {
blk_obj_t blk_obj;
sem_count_t count;
sem_count_t peak_count;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t sem_item;
#endif
uint8_t mm_alloc_flag;
} ksem_t;
/**
* This function will create a semaphore
* @param[in] sem pointer to the semaphore(the space is provided by user)
* @param[in] name name of the semaphore
* @param[in] count the init count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_create(ksem_t *sem, const name_t *name, sem_count_t count);
/**
* This function will delete a semaphore
* @param[in] sem pointer to the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_del(ksem_t *sem);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn-semaphore
* @param[out] sem pointer to the semaphore(the space is provided by kernel)
* @param[in] name name of the semaphore
* @param[in] count the init count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_dyn_create(ksem_t **sem, const name_t *name,
sem_count_t count);
/**
* This function will delete a dyn-semaphore
* @param[in] sem pointer to the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_dyn_del(ksem_t *sem);
#endif
/**
* This function will give a semaphore
* @param[in] sem pointer to the semphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_give(ksem_t *sem);
/**
* This function will give a semaphore and wakeup all thee waiting task
* @param[in] sem pointer to the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_give_all(ksem_t *sem);
/**
* This function will take a semaphore
* @param[in] sem pointer to the semaphore
* @param[in] ticks ticks to wait before take
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_take(ksem_t *sem, tick_t ticks);
/**
* This function will set the count of a semaphore
* @param[in] sem pointer to the semaphore
* @param[in] sem_count count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_count_set(ksem_t *sem, sem_count_t count);
/**
* This function will get count of a semaphore
* @param[in] sem pointer to the semaphore
* @param[out] count count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_count_get(ksem_t *sem, sem_count_t *count);
#endif /* K_SEM_H */

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_SOC_H
#define K_SOC_H
#if (RHINO_CONFIG_HW_COUNT > 0)
void soc_hw_timer_init(void);
hr_timer_t soc_hr_hw_cnt_get(void);
lr_timer_t soc_lr_hw_cnt_get(void);
#define HR_COUNT_GET() soc_hr_hw_cnt_get()
#else /* RHINO_CONFIG_HW_COUNT */
#define HR_COUNT_GET() 0u
#endif /* RHINO_CONFIG_HW_COUNT */
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
#define LR_COUNT_GET() soc_lr_hw_cnt_get()
#else /* RHINO_CONFIG_TASK_SCHED_STATS */
#define LR_COUNT_GET() 0u
#endif /* RHINO_CONFIG_TASK_SCHED_STATS */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
void soc_intrpt_guard(void);
#endif
#if (RHINO_CONFIG_INTRPT_STACK_REMAIN_GET > 0)
size_t soc_intrpt_stack_remain_get(void);
#endif
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
void soc_intrpt_stack_ovf_check(void);
#endif
void soc_err_proc(kstat_t err);
size_t soc_get_cur_sp(void);
#endif /* K_SOC_H */

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_STATS_H
#define K_STATS_H
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
void kobj_list_init(void);
#endif
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
/**
* This function will check task stack overflow
*/
void krhino_stack_ovf_check(void);
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
/**
* This function will reset task schedule stats
*/
void krhino_task_sched_stats_reset(void);
/**
* This function will get task statistic data
*/
void krhino_task_sched_stats_get(void);
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
void krhino_overhead_measure(void);
#endif
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
uint32_t krhino_get_cpu_usage(void);
#endif
#endif /* K_STATS_H */

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_SYS_H
#define K_SYS_H
#define RHINO_VERSION 10000
#define RHINO_IDLE_PRI (RHINO_CONFIG_PRI_MAX - 1)
#define RHINO_FALSE 0u
#define RHINO_TRUE 1u
#define RHINO_NO_WAIT 0u
#define MAX_TIMER_TICKS ((tick_t)-1 >> 1)
#if (RHINO_CONFIG_64_BIT_TYPE > 0)
#define RHINO_WAIT_FOREVER ((uint64_t)-1)
typedef uint64_t sys_time_t;
typedef int64_t sys_time_i_t;
typedef uint64_t idle_count_t;
typedef uint64_t tick_t;
typedef int64_t tick_i_t;
#else
#define RHINO_WAIT_FOREVER ((uint32_t)-1)
typedef uint32_t sys_time_t;
typedef int32_t sys_time_i_t;
typedef uint32_t idle_count_t;
typedef uint32_t tick_t;
typedef int32_t tick_i_t;
#endif
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
#if (RHINO_CONFIG_CPU_STACK_DOWN > 0)
extern cpu_stack_t *g_intrpt_stack_bottom;
#else
extern cpu_stack_t *g_intrpt_stack_top;
#endif
#endif /* RHINO_CONFIG_INTRPT_STACK_OVF_CHECK */
/**
* This function will init AliOS
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_init(void);
/**
* This function will start AliOS
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_start(void);
/**
* This function will enter interrupt
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_intrpt_enter(void);
/**
* This function will exit interrupt
*/
void krhino_intrpt_exit(void);
/**
* This function will check intrpt-stack overflow
*/
void krhino_intrpt_stack_ovf_check(void);
/**
* This function will get the whole ram space used by kernel
* @return the whole ram space used by kernel
*/
size_t krhino_global_space_get(void);
/**
* This function will get kernel version
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
uint32_t krhino_version_get(void);
void krhino_check_fatal_call(const char *func);
#endif /* K_SYS_H */

View File

@@ -0,0 +1,312 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TASK_H
#define K_TASK_H
typedef enum {
K_SEED,
K_RDY,
K_PEND,
K_SUSPENDED,
K_PEND_SUSPENDED,
K_SLEEP,
K_SLEEP_SUSPENDED,
K_DELETED,
} task_stat_t;
typedef struct {
void *task_stack;
#if (RHINO_CONFIG_TASK_INFO > 0)
/* for user data extension do not move the position! */
void *user_info[RHINO_CONFIG_TASK_INFO_NUM];
#endif
cpu_stack_t *task_stack_base;
uint32_t stack_size;
klist_t task_list;
#if (RHINO_CONFIG_TASK_SUSPEND > 0)
suspend_nested_t suspend_count;
#endif
struct mutex_s *mutex_list;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t task_stats_item;
#endif
klist_t tick_list;
tick_t tick_match;
tick_t tick_remain;
klist_t *tick_head;
void *msg;
#if (RHINO_CONFIG_BUF_QUEUE > 0)
size_t bq_msg_size;
#endif
const name_t *task_name;
task_stat_t task_state;
blk_state_t blk_state;
/* Task block on mutex, queue, semphore, event */
blk_obj_t *blk_obj;
#if (RHINO_CONFIG_TASK_SEM > 0)
struct sem_s *task_sem_obj;
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
size_t task_free_stack_size;
ctx_switch_t task_ctx_switch_times;
sys_time_t task_time_total_run;
sys_time_t task_time_total_run_prev;
lr_timer_t task_exec_time;
lr_timer_t task_time_start;
#endif
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
hr_timer_t task_intrpt_disable_time_max;
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
hr_timer_t task_sched_disable_time_max;
#endif
#if (RHINO_CONFIG_SCHED_RR > 0)
/* for task time slice*/
uint32_t time_slice;
uint32_t time_total;
#endif
#if (RHINO_CONFIG_EVENT_FLAG > 0)
uint32_t pend_flags;
void *pend_info;
uint8_t pend_option;
#endif
#if (RHINO_CONFIG_SCHED_RR > 0)
uint8_t sched_policy;
#endif
uint8_t cpu_num;
#if (RHINO_CONFIG_CPU_NUM > 1)
uint8_t cpu_binded;
uint8_t cur_exc;
#endif
/* current prio */
uint8_t prio;
/* base prio */
uint8_t b_prio;
uint8_t mm_alloc_flag:2, lprun:1, rev: 5;
void *arg;
uint32_t runtime;
int32_t task_errno;
} ktask_t;
typedef void (*task_entry_t)(void *arg);
/**
* This function will initialize a task
* @param[in] task the task to be created
* @param[in] name the name of task, which shall be unique
* @param[in] arg the parameter of task enter function
* @param[in] pri the prio of task
* @param[in] ticks the time slice if there are same prio task
* @param[in] stack_buf the start address of task stack
* @param[in] stack the size of thread stack
* @param[in] entry the entry function of task
* @param[in] autorun the autorunning flag of task
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_create(ktask_t *task, const name_t *name, void *arg,
uint8_t prio, tick_t ticks, cpu_stack_t *stack_buf,
size_t stack_size, task_entry_t entry, uint8_t autorun);
#if (RHINO_CONFIG_CPU_NUM > 1)
kstat_t krhino_task_cpu_create(ktask_t *task, const name_t *name, void *arg,
uint8_t prio, tick_t ticks, cpu_stack_t *stack_buf,
size_t stack_size, task_entry_t entry, uint8_t cpu_num,
uint8_t autorun);
kstat_t krhino_task_cpu_bind(ktask_t *task, uint8_t cpu_num);
kstat_t krhino_task_cpu_unbind(ktask_t *task);
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will initialize a task
* @param[in] task the task to be created
* @param[in] name the name of task, which shall be unique
* @param[in] arg the parameter of task enter function
* @param[in] pri the prio of task
* @param[in] ticks the time slice if there are same prio task
* @param[in] stack the size of thread stack
* @param[in] entry the entry function of task
* @param[in] autorun the autorunning flag of task
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_dyn_create(ktask_t **task, const name_t *name, void *arg,
uint8_t pri,
tick_t ticks, void *stack, size_t stack_size,
task_entry_t entry, uint8_t autorun);
#if (RHINO_CONFIG_CPU_NUM > 1)
kstat_t krhino_task_cpu_dyn_create(ktask_t **task, const name_t *name, void *arg,
uint8_t pri, tick_t ticks, size_t stack,
task_entry_t entry, uint8_t cpu_num, uint8_t autorun);
#endif
#endif
#if (RHINO_CONFIG_TASK_DEL > 0)
/**
* This function will delete a task
* @param[in] task the task to be deleted.
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_del(ktask_t *task);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will delete a dyn-task
* @param[in] task the task to be deleted.
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_dyn_del(ktask_t *task);
#endif
#endif
/**
* This function will cause a task to sleep for some ticks
* @param[in] ticks the ticks to sleep
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sleep(tick_t dly);
/**
* This function will yield a task
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_yield(void);
/**
* This function will get the current task for this cpu
* @return the current task
*/
ktask_t *krhino_cur_task_get(void);
#if (RHINO_CONFIG_TASK_SUSPEND > 0)
/**
* This function will suspend a task
* @param[in] task the task to be suspended
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_suspend(ktask_t *task);
/**
* This function will resume a task
* @param[in] task the task to be resumed
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_resume(ktask_t *task);
#endif
/**
* This function will get min free stack size in the total runtime
* @param[in] task the task where get free stack size.
* @param[in] free the free task stack size to be filled with.
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_stack_min_free(ktask_t *task, size_t *free);
/**
* This function will get current free stack size
* @param[in] task the task where get free stack size.
* @param[in] free the free task stack size to be filled with.
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_stack_cur_free(ktask_t *task, size_t *free);
/**
* This function will change the prio of task
* @param[in] task the task to be changed prio
* @param[in] pri the prio to be changed.
* @param[out] old_pri the old task prio to be filled with
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_pri_change(ktask_t *task, uint8_t pri, uint8_t *old_pri);
#if (RHINO_CONFIG_TASK_WAIT_ABORT > 0)
/**
* This function will abort a task and wakup the task
* @param[in] task the task to be aborted
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_wait_abort(ktask_t *task);
#endif
#if (RHINO_CONFIG_SCHED_RR > 0)
/**
* This function will set task timeslice
* @param[in] task the task to be set timeslice
* @param[in] slice the task time slice
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_time_slice_set(ktask_t *task, size_t slice);
/**
* This function will set task sched policy
* @param[in] task the task to be set timeslice
* @param[in] policy the policy to be set, pllicy option can be either KSCHED_FIFO or KSCHED_RR
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sched_policy_set(ktask_t *task, uint8_t policy);
/**
* This function will get task sched policy
* @param[in] task the task to be get timeslice
* @param[out] policy the policy to be get
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sched_policy_get(ktask_t *task, uint8_t *policy);
#endif
#if (RHINO_CONFIG_TASK_INFO > 0)
/**
* This function will set task private infomation
* @param[in] task the task to be set private infomation
* @param[out] info the private information
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_info_set(ktask_t *task, size_t idx, void *info);
/**
* This function will get task private infomation
* @param[in] task the task to be get private infomation
* @param[out] info to save private infomation
* @return the task private information
*/
kstat_t krhino_task_info_get(ktask_t *task, size_t idx, void **info);
#endif
/**
* This function will be set in cpu_task_stack_init,set LR reg with
* this funtion pointer
*/
void krhino_task_deathbed(void);
void krhino_task_set_lprun(ktask_t *task, uint8_t run);
void krhino_lpower_mode(uint8_t enable);
#endif /* K_TASK_H */

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TASK_SEM_H
#define K_TASK_SEM_H
/**
* This function will create a task-semaphore
* @param[in] task pointer to the task
* @param[in] sem pointer to the semaphore
* @param[in] name name of the task-semaphore
* @param[in] count count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_create(ktask_t *task, ksem_t *sem, const name_t *name,
size_t count);
/**
* This function will delete a task-semaphore
* @param[in] task pointer to the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_del(ktask_t *task);
/**
* This function will give up a task-semaphore
* @param[in] task pointer to the task
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_give(ktask_t *task);
/**
* This function will take a task-semaphore
* @param[in] ticks ticks to wait before take the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_take(tick_t ticks);
/**
* This function will set the count of a task-semaphore
* @param[in] task pointer to the task
* @param[in] count count of the semaphre to set
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_count_set(ktask_t *task, sem_count_t count);
/**
* This function will get task-semaphore count
* @param[in] task pointer to the semphore
* @param[out] count count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_count_get(ktask_t *task, sem_count_t *count);
#endif /* K_TASK_SEM_H */

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TIME_H
#define K_TIME_H
/**
* This function will handle systick routine
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
void krhino_tick_proc(void);
/**
* This function will get time of the system in ms
* @return system time
*/
sys_time_t krhino_sys_time_get(void);
/**
* This function will get ticks of the system
* @return the system ticks
*/
sys_time_t krhino_sys_tick_get(void);
/**
* This function will convert ms to ticks
* @param[in] ms ms which will be converted to ticks
* @return the ticks of the ms
*/
tick_t krhino_ms_to_ticks(sys_time_t ms);
/**
* This function will convert ticks to ms
* @param[in] ticks ticks which will be converted to ms
* @return the ms of the ticks
*/
sys_time_t krhino_ticks_to_ms(tick_t ticks);
#endif /* K_TIME_H */

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TIMER_H
#define K_TIMER_H
enum {
TIMER_CMD_CB = 0u,
TIMER_CMD_START,
TIMER_CMD_STOP,
TIMER_CMD_CHG,
TIMER_ARG_CHG,
TIMER_ARG_CHG_AUTO,
TIMER_CMD_DEL,
TIMER_CMD_DYN_DEL
};
typedef void (*timer_cb_t)(void *timer, void *arg);
typedef struct {
klist_t timer_list;
klist_t *to_head;
const name_t *name;
timer_cb_t cb;
void *timer_cb_arg;
sys_time_t match;
sys_time_t remain;
sys_time_t init_count;
sys_time_t round_ticks;
void *priv;
kobj_type_t obj_type;
uint8_t timer_state;
uint8_t mm_alloc_flag;
} ktimer_t;
typedef struct {
ktimer_t *timer;
uint8_t cb_num;
sys_time_t first;
union {
sys_time_t round;
void *arg;
} u;
} k_timer_queue_cb;
typedef enum {
TIMER_DEACTIVE = 0u,
TIMER_ACTIVE
} k_timer_state_t;
/**
* This function will create a timer
* @param[in] timer pointer to the timer(the space is provided by user)
* @param[in] name name of the timer
* @param[in] cb callbak of the timer
* @param[in] first ticks of the first timer triger
* @param[in] round ticks of the normal timer triger
* @param[in] arg the argument of the callback
* @param[in] auto_run auto run or not when the timer is created
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_create(ktimer_t *timer, const name_t *name, timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run);
/**
* This function will delete a timer
* @param[in] timer pointer to a timer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_del(ktimer_t *timer);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn-timer
* @param[in] timer pointer to the timer
* @param[in] name name of the timer
* @param[in] cb callbak of the timer
* @param[in] first ticks of the first timer triger
* @param[in] round ticks of the normal timer triger
* @param[in] arg the argument of the callback
* @param[in] auto_run auto run or not when the timer is created
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_dyn_create(ktimer_t **timer, const name_t *name,
timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run);
/**
* This function will delete a dyn-timer
* @param[in] timer pointer to a timer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_dyn_del(ktimer_t *timer);
#endif
/**
* This function will start a timer
* @param[in] timer pointer to the timer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_start(ktimer_t *timer);
/**
* This function will stop a timer
* @param[in] timer pointer to the timer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_stop(ktimer_t *timer);
/**
* This function will change attributes of a timer
* @param[in] timer pointer to the timer
* @param[in] first ticks of the first timer triger
* @param[in] round ticks of the normal timer triger
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_change(ktimer_t *timer, sys_time_t first, sys_time_t round);
/**
* This function will change attributes of a timer without stop and start
* @param[in] timer pointer to the timer
* @param[in] first ticks of the first timer triger
* @param[in] round ticks of the normal timer triger
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_arg_change_auto(ktimer_t *timer, void *arg);
/**
* This function will change callback arg attributes of a timer
* @param[in] timer pointer to the timer
* @param[in] arg timer callback arg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_arg_change(ktimer_t *timer, void *arg);
#endif /* K_TIMER_H */

View File

@@ -0,0 +1,207 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TRACE_H
#define K_TRACE_H
#if (RHINO_CONFIG_TRACE > 0)
/* task trace function */
void _trace_init(void);
void _trace_task_switch(ktask_t *from, ktask_t *to);
void _trace_intrpt_task_switch(ktask_t *from, ktask_t *to);
void _trace_task_create(ktask_t *task);
void _trace_task_sleep(ktask_t *task, tick_t ticks);
void _trace_task_pri_change(ktask_t *task, ktask_t *task_pri_chg, uint8_t pri);
void _trace_task_suspend(ktask_t *task, ktask_t *task_suspended);
void _trace_task_resume(ktask_t *task, ktask_t *task_resumed);
void _trace_task_del(ktask_t *task, ktask_t *task_del);
void _trace_task_abort(ktask_t *task, ktask_t *task_abort);
/* semaphore trace function */
void _trace_sem_create(ktask_t *task, ksem_t *sem);
void _trace_sem_overflow(ktask_t *task, ksem_t *sem);
void _trace_sem_del(ktask_t *task, ksem_t *sem);
void _trace_sem_get_success(ktask_t *task, ksem_t *sem);
void _trace_sem_get_blk(ktask_t *task, ksem_t *sem, tick_t wait_option);
void _trace_sem_task_wake(ktask_t *task, ktask_t *task_waked_up, ksem_t *sem,
uint8_t opt_wake_all);
void _trace_sem_cnt_increase(ktask_t *task, ksem_t *sem);
/* mutex trace function */
void _trace_mutex_create(ktask_t *task, kmutex_t *mutex, const name_t *name);
void _trace_mutex_release(ktask_t *task, ktask_t *task_release,
uint8_t new_pri);
void _trace_mutex_get(ktask_t *task, kmutex_t *mutex, tick_t wait_option);
void _trace_task_pri_inv(ktask_t *task, ktask_t *mtxtsk);
void _trace_mutex_get_blk(ktask_t *task, kmutex_t *mutex, tick_t wait_option);
void _trace_mutex_release_success(ktask_t *task, kmutex_t *mutex);
void _trace_mutex_task_wake(ktask_t *task, ktask_t *task_waked_up,
kmutex_t *mutex);
void _trace_mutex_del(ktask_t *task, kmutex_t *mutex);
/* event trace function */
void _trace_event_create(ktask_t *task, kevent_t *event, const name_t *name,
uint32_t flags_init);
void _trace_event_get(ktask_t *task, kevent_t *event);
void _trace_event_get_blk(ktask_t *task, kevent_t *event, tick_t wait_option);
void _trace_event_task_wake(ktask_t *task, ktask_t *task_waked_up,
kevent_t *event);
void _trace_event_del(ktask_t *task, kevent_t *event);
/* buf_queue trace function */
void _trace_buf_queue_create(ktask_t *task, kbuf_queue_t *buf_queue);
void _trace_buf_max(ktask_t *task, kbuf_queue_t *buf_queue, void *p_void,
size_t msg_size);
void _trace_buf_post(ktask_t *task, kbuf_queue_t *buf_queue, void *p_void,
size_t msg_size);
void _trace_buf_queue_task_wake(ktask_t *task, ktask_t *task_waked_up,
kbuf_queue_t *buf_queue);
void _trace_buf_queue_get_blk(ktask_t *task, kbuf_queue_t *buf_queue,
tick_t wait_option);
/* timer trace function */
void _trace_timer_create(ktask_t *task, ktimer_t *timer);
void _trace_timer_del(ktask_t *task, ktimer_t *timer);
/* mblk trace function */
void _trace_mblk_pool_create(ktask_t *task, mblk_pool_t *pool);
/* mm trace function */
//void _trace_mm_pool_create(ktask_t *task, mm_pool_t *pool);
/* work queue trace */
void _trace_work_init(ktask_t *task, kwork_t *work);
void _trace_workqueue_create(ktask_t *task, kworkqueue_t *workqueue);
void _trace_workqueue_del(ktask_t *task, kworkqueue_t *workqueue);
/* task trace */
#define TRACE_INIT() _trace_init()
#define TRACE_TASK_SWITCH(from, to) _trace_task_switch(from, to)
#define TRACE_TASK_CREATE(task) _trace_task_create(task)
#define TRACE_TASK_SLEEP(task, ticks) _trace_task_sleep(task, ticks)
#define TRACE_INTRPT_TASK_SWITCH(from, to) _trace_intrpt_task_switch(from, to)
#define TRACE_TASK_PRI_CHANGE(task, task_pri_chg, pri) _trace_task_pri_change(task, task_pri_chg, pri)
#define TRACE_TASK_SUSPEND(task, task_suspended) _trace_task_suspend(task, task_suspended)
#define TRACE_TASK_RESUME(task, task_resumed) _trace_task_resume(task, task_resumed)
#define TRACE_TASK_DEL(task, task_del) _trace_task_del(task, task_del)
#define TRACE_TASK_WAIT_ABORT(task, task_abort) _trace_task_abort(task, task_abort)
/* semaphore trace */
#define TRACE_SEM_CREATE(task, sem) _trace_sem_create(task, sem)
#define TRACE_SEM_OVERFLOW(task, sem) _trace_sem_overflow(task, sem)
#define TRACE_SEM_CNT_INCREASE(task, sem) _trace_sem_cnt_increase(task, sem)
#define TRACE_SEM_GET_SUCCESS(task, sem) _trace_sem_get_success(task, sem)
#define TRACE_SEM_GET_BLK(task, sem, wait_option) _trace_sem_get_blk(task, sem, wait_option)
#define TRACE_SEM_TASK_WAKE(task, task_waked_up, sem, opt_wake_all) _trace_sem_task_wake(task, task_waked_up, sem, opt_wake_all)
#define TRACE_SEM_DEL(task, sem) _trace_sem_del(task, sem);
/* mutex trace */
#define TRACE_MUTEX_CREATE(task, mutex, name) _trace_mutex_create(task, mutex, name)
#define TRACE_MUTEX_RELEASE(task, task_release, new_pri) _trace_mutex_release(task, task_release, new_pri)
#define TRACE_MUTEX_GET(task, mutex, wait_option) _trace_mutex_get(task, mutex, wait_option)
#define TRACE_TASK_PRI_INV(task, mtxtsk) _trace_task_pri_inv(task, mtxtsk)
#define TRACE_MUTEX_GET_BLK(task, mutex, wait_option) _trace_mutex_get_blk(task, mutex, wait_option)
#define TRACE_MUTEX_RELEASE_SUCCESS(task, mutex) _trace_mutex_release_success(task, mutex)
#define TRACE_MUTEX_TASK_WAKE(task, task_waked_up, mutex) _trace_mutex_task_wake(task, task_waked_up, mutex)
#define TRACE_MUTEX_DEL(task, mutex) _trace_mutex_del(task, mutex)
/* event trace */
#define TRACE_EVENT_CREATE(task, event, name, flags_init) _trace_event_create(task, event, name, flags_init)
#define TRACE_EVENT_GET(task, event) _trace_event_get(task, event)
#define TRACE_EVENT_GET_BLK(task, event, wait_option) _trace_event_get_blk(task, event, wait_option)
#define TRACE_EVENT_TASK_WAKE(task, task_waked_up, event) _trace_event_task_wake(task, task_waked_up, event)
#define TRACE_EVENT_DEL(task, event) _trace_event_del(task, event)
/* buf_queue trace */
#define TRACE_BUF_QUEUE_CREATE(task, buf_queue) _trace_buf_queue_create(task, buf_queue)
#define TRACE_BUF_QUEUE_MAX(task, buf_queue, msg, msg_size) _trace_buf_max(task, buf_queue, msg, msg_size)
#define TRACE_BUF_QUEUE_POST(task, buf_queue, msg, msg_size) _trace_buf_post(task, buf_queue, msg, msg_size)
#define TRACE_BUF_QUEUE_TASK_WAKE(task, task_waked_up, queue) _trace_buf_queue_task_wake(task, task_waked_up, queue)
#define TRACE_BUF_QUEUE_GET_BLK(task, buf_queue, wait_option) _trace_buf_queue_get_blk(task, buf_queue, wait_option)
/* timer trace */
#define TRACE_TIMER_CREATE(task, timer) _trace_timer_create(task, timer)
#define TRACE_TIMER_DEL(task, timer) _trace_timer_del(task, timer)
/* mblk trace */
#define TRACE_MBLK_POOL_CREATE(task, pool) _trace_mblk_pool_create(task, pool)
/* mm trace */
#define TRACE_MM_POOL_CREATE(task, pool) _trace_mm_pool_create(task, pool)
/* mm region */
#define TRACE_MM_REGION_CREATE(task, regions) _trace_mm_region_create(task, regions)
/* work queue trace */
#define TRACE_WORK_INIT(task, work) _trace_work_init(task, work)
#define TRACE_WORKQUEUE_CREATE(task, workqueue) _trace_workqueue_create(task, workqueue)
#define TRACE_WORKQUEUE_DEL(task, workqueue) _trace_workqueue_del(task, workqueue)
#else
/* task trace */
#define TRACE_INIT()
#define TRACE_TASK_SWITCH(from, to)
#define TRACE_TASK_CREATE(task)
#define TRACE_TASK_SLEEP(task, ticks)
#define TRACE_INTRPT_TASK_SWITCH(from, to)
#define TRACE_TASK_PRI_CHANGE(task, task_pri_chg, pri)
#define TRACE_TASK_SUSPEND(task, task_suspended)
#define TRACE_TASK_RESUME(task, task_resumed)
#define TRACE_TASK_DEL(task, task_del)
#define TRACE_TASK_WAIT_ABORT(task, task_abort)
/* semaphore trace */
#define TRACE_SEM_CREATE(task, sem)
#define TRACE_SEM_OVERFLOW(task, sem)
#define TRACE_SEM_CNT_INCREASE(task, sem)
#define TRACE_SEM_GET_SUCCESS(task, sem)
#define TRACE_SEM_GET_BLK(task, sem, wait_option)
#define TRACE_SEM_TASK_WAKE(task, task_waked_up, sem, opt_wake_all)
#define TRACE_SEM_DEL(task, sem)
/* mutex trace */
#define TRACE_MUTEX_CREATE(task, mutex, name)
#define TRACE_MUTEX_RELEASE(task, task_release, new_pri)
#define TRACE_MUTEX_GET(task, mutex, wait_option)
#define TRACE_TASK_PRI_INV(task, mtxtsk)
#define TRACE_MUTEX_GET_BLK(task, mutex, wait_option)
#define TRACE_MUTEX_RELEASE_SUCCESS(task, mutex)
#define TRACE_MUTEX_TASK_WAKE(task, task_waked_up, mutex)
#define TRACE_MUTEX_DEL(task, mutex)
/* event trace */
#define TRACE_EVENT_CREATE(task, event, name, flags_init)
#define TRACE_EVENT_GET(task, event)
#define TRACE_EVENT_GET_BLK(task, event, wait_option)
#define TRACE_EVENT_TASK_WAKE(task, task_waked_up, event)
#define TRACE_EVENT_DEL(task, event)
/* buf_queue trace */
#define TRACE_BUF_QUEUE_CREATE(task, buf_queue)
#define TRACE_BUF_QUEUE_MAX(task, buf_queue, msg, msg_size)
#define TRACE_BUF_QUEUE_POST(task, buf_queue, msg, msg_size)
#define TRACE_BUF_QUEUE_TASK_WAKE(task, task_waked_up, queue)
#define TRACE_BUF_QUEUE_GET_BLK(task, buf_queue, wait_option)
/* timer trace */
#define TRACE_TIMER_CREATE(task, timer)
#define TRACE_TIMER_DEL(task, timer)
/* MBLK trace */
#define TRACE_MBLK_POOL_CREATE(task, pool)
/* MM trace */
#define TRACE_MM_POOL_CREATE(task, pool)
/* MM region trace*/
#define TRACE_MM_REGION_CREATE(task, regions)
/* work queue trace */
#define TRACE_WORK_INIT(task, work)
#define TRACE_WORKQUEUE_CREATE(task, workqueue)
#define TRACE_WORKQUEUE_DEL(task, workqueue)
#endif
#endif

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_WORKQUEUE_H
#define K_WORKQUEUE_H
#if (RHINO_CONFIG_WORKQUEUE > 0)
#define WORKQUEUE_WORK_MAX 32
typedef void (*work_handle_t)(void *arg);
typedef struct {
klist_t work_node;
work_handle_t handle;
void *arg;
tick_t dly;
ktimer_t *timer;
void *wq;
uint8_t work_exit;
} kwork_t;
typedef struct {
klist_t workqueue_node;
klist_t work_list;
kwork_t *work_current; /* current work */
const name_t *name;
ktask_t worker;
ksem_t sem;
} kworkqueue_t;
/**
* This function will creat a workqueue
* @param[in] workqueue the workqueue to be created
* @param[in] name the name of workqueue/worker, which should be unique
* @param[in] pri the priority of the worker
* @param[in] stack_buf the stack of the worker(task)
* @param[in] stack_size the size of the worker-stack
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_workqueue_create(kworkqueue_t *workqueue, const name_t *name,
uint8_t pri, cpu_stack_t *stack_buf, size_t stack_size);
/**
* This function will delete a workqueue
* @param[in] workqueue the workqueue to be deleted
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_workqueue_del(kworkqueue_t *workqueue);
/**
* This function will initialize a work
* @param[in] work the work to be initialized
* @param[in] handle the call back function to run
* @param[in] arg the paraments of the function
* @param[in] dly the ticks to delay before run
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_work_init(kwork_t *work, work_handle_t handle, void *arg,
tick_t dly);
/**
* This function will run a work on a workqueue
* @param[in] workqueue the workqueue to run work
* @param[in] work the work to run
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_work_run(kworkqueue_t *workqueue, kwork_t *work);
/**
* This function will run a work on the default workqueue
* @param[in] work the work to run
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_work_sched(kwork_t *work);
/**
* This function will cancel a work
* @param[in] work the work to cancel
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_work_cancel(kwork_t *work);
#endif
#endif /* K_WORKQUEUE_H */

View File

@@ -0,0 +1,439 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_BUF_QUEUE > 0)
static kstat_t buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf, size_t size, size_t max_msg, uint8_t mm_alloc_flag, size_t type)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
NULL_PARA_CHK(buf);
NULL_PARA_CHK(name);
if (max_msg == 0u) {
return RHINO_INV_PARAM;
}
if (size == 0u) {
return RHINO_BUF_QUEUE_SIZE_ZERO;
}
/* init the queue blocked list */
klist_init(&queue->blk_obj.blk_list);
klist_init(&queue->sblk_obj.blk_list);
queue->buf = buf;
queue->cur_num = 0u;
queue->peak_num = 0u;
queue->max_msg_size = max_msg;
queue->blk_obj.name = name;
queue->blk_obj.blk_policy = BLK_POLICY_PRI;
queue->sblk_obj.name = name;
queue->sblk_obj.blk_policy = BLK_POLICY_PRI;
queue->mm_alloc_flag = mm_alloc_flag;
RHINO_CRITICAL_ENTER();
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_insert(&(g_kobj_list.buf_queue_head), &queue->buf_queue_item);
#endif
RHINO_CRITICAL_EXIT();
queue->blk_obj.obj_type = RHINO_BUF_QUEUE_OBJ_TYPE;
queue->sblk_obj.obj_type = RHINO_BUF_QUEUE_OBJ_TYPE;
ringbuf_init(&(queue->ringbuf), buf, size, type, max_msg);
queue->min_free_buf_size = queue->ringbuf.freesize;
TRACE_BUF_QUEUE_CREATE(krhino_cur_task_get(), queue);
return RHINO_SUCCESS;
}
kstat_t krhino_buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf, size_t size, size_t max_msg)
{
return buf_queue_create(queue, name, buf, size, max_msg, K_OBJ_STATIC_ALLOC, RINGBUF_TYPE_DYN);
}
kstat_t krhino_fix_buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf, size_t msg_size, size_t msg_num)
{
return buf_queue_create(queue, name, buf, msg_size * msg_num, msg_size, K_OBJ_STATIC_ALLOC, RINGBUF_TYPE_FIX);
}
kstat_t krhino_buf_queue_del(kbuf_queue_t *queue)
{
CPSR_ALLOC();
klist_t *head;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
head = &queue->blk_obj.blk_list;
queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(head)) {
pend_task_rm(krhino_list_entry(head->next, ktask_t, task_list));
}
head = &queue->sblk_obj.blk_list;
queue->sblk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(head)) {
pend_task_rm(krhino_list_entry(head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&queue->buf_queue_item);
#endif
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_buf_queue_dyn_create(kbuf_queue_t **queue, const name_t *name,
size_t size, size_t max_msg)
{
kstat_t stat;
kbuf_queue_t *queue_obj;
NULL_PARA_CHK(queue);
if (size == 0u) {
return RHINO_BUF_QUEUE_SIZE_ZERO;
}
queue_obj = krhino_mm_alloc(sizeof(kbuf_queue_t), __builtin_return_address(0));
if (queue_obj == NULL) {
return RHINO_NO_MEM;
}
queue_obj->buf = krhino_mm_alloc(size, __builtin_return_address(0));
if (queue_obj->buf == NULL) {
krhino_mm_free(queue_obj);
return RHINO_NO_MEM;
}
stat = buf_queue_create(queue_obj, name, queue_obj->buf, size, max_msg,
K_OBJ_DYN_ALLOC, RINGBUF_TYPE_DYN);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(queue_obj->buf);
krhino_mm_free(queue_obj);
return stat;
}
*queue = queue_obj;
return RHINO_SUCCESS;
}
kstat_t krhino_buf_queue_dyn_del(kbuf_queue_t *queue)
{
CPSR_ALLOC();
klist_t *head;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
head = &queue->blk_obj.blk_list;
queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
while (!is_klist_empty(head)) {
pend_task_rm(krhino_list_entry(head->next, ktask_t, task_list));
}
head = &queue->sblk_obj.blk_list;
queue->sblk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
while (!is_klist_empty(head)) {
pend_task_rm(krhino_list_entry(head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&queue->buf_queue_item);
#endif
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(queue->buf);
krhino_mm_free(queue);
return RHINO_SUCCESS;
}
#endif
static kstat_t buf_queue_send(kbuf_queue_t *queue, void *msg, size_t msg_size, tick_t ticks)
{
CPSR_ALLOC();
klist_t *head;
ktask_t *task;
kstat_t err;
uint8_t cur_cpu_num;
/* this is only needed when system zero interrupt feature is enabled */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
__retry:
RHINO_CRITICAL_ENTER();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
(void)cur_cpu_num;
if (msg_size > queue->max_msg_size) {
TRACE_BUF_QUEUE_MAX(g_active_task[cur_cpu_num], queue, msg, msg_size);
RHINO_CRITICAL_EXIT();
return RHINO_BUF_QUEUE_MSG_SIZE_OVERFLOW;
}
if (msg_size == 0) {
RHINO_CRITICAL_EXIT();
return RHINO_INV_PARAM;
}
head = &queue->blk_obj.blk_list;
/* buf queue is not full here, if there is no blocked receive task */
if (is_klist_empty(head)) {
err = ringbuf_push(&(queue->ringbuf), msg, msg_size);
if (err != RHINO_SUCCESS) {
if (err == RHINO_RINGBUF_FULL) {
if(ticks){
pend_to_blk_obj((blk_obj_t *)&queue->sblk_obj.blk_list, g_active_task[cur_cpu_num], ticks, psr);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
err = pend_state_end_proc(g_active_task[cur_cpu_num]);
RHINO_CPU_INTRPT_ENABLE();
if(err == RHINO_SUCCESS){
goto __retry;
}
RHINO_CRITICAL_ENTER();
}
err = RHINO_BUF_QUEUE_FULL;
}
RHINO_CRITICAL_EXIT();
return err;
}
queue->cur_num ++;
if (queue->peak_num < queue->cur_num) {
queue->peak_num = queue->cur_num;
}
if (queue->min_free_buf_size > queue->ringbuf.freesize) {
queue->min_free_buf_size = queue->ringbuf.freesize;
}
TRACE_BUF_QUEUE_POST(g_active_task[cur_cpu_num], queue, msg, msg_size);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
task = krhino_list_entry(head->next, ktask_t, task_list);
memcpy(task->msg, msg, msg_size);
task->bq_msg_size = msg_size;
pend_task_wakeup(task);
TRACE_BUF_QUEUE_TASK_WAKE(g_active_task[cur_cpu_num], task, queue);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
kstat_t krhino_buf_queue_send(kbuf_queue_t *queue, void *msg, size_t size, tick_t ticks)
{
NULL_PARA_CHK(queue);
NULL_PARA_CHK(msg);
return buf_queue_send(queue, msg, size, ticks);
}
kstat_t krhino_buf_queue_recv(kbuf_queue_t *queue, tick_t ticks, void *msg,
size_t *size)
{
CPSR_ALLOC();
klist_t *blk_list_head;
kstat_t ret;
uint8_t cur_cpu_num;
NULL_PARA_CHK(queue);
NULL_PARA_CHK(msg);
NULL_PARA_CHK(size);
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
cur_cpu_num = cpu_cur_get();
if ((g_intrpt_nested_level[cur_cpu_num] > 0u) && (ticks != RHINO_NO_WAIT)) {
RHINO_CRITICAL_EXIT();
return RHINO_NOT_CALLED_BY_INTRPT;
}
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
blk_list_head = &queue->sblk_obj.blk_list;
if (!ringbuf_is_empty(&(queue->ringbuf))) {
ringbuf_pop(&(queue->ringbuf), msg, size);
queue->cur_num --;
while (!is_klist_empty(blk_list_head)) {
pend_task_wakeup(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
if (ticks == RHINO_NO_WAIT) {
*size = 0u;
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
*size = 0u;
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
g_active_task[cur_cpu_num]->msg = msg;
pend_to_blk_obj((blk_obj_t *)queue, g_active_task[cur_cpu_num], ticks, psr);
TRACE_BUF_QUEUE_GET_BLK(g_active_task[cur_cpu_num], queue, ticks);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
cur_cpu_num = cpu_cur_get();
ret = pend_state_end_proc(g_active_task[cur_cpu_num]);
switch (ret) {
case RHINO_SUCCESS:
*size = g_active_task[cur_cpu_num]->bq_msg_size;
break;
default:
*size = 0u;
break;
}
RHINO_CPU_INTRPT_ENABLE();
return ret;
}
kstat_t krhino_buf_queue_flush(kbuf_queue_t *queue)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
ringbuf_reset(&(queue->ringbuf));
queue->cur_num = 0u;
queue->peak_num = 0u;
queue->min_free_buf_size = queue->ringbuf.freesize;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
kstat_t krhino_buf_queue_info_get(kbuf_queue_t *queue, kbuf_queue_info_t *info)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
NULL_PARA_CHK(info);
RHINO_CRITICAL_ENTER();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
info->free_buf_size = queue->ringbuf.freesize;
info->min_free_buf_size = queue->min_free_buf_size;
info->buf_size = queue->ringbuf.end - queue->ringbuf.buf;
info->max_msg_size = queue->max_msg_size;
info->cur_num = queue->cur_num;
info->peak_num = queue->peak_num;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
#endif

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
void dym_mem_proc_hdl(void)
{
CPSR_ALLOC();
res_free_t *res_free;
res_free_t tmp;
uint32_t i;
if (!is_klist_empty(&g_res_list)) {
RHINO_CRITICAL_ENTER();
res_free = krhino_list_entry(g_res_list.next, res_free_t, res_list);
klist_rm(&res_free->res_list);
RHINO_CRITICAL_EXIT();
memcpy(&tmp, res_free, sizeof(res_free_t));
for (i = 0; i < tmp.cnt; i++) {
krhino_mm_free(tmp.res[i]);
}
}
}
#if 0
void dyn_mem_proc_task(void *arg)
{
CPSR_ALLOC();
kstat_t ret;
res_free_t *res_free;
res_free_t tmp;
uint32_t i;
(void)arg;
while (1) {
ret = krhino_sem_take(&g_res_sem, RHINO_WAIT_FOREVER);
if (ret != RHINO_SUCCESS) {
k_err_proc(RHINO_DYN_MEM_PROC_ERR);
}
while (1) {
RHINO_CRITICAL_ENTER();
if (!is_klist_empty(&g_res_list)) {
res_free = krhino_list_entry(g_res_list.next, res_free_t, res_list);
klist_rm(&res_free->res_list);
RHINO_CRITICAL_EXIT();
memcpy(&tmp, res_free, sizeof(res_free_t));
for (i = 0; i < tmp.cnt; i++) {
krhino_mm_free(tmp.res[i]);
}
}
else {
RHINO_CRITICAL_EXIT();
break;
}
}
}
}
__init void dyn_mem_proc_task_start(void)
{
krhino_task_create(&g_dyn_task, "dyn_mem", 0, RHINO_CONFIG_K_DYN_MEM_TASK_PRI,
0, g_dyn_task_stack, RHINO_CONFIG_K_DYN_TASK_STACK,
dyn_mem_proc_task, 1);
}
#endif
#endif

View File

@@ -0,0 +1,17 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void k_err_proc(kstat_t err)
{
#if 1
soc_err_proc(err);
#else
if (g_err_proc != NULL) {
g_err_proc(err);
}
#endif
}

View File

@@ -0,0 +1,339 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_EVENT_FLAG > 0)
static kstat_t event_create(kevent_t *event, const name_t *name, uint32_t flags,
uint8_t mm_alloc_flag)
{
CPSR_ALLOC();
NULL_PARA_CHK(event);
NULL_PARA_CHK(name);
/* init the list */
klist_init(&event->blk_obj.blk_list);
event->blk_obj.blk_policy = BLK_POLICY_PRI;
event->blk_obj.name = name;
event->flags = flags;
event->mm_alloc_flag = mm_alloc_flag;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
RHINO_CRITICAL_ENTER();
klist_insert(&(g_kobj_list.event_head), &event->event_item);
RHINO_CRITICAL_EXIT();
#endif
TRACE_EVENT_CREATE(krhino_cur_task_get(), event, name, flags);
event->blk_obj.obj_type = RHINO_EVENT_OBJ_TYPE;
return RHINO_SUCCESS;
}
kstat_t krhino_event_create(kevent_t *event, const name_t *name, uint32_t flags)
{
return event_create(event, name, flags, K_OBJ_STATIC_ALLOC);
}
kstat_t krhino_event_del(kevent_t *event)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(event);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (event->blk_obj.obj_type != RHINO_EVENT_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (event->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &event->blk_obj.blk_list;
event->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
event->flags = 0u;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&event->event_item);
#endif
TRACE_EVENT_DEL(g_active_task[cpu_cur_get()], event);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_event_dyn_create(kevent_t **event, const name_t *name,
uint32_t flags)
{
kstat_t stat;
kevent_t *event_obj;
if (event == NULL) {
return RHINO_NULL_PTR;
}
event_obj = krhino_mm_alloc(sizeof(kevent_t), __builtin_return_address(0));
if (event_obj == NULL) {
return RHINO_NO_MEM;
}
stat = event_create(event_obj, name, flags, K_OBJ_DYN_ALLOC);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(event_obj);
return stat;
}
*event = event_obj;
return stat;
}
kstat_t krhino_event_dyn_del(kevent_t *event)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(event);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (event->blk_obj.obj_type != RHINO_EVENT_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (event->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &event->blk_obj.blk_list;
event->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
event->flags = 0u;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&event->event_item);
#endif
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(event);
return RHINO_SUCCESS;
}
#endif
kstat_t krhino_event_get(kevent_t *event, uint32_t flags, uint8_t opt,
uint32_t *actl_flags, tick_t ticks)
{
CPSR_ALLOC();
kstat_t stat;
uint8_t status;
uint8_t cur_cpu_num;
NULL_PARA_CHK(event);
NULL_PARA_CHK(actl_flags);
if ((opt != RHINO_AND) && (opt != RHINO_OR) && (opt != RHINO_AND_CLEAR) &&
(opt != RHINO_OR_CLEAR)) {
return RHINO_NO_THIS_EVENT_OPT;
}
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (event->blk_obj.obj_type != RHINO_EVENT_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
/* if option is AND MASK or OR MASK */
if (opt & RHINO_FLAGS_AND_MASK) {
if ((event->flags & flags) == flags) {
status = RHINO_TRUE;
} else {
status = RHINO_FALSE;
}
} else {
if ((event->flags & flags) > 0u) {
status = RHINO_TRUE;
} else {
status = RHINO_FALSE;
}
}
if (status == RHINO_TRUE) {
*actl_flags = event->flags;
if (opt & RHINO_FLAGS_CLEAR_MASK) {
event->flags &= ~flags;
}
TRACE_EVENT_GET(g_active_task[cur_cpu_num], event);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* can't get event, and return immediately if wait_option is RHINO_NO_WAIT */
if (ticks == RHINO_NO_WAIT) {
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
/* system is locked so task can not be blocked just return immediately */
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
/* remember the passed information */
g_active_task[cur_cpu_num]->pend_option = opt;
g_active_task[cur_cpu_num]->pend_flags = flags;
g_active_task[cur_cpu_num]->pend_info = actl_flags;
pend_to_blk_obj((blk_obj_t *)event, g_active_task[cur_cpu_num], ticks, psr);
TRACE_EVENT_GET_BLK(g_active_task[cur_cpu_num], event, ticks);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
/* so the task is waked up, need know which reason cause wake up */
stat = pend_state_end_proc(g_active_task[cpu_cur_get()]);
RHINO_CPU_INTRPT_ENABLE();
return stat;
}
static kstat_t event_set(kevent_t *event, uint32_t flags, uint8_t opt)
{
CPSR_ALLOC();
klist_t *iter;
klist_t *event_head;
klist_t *iter_temp;
ktask_t *task;
uint8_t status;
uint32_t cur_event_flags;
/* this is only needed when system zero interrupt feature is enabled */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
status = RHINO_FALSE;
RHINO_CRITICAL_ENTER();
if (event->blk_obj.obj_type != RHINO_EVENT_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
event_head = &event->blk_obj.blk_list;
/* if the set_option is AND_MASK, it just clears the flags and will return immediately */
if (opt & RHINO_FLAGS_AND_MASK) {
event->flags &= flags;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
} else {
event->flags |= flags;
}
cur_event_flags = event->flags;
iter = event_head->next;
/* if list is not empty */
while (iter != event_head) {
task = krhino_list_entry(iter, ktask_t, task_list);
iter_temp = iter->next;
if (task->pend_option & RHINO_FLAGS_AND_MASK) {
if ((cur_event_flags & task->pend_flags) == task->pend_flags) {
status = RHINO_TRUE;
} else {
status = RHINO_FALSE;
}
} else {
if (cur_event_flags & task->pend_flags) {
status = RHINO_TRUE;
} else {
status = RHINO_FALSE;
}
}
if (status == RHINO_TRUE) {
(*(uint32_t *)(task->pend_info)) = cur_event_flags;
/* the task condition is met, just wake this task */
pend_task_wakeup(task);
TRACE_EVENT_TASK_WAKE(g_active_task[cpu_cur_get()], task, event);
/* does it need to clear the flags */
if (task->pend_option & RHINO_FLAGS_CLEAR_MASK) {
event->flags &= ~(task->pend_flags);
}
}
iter = iter_temp;
}
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
kstat_t krhino_event_set(kevent_t *event, uint32_t flags, uint8_t opt)
{
NULL_PARA_CHK(event);
if ((opt != RHINO_AND) && (opt != RHINO_OR)) {
return RHINO_NO_THIS_EVENT_OPT;
}
return event_set(event, flags, opt);
}
#endif /* RHINO_CONFIG_EVENT_FLAG */

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
void idle_count_set(idle_count_t value)
{
CPSR_ALLOC();
RHINO_CPU_INTRPT_DISABLE();
g_idle_count[cpu_cur_get()] = value;
RHINO_CPU_INTRPT_ENABLE();
}
idle_count_t idle_count_get(void)
{
CPSR_ALLOC();
idle_count_t idle_count;
RHINO_CPU_INTRPT_DISABLE();
idle_count = g_idle_count[cpu_cur_get()];
RHINO_CPU_INTRPT_ENABLE();
return idle_count;
}
#endif
void __attribute__((weak)) user_idle_hook(void)
{
}
void idle_task(void *arg)
{
CPSR_ALLOC();
/* avoid warning */
(void)arg;
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_idle_pre_hook();
#endif
while (RHINO_TRUE) {
RHINO_CPU_INTRPT_DISABLE();
g_idle_count[cpu_cur_get()]++;
RHINO_CPU_INTRPT_ENABLE();
user_idle_hook();
uint32_t in_disable_irq(void);
if (in_disable_irq()) {
void enable_irq(uint32_t flags);
enable_irq(0);
}
dym_mem_proc_hdl();
/* RHINO_CONFIG_CPU_PWR_MGMT */
#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
cpu_pwr_down();
#endif
}
}

View File

@@ -0,0 +1,108 @@
#include "sys_config.h"
#include "tx_platform.h"
#include <csi_kernel.h>
#include <k_api.h>
#include <csi_core.h>
#include <stdio.h>
#if RHINO_CONFIG_ISR_TASK
#define RB_NPOS(rb, pos, i) ({ \
uint32 __pos__ = (rb)->pos;\
((__pos__+(i)>=(rb)->qsize) ? (__pos__+(i)-(rb)->qsize) : (__pos__+(i))); \
})
/* rpos == wpos 表示 rbuffer 为空 */
#define RB_EMPTY(rb) ((rb)->wpos == (rb)->rpos)
/* wpos+1 == rpos 表示 rbuffer 已满 */
#define RB_FULL(rb) ({ \
uint32 _rpos_ = ((rb)->rpos);\
uint32 _wpos_ = ((rb)->wpos)+1;\
((_wpos_>=(rb)->qsize) ? (_wpos_-(rb)->qsize) : (_wpos_)) == (_rpos_);\
})
/* rbuffer 中未被读取的数据长度 */
#define RB_COUNT(rb) ({ \
uint32 _rpos_ = ((rb)->rpos);\
uint32 _wpos_ = ((rb)->wpos);\
((_rpos_<=_wpos_)? (_wpos_-_rpos_): ((rb)->qsize-_rpos_+_wpos_))\
})
/* rbuffer中剩余空间长度 */
#define RB_IDLE(rb) ({ \
uint32 _rpos_ = ((rb)->rpos);\
uint32 _wpos_ = ((rb)->wpos);\
((_wpos_<_rpos_)? (_rpos_-_wpos_-1): ((rb)->qsize-_wpos_+_rpos_-1))\
})
/*get a value from ringbuffer*/
#define RB_GET(rb, val) do{\
if(!RB_EMPTY(rb)){\
val = (rb)->rbq[(rb)->rpos];\
(rb)->rpos = RB_NPOS((rb), rpos, 1);\
}\
} while(0)
/*set a value into ringbuffer*/
#define RB_SET(rb, val) do{\
if(!RB_FULL(rb)){\
(rb)->rbq[(rb)->wpos] = val;\
(rb)->wpos = RB_NPOS((rb), wpos, 1);\
}else{ k_err_proc(RHINO_INTRPT_ISR_OVF); }\
} while (0)
typedef struct {
void (*hdl)(void *data);
void *data;
} k_isr_data;
struct k_isr_buff {
uint8_t rpos, wpos, qsize, busy;
k_isr_data *rbq;
};
static void ISR_task(void *pa)
{
kstat_t ret;
k_isr_data isr;
struct k_isr_buff *rb = (struct k_isr_buff *)g_isr_buff;
while (1) {
ret = krhino_sem_take(&g_isr_sem, 0xffffffff);
if (ret != RHINO_SUCCESS) {
k_err_proc(RHINO_SYS_FATAL_ERR);
}
isr.hdl = 0;
RB_GET(rb, isr);
if (isr.hdl) {
isr.hdl(isr.data);
}
}
}
__init void kisr_init(void)
{
struct k_isr_buff *rb = (struct k_isr_buff *)g_isr_buff;
rb->wpos = 0;
rb->rpos = 0;
rb->qsize = RHINO_CONFIG_ISR_BUFF_SIZE;
rb->rbq = (k_isr_data *)(rb + 1);
krhino_sem_create(&g_isr_sem, "isr_sem", 0);
krhino_task_create(&g_isr_task, "isr", NULL,
RHINO_CONFIG_ISR_TASK_PRI, 0u, g_isr_task_stack,
RHINO_CONFIG_ISR_TASK_STACK_SIZE, ISR_task, 1u);
}
void isr_run(void (*hdl)(void *data), void *data)
{
k_isr_data isr = { hdl, data };
struct k_isr_buff *rb = (struct k_isr_buff *)g_isr_buff;
uint32_t flag = __disable_irq();
RB_SET(rb, isr);
if (!flag) __enable_irq();
krhino_sem_give(&g_isr_sem);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#ifndef MPOOL_ALLOC
#if (RHINO_CONFIG_MM_BLK > 0)
kstat_t krhino_mblk_pool_init(mblk_pool_t *pool, const name_t *name,
void *pool_start,
size_t blk_size, size_t pool_size)
{
CPSR_ALLOC();
uint32_t blks; /* max blocks mem pool offers */
uint8_t *blk_cur; /* block pointer for traversing */
uint8_t *blk_next; /* next block pointe for traversing */
uint8_t *pool_end; /* mem pool end */
uint8_t addr_align_mask; /* address alignment */
NULL_PARA_CHK(pool);
NULL_PARA_CHK(name);
NULL_PARA_CHK(pool_start);
/* over one block at least */
if (pool_size < (blk_size << 1u)) {
return RHINO_BLK_POOL_SIZE_ERR;
}
/* check address & size alignment */
addr_align_mask = sizeof(void *) - 1u;
if (((size_t)pool_start & addr_align_mask) > 0u) {
return RHINO_INV_ALIGN;
}
if ((blk_size & addr_align_mask) > 0u) {
return RHINO_INV_ALIGN;
}
if ((pool_size & addr_align_mask) > 0u) {
return RHINO_INV_ALIGN;
}
pool_end = (uint8_t *)pool_start + pool_size;
blks = 0u;
blk_cur = (uint8_t *)pool_start;
blk_next = blk_cur + blk_size;
while (blk_next < pool_end) {
blks++;
/* use initial 4 byte point to next block */
*(uint8_t **)blk_cur = blk_next;
blk_cur = blk_next;
blk_next = blk_cur + blk_size;
}
if (blk_next == pool_end) {
blks++;
}
/* the last one */
*((uint8_t **)blk_cur) = NULL;
pool->pool_name = name;
pool->blk_whole = blks;
pool->blk_avail = blks;
pool->blk_size = blk_size;
pool->avail_list = (uint8_t *)pool_start;
pool->obj_type = RHINO_MM_BLK_OBJ_TYPE;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
RHINO_CRITICAL_ENTER();
klist_insert(&(g_kobj_list.mblkpool_head), &pool->mblkpool_stats_item);
RHINO_CRITICAL_EXIT();
#endif
TRACE_MBLK_POOL_CREATE(krhino_cur_task_get(), pool);
return RHINO_SUCCESS;
}
kstat_t krhino_mblk_alloc(mblk_pool_t *pool, void **blk)
{
CPSR_ALLOC();
kstat_t status;
uint8_t *avail_blk;
NULL_PARA_CHK(pool);
NULL_PARA_CHK(blk);
if (pool->obj_type != RHINO_MM_BLK_OBJ_TYPE) {
return RHINO_KOBJ_TYPE_ERR;
}
RHINO_CRITICAL_ENTER();
if (pool->blk_avail > 0u) {
avail_blk = pool->avail_list;
*((uint8_t **)blk) = avail_blk;
/* the first 4 byte is the pointer for next block */
pool->avail_list = *(uint8_t **)(avail_blk);
pool->blk_avail--;
status = RHINO_SUCCESS;
} else {
*((uint8_t **)blk) = NULL;
status = RHINO_NO_MEM;
}
RHINO_CRITICAL_EXIT();
return status;
}
kstat_t krhino_mblk_free(mblk_pool_t *pool, void *blk)
{
CPSR_ALLOC();
NULL_PARA_CHK(pool);
NULL_PARA_CHK(blk);
if (pool->obj_type != RHINO_MM_BLK_OBJ_TYPE) {
return RHINO_KOBJ_TYPE_ERR;
}
RHINO_CRITICAL_ENTER();
/* use the first 4 byte of the free block point to head of avail list */
*((uint8_t **)blk) = pool->avail_list;
pool->avail_list = blk;
pool->blk_avail++;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
#endif /* RHINO_CONFIG_MM_BLK */
#endif

View File

@@ -0,0 +1,480 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <k_api.h>
#ifndef MPOOL_ALLOC
#if (RHINO_CONFIG_MM_TLF > 0)
#include "k_mm.h"
#endif
#include "k_mm_debug.h"
#ifdef CONFIG_AOS_CLI
#include "aos/types.h"
#include "aos/cli.h"
extern int csp_printf(const char *fmt, ...);
#define print aos_cli_printf
#else
#define print printf
#endif
#if (RHINO_CONFIG_MM_DEBUG > 0)
extern klist_t g_mm_region_list_head;
#if (RHINO_CONFIG_MM_LEAKCHECK > 0)
static mm_scan_region_t g_mm_scan_region[AOS_MM_SCAN_REGION_MAX];
static void **g_leak_match;
static uint32_t g_recheck_flag = 0;
static uint32_t check_malloc_region(void *adress);
uint32_t if_adress_is_valid(void *adress);
uint32_t dump_mmleak(void);
uint32_t krhino_mm_leak_region_init(void *start, void *end)
{
static uint32_t i = 0;
if (i >= AOS_MM_SCAN_REGION_MAX) {
return i;
}
if ((start == NULL) || (end == NULL)) {
return i;
}
g_mm_scan_region[i].start = start;
g_mm_scan_region[i].end = end;
i++;
return i;
}
static uint32_t check_task_stack(ktask_t *task, void **p)
{
uint32_t offset = 0;
kstat_t rst = RHINO_SUCCESS;
void *start, *cur, *end;
start = task->task_stack_base;
end = task->task_stack_base + task->stack_size;
rst = krhino_task_stack_cur_free(task, &offset);
if (rst == RHINO_SUCCESS) {
cur = task->task_stack_base + task->stack_size - offset;
} else {
k_err_proc(RHINO_SYS_SP_ERR);
return 0;
}
if ((size_t)p >= (size_t)cur &&
(size_t)p < (size_t)end) {
return 1;
} else if ((size_t)p >= (size_t)start && (size_t)p < (size_t)cur) {
return 0;
}
/*maybe lost*/
return 1;
}
static uint32_t check_if_in_stack(void **p)
{
klist_t *taskhead = &g_kobj_list.task_head;
klist_t *taskend = taskhead;
klist_t *tmp;
ktask_t *task;
for (tmp = taskhead->next; tmp != taskend; tmp = tmp->next) {
task = krhino_list_entry(tmp, ktask_t, task_stats_item);
if (1 == check_task_stack(task, p)) {
return 1;
}
}
return 0;
}
uint32_t scan_region(void *start, void *end, void *adress)
{
void **p = (void **)((uint32_t)start & ~(sizeof(size_t) - 1));
while ((void *)p < end) {
if (NULL != p && adress == *p) {
g_leak_match = p;
return 1;
}
p++;
}
return 0;
}
uint32_t check_mm_leak(uint8_t *adress)
{
uint32_t rst = 0;
uint32_t i;
for (i = 0; i < AOS_MM_SCAN_REGION_MAX; i++) {
if ((NULL == g_mm_scan_region[i].start) || (NULL == g_mm_scan_region[i].end)) {
continue;
}
if (1 == scan_region(g_mm_scan_region[i].start, g_mm_scan_region[i].end,
adress)) {
return 1;
}
}
rst = check_malloc_region(adress);
if (1 == rst) {
return 1;
}
return 0;
}
static uint32_t recheck(void *start, void *end)
{
void **p = (void **)((uint32_t)start & ~(sizeof(size_t) - 1));
g_recheck_flag = 1;
while ((void *)p <= end) {
if (NULL != p && 1 == if_adress_is_valid(*p)) {
if ( 1 == check_mm_leak(*p)) {
g_recheck_flag = 0;
return 1;
}
}
p++;
}
g_recheck_flag = 0;
return 0;
}
#if (RHINO_CONFIG_MM_TLF > 0)
uint32_t check_malloc_region(void *adress)
{
uint32_t rst = 0;
k_mm_region_info_t *reginfo, *nextreg;
k_mm_list_t *next, *cur;
NULL_PARA_CHK(g_kmm_head);
reginfo = g_kmm_head->regioninfo;
while (reginfo) {
VGF(VALGRIND_MAKE_MEM_DEFINED(reginfo, sizeof(k_mm_region_info_t)));
cur = (k_mm_list_t *) ((char *) reginfo - MMLIST_HEAD_SIZE);
/*jump first blk*/
cur = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
while (cur) {
VGF(VALGRIND_MAKE_MEM_DEFINED(cur, MMLIST_HEAD_SIZE));
if ((cur->size & RHINO_MM_BLKSIZE_MASK)) {
next = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
if (0 == g_recheck_flag && !(cur->size & RHINO_MM_FREE)) {
if ((uint8_t *)krhino_cur_task_get()->task_stack_base >= cur->mbinfo.buffer
&& (uint8_t *)krhino_cur_task_get()->task_stack_base < (uint8_t *)next) {
cur = next;
continue;
}
rst = scan_region(cur->mbinfo.buffer, (void *) next, adress);
if (1 == rst) {
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
return check_if_in_stack(g_leak_match);
}
}
} else {
next = NULL;
}
if (1 == g_recheck_flag &&
(uint32_t)adress >= (uint32_t)cur->mbinfo.buffer &&
(uint32_t)adress < (uint32_t)next) {
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
return 1;
}
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
cur = next;
}
nextreg = reginfo->next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
reginfo = nextreg;
}
return 0;
}
uint32_t if_adress_is_valid(void *adress)
{
k_mm_region_info_t *reginfo, *nextreg;
k_mm_list_t *next, *cur;
reginfo = g_kmm_head->regioninfo;
while (reginfo) {
VGF(VALGRIND_MAKE_MEM_DEFINED(reginfo, sizeof(k_mm_region_info_t)));
cur = (k_mm_list_t *) ((char *) reginfo - MMLIST_HEAD_SIZE);
/*jump first blk*/
cur = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
while (cur) {
VGF(VALGRIND_MAKE_MEM_DEFINED(cur, MMLIST_HEAD_SIZE));
if ((cur->size & RHINO_MM_BLKSIZE_MASK)) {
next = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
if (!(cur->size & RHINO_MM_FREE) &&
(size_t)adress >= (size_t)cur->mbinfo.buffer && (size_t)adress < (size_t)next ) {
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
return 1;
}
} else {
next = NULL;
}
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
cur = next;
}
nextreg = reginfo->next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
reginfo = nextreg;
}
return 0;
}
uint32_t dump_mmleak()
{
k_mm_region_info_t *reginfo, *nextreg;
k_mm_list_t *next, *cur;
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
krhino_mutex_lock(&g_kmm_head->mm_mutex, RHINO_WAIT_FOREVER);
#endif
reginfo = g_kmm_head->regioninfo;
while (reginfo) {
VGF(VALGRIND_MAKE_MEM_DEFINED(reginfo, sizeof(k_mm_region_info_t)));
cur = (k_mm_list_t *) ((char *) reginfo - MMLIST_HEAD_SIZE);
/*jump first blk*/
cur = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
while (cur) {
VGF(VALGRIND_MAKE_MEM_DEFINED(cur, MMLIST_HEAD_SIZE));
if ((cur->size & RHINO_MM_BLKSIZE_MASK)) {
next = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
if (!(cur->size & RHINO_MM_FREE) &&
0 == check_mm_leak(cur->mbinfo.buffer)
&& 0 == recheck((void *)cur->mbinfo.buffer , (void *)next)) {
print("adress:0x%0x owner:0x%0x len:%-5d type:%s\r\n",
(void *)cur->mbinfo.buffer, cur->owner,
cur->size & RHINO_MM_BLKSIZE_MASK, "leak");
}
} else {
next = NULL;
}
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
cur = next;
}
nextreg = reginfo->next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
reginfo = nextreg;
}
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
krhino_mutex_unlock(&g_kmm_head->mm_mutex);
#endif
return 0;
}
#endif
#endif
#if (RHINO_CONFIG_MM_TLF > 0)
void print_block(k_mm_list_t *b)
{
if (!b) {
return;
}
print("%p ", b);
if (b->size & RHINO_MM_FREE) {
#if (RHINO_CONFIG_MM_DEBUG > 0u)
if (b->dye != RHINO_MM_FREE_DYE) {
print("!");
} else {
print(" ");
}
#endif
print("free ");
} else {
#if (RHINO_CONFIG_MM_DEBUG > 0u)
if (b->dye != RHINO_MM_CORRUPT_DYE) {
print("!");
} else {
print(" ");
}
#endif
print("used ");
}
if ((b->size & RHINO_MM_BLKSIZE_MASK)) {
print(" %6lu ", (unsigned long) (b->size & RHINO_MM_BLKSIZE_MASK));
} else {
print(" sentinel ");
}
#if (RHINO_CONFIG_MM_DEBUG > 0u)
print(" %8x ", b->dye);
print(" 0x%-8x ", b->owner);
#endif
if (b->size & RHINO_MM_PREVFREE) {
print("pre-free [%8p];", b->prev);
} else {
print("pre-used;");
}
if (b->size & RHINO_MM_FREE) {
VGF(VALGRIND_MAKE_MEM_DEFINED(&b->mbinfo, sizeof(struct free_ptr_struct)));
print(" free[%8p,%8p] ", b->mbinfo.free_ptr.prev, b->mbinfo.free_ptr.next);
VGF(VALGRIND_MAKE_MEM_NOACCESS(&b->mbinfo, sizeof(struct free_ptr_struct)));
}
print("\r\n");
}
void dump_kmm_free_map(k_mm_head *mmhead)
{
k_mm_list_t *next, *tmp;
int i, j;
if (!mmhead) {
return;
}
print("address, stat size dye caller pre-stat point\r\n");
print("FL bitmap: 0x%x\r\n", (unsigned) mmhead->fl_bitmap);
for (i = 0; i < FLT_SIZE; i++) {
if (mmhead->sl_bitmap[i]) {
print("SL bitmap 0x%x\r\n", (unsigned) mmhead->sl_bitmap[i]);
}
for (j = 0; j < SLT_SIZE; j++) {
next = mmhead->mm_tbl[i][j];
if (next) {
print("-> [%d][%d]\r\n", i, j);
}
while (next) {
VGF(VALGRIND_MAKE_MEM_DEFINED(next, MMLIST_HEAD_SIZE));
print_block(next);
VGF(VALGRIND_MAKE_MEM_DEFINED(&next->mbinfo, sizeof(struct free_ptr_struct)));
tmp = next->mbinfo.free_ptr.next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(&next->mbinfo, sizeof(struct free_ptr_struct)));
VGF(VALGRIND_MAKE_MEM_NOACCESS(next, MMLIST_HEAD_SIZE));
next = tmp;
}
}
}
}
void dump_kmm_map(k_mm_head *mmhead)
{
k_mm_region_info_t *reginfo, *nextreg;
k_mm_list_t *next, *cur;
if (!mmhead) {
return;
}
print("ALL BLOCKS\r\n");
print("address, stat size dye caller pre-stat point\r\n");
reginfo = mmhead->regioninfo;
while (reginfo) {
VGF(VALGRIND_MAKE_MEM_DEFINED(reginfo, sizeof(k_mm_region_info_t)));
cur = (k_mm_list_t *) ((char *) reginfo - MMLIST_HEAD_SIZE);
while (cur) {
VGF(VALGRIND_MAKE_MEM_DEFINED(cur, MMLIST_HEAD_SIZE));
print_block(cur);
if ((cur->size & RHINO_MM_BLKSIZE_MASK)) {
next = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
} else {
next = NULL;
}
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
cur = next;
}
nextreg = reginfo->next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
reginfo = nextreg;
}
}
void dump_kmm_statistic_info(k_mm_head *mmhead)
{
int i = 0;
if (!mmhead) {
return;
}
#if (K_MM_STATISTIC > 0)
print(" free | used | maxused\r\n");
print(" %10d | %10d | %10d\r\n", mmhead->free_size, mmhead->used_size,
mmhead->maxused_size);
print("\r\n");
print("-----------------alloc size statistic:-----------------\r\n");
for (i = 0; i < MAX_MM_BIT - 1; i++) {
if (i % 4 == 0 && i != 0) {
print("\r\n");
}
print("[2^%02d] bytes: %5d |", (i + 2), mmhead->mm_size_stats[i]);
}
print("\r\n");
#endif
}
uint32_t dumpsys_mm_info_func(char *buf, uint32_t len)
{
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
krhino_mutex_lock(&g_kmm_head->mm_mutex, RHINO_WAIT_FOREVER);
#endif
VGF(VALGRIND_MAKE_MEM_DEFINED(g_kmm_head, sizeof(k_mm_head)));
print("\r\n");
print("------------------------------- all memory blocks --------------------------------- \r\n");
print("g_kmm_head = %8x\r\n", (unsigned int)g_kmm_head);
dump_kmm_map(g_kmm_head);
print("\r\n");
print("----------------------------- all free memory blocks ------------------------------- \r\n");
dump_kmm_free_map(g_kmm_head);
print("\r\n");
print("------------------------- memory allocation statistic ------------------------------ \r\n");
dump_kmm_statistic_info(g_kmm_head);
VGF(VALGRIND_MAKE_MEM_NOACCESS(g_kmm_head, sizeof(k_mm_head)));
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
krhino_mutex_unlock(&g_kmm_head->mm_mutex);
#endif
return RHINO_SUCCESS;
}
#endif
#endif
#endif

View File

@@ -0,0 +1,456 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include "csi_core.h"
kstat_t mutex_create(kmutex_t *mutex, const name_t *name, uint8_t mm_alloc_flag)
{
CPSR_ALLOC();
NULL_PARA_CHK(mutex);
NULL_PARA_CHK(name);
/* init the list */
klist_init(&mutex->blk_obj.blk_list);
mutex->blk_obj.blk_policy = BLK_POLICY_PRI;
mutex->blk_obj.name = name;
mutex->mutex_task = NULL;
mutex->mutex_list = NULL;
mutex->mm_alloc_flag = mm_alloc_flag;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
RHINO_CRITICAL_ENTER();
klist_insert(&(g_kobj_list.mutex_head), &mutex->mutex_item);
RHINO_CRITICAL_EXIT();
#endif
mutex->blk_obj.obj_type = RHINO_MUTEX_OBJ_TYPE;
TRACE_MUTEX_CREATE(krhino_cur_task_get(), mutex, name);
return RHINO_SUCCESS;
}
kstat_t krhino_mutex_create(kmutex_t *mutex, const name_t *name)
{
return mutex_create(mutex, name, K_OBJ_STATIC_ALLOC);
}
static void mutex_release(ktask_t *task, kmutex_t *mutex_rel)
{
uint8_t new_pri;
/* find suitable task prio */
new_pri = mutex_pri_look(task, mutex_rel);
if (new_pri != task->prio) {
/* change prio */
task_pri_change(task, new_pri);
TRACE_MUTEX_RELEASE(g_active_task[cpu_cur_get()], task, new_pri);
}
}
kstat_t krhino_mutex_del(kmutex_t *mutex)
{
CPSR_ALLOC();
klist_t *blk_list_head;
if (mutex == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(mutex);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (mutex->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &mutex->blk_obj.blk_list;
mutex->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
if (mutex->mutex_task != NULL) {
mutex_release(mutex->mutex_task, mutex);
}
/* all task blocked on this mutex is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&mutex->mutex_item);
#endif
TRACE_MUTEX_DEL(g_active_task[cpu_cur_get()], mutex);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_mutex_dyn_create(kmutex_t **mutex, const name_t *name)
{
kstat_t stat;
kmutex_t *mutex_obj;
if (mutex == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(mutex);
mutex_obj = krhino_mm_alloc(sizeof(kmutex_t), __builtin_return_address(0));
if (mutex_obj == NULL) {
return RHINO_NO_MEM;
}
stat = mutex_create(mutex_obj, name, K_OBJ_DYN_ALLOC);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(mutex_obj);
return stat;
}
*mutex = mutex_obj;
return stat;
}
kstat_t krhino_mutex_dyn_del(kmutex_t *mutex)
{
CPSR_ALLOC();
klist_t *blk_list_head;
if (mutex == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(mutex);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (mutex->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &mutex->blk_obj.blk_list;
mutex->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
if (mutex->mutex_task != NULL) {
mutex_release(mutex->mutex_task, mutex);
}
/* all task blocked on this mutex is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&mutex->mutex_item);
#endif
TRACE_MUTEX_DEL(g_active_task[cpu_cur_get()], mutex);
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(mutex);
return RHINO_SUCCESS;
}
#endif
uint8_t mutex_pri_limit(ktask_t *task, uint8_t pri)
{
kmutex_t *mutex_tmp;
uint8_t high_pri;
ktask_t *first_blk_task;
klist_t *blk_list_head;
high_pri = pri;
for (mutex_tmp = task->mutex_list; mutex_tmp != NULL;
mutex_tmp = mutex_tmp->mutex_list) {
blk_list_head = &mutex_tmp->blk_obj.blk_list;
if (!is_klist_empty(blk_list_head)) {
first_blk_task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
pri = first_blk_task->prio;
}
/* can not set lower prio than the highest prio in all mutexes which hold lock */
if (pri < high_pri) {
high_pri = pri;
}
}
return high_pri;
}
uint8_t mutex_pri_look(ktask_t *task, kmutex_t *mutex_rel)
{
kmutex_t *mutex_tmp;
kmutex_t **prev;
uint8_t new_pri;
uint8_t pri;
ktask_t *first_blk_task;
klist_t *blk_list_head;
/* the base prio of task */
new_pri = task->b_prio;
/* the highest prio in mutex which is locked */
pri = new_pri;
prev = &task->mutex_list;
while ((mutex_tmp = *prev) != NULL) {
if (mutex_tmp == mutex_rel) {
/* delete itself from list and make task->mutex_list point to next */
*prev = mutex_tmp->mutex_list;
continue;
}
blk_list_head = &mutex_tmp->blk_obj.blk_list;
if (!is_klist_empty(blk_list_head)) {
first_blk_task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
pri = first_blk_task->prio;
}
if (new_pri > pri) {
new_pri = pri;
}
prev = &mutex_tmp->mutex_list;
}
return new_pri;
}
void mutex_task_pri_reset(ktask_t *task)
{
kmutex_t *mutex_tmp;
ktask_t *mutex_task;
if (task->blk_obj->obj_type == RHINO_MUTEX_OBJ_TYPE) {
mutex_tmp = (kmutex_t *)(task->blk_obj);
mutex_task = mutex_tmp->mutex_task;
/* the new highest prio task blocked on this mutex may decrease prio than before so reset the mutex task prio */
if (mutex_task->prio == task->prio) {
mutex_release(mutex_task, NULL);
}
}
}
#ifdef MUTEX_LOCKERR_MAX
extern uint32_t mutex_lockerr_list[MUTEX_LOCKERR_MAX];
extern uint32_t mutex_lockerr_cnt;
void krhino_mutex_lockerr(uint32_t lr)
{
int i = 0;
for(i=0; i<mutex_lockerr_cnt; i++){
if(mutex_lockerr_list[i] == lr){
return;
}
}
mutex_lockerr_list[mutex_lockerr_cnt++] = lr;
}
#endif
kstat_t krhino_mutex_lock(kmutex_t *mutex, tick_t ticks, uint32_t lr)
{
CPSR_ALLOC();
kstat_t ret;
ktask_t *mutex_task;
uint8_t cur_cpu_num;
NULL_PARA_CHK(mutex);
if (g_sys_stat == RHINO_STOPPED) {
return RHINO_SUCCESS;
}
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
#ifdef MUTEX_LOCKERR_MAX
if(mutex_lockerr_cnt < MUTEX_LOCKERR_MAX && (__in_disable_irq(psr) || __in_interrupt())){
krhino_mutex_lockerr(mutex, lr);
}
#endif
INTRPT_NESTED_LEVEL_CHK();
if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
/* if the same task get the same mutex again, it causes mutex owner nested */
if (g_active_task[cur_cpu_num] == mutex->mutex_task) {
if (mutex->owner_nested == (mutex_nested_t)-1) {
/* fatal error here, system must be stoped here */
k_err_proc(RHINO_MUTEX_NESTED_OVF);
RHINO_CRITICAL_EXIT();
return RHINO_MUTEX_NESTED_OVF;
} else {
mutex->owner_nested++;
}
RHINO_CRITICAL_EXIT();
return RHINO_MUTEX_OWNER_NESTED;
}
mutex_task = mutex->mutex_task;
if (mutex_task == NULL) {
/* get lock */
mutex->mutex_task = g_active_task[cur_cpu_num];
mutex->mutex_list = g_active_task[cur_cpu_num]->mutex_list;
g_active_task[cur_cpu_num]->mutex_list = mutex;
mutex->owner_nested = 1u;
TRACE_MUTEX_GET(g_active_task[cur_cpu_num], mutex, ticks);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* can't get mutex, and return immediately if wait_option is RHINO_NO_WAIT */
if (ticks == RHINO_NO_WAIT) {
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
/* system is locked so task can not be blocked just return immediately */
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
/* if current task is a higher prio task and block on the mutex
prio inverse condition happened, prio inherit method is used here */
if (g_active_task[cur_cpu_num]->prio < mutex_task->prio) {
task_pri_change(mutex_task, g_active_task[cur_cpu_num]->prio);
TRACE_TASK_PRI_INV(g_active_task[cur_cpu_num], mutex_task);
}
/* any way block the current task */
pend_to_blk_obj((blk_obj_t *)mutex, g_active_task[cur_cpu_num], ticks, psr);
TRACE_MUTEX_GET_BLK(g_active_task[cur_cpu_num], mutex, ticks);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
/* so the task is waked up, need know which reason cause wake up */
ret = pend_state_end_proc(g_active_task[cpu_cur_get()]);
RHINO_CPU_INTRPT_ENABLE();
return ret;
}
kstat_t krhino_mutex_unlock(kmutex_t *mutex)
{
CPSR_ALLOC();
klist_t *blk_list_head;
ktask_t *task;
uint8_t cur_cpu_num;
NULL_PARA_CHK(mutex);
if (g_sys_stat == RHINO_STOPPED) {
return RHINO_SUCCESS;
}
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
/* mutex must be released by itself */
if (g_active_task[cur_cpu_num] != mutex->mutex_task) {
RHINO_CRITICAL_EXIT();
return RHINO_MUTEX_NOT_RELEASED_BY_OWNER;
}
mutex->owner_nested--;
if (mutex->owner_nested > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_MUTEX_OWNER_NESTED;
}
mutex_release(g_active_task[cur_cpu_num], mutex);
blk_list_head = &mutex->blk_obj.blk_list;
/* if no block task on this list just return */
if (is_klist_empty(blk_list_head)) {
/* No wait task */
mutex->mutex_task = NULL;
TRACE_MUTEX_RELEASE_SUCCESS(g_active_task[cur_cpu_num], mutex);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* there must have task blocked on this mutex object */
task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
/* wake up the occupy task, which is the highst prio task on the list */
pend_task_wakeup(task);
TRACE_MUTEX_TASK_WAKE(g_active_task[cur_cpu_num], task, mutex);
/* change mutex get task */
mutex->mutex_task = task;
mutex->mutex_list = task->mutex_list;
task->mutex_list = mutex;
mutex->owner_nested = 1u;
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
__bobj uint64_t g_sys_tick_count;
__bobj uint32_t g_cpuloading;
__bobj uint32_t g_cpuloading_int;
__bobj volatile uint64_t g_sys_time_last;
__bobj kstat_t g_sys_stat;
__bobj uint8_t g_idle_task_spawned[RHINO_CONFIG_CPU_NUM];
__bobj runqueue_t g_ready_queue;
/* schedule lock counter */
__bobj uint8_t g_sched_lock[RHINO_CONFIG_CPU_NUM];
__bobj uint8_t g_intrpt_nested_level[RHINO_CONFIG_CPU_NUM];
/* highest pri task in ready queue */
__bobj ktask_t *g_preferred_ready_task[RHINO_CONFIG_CPU_NUM];
/* current active task */
__bobj ktask_t *g_active_task[RHINO_CONFIG_CPU_NUM];
/* idle task attribute */
__bobj ktask_t g_idle_task[RHINO_CONFIG_CPU_NUM];
__bobj idle_count_t g_idle_count[RHINO_CONFIG_CPU_NUM];
__bobj cpu_stack_t g_idle_task_stack[RHINO_CONFIG_CPU_NUM][RHINO_CONFIG_IDLE_TASK_STACK_SIZE];
/* tick attribute */
__bobj tick_t g_tick_count;
__bobj klist_t g_tick_head;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
__bobj kobj_list_t g_kobj_list;
#endif
#if (RHINO_CONFIG_TIMER > 0)
__bobj klist_t g_timer_head;
__bobj sys_time_t g_timer_count;
__bobj ktask_t g_timer_task;
__bobj cpu_stack_t g_timer_task_stack[RHINO_CONFIG_TIMER_TASK_STACK_SIZE];
__bobj kbuf_queue_t g_timer_queue;
__bobj k_timer_queue_cb timer_queue_cb[RHINO_CONFIG_TIMER_MSG_NUM];
#endif
#if (RHINO_CONFIG_ISR_TASK > 0)
__bobj ktask_t g_isr_task;
__bobj ksem_t g_isr_sem;
__bobj uint32_t g_isr_buff[4+2*RHINO_CONFIG_ISR_BUFF_SIZE];
__bobj cpu_stack_t g_isr_task_stack[RHINO_CONFIG_ISR_TASK_STACK_SIZE];
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
__bobj hr_timer_t g_sched_disable_time_start;
__bobj hr_timer_t g_sched_disable_max_time;
__bobj hr_timer_t g_cur_sched_disable_max_time;
#endif
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
__bobj uint16_t g_intrpt_disable_times;
__bobj hr_timer_t g_intrpt_disable_time_start;
__bobj hr_timer_t g_intrpt_disable_max_time;
__bobj hr_timer_t g_cur_intrpt_disable_max_time;
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
__bobj hr_timer_t g_sys_measure_waste;
#endif
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
__bobj ktask_t g_cpu_usage_task;
__bobj cpu_stack_t g_cpu_task_stack[RHINO_CONFIG_CPU_USAGE_TASK_STACK];
__bobj idle_count_t g_idle_count_max;
__bobj uint32_t g_cpu_usage;
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
__bobj ctx_switch_t g_sys_ctx_switch_times;
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
__bobj ksem_t g_res_sem;
__bobj klist_t g_res_list;
__bobj ktask_t g_dyn_task;
__bobj cpu_stack_t g_dyn_task_stack[RHINO_CONFIG_K_DYN_TASK_STACK];
#endif
#if (RHINO_CONFIG_WORKQUEUE > 0)
__bobj klist_t g_workqueue_list_head;
__bobj kmutex_t g_workqueue_mutex;
__bobj kworkqueue_t g_workqueue_default;
__bobj cpu_stack_t g_workqueue_stack[RHINO_CONFIG_WORKQUEUE_STACK_SIZE];
#endif
#if (RHINO_CONFIG_MM_TLF > 0)
//k_mm_head *g_kmm_head;
#endif
__bobj kspinlock_t g_sys_lock;
__bobj uint8_t g_in_interrupt;

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include "csi_core.h"
RHINO_INLINE void pend_list_add(klist_t *head, ktask_t *task)
{
klist_t *tmp;
klist_t *list_start = head;
klist_t *list_end = head;
for (tmp = list_start->next; tmp != list_end; tmp = tmp->next) {
if (krhino_list_entry(tmp, ktask_t, task_list)->prio > task->prio) {
break;
}
}
klist_insert(tmp, &task->task_list);
}
void pend_task_wakeup(ktask_t *task)
{
/* wake up task depend on the different state of task */
switch (task->task_state) {
case K_PEND:
/* remove task on the block list because task is waken up */
klist_rm(&task->task_list);
/* add to the ready list again */
ready_list_add(&g_ready_queue, task);
task->task_state = K_RDY;
break;
case K_PEND_SUSPENDED:
/* remove task on the block list because task is waken up */
klist_rm(&task->task_list);
task->task_state = K_SUSPENDED;
break;
default:
k_err_proc(RHINO_SYS_FATAL_ERR);
break;
}
/* remove task on the tick list because task is waken up */
tick_list_rm(task);
task->blk_state = BLK_FINISH;
task->blk_obj = NULL;
}
void pend_to_blk_obj(blk_obj_t *blk_obj, ktask_t *task, tick_t timeout, uint32_t psr)
{
if(__in_disable_irq(psr) || __in_interrupt()){
assert_internal(__FUNCTION__, __LINE__, "SYS IRQ DISABLED",__builtin_return_address(0));
}
/* task need to remember which object is blocked on */
task->blk_obj = blk_obj;
if (timeout != RHINO_WAIT_FOREVER) {
tick_list_insert(task, timeout);
}
task->task_state = K_PEND;
/* remove from the ready list */
ready_list_rm(&g_ready_queue, task);
if (blk_obj->blk_policy == BLK_POLICY_FIFO) {
/* add to the end of blocked objet list */
klist_insert(&blk_obj->blk_list, &task->task_list);
} else {
/* add to the prio sorted block list */
pend_list_add(&blk_obj->blk_list, task);
}
}
void pend_task_rm(ktask_t *task)
{
switch (task->task_state) {
case K_PEND:
/* remove task on the block list because task is waken up */
klist_rm(&task->task_list);
/*add to the ready list again*/
ready_list_add(&g_ready_queue, task);
task->task_state = K_RDY;
break;
case K_PEND_SUSPENDED:
/* remove task on the block list because task is waken up */
klist_rm(&task->task_list);
task->task_state = K_SUSPENDED;
break;
default:
k_err_proc(RHINO_SYS_FATAL_ERR);
break;
}
/* remove task on the tick list because task is waken up */
tick_list_rm(task);
task->blk_state = BLK_DEL;
/* task is nothing blocked on so reset it to NULL */
task->blk_obj = NULL;
}
void pend_list_reorder(ktask_t *task)
{
if (task->blk_obj->blk_policy == BLK_POLICY_PRI) {
/* remove it first and add it again in prio sorted list */
klist_rm(&task->task_list);
pend_list_add(&task->blk_obj->blk_list, task);
}
}
kstat_t pend_state_end_proc(ktask_t *task)
{
kstat_t status;
switch (task->blk_state) {
case BLK_FINISH:
status = RHINO_SUCCESS;
break;
case BLK_ABORT:
status = RHINO_BLK_ABORT;
break;
case BLK_TIMEOUT:
status = RHINO_BLK_TIMEOUT;
break;
case BLK_DEL:
status = RHINO_BLK_DEL;
break;
default:
k_err_proc(RHINO_BLK_INV_STATE);
status = RHINO_BLK_INV_STATE;
break;
}
return status;
}

View File

@@ -0,0 +1,410 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_QUEUE > 0)
RHINO_INLINE void task_msg_recv(ktask_t *task, void *msg)
{
task->msg = msg;
pend_task_wakeup(task);
}
static kstat_t queue_create(kqueue_t *queue, const name_t *name, void **start,
size_t msg_num, uint8_t mm_alloc_flag)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
NULL_PARA_CHK(start);
NULL_PARA_CHK(name);
if (msg_num == 0u) {
return RHINO_INV_PARAM;
}
/* init the queue blocked list */
klist_init(&queue->blk_obj.blk_list);
queue->blk_obj.name = name;
queue->blk_obj.blk_policy = BLK_POLICY_PRI;
queue->msg_q.queue_start = start;
ringbuf_init(&queue->ringbuf, (void *)start, msg_num * sizeof(void *),
RINGBUF_TYPE_FIX, sizeof(void *));
queue->msg_q.size = msg_num;
queue->msg_q.cur_num = 0u;
queue->msg_q.peak_num = 0u;
queue->mm_alloc_flag = mm_alloc_flag;
RHINO_CRITICAL_ENTER();
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_insert(&(g_kobj_list.queue_head), &queue->queue_item);
#endif
RHINO_CRITICAL_EXIT();
queue->blk_obj.obj_type = RHINO_QUEUE_OBJ_TYPE;
return RHINO_SUCCESS;
}
kstat_t krhino_queue_create(kqueue_t *queue, const name_t *name, void **start,
size_t msg_num)
{
return queue_create(queue, name, start, msg_num, K_OBJ_STATIC_ALLOC);
}
kstat_t krhino_queue_del(kqueue_t *queue)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &queue->blk_obj.blk_list;
queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&queue->queue_item);
#endif
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_queue_dyn_create(kqueue_t **queue, const name_t *name,
size_t msg_num)
{
kstat_t stat;
kqueue_t *queue_obj;
void *msg_start;
NULL_PARA_CHK(queue);
queue_obj = krhino_mm_alloc(sizeof(kqueue_t), __builtin_return_address(0));
if (queue_obj == NULL) {
return RHINO_NO_MEM;
}
msg_start = krhino_mm_alloc(msg_num * sizeof(void *), __builtin_return_address(0));
if (msg_start == NULL) {
krhino_mm_free(queue_obj);
return RHINO_NO_MEM;
}
stat = queue_create(queue_obj, name, (void **)msg_start, msg_num,
K_OBJ_DYN_ALLOC);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(msg_start);
krhino_mm_free(queue_obj);
return stat;
}
*queue = queue_obj;
return stat;
}
kstat_t krhino_queue_dyn_del(kqueue_t *queue)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &queue->blk_obj.blk_list;
queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&queue->queue_item);
#endif
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(queue->msg_q.queue_start);
krhino_mm_free(queue);
return RHINO_SUCCESS;
}
#endif
static kstat_t msg_send(kqueue_t *p_q, void *p_void, uint8_t opt_wake_all)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(p_q);
/* this is only needed when system zero interrupt feature is enabled */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
RHINO_CRITICAL_ENTER();
if (p_q->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (p_q->msg_q.cur_num >= p_q->msg_q.size) {
RHINO_CRITICAL_EXIT();
return RHINO_QUEUE_FULL;
}
blk_list_head = &p_q->blk_obj.blk_list;
/* queue is not full here, if there is no blocked receive task */
if (is_klist_empty(blk_list_head)) {
p_q->msg_q.cur_num++;
/* update peak_num for debug */
if (p_q->msg_q.cur_num > p_q->msg_q.peak_num) {
p_q->msg_q.peak_num = p_q->msg_q.cur_num;
}
ringbuf_push(&p_q->ringbuf, &p_void, sizeof(void *));
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* wake all the task blocked on this queue */
if (opt_wake_all) {
while (!is_klist_empty(blk_list_head)) {
task_msg_recv(krhino_list_entry(blk_list_head->next, ktask_t, task_list),
p_void);
}
} else {
task_msg_recv(krhino_list_entry(blk_list_head->next, ktask_t, task_list),
p_void);
}
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
kstat_t krhino_queue_back_send(kqueue_t *queue, void *msg)
{
return msg_send(queue, msg, WAKE_ONE_TASK);
}
kstat_t krhino_queue_all_send(kqueue_t *queue, void *msg)
{
return msg_send(queue, msg, WAKE_ALL_TASK);
}
kstat_t krhino_queue_recv(kqueue_t *queue, tick_t ticks, void **msg)
{
CPSR_ALLOC();
kstat_t ret;
uint8_t cur_cpu_num;
NULL_PARA_CHK(queue);
NULL_PARA_CHK(msg);
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
cur_cpu_num = cpu_cur_get();
if ((g_intrpt_nested_level[cur_cpu_num] > 0u) && (ticks != RHINO_NO_WAIT)) {
RHINO_CRITICAL_EXIT();
return RHINO_NOT_CALLED_BY_INTRPT;
}
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
/* if queue has msgs, just receive it */
if (queue->msg_q.cur_num > 0u) {
ringbuf_pop(&queue->ringbuf, msg, NULL);
queue->msg_q.cur_num--;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
if (ticks == RHINO_NO_WAIT) {
*msg = NULL;
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
/* if system is locked, block operation is not allowed */
if (g_sched_lock[cur_cpu_num] > 0u) {
*msg = NULL;
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
pend_to_blk_obj((blk_obj_t *)queue, g_active_task[cur_cpu_num], ticks, psr);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
cur_cpu_num = cpu_cur_get();
ret = pend_state_end_proc(g_active_task[cur_cpu_num]);
switch (ret) {
case RHINO_SUCCESS:
*msg = g_active_task[cur_cpu_num]->msg;
break;
default:
*msg = NULL;
break;
}
RHINO_CPU_INTRPT_ENABLE();
return ret;
}
kstat_t krhino_queue_is_full(kqueue_t *queue)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->msg_q.cur_num >= queue->msg_q.size) {
ret = RHINO_QUEUE_FULL;
} else {
ret = RHINO_QUEUE_NOT_FULL;
}
RHINO_CRITICAL_EXIT();
return ret;
}
kstat_t krhino_queue_flush(kqueue_t *queue)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
queue->msg_q.cur_num = 0u;
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
kstat_t krhino_queue_info_get(kqueue_t *queue, msg_info_t *info)
{
CPSR_ALLOC();
klist_t *blk_list_head;
if (queue == NULL) {
return RHINO_NULL_PTR;
}
if (info == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(queue);
NULL_PARA_CHK(info);
RHINO_CPU_INTRPT_DISABLE();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CPU_INTRPT_ENABLE();
return RHINO_KOBJ_TYPE_ERR;
}
blk_list_head = &queue->blk_obj.blk_list;
info->msg_q.peak_num = queue->msg_q.peak_num;
info->msg_q.cur_num = queue->msg_q.cur_num;
info->msg_q.queue_start = queue->msg_q.queue_start;
info->msg_q.size = queue->msg_q.size;
info->pend_entry = blk_list_head->next;
RHINO_CPU_INTRPT_ENABLE();
return RHINO_SUCCESS;
}
#endif

View File

@@ -0,0 +1,367 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
kstat_t ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len, size_t type,
size_t block_size)
{
p_ringbuf->type = type;
p_ringbuf->buf = buf;
p_ringbuf->end = (uint8_t *)buf + len;
p_ringbuf->blk_size = block_size;
ringbuf_reset(p_ringbuf);
return RHINO_SUCCESS;
}
static size_t ringbuf_headlen_compress(size_t head_len, uint8_t *cmp_buf)
{
size_t len_bytes = 0;
uint8_t *p_len = NULL;
uint32_t be_len = 0;
be_len = krhino_ntohl(head_len);
p_len = (uint8_t *)&be_len;
len_bytes = COMPRESS_LEN(head_len);
if (len_bytes == 1) {
cmp_buf[0] = RINGBUF_LEN_1BYTE_MAXVALUE & p_len[3];
} else if (len_bytes == 2) {
cmp_buf[0] = RINGBUF_LEN_VLE_2BYTES | p_len[2];
cmp_buf[1] = p_len[3];
} else if (len_bytes == 3) {
cmp_buf[0] = RINGBUF_LEN_VLE_3BYTES | p_len[1];
cmp_buf[1] = p_len[2];
cmp_buf[2] = p_len[3];
}
return len_bytes;
}
static size_t ringbuf_headlen_decompress(size_t buf_len, uint8_t *cmp_buf)
{
size_t data_len = 0;
uint32_t be_len = 0;
uint8_t *len_buf = (uint8_t *)&be_len;
memcpy(&len_buf[sizeof(uint32_t) - buf_len], cmp_buf, buf_len);
if (buf_len > 1) {
len_buf[sizeof(uint32_t) - buf_len] &= RINGBUF_LEN_MASK_CLEAN_TWOBIT;
}
data_len = krhino_ntohl(be_len);
return data_len;
}
kstat_t ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len)
{
size_t len_bytes = 0;
size_t split_len = 0;
uint8_t c_len[RINGBUF_LEN_MAX_SIZE] = {0};
if (ringbuf_is_full(p_ringbuf)) {
return RHINO_RINGBUF_FULL;
}
if (p_ringbuf->type == RINGBUF_TYPE_FIX) {
if (p_ringbuf->tail == p_ringbuf->end) {
p_ringbuf->tail = p_ringbuf->buf;
}
memcpy(p_ringbuf->tail, data, p_ringbuf->blk_size);
p_ringbuf->tail += p_ringbuf->blk_size;
p_ringbuf->freesize -= p_ringbuf->blk_size;
} else {
len_bytes = ringbuf_headlen_compress(len, c_len);
if (len_bytes == 0 || len_bytes > RINGBUF_LEN_MAX_SIZE ) {
return RHINO_INV_PARAM;
}
/* for dynamic length ringbuf */
if (p_ringbuf->freesize < len_bytes + len ) {
return RHINO_RINGBUF_FULL;
}
if (p_ringbuf->tail == p_ringbuf->end) {
p_ringbuf->tail = p_ringbuf->buf;
}
/* copy length data to buffer */
if (p_ringbuf->tail >= p_ringbuf->head &&
(split_len = p_ringbuf->end - p_ringbuf->tail) < len_bytes && split_len > 0) {
memcpy(p_ringbuf->tail, &c_len[0], split_len);
len_bytes -= split_len;
p_ringbuf->tail = p_ringbuf->buf;
p_ringbuf->freesize -= split_len;
} else {
split_len = 0;
}
if (len_bytes > 0) {
memcpy(p_ringbuf->tail, &c_len[split_len], len_bytes);
p_ringbuf->freesize -= len_bytes;
p_ringbuf->tail += len_bytes;
}
/* copy data to ringbuf, if break by buffer end, split data and copy to buffer head*/
split_len = 0;
if (p_ringbuf->tail == p_ringbuf->end) {
p_ringbuf->tail = p_ringbuf->buf;
}
if (p_ringbuf->tail >= p_ringbuf->head &&
((split_len = p_ringbuf->end - p_ringbuf->tail) < len) &&
split_len > 0) {
memcpy(p_ringbuf->tail, data, split_len);
data = (uint8_t *)data + split_len;
len -= split_len;
p_ringbuf->tail = p_ringbuf->buf;
p_ringbuf->freesize -= split_len;
}
memcpy(p_ringbuf->tail, data, len);
p_ringbuf->tail += len;
p_ringbuf->freesize -= len;
}
return RHINO_SUCCESS;
}
kstat_t ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen)
{
size_t split_len = 0;
uint8_t *data = pdata;
size_t len = 0;
uint8_t c_len[RINGBUF_LEN_MAX_SIZE] = {0};
size_t len_bytes = 0;
if (ringbuf_is_empty(p_ringbuf)) {
return RHINO_RINGBUF_EMPTY;
}
if (p_ringbuf->type == RINGBUF_TYPE_FIX) {
if (p_ringbuf->head == p_ringbuf->end) {
p_ringbuf->head = p_ringbuf->buf;
}
memcpy(pdata, p_ringbuf->head, p_ringbuf->blk_size);
p_ringbuf->head += p_ringbuf->blk_size;
p_ringbuf->freesize += p_ringbuf->blk_size;
if (plen != NULL) {
*plen = p_ringbuf->blk_size;
}
return RHINO_SUCCESS;
} else {
if (p_ringbuf->head == p_ringbuf->end) {
p_ringbuf->head = p_ringbuf->buf;
}
/*decode length */
if ((*p_ringbuf->head & RINGBUF_LEN_MASK_ONEBIT) == 0 ) {
/*length use one byte*/
len_bytes = 1;
} else if ((*p_ringbuf->head & RINGBUF_LEN_MASK_TWOBIT) ==
RINGBUF_LEN_VLE_2BYTES) {
/*length use 2 bytes*/
len_bytes = 2;
} else if ((*p_ringbuf->head & RINGBUF_LEN_MASK_TWOBIT) ==
RINGBUF_LEN_VLE_3BYTES) {
/*length use 3 bytes*/
len_bytes = 3;
} else {
return RHINO_INV_PARAM;
}
if (((split_len = p_ringbuf->end - p_ringbuf->head) < len_bytes) &&
split_len > 0) {
memcpy(&c_len[0], p_ringbuf->head, split_len);
p_ringbuf->head = p_ringbuf->buf;
p_ringbuf->freesize += split_len;
} else {
split_len = 0;
}
if (len_bytes - split_len > 0) {
memcpy(&c_len[split_len], p_ringbuf->head, (len_bytes - split_len));
p_ringbuf->head += (len_bytes - split_len);
p_ringbuf->freesize += (len_bytes - split_len);
}
*plen = len = ringbuf_headlen_decompress(len_bytes, c_len);
if (p_ringbuf->head == p_ringbuf->end) {
p_ringbuf->head = p_ringbuf->buf;
}
if (p_ringbuf->head > p_ringbuf->tail &&
(split_len = p_ringbuf->end - p_ringbuf->head) < len) {
memcpy(pdata, p_ringbuf->head, split_len);
data = (uint8_t *)pdata + split_len;
len -= split_len;
p_ringbuf->head = p_ringbuf->buf;
p_ringbuf->freesize += split_len;
}
memcpy(data, p_ringbuf->head, len);
p_ringbuf->head += len;
p_ringbuf->freesize += len;
return RHINO_SUCCESS;
}
}
uint8_t ringbuf_is_full(k_ringbuf_t *p_ringbuf)
{
if (p_ringbuf->type == RINGBUF_TYPE_DYN && p_ringbuf->freesize < 2) {
return 1;
}
if (p_ringbuf->type == RINGBUF_TYPE_FIX &&
p_ringbuf->freesize < p_ringbuf->blk_size) {
return 1;
}
return false;
}
uint8_t ringbuf_is_empty(k_ringbuf_t *p_ringbuf)
{
if (p_ringbuf->freesize == (size_t)(p_ringbuf->end - p_ringbuf->buf)) {
return true;
}
return false;
}
/*external api*/
kstat_t ringbuf_reset(k_ringbuf_t *p_ringbuf)
{
p_ringbuf->head = p_ringbuf->buf;
p_ringbuf->tail = p_ringbuf->buf;
p_ringbuf->freesize = p_ringbuf->end - p_ringbuf->buf;
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_RINGBUF_VENDOR > 0)
kstat_t krhino_ringbuf_reset(k_ringbuf_t *p_ringbuf)
{
CPSR_ALLOC();
kstat_t err;
NULL_PARA_CHK(p_ringbuf);
RHINO_CRITICAL_ENTER();
err = ringbuf_reset(p_ringbuf);
RHINO_CRITICAL_EXIT();
return err;
}
kstat_t krhino_ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len,
size_t type, size_t block_size)
{
CPSR_ALLOC();
kstat_t err;
NULL_PARA_CHK(p_ringbuf);
NULL_PARA_CHK(buf);
if (len == 0 || (type != RINGBUF_TYPE_DYN && type != RINGBUF_TYPE_FIX)) {
return RHINO_INV_PARAM;
}
if (type == RINGBUF_TYPE_FIX) {
if (len == 0 || block_size == 0 || len % block_size) {
return RHINO_INV_PARAM;
}
}
RHINO_CRITICAL_ENTER();
err = ringbuf_init(p_ringbuf, buf, len, type, block_size);
RHINO_CRITICAL_EXIT();
return err;
}
kstat_t krhino_ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len)
{
CPSR_ALLOC();
kstat_t err;
NULL_PARA_CHK(p_ringbuf);
NULL_PARA_CHK(data);
if (len <= 0 || len > RINGBUF_LEN_3BYTES_MAXVALUE ||
(p_ringbuf->type == RINGBUF_TYPE_FIX && len != p_ringbuf->blk_size) ) {
return RHINO_INV_PARAM;
}
RHINO_CRITICAL_ENTER();
err = ringbuf_push(p_ringbuf, data, len);
RHINO_CRITICAL_EXIT();
return err;
}
kstat_t krhino_ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen)
{
CPSR_ALLOC();
kstat_t err;
NULL_PARA_CHK(p_ringbuf);
NULL_PARA_CHK(pdata);
if (p_ringbuf->type == RINGBUF_TYPE_DYN && plen == NULL) {
return RHINO_INV_PARAM;
}
RHINO_CRITICAL_ENTER();
err = ringbuf_pop(p_ringbuf, pdata, plen);
RHINO_CRITICAL_EXIT();
return err;
}
uint8_t krhino_ringbuf_is_empty(k_ringbuf_t *p_ringbuf)
{
CPSR_ALLOC();
uint8_t empty;
NULL_PARA_CHK(p_ringbuf);
RHINO_CRITICAL_ENTER();
empty = ringbuf_is_empty(p_ringbuf);
RHINO_CRITICAL_EXIT();
return empty;
}
uint8_t krhino_ringbuf_is_full(k_ringbuf_t *p_ringbuf)
{
CPSR_ALLOC();
uint8_t full;
NULL_PARA_CHK(p_ringbuf);
RHINO_CRITICAL_ENTER();
full = ringbuf_is_full(p_ringbuf);
RHINO_CRITICAL_EXIT();
return full;
}
#endif

View File

@@ -0,0 +1,490 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include <csi_core.h>
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
static void sched_disable_measure_start(void)
{
/* start measure system lock time */
if (g_sched_lock[cpu_cur_get()] == 0u) {
g_sched_disable_time_start = HR_COUNT_GET();
}
}
static void sched_disable_measure_stop(void)
{
hr_timer_t diff;
/* stop measure system lock time, g_sched_lock is always zero here */
diff = HR_COUNT_GET() - g_sched_disable_time_start;
if (g_sched_disable_max_time < diff) {
g_sched_disable_max_time = diff;
}
if (g_cur_sched_disable_max_time < diff) {
g_cur_sched_disable_max_time = diff;
}
}
#endif
kstat_t krhino_sched_disable(void)
{
CPSR_ALLOC();
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (g_sched_lock[cpu_cur_get()] >= SCHED_MAX_LOCK_COUNT) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_LOCK_COUNT_OVF;
}
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
sched_disable_measure_start();
#endif
g_sched_lock[cpu_cur_get()]++;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
kstat_t krhino_sched_enable(void)
{
CPSR_ALLOC();
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (g_sched_lock[cpu_cur_get()] == 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_ALREADY_ENABLED;
}
g_sched_lock[cpu_cur_get()]--;
if (g_sched_lock[cpu_cur_get()] > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
sched_disable_measure_stop();
#endif
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_CPU_NUM > 1)
void core_sched(void)
{
uint8_t cur_cpu_num;
cur_cpu_num = cpu_cur_get();
if (g_intrpt_nested_level[cur_cpu_num] > 0u) {
return;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
return;
}
preferred_cpu_ready_task_get(&g_ready_queue, cur_cpu_num);
/* if preferred task is currently task, then no need to do switch and just return */
if (g_preferred_ready_task[cur_cpu_num] == g_active_task[cur_cpu_num]) {
return;
}
TRACE_TASK_SWITCH(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_task_switch_hook(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#endif
g_active_task[cur_cpu_num]->cur_exc = 0;
cpu_task_switch();
}
#else
void core_sched(void)
{
CPSR_ALLOC();
uint8_t cur_cpu_num;
RHINO_CPU_INTRPT_DISABLE();
cur_cpu_num = cpu_cur_get();
if (g_intrpt_nested_level[cur_cpu_num] > 0u) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
preferred_cpu_ready_task_get(&g_ready_queue, cur_cpu_num);
/* if preferred task is currently task, then no need to do switch and just return */
if (g_preferred_ready_task[cur_cpu_num] == g_active_task[cur_cpu_num]) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
TRACE_TASK_SWITCH(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_task_switch_hook(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#endif
cpu_task_switch();
RHINO_CPU_INTRPT_ENABLE();
}
#endif
__init void runqueue_init(runqueue_t *rq)
{
uint8_t prio;
rq->highest_pri = RHINO_CONFIG_PRI_MAX;
for (prio = 0; prio < RHINO_CONFIG_PRI_MAX; prio++) {
rq->cur_list_item[prio] = NULL;
}
}
RHINO_INLINE void ready_list_init(runqueue_t *rq, ktask_t *task)
{
rq->cur_list_item[task->prio] = &task->task_list;
klist_init(rq->cur_list_item[task->prio]);
krhino_bitmap_set(rq->task_bit_map, task->prio);
if ((task->prio) < (rq->highest_pri)) {
rq->highest_pri = task->prio;
}
}
RHINO_INLINE uint8_t is_ready_list_empty(uint8_t prio)
{
return (g_ready_queue.cur_list_item[prio] == NULL);
}
RHINO_INLINE void _ready_list_add_tail(runqueue_t *rq, ktask_t *task)
{
if (is_ready_list_empty(task->prio)) {
ready_list_init(rq, task);
return;
}
klist_insert(rq->cur_list_item[task->prio], &task->task_list);
}
RHINO_INLINE void _ready_list_add_head(runqueue_t *rq, ktask_t *task)
{
if (is_ready_list_empty(task->prio)) {
ready_list_init(rq, task);
return;
}
klist_insert(rq->cur_list_item[task->prio], &task->task_list);
rq->cur_list_item[task->prio] = &task->task_list;
}
#if (RHINO_CONFIG_CPU_NUM > 1)
static void task_sched_to_cpu(runqueue_t *rq, ktask_t *task, uint8_t cur_cpu_num)
{
uint8_t i;
uint8_t low_pri;
(void)rq;
if (g_sys_stat == RHINO_RUNNING) {
if (task->cpu_binded == 1) {
if (task->cpu_num != cur_cpu_num) {
if (task->prio <= g_active_task[task->cpu_num]->prio) {
cpu_signal(task->cpu_num);
}
}
} else {
/* find the lowest pri */
low_pri = g_active_task[0]->prio;
for (i = 0; i < RHINO_CONFIG_CPU_NUM - 1; i++) {
if (low_pri < g_active_task[i + 1]->prio) {
low_pri = g_active_task[i + 1]->prio;
}
}
/* which cpu run the lowest pri, just notify it */
for (i = 0; i < RHINO_CONFIG_CPU_NUM; i++) {
if (low_pri == g_active_task[i]->prio) {
if (i != cur_cpu_num) {
cpu_signal(i);
}
return;
}
}
}
}
}
void ready_list_add_head(runqueue_t *rq, ktask_t *task)
{
_ready_list_add_head(rq, task);
task_sched_to_cpu(rq, task, cpu_cur_get());
}
void ready_list_add_tail(runqueue_t *rq, ktask_t *task)
{
_ready_list_add_tail(rq, task);
task_sched_to_cpu(rq, task, cpu_cur_get());
}
#else
void ready_list_add_head(runqueue_t *rq, ktask_t *task)
{
_ready_list_add_head(rq, task);
}
void ready_list_add_tail(runqueue_t *rq, ktask_t *task)
{
_ready_list_add_tail(rq, task);
}
#endif
void ready_list_add(runqueue_t *rq, ktask_t *task)
{
/* if task prio is equal current task prio then add to the end */
if (task->prio == g_active_task[cpu_cur_get()]->prio) {
ready_list_add_tail(rq, task);
} else {
ready_list_add_head(rq, task);
}
}
void ready_list_rm(runqueue_t *rq, ktask_t *task)
{
int32_t i;
uint8_t pri = task->prio;
/* if the ready list is not only one, we do not need to update the highest prio */
if ((rq->cur_list_item[pri]) != (rq->cur_list_item[pri]->next)) {
if (rq->cur_list_item[pri] == &task->task_list) {
rq->cur_list_item[pri] = rq->cur_list_item[pri]->next;
}
klist_rm(&task->task_list);
return;
}
/* only one item,just set cur item ptr to NULL */
rq->cur_list_item[pri] = NULL;
krhino_bitmap_clear(rq->task_bit_map, pri);
/* if task prio not equal to the highest prio, then we do not need to update the highest prio */
/* this condition happens when a current high prio task to suspend a low priotity task */
if (pri != rq->highest_pri) {
return;
}
/* find the highest ready task */
i = krhino_find_first_bit(rq->task_bit_map);
/* update the next highest prio task */
if (i >= 0) {
rq->highest_pri = i;
} else {
k_err_proc(RHINO_SYS_FATAL_ERR);
}
}
void ready_list_head_to_tail(runqueue_t *rq, ktask_t *task)
{
rq->cur_list_item[task->prio] = rq->cur_list_item[task->prio]->next;
}
#if (RHINO_CONFIG_CPU_NUM > 1)
void preferred_cpu_ready_task_get(runqueue_t *rq, uint8_t cpu_num)
{
klist_t *iter;
ktask_t *task;
uint32_t task_bit_map[NUM_WORDS];
klist_t *node;
uint8_t flag;
uint8_t highest_pri = rq->highest_pri;
node = rq->cur_list_item[highest_pri];
iter = node;
memcpy(task_bit_map, rq->task_bit_map, NUM_WORDS * sizeof(uint32_t));
while (1) {
task = krhino_list_entry(iter, ktask_t, task_list);
if (g_active_task[cpu_num] == task) {
break;
}
flag = ((task->cur_exc == 0) && (task->cpu_binded == 0))
|| ((task->cur_exc == 0) && (task->cpu_binded == 1) && (task->cpu_num == cpu_num));
if (flag > 0) {
task->cpu_num = cpu_num;
task->cur_exc = 1;
g_preferred_ready_task[cpu_num] = task;
break;
}
if (iter->next == rq->cur_list_item[highest_pri]) {
task_bit_map[highest_pri >> 5] &= ~(1u << (31u - (highest_pri & 31u)));
highest_pri = krhino_find_first_bit(task_bit_map);
iter = rq->cur_list_item[highest_pri];
} else {
iter = iter->next;
}
}
}
#else
void preferred_cpu_ready_task_get(runqueue_t *rq, uint8_t cpu_num)
{
klist_t *node = rq->cur_list_item[rq->highest_pri];
/* get the highest prio task object */
g_preferred_ready_task[cpu_num] = krhino_list_entry(node, ktask_t, task_list);
}
#endif
#if (RHINO_CONFIG_SCHED_RR > 0)
#if (RHINO_CONFIG_CPU_NUM > 1)
static void _time_slice_update(ktask_t *task, uint8_t i)
{
klist_t *head;
head = g_ready_queue.cur_list_item[task->prio];
task->runtime++;
/* if ready list is empty then just return because nothing is to be caculated */
if (is_ready_list_empty(task->prio)) {
return;
}
if (task->sched_policy == KSCHED_FIFO) {
return;
}
/* there is only one task on this ready list, so do not need to caculate time slice */
/* idle task must satisfy this condition */
if (head->next == head) {
return;
}
if (task->time_slice > 0u) {
task->time_slice--;
}
/* if current active task has time_slice, just return */
if (task->time_slice > 0u) {
return;
}
/* move current active task to the end of ready list for the same prio */
ready_list_head_to_tail(&g_ready_queue, task);
/* restore the task time slice */
task->time_slice = task->time_total;
if (i != cpu_cur_get()) {
cpu_signal(i);
}
}
void time_slice_update(void)
{
CPSR_ALLOC();
uint8_t i;
RHINO_CRITICAL_ENTER();
for (i = 0; i < RHINO_CONFIG_CPU_NUM; i++) {
_time_slice_update(g_active_task[i], i);
}
RHINO_CRITICAL_EXIT();
}
#else
void time_slice_update(void)
{
CPSR_ALLOC();
ktask_t *task;
klist_t *head;
uint8_t task_pri;
RHINO_CRITICAL_ENTER();
task_pri = g_active_task[cpu_cur_get()]->prio;
head = g_ready_queue.cur_list_item[task_pri];
/* if ready list is empty then just return because nothing is to be caculated */
if (is_ready_list_empty(task_pri)) {
RHINO_CRITICAL_EXIT();
return;
}
/* Always look at the first task on the ready list */
task = krhino_list_entry(head, ktask_t, task_list);
task->runtime++;
if (task->sched_policy == KSCHED_FIFO) {
RHINO_CRITICAL_EXIT();
return;
}
/* there is only one task on this ready list, so do not need to caculate time slice */
/* idle task must satisfy this condition */
if (head->next == head) {
RHINO_CRITICAL_EXIT();
return;
}
if (task->time_slice > 0u) {
task->time_slice--;
}
/* if current active task has time_slice, just return */
if (task->time_slice > 0u) {
RHINO_CRITICAL_EXIT();
return;
}
/* move current active task to the end of ready list for the same prio */
ready_list_head_to_tail(&g_ready_queue, task);
/* restore the task time slice */
task->time_slice = task->time_total;
RHINO_CRITICAL_EXIT();
}
#endif
#endif

View File

@@ -0,0 +1,345 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_SEM > 0)
static kstat_t sem_create(ksem_t *sem, const name_t *name, sem_count_t count,
uint8_t mm_alloc_flag)
{
CPSR_ALLOC();
NULL_PARA_CHK(sem);
NULL_PARA_CHK(name);
/* init the list */
klist_init(&sem->blk_obj.blk_list);
/* init resource */
sem->count = count;
sem->peak_count = count;
sem->blk_obj.name = name;
sem->blk_obj.blk_policy = BLK_POLICY_PRI;
sem->mm_alloc_flag = mm_alloc_flag;
RHINO_CRITICAL_ENTER();
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_insert(&(g_kobj_list.sem_head), &sem->sem_item);
#endif
RHINO_CRITICAL_EXIT();
sem->blk_obj.obj_type = RHINO_SEM_OBJ_TYPE;
TRACE_SEM_CREATE(krhino_cur_task_get(), sem);
return RHINO_SUCCESS;
}
kstat_t krhino_sem_create(ksem_t *sem, const name_t *name, sem_count_t count)
{
return sem_create(sem, name, count, K_OBJ_STATIC_ALLOC);
}
kstat_t krhino_sem_del(ksem_t *sem)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(sem);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (sem->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &sem->blk_obj.blk_list;
sem->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&sem->sem_item);
#endif
TRACE_SEM_DEL(g_active_task[cpu_cur_get()], sem);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_sem_dyn_create(ksem_t **sem, const name_t *name,
sem_count_t count)
{
kstat_t stat;
ksem_t *sem_obj;
NULL_PARA_CHK(sem);
sem_obj = krhino_mm_alloc(sizeof(ksem_t), __builtin_return_address(0));
if (sem_obj == NULL) {
return RHINO_NO_MEM;
}
stat = sem_create(sem_obj, name, count, K_OBJ_DYN_ALLOC);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(sem_obj);
return stat;
}
*sem = sem_obj;
return stat;
}
kstat_t krhino_sem_dyn_del(ksem_t *sem)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(sem);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (sem->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &sem->blk_obj.blk_list;
sem->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&sem->sem_item);
#endif
TRACE_SEM_DEL(g_active_task[cpu_cur_get()], sem);
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(sem);
return RHINO_SUCCESS;
}
#endif
static kstat_t sem_give(ksem_t *sem, uint8_t opt_wake_all)
{
CPSR_ALLOC();
uint8_t cur_cpu_num;
klist_t *blk_list_head;
/* this is only needed when system zero interrupt feature is enabled */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
RHINO_CRITICAL_ENTER();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
(void)cur_cpu_num;
blk_list_head = &sem->blk_obj.blk_list;
if (is_klist_empty(blk_list_head)) {
if (sem->count == (sem_count_t)-1) {
TRACE_SEM_OVERFLOW(g_active_task[cur_cpu_num], sem);
RHINO_CRITICAL_EXIT();
return RHINO_SEM_OVF;
}
/* increase resource */
sem->count++;
if (sem->count > sem->peak_count) {
sem->peak_count = sem->count;
}
TRACE_SEM_CNT_INCREASE(g_active_task[cur_cpu_num], sem);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* wake all the task blocked on this semaphore */
if (opt_wake_all) {
while (!is_klist_empty(blk_list_head)) {
TRACE_SEM_TASK_WAKE(g_active_task[cur_cpu_num], krhino_list_entry(blk_list_head->next,
ktask_t, task_list),
sem, opt_wake_all);
pend_task_wakeup(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
} else {
TRACE_SEM_TASK_WAKE(g_active_task[cur_cpu_num], krhino_list_entry(blk_list_head->next,
ktask_t, task_list),
sem, opt_wake_all);
/* wake up the highest prio task block on the semaphore */
pend_task_wakeup(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
kstat_t krhino_sem_give(ksem_t *sem)
{
NULL_PARA_CHK(sem);
return sem_give(sem, WAKE_ONE_SEM);
}
kstat_t krhino_sem_give_all(ksem_t *sem)
{
NULL_PARA_CHK(sem);
return sem_give(sem, WAKE_ALL_SEM);
}
kstat_t krhino_sem_take(ksem_t *sem, tick_t ticks)
{
CPSR_ALLOC();
uint8_t cur_cpu_num;
kstat_t stat;
NULL_PARA_CHK(sem);
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
if (sem->count > 0u) {
sem->count--;
TRACE_SEM_GET_SUCCESS(g_active_task[cur_cpu_num], sem);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* can't get semphore, and return immediately if wait_option is RHINO_NO_WAIT */
if (ticks == RHINO_NO_WAIT) {
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
pend_to_blk_obj((blk_obj_t *)sem, g_active_task[cur_cpu_num], ticks, psr);
TRACE_SEM_GET_BLK(g_active_task[cur_cpu_num], sem, ticks);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
stat = pend_state_end_proc(g_active_task[cpu_cur_get()]);
RHINO_CPU_INTRPT_ENABLE();
return stat;
}
kstat_t krhino_sem_count_set(ksem_t *sem, sem_count_t sem_count)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(sem);
blk_list_head = &sem->blk_obj.blk_list;
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
/* set new count */
if (sem->count > 0u) {
sem->count = sem_count;
} else {
if (is_klist_empty(blk_list_head)) {
sem->count = sem_count;
} else {
RHINO_CRITICAL_EXIT();
return RHINO_SEM_TASK_WAITING;
}
}
/* update sem peak count if need */
if (sem->count > sem->peak_count) {
sem->peak_count = sem->count;
}
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
kstat_t krhino_sem_count_get(ksem_t *sem, sem_count_t *count)
{
NULL_PARA_CHK(sem);
NULL_PARA_CHK(count);
*count = sem->count;
return RHINO_SUCCESS;
}
#endif /* RHINO_CONFIG_SEM */

View File

@@ -0,0 +1,231 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include <csi_core.h>
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
__init void kobj_list_init(void)
{
klist_init(&(g_kobj_list.task_head));
klist_init(&(g_kobj_list.mutex_head));
#if (RHINO_CONFIG_MM_BLK > 0)
klist_init(&(g_kobj_list.mblkpool_head));
#endif
#if (RHINO_CONFIG_SEM > 0)
klist_init(&(g_kobj_list.sem_head));
#endif
#if (RHINO_CONFIG_QUEUE > 0)
klist_init(&(g_kobj_list.queue_head));
#endif
#if (RHINO_CONFIG_BUF_QUEUE > 0)
klist_init(&(g_kobj_list.buf_queue_head));
#endif
#if (RHINO_CONFIG_EVENT_FLAG > 0)
klist_init(&(g_kobj_list.event_head));
#endif
}
#endif
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
#if (RHINO_CONFIG_CPU_STACK_DOWN > 0)
void krhino_stack_ovf_check(void)
{
cpu_stack_t *stack_start;
stack_start = g_active_task[cpu_cur_get()]->task_stack_base;
if (*stack_start != RHINO_TASK_STACK_OVF_MAGIC) {
k_err_proc(RHINO_TASK_STACK_OVF);
}
if ((cpu_stack_t *)(g_active_task[cpu_cur_get()]->task_stack) < stack_start) {
k_err_proc(RHINO_TASK_STACK_OVF);
}
}
#else
void krhino_stack_ovf_check(void)
{
cpu_stack_t *stack_start;
cpu_stack_t *stack_end;
stack_start = g_active_task[cpu_cur_get()]->task_stack_base;
stack_end = stack_start + g_active_task[cpu_cur_get()]->stack_size;
if (*(stack_end - 1) != RHINO_TASK_STACK_OVF_MAGIC) {
k_err_proc(RHINO_TASK_STACK_OVF);
}
if ((cpu_stack_t *)(g_active_task[cpu_cur_get()]->task_stack) > stack_end) {
k_err_proc(RHINO_TASK_STACK_OVF);
}
}
#endif
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
void krhino_task_sched_stats_reset(void)
{
lr_timer_t cur_time;
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
g_cur_intrpt_disable_max_time = 0;
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
g_cur_sched_disable_max_time = 0;
#endif
/* system first task starting time should be measured otherwise not correct */
cur_time = (lr_timer_t)LR_COUNT_GET();
g_preferred_ready_task->task_time_start = cur_time;
}
void krhino_task_sched_stats_get(void)
{
lr_timer_t cur_time;
lr_timer_t exec_time;
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
hr_timer_t intrpt_disable_time;
if (g_cur_intrpt_disable_max_time > g_sys_measure_waste) {
intrpt_disable_time = g_cur_intrpt_disable_max_time - g_sys_measure_waste;
} else {
intrpt_disable_time = 0;
}
if (g_active_task[cpu_cur_get()]->task_intrpt_disable_time_max < intrpt_disable_time) {
g_active_task[cpu_cur_get()]->task_intrpt_disable_time_max = intrpt_disable_time;
}
g_cur_intrpt_disable_max_time = 0;
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
if (g_active_task[cpu_cur_get()]->task_sched_disable_time_max < g_cur_sched_disable_max_time) {
g_active_task[cpu_cur_get()]->task_sched_disable_time_max = g_cur_sched_disable_max_time;
}
g_cur_sched_disable_max_time = 0;
#endif
/* Keep track of new task and total system context switch times */
g_preferred_ready_task[cpu_cur_get()]->task_ctx_switch_times++;
g_sys_ctx_switch_times++;
cur_time = (lr_timer_t)LR_COUNT_GET();
exec_time = cur_time - g_active_task[cpu_cur_get()]->task_time_start;
g_active_task[cpu_cur_get()]->task_time_total_run += (sys_time_t)exec_time;
g_preferred_ready_task[cpu_cur_get()]->task_time_start = cur_time;
}
#endif /* RHINO_CONFIG_TASK_SCHED_STATS */
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
void intrpt_disable_measure_start(void)
{
g_intrpt_disable_times++;
/* start measure interrupt disable time */
if (g_intrpt_disable_times == 1u) {
g_intrpt_disable_time_start = HR_COUNT_GET();
}
}
void intrpt_disable_measure_stop(void)
{
hr_timer_t diff;
g_intrpt_disable_times--;
if (g_intrpt_disable_times == 0u) {
diff = HR_COUNT_GET() - g_intrpt_disable_time_start;
if (g_intrpt_disable_max_time < diff) {
g_intrpt_disable_max_time = diff;
}
if (g_cur_intrpt_disable_max_time < diff) {
g_cur_intrpt_disable_max_time = diff;
}
}
}
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
void krhino_overhead_measure(void)
{
hr_timer_t diff;
hr_timer_t m1;
hr_timer_t m2;
m1 = HR_COUNT_GET();
HR_COUNT_GET();
HR_COUNT_GET();
m2 = HR_COUNT_GET();
diff = m2 - m1;
/* measure time overhead */
g_sys_measure_waste = diff;
}
#endif
/*it should be called in cpu_stats task*/
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
static void cpu_usage_task_entry(void *arg)
{
idle_count_t idle_count;
(void)arg;
while (1) {
idle_count_set(0u);
krhino_task_sleep(RHINO_CONFIG_TICKS_PER_SECOND / 2);
idle_count = idle_count_get();
if (idle_count > g_idle_count_max) {
g_idle_count_max = idle_count;
}
if (idle_count < g_idle_count_max) {
/* use 64bit for cpu_task_idle_count to avoid overflow quickly */
g_cpu_usage = 10000 - (uint32_t)((idle_count * 10000) / g_idle_count_max);
}
else {
g_cpu_usage = 10000;
}
}
}
__init void cpu_usage_stats_start(void)
{
/* create a statistic task to calculate cpu usage */
krhino_task_create(&g_cpu_usage_task, "cpu_stats", 0,
RHINO_CONFIG_CPU_USAGE_TASK_PRI,
0, g_cpu_task_stack, RHINO_CONFIG_CPU_USAGE_TASK_STACK, cpu_usage_task_entry,
1);
}
uint32_t krhino_get_cpu_usage(void)
{
return g_cpu_usage;
}
#endif /* RHINO_CONFIG_CPU_USAGE_STATS */

View File

@@ -0,0 +1,249 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include <csi_core.h>
__init RHINO_INLINE void rhino_stack_check_init(void)
{
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
#if (RHINO_CONFIG_CPU_STACK_DOWN > 0)
*g_intrpt_stack_bottom = RHINO_INTRPT_STACK_OVF_MAGIC;
#else
*g_intrpt_stack_top = RHINO_INTRPT_STACK_OVF_MAGIC;
#endif
#endif /* RHINO_CONFIG_INTRPT_STACK_OVF_CHECK */
#if (RHINO_CONFIG_STACK_OVF_CHECK_HW != 0)
cpu_intrpt_stack_protect();
#endif
}
__init kstat_t krhino_init(void)
{
g_sys_stat = RHINO_STOPPED;
krhino_spin_init(&g_sys_lock);
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_init_hook();
#endif
runqueue_init(&g_ready_queue);
tick_list_init();
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
kobj_list_init();
#endif
#if (RHINO_CONFIG_MM_TLF > 0)
//k_mm_init();
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
klist_init(&g_res_list);
krhino_sem_create(&g_res_sem, "res_sem", 0);
//dyn_mem_proc_task_start(); //idle task do it.
#endif
#if (RHINO_CONFIG_CPU_NUM > 1)
for (uint8_t i = 0; i < RHINO_CONFIG_CPU_NUM; i++) {
krhino_task_cpu_create(&g_idle_task[i], "idle_task", NULL, RHINO_IDLE_PRI, 0,
&g_idle_task_stack[i][0], RHINO_CONFIG_IDLE_TASK_STACK_SIZE,
idle_task, i, 1u);
}
#else
krhino_task_create(&g_idle_task[0], "idle_task", NULL, RHINO_IDLE_PRI, 0,
&g_idle_task_stack[0][0], RHINO_CONFIG_IDLE_TASK_STACK_SIZE,
idle_task, 1u);
#endif
#if (RHINO_CONFIG_WORKQUEUE > 0)
workqueue_init();
#endif
#if (RHINO_CONFIG_TIMER > 0)
ktimer_init();
#endif
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
cpu_usage_stats_start();
#endif
#if (RHINO_CONFIG_ISR_TASK > 0)
kisr_init();
#endif
rhino_stack_check_init();
return RHINO_SUCCESS;
}
__init kstat_t krhino_start(void)
{
if (g_sys_stat == RHINO_STOPPED) {
#if (RHINO_CONFIG_CPU_NUM > 1)
for (uint8_t i = 0; i < RHINO_CONFIG_CPU_NUM; i++) {
preferred_cpu_ready_task_get(&g_ready_queue, i);
g_active_task[i] = g_preferred_ready_task[i];
g_active_task[i]->cur_exc = 1;
}
#else
preferred_cpu_ready_task_get(&g_ready_queue, 0);
g_active_task[0] = g_preferred_ready_task[0];
#endif
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_start_hook();
#endif
g_sys_stat = RHINO_RUNNING;
cpu_first_task_start();
/* should not be here */
return RHINO_SYS_FATAL_ERR;
}
return RHINO_RUNNING;
}
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
#if (RHINO_CONFIG_CPU_STACK_DOWN > 0)
void krhino_intrpt_stack_ovf_check(void)
{
if (*g_intrpt_stack_bottom != RHINO_INTRPT_STACK_OVF_MAGIC) {
k_err_proc(RHINO_INTRPT_STACK_OVF);
}
}
#else
void krhino_intrpt_stack_ovf_check(void)
{
if (*g_intrpt_stack_top != RHINO_INTRPT_STACK_OVF_MAGIC) {
k_err_proc(RHINO_INTRPT_STACK_OVF);
}
}
#endif
#endif /* RHINO_CONFIG_INTRPT_STACK_OVF_CHECK */
kstat_t krhino_intrpt_enter(void)
{
CPSR_ALLOC();
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
krhino_intrpt_stack_ovf_check();
#endif
RHINO_CPU_INTRPT_DISABLE();
/* RHINO_CONFIG_CPU_PWR_MGMT */
#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
cpu_pwr_up();
#endif
if (g_intrpt_nested_level[cpu_cur_get()] >= RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL) {
k_err_proc(RHINO_INTRPT_NESTED_LEVEL_OVERFLOW);
RHINO_CPU_INTRPT_ENABLE();
return RHINO_INTRPT_NESTED_LEVEL_OVERFLOW;
}
g_intrpt_nested_level[cpu_cur_get()]++;
RHINO_CPU_INTRPT_ENABLE();
return RHINO_SUCCESS;
}
void krhino_intrpt_exit(void)
{
CPSR_ALLOC();
uint8_t cur_cpu_num;
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
krhino_intrpt_stack_ovf_check();
#endif
RHINO_CPU_INTRPT_DISABLE();
cur_cpu_num = cpu_cur_get();
if (g_intrpt_nested_level[cur_cpu_num] == 0u) {
RHINO_CPU_INTRPT_ENABLE();
k_err_proc(RHINO_INV_INTRPT_NESTED_LEVEL);
}
g_intrpt_nested_level[cur_cpu_num]--;
if (g_intrpt_nested_level[cur_cpu_num] > 0u) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
preferred_cpu_ready_task_get(&g_ready_queue, cur_cpu_num);
if (g_preferred_ready_task[cur_cpu_num] == g_active_task[cur_cpu_num]) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
TRACE_INTRPT_TASK_SWITCH(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#if (RHINO_CONFIG_CPU_NUM > 1)
g_active_task[cur_cpu_num]->cur_exc = 0;
#endif
cpu_intrpt_switch();
RHINO_CPU_INTRPT_ENABLE();
}
size_t krhino_global_space_get(void)
{
size_t mem;
mem = sizeof(g_sys_stat) + sizeof(g_idle_task_spawned) + sizeof(g_ready_queue)
+ sizeof(g_sched_lock) + sizeof(g_intrpt_nested_level) + sizeof(g_preferred_ready_task)
+ sizeof(g_active_task) + sizeof(g_idle_task) + sizeof(g_idle_task_stack)
+ sizeof(g_tick_head) + sizeof(g_tick_count) + sizeof(g_idle_count);
#if (RHINO_CONFIG_TIMER > 0)
mem += sizeof(g_timer_head) + sizeof(g_timer_count)
+ sizeof(g_timer_task) + sizeof(g_timer_task_stack)
+ sizeof(g_timer_queue) + sizeof(timer_queue_cb);
#endif
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
mem += sizeof(g_kobj_list);
#endif
mem += sizeof(g_sys_lock);
return mem;
}
uint32_t krhino_version_get(void)
{
return RHINO_VERSION;
}
void krhino_check_fatal_call(const char *func)
{
#ifdef SYSCHK_FATAL_CALL
uint8_t loop = 0;
uint32_t psr = __get_PSR();
if(__in_disable_irq(psr) || __in_interrupt()){
while(loop++ < 10){
printf("\0013**DANGEROUS** DO NOT CALL %s %s !\r\n", func, __in_disable_irq(psr)?"WHEN IRQ DISABLED":"IN INTERRUPT");
}
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_TASK_SEM > 0)
kstat_t krhino_task_sem_create(ktask_t *task, ksem_t *sem, const name_t *name,
size_t count)
{
kstat_t ret;
if (task == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(task);
ret = krhino_sem_create(sem, name, count);
if (ret == RHINO_SUCCESS) {
task->task_sem_obj = sem;
} else {
task->task_sem_obj = NULL;
}
return ret;
}
kstat_t krhino_task_sem_del(ktask_t *task)
{
NULL_PARA_CHK(task);
return krhino_sem_del(task->task_sem_obj);
}
kstat_t krhino_task_sem_give(ktask_t *task)
{
NULL_PARA_CHK(task);
return krhino_sem_give(task->task_sem_obj);
}
kstat_t krhino_task_sem_take(tick_t ticks)
{
return krhino_sem_take(krhino_cur_task_get()->task_sem_obj, ticks);
}
kstat_t krhino_task_sem_count_set(ktask_t *task, sem_count_t count)
{
NULL_PARA_CHK(task);
return krhino_sem_count_set(task->task_sem_obj, count);
}
kstat_t krhino_task_sem_count_get(ktask_t *task, sem_count_t *count)
{
NULL_PARA_CHK(task);
return krhino_sem_count_get(task->task_sem_obj, count);
}
#endif

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
__init void tick_list_init(void)
{
klist_init(&g_tick_head);
}
RHINO_INLINE void tick_list_pri_insert(klist_t *head, ktask_t *task)
{
tick_t val;
klist_t *q;
klist_t *list_start;
klist_t *list_end;
ktask_t *task_iter_temp;
list_start = list_end = head;
val = task->tick_remain;
for (q = list_start->next; q != list_end; q = q->next) {
task_iter_temp = krhino_list_entry(q, ktask_t, tick_list);
if ((task_iter_temp->tick_match - g_tick_count) > val) {
break;
}
}
klist_insert(q, &task->tick_list);
}
void tick_list_insert(ktask_t *task, tick_t time)
{
klist_t *tick_head_ptr;
if (time > 0u) {
task->tick_match = g_tick_count + time;
task->tick_remain = time;
tick_head_ptr = &g_tick_head;
tick_list_pri_insert(tick_head_ptr, task);
task->tick_head = tick_head_ptr;
}
}
void tick_list_rm(ktask_t *task)
{
klist_t *tick_head_ptr = task->tick_head;
if (tick_head_ptr != NULL) {
klist_rm(&task->tick_list);
task->tick_head = NULL;
}
}
void tick_list_update(tick_i_t ticks)
{
CPSR_ALLOC();
klist_t *tick_head_ptr;
ktask_t *p_tcb;
klist_t *iter;
klist_t *iter_temp;
tick_i_t delta;
RHINO_CRITICAL_ENTER();
g_tick_count += ticks;
tick_head_ptr = &g_tick_head;
iter = tick_head_ptr->next;
while (RHINO_TRUE) {
/* search all the time list if possible */
if (iter != tick_head_ptr) {
iter_temp = iter->next;
p_tcb = krhino_list_entry(iter, ktask_t, tick_list);
delta = (tick_i_t)p_tcb->tick_match - (tick_i_t)g_tick_count;
/* since time list is sorted by remain time, so just campare the absolute time */
if (delta <= 0) {
switch (p_tcb->task_state) {
case K_SLEEP:
p_tcb->blk_state = BLK_FINISH;
p_tcb->task_state = K_RDY;
tick_list_rm(p_tcb);
ready_list_add(&g_ready_queue, p_tcb);
break;
case K_PEND:
tick_list_rm(p_tcb);
/* remove task on the block list because task is timeout */
klist_rm(&p_tcb->task_list);
ready_list_add(&g_ready_queue, p_tcb);
p_tcb->blk_state = BLK_TIMEOUT;
p_tcb->task_state = K_RDY;
mutex_task_pri_reset(p_tcb);
p_tcb->blk_obj = NULL;
break;
case K_PEND_SUSPENDED:
tick_list_rm(p_tcb);
/* remove task on the block list because task is timeout */
klist_rm(&p_tcb->task_list);
p_tcb->blk_state = BLK_TIMEOUT;
p_tcb->task_state = K_SUSPENDED;
mutex_task_pri_reset(p_tcb);
p_tcb->blk_obj = NULL;
break;
case K_SLEEP_SUSPENDED:
p_tcb->task_state = K_SUSPENDED;
p_tcb->blk_state = BLK_FINISH;
tick_list_rm(p_tcb);
break;
default:
k_err_proc(RHINO_SYS_FATAL_ERR);
break;
}
iter = iter_temp;
} else {
break;
}
} else {
break;
}
}
RHINO_CRITICAL_EXIT();
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void mcu_watchdog_feed(void);
void krhino_tick_proc(void)
{
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_tick_hook();
#endif
tick_list_update(1);
#if (RHINO_CONFIG_SCHED_RR > 0)
time_slice_update();
#endif
// mcu_watchdog_feed();
}
sys_time_t krhino_sys_tick_get(void)
{
CPSR_ALLOC();
sys_time_t tick_tmp;
RHINO_CPU_INTRPT_DISABLE();
tick_tmp = g_tick_count;
RHINO_CPU_INTRPT_ENABLE();
return tick_tmp;
}
sys_time_t krhino_sys_time_get(void)
{
return (sys_time_t)(krhino_sys_tick_get() * 1000 /
RHINO_CONFIG_TICKS_PER_SECOND);
}
tick_t krhino_ms_to_ticks(sys_time_t ms)
{
uint16_t padding;
uint16_t surplus;
tick_t ticks;
surplus = ms % 1000;
ticks = (ms / 1000) * RHINO_CONFIG_TICKS_PER_SECOND;
padding = 1000 / RHINO_CONFIG_TICKS_PER_SECOND;
padding = (padding > 0) ? (padding - 1) : 0;
ticks += ((surplus + padding) * RHINO_CONFIG_TICKS_PER_SECOND) / 1000;
return ticks;
}
sys_time_t krhino_ticks_to_ms(tick_t ticks)
{
uint32_t padding;
uint32_t surplus;
sys_time_t time;
surplus = ticks % RHINO_CONFIG_TICKS_PER_SECOND;
time = (ticks / RHINO_CONFIG_TICKS_PER_SECOND) * 1000;
padding = RHINO_CONFIG_TICKS_PER_SECOND / 1000;
padding = (padding > 0) ? (padding - 1) : 0;
time += ((surplus + padding) * 1000) / RHINO_CONFIG_TICKS_PER_SECOND;
return time;
}

View File

@@ -0,0 +1,452 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_TIMER > 0)
static void timer_list_pri_insert(klist_t *head, ktimer_t *timer)
{
sys_time_t val;
klist_t *q;
klist_t *start;
klist_t *end;
ktimer_t *task_iter_temp;
start = end = head;
val = timer->remain;
for (q = start->next; q != end; q = q->next) {
task_iter_temp = krhino_list_entry(q, ktimer_t, timer_list);
if ((task_iter_temp->match - g_timer_count) > val) {
break;
}
}
klist_insert(q, &timer->timer_list);
}
static void timer_list_rm(ktimer_t *timer)
{
klist_t *head;
head = timer->to_head;
if (head != NULL) {
klist_rm(&timer->timer_list);
timer->to_head = NULL;
}
}
static kstat_t timer_create(ktimer_t *timer, const name_t *name, timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run,
uint8_t mm_alloc_flag)
{
kstat_t err = RHINO_SUCCESS;
NULL_PARA_CHK(timer);
NULL_PARA_CHK(name);
NULL_PARA_CHK(cb);
if (first == 0u) {
return RHINO_INV_PARAM;
}
if (first >= MAX_TIMER_TICKS) {
return RHINO_INV_PARAM;
}
if (round >= MAX_TIMER_TICKS) {
return RHINO_INV_PARAM;
}
timer->name = name;
timer->cb = cb;
timer->init_count = first;
timer->round_ticks = round;
timer->remain = 0u;
timer->match = 0u;
timer->timer_state = TIMER_DEACTIVE;
timer->to_head = NULL;
timer->mm_alloc_flag = mm_alloc_flag;
timer->timer_cb_arg = arg;
klist_init(&timer->timer_list);
timer->obj_type = RHINO_TIMER_OBJ_TYPE;
if (auto_run > 0u) {
err = krhino_timer_start(timer);
}
TRACE_TIMER_CREATE(krhino_cur_task_get(), timer);
return err;
}
kstat_t krhino_timer_create(ktimer_t *timer, const name_t *name, timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run)
{
return timer_create(timer, name, cb, first, round, arg, auto_run,
K_OBJ_STATIC_ALLOC);
}
kstat_t krhino_timer_del(ktimer_t *timer)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.cb_num = TIMER_CMD_DEL;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_timer_dyn_create(ktimer_t **timer, const name_t *name,
timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run)
{
kstat_t ret;
ktimer_t *timer_obj;
NULL_PARA_CHK(timer);
if (first >= MAX_TIMER_TICKS) {
return RHINO_INV_PARAM;
}
if (round >= MAX_TIMER_TICKS) {
return RHINO_INV_PARAM;
}
timer_obj = krhino_mm_alloc(sizeof(ktimer_t), __builtin_return_address(0));
if (timer_obj == NULL) {
return RHINO_NO_MEM;
}
ret = timer_create(timer_obj, name, cb, first, round, arg, auto_run,
K_OBJ_DYN_ALLOC);
if (ret != RHINO_SUCCESS) {
krhino_mm_free(timer_obj);
return ret;
}
*timer = timer_obj;
return ret;
}
kstat_t krhino_timer_dyn_del(ktimer_t *timer)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.cb_num = TIMER_CMD_DYN_DEL;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
#endif
kstat_t krhino_timer_start(ktimer_t *timer)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.cb_num = TIMER_CMD_START;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
kstat_t krhino_timer_stop(ktimer_t *timer)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.cb_num = TIMER_CMD_STOP;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
kstat_t krhino_timer_change(ktimer_t *timer, sys_time_t first, sys_time_t round)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
if (first >= (tick_t)-1) {
return RHINO_INV_PARAM;
}
if (round >= (tick_t)-1) {
return RHINO_INV_PARAM;
}
cb.timer = timer;
cb.first = first;
cb.u.round = round;
cb.cb_num = TIMER_CMD_CHG;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
kstat_t krhino_timer_arg_change(ktimer_t *timer, void *arg)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.u.arg = arg;
cb.cb_num = TIMER_ARG_CHG;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
kstat_t krhino_timer_arg_change_auto(ktimer_t *timer, void *arg)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.u.arg = arg;
cb.cb_num = TIMER_ARG_CHG_AUTO;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
extern uint64_t os_mseconds(void);
extern void hgprintf(const char *fmt, ...);
static void timer_cb_proc(void)
{
klist_t *q;
klist_t *start;
klist_t *end;
ktimer_t *timer;
sys_time_i_t delta;
uint64_t tick;
start = end = &g_timer_head;
for (q = start->next; q != end; q = q->next) {
timer = krhino_list_entry(q, ktimer_t, timer_list);
delta = (sys_time_i_t)timer->match - (sys_time_i_t)g_timer_count;
if (delta <= 0) {
tick = os_mseconds();
timer->cb(timer, timer->timer_cb_arg);
if(os_mseconds() - tick > 5){
hgprintf("\0011timer:%p, callback:%p use time: %d ms!\r\n", timer, timer->cb, (uint32_t)(os_mseconds() - tick));
}
timer_list_rm(timer);
if (timer->round_ticks > 0u) {
timer->remain = timer->round_ticks;
timer->match = g_timer_count + timer->remain;
timer->to_head = &g_timer_head;
timer_list_pri_insert(&g_timer_head, timer);
} else {
timer->timer_state = TIMER_DEACTIVE;
}
}
else {
break;
}
}
}
static void cmd_proc(k_timer_queue_cb *cb, uint8_t cmd)
{
ktimer_t *timer;
timer = cb->timer;
switch (cmd) {
case TIMER_CMD_START:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state == TIMER_ACTIVE) {
break;
}
timer->match = g_timer_count + timer->init_count;
/* sort by remain time */
timer->remain = timer->init_count;
/* used by timer delete */
timer->to_head = &g_timer_head;
timer_list_pri_insert(&g_timer_head, timer);
timer->timer_state = TIMER_ACTIVE;
break;
case TIMER_CMD_STOP:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state == TIMER_DEACTIVE) {
break;
}
timer_list_rm(timer);
timer->timer_state = TIMER_DEACTIVE;
break;
case TIMER_CMD_CHG:
if (cb->first == 0u) {
break;
}
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state != TIMER_DEACTIVE) {
timer_list_rm(timer);
timer->timer_state = TIMER_DEACTIVE;
}
timer->init_count = cb->first;
timer->round_ticks = cb->u.round;
break;
case TIMER_ARG_CHG:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state != TIMER_DEACTIVE) {
break;
}
timer->timer_cb_arg = cb->u.arg;
break;
case TIMER_CMD_DEL:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state != TIMER_DEACTIVE) {
break;
}
if (timer->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
break;
}
timer->obj_type = RHINO_OBJ_TYPE_NONE;
TRACE_TIMER_DEL(krhino_cur_task_get(), timer);
break;
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
case TIMER_CMD_DYN_DEL:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state != TIMER_DEACTIVE) {
break;
}
if (timer->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
break;
}
timer->obj_type = RHINO_OBJ_TYPE_NONE;
TRACE_TIMER_DEL(krhino_cur_task_get(), timer);
krhino_mm_free(timer);
break;
#endif
default:
k_err_proc(RHINO_SYS_FATAL_ERR);
break;
}
}
static void timer_cmd_proc(k_timer_queue_cb *cb)
{
if (cb->cb_num == TIMER_ARG_CHG_AUTO) {
cmd_proc(cb, TIMER_CMD_STOP);
cmd_proc(cb, TIMER_ARG_CHG);
cmd_proc(cb, TIMER_CMD_START);
}
else {
cmd_proc(cb, cb->cb_num);
}
}
static void timer_task(void *pa)
{
ktimer_t *timer;
k_timer_queue_cb cb_msg;
kstat_t err;
sys_time_t tick_start;
sys_time_t tick_end;
sys_time_i_t delta;
size_t msg_size;
(void)pa;
while (RHINO_TRUE) {
err = krhino_buf_queue_recv(&g_timer_queue, RHINO_WAIT_FOREVER, &cb_msg, &msg_size);
tick_end = krhino_sys_tick_get();
if (err == RHINO_SUCCESS) {
g_timer_count = tick_end;
}
else {
k_err_proc(RHINO_SYS_FATAL_ERR);
}
timer_cmd_proc(&cb_msg);
while (!is_klist_empty(&g_timer_head)) {
timer = krhino_list_entry(g_timer_head.next, ktimer_t, timer_list);
tick_start = krhino_sys_tick_get();
delta = (sys_time_i_t)timer->match - (sys_time_i_t)tick_start;
if (delta > 0) {
err = krhino_buf_queue_recv(&g_timer_queue, (tick_t)delta, &cb_msg, &msg_size);
tick_end = krhino_sys_tick_get();
if (err == RHINO_BLK_TIMEOUT) {
g_timer_count = tick_end;
}
else if (err == RHINO_SUCCESS) {
g_timer_count = tick_end;
timer_cmd_proc(&cb_msg);
}
else {
k_err_proc(RHINO_SYS_FATAL_ERR);
}
}
else {
g_timer_count = tick_start;
}
timer_cb_proc();
}
}
}
__init void ktimer_init(void)
{
klist_init(&g_timer_head);
krhino_fix_buf_queue_create(&g_timer_queue, "timer_queue",
timer_queue_cb, sizeof(k_timer_queue_cb), RHINO_CONFIG_TIMER_MSG_NUM);
krhino_task_create(&g_timer_task, "timer_task", NULL,
RHINO_CONFIG_TIMER_TASK_PRI, 0u, g_timer_task_stack,
RHINO_CONFIG_TIMER_TASK_STACK_SIZE, timer_task, 1u);
}
#endif /* RHINO_CONFIG_TIMER */

View File

@@ -0,0 +1,327 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_WORKQUEUE > 0)
static kstat_t workqueue_is_exist(kworkqueue_t *workqueue)
{
CPSR_ALLOC();
kworkqueue_t *pos;
RHINO_CRITICAL_ENTER();
for (pos = krhino_list_entry(g_workqueue_list_head.next, kworkqueue_t, workqueue_node);
&pos->workqueue_node != &g_workqueue_list_head;
pos = krhino_list_entry(pos->workqueue_node.next, kworkqueue_t, workqueue_node)) {
if (pos == workqueue) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_EXIST;
}
}
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_NOT_EXIST;
}
static void worker_task(void *arg)
{
CPSR_ALLOC();
kstat_t ret;
kwork_t *work = NULL;
kworkqueue_t *queue = (kworkqueue_t *)arg;
while (1) {
ret = krhino_sem_take(&(queue->sem), RHINO_WAIT_FOREVER);
if (ret != RHINO_SUCCESS) {
k_err_proc(ret);
}
RHINO_CRITICAL_ENTER();
/* have work to do. */
work = krhino_list_entry(queue->work_list.next, kwork_t, work_node);
klist_rm_init(&(work->work_node));
queue->work_current = work;
work->work_exit = 0;
RHINO_CRITICAL_EXIT();
/* do work */
work->handle(work->arg);
RHINO_CRITICAL_ENTER();
/* clean current work */
queue->work_current = NULL;
RHINO_CRITICAL_EXIT();
}
}
kstat_t krhino_workqueue_create(kworkqueue_t *workqueue, const name_t *name,
uint8_t pri, cpu_stack_t *stack_buf, size_t stack_size)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
NULL_PARA_CHK(name);
NULL_PARA_CHK(stack_buf);
if (pri >= RHINO_CONFIG_PRI_MAX) {
return RHINO_BEYOND_MAX_PRI;
}
if (stack_size == 0u) {
return RHINO_TASK_INV_STACK_SIZE;
}
ret = workqueue_is_exist(workqueue);
if (ret == RHINO_WORKQUEUE_EXIST) {
return RHINO_WORKQUEUE_EXIST;
}
klist_init(&(workqueue->workqueue_node));
klist_init(&(workqueue->work_list));
workqueue->work_current = NULL;
workqueue->name = name;
ret = krhino_sem_create(&(workqueue->sem), "WORKQUEUE-SEM", 0);
if (ret != RHINO_SUCCESS) {
return ret;
}
RHINO_CRITICAL_ENTER();
klist_insert(&g_workqueue_list_head, &(workqueue->workqueue_node));
RHINO_CRITICAL_EXIT();
ret = krhino_task_create(&(workqueue->worker), name, (void *)workqueue, pri,
0, stack_buf, stack_size, worker_task, 1);
if (ret != RHINO_SUCCESS) {
RHINO_CRITICAL_ENTER();
klist_rm_init(&(workqueue->workqueue_node));
RHINO_CRITICAL_EXIT();
krhino_sem_del(&(workqueue->sem));
return ret;
}
TRACE_WORKQUEUE_CREATE(krhino_cur_task_get(), workqueue);
return RHINO_SUCCESS;
}
kstat_t krhino_workqueue_del(kworkqueue_t *workqueue)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
ret = workqueue_is_exist(workqueue);
if (ret == RHINO_WORKQUEUE_NOT_EXIST) {
return RHINO_WORKQUEUE_NOT_EXIST;
}
RHINO_CRITICAL_ENTER();
if (!is_klist_empty(&(workqueue->work_list))) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_BUSY;
}
if (workqueue->work_current != NULL) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_BUSY;
}
RHINO_CRITICAL_EXIT();
ret = krhino_task_del(&(workqueue->worker));
if (ret != RHINO_SUCCESS) {
return ret;
}
ret = krhino_sem_del(&(workqueue->sem));
if (ret != RHINO_SUCCESS) {
return ret;
}
RHINO_CRITICAL_ENTER();
klist_rm_init(&(workqueue->workqueue_node));
TRACE_WORKQUEUE_DEL(g_active_task[cpu_cur_get()], workqueue);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
static void work_timer_cb(void *timer, void *arg)
{
CPSR_ALLOC();
kstat_t ret;
kwork_t *work = ((ktimer_t *)timer)->priv;
kworkqueue_t *wq = (kworkqueue_t *)arg;
RHINO_CRITICAL_ENTER();
if (wq->work_current == work) {
RHINO_CRITICAL_EXIT();
return;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return;
}
/* NOTE: the work MUST be initialized firstly */
klist_rm_init(&(work->work_node));
klist_insert(&(wq->work_list), &(work->work_node));
work->wq = wq;
work->work_exit = 1;
RHINO_CRITICAL_EXIT();
ret = krhino_sem_give(&(wq->sem));
if (ret != RHINO_SUCCESS) {
return;
}
}
kstat_t krhino_work_init(kwork_t *work, work_handle_t handle, void *arg,
tick_t dly)
{
kstat_t ret;
if (work == NULL) {
return RHINO_NULL_PTR;
}
if (handle == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(work);
NULL_PARA_CHK(handle);
memset(work, 0, sizeof(kwork_t));
klist_init(&(work->work_node));
work->handle = handle;
work->arg = arg;
work->dly = dly;
work->wq = NULL;
if (dly > 0) {
ret = krhino_timer_dyn_create((ktimer_t **)(&work->timer), "WORK-TIMER", work_timer_cb,
work->dly, 0, (void *)work, 0);
if (ret != RHINO_SUCCESS) {
return ret;
}
}
TRACE_WORK_INIT(krhino_cur_task_get(), work);
return RHINO_SUCCESS;
}
kstat_t krhino_work_run(kworkqueue_t *workqueue, kwork_t *work)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
NULL_PARA_CHK(work);
if (work->dly == 0) {
RHINO_CRITICAL_ENTER();
if (workqueue->work_current == work) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_RUNNING;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_EXIST;
}
/* NOTE: the work MUST be initialized firstly */
klist_rm_init(&(work->work_node));
klist_insert(&(workqueue->work_list), &(work->work_node));
work->wq = workqueue;
work->work_exit = 1;
RHINO_CRITICAL_EXIT();
ret = krhino_sem_give(&(workqueue->sem));
if (ret != RHINO_SUCCESS) {
return ret;
}
} else {
RHINO_CRITICAL_ENTER();
work->timer->priv = work;
RHINO_CRITICAL_EXIT();
ret = krhino_timer_arg_change_auto(work->timer, (void *)workqueue);
if (ret != RHINO_SUCCESS) {
return ret;
}
}
return RHINO_SUCCESS;
}
kstat_t krhino_work_sched(kwork_t *work)
{
return krhino_work_run(&g_workqueue_default, work);
}
kstat_t krhino_work_cancel(kwork_t *work)
{
CPSR_ALLOC();
kworkqueue_t *wq;
NULL_PARA_CHK(work);
wq = (kworkqueue_t *)work->wq;
if (wq == NULL) {
if (work->dly > 0) {
krhino_timer_stop(work->timer);
}
return RHINO_SUCCESS;
}
RHINO_CRITICAL_ENTER();
if (wq->work_current == work) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_RUNNING;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_EXIST;
}
klist_rm_init(&(work->work_node));
work->wq = NULL;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
void workqueue_init(void)
{
klist_init(&g_workqueue_list_head);
krhino_workqueue_create(&g_workqueue_default, "DEFAULT-WORKQUEUE",
RHINO_CONFIG_WORKQUEUE_TASK_PRIO, g_workqueue_stack,
RHINO_CONFIG_WORKQUEUE_STACK_SIZE);
}
#endif

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CORETIM_H
#define CORETIM_H
#define CORETIM_BASE (0xE000E000)
#define CORET_CSR (volatile uint32_t *)(CORETIM_BASE + 0x10)
#define CORET_RVR (volatile uint32_t *)(CORETIM_BASE + 0x14)
#define CORET_CVR (volatile uint32_t *)(CORETIM_BASE + 0x18)
#define CORET_CALIB (volatile uint32_t *)(CORETIM_BASE + 0x1c)
#define CORET_ICPR (volatile uint32_t *)(CORETIM_BASE + 0x280)
/*
* define the bits for TxControl
*/
#define CORETIM_TXCONTROL_ENABLE (1UL << 0)
#define CORETIM_TXCONTROL_INTMASK (1UL << 1)
#define CORETIM_TXCONTROL_MODE (1UL << 16)
/* function prototypes */
void coretim_init(uint32_t hz);
void coretim_clr_irq(void);
uint32_t coretim_get_currval(void);
#endif /* CORETIM_H */

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
//#include <drv_timer.h>
#include <csi_config.h>
#include <csi_core.h>
/* auto define heap size */
extern size_t __heap_start;
extern size_t __heap_end;
extern k_mm_region_t g_mm_region[];
extern int32_t sys_event_new(uint32_t event_id, uint32_t data);
extern void soc_hw_timer_init(void);
#if (RHINO_CONFIG_USER_HOOK > 0)
__init void krhino_init_hook(void)
{
#if (RHINO_CONFIG_HW_COUNT > 0)
soc_hw_timer_init();
#endif
/* auto define heap size */
//g_mm_region[0].len = (uint32_t)(&__heap_end) - (uint32_t)(&__heap_start);
}
void krhino_start_hook(void)
{
}
void krhino_task_create_hook(ktask_t *task)
{
}
void krhino_task_del_hook(ktask_t *task, res_free_t *arg)
{
sys_event_new((0x4<<16)|0x4, (uint32_t)task); //SYS_EVENT(SYS_EVENT_SYSTEM, SYSEVT_TASK_DELETE)
}
void krhino_task_abort_hook(ktask_t *task)
{
}
void krhino_task_switch_hook(ktask_t *orgin, ktask_t *dest)
{
}
void krhino_tick_hook(void)
{
}
void krhino_idle_pre_hook(void)
{
extern void lpm_idle_pre_hook(void);
lpm_idle_pre_hook();
}
int32_t _sleep_tick_get()
{
if (is_klist_empty(&g_tick_head))
{
return -1;
}
ktask_t * p_tcb = krhino_list_entry(g_tick_head.next, ktask_t, tick_list);
return p_tcb->tick_match > g_tick_count ? p_tcb->tick_match - g_tick_count : 0;
}
void krhino_idle_hook(void)
{
extern void lpm_idle_hook(void);
lpm_idle_hook();
}
void krhino_intrpt_hook(int irq)
{
}
void krhino_mm_alloc_hook(void *mem, size_t size)
{
}
#endif
void krhino_intrpt_enter_hook(int irq)
{
}
void krhino_intrpt_exit_hook(int irq)
{
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
void __attribute__((weak)) lpm_idle_hook(void)
{
}
void __attribute__((weak)) lpm_idle_pre_hook(void)
{
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#include <csi_config.h>
#include <soc.h>
//#include <drv_timer.h>
#include "osal/irq.h"
#define OS_MS_PERIOD_TICK (1000/OS_SYSTICK_HZ)
typedef struct osTimespec {
long tv_sec;
long tv_msec;
} osTimespec_t;
extern uint64_t g_sys_tick_count;
extern uint32_t g_cpuloading;
extern uint32_t g_cpuloading_int;
extern volatile uint64_t g_sys_time_last;
void systick_handler(void)
{
g_cpuloading_int++;
g_sys_tick_count++;
krhino_tick_proc();
if((g_cpuloading_int*OS_MS_PERIOD_TICK) >= 2000){
g_cpuloading = 100*(g_cpuloading_int - g_idle_task[cpu_cur_get()].runtime) / g_cpuloading_int;
g_idle_task[cpu_cur_get()].runtime = 0;
g_cpuloading_int = 0;
}
}
uint64_t krhino_curr_nanosec(void)
{
uint32_t flag;
uint32_t cycles;
uint64_t tick;
uint64_t now;
flag = __disable_irq();
tick = g_sys_tick_count;
cycles = csi_coret_get_value();
if(csi_vic_get_pending_irq(CORET_IRQn)) { //tick中断被delay
tick++;
}
if (!flag) __enable_irq();
cycles = csi_coret_get_load() - cycles;
now = (tick * OS_MS_PERIOD_TICK * 1000000ULL) +
(uint64_t)cycles * 1000000000ULL / DEFAULT_SYS_CLK;
if(now < g_sys_time_last){
now += (OS_MS_PERIOD_TICK * 1000000ULL);
}
g_sys_time_last = now;
return now;
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <csi_config.h>
#include <stdlib.h>
#include <stdio.h>
#include <k_api.h>
//#include <drv_timer.h>
#include <soc.h>
#include <csi_core.h>
#define THIS_MODULE MODULE_NONE
/* auto define heap size */
extern size_t __heap_start;
extern size_t __heap_end;
#ifndef RHINO_CONFIG_STD_MALLOC
static k_mm_region_head_t hobbit_mm_region_head;
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
void soc_hw_timer_init(void)
{
}
hr_timer_t soc_hr_hw_cnt_get(void)
{
return 0;
}
lr_timer_t soc_lr_hw_cnt_get(void)
{
return 0;
}
#endif
/* auto define heap size */
k_mm_region_t g_mm_region[] = {
{(uint8_t *)&__heap_start, (size_t)0},
};
int g_region_num = sizeof(g_mm_region)/sizeof(k_mm_region_t);
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
void soc_intrpt_guard(void)
{
return;
}
#endif
#if (RHINO_CONFIG_INTRPT_STACK_REMAIN_GET > 0)
size_t soc_intrpt_stack_remain_get(void)
{
return 0;
}
#endif
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
void soc_intrpt_stack_ovf_check(void)
{
return;
}
#endif
size_t soc_get_cur_sp(void)
{
return __get_SP();
}
extern void mcu_reset(void);
void soc_err_proc(kstat_t err)
{
switch(err) {
case RHINO_TASK_STACK_OVF:
case RHINO_INTRPT_STACK_OVF:
printf("stack overflow: %s!, %p\n", g_active_task[0]->task_name, g_active_task[0]);
break;
default:
printf("sys error:%d, cur task %s!, lr:%p\n",
err, g_active_task[0]->task_name, __builtin_return_address(0));
}
mcu_reset();
//while(1);
}
//__bobj krhino_err_proc_t g_err_proc = soc_err_proc;

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
14jan2018, init vesion
*/
/*
DESCRIPTION
This file provides APIs for management CPU power.
*/
#ifndef __cpu_pwr_api_h__
#define __cpu_pwr_api_h__
#ifdef __cplusplus
extern "C" {
#endif
#include "k_api.h"
#include "cpu_pwr_hal_lib.h"
/*
* CPU power management operates in one of three possible modes:
*
* CPU_IDLE_MODE_RUN:
* In this CPU mode of operation, idle CPU power management is disabled.
*
* CPU_IDLE_MODE_SLEEP:
* the CPUs sleep when idle, but system clock interupts wakes up the CPU
* at every tick.
*
* CPU_IDLE_MODE_TICKLESS: CPUs sleep when idle, potentially for multiple
* ticks at a time.
*/
typedef enum cpu_idle_mode
{
CPU_IDLE_MODE_RUN = 0,
CPU_IDLE_MODE_SLEEP = 1,
CPU_IDLE_MODE_TICKLESS = 2
} CPU_IDLE_MODE;
#if RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT
extern kstat_t cpu_pwr_p_state_set (uint32_t cpuIndex, cpu_pstate_t cpuPState);
extern kstat_t cpu_pwr_p_state_get (uint32_t cpuIndex, cpu_pstate_t * pCpuPState);
extern kstat_t cpu_pwr_p_state_capability_get (uint32_t cpuIndex, uint32_t * pSupportBitsetP);
#endif /* RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT */
extern kstat_t cpu_pwr_c_state_set (cpu_cstate_t);
extern kstat_t cpu_pwr_c_state_get (uint32_t cpuIndex, cpu_cstate_t * pCpuCState);
extern kstat_t cpu_pwr_c_state_capability_get (uint32_t cpuIndex, uint32_t * pSupportBitsetC);
extern kstat_t cpu_pwr_idle_mode_set (CPU_IDLE_MODE mode);
extern kstat_t cpu_pwr_idle_mode_get (CPU_IDLE_MODE * pMode);
#if RHINO_CONFIG_CPU_TICKLESS
extern kstat_t tickless_task_ignore (ktask_t * p_tcb);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __cpu_pwr_api_h__ */

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
#ifndef __k_config_pwr_mgmt_h__
#define __k_config_pwr_mgmt_h__
/* cpu power management configuration */
#ifndef RHINO_CONFIG_CPU_TICKLESS
#define RHINO_CONFIG_CPU_TICKLESS 1
#endif
#ifndef RHINO_CONFIG_CPU_PWR_MGMT_SHOW
#define RHINO_CONFIG_CPU_PWR_MGMT_SHOW 0
#endif
#ifndef RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT
#define RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT 0
#endif
#ifndef RHINO_CONFIG_PWR_DEBUG
#define RHINO_CONFIG_PWR_DEBUG 0
#endif
#ifndef RHINO_PWR_MGMT_ERR
#define RHINO_PWR_MGMT_ERR -1
#endif
#endif /* __k_config_pwr_mgmt_h__ */

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
14jan2018, init vesion
*/
#ifndef __cpu_pwr_hal_lib_h__
#define __cpu_pwr_hal_lib_h__
#ifdef __cplusplus
extern "C" {
#endif
#include "k_cpuset.h"
#include "pwr_state.h"
#include "dl_list.h"
#include "k_err.h"
/* defines */
#define CPU_PWR_TOPO_LEVEL_ROOT 0
#define CPU_PWR_TOPO_LEVEL_1 1
#define CPU_PWR_TOPO_LEVEL_2 2
#define CPU_PWR_TOPO_LEVEL_3 3
#define CPU_PWR_TOPO_LEVEL_4 4
#define CPU_PWR_TOPO_LEVEL_5 5
#define CPU_PWR_NODE_NAME_LEN 64
#define CPU_PWR_ROOT_NODE_NAME "cpu_pwr_root"
#define CPU_STATE_BIT(n) (1 << (n))
#define CPU_FREQ_UNKNOW (-1)
#define CPU_VOLT_UNKNOW (-1)
#define CPU_LATENCY_UNKNOW (-1)
typedef struct
{
uint32_t state;
uint32_t value;
} state_val_pair_t;
struct cpu_pwr;
typedef kstat_t (*FUNC_CPU_PSTATE_SET) (struct cpu_pwr * p_cpu_node, uint32_t cpu_state);
typedef kstat_t (*FUNC_CPU_CSTATE_SET) (uint32_t cpu_state, int master);
typedef kstat_t (*FUNC_CPU_STATE_GET) (struct cpu_pwr * p_cpu_node, uint32_t * pCpuState);
typedef struct cpu_pwr
{
uint32_t supportBitsetC;
int stateNumC;
state_val_pair_t * pPairLatency;
atomic_val_t stateUpdatingC;
cpu_cstate_t currentCState;
cpu_cstate_t desireCState;
FUNC_CPU_CSTATE_SET cpuCStateSetFunc;
#if RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT
uint32_t supportBitsetP;
int stateNumP;
state_val_pair_t * pPairFreq;
state_val_pair_t * pPairVolt;
atomic_val_t stateUpdatingP;
cpu_pstate_t currentPState;
cpu_pstate_t desirePState;
FUNC_CPU_PSTATE_SET cpuPStateSetFunc;
#endif /* RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT */
#ifdef RHINO_CONFIG_SMP
cpuset_t childLiveCpuSet;
uint32_t childIndexMask;
#endif /* RHINO_CONFIG_SMP */
char * name;
uint32_t unit;
uint32_t level;
DL_NODE node;
DL_LIST childList;
struct cpu_pwr * pParent;
} cpu_pwr_t;
extern void cpu_pwr_hal_lib_init (void);
extern void cpu_pwr_child_add (cpu_pwr_t * p_cpu_parent, cpu_pwr_t * pCpuChild);
extern kstat_t cpu_pwr_node_init_static (uint32_t,char *,uint32_t,cpu_pwr_t *);
extern kstat_t cpu_pwr_node_init_dyn (uint32_t,char*,uint32_t,cpu_pwr_t **);
extern cpu_pwr_t * cpu_pwr_node_find_by_name (char * pName,uint32_t index);
extern kstat_t cpu_pwr_leaf_node_record (cpu_pwr_t * p_cpu_node, uint32_t cpuIndex);
extern kstat_t cpu_pwr_c_method_set_by_level (uint32_t level, FUNC_CPU_CSTATE_SET cpuCStateSetFunc);
extern kstat_t cpu_pwr_c_state_capability_set (uint32_t cpuIndex, uint32_t supportBitsetC);
extern kstat_t cpu_pwr_c_state_capability_set_by_level (uint32_t level, uint32_t supportBitsetC);
extern kstat_t cpu_pwr_c_state_latency_save (uint32_t cpuIndex, cpu_cstate_t cpu_state, uint32_t latency);
extern uint32_t cpu_pwr_c_state_latency_get (uint32_t cpuIndex, cpu_cstate_t CState);
extern void cpu_pwr_child_index_mask_set (uint32_t, uint32_t);
#if RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT
extern kstat_t cpu_pwr_p_method_set_by_level (uint32_t level, FUNC_CPU_PSTATE_SET cpuPStateSetFunc);
extern kstat_t cpu_pwr_cur_p_state_update_directly (uint32_t cpuIndex, cpu_pstate_t cpuPState);
extern kstat_t cpu_pwr_p_state_capability_set (uint32_t cpuIndex, uint32_t supportBitsetP);
extern kstat_t cpu_pwr_p_state_capability_set_by_level (uint32_t level, uint32_t supportBitsetP);
extern kstat_t cpu_pwr_freq_save (uint32_t cpuIndex, cpu_pstate_t cpu_state, uint32_t cpuFreq);
extern kstat_t cpu_pwr_volt_save (uint32_t cpuIndex, cpu_pstate_t cpu_state, uint32_t cpuVolt);
extern uint32_t cpu_pwr_freq_get_by_p_state (cpu_pwr_t * p_cpu_node, cpu_pstate_t PState);
extern uint32_t cpu_pwr_volt_get_by_p_state (cpu_pwr_t * p_cpu_node, cpu_pstate_t PState);
#endif /*RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT*/
#ifdef __cplusplus
}
#endif
#endif /* __cpu_pwr_hal_lib_h__ */

View File

@@ -0,0 +1,57 @@
/* cpu_pwr_lib.c - CPU power manager common library */
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
14jan2018, init vesion
*/
#ifndef __cpu_pwr_lib_h__
#define __cpu_pwr_lib_h__
#ifdef __cplusplus
extern "C" {
#endif
#include "k_api.h"
#include "k_cpuset.h"
#include "pwr_state.h"
#include "dl_list.h"
#ifndef container_of
#define container_of(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type,member)))
#endif /* container_of */
/* Maximum number of CPUs */
#ifdef RHINO_CONFIG_SMP
#define CPUS_NUM_MAX 4
#else
#define CPUS_NUM_MAX 1
#endif /* RHINO_CONFIG_SMP */
extern void cpu_pwrmgmt_init(void);
extern void cpu_pwr_down (void);
extern void cpu_pwr_up (void);
extern void cpu_pwr_enabled (int enabled);
#if RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT
extern void (*_func_cpu_pwr_idle_enter_hook) (void);
extern void (*_func_cpu_pwr_int_enter_hook) (void);
extern void (*_func_cpu_pwr_int_exit_hook) (void);
#endif /* RHINO_CONFIG_CPU_PWR_P_STATE_SUPPORT */
extern void (*_func_cpu_tickless_up) (void);
extern void (*_func_cpu_tickless_down) (void);
extern kstat_t (*_func_tickless_ignore_list_add) (klist_t *p_tick_node);
#ifdef __cplusplus
}
#endif
#endif /* __cpu_pwr_lib_h__ */

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
14jan2018, init vesion
*/
#ifndef __cpu_tickless_h__
#define __cpu_tickless_h__
#ifdef __cplusplus
extern "C" {
#endif
#include "k_api.h"
#include "pwr_state.h"
typedef kstat_t (*FUNC_ONE_SHOT_INIT) (void);
typedef uint32_t (*FUNC_ONE_SHOT_SECONDS_MAX) (void);
typedef kstat_t (*FUNC_ONE_SHOT_START) (uint64_t planUse);
typedef kstat_t (*FUNC_ONE_SHOT_STOP) (uint64_t * pPassedUs);
typedef struct
{
FUNC_ONE_SHOT_INIT one_shot_init;
FUNC_ONE_SHOT_SECONDS_MAX one_shot_seconds_max;
FUNC_ONE_SHOT_START one_shot_start;
FUNC_ONE_SHOT_STOP one_shot_stop;
}one_shot_timer_t;
extern kstat_t tickless_init (void);
extern void tickless_c_states_add(uint32_t c_state_set);
extern void tickless_one_shot_timer_save
(cpu_cstate_t c_state, one_shot_timer_t * p_timer);
#ifdef __cplusplus
}
#endif
#endif /* __cpu_tickless_h__ */

View File

@@ -0,0 +1,189 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/* double linked list header */
#ifndef __dl_list_h__
#define __dl_list_h__
#ifdef __cplusplus
extern "C" {
#endif
/* defines */
/* typedefs */
typedef struct _rhino_dlnode /* Node of a linked list. */
{
struct _rhino_dlnode* next; /* Points at the next node in the list */
struct _rhino_dlnode* previous; /* Points at the previous node in the list */
} _RHINO_DL_NODE;
typedef struct /* Header for a linked list. */
{
_RHINO_DL_NODE* head; /* header of list */
_RHINO_DL_NODE* tail; /* tail of list */
} _RHINO_DL_LIST;
typedef _RHINO_DL_NODE DL_NODE;
typedef _RHINO_DL_LIST DL_LIST;
/* DLL_INIT() initialize the specified list to an empty list. */
#define DLL_INIT(list) \
{ \
((DL_LIST *)(list))->head = NULL; \
((DL_LIST *)(list))->tail = NULL; \
}
/* DLL_ADD() adds the specified node to the end of the specified list. */
#define DLL_ADD(list, node) \
{ \
DL_NODE* listTail = (list)->tail; \
DLL_INSERT ((list), listTail, (node)); \
}
/*
* DLL_INSERT() inserts the specified node in the specified list.
* The new node is placed following the specified 'previous' node in the list.
* If the specified previous node is NULL, the node is inserted at the head
* of the list.
*/
#define DLL_INSERT(list, previousNode, node) \
{ \
DL_NODE *temp; \
if ((previousNode) == NULL) \
{ \
temp = ((DL_LIST *)(list))->head; \
((DL_LIST *)(list))->head = (DL_NODE *)(node); \
} \
else \
{ \
temp = ((DL_NODE *)(previousNode))->next; \
((DL_NODE *)(previousNode))->next = (DL_NODE *)(node); \
} \
if (temp == NULL) \
{ \
((DL_LIST *)(list))->tail = (DL_NODE *)(node); \
} \
else \
{ \
temp->previous = (DL_NODE *)(node); \
} \
((DL_NODE *)(node))->next = temp; \
((DL_NODE *)(node))->previous = (DL_NODE *)(previousNode); \
}
/* DLL_REMOVE() Remove the specified node in the doubly linked list.*/
#define DLL_REMOVE(list, node) \
{ \
if (((DL_NODE *)(node))->previous == NULL) \
{ \
((DL_LIST *)(list))->head = ((DL_NODE *)(node))->next; \
} \
else \
{ \
((DL_NODE *)(node))->previous->next = ((DL_NODE *)(node))->next; \
} \
if (((DL_NODE *)(node))->next == NULL) \
{ \
((DL_LIST *)(list))->tail = ((DL_NODE *)(node))->previous; \
} \
else \
{ \
((DL_NODE *)(node))->next->previous = ((DL_NODE *)(node))->previous; \
} \
}
/*
* DLL_FIRST() finds the first node in a doubly linked list.
*
* RETURNS: Pointer to the first node in a list, or NULL if the list is empty.
*/
#define DLL_FIRST(pList) \
( \
(((DL_LIST *)(pList))->head) \
)
/*
* DLL_LAST () finds the last node in a doubly linked list.
*
* RETURNS: Pointer to the last node in list, or NULL if the list is empty.
*/
#define DLL_LAST(pList) \
( \
(((DL_LIST *)(pList))->tail) \
)
/*
* DLL_NEXT() locates the node immediately after the node pointed to by the pNode.
*
* RETURNS: Pointer to the next node in list, or NULL if there is no next node.
*/
#define DLL_NEXT(pNode) \
( \
(((DL_NODE *)(pNode))->next) \
)
/*
* DLL_PREVIOUS() locates the node immediately before the node pointed
* to by the pNode.
*
* RETURNS: Pointer to the preceding node in the list, or
* NULL if there is no next node.
*/
#define DLL_PREVIOUS(pNode) \
( \
(((DL_NODE *)(pNode))->previous) \
)
/*
* DLL_EMPTY() is used to check if list is empty.
* RETURNS: TRUE if list is empty. FALSE otherwise
*/
#define DLL_EMPTY(pList) \
( \
(((DL_LIST *)pList)->head == NULL) \
)
/*
* DLL_GET() gets the first node from the specified list, deletes the node
* from the list, and returns a pointer to the node gotten.
*
* RETURNS: Pointer to the first node in list, or NULL if there is list empty.
*/
#define DLL_GET(list, node) \
{ \
(node) = (void *)((DL_LIST *)(list))->head; \
if ((node) != NULL) \
{ \
((DL_LIST *)(list))->head = ((DL_NODE *)(node))->next; \
if (((DL_NODE *)(node))->next == NULL) \
{ \
((DL_LIST *)(list))->tail = NULL; \
} \
else \
{ \
((DL_NODE *)(node))->next->previous = NULL; \
} \
} \
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __dl_list_h__ */

View File

@@ -0,0 +1,66 @@
/* pwr_debug.c - CPU power manager debug header file */
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
21jan2018,WangMin writen.
*/
#ifndef __pwr_debug_h__
#define __pwr_debug_h__
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#define DBG_OFF 0x00000000
#define DBG_WARN 0x00000001
#define DBG_ERR 0x00000002
#define DBG_INFO 0x00000004
#define DBG_ALL 0xffffffff
extern int pwr_debug_level;
#undef PWR_DEBUG_LINE_INFO
#if RHINO_CONFIG_PWR_DEBUG
#ifdef PWR_DEBUG_LINE_INFO
#define PWR_DBG(lvl,...) \
printf("%s,%d\n",__FILE__,__LINE__); \
do { \
if (pwr_debug_level >= lvl) \
{ \
printf(__VA_ARGS__); \
} \
} \
while (0)
#else /* PWR_DEBUG_LINE_INFO */
#define PWR_DBG(lvl,...) \
do { \
if (pwr_debug_level >= lvl) \
{ \
printf(__VA_ARGS__); \
} \
} \
while (0)
#endif /* PWR_DEBUG_LINE_INFO */
#else /* RHINO_CONFIG_PWR_DEBUG */
#define PWR_DBG(lvl,...)
#endif /* ! RHINO_CONFIG_PWR_DEBUG */
#ifdef __cplusplus
}
#endif
#endif /* __pwr_debug_h__ */

View File

@@ -0,0 +1,117 @@
/* vxbPwrStates.h - device power state definitions */
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
modification history
--------------------
21jan2018,WangMin writen.
*/
/*
DESCRIPTION
This file provides base type define power state.
*/
#ifndef __pwr_state_h__
#define __pwr_state_h__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* CPU states */
typedef enum
{
CPU_CSTATE_C0 = 0, /* Operating */
CPU_CSTATE_C1 = 1, /* Halt -- not executing put powered on */
CPU_CSTATE_C2 = 2, /* not execuing with lower power than C1 */
CPU_CSTATE_C3 = 3, /* not execuing with lower power than C2 */
CPU_CSTATE_C4 = 4, /* not execuing with lower power than C3 */
CPU_CSTATE_C5 = 5,
CPU_CSTATE_C6 = 6,
CPU_CSTATE_C7 = 7,
CPU_CSTATE_C8 = 8,
CPU_CSTATE_C9 = 9,
CPU_CSTATE_C10 = 10,
CPU_CSTATE_C11 = 11,
CPU_CSTATE_C12 = 12,
CPU_CSTATE_C13 = 13,
CPU_CSTATE_C14 = 14,
CPU_CSTATE_C15 = 15,
CPU_CSTATE_C16 = 16,
CPU_CSTATE_C17 = 17,
CPU_CSTATE_C18 = 18,
CPU_CSTATE_C19 = 19,
CPU_CSTATE_C20 = 20,
CPU_CSTATE_C21 = 21,
CPU_CSTATE_C22 = 22,
CPU_CSTATE_C23 = 23,
CPU_CSTATE_C24 = 24,
CPU_CSTATE_C25 = 25,
CPU_CSTATE_C26 = 26,
CPU_CSTATE_C27 = 27,
CPU_CSTATE_C28 = 28,
CPU_CSTATE_C29 = 29,
CPU_CSTATE_C30 = 30,
CPU_CSTATE_C31 = 31,
CPU_CSTATE_MAX = 31,
CPU_CSTATE_NONE = 0xFF
} cpu_cstate_t;
/* Performance states */
typedef enum
{
CPU_PSTATE_P0 = 0, /* Max power and clock */
CPU_PSTATE_P1 = 1,
CPU_PSTATE_P2 = 2,
CPU_PSTATE_P3 = 3,
CPU_PSTATE_P4 = 4,
CPU_PSTATE_P5 = 5,
CPU_PSTATE_P6 = 6,
CPU_PSTATE_P7 = 7,
CPU_PSTATE_P8 = 8,
CPU_PSTATE_P9 = 9,
CPU_PSTATE_P10 = 10,
CPU_PSTATE_P11 = 11,
CPU_PSTATE_P12 = 12,
CPU_PSTATE_P13 = 13,
CPU_PSTATE_P14 = 14,
CPU_PSTATE_P15 = 15,
CPU_PSTATE_P16 = 16,
CPU_PSTATE_P17 = 17,
CPU_PSTATE_P18 = 18,
CPU_PSTATE_P19 = 19,
CPU_PSTATE_P20 = 20,
CPU_PSTATE_P21 = 21,
CPU_PSTATE_P22 = 22,
CPU_PSTATE_P23 = 23,
CPU_PSTATE_P24 = 24,
CPU_PSTATE_P25 = 25,
CPU_PSTATE_P26 = 26,
CPU_PSTATE_P27 = 27,
CPU_PSTATE_P28 = 28,
CPU_PSTATE_P29 = 29,
CPU_PSTATE_P30 = 30,
CPU_PSTATE_P31 = 31,
CPU_PSTATE_MAX = 32,
CPU_PSTATE_NONE = 0xFF
} cpu_pstate_t;
#ifdef __cplusplus
}
#endif
#endif /* __pwr_state_h__ */