2015-04-10 16:44:37 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
|
|
|
*
|
2015-10-06 11:00:37 -05:00
|
|
|
* 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
|
2015-04-10 16:44:37 -07:00
|
|
|
*
|
2015-10-06 11:00:37 -05:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2015-04-10 16:44:37 -07:00
|
|
|
*
|
2015-10-06 11:00:37 -05:00
|
|
|
* 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.
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
|
|
|
|
2015-12-04 10:09:39 -05:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @brief Private nanokernel definitions (ARM)
|
|
|
|
*
|
2015-10-20 09:42:33 -07:00
|
|
|
* This file contains private nanokernel structures definitions and various
|
|
|
|
* other definitions for the ARM Cortex-M3 processor architecture.
|
|
|
|
*
|
|
|
|
* This file is also included by assembly language files which must #define
|
|
|
|
* _ASMLANGUAGE before including this header file. Note that nanokernel
|
|
|
|
* assembly source files obtains structure offset values via "absolute symbols"
|
|
|
|
* in the offsets.o module.
|
2015-07-01 17:22:39 -04:00
|
|
|
*/
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-06-19 11:07:02 -04:00
|
|
|
#ifndef _NANO_PRIVATE_H
|
|
|
|
#define _NANO_PRIVATE_H
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <toolchain.h>
|
|
|
|
#include <sections.h>
|
2015-05-28 10:56:47 -07:00
|
|
|
#include <arch/cpu.h>
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
#ifndef _ASMLANGUAGE
|
2015-06-04 09:02:25 -04:00
|
|
|
#include <../../../kernel/nanokernel/include/nano_internal.h>
|
2015-04-10 16:44:37 -07:00
|
|
|
#include <stdint.h>
|
2015-06-14 14:19:10 -04:00
|
|
|
#include <misc/dlist.h>
|
2015-04-10 16:44:37 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef _ASMLANGUAGE
|
2016-03-02 17:31:26 -06:00
|
|
|
|
|
|
|
#ifdef CONFIG_THREAD_MONITOR
|
|
|
|
struct __thread_entry {
|
|
|
|
_thread_entry_t pEntry;
|
|
|
|
void *parameter1;
|
|
|
|
void *parameter2;
|
|
|
|
void *parameter3;
|
|
|
|
};
|
|
|
|
#endif /*CONFIG_THREAD_MONITOR*/
|
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
struct coop {
|
|
|
|
/*
|
2016-04-25 11:41:43 -04:00
|
|
|
* Unused for Cortex-M, which automatically saves the necessary
|
|
|
|
* registers in its exception stack frame.
|
2015-04-10 16:44:37 -07:00
|
|
|
*
|
|
|
|
* For Cortex-A, this may be:
|
|
|
|
*
|
|
|
|
* uint32_t a1; // r0
|
|
|
|
* uint32_t a2; // r1
|
|
|
|
* uint32_t a3; // r2
|
|
|
|
* uint32_t a4; // r3
|
|
|
|
* uint32_t ip; // r12
|
|
|
|
* uint32_t lr; // r14
|
|
|
|
* uint32_t pc; // r15
|
|
|
|
* uint32_t xpsr;
|
|
|
|
*/
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct __esf tESF;
|
|
|
|
|
|
|
|
struct preempt {
|
|
|
|
uint32_t v1; /* r4 */
|
|
|
|
uint32_t v2; /* r5 */
|
|
|
|
uint32_t v3; /* r6 */
|
|
|
|
uint32_t v4; /* r7 */
|
|
|
|
uint32_t v5; /* r8 */
|
|
|
|
uint32_t v6; /* r9 */
|
|
|
|
uint32_t v7; /* r10 */
|
|
|
|
uint32_t v8; /* r11 */
|
|
|
|
uint32_t psp; /* r13 */
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct preempt tPreempt;
|
|
|
|
|
|
|
|
#endif /* _ASMLANGUAGE */
|
|
|
|
|
2015-08-20 11:04:01 -04:00
|
|
|
/* Bitmask definitions for the struct tcs.flags bit field */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
#define FIBER 0x000
|
2015-08-20 11:04:01 -04:00
|
|
|
#define TASK 0x001 /* 1 = task, 0 = fiber */
|
|
|
|
#define INT_ACTIVE 0x002 /* 1 = executino context is interrupt handler */
|
|
|
|
#define EXC_ACTIVE 0x004 /* 1 = executino context is exception handler */
|
|
|
|
#define USE_FP 0x010 /* 1 = thread uses floating point unit */
|
2015-04-10 16:44:37 -07:00
|
|
|
#define PREEMPTIBLE \
|
2015-08-20 11:04:01 -04:00
|
|
|
0x020 /* 1 = preemptible thread \
|
2015-04-10 16:44:37 -07:00
|
|
|
* NOTE: the value must be < 0x100 to be able to \
|
|
|
|
* use a small thumb instr with immediate \
|
|
|
|
* when loading PREEMPTIBLE in a GPR \
|
|
|
|
*/
|
2015-08-20 11:04:01 -04:00
|
|
|
#define ESSENTIAL 0x200 /* 1 = system thread that must not abort */
|
2015-04-10 16:44:37 -07:00
|
|
|
#define NO_METRICS 0x400 /* 1 = _Swap() not to update task metrics */
|
|
|
|
|
|
|
|
/* stacks */
|
|
|
|
|
|
|
|
#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE)
|
|
|
|
#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE)
|
|
|
|
|
2015-06-17 11:16:57 -04:00
|
|
|
#ifdef CONFIG_CPU_CORTEX_M
|
2015-08-20 16:46:11 -04:00
|
|
|
#include <cortex_m/stack.h>
|
|
|
|
#include <cortex_m/exc.h>
|
2015-04-10 16:44:37 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef _ASMLANGUAGE
|
2016-04-25 11:41:43 -04:00
|
|
|
|
|
|
|
#ifdef CONFIG_FLOAT
|
|
|
|
struct preemp_float {
|
|
|
|
float s16;
|
|
|
|
float s17;
|
|
|
|
float s18;
|
|
|
|
float s19;
|
|
|
|
float s20;
|
|
|
|
float s21;
|
|
|
|
float s22;
|
|
|
|
float s23;
|
|
|
|
float s24;
|
|
|
|
float s25;
|
|
|
|
float s26;
|
|
|
|
float s27;
|
|
|
|
float s28;
|
|
|
|
float s29;
|
|
|
|
float s30;
|
|
|
|
float s31;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2015-08-20 11:04:01 -04:00
|
|
|
struct tcs {
|
|
|
|
struct tcs *link; /* singly-linked list in _nanokernel.fibers */
|
2015-04-10 16:44:37 -07:00
|
|
|
uint32_t flags;
|
|
|
|
uint32_t basepri;
|
|
|
|
int prio;
|
2015-08-20 11:04:01 -04:00
|
|
|
#ifdef CONFIG_THREAD_CUSTOM_DATA
|
2015-04-10 16:44:37 -07:00
|
|
|
void *custom_data; /* available for custom use */
|
|
|
|
#endif
|
|
|
|
struct coop coopReg;
|
|
|
|
struct preempt preempReg;
|
2015-08-20 11:04:01 -04:00
|
|
|
#if defined(CONFIG_THREAD_MONITOR)
|
2016-03-02 17:31:26 -06:00
|
|
|
struct __thread_entry *entry; /* thread entry and parameters description */
|
2015-08-20 11:04:01 -04:00
|
|
|
struct tcs *next_thread; /* next item in list of ALL fiber+tasks */
|
2015-04-10 16:44:37 -07:00
|
|
|
#endif
|
2015-06-14 14:19:10 -04:00
|
|
|
#ifdef CONFIG_NANO_TIMEOUTS
|
|
|
|
struct _nano_timeout nano_timeout;
|
|
|
|
#endif
|
2015-12-04 15:12:03 -05:00
|
|
|
#ifdef CONFIG_ERRNO
|
|
|
|
int errno_var;
|
|
|
|
#endif
|
2016-02-23 11:05:14 -05:00
|
|
|
#ifdef CONFIG_MICROKERNEL
|
|
|
|
void *uk_task_ptr;
|
|
|
|
#endif
|
2016-04-25 11:41:43 -04:00
|
|
|
#ifdef CONFIG_FLOAT
|
|
|
|
/*
|
|
|
|
* No cooperative floating point register set structure exists for
|
|
|
|
* the Cortex-M as it automatically saves the necessary registers
|
|
|
|
* in its exception stack frame.
|
|
|
|
*/
|
|
|
|
struct preemp_float preemp_float_regs;
|
|
|
|
#endif
|
2015-04-10 16:44:37 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct s_NANO {
|
2015-08-20 11:04:01 -04:00
|
|
|
struct tcs *fiber; /* singly linked list of runnable fiber */
|
|
|
|
struct tcs *task; /* pointer to runnable task */
|
|
|
|
struct tcs *current; /* currently scheduled thread (fiber or task) */
|
|
|
|
int flags; /* struct tcs->flags of 'current' thread */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-08-20 11:04:01 -04:00
|
|
|
#if defined(CONFIG_THREAD_MONITOR)
|
|
|
|
struct tcs *threads; /* singly linked list of ALL fiber+tasks */
|
2015-04-10 16:44:37 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CONFIG_FP_SHARING
|
2015-08-20 11:04:01 -04:00
|
|
|
struct tcs *current_fp; /* thread (fiber or task) that owns the FP regs */
|
2015-04-10 16:44:37 -07:00
|
|
|
#endif /* CONFIG_FP_SHARING */
|
|
|
|
|
2016-03-18 16:43:40 -07:00
|
|
|
#ifdef CONFIG_SYS_POWER_MANAGEMENT
|
2015-04-10 16:44:37 -07:00
|
|
|
int32_t idle; /* Number of ticks for kernel idling */
|
2016-03-18 16:43:40 -07:00
|
|
|
#endif
|
2015-06-14 14:19:10 -04:00
|
|
|
|
2016-03-10 11:18:05 -05:00
|
|
|
#if defined(CONFIG_NANO_TIMEOUTS) || defined(CONFIG_NANO_TIMERS)
|
2015-06-14 14:19:10 -04:00
|
|
|
sys_dlist_t timeout_q;
|
idle: fix tasks waiting when NANO_TIMEOUTS is enabled
Fix an issue where, if a task is pending on a nano timeout, the duration
it wants to wait is not taken into account by the tickless idle code.
This could cause a system to wait forever, or to the limit of the timer
hardware (which is forever, for all intents and purposes).
This fix is to add one field in the nanokernel data structure for one
task to record the amount of ticks it will wait on a nano timeout. Only
one task has to be able to record this information, since, these waits
being looping busy waits, the task of highest priority is the only task
that can be actively waiting with a nano timeout. If a task of lower
priority was previously waiting, and a new task is now waiting, it means
that the wait of the original task has been interrupted, which will
cause said task to run the busy loop on the object again when it gets
scheduled, and the number of ticks it wants to wait has to be recomputed
and recorded again.
Change-Id: Ibcf0f288fc42d96897642cfee00ab7359716703f
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-01-26 13:47:03 -05:00
|
|
|
int32_t task_timeout;
|
2015-06-14 14:19:10 -04:00
|
|
|
#endif
|
2015-04-10 16:44:37 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct s_NANO tNANO;
|
2015-05-08 17:12:45 -05:00
|
|
|
extern tNANO _nanokernel;
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
#endif /* _ASMLANGUAGE */
|
|
|
|
|
|
|
|
#ifndef _ASMLANGUAGE
|
|
|
|
extern void _FaultInit(void);
|
|
|
|
extern void _CpuIdleInit(void);
|
|
|
|
static ALWAYS_INLINE void nanoArchInit(void)
|
|
|
|
{
|
2015-05-08 17:12:45 -05:00
|
|
|
_nanokernel.flags = FIBER;
|
2015-04-10 16:44:37 -07:00
|
|
|
_InterruptStackSetup();
|
|
|
|
_ExcSetup();
|
|
|
|
_FaultInit();
|
|
|
|
_CpuIdleInit();
|
|
|
|
}
|
|
|
|
|
2015-07-01 17:22:39 -04:00
|
|
|
/**
|
|
|
|
*
|
2015-07-01 17:51:40 -04:00
|
|
|
* @brief Set the return value for the specified fiber (inline)
|
2015-07-01 17:22:39 -04:00
|
|
|
*
|
|
|
|
* The register used to store the return value from a function call invocation
|
|
|
|
* to <value>. It is assumed that the specified <fiber> is pending, and thus
|
2015-08-20 11:04:01 -04:00
|
|
|
* the fiber's thread is stored in its struct tcs structure.
|
2015-07-01 17:22:39 -04:00
|
|
|
*
|
2015-10-20 09:42:33 -07:00
|
|
|
* @param fiber pointer to the fiber
|
|
|
|
* @param value is the value to set as a return value
|
|
|
|
*
|
2015-07-01 17:29:04 -04:00
|
|
|
* @return N/A
|
2015-07-01 17:22:39 -04:00
|
|
|
*/
|
2015-10-20 09:42:33 -07:00
|
|
|
static ALWAYS_INLINE void fiberRtnValueSet(struct tcs *fiber,
|
|
|
|
unsigned int value)
|
2015-04-10 16:44:37 -07:00
|
|
|
{
|
|
|
|
tESF *pEsf = (void *)fiber->preempReg.psp;
|
2015-04-14 17:15:52 -05:00
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
pEsf->a1 = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void nano_cpu_atomic_idle(unsigned int);
|
|
|
|
|
|
|
|
#define _IS_IN_ISR() _IsInIsr()
|
|
|
|
|
|
|
|
extern void _IntLibInit(void);
|
|
|
|
|
|
|
|
#endif /* _ASMLANGUAGE */
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-06-19 11:07:02 -04:00
|
|
|
#endif /* _NANO_PRIVATE_H */
|