mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-01-18 13:53:16 +01:00
Initial realease.
This commit is contained in:
@@ -7,9 +7,9 @@ License: BSD Revised
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
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 VM is
|
||||
for the evaluation of Real Time Operating Systems (like atomthreads) and
|
||||
the development and testing of modules for this Real Time Operating System
|
||||
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.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
@@ -21,19 +21,20 @@ directory and the
|
||||
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 well on single core
|
||||
systems.
|
||||
Atomvm was designed for multi core systems but also runs fine on any single
|
||||
core system.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
RUNNING THE TESTS
|
||||
|
||||
The test, main.c, was designed to stress the vm as opposed to testing the RTOS.
|
||||
However, the test can also run the unit tests if desired by using the
|
||||
precompiled directive UNIT_TESTS and linking in the desired unit 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.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
FINALLY
|
||||
|
||||
Good luck, but most of all, have fun!
|
||||
Good luck, but most of all, have fun!!
|
||||
|
||||
@@ -30,31 +30,31 @@
|
||||
#include "atomvm.h"
|
||||
#include <string.h>
|
||||
|
||||
#define CONTEXT_VM (CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS)
|
||||
#define CONTEXT_VM (CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS)
|
||||
|
||||
#define ATOMVM_ATOMVM_PERF_COUNTER(patomvm, counter) (InterlockedIncrement(&patomvm->perf_counters.counter))
|
||||
#define ATOMVM_ATOMVM_PERF_COUNTER(patomvm, counter) (InterlockedIncrement(&patomvm->perf_counters.counter))
|
||||
|
||||
/* Data types */
|
||||
|
||||
/* Forward declarations */
|
||||
typedef struct ATOMVM_S * PATOMVM ;
|
||||
typedef struct ATOMVM_CALLBACK_S * PATOMVM_CALLBACK ;
|
||||
typedef struct ATOMVM_CONTEXT_S * PATOMVM_CONTEXT ;
|
||||
typedef struct ATOMVM_S * PATOMVM ;
|
||||
typedef struct ATOMVM_CALLBACK_S * PATOMVM_CALLBACK ;
|
||||
typedef struct ATOMVM_CONTEXT_S * PATOMVM_CONTEXT ;
|
||||
|
||||
typedef uint32_t (*ATOMVM_CALLBACK_F) (PATOMVM, PATOMVM_CALLBACK) ;
|
||||
|
||||
typedef struct ATOMVM_CALLBACK_S {
|
||||
|
||||
/* Address of callback function */
|
||||
volatile ATOMVM_CALLBACK_F callback ;
|
||||
volatile ATOMVM_CALLBACK_F callback ;
|
||||
|
||||
/* Synchronization lock, the virtual machine will be suspended during
|
||||
the callback. Regular WIN32 synchronization methods cant be used
|
||||
because SuspendThread() is used on the vm thread. */
|
||||
volatile uint32_t lock ;
|
||||
volatile uint32_t lock ;
|
||||
|
||||
/* Result of the call */
|
||||
volatile uint32_t result ;
|
||||
volatile uint32_t result ;
|
||||
|
||||
} ATOMVM_CALLBACK, *PATOMVM_CALLBACK ;
|
||||
|
||||
@@ -63,24 +63,24 @@ typedef struct ATOMVM_CALLBACK_S {
|
||||
that take as parameter a pointer to a ATOMVM_CONTEXT to operate on */
|
||||
typedef struct ATOMVM_CALLBACK_CONTEXT_S {
|
||||
|
||||
ATOMVM_CALLBACK callback ;
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
/* Context the callback function will operate on */
|
||||
volatile PATOMVM_CONTEXT pcontext ;
|
||||
volatile PATOMVM_CONTEXT pcontext ;
|
||||
|
||||
} ATOMVM_CALLBACK_CONTEXT, *PATOMVM_CALLBACK_CONTEXT ;
|
||||
|
||||
typedef struct ATOMVM_PERF_COUNTERS_S {
|
||||
|
||||
/* Number of interrupt requests */
|
||||
uint32_t int_request ;
|
||||
uint32_t int_request ;
|
||||
|
||||
/* Number of service calls (context switches and
|
||||
context init from atom virtual machime) */
|
||||
uint32_t service_call ;
|
||||
uint32_t service_call ;
|
||||
|
||||
/* Total number of context switches */
|
||||
uint32_t context_switch ;
|
||||
uint32_t context_switch ;
|
||||
|
||||
} ATOMVM_PERF_COUNTERS, *PATOMVM_PERF_COUNTERS ;
|
||||
|
||||
@@ -90,14 +90,14 @@ typedef struct ATOMVM_CONTEXT_S {
|
||||
|
||||
/* A virtual machine thread context. These are saved and restored
|
||||
during context initialization and context switches */
|
||||
CONTEXT context ;
|
||||
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 ;
|
||||
volatile uint32_t critical_count ;
|
||||
|
||||
} ATOMVM_CONTEXT, *PATOMVM_CONTEXT ;
|
||||
|
||||
@@ -106,40 +106,40 @@ by a call to atomvmCtrlInit(). */
|
||||
typedef struct ATOMVM_S {
|
||||
|
||||
/* Thread the virtual machine will run in */
|
||||
HANDLE vm_thread ;
|
||||
HANDLE vm_thread ;
|
||||
|
||||
/* Handles to events and mutexes used for synchronization */
|
||||
HANDLE atomvm_call ;
|
||||
HANDLE atomvm_int ;
|
||||
HANDLE atomvm_int_complete ;
|
||||
HANDLE atomvm_close ;
|
||||
HANDLE atomvm_call ;
|
||||
HANDLE atomvm_int ;
|
||||
HANDLE atomvm_int_complete ;
|
||||
HANDLE atomvm_close ;
|
||||
|
||||
/* next ISR */
|
||||
volatile void (*isr)(void) ;
|
||||
volatile void (*isr)(void) ;
|
||||
/* True if in an ISR */
|
||||
volatile uint32_t status_isr ;
|
||||
volatile uint32_t status_isr ;
|
||||
|
||||
/* The current context that was scheduled by a call
|
||||
to atomvmContextSwitch() */
|
||||
PATOMVM_CONTEXT current_context ;
|
||||
PATOMVM_CONTEXT current_context ;
|
||||
|
||||
/* Service call address, synchronization lock, parameters
|
||||
and, return value for the current service call */
|
||||
PATOMVM_CALLBACK 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) */
|
||||
ATOMVM_CONTEXT atom_init_context ;
|
||||
ATOMVM_CONTEXT atom_init_context ;
|
||||
|
||||
/* Performance counters */
|
||||
volatile ATOMVM_PERF_COUNTERS perf_counters ;
|
||||
volatile ATOMVM_PERF_COUNTERS perf_counters ;
|
||||
|
||||
} ATOMVM, *PATOMVM ;
|
||||
|
||||
|
||||
/* Forward declaration for the atom virtual machine thread */
|
||||
static DWORD WINAPI vm_thread (LPVOID lpParameter) ;
|
||||
static DWORD WINAPI vm_thread (LPVOID lpParameter) ;
|
||||
|
||||
|
||||
/**
|
||||
@@ -202,11 +202,11 @@ atomvmCtrlInit (HATOMVM *atomvm)
|
||||
void
|
||||
atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
HANDLE wait[3] ;
|
||||
uint32_t res ;
|
||||
uint32_t wait_object ;
|
||||
PATOMVM_CALLBACK pservice_call ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
HANDLE wait[3] ;
|
||||
uint32_t res ;
|
||||
uint32_t wait_object ;
|
||||
PATOMVM_CALLBACK service_call ;
|
||||
|
||||
ResumeThread (patomvm->vm_thread) ;
|
||||
|
||||
@@ -222,9 +222,8 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
|
||||
ATOMVM_ATOMVM_PERF_COUNTER(patomvm, service_call) ;
|
||||
|
||||
//InterlockedExchange ((volatile uint32_t*)&pservice_call, (uint32_t)patomvm->service_call) ;
|
||||
pservice_call = patomvm->service_call ;
|
||||
while (!pservice_call->lock) {
|
||||
service_call = patomvm->service_call ;
|
||||
while (!service_call->lock) {
|
||||
SwitchToThread () ;
|
||||
}
|
||||
|
||||
@@ -236,8 +235,8 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
is stopped before executing the next instruction. */
|
||||
FlushProcessWriteBuffers ();
|
||||
#endif
|
||||
InterlockedExchange (&pservice_call->result, pservice_call->callback (patomvm, pservice_call)) ;
|
||||
InterlockedExchange (&pservice_call->lock, 0) ;
|
||||
InterlockedExchange (&service_call->result, service_call->callback (patomvm, service_call)) ;
|
||||
InterlockedExchange (&service_call->lock, 0) ;
|
||||
ResetEvent (patomvm->atomvm_call) ;
|
||||
res = ResumeThread (patomvm->vm_thread) ;
|
||||
ATOMVM_ASSERT(res == 1 , _T("ResumeThread failed")) ;
|
||||
@@ -313,8 +312,8 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
void
|
||||
atomvmCtrlClose (HATOMVM atomvm)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
DWORD code ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
DWORD code ;
|
||||
|
||||
__atomvmClose () ;
|
||||
|
||||
@@ -392,8 +391,8 @@ invokeCallback (PATOMVM patomvm, ATOMVM_CALLBACK_F callback, PATOMVM_CALLBACK se
|
||||
int32_t
|
||||
atomvmExitCritical (HATOMVM atomvm)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
int32_t count = 0;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
int32_t count = 0;
|
||||
|
||||
if (patomvm->status_isr == 0) {
|
||||
count = InterlockedDecrement (&patomvm->current_context->critical_count) ;
|
||||
@@ -421,8 +420,8 @@ atomvmExitCritical (HATOMVM atomvm)
|
||||
int32_t
|
||||
atomvmEnterCritical (HATOMVM atomvm)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
int32_t count = 0 ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
int32_t count = 0 ;
|
||||
|
||||
if (patomvm->status_isr == 0) {
|
||||
count = InterlockedIncrement (&patomvm->current_context->critical_count) ;
|
||||
@@ -452,7 +451,7 @@ atomvmEnterCritical (HATOMVM atomvm)
|
||||
void
|
||||
atomvmCtrlIntRequest (HATOMVM atomvm, uint32_t isr)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
|
||||
while (InterlockedCompareExchange ((volatile uint32_t *)&patomvm->isr, isr, 0) == 0) {
|
||||
SwitchToThread() ;
|
||||
@@ -477,8 +476,8 @@ atomvmCtrlIntRequest (HATOMVM atomvm, uint32_t isr)
|
||||
uint32_t
|
||||
callbackContextCreate (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
PATOMVM_CALLBACK_CONTEXT context_switch = (PATOMVM_CALLBACK_CONTEXT)callback;
|
||||
CONTEXT * pcontext = &context_switch->pcontext->context ;
|
||||
PATOMVM_CALLBACK_CONTEXT context_switch = (PATOMVM_CALLBACK_CONTEXT)callback;
|
||||
CONTEXT * pcontext = &context_switch->pcontext->context ;
|
||||
|
||||
pcontext->ContextFlags = CONTEXT_VM ;
|
||||
|
||||
@@ -505,11 +504,11 @@ callbackContextCreate (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
uint32_t
|
||||
atomvmContextCreate (HATOMVM atomvm, HATOMVM_CONTEXT* atomvm_context, uint32_t stack, uint32_t entry)
|
||||
{
|
||||
uint32_t res ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
PATOMVM_CONTEXT new_context = (PATOMVM_CONTEXT)malloc (sizeof(ATOMVM_CONTEXT)) ;
|
||||
CONTEXT* pcontext = &new_context->context ;
|
||||
ATOMVM_CALLBACK_CONTEXT context_init ;
|
||||
uint32_t res ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
PATOMVM_CONTEXT new_context = (PATOMVM_CONTEXT)malloc (sizeof(ATOMVM_CONTEXT)) ;
|
||||
CONTEXT* pcontext = &new_context->context ;
|
||||
ATOMVM_CALLBACK_CONTEXT context_init ;
|
||||
|
||||
context_init.pcontext = new_context ;
|
||||
|
||||
@@ -543,10 +542,10 @@ atomvmContextCreate (HATOMVM atomvm, HATOMVM_CONTEXT* atomvm_context, uint32_t s
|
||||
uint32_t
|
||||
callbackContextSwitch (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
uint32_t res1 ;
|
||||
uint32_t res2 ;
|
||||
PATOMVM_CALLBACK_CONTEXT context_switch = (PATOMVM_CALLBACK_CONTEXT)callback ;
|
||||
CONTEXT* pnew_context = &context_switch->pcontext->context ;
|
||||
uint32_t res1 ;
|
||||
uint32_t res2 ;
|
||||
PATOMVM_CALLBACK_CONTEXT context_switch = (PATOMVM_CALLBACK_CONTEXT)callback ;
|
||||
CONTEXT* pnew_context = &context_switch->pcontext->context ;
|
||||
|
||||
ATOMVM_ATOMVM_PERF_COUNTER(patomvm, context_switch) ;
|
||||
|
||||
@@ -576,8 +575,8 @@ callbackContextSwitch (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
uint32_t
|
||||
atomvmContextSwitch (HATOMVM atomvm, HATOMVM_CONTEXT new_context)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
ATOMVM_CALLBACK_CONTEXT context_switch ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
ATOMVM_CALLBACK_CONTEXT context_switch ;
|
||||
|
||||
context_switch.pcontext = (PATOMVM_CONTEXT) new_context ;
|
||||
|
||||
@@ -599,7 +598,7 @@ atomvmContextSwitch (HATOMVM atomvm, HATOMVM_CONTEXT new_context)
|
||||
void
|
||||
atomvmContextDesrtroy (HATOMVM atomvm, HATOMVM_CONTEXT context)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
|
||||
ATOMVM_ASSERT(patomvm->current_context != (PATOMVM_CONTEXT)context,
|
||||
_T("atomvmContextDesrtroy failed")) ;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define ATOMVM_ASSERT(x, msg) _ASSERT(x)
|
||||
#define ATOMVM_ASSERT(x, msg) _ASSERT(x)
|
||||
#else
|
||||
#define ATOMVM_ASSERT(x, msg)
|
||||
#endif
|
||||
@@ -44,29 +44,28 @@
|
||||
|
||||
/* This is an opaque handle to an instance of an atomvm created
|
||||
by a call to atomvmCtrlInit() */
|
||||
typedef struct ATOMVM* HATOMVM ;
|
||||
typedef struct ATOMVM* HATOMVM ;
|
||||
|
||||
/* This is an opaque handle to an atomvm context created
|
||||
by a call to atomvmContextCreate() */
|
||||
typedef struct ATOMVM_CONTEXT* HATOMVM_CONTEXT ;
|
||||
typedef struct ATOMVM_CONTEXT* HATOMVM_CONTEXT ;
|
||||
|
||||
|
||||
/* Function prototypes used for controlling the atom virtual machine */
|
||||
extern uint32_t atomvmCtrlInit (HATOMVM* atomvm) ;
|
||||
extern void atomvmCtrlRun (HATOMVM atomvm, uint32_t flags) ;
|
||||
extern void atomvmCtrlIntRequest (HATOMVM atomvm, uintptr_t isr) ;
|
||||
extern void atomvmCtrlClose (HATOMVM atomvm) ;
|
||||
extern uint32_t atomvmCtrlInit (HATOMVM* atomvm) ;
|
||||
extern void atomvmCtrlRun (HATOMVM atomvm, uint32_t flags) ;
|
||||
extern void atomvmCtrlIntRequest (HATOMVM atomvm, uintptr_t isr) ;
|
||||
extern void atomvmCtrlClose (HATOMVM atomvm) ;
|
||||
|
||||
/* Function prototypes for use by the atom virtual machine */
|
||||
extern int32_t atomvmExitCritical (HATOMVM atomvm) ;
|
||||
extern int32_t atomvmEnterCritical (HATOMVM atomvm) ;
|
||||
extern uint32_t atomvmContextCreate (HATOMVM atomvm, HATOMVM_CONTEXT* context, uint32_t stack, uint32_t entry) ;
|
||||
extern uint32_t atomvmContextSwitch (HATOMVM atomvm, HATOMVM_CONTEXT new_context) ;
|
||||
extern void atomvmContextDesrtroy (HATOMVM atomvm, HATOMVM_CONTEXT context) ;
|
||||
extern int32_t atomvmExitCritical (HATOMVM atomvm) ;
|
||||
extern int32_t atomvmEnterCritical (HATOMVM atomvm) ;
|
||||
extern uint32_t atomvmContextCreate (HATOMVM atomvm, HATOMVM_CONTEXT* context, uint32_t stack, uint32_t entry) ;
|
||||
extern uint32_t atomvmContextSwitch (HATOMVM atomvm, HATOMVM_CONTEXT new_context) ;
|
||||
extern void atomvmContextDesrtroy (HATOMVM atomvm, HATOMVM_CONTEXT context) ;
|
||||
|
||||
/* Function prototypes to be implemted in the atom virtual machine */
|
||||
extern void __atomvmReset (void) ;
|
||||
extern void __atomvmClose (void) ;
|
||||
extern void __atomvmReset (void) ;
|
||||
extern void __atomvmClose (void) ;
|
||||
|
||||
|
||||
#endif /* __ATOMVM_H__ */
|
||||
|
||||
Reference in New Issue
Block a user