mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-11-04 16:17:26 +01:00
Merge navaro change into navaro branch.
This commit is contained in:
+5
-26
@@ -1,38 +1,17 @@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Library: Atomthreads ARMv7 Port
|
||||
Library: Atomthreads ARM Port
|
||||
Author: Natie van Rooyen <natie@navaro.nl>
|
||||
License: BSD Revised
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
ARM ARMv7 PORT
|
||||
ARM PORT
|
||||
|
||||
This folder contains a port of the Atomthreads real time kernel for the
|
||||
ARMv7 processor architecture. This port was only tested on a ARMv7 but
|
||||
should work on other versions of the ARM processor as well.
|
||||
ARM processor architecture. This port was tested on the ARMv5 and ARMv7
|
||||
architectures.
|
||||
|
||||
To Use:
|
||||
|
||||
1. From your platforms IRQ vector branch to the "__irq_context_handler()".
|
||||
All interrupts from where calls to Atomthreads will be made should do
|
||||
this. The "__irq_context_handler()" will call a platform specific
|
||||
function called "__context_preempt_handler()" to dispatch the interrupt.
|
||||
|
||||
2. Implement the function "__context_preempt_handler()"
|
||||
from where your platforms interrupt controller will be serviced and the
|
||||
interrupt will be dispatched to a specific interrupt service routine. In
|
||||
the case of your platforms timer tick interrupt call the "archTickHandler()"
|
||||
implemented in "atomport.c".
|
||||
|
||||
3. Initialize your platforms timer tick hardware to generate an OS timer tick
|
||||
interrupt.
|
||||
|
||||
4. Add code to acknowledge your timer hardware's interrupt in the
|
||||
function "archTickHandler()" implemented in "atomport.c". This must
|
||||
be done here because "atomIntExit()" might switch the context.
|
||||
|
||||
5. After your platforms c-runtime initialization has completed, start
|
||||
Atomthreads from your runtime's "main()" function.
|
||||
|
||||
6. Include the port's Makefile in your platform build flow.
|
||||
See the example project in the "platforms/qemu_integratorcp" directory.
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
*/
|
||||
typedef void * SYSCONTEXT ;
|
||||
|
||||
extern void contextInit (void) ;
|
||||
extern void contextSwitch (SYSCONTEXT* save_context, SYSCONTEXT* new_context) ;
|
||||
extern void contextStart (SYSCONTEXT* context) ;
|
||||
extern void contextEnableInterrupts (void) ;
|
||||
@@ -145,43 +144,3 @@ archContextSwitch (ATOM_TCB * p_sp_old, ATOM_TCB * p_sp_new)
|
||||
{
|
||||
contextSwitch (&p_sp_old->sp_save_ptr, &p_sp_new->sp_save_ptr) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \b archTimerTickIrqHandler
|
||||
*
|
||||
* System timer tick interrupt handler.
|
||||
*
|
||||
*/
|
||||
void
|
||||
archTickHandler (void)
|
||||
{
|
||||
atomIntEnter();
|
||||
|
||||
/* Call the OS system tick handler */
|
||||
atomTimerTick();
|
||||
|
||||
/* ack the interrupt if needed */
|
||||
/* ... */
|
||||
|
||||
/* Call the interrupt exit routine */
|
||||
atomIntExit(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b archTickInit
|
||||
*
|
||||
* System timer initialization.
|
||||
*
|
||||
*/
|
||||
void
|
||||
archTickInit (void)
|
||||
{
|
||||
/* Initialize NVIC PendSV */
|
||||
contextInit () ;
|
||||
|
||||
/* Initializa Timer Hardware */
|
||||
/* ... */
|
||||
}
|
||||
|
||||
|
||||
|
||||
+23
-16
@@ -27,17 +27,22 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ATOM_PORT_H
|
||||
#define __ATOM_PORT_H
|
||||
#ifndef __ATOM_PORT_H__
|
||||
#define __ATOM_PORT_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include "types.h"
|
||||
|
||||
/* Required number of system ticks per second (normally 100 for 10ms tick) */
|
||||
#define SYSTEM_TICKS_PER_SEC 100
|
||||
#define SYSTEM_TICKS_PER_SEC 100
|
||||
|
||||
/* Size of each stack entry / stack alignment size (e.g. 8 bits) */
|
||||
#define STACK_ALIGN_SIZE sizeof(uint32_t)
|
||||
/**
|
||||
* Definition of NULL.
|
||||
* If stddef.h is available on the platform it is simplest to include it
|
||||
* from this header, otherwise define below.
|
||||
*/
|
||||
#define NULL ((void *)(0))
|
||||
|
||||
/* Size of each stack entry / stack alignment size (e.g. 32 bits) */
|
||||
#define STACK_ALIGN_SIZE sizeof(unsigned int)
|
||||
|
||||
/**
|
||||
* Architecture-specific types.
|
||||
@@ -48,20 +53,22 @@
|
||||
|
||||
/* *
|
||||
*
|
||||
* Functions defined in atomport_arm.S
|
||||
* Functions defined in atomport_arm.asm
|
||||
*
|
||||
*/
|
||||
extern uint32_t contextEnterCritical (void) ;
|
||||
extern void contextExitCritical (uint32_t posture) ;
|
||||
extern void contextInit (void) ;
|
||||
extern uint32_t contextEnterCritical (void) ;
|
||||
extern void contextExitCritical (uint32_t posture) ;
|
||||
|
||||
|
||||
/* Critical region protection */
|
||||
/**
|
||||
* Critical region protection: this should disable interrupts
|
||||
* to protect OS data structures during modification. It must
|
||||
* allow nested calls, which means that interrupts should only
|
||||
* be re-enabled when the outer CRITICAL_END() is reached.
|
||||
*/
|
||||
#define CRITICAL_STORE uint32_t __atom_critical
|
||||
#define CRITICAL_START() __atom_critical = contextEnterCritical()
|
||||
#define CRITICAL_END() contextExitCritical(__atom_critical)
|
||||
|
||||
|
||||
/* Uncomment to enable stack-checking */
|
||||
/* #define ATOM_STACK_CHECKING */
|
||||
|
||||
#endif /* __ATOM_PORT_H */
|
||||
#endif /* __ATOM_PORT_H__ */
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
extern void archTickHandler (void) ;
|
||||
extern void archTickInit (void) ;
|
||||
extern void archIRQHandler (void) ;
|
||||
|
||||
/* required interface */
|
||||
extern void __context_preempt_handler (void) ;
|
||||
|
||||
#endif /* __ATOM_PORT_PRIVATE_H__ */
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
|
||||
|
||||
.global archIRQHandler
|
||||
|
||||
.global contextEnterCritical
|
||||
.global contextExitCritical
|
||||
.global contextEnableInterrupts
|
||||
@@ -44,7 +43,7 @@
|
||||
.global contextInit
|
||||
|
||||
|
||||
.global __context_preempt_handler
|
||||
.extern __context_preempt_handler
|
||||
|
||||
/**/
|
||||
.equ USR_MODE, 0x10
|
||||
|
||||
+4
-10
@@ -40,16 +40,6 @@ typedef int int32_t ;
|
||||
typedef short int16_t ;
|
||||
typedef char int8_t ;
|
||||
|
||||
// typedef volatile unsigned int REG_DWORD ;// Hardware register definition
|
||||
|
||||
#define UWORD64 unsigned long long
|
||||
#define UWORD32 unsigned int
|
||||
#define UWORD16 unsigned short
|
||||
#define UWORD8 unsigned char
|
||||
#define WORD32 int
|
||||
#define WORD16 short
|
||||
#define WORD8 char
|
||||
|
||||
#ifndef OFFSETOF
|
||||
#define OFFSETOF(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
@@ -58,6 +48,10 @@ typedef char int8_t ;
|
||||
#define INLINE __inline
|
||||
#endif
|
||||
|
||||
/* IO definitions (access restrictions to peripheral registers) */
|
||||
#define __I volatile /*!< defines 'read only' permissions */
|
||||
#define __O volatile /*!< defines 'write only' permissions */
|
||||
#define __IO volatile /*!< defines 'read / write' permissions */
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Library: Atomvn
|
||||
Author: Natie van Rooyen <natie@navaro.nl>
|
||||
License: BSD Revised
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Atomvm is a tiny virtual machine that runs on Windows and can be debugged
|
||||
from an IDE like Microsoft Visual C++ Express. The primary purpose of this
|
||||
virtual machine is for the evaluation of Real Time Operating Systems like
|
||||
Atomthreads and the development and testing of programs for it on a Windows
|
||||
machine.
|
||||
|
||||
Atomvm makes use of the Windows API functions GetThreadContext() and
|
||||
SetThreadContext() to create multiple virtual contexts or threads inside a
|
||||
single Windows thread. Atomvm also simulates interrupts with an interrupt
|
||||
mask accessible from the Atomvm threads. External events can be queued as
|
||||
interrupts to Atomvm, for example a timer loop generating system timer tick
|
||||
interrupts for a Real Time Operating System ported to Atomvm.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
BUILDING THE SOURCE
|
||||
|
||||
To test this project, just add all the files from the "atomthreads/kernel"
|
||||
directory and the "atomthreads/ports/atomvm" directory as well as the test
|
||||
program "atomthreads/ports/atomvm/test/main.c" to your project. Add both the
|
||||
before mentioned directories to the include paths of your project and compile.
|
||||
|
||||
Atomvm was designed for multi core systems but also runs fine on any single
|
||||
core system.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
RUNNING THE TESTS
|
||||
|
||||
The test, main.c, is intentioned to stress the virtual machine.
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ATOM_PORT_TESTS_H
|
||||
#define __ATOM_PORT_TESTS_H
|
||||
#ifndef __ATOMPORT_TEST_H__
|
||||
#define __ATOMPORT_TEST_H__
|
||||
|
||||
/* Include Atomthreads kernel API */
|
||||
#include "atom.h"
|
||||
@@ -54,5 +54,4 @@
|
||||
/* #define TESTS_LOG_STACK_USAGE */
|
||||
|
||||
|
||||
#endif /* __ATOM_PORT_TESTS_H */
|
||||
|
||||
#endif /* __ATOMPORT_TEST_H__ */
|
||||
|
||||
+8
-21
@@ -32,7 +32,6 @@
|
||||
#include "windows.h"
|
||||
|
||||
/** Forward declarations */
|
||||
static void thread_shell (void);
|
||||
DWORD WINAPI cntrl_thread_proc (LPVOID lpParameter) ;
|
||||
|
||||
/* Global data */
|
||||
@@ -51,9 +50,9 @@ static HANDLE cntrl_thread ;
|
||||
*
|
||||
*/
|
||||
void
|
||||
atomvmRun ()
|
||||
atomvmRun (void)
|
||||
{
|
||||
atomvmCtrlInit (&the_atomvm) ;
|
||||
atomvmCtrlCreate (&the_atomvm) ;
|
||||
cntrl_thread = CreateThread (NULL, 0, cntrl_thread_proc, (uint32_t*)the_atomvm, CREATE_SUSPENDED, NULL) ;
|
||||
ResumeThread (cntrl_thread) ;
|
||||
}
|
||||
@@ -73,7 +72,7 @@ cntrl_thread_proc (LPVOID lpParameter)
|
||||
*
|
||||
*/
|
||||
void
|
||||
thread_shell (void)
|
||||
thread_shell (uint32_t arg)
|
||||
{
|
||||
ATOM_TCB *curr_tcb;
|
||||
|
||||
@@ -85,7 +84,8 @@ thread_shell (void)
|
||||
* is first restored.
|
||||
*/
|
||||
// sei();
|
||||
atomvmExitCritical () ;
|
||||
//atomvmExitCritical () ;
|
||||
atomvmInterruptMask (0) ;
|
||||
|
||||
/* Call the thread entry point */
|
||||
if (curr_tcb && curr_tcb->entry_point)
|
||||
@@ -110,7 +110,8 @@ archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_point)(u
|
||||
tcb_ptr->entry_param = entry_param ;
|
||||
tcb_ptr->entry_point = entry_point ;
|
||||
|
||||
atomvmContextCreate (&tcb_ptr->context, (unsigned int )stack_top, (unsigned int )thread_shell) ;
|
||||
tcb_ptr->context = atomvmContextCreate (1) ;
|
||||
atomvmContextInit (tcb_ptr->context, (unsigned int *)stack_top, thread_shell, entry_param, 0) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +147,7 @@ archContextSwitch (ATOM_TCB * p_sp_old, ATOM_TCB * p_sp_new)
|
||||
* System timer tick interrupt handler.
|
||||
*
|
||||
*/
|
||||
void archTimerTickIrqHandler ()
|
||||
void archTimerTickIrqHandler (void)
|
||||
{
|
||||
atomIntEnter();
|
||||
|
||||
@@ -156,17 +157,3 @@ void archTimerTickIrqHandler ()
|
||||
/* Call the interrupt exit routine */
|
||||
atomIntExit(TRUE);
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
__enter_critical ()
|
||||
{
|
||||
return atomvmEnterCritical () ;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__exit_critical (unsigned int isr)
|
||||
{
|
||||
atomvmExitCritical () ;
|
||||
}
|
||||
|
||||
+10
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Kelvin Lawson. All rights reserved.
|
||||
* Copyright (c) 2012, Natie van Rooyen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -32,19 +32,9 @@
|
||||
|
||||
#include "atomvm.h"
|
||||
|
||||
#define SYSTEM_MEMALIGN sizeof (unsigned int)
|
||||
#define SYSTEM_TICKS_PER_SEC 100
|
||||
|
||||
|
||||
typedef unsigned int uintptr_t ;
|
||||
typedef int intptr_t ;
|
||||
typedef unsigned int uint32_t ;
|
||||
typedef unsigned short uint16_t ;
|
||||
typedef unsigned char uint8_t ;
|
||||
typedef int int32_t ;
|
||||
typedef short int16_t ;
|
||||
typedef char int8_t ;
|
||||
|
||||
/* Size of each stack entry / stack alignment size (e.g. 32 bits) */
|
||||
#define STACK_ALIGN_SIZE sizeof(unsigned int)
|
||||
|
||||
/**
|
||||
* Architecture-specific types.
|
||||
@@ -52,23 +42,21 @@ typedef char int8_t ;
|
||||
* included above.
|
||||
*/
|
||||
#define POINTER void *
|
||||
#define ATOM_TLS HATOMVM_CONTEXT context ;
|
||||
|
||||
|
||||
/* Critical region protection */
|
||||
extern unsigned int __enter_critical() ;
|
||||
extern void __exit_critical(unsigned int) ;
|
||||
|
||||
#define CRITICAL_STORE unsigned int __atom
|
||||
#define CRITICAL_START() __atom = __enter_critical()
|
||||
#define CRITICAL_END() __exit_critical(__atom)
|
||||
#define CRITICAL_STORE unsigned int __atom_int_mask
|
||||
#define CRITICAL_START() __atom_int_mask = atomvmInterruptMask(1)
|
||||
#define CRITICAL_END() atomvmInterruptMask(__atom_int_mask)
|
||||
|
||||
#define ATOM_TLS HATOMVM_CONTEXT context ;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void atomvmRun () ;
|
||||
extern void archTimerTickIrqHandler () ;
|
||||
extern void atomvmRun (void) ;
|
||||
extern void archTimerTickIrqHandler (void) ;
|
||||
|
||||
/* The instance of the atomvm for this port */
|
||||
extern HATOMVM the_atomvm ;
|
||||
|
||||
#endif /* __ATOM_PORT_H */
|
||||
#endif /* __ATOM_PORT_H__ */
|
||||
|
||||
+158
-322
@@ -39,18 +39,21 @@
|
||||
*
|
||||
* \b Function prototypes used for controlling the atom virtual machine: \n
|
||||
*
|
||||
* \li atomvmCtrlInit(): .
|
||||
* \li atomvmCtrlCreate(): .
|
||||
* \li atomvmCtrlRun(): .
|
||||
* \li atomvmCtrlIntRequest(): .
|
||||
* \li atomvmCtrlClose(): .
|
||||
*
|
||||
* \b Function prototypes for use by the atom virtual machine: \n
|
||||
*
|
||||
* \li atomvmExitCritical(): .
|
||||
* \li atomvmEnterCritical(): .
|
||||
* \li atomvmInterruptMask(): .
|
||||
* \li atomvmContextCreate(): .
|
||||
* \li atomvmContextSwitch(): .
|
||||
* \li atomvmContextDesrtroy(): .
|
||||
* \li atomvmWriteThreadId(): .
|
||||
* \li atomvmReadThreadId(): .
|
||||
* \li atomvmInterruptWait(): .
|
||||
* \li atomvmGetVmId(): .
|
||||
*
|
||||
* \b Function prototypes to be implemted in the atom virtual machine: \n
|
||||
*
|
||||
@@ -67,8 +70,6 @@
|
||||
|
||||
#define CONTEXT_VM (CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS)
|
||||
|
||||
#define ATOMVM_ATOMVM_PERF_COUNTER(patomvm, counter) (InterlockedIncrement(&patomvm->perf_counters.counter))
|
||||
|
||||
/* Data types */
|
||||
|
||||
/* Forward declarations */
|
||||
@@ -118,31 +119,17 @@ typedef struct ATOMVM_CALLBACK_CONTEXT_SWITCH_S {
|
||||
|
||||
} ATOMVM_CALLBACK_CONTEXT_SWITCH, *PATOMVM_CALLBACK_CONTEXT_SWITCH ;
|
||||
|
||||
/* ATOMVM_CALLBACK_IPI is the parameter for a ATOMVM_CALLBACK_F call
|
||||
that take as parameter a pointer to a ipi target and the isr to call */
|
||||
typedef struct ATOMVM_CALLBACK_IPI_S {
|
||||
/* ATOMVM_CALLBACK_INT_REQUEST is the parameter for a ATOMVM_CALLBACK_F call
|
||||
that take as parameter a pointer to to the function that will be called in
|
||||
an interrupt context */
|
||||
typedef struct ATOMVM_CALLBACK_INT_REQUEST_S {
|
||||
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
/* Parameters the callback function will operate on */
|
||||
volatile uint32_t target ;
|
||||
volatile uint32_t isr ;
|
||||
/* Function pointer the callback will call */
|
||||
void (*isr) (void) ;
|
||||
|
||||
} ATOMVM_CALLBACK_IPI, *PATOMVM_CALLBACK_IPI ;
|
||||
|
||||
typedef struct ATOMVM_PERF_COUNTERS_S {
|
||||
|
||||
/* Number of interrupt requests */
|
||||
uint32_t int_request ;
|
||||
|
||||
/* Number of service calls (context switches and
|
||||
context init from atom virtual machime) */
|
||||
uint32_t service_call ;
|
||||
|
||||
/* Total number of context switches */
|
||||
uint32_t context_switch ;
|
||||
|
||||
} ATOMVM_PERF_COUNTERS, *PATOMVM_PERF_COUNTERS ;
|
||||
} ATOMVM_CALLBACK_INT_REQUEST, *PATOMVM_CALLBACK_INT_REQUEST ;
|
||||
|
||||
/* ATOMVM_CONTEXT saves the state of a context created by
|
||||
atomvmContextCreate() and sheduled by atomvmContextSwitch(). */
|
||||
@@ -152,18 +139,16 @@ typedef struct ATOMVM_CONTEXT_S {
|
||||
during context initialization and context switches */
|
||||
CONTEXT context ;
|
||||
|
||||
/* When entering a critical section the critical_count is
|
||||
incremented for the context. Interrupts will only occur while
|
||||
the critical_count is zero. The functions atomvmExitCritical()
|
||||
and atomvmEnterCritical() will respectively decrement and
|
||||
increment the critical count */
|
||||
volatile uint32_t critical_count ;
|
||||
/* When entering a critical section the interrupt_mask is
|
||||
set for the context. Interrupts will only occur while
|
||||
the interrupt_mask is zero. */
|
||||
volatile uint32_t interrupt_mask ;
|
||||
uint32_t thread_id ;
|
||||
|
||||
} ATOMVM_CONTEXT, *PATOMVM_CONTEXT ;
|
||||
|
||||
/* ATOMVM defines the state of an instance to an atomvm. It is created
|
||||
by a call to atomvmCtrlInit(). */
|
||||
by a call to atomvmCtrlCreate(). */
|
||||
typedef struct ATOMVM_S {
|
||||
|
||||
uint32_t atomvm_id ;
|
||||
@@ -176,7 +161,6 @@ typedef struct ATOMVM_S {
|
||||
HANDLE atomvm_int ;
|
||||
HANDLE atomvm_int_complete ;
|
||||
HANDLE atomvm_close ;
|
||||
HANDLE atomvm_event ;
|
||||
|
||||
/* next ISR */
|
||||
volatile void (*isr)(void) ;
|
||||
@@ -191,21 +175,15 @@ typedef struct ATOMVM_S {
|
||||
and, return value for the current service call */
|
||||
PATOMVM_CALLBACK service_call ;
|
||||
|
||||
/* Context for startup, before any context was scheduled
|
||||
(workaround to not check everytime if the first context
|
||||
was already started) */
|
||||
/* Context for startup, before any context was scheduled */
|
||||
ATOMVM_CONTEXT atom_init_context ;
|
||||
|
||||
/* Performance counters */
|
||||
volatile ATOMVM_PERF_COUNTERS perf_counters ;
|
||||
|
||||
} ATOMVM, *PATOMVM ;
|
||||
|
||||
|
||||
/* Global declarations */
|
||||
volatile uint32_t g_atomvm_counter = 0 ;
|
||||
volatile DWORD g_atomvm_tls_idx ;
|
||||
PATOMVM g_vms[ATOMVM_MAX_VM] ;
|
||||
volatile uint32_t g_atomvm_id = 0 ;
|
||||
volatile DWORD g_atomvm_tls_idx ;
|
||||
|
||||
|
||||
/* Forward declaration for the atom virtual machine thread */
|
||||
@@ -214,57 +192,50 @@ static DWORD WINAPI vm_thread (LPVOID lpParameter) ;
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCtrlInit
|
||||
* \b atomvmCtrlCreate
|
||||
*
|
||||
* This is an atomvm controll function used by a controlling thread
|
||||
* and must not be called from the atom virtual machine.
|
||||
* This is an atomvm controll function used by a controlling thread.
|
||||
*
|
||||
* Initializes the virtual machine.
|
||||
*
|
||||
* ToDo: More Error checking.
|
||||
*
|
||||
* @param[out] atomvm Handle to the virtual machine created.
|
||||
* @param[out] atomvm Handle to the virtual machine to create.
|
||||
*
|
||||
* @return Zero on failure.
|
||||
*/
|
||||
uint32_t
|
||||
atomvmCtrlInit (HATOMVM *atomvm)
|
||||
atomvmCtrlCreate (HATOMVM *atomvm)
|
||||
{
|
||||
PATOMVM patomvm = 0 ;
|
||||
int32_t i ;
|
||||
|
||||
if (g_atomvm_counter < ATOMVM_MAX_VM) {
|
||||
patomvm = (PATOMVM) malloc (sizeof(struct ATOMVM_S)) ;
|
||||
|
||||
patomvm = (PATOMVM) malloc (sizeof(struct ATOMVM_S)) ;
|
||||
if (patomvm) {
|
||||
|
||||
if (patomvm) {
|
||||
memset (patomvm, 0, sizeof(struct ATOMVM_S)) ;
|
||||
|
||||
memset (patomvm, 0, sizeof(struct ATOMVM_S)) ;
|
||||
|
||||
patomvm->atomvm_id = InterlockedIncrement(&g_atomvm_counter) - 1 ;
|
||||
|
||||
if (patomvm->atomvm_id == 0) {
|
||||
g_atomvm_tls_idx = TlsAlloc () ;
|
||||
for (i=0; i<ATOMVM_MAX_VM; i++) {
|
||||
g_vms[i] = 0 ;
|
||||
}
|
||||
}
|
||||
g_vms[patomvm->atomvm_id] = patomvm ;
|
||||
|
||||
patomvm->atomvm_call = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_int = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_int_complete = CreateEvent (NULL, FALSE, TRUE, 0) ;
|
||||
patomvm->atomvm_close = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_event = CreateEvent (NULL, FALSE, FALSE, 0) ;
|
||||
|
||||
patomvm->vm_thread = CreateThread (NULL, 0, vm_thread, (void*)patomvm, CREATE_SUSPENDED, NULL) ;
|
||||
|
||||
patomvm->atom_init_context.critical_count = 1 ;
|
||||
patomvm->current_context = &patomvm->atom_init_context ;
|
||||
|
||||
*atomvm = (HATOMVM)patomvm ;
|
||||
patomvm->atomvm_id = InterlockedIncrement(&g_atomvm_id) - 1 ;
|
||||
|
||||
if (patomvm->atomvm_id == 0) {
|
||||
g_atomvm_tls_idx = TlsAlloc () ;
|
||||
}
|
||||
|
||||
patomvm->atomvm_call = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_int = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_int_complete = CreateEvent (NULL, FALSE, TRUE, 0) ;
|
||||
patomvm->atomvm_close = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
|
||||
ATOMVM_ASSERT(patomvm->atomvm_call && patomvm->atomvm_int && patomvm->atomvm_int_complete &&
|
||||
patomvm->atomvm_close, _T("ResumeThread failed")) ;
|
||||
|
||||
patomvm->vm_thread = CreateThread (NULL, 0, vm_thread, (void*)patomvm, CREATE_SUSPENDED, NULL) ;
|
||||
|
||||
ATOMVM_ASSERT(patomvm->vm_thread, _T("CreateThread failed")) ;
|
||||
|
||||
patomvm->atom_init_context.interrupt_mask = 1 ;
|
||||
patomvm->current_context = &patomvm->atom_init_context ;
|
||||
|
||||
*atomvm = (HATOMVM)patomvm ;
|
||||
|
||||
}
|
||||
|
||||
return patomvm != 0 ;
|
||||
@@ -275,16 +246,13 @@ atomvmCtrlInit (HATOMVM *atomvm)
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCtrlRun
|
||||
*
|
||||
* This is an atomvm controll function used by a controlling thread
|
||||
* and must not be called from the atom virtual machine.
|
||||
*
|
||||
* After a call to atomvmCtrlInit this function start the atom virtual machine.
|
||||
* After a call to atomvmCtrlCreate this function start the atom virtual machine.
|
||||
* The calling thread will be used to manage interrupts and service calls in
|
||||
* the virtual machine. This function will not return untill atomvmCtrlClose
|
||||
* is called.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] flags Reserved for later use.
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlCreate.
|
||||
* @param[in] flags not used.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
@@ -299,9 +267,7 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
#if defined DEBUG || defined _DEBUG
|
||||
BOOL tls_res =
|
||||
#endif
|
||||
TlsSetValue (g_atomvm_tls_idx, (void*) atomvm) ;
|
||||
|
||||
|
||||
TlsSetValue (g_atomvm_tls_idx, (void*) atomvm) ;
|
||||
ATOMVM_ASSERT(tls_res, _T("TlsSetValue failed")) ;
|
||||
|
||||
ResumeThread (patomvm->vm_thread) ;
|
||||
@@ -316,8 +282,6 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
|
||||
if (wait_object == WAIT_OBJECT_0) {
|
||||
|
||||
ATOMVM_ATOMVM_PERF_COUNTER(patomvm, service_call) ;
|
||||
|
||||
service_call = patomvm->service_call ;
|
||||
while (!service_call->lock) {
|
||||
SwitchToThread () ;
|
||||
@@ -328,7 +292,8 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
#if (_WIN32_WINNT >= 0x0600)
|
||||
/*
|
||||
This is used for multi processor machines to ensure the thread
|
||||
is stopped before executing the next instruction. */
|
||||
is stopped before executing the next instruction. Set
|
||||
_WIN32_WINNT < 0x0600 if you are running Windows XP */
|
||||
FlushProcessWriteBuffers ();
|
||||
#endif
|
||||
InterlockedExchange (&service_call->result, service_call->callback (patomvm, service_call)) ;
|
||||
@@ -336,25 +301,23 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
ResetEvent (patomvm->atomvm_call) ;
|
||||
res = ResumeThread (patomvm->vm_thread) ;
|
||||
ATOMVM_ASSERT(res == 1 , _T("ResumeThread failed")) ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
else if (wait_object == WAIT_OBJECT_0 + 1) {
|
||||
|
||||
if (patomvm->current_context->critical_count == 0) {
|
||||
if (patomvm->current_context->interrupt_mask == 0) {
|
||||
|
||||
while ((res = SuspendThread (patomvm->vm_thread)) == (DWORD)-1) ;
|
||||
ATOMVM_ASSERT(res == 0 , _T("SuspendThread failed")) ;
|
||||
#if (_WIN32_WINNT >= 0x0600)
|
||||
/*
|
||||
This is used for multi processor machines to ensure the thread
|
||||
is stopped before executing the next instruction. */
|
||||
is stopped before executing the next instruction. Set
|
||||
_WIN32_WINNT < 0x0600 if you are running Windows XP */
|
||||
FlushProcessWriteBuffers ();
|
||||
#endif
|
||||
if (patomvm->current_context->critical_count == 0) {
|
||||
|
||||
ATOMVM_ATOMVM_PERF_COUNTER(patomvm, int_request) ;
|
||||
if (patomvm->current_context->interrupt_mask == 0) {
|
||||
|
||||
patomvm->status_isr++ ;
|
||||
patomvm->isr () ;
|
||||
@@ -404,11 +367,11 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
* and must not be called from the atom virtual machine.
|
||||
*
|
||||
* Closes the virtual machine and release all memory and handles created
|
||||
* in atomvmCtrlInit.
|
||||
* in atomvmCtrlCreate.
|
||||
*
|
||||
* ToDo: this function was never tested.
|
||||
* ToDo: more testing.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlCreate.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
@@ -432,7 +395,7 @@ atomvmCtrlClose (HATOMVM atomvm)
|
||||
CloseHandle (patomvm->atomvm_close) ;
|
||||
CloseHandle (patomvm->vm_thread) ;
|
||||
|
||||
TlsFree (g_atomvm_tls_idx) ;
|
||||
// TlsFree (g_atomvm_tls_idx) ;
|
||||
|
||||
free (atomvm) ;
|
||||
}
|
||||
@@ -446,9 +409,9 @@ atomvmCtrlClose (HATOMVM atomvm)
|
||||
* an isr it is already in the conrtext of the controll thread and the callback
|
||||
* routine is called directly.
|
||||
*
|
||||
* The atom virtual machine is suspended during the callback.
|
||||
* The atom virtual machine thread is suspended during the callback.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
|
||||
* @param[in] callback Callback function.
|
||||
* @param[in/out] context Context the function will operate on.
|
||||
*
|
||||
@@ -483,91 +446,43 @@ invokeCallback (PATOMVM patomvm, ATOMVM_CALLBACK_F callback, PATOMVM_CALLBACK se
|
||||
/*
|
||||
* \b getAtomvm
|
||||
*
|
||||
* Get the atomvm instance for the calling thredd
|
||||
* Get the atomvm instance for the calling thread
|
||||
*
|
||||
* @return atomvm instance
|
||||
*/
|
||||
__inline PATOMVM
|
||||
getAtomvm ()
|
||||
getAtomvm (void)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) TlsGetValue (g_atomvm_tls_idx) ;
|
||||
|
||||
ATOMVM_ASSERT(patomvm , _T("TlsGetValue failed")) ;
|
||||
|
||||
return patomvm ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmExitCritical
|
||||
* \b atomvmInterruptMask
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function will decrement the critical count for the current atomvm context.
|
||||
* When the critical count reaches zero, interrupts will be enabled again. Calling
|
||||
* this function from inside an isr has no effect.
|
||||
* This function will mask interrupts for the current atomvm context.
|
||||
*
|
||||
* @return Critical count before the function call.
|
||||
* @param[in] mask zero enables interrupts any other value masks interrupts.
|
||||
*
|
||||
* @return Interrupt mask before the function call.
|
||||
*/
|
||||
int32_t
|
||||
atomvmExitCritical ()
|
||||
atomvmInterruptMask (uint32_t mask)
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
int32_t count = 0;
|
||||
int32_t interrupts = 0;
|
||||
|
||||
if (patomvm->status_isr == 0) {
|
||||
count = InterlockedDecrement (&patomvm->current_context->critical_count) ;
|
||||
interrupts = InterlockedExchange (&patomvm->current_context->interrupt_mask, mask) ;
|
||||
}
|
||||
|
||||
return count ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmEnterCritical
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function will increment the critical count for the current atomvm
|
||||
* context. Interrupts will be disabled when the critical count is not zero.
|
||||
* Calling this function from inside an isr has no effect.
|
||||
*
|
||||
* All threads are created with a critical count of 1.
|
||||
*
|
||||
*
|
||||
* @return Critical count before the function call.
|
||||
*/
|
||||
int32_t
|
||||
atomvmEnterCritical ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
int32_t count = 0 ;
|
||||
|
||||
if (patomvm->status_isr == 0) {
|
||||
count = InterlockedIncrement (&patomvm->current_context->critical_count) ;
|
||||
}
|
||||
|
||||
return count ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCriticalCount
|
||||
*
|
||||
* Rerurns the critical cont of the current context.
|
||||
*
|
||||
* @return the critical cont of the current context.
|
||||
*/
|
||||
int32_t
|
||||
atomvmCriticalCount ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
|
||||
return patomvm->current_context->critical_count ;
|
||||
return interrupts ;
|
||||
}
|
||||
|
||||
|
||||
@@ -575,31 +490,30 @@ atomvmCriticalCount ()
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCtrlIntRequest
|
||||
*
|
||||
* This is an atomvm controll function used by a controlling thread(s)
|
||||
* This is an atomvm controll function used by external threads
|
||||
* and must not be called from the atom virtual machine.
|
||||
*
|
||||
* This function requests an interrupt service routine to be called in the
|
||||
* context of the atom virtual machine.
|
||||
*
|
||||
* The call will return immediately after the interrupt was scheduled.
|
||||
* The call will block while a previously scheduled interrupt is in progress.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] isr The address of the interrupt service routine. The routine must use
|
||||
* the default calling convention of the compiler.
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlCreate.
|
||||
* @param[in] isr The address of the interrupt service routine.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void
|
||||
atomvmCtrlIntRequest (HATOMVM atomvm, uint32_t isr)
|
||||
atomvmCtrlIntRequest (HATOMVM atomvm, void (*isr) (void))
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
|
||||
WaitForSingleObject (patomvm->atomvm_int_complete, INFINITE) ;
|
||||
while (InterlockedCompareExchange ((volatile uint32_t *)&patomvm->isr, isr, 0) != 0) {
|
||||
while (InterlockedCompareExchange ((volatile uint32_t *)&patomvm->isr, (uint32_t)isr, 0) != 0) {
|
||||
SwitchToThread() ;
|
||||
}
|
||||
SetEvent (patomvm->atomvm_int) ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -610,7 +524,7 @@ atomvmCtrlIntRequest (HATOMVM atomvm, uint32_t isr)
|
||||
*
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
|
||||
* @param[out] context Context to be initialized.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
@@ -636,15 +550,12 @@ callbackContextCreate (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
* This function creates a atomvm thread context that can be scheduled
|
||||
* by atomvmContextSwitch.
|
||||
*
|
||||
* @param[out] context Handle to the context of the thread that are allocated
|
||||
* by the caller.
|
||||
* @param[in] stack Stack top.
|
||||
* @param[in] entry Entry point using the default caling convention of the compiler.
|
||||
* @param[in] interrupt_mask initial interrupt mask of the thread.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
* @return Handle to the context of the thread created.
|
||||
*/
|
||||
uint32_t
|
||||
atomvmContextCreate (HATOMVM_CONTEXT* atomvm_context, uint32_t stack, uint32_t entry)
|
||||
HATOMVM_CONTEXT
|
||||
atomvmContextCreate (uint32_t interrupt_mask)
|
||||
{
|
||||
uint32_t res ;
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
@@ -653,22 +564,55 @@ atomvmContextCreate (HATOMVM_CONTEXT* atomvm_context, uint32_t stack, uint32_t e
|
||||
ATOMVM_CALLBACK_CONTEXT context_init ;
|
||||
|
||||
context_init.pcontext = new_context ;
|
||||
|
||||
new_context->critical_count = 1 ;
|
||||
|
||||
new_context->interrupt_mask = interrupt_mask ;
|
||||
new_context->thread_id = (uint32_t) -1 ;
|
||||
res = invokeCallback (patomvm, callbackContextCreate, (PATOMVM_CALLBACK)&context_init) ;
|
||||
|
||||
if (res) {
|
||||
pcontext->Ebp = stack ;
|
||||
pcontext->Esp = stack ;
|
||||
pcontext->Eip = entry ;
|
||||
*atomvm_context = (HATOMVM_CONTEXT)new_context ;
|
||||
return (HATOMVM_CONTEXT)new_context ;
|
||||
} else {
|
||||
free (new_context) ;
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmContextInit
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function initialize a atomvm thread context that can be scheduled
|
||||
* by atomvmContextSwitch.
|
||||
*
|
||||
* @param[out] context Handle to the context of the thread that are allocated
|
||||
* by the caller.
|
||||
* @param[in] stack Stack top.
|
||||
* @param[in] entry Entry point of the thread.
|
||||
* @param[in] arg argument passed on the stack as first parameter.
|
||||
* @param[in] exit exit function to return to.
|
||||
* @param[in] status status for exit function.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
atomvmContextInit (HATOMVM_CONTEXT context, uint32_t* stack, void (*entry)(uint32_t), uint32_t arg, void (*exit)(uint32_t))
|
||||
{
|
||||
uint32_t res = 0 ;
|
||||
PATOMVM_CONTEXT new_context = (PATOMVM_CONTEXT)context ;
|
||||
CONTEXT* pcontext = &new_context->context ;
|
||||
|
||||
*stack-- = arg;
|
||||
*stack = (uint32_t)exit ;
|
||||
|
||||
pcontext->Ebp = (uint32_t)stack ;
|
||||
pcontext->Esp = (uint32_t)stack ;
|
||||
pcontext->Eip = (uint32_t)entry ;
|
||||
|
||||
return res ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \b callbackContextSwitch
|
||||
*
|
||||
@@ -676,7 +620,7 @@ atomvmContextCreate (HATOMVM_CONTEXT* atomvm_context, uint32_t stack, uint32_t e
|
||||
*
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
|
||||
* @param[out] context Context to be scheduled.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
@@ -687,18 +631,14 @@ callbackContextSwitch (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
uint32_t res1 = 1 ;
|
||||
uint32_t res2 ;
|
||||
PATOMVM_CALLBACK_CONTEXT_SWITCH context_switch = (PATOMVM_CALLBACK_CONTEXT_SWITCH)callback ;
|
||||
CONTEXT* p_old_context = &context_switch->p_old_context->context ;
|
||||
CONTEXT* p_new_context = &context_switch->p_new_context->context ;
|
||||
|
||||
ATOMVM_ATOMVM_PERF_COUNTER(patomvm, context_switch) ;
|
||||
|
||||
if (p_old_context) {
|
||||
res1 = GetThreadContext (patomvm->vm_thread, p_old_context) ;
|
||||
if (context_switch->p_old_context) {
|
||||
res1 = GetThreadContext (patomvm->vm_thread, &context_switch->p_old_context->context) ;
|
||||
ATOMVM_ASSERT(res1 , _T("GetThreadContext failed")) ;
|
||||
}
|
||||
|
||||
InterlockedExchange ((volatile uint32_t*)&patomvm->current_context, (uint32_t)p_new_context) ;
|
||||
res2 = SetThreadContext (patomvm->vm_thread, &patomvm->current_context->context) ;
|
||||
patomvm->current_context = context_switch->p_new_context ;
|
||||
res2 = SetThreadContext (patomvm->vm_thread, &context_switch->p_new_context->context) ;
|
||||
ATOMVM_ASSERT(res2 , _T("SetThreadContext failed")) ;
|
||||
|
||||
return res1 & res2 ;
|
||||
@@ -783,7 +723,7 @@ atomvmWriteThreadId (uint32_t thread_id)
|
||||
* @return thread_id
|
||||
*/
|
||||
uint32_t
|
||||
atomvmReadThreadId ()
|
||||
atomvmReadThreadId (void)
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
|
||||
@@ -796,103 +736,18 @@ atomvmReadThreadId ()
|
||||
* \b atomvmGetVmId
|
||||
*
|
||||
* Returns an identifier for the virtual machine. This is zero for the first
|
||||
* virtual machine created with atomvmCtrlInit(), 1 for the second and so on.
|
||||
* virtual machine created with atomvmCtrlCreate(), 1 for the second and so on.
|
||||
*
|
||||
* @return The atom vm ID
|
||||
*/
|
||||
uint32_t
|
||||
atomvmGetVmId ()
|
||||
atomvmGetVmId (void)
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
|
||||
return patomvm->atomvm_id ;
|
||||
}
|
||||
/**
|
||||
* \b callbackEventWait
|
||||
*
|
||||
* This function is invoked from the controll thread after a call to atomvmEventWait.
|
||||
*
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[out] context Context to be scheduled.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
callbackEventWait (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
return WaitForSingleObject (patomvm->atomvm_event, INFINITE) == WAIT_OBJECT_0 ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmEventWait
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
*
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void
|
||||
atomvmEventWait ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
invokeCallback (patomvm, callbackEventWait, (PATOMVM_CALLBACK)&callback) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \b callbackEventSend
|
||||
*
|
||||
* This function is invoked from the controll thread after a call to atomvmEventSend.
|
||||
*
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[out] context Context to be scheduled.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
callbackEventSend (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
int32_t i ;
|
||||
for (i=0; i<ATOMVM_MAX_VM; i++) {
|
||||
if (g_vms[i] && (g_vms[i] != patomvm)) {
|
||||
SetEvent (g_vms[i]->atomvm_event) ;
|
||||
}
|
||||
}
|
||||
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmEventSend
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
*
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void
|
||||
atomvmEventSend ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
invokeCallback (patomvm, callbackEventSend, (PATOMVM_CALLBACK)&callback) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \b callbackInterruptWait
|
||||
@@ -901,13 +756,13 @@ atomvmEventSend ()
|
||||
*
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
|
||||
* @param[out] callback Callback parameter.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
callbackInterruptWait (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
callbackIntWait (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
WaitForSingleObject (patomvm->atomvm_int_complete, INFINITE) ;
|
||||
return WaitForSingleObject (patomvm->atomvm_int, INFINITE) == WAIT_OBJECT_0 ;
|
||||
@@ -926,72 +781,53 @@ callbackInterruptWait (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
* @return void.
|
||||
*/
|
||||
void
|
||||
atomvmInterruptWait ()
|
||||
atomvmIntWait (void)
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
invokeCallback (patomvm, callbackInterruptWait, (PATOMVM_CALLBACK)&callback) ;
|
||||
invokeCallback (patomvm, callbackIntWait, (PATOMVM_CALLBACK)&callback) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b callbackScheduleIpi
|
||||
* \b callbackIntRequest
|
||||
*
|
||||
* This function is invoked from the controll thread after a call to atomvmScheduleIpi().
|
||||
* This function is invoked from the controll thread after a call to atomvmIntRequest().
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] target Target atomvm ID, less than ATOMVM_MAX_VM
|
||||
* @param[in] isr interrupt service routine
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
|
||||
* @param[in] callback Callback parameter.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
callbackScheduleIpi (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
callbackIntRequest (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
PATOMVM_CALLBACK_IPI callback_ipi = (PATOMVM_CALLBACK_IPI)callback ;
|
||||
uint32_t res = 0 ;
|
||||
PATOMVM_CALLBACK_INT_REQUEST int_request = (PATOMVM_CALLBACK_INT_REQUEST)callback ;
|
||||
|
||||
if ((callback_ipi->target < ATOMVM_MAX_VM) &&
|
||||
(g_vms[callback_ipi->target] != patomvm) ) {
|
||||
|
||||
atomvmCtrlIntRequest ((HATOMVM)g_vms[callback_ipi->target], callback_ipi->isr) ;
|
||||
res = 1 ;
|
||||
|
||||
}
|
||||
|
||||
return res ;
|
||||
int_request->isr () ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmScheduleIpi
|
||||
* \b atomvmIntRequest
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
* @param[in] isr Function that will be called from the controll thread.
|
||||
*
|
||||
* @param[in] target Target atomvm ID
|
||||
* @param[in] isr interrupt service routine
|
||||
*
|
||||
* @return Zero on failure, the vm is not running.
|
||||
* @return void.
|
||||
*/
|
||||
uint32_t
|
||||
atomvmScheduleIpi (uint32_t target, uintptr_t isr)
|
||||
void
|
||||
atomvmIntRequest (void (*isr) (void))
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK_IPI callback ;
|
||||
|
||||
callback.target = target ;
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK_INT_REQUEST callback ;
|
||||
|
||||
callback.isr = isr ;
|
||||
|
||||
return invokeCallback (patomvm, callbackScheduleIpi, (PATOMVM_CALLBACK)&callback) ;
|
||||
|
||||
|
||||
invokeCallback (patomvm, callbackIntRequest, (PATOMVM_CALLBACK)&callback) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+28
-38
@@ -35,32 +35,26 @@
|
||||
* @authors Natie van Rooyen
|
||||
*
|
||||
* @section intro Introduction
|
||||
* Atomvm is a tiny virtual machine that can run on Windows inside an IDE with a
|
||||
* debugger like Microsoft Visual C++ Express. The primary purpose of this virtual
|
||||
* machine is for the evaluation of Real Time Operating Systems (like atomthreads)
|
||||
* and the development and testing of modules for this Real Time Operating System
|
||||
* in a user friendly environment.:
|
||||
* Atomvm is a tiny virtual machine that runs on Windows and can be debugged
|
||||
* from an IDE like Microsoft Visual C++ Express. The primary purpose of this
|
||||
* virtual machine is for the evaluation of Real Time Operating Systems (like
|
||||
* Atomthreads) and the development and testing of modules for this Real Time
|
||||
* Operating System on a Windows machine.
|
||||
*
|
||||
* Atomvm makes use of the Windows API functions GetThreadContext() and
|
||||
* SetThreadContext() to create multiple virtual contexts or threads inside a
|
||||
* single Windows thread. Atomvm also simulates interrupts with an interrupt
|
||||
* mask accessible from the Atomvm threads. External events can be queued as
|
||||
* interrupts to Atomvm, for example a timer loop generating system timer tick
|
||||
* interrupts for a Real Time Operating System ported to Atomvm.
|
||||
*
|
||||
* @section build Building The Source
|
||||
* To test this project, just add all the files from the "atomthreads/kernel"
|
||||
* directory and the "atomthreads/ports/atomvm" directory as well as the test
|
||||
* program main.c to your project. Add both the
|
||||
* before mentioned directories to the include paths of your project and compile. \n
|
||||
* Atomvm was designed for multi core systems but also runs fine on any single
|
||||
* core system.
|
||||
*
|
||||
* @section test Running The Test
|
||||
* The test, main.c, is intentioned to stress the virtual machine as opposed to
|
||||
* testing the Real Time Operating System. However, this test can also run the
|
||||
* unit tests of atomthreads by using the preprocessor directive "UNIT_TESTS" and
|
||||
* linking in the desired unit test into the project.
|
||||
* */
|
||||
|
||||
#ifndef __ATOMVM_H__
|
||||
#define __ATOMVM_H__
|
||||
|
||||
#include <crtdbg.h>
|
||||
#include "atomuser.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#if defined _DEBUG || defined DEBUG
|
||||
@@ -75,7 +69,7 @@
|
||||
/* Forward declarations */
|
||||
|
||||
/* This is an opaque handle to an instance of an atomvm created
|
||||
by a call to atomvmCtrlInit() */
|
||||
by a call to atomvmCtrlCreate() */
|
||||
typedef struct ATOMVM* HATOMVM ;
|
||||
|
||||
/* This is an opaque handle to an atomvm context created
|
||||
@@ -84,40 +78,36 @@ typedef struct ATOMVM_CONTEXT* HATOMVM_CONTEXT ;
|
||||
|
||||
|
||||
/* Function prototypes used for controlling the atom virtual machine */
|
||||
extern uint32_t atomvmCtrlInit (HATOMVM* atomvm) ;
|
||||
extern uint32_t atomvmCtrlCreate (HATOMVM* atomvm) ;
|
||||
extern void atomvmCtrlRun (HATOMVM atomvm, uint32_t flags) ;
|
||||
extern void atomvmCtrlIntRequest (HATOMVM atomvm, uintptr_t isr) ;
|
||||
extern void atomvmCtrlIntRequest (HATOMVM atomvm, void (*isr) (void)) ;
|
||||
extern void atomvmCtrlClose (HATOMVM atomvm) ;
|
||||
|
||||
/* Function prototypes for use by the atom virtual machine */
|
||||
extern int32_t atomvmExitCritical () ;
|
||||
extern int32_t atomvmEnterCritical () ;
|
||||
extern int32_t atomvmCriticalCount () ;
|
||||
extern uint32_t atomvmContextCreate (HATOMVM_CONTEXT* context, uint32_t stack, uint32_t entry) ;
|
||||
/* Function prototypes for use by the atom virtual machine from within the
|
||||
call to __atomvmReset(). */
|
||||
extern int32_t atomvmInterruptMask (uint32_t mask) ;
|
||||
extern HATOMVM_CONTEXT atomvmContextCreate (uint32_t interrupt_mask) ;
|
||||
extern uint32_t atomvmContextInit (HATOMVM_CONTEXT context, uint32_t* stack,
|
||||
void (*entry)(uint32_t), uint32_t arg, void (*exit)(uint32_t)) ;
|
||||
extern uint32_t atomvmContextSwitch (HATOMVM_CONTEXT old_context, HATOMVM_CONTEXT new_context) ;
|
||||
extern void atomvmContextDesrtroy (HATOMVM_CONTEXT context) ;
|
||||
extern void atomvmWriteThreadId (uint32_t thread_id) ;
|
||||
extern uint32_t atomvmReadThreadId () ;
|
||||
/* Function prototypes for use by the atom virtual machine
|
||||
for synchronization with other running atom virtual machines */
|
||||
extern uint32_t atomvmGetVmId () ;
|
||||
extern void atomvmInterruptWait () ;
|
||||
extern void atomvmEventWait () ;
|
||||
extern void atomvmEventSend () ;
|
||||
extern uint32_t atomvmScheduleIpi (uint32_t target, uintptr_t isr) ;
|
||||
|
||||
|
||||
extern uint32_t atomvmReadThreadId (void) ;
|
||||
extern void atomvmIntWait (void) ;
|
||||
extern void atomvmIntRequest (void (*isr) (void)) ;
|
||||
extern uint32_t atomvmGetVmId (void) ;
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b __atomvmReset
|
||||
*
|
||||
* Function prototype to be implemted in the atom virtual machine
|
||||
* Function prototype to be implemented as entry point for the atom virtual machine.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
extern void __atomvmReset (void) ;
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b __atomvmClose
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "atom.h"
|
||||
#include "atomvm.h"
|
||||
#include "atomport.h"
|
||||
|
||||
|
||||
// #define UNIT_TESTS
|
||||
#ifdef UNIT_TESTS
|
||||
extern uint32_t test_start (void) ;
|
||||
#endif
|
||||
|
||||
#define TEST_THREADS 47
|
||||
|
||||
#define TEST_STACK_BYTE_SIZE 0x10000
|
||||
#define IDLE_STACK_BYTE_SIZE 0x10000
|
||||
#define MONITOR_STACK_BYTE_SIZE 0x10000
|
||||
|
||||
|
||||
|
||||
static unsigned char idle_stack[IDLE_STACK_BYTE_SIZE] ;
|
||||
static unsigned char monitor_stack[MONITOR_STACK_BYTE_SIZE] ;
|
||||
static unsigned char test_stack[TEST_THREADS+1][TEST_STACK_BYTE_SIZE] ;
|
||||
static unsigned int test_counter[TEST_THREADS+1] = {0} ;
|
||||
|
||||
static unsigned int test2_counter = 0 ;
|
||||
static unsigned int test3_counter = 0 ;
|
||||
static unsigned int test_isr_count = 0 ;
|
||||
|
||||
|
||||
static unsigned char test2_stack[TEST_STACK_BYTE_SIZE] ;
|
||||
static unsigned char test3_stack[TEST_STACK_BYTE_SIZE] ;
|
||||
static unsigned char test_idle_stack[TEST_STACK_BYTE_SIZE] ;
|
||||
|
||||
|
||||
static uint8_t test_prio[60] = {
|
||||
001,010,100,200,250, 200,200,200,200,200,
|
||||
150,150,150,150,150, 250,250,250,250,250,
|
||||
101,102,103,104,105, 202,204,206,208,210,
|
||||
150,150,150,150,150, 250,250,250,250,250,
|
||||
121,122,123,124,125, 061,063,065,067,061,
|
||||
150,150,150,150,150, 250,250,250,250,250
|
||||
};
|
||||
|
||||
static uint32_t test_interv[60] = {
|
||||
001,001,001,001,001, 002,003,004,005,006,
|
||||
015,015,015,015,015, 025,024,023,022,021,
|
||||
905,005,005,005,805, 050,051,052,053,054,
|
||||
015,015,015,015,015, 025,024,023,022,021,
|
||||
030,030,030,030,030, 070,071,072,073,474,
|
||||
005,006,007,007,001, 001,001,003,003,005
|
||||
};
|
||||
|
||||
|
||||
ATOM_TCB test_tcb[TEST_THREADS+1] ;
|
||||
ATOM_TCB monitor_tcb ;
|
||||
ATOM_TCB test2_tcb ;
|
||||
ATOM_TCB test3_tcb ;
|
||||
ATOM_TCB test_idle_tcb ;
|
||||
|
||||
DWORD WINAPI isr_thread_proc (LPVOID lpParameter) ;
|
||||
static HANDLE isr_thread_1 ;
|
||||
static HANDLE isr_thread_2 ;
|
||||
static HANDLE isr_thread_3 ;
|
||||
static HANDLE isr_thread_4 ;
|
||||
|
||||
void
|
||||
ipi_sr()
|
||||
{
|
||||
printf("ipi\r\n") ;
|
||||
}
|
||||
|
||||
void
|
||||
monitor_thread (uint32_t parm)
|
||||
{
|
||||
CRITICAL_STORE;
|
||||
int i ;
|
||||
int c = 0 ;
|
||||
ATOM_TCB *tcb ;
|
||||
static unsigned int idle_1 = 0, idle_2 = 0, int_count = 0 ;
|
||||
unsigned int delta_idle_1 , delta_idle_2 , delta_int_count ;
|
||||
|
||||
tcb = atomCurrentContext() ;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
CRITICAL_START();
|
||||
|
||||
printf("Monitor # %04d (%08d)\n", c++, atomTimeGet()) ;
|
||||
printf("-------------------------\n") ;
|
||||
|
||||
for (i=0; i<TEST_THREADS/3; i++) {
|
||||
printf("Thr %.2d cnt %08d\t",i,test_counter[i]);
|
||||
printf("Thr %.2d cnt %08d\t",i+TEST_THREADS/3,test_counter[i+TEST_THREADS/3]);
|
||||
printf("Thr %.2d cnt %08d\n",i+TEST_THREADS*2/3,test_counter[i+TEST_THREADS*2/3]);
|
||||
}
|
||||
|
||||
delta_idle_1 = test2_counter - idle_1 ;
|
||||
delta_idle_2 = test3_counter - idle_2 ;
|
||||
delta_int_count = test_isr_count - int_count ;
|
||||
printf("\nIdle Threadd 1 Counter = %d %d %d\nIdle Theadrd 2 Counter = %d %d %d\nInterrupt Counter = %d %d %d",
|
||||
test2_counter, delta_idle_1, (unsigned int)(test2_counter / c),
|
||||
test3_counter, delta_idle_2, (unsigned int)(test3_counter / c),
|
||||
test_isr_count, delta_int_count, (unsigned int)(test_isr_count / c));
|
||||
printf ("\n\n") ;
|
||||
idle_1 = test2_counter ;
|
||||
idle_2 = test3_counter ;
|
||||
int_count = test_isr_count ;
|
||||
CRITICAL_END();
|
||||
//for (i=0; i<100;i++) {
|
||||
// atomvmInterruptWait () ;
|
||||
//}
|
||||
atomTimerDelay (450) ;
|
||||
//atomvmScheduleIpi (atomvmGetVmId(), (uint32_t) ipi_sr) ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_thread (uint32_t parm)
|
||||
{
|
||||
CRITICAL_STORE;
|
||||
|
||||
for (;;) {
|
||||
|
||||
atomTimerDelay (test_interv[parm]) ;
|
||||
CRITICAL_START();
|
||||
test_counter[parm]++ ;
|
||||
CRITICAL_END();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test2_thread (uint32_t parm)
|
||||
{
|
||||
CRITICAL_STORE;
|
||||
|
||||
for (;;) {
|
||||
|
||||
CRITICAL_START();
|
||||
test2_counter++ ;
|
||||
CRITICAL_END();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test3_thread(uint32_t parm)
|
||||
{
|
||||
CRITICAL_STORE;
|
||||
|
||||
for (;;) {
|
||||
|
||||
CRITICAL_START();
|
||||
test3_counter++ ;
|
||||
CRITICAL_END();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
void unit_test_thread(uint32_t parm)
|
||||
{
|
||||
unsigned int failures ;
|
||||
|
||||
failures = test_start () ;
|
||||
printf ("test_start %d failures\n", failures) ;
|
||||
|
||||
while(1) {
|
||||
|
||||
atomTimerDelay (100);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
__atomvmReset ()
|
||||
{
|
||||
unsigned int i ;
|
||||
|
||||
atomOSInit(&idle_stack[0], IDLE_STACK_BYTE_SIZE, 1) ;
|
||||
#ifndef UNIT_TESTS
|
||||
|
||||
for (i=0; i< TEST_THREADS;i++) {
|
||||
atomThreadCreate ((ATOM_TCB *)&test_tcb[i], test_prio[i], test_thread, i, &test_stack[i][0], TEST_STACK_BYTE_SIZE, 1);
|
||||
}
|
||||
|
||||
atomThreadCreate ((ATOM_TCB *)&monitor_tcb, 50, monitor_thread, 0, &monitor_stack[0], MONITOR_STACK_BYTE_SIZE, 1);
|
||||
|
||||
atomThreadCreate ((ATOM_TCB *)&test2_tcb, 253, test2_thread, 0, &test2_stack[0], TEST_STACK_BYTE_SIZE, 1);
|
||||
atomThreadCreate ((ATOM_TCB *)&test3_tcb, 253, test3_thread, 0, &test3_stack[0], TEST_STACK_BYTE_SIZE, 1);
|
||||
#else
|
||||
|
||||
atomThreadCreate ((ATOM_TCB *)&test2_tcb, 16, unit_test_thread, 0, &test2_stack[], TEST_STACK_BYTE_SIZE, 1);
|
||||
|
||||
#endif
|
||||
|
||||
atomOSStart() ;
|
||||
}
|
||||
|
||||
void
|
||||
__atomvmClose ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
test_isr (void)
|
||||
{
|
||||
static int i = 0 ;
|
||||
test_isr_count++ ;
|
||||
if (i++==25) {
|
||||
//Sleep(3) ;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI
|
||||
isr_thread_proc (LPVOID lpParameter)
|
||||
{
|
||||
int i = 0 ;
|
||||
int x ;
|
||||
int y = rand() % 100 ;
|
||||
while (1) {
|
||||
atomvmCtrlIntRequest (the_atomvm, test_isr) ;
|
||||
if (i++==y) {
|
||||
x = rand() % 50 ;
|
||||
Sleep (x) ;
|
||||
y = rand() % 100 ;
|
||||
i = 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
main ()
|
||||
{
|
||||
atomvmRun () ;
|
||||
|
||||
#ifndef UNIT_TESTS
|
||||
isr_thread_1 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
|
||||
isr_thread_2 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
|
||||
isr_thread_3 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
|
||||
isr_thread_4 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
|
||||
|
||||
ResumeThread (isr_thread_1) ;
|
||||
ResumeThread (isr_thread_2) ;
|
||||
ResumeThread (isr_thread_3) ;
|
||||
ResumeThread (isr_thread_4) ;
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
Sleep(1) ;
|
||||
atomvmCtrlIntRequest (the_atomvm, archTimerTickIrqHandler) ;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual C++ Express 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvc", "msvc.vcxproj", "{77095EB1-4988-4A04-8751-69C63C7C541B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{77095EB1-4988-4A04-8751-69C63C7C541B}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{77095EB1-4988-4A04-8751-69C63C7C541B}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{77095EB1-4988-4A04-8751-69C63C7C541B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{77095EB1-4988-4A04-8751-69C63C7C541B}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{77095EB1-4988-4A04-8751-69C63C7C541B}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>msvc</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(MSBuildProjectDirectory)/../../../kernel;$(MSBuildProjectDirectory)/..;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(MSBuildProjectDirectory)/..;$(MSBuildProjectDirectory)/../../../kernel;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\kernel\atom.h" />
|
||||
<ClInclude Include="..\..\..\kernel\atommutex.h" />
|
||||
<ClInclude Include="..\..\..\kernel\atomqueue.h" />
|
||||
<ClInclude Include="..\..\..\kernel\atomsem.h" />
|
||||
<ClInclude Include="..\..\..\kernel\atomtimer.h" />
|
||||
<ClInclude Include="..\atomport-tests.h" />
|
||||
<ClInclude Include="..\atomport.h" />
|
||||
<ClInclude Include="..\atomuser.h" />
|
||||
<ClInclude Include="..\atomvm.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\kernel\atomkernel.c" />
|
||||
<ClCompile Include="..\..\..\kernel\atommutex.c" />
|
||||
<ClCompile Include="..\..\..\kernel\atomqueue.c" />
|
||||
<ClCompile Include="..\..\..\kernel\atomsem.c" />
|
||||
<ClCompile Include="..\..\..\kernel\atomtimer.c" />
|
||||
<ClCompile Include="..\atomport.c" />
|
||||
<ClCompile Include="..\atomvm.c" />
|
||||
<ClCompile Include="main.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="atomthreads">
|
||||
<UniqueIdentifier>{d05cbb5a-256f-4127-bd5b-c3bd69b3672c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="port">
|
||||
<UniqueIdentifier>{f30700d8-652d-477c-a4f2-d23e7784de50}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="atomvm">
|
||||
<UniqueIdentifier>{a4f641bc-296d-4546-a831-2e1d0d7e9242}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\kernel\atom.h">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\kernel\atommutex.h">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\kernel\atomqueue.h">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\kernel\atomsem.h">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\kernel\atomtimer.h">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\atomport.h">
|
||||
<Filter>port</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\atomport-tests.h">
|
||||
<Filter>port</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\atomuser.h">
|
||||
<Filter>port</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\atomvm.h">
|
||||
<Filter>atomvm</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\kernel\atomkernel.c">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\kernel\atommutex.c">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\kernel\atomqueue.c">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\kernel\atomsem.c">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\kernel\atomtimer.c">
|
||||
<Filter>atomthreads</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\atomport.c">
|
||||
<Filter>port</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.c" />
|
||||
<ClCompile Include="..\atomvm.c">
|
||||
<Filter>atomvm</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2010,Kelvin Lawson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __ATOM_USER_H__
|
||||
#define __ATOM_USER_H__
|
||||
|
||||
|
||||
/* Portable uint8_t and friends not available from stdint.h on this platform */
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#define SYSTEM_MEMALIGN sizeof (unsigned int)
|
||||
|
||||
|
||||
typedef unsigned int uintptr_t ;
|
||||
typedef int intptr_t ;
|
||||
typedef unsigned int uint32_t ;
|
||||
typedef unsigned short uint16_t ;
|
||||
typedef unsigned char uint8_t ;
|
||||
typedef int int32_t ;
|
||||
typedef short int16_t ;
|
||||
typedef char int8_t ;
|
||||
|
||||
|
||||
/**
|
||||
* Architecture-specific types.
|
||||
* Most of these are available from stdint.h on this platform, which is
|
||||
* included above.
|
||||
*/
|
||||
#define POINTER void *
|
||||
|
||||
|
||||
#define ATOM_TLS HATOMVM_CONTEXT context ;
|
||||
|
||||
|
||||
#endif /* __ATOM_USER_H__ */
|
||||
+5
-19
@@ -1,31 +1,17 @@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Library: Atomthreads CortexM3 Port
|
||||
Library: Atomthreads ARM Cortex M Port
|
||||
Author: Natie van Rooyen <natie@navaro.nl>
|
||||
License: BSD Revised
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
ARM CortexM3 PORT
|
||||
ARM Cortex M PORT
|
||||
|
||||
This folder contains a port of the Atomthreads real time kernel for the
|
||||
ARM CortexM3 processor architecture.
|
||||
ARM CortexM type processor architecture. This port was tested on the
|
||||
Cortex M3 and the Cortex M4.
|
||||
|
||||
To Use:
|
||||
|
||||
1. Install the "pendSV_Handler" and "tick_Handler" implemented in the file
|
||||
"atomport_arm.asm" in your platforms interrupt vectors.
|
||||
|
||||
2. Complete the function "archTickInit()" implemented in "atomport.c" to
|
||||
initialize your platforms timer tick interrupt. If you use the build in
|
||||
SysTick of the CortexM3 you also have to add code here to start it.
|
||||
|
||||
3. If required, add code to acknowledge your timer hardware's interrupt in
|
||||
the function "archTickHandler()" also implemented in "atomport.c".
|
||||
|
||||
4. During your platform initialization call the function "archTickInit()"
|
||||
exported from "atomport_private.h" to initialize the CortexM3
|
||||
"PendSV_Handler".
|
||||
|
||||
5. After your platforms c-runtime initialization has completed, start
|
||||
Atomthreads from your runtime's "main()" function.
|
||||
See the example project in the "platforms/qemu_lm3s" directory.
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
*/
|
||||
typedef void * SYSCONTEXT ;
|
||||
|
||||
extern void contextInit (void) ;
|
||||
extern void contextSwitch (SYSCONTEXT* save_context, SYSCONTEXT* new_context) ;
|
||||
extern void contextStart (SYSCONTEXT* context) ;
|
||||
extern void contextEnableInterrupts (void) ;
|
||||
@@ -93,7 +92,11 @@ archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_point)(u
|
||||
|
||||
*stack_ptr = 0x01000000L; //-- xPSR
|
||||
stack_ptr--;
|
||||
*stack_ptr = ((uint32_t)thread_shell) | 1; //-- Entry Point (1 for THUMB mode)
|
||||
#ifndef PLATFORM_QEMU_LM3S_HACK
|
||||
*stack_ptr = ((uint32_t)thread_shell) | 1 ; //-- Entry Point (1 for THUMB mode)
|
||||
#else
|
||||
*stack_ptr = ((uint32_t)thread_shell) & ~1 ; //-- Entry Point (1 for THUMB mode)
|
||||
#endif
|
||||
stack_ptr--;
|
||||
*stack_ptr = ((uint32_t)/*exit*/0) | 1; //-- R14 (LR) (1 for THUMB mode)
|
||||
stack_ptr--;
|
||||
@@ -151,43 +154,3 @@ archContextSwitch (ATOM_TCB * p_sp_old, ATOM_TCB * p_sp_new)
|
||||
{
|
||||
contextSwitch (&p_sp_old->sp_save_ptr, &p_sp_new->sp_save_ptr) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \b archTimerTickIrqHandler
|
||||
*
|
||||
* System timer tick interrupt handler.
|
||||
*
|
||||
*/
|
||||
void
|
||||
archTickHandler (void)
|
||||
{
|
||||
atomIntEnter();
|
||||
|
||||
/* Call the OS system tick handler */
|
||||
atomTimerTick();
|
||||
|
||||
/* ack the interrupt if needed */
|
||||
/* ... */
|
||||
|
||||
/* Call the interrupt exit routine */
|
||||
atomIntExit(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b archTickInit
|
||||
*
|
||||
* System timer initialization.
|
||||
*
|
||||
*/
|
||||
void
|
||||
archTickInit (void)
|
||||
{
|
||||
/* Initialize NVIC PendSV */
|
||||
contextInit () ;
|
||||
|
||||
/* Initializa Timer Hardware */
|
||||
/* ... */
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,25 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define SYSTEM_TICKS_PER_SEC 100
|
||||
#define SYSTEM_TICKS_PER_SEC 100
|
||||
|
||||
/**
|
||||
* Definition of NULL.
|
||||
* If stddef.h is available on the platform it is simplest to include it
|
||||
* from this header, otherwise define below.
|
||||
*/
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)(0))
|
||||
#endif
|
||||
|
||||
/* Size of each stack entry / stack alignment size (e.g. 32 bits) */
|
||||
#define STACK_ALIGN_SIZE sizeof(unsigned int)
|
||||
|
||||
/**
|
||||
* Architecture-specific types.
|
||||
* Most of these are available from types.h on this platform, which is
|
||||
* included above.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,15 +58,18 @@
|
||||
* Most of these are available from types.h on this platform, which is
|
||||
* included above.
|
||||
*/
|
||||
#ifndef POINTER
|
||||
#define POINTER void *
|
||||
#endif
|
||||
|
||||
/* *
|
||||
*
|
||||
* Functions defined in atomport_arm.asm
|
||||
*
|
||||
*/
|
||||
extern uint32_t contextEnterCritical (void) ;
|
||||
extern void contextExitCritical (uint32_t posture) ;
|
||||
extern void contextInit (void) ;
|
||||
extern uint32_t contextEnterCritical (void) ;
|
||||
extern void contextExitCritical (uint32_t posture) ;
|
||||
|
||||
|
||||
/* Critical region protection */
|
||||
@@ -57,3 +78,4 @@ extern void contextExitCritical (uint32_t posture) ;
|
||||
#define CRITICAL_END() contextExitCritical(__atom_critical)
|
||||
|
||||
#endif /* __ATOM_PORT_H__ */
|
||||
|
||||
|
||||
@@ -32,7 +32,10 @@
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
extern void archTickHandler (void) ;
|
||||
extern void archTickInit (void) ;
|
||||
extern void archPendSVHandler (void) ;
|
||||
extern void archTickHandler (void) ;
|
||||
|
||||
/* required interface */
|
||||
extern void __context_tick_handler (void) ;
|
||||
|
||||
#endif /* __ATOM_PORT_PRIVATE_H__ */
|
||||
|
||||
+71
-11
@@ -28,29 +28,41 @@
|
||||
*/
|
||||
|
||||
|
||||
.global archPendSVHandler
|
||||
.global archTickHandler
|
||||
.global contextInit
|
||||
.global contextSwitch
|
||||
.global contextStart
|
||||
.global contextEnableInterrupts
|
||||
.global contextEnterCritical
|
||||
.global contextExitCritical
|
||||
.global pendSV_Handler
|
||||
.global tick_Handler
|
||||
|
||||
.global archTickHandler
|
||||
|
||||
.extern __context_tick_handler
|
||||
|
||||
|
||||
/**/
|
||||
.equ NVIC_INT_CTRL, 0xE000ED04 // Interrupt control state register
|
||||
.equ NVIC_PENDSVSET, 0x10000000 // Value to trigger PendSV exception
|
||||
.equ NVIC_PR_12_15_ADDR, 0xE000ED20 // System Handlers 12-15 Priority Register Address
|
||||
.equ NVIC_PENDS_VPRIORITY, 0x00FF0000 // PendSV priority is minimal (0xFF)
|
||||
#ifdef PLATFORM_QEMU_LM3S_HACK
|
||||
.equ NVIC_PENDS_VPRIORITY, 0x00F00000 // PendSV priority is minimal (0xFF -- 0x00FF0000)
|
||||
#else
|
||||
.equ NVIC_PENDS_VPRIORITY, 0x00FF0000 // PendSV priority is minimal (0xFF -- 0x00FF0000)
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_QEMU_LM3S_HACK
|
||||
.equ NVIC_ISER, 0xE000E100
|
||||
.equ NVIC_ICER, 0xE000E180
|
||||
.equ NVIC_I_TIMER0, 0x80000
|
||||
#endif
|
||||
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
.thumb
|
||||
|
||||
|
||||
/**
|
||||
* \b contextInit
|
||||
*
|
||||
@@ -128,7 +140,13 @@ contextStart:
|
||||
* @return None
|
||||
*/
|
||||
contextEnableInterrupts:
|
||||
#ifndef PLATFORM_QEMU_LM3S_HACK
|
||||
CPSIE i
|
||||
#else
|
||||
LDR r1, =NVIC_ISER
|
||||
LDR r0, =NVIC_I_TIMER0
|
||||
STR r0, [r1]
|
||||
#endif
|
||||
BX lr
|
||||
|
||||
|
||||
@@ -142,10 +160,14 @@ contextEnableInterrupts:
|
||||
* @return None
|
||||
*/
|
||||
contextExitCritical:
|
||||
#ifndef PLATFORM_QEMU_LM3S_HACK
|
||||
MSR PRIMASK, r0
|
||||
#else
|
||||
LDR r1, =NVIC_ISER
|
||||
STR r0, [r1]
|
||||
#endif
|
||||
BX lr
|
||||
|
||||
|
||||
/**
|
||||
* \b contextEnterCritical
|
||||
*
|
||||
@@ -154,19 +176,33 @@ contextExitCritical:
|
||||
* @return Current interrupt posture
|
||||
*/
|
||||
contextEnterCritical:
|
||||
#ifndef PLATFORM_QEMU_LM3S_HACK
|
||||
MRS r0, PRIMASK
|
||||
CPSID i
|
||||
#else
|
||||
LDR r1, =NVIC_ISER
|
||||
LDR r0, [r1]
|
||||
LDR r1, =NVIC_ICER
|
||||
STR r0, [r1]
|
||||
#endif
|
||||
BX lr
|
||||
|
||||
/**
|
||||
* \b PendSV_Handler
|
||||
* \b archPendSVHandler
|
||||
*
|
||||
* CortexM3 PendSV_Handler. Switch context to a new stack.
|
||||
* CortexM3 archPendSVHandler. Switch context to a new stack.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
pendSV_Handler:
|
||||
.thumb_func
|
||||
archPendSVHandler:
|
||||
#ifndef PLATFORM_QEMU_LM3S_HACK
|
||||
CPSID i // Disable core int
|
||||
#else
|
||||
LDR r0, =NVIC_ICER
|
||||
LDR r1, =NVIC_I_TIMER0
|
||||
STR r1, [r0]
|
||||
#endif
|
||||
|
||||
LDR r1, =context_save_stack_ptr
|
||||
LDR r0, [r1] // Load old (current) stack pointer address
|
||||
@@ -192,28 +228,52 @@ pendsv_handler_new_stack:
|
||||
MSR PSP, r2 // Mov new stack point to PSP
|
||||
|
||||
pendsv_handler_exit:
|
||||
#ifndef PLATFORM_QEMU_LM3S_HACK
|
||||
CPSIE i // Enable core int
|
||||
#else
|
||||
LDR r0, =NVIC_ISER
|
||||
LDR r1, =NVIC_I_TIMER0
|
||||
STR r1, [r0]
|
||||
#endif
|
||||
|
||||
ORR lr, lr, #0x04 // Ensure exception return uses process stack
|
||||
BX lr // Exit interrupt
|
||||
|
||||
|
||||
/**
|
||||
* \b Tick_Handler
|
||||
* \b archTickHandler
|
||||
*
|
||||
* System timer tick interrupt handler.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
tick_Handler:
|
||||
.thumb_func
|
||||
archTickHandler:
|
||||
PUSH {r4-r11, lr}
|
||||
|
||||
#ifndef PLATFORM_QEMU_LM3S_HACK
|
||||
cpsid I // Disable core int
|
||||
BL archTickHandler
|
||||
#else
|
||||
LDR r0, =NVIC_ICER
|
||||
LDR r1, =NVIC_I_TIMER0
|
||||
STR r1, [r0]
|
||||
#endif
|
||||
|
||||
BL __context_tick_handler
|
||||
|
||||
#ifndef PLATFORM_QEMU_LM3S_HACK
|
||||
cpsie I // Enable core int
|
||||
#else
|
||||
LDR r0, =NVIC_ISER
|
||||
LDR r1, =NVIC_I_TIMER0
|
||||
STR r1, [r0]
|
||||
#endif
|
||||
|
||||
POP {r4-r11, pc}
|
||||
|
||||
|
||||
/**/
|
||||
.data
|
||||
context_new_stack_ptr: .long 0x00000000
|
||||
context_save_stack_ptr: .long 0x00000000
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#ifndef __TYPES_H__
|
||||
#define __TYPES_H__
|
||||
|
||||
#ifndef _STDINT_H
|
||||
typedef unsigned int uintptr_t ;
|
||||
typedef int intptr_t ;
|
||||
typedef unsigned long long uint64_t ;
|
||||
@@ -39,6 +40,26 @@ typedef unsigned char uint8_t ;
|
||||
typedef int int32_t ;
|
||||
typedef short int16_t ;
|
||||
typedef char int8_t ;
|
||||
#endif
|
||||
|
||||
#ifndef OFFSETOF
|
||||
#define OFFSETOF(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
|
||||
#ifndef INLINE
|
||||
#define INLINE __inline
|
||||
#endif
|
||||
|
||||
/* IO definitions (access restrictions to peripheral registers) */
|
||||
#ifndef __I
|
||||
#define __I volatile /*!< defines 'read only' permissions */
|
||||
#endif
|
||||
#ifndef __O
|
||||
#define __O volatile /*!< defines 'write only' permissions */
|
||||
#endif
|
||||
#ifndef __IO
|
||||
#define __IO volatile /*!< defines 'read / write' permissions */
|
||||
#endif
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user