[Feature]Upload Modem source code
Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/service/mertos/include/mer_kernel_scheduler.h b/mcu/service/mertos/include/mer_kernel_scheduler.h
new file mode 100644
index 0000000..8eca4e3
--- /dev/null
+++ b/mcu/service/mertos/include/mer_kernel_scheduler.h
@@ -0,0 +1,429 @@
+/*****************************************************************************
+* Copyright Statement:
+* --------------------
+* This software is protected by Copyright and the information contained
+* herein is confidential. The software may not be copied and the information
+* contained herein may not be used or disclosed except with the written
+* permission of MediaTek Inc. (C) 2018
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+*
+* Filename:
+* ---------
+* mer_kernel_scheduler.h
+*
+* Project:
+* --------
+* MERTOS
+*
+* Description:
+* ------------
+* MERTOS scheduler header
+*
+* Author:
+* -------
+ * -------
+*
+*****************************************************************************/
+#ifndef _MER_KERNEL_SCHEDULER_H_
+#define _MER_KERNEL_SCHEDULER_H_
+#include "mer_kernel_config_public.h"
+
+#if defined(__MD97__) || defined(__MD97P__)
+
+#define MER_KERNEL_SCHEDULER_WAKE_UP_STATE 0x2
+#define MER_KERNEL_SCHEDULER_BUSY_STATE 0x0
+#define MER_KERNEL_SCHEDULER_IDLE_STATE 0x1
+
+#define MER_KERNEL_SCHEDULER_CORE0_MASK 0x7
+#define MER_KERNEL_SCHEDULER_CORE1_MASK 0x38
+
+#else
+ #error "unsupport platform"
+#endif /* __MD97__ || __MD97P__ */
+
+#define MER_KERNEL_SCHEDULER_JOB_INDEX_MASK (0xFFFFFFF)
+#define MER_KERNEL_SCHEDULER_JOB_PRIORITY_MASK (~(MER_KERNEL_SCHEDULER_JOB_INDEX_MASK))
+
+#define MER_KERNEL_SCHEDULER_LOCK_IS_RELEASED (0x0)
+#define MER_KERNEL_SCHEDULER_LOCK_IS_NOT_RELEASED (0x1)
+
+//#define __MER_KERNEL_SCHEDULER_ENCODE_DI_PRIORITY__
+
+#ifndef MER_KERNEL_IS_ASSEMBLY
+ #error "please include public header"
+#endif /* MER_KERNEL_IS_ASSEMBLY */
+
+#if !MER_KERNEL_IS_ASSEMBLY
+
+#include "mer_service_types.h"
+#include "mer_kernel_utility_target.h"
+#include "mer_kernel.h"
+#include "mer_kernel_dpc.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Internal type
+///////////////////////////////////////////////////////////////////////////////
+typedef struct {
+ mer_uint32 priority;
+ mer_uint32 affinity_mask;
+ mer_uint32 job_index;
+ mer_uint32 self_adjust;
+} mer_kernel_scheduler_job;
+
+typedef void (*mer_kernel_scheduler_job_callback)(mer_uint32);
+//typedef void (*mer_kernel_scheduler_set_job_callback)(mer_uint32);
+
+typedef enum {
+ MER_KERNEL_SCHEDULER_INSERT_TO_HEAD = 0,
+ MER_KERNEL_SCHEDULER_INSERT_TO_TAIL = 2,
+ MER_KERNEL_SCHEDULER_INSERT_TO_HEAD_AND_RETURN = 0x10,
+ MER_KERNEL_SCHEDULER_INSERT_TO_TAIL_AND_RETURN = 0x12,
+} mer_kernel_scheduler_job_insert_type;
+
+typedef enum {
+ MER_KERNEL_SCHEDULER_CONTEXT_TASK = 1,
+ MER_KERNEL_SCHEDULER_CONTEXT_DPC = 2,
+ MER_KERNEL_SCHEDULER_CONTEXT_ISR = 3,
+ MER_KERNEL_SCHEDULER_CONTEXT_NONE = 4,
+} mer_kernel_scheduler_context_type;
+
+///////////////////////////////////////////////////////////////////////////////
+// External Variable
+///////////////////////////////////////////////////////////////////////////////
+extern mer_kernel_scheduler_job mer_kernel_scheduler_running_job[MIPS_HW_VPE_NUM];
+extern mer_kernel_scheduler_job mer_kernel_scheduler_ready_job[MIPS_HW_VPE_NUM];
+extern mer_kernel_scheduler_job_callback mer_kernel_scheduler_job_insert[];
+extern mer_uint32 mer_kernel_scheduler_idle_flag_mips[MIPS_HW_VPE_NUM];
+
+extern mer_uint32 mer_kernel_dpc_info_table_begin;
+extern mer_uint32 mer_kernel_dpc_info_table_end;
+extern mer_uint32 mer_kernel_task_info_table_begin;
+extern mer_uint32 mer_kernel_task_info_table_end;
+
+///////////////////////////////////////////////////////////////////////////////
+// External Function
+///////////////////////////////////////////////////////////////////////////////
+extern void mer_kernel_scheduler_reschedule_job();
+mer_uint32 mer_kernel_scheduler_insert_job(mer_uint32 new_job_priority,
+ mer_uint32 new_job_affinity_mask,
+ mer_uint32 new_job_index,
+ mer_kernel_scheduler_job_insert_type new_job_insert_position);
+void mer_kernel_scheduler_switch_local_job(mer_uint32 current_vpe);
+void mer_kernel_scheduler_adjust_priority(mer_uint32 current_vpe);
+
+/* Low power */
+mer_uint32 mer_kernel_scheduler_remove_vpes_from_scheduling();
+void mer_kernel_scheduler_restore_current_vpe_to_scheduling(mer_uint32 core);
+void mer_kernel_scheduler_set_slave_vpe_idle_flag();
+void mer_kernel_scheduler_remove_slave_vpe_idle_flag();
+
+void mer_kernel_scheduler_initialization();
+
+mer_kernel_scheduler_context_type mer_kernel_scheduler_get_current_context_level();
+
+///////////////////////////////////////////////////////////////////////////////
+// Static Inline Function
+///////////////////////////////////////////////////////////////////////////////
+/**
+ * Check whether the job priority of VPE is in ISR
+ * Time complexity O(1)
+ *
+ * @param[out] 1 if in ISR, otherwise 0 if in DPC/Task
+ * @param[in] priority
+ *
+ */
+static inline mer_uint32 mer_kernel_scheduler_is_in_isr(mer_uint32 priority){
+
+ mer_uint32 non_isr_mask = 0xC0000000;
+ return ((priority & non_isr_mask) == 0);
+}
+
+/**
+ * Encode DI to current running priority
+ * Time complexity O(1)
+ *
+ * @param[out] current_vpe
+ * @param[in] N/A
+ *
+ */
+static inline void mer_kernel_scheduler_di(mer_uint32 current_vpe){
+
+#if defined(__MER_KERNEL_SCHEDULER_ENCODE_DI_PRIORITY__)
+#error "should not compile"
+#if defined(__MER_KERNEL_USE_MIPS_CP0_CONTEXT_REG__)
+ if (MER_KERNEL_GET_INTERRUPT_COUNT()){
+#else
+ if (mer_kernel_interrupt_count[current_vpe]){
+#endif /* __MER_KERNEL_USE_MIPS_CP0_CONTEXT_REG__ */
+ return;
+ }
+
+ mer_uint32 priority = mer_kernel_scheduler_running_job[current_vpe].priority;
+ mer_uint32 level_mask = ((priority & (~MER_KERNEL_SCHEDULER_JOB_INDEX_MASK)) >> 2);
+ mer_uint32 job_mask = (priority & MER_KERNEL_SCHEDULER_JOB_INDEX_MASK);
+
+ mer_kernel_scheduler_running_job[current_vpe].priority = level_mask | job_mask;
+ mer_kernel_utility_coherence_sync();
+
+#endif /* __MER_KERNEL_SCHEDULER_ENCODE_DI_PRIORITY__ */
+}
+
+/**
+ * Encode EI to current running priority
+ * Time complexity O(1)
+ *
+ * @param[out] N/A
+ * @param[in] current_vpe
+ *
+ */
+static inline void mer_kernel_scheduler_ei(mer_uint32 current_vpe){
+
+#if defined(__MER_KERNEL_SCHEDULER_ENCODE_DI_PRIORITY__)
+#error "should not compile"
+#if defined(__MER_KERNEL_USE_MIPS_CP0_CONTEXT_REG__)
+ if (MER_KERNEL_GET_INTERRUPT_COUNT()){
+#else
+ if (mer_kernel_interrupt_count[current_vpe]){
+#endif /* __MER_KERNEL_USE_MIPS_CP0_CONTEXT_REG__ */
+
+ mer_uint32 priority = mer_kernel_scheduler_running_job[current_vpe].priority;
+ mer_uint32 level_mask = ((priority & (~MER_KERNEL_SCHEDULER_JOB_INDEX_MASK)) << 2);
+ mer_uint32 job_mask = (priority & MER_KERNEL_SCHEDULER_JOB_INDEX_MASK);
+
+ mer_kernel_scheduler_running_job[current_vpe].priority = level_mask | job_mask;
+ mer_kernel_utility_coherence_sync();
+
+#endif /* __MER_KERNEL_SCHEDULER_ENCODE_DI_PRIORITY__ */
+
+}
+
+/**
+ * Set wake up status for child VPE (VPE1 in 93/95) before it reset
+ * Time complexity O(1)
+ *
+ * @param[out] N/A
+ * @param[in] N/A
+ *
+ */
+static inline void mer_kernel_scheduler_notify_child_vpe(){
+
+#if defined(__MD97__) || defined(__MD97P__)
+ mer_uint32 current_vpe = mer_kernel_utility_get_current_vpe_id();
+ mer_kernel_scheduler_idle_flag_mips[current_vpe+1] = MER_KERNEL_SCHEDULER_WAKE_UP_STATE;
+ mer_kernel_scheduler_idle_flag_mips[current_vpe+2] = MER_KERNEL_SCHEDULER_WAKE_UP_STATE;
+#else
+ #error "should porting to new platform"
+#endif
+
+}
+
+/**
+ * check if current context level is in dpc or not
+ * Time complexity O(1)
+ *
+ * @param[out] TRUE/FALSE
+ * @param[in] N/A
+ *
+ */
+__attribute__((always_inline)) static inline mer_uint32 mer_kernel_scheduler_is_in_dpc(){
+
+#if defined(__MER_KERNEL_USE_MIPS_CP0_CONTEXT_REG__)
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#else
+ /* Use the type in structure instead to have a better profiling result */
+ mer_uint32 control_block = MER_KERNEL_GET_CURRENT_CONTROL_BLOCK();
+ return ((MER_KERNEL_GET_INTERRUPT_COUNT() == 0) && \
+ (control_block) && \
+ (((mer_service_dpc_cb *)(control_block))->job_type == MER_SERVICE_TYPE_DPC));
+#endif
+#else
+ #error "should porting this part"
+#endif
+}
+
+/**
+ * check if current context level is in task or not
+ * Time complexity O(1)
+ *
+ * @param[out] TRUE/FALSE
+ * @param[in] N/A
+ *
+ */
+__attribute__((always_inline)) static inline mer_uint32 mer_kernel_scheduler_is_in_task(){
+
+#if defined(__MER_KERNEL_USE_MIPS_CP0_CONTEXT_REG__)
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#else
+ /* Use the type in structure instead to have a better profiling result */
+ mer_uint32 control_block = MER_KERNEL_GET_CURRENT_CONTROL_BLOCK();
+ return ((MER_KERNEL_GET_INTERRUPT_COUNT() == 0) && \
+ (control_block) && \
+ (((mer_service_dpc_cb *)(control_block))->job_type == MER_SERVICE_TYPE_TASK));
+#endif
+
+#else
+ #error "should porting this part"
+#endif
+}
+
+/**
+ * atomic read
+ *
+ * @param[out] value
+ * @param[in] address
+ *
+ */
+static inline mer_uint32 mer_kernel_scheduler_atmoic_read(mer_uint32 *ptr){
+
+ mer_uint32 ret_value = 0;
+ __asm__ __volatile__(
+ "ll %0, 0(%1) \n" \
+ :"=d"(ret_value) \
+ :"d"(ptr) \
+ :"memory" \
+ );
+
+ return ret_value;
+}
+
+/**
+ * atomic write
+ *
+ * @param[out] result
+ * @param[in] address
+ *
+ */
+static inline mer_uint32 mer_kernel_scheduler_atomic_write(mer_uint32 *ptr, mer_uint32 result){
+
+ __asm__ __volatile__(
+ "sc %0, 0(%1) \n" \
+ :"=d"(result) \
+ :"d"(ptr), "0"(result) \
+ :"memory" \
+ );
+
+ return result;
+}
+
+/**
+ * Wipe out the VPE running priority when entering ISR
+ *
+ * Time complexity O(1)
+ *
+ * @param[out] N/A
+ * @param[in] vpe_id, job_stack_pointer
+ *
+ */
+__attribute__((always_inline)) static inline void mer_kernel_scheduler_enter_isr(mer_uint32 vpe_id, mer_uint32 job_stack_pointer)
+{
+ /* Note that we do not take schedule lock here since we DO NOT allow ignore
+ ISR priority. It means, when I am in ISR, NO other VPE will send OS
+ interrupt to me even when I am a extremely short ISR from idle.
+ By doing so, we can make sure when sending an interrupt, the target
+ should receive OS interrupt immediately (unless it disable interrupt)
+ This reduce the chance that multiple OS interrupt send to same VPE.
+ */
+
+
+#if defined(__MER_KERNEL_DYNAMIC_BALANCE_JOB__)
+ mer_uint32 *job_sp = (mer_uint32 *)(MER_KERNEL_GET_CURRENT_CONTROL_BLOCK());
+ *job_sp = job_stack_pointer;
+#else
+ mer_uint32 *job_sp = (mer_uint32 *)(MER_KERNEL_GET_CURRENT_CONTROL_BLOCK());
+ *job_sp = job_stack_pointer;
+#endif
+
+ mer_uint32 result;
+
+ do {
+ //mer_kernel_utility_coherence_sync();
+
+ mer_uint32 *ptr = &mer_kernel_scheduler_running_job[vpe_id].priority;
+
+ mer_uint32 ll_value = mer_kernel_scheduler_atmoic_read(ptr);
+
+ mer_uint32 level_mask = ((ll_value & (~MER_KERNEL_SCHEDULER_JOB_INDEX_MASK)) >> 2);
+ mer_uint32 job_mask = (ll_value & MER_KERNEL_SCHEDULER_JOB_INDEX_MASK);
+
+ result = mer_kernel_scheduler_atomic_write(ptr, (level_mask | job_mask));
+
+ }while(result == 0);
+
+ //mer_kernel_utility_coherence_sync();
+
+}
+
+/**
+ * Recover out the VPE running priority when leaving ISR
+ *
+ * Time complexity O(1)
+ *
+ * @param[out] N/A
+ * @param[in] N/A
+ *
+ */
+__attribute__((always_inline)) static inline mer_bool mer_kernel_scheduler_recover_job_info(mer_uint32 vpe_id){
+
+ mer_uint32 result, self_reorder, ready_job = mer_kernel_scheduler_ready_job[vpe_id].priority;
+ mer_uint32 *ptr = &mer_kernel_scheduler_running_job[vpe_id].priority;
+
+ do {
+
+ mer_uint32 ll_value = mer_kernel_scheduler_atmoic_read(ptr);
+
+ mer_uint32 level_mask = ((ll_value & (~MER_KERNEL_SCHEDULER_JOB_INDEX_MASK)) << 2);
+ mer_uint32 job_mask = (ll_value & MER_KERNEL_SCHEDULER_JOB_INDEX_MASK);
+ mer_uint32 origin_mask = (level_mask | job_mask);
+
+ self_reorder = (ready_job < origin_mask);
+
+ result = mer_kernel_scheduler_atomic_write(ptr, origin_mask);
+
+ }while(result == 0);
+
+ return self_reorder;
+
+}
+
+#endif /* !MER_IS_ASSEMBLY */
+
+#endif /* _MER_KERNEL_SCHEDULER_H_ */
+