mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-02-09 08:23:21 +01:00
ARM: Add comments describing port operation.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Natie van Rooyen. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@@ -31,23 +31,40 @@
|
||||
#include "atomport.h"
|
||||
|
||||
|
||||
/**
|
||||
* Functions defined in atomport_s.s
|
||||
*/
|
||||
typedef void * SYSCONTEXT ;
|
||||
extern void contextSwitch (SYSCONTEXT* save_context, SYSCONTEXT* new_context) ;
|
||||
extern void contextStart (SYSCONTEXT* context) ;
|
||||
extern void contextEnableInterrupts (void) ;
|
||||
/** Functions defined in atomport_s.s */
|
||||
typedef void * SYSCONTEXT;
|
||||
extern void contextSwitch (SYSCONTEXT* save_context, SYSCONTEXT* new_context);
|
||||
extern void contextStart (SYSCONTEXT* context);
|
||||
extern void contextEnableInterrupts (void);
|
||||
|
||||
|
||||
/** Forward declarations */
|
||||
static void thread_shell (void);
|
||||
|
||||
|
||||
/**
|
||||
* \b thread_shell
|
||||
*
|
||||
* Documented in Atomthreads.
|
||||
* Shell routine which is used to call all thread entry points.
|
||||
*
|
||||
* This routine is called whenever a new thread is starting, and
|
||||
* provides a simple wrapper around the thread entry point that
|
||||
* allows us to carry out any actions we want to do on thread's
|
||||
* first starting up, or returning after completion.
|
||||
*
|
||||
* We mainly just want to make sure interrupts are enabled when a
|
||||
* thread is run for the first time. This can be done via stack
|
||||
* restores when threads are first run, but it's handy to have this
|
||||
* wrapper anyway to run some common code if threads run to
|
||||
* completion.
|
||||
*
|
||||
* A thread shell is also handy for providing port users with a place
|
||||
* to do any other initialisation that must be done for each thread
|
||||
* (e.g. opening stdio files etc).
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void
|
||||
thread_shell (void)
|
||||
static void thread_shell (void)
|
||||
{
|
||||
ATOM_TCB *curr_tcb;
|
||||
|
||||
@@ -58,7 +75,7 @@ thread_shell (void)
|
||||
* Enable interrupts - these will not be enabled when a thread
|
||||
* is first restored.
|
||||
*/
|
||||
contextEnableInterrupts () ;
|
||||
contextEnableInterrupts ();
|
||||
|
||||
/* Call the thread entry point */
|
||||
if (curr_tcb && curr_tcb->entry_point)
|
||||
@@ -69,47 +86,76 @@ thread_shell (void)
|
||||
/* Thread has run to completion: remove it from the ready list */
|
||||
curr_tcb->suspended = TRUE;
|
||||
atomSched (FALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \b archThreadContextInit
|
||||
*
|
||||
* Documented in Atomthreads.
|
||||
* Architecture-specific thread context initialisation routine.
|
||||
*
|
||||
* This function must set up a thread's context ready for restoring
|
||||
* and running the thread via archFirstThreadRestore() or
|
||||
* archContextSwitch().
|
||||
*
|
||||
* The layout required to fill the correct register values is
|
||||
* described in archContextSwitch(). Note that not all registers
|
||||
* are restored by archContextSwitch() and archFirstThreadRestore()
|
||||
* as this port takes advantage of the fact that not all registers
|
||||
* must be stored by ARM gcc C subroutines. This means that we don't
|
||||
* provide start values for those registers, as they are "don't cares".
|
||||
*
|
||||
* @param[in] tcb_ptr Pointer to the TCB of the thread being created
|
||||
* @param[in] stack_top Pointer to the top of the new thread's stack
|
||||
* @param[in] entry_point Pointer to the thread entry point function
|
||||
* @param[in] entry_param Parameter to be passed to the thread entry point
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void
|
||||
archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_point)(uint32_t), uint32_t entry_param)
|
||||
void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_point)(uint32_t), uint32_t entry_param)
|
||||
{
|
||||
uint32_t * stack_ptr ;
|
||||
uint32_t *stack_ptr;
|
||||
|
||||
tcb_ptr->sp_save_ptr = stack_top;
|
||||
tcb_ptr->entry_param = entry_param ;
|
||||
tcb_ptr->entry_point = entry_point ;
|
||||
/** Start at stack top */
|
||||
tcb_ptr->sp_save_ptr = stack_ptr = stack_top;
|
||||
|
||||
stack_ptr = (uint32_t *)stack_top; //-- Load stack pointer
|
||||
/**
|
||||
* After restoring all of the context registers, the thread restore
|
||||
* routines will return to the address of the calling routine on the
|
||||
* stack. In this case (the first time a thread is run) we "return"
|
||||
* to the entry point for the thread. That is, we store the thread
|
||||
* entry point in the place that return will look for the return
|
||||
* address: the stack.
|
||||
*
|
||||
* Note that we are using the thread_shell() routine to start all
|
||||
* threads, so we actually store the address of thread_shell()
|
||||
* here. Other ports may store the real thread entry point here
|
||||
* and call it directly from the thread restore routines.
|
||||
*
|
||||
* Because we are filling the stack from top to bottom, this goes
|
||||
* on the stack first (at the top).
|
||||
*/
|
||||
*stack_ptr-- = (uint32_t)thread_shell;
|
||||
|
||||
*stack_ptr = ( uint32_t ) thread_shell ;
|
||||
stack_ptr--;
|
||||
/**
|
||||
* Store starting register values for R4-R11
|
||||
*/
|
||||
*stack_ptr-- = (uint32_t) 0x00001111; /* R11 */
|
||||
*stack_ptr-- = (uint32_t) 0x00001010; /* R10 */
|
||||
*stack_ptr-- = (uint32_t) 0x00000909; /* R9 */
|
||||
*stack_ptr-- = (uint32_t) 0x00000808; /* R8 */
|
||||
*stack_ptr-- = (uint32_t) 0x00000707; /* R7 */
|
||||
*stack_ptr-- = (uint32_t) 0x00000606; /* R6 */
|
||||
*stack_ptr-- = (uint32_t) 0x00000505; /* R5 */
|
||||
*stack_ptr = (uint32_t) 0x00000404; /* R4 */
|
||||
|
||||
*stack_ptr = ( uint32_t ) 0x00001111; /* R11 */
|
||||
stack_ptr--;
|
||||
*stack_ptr = ( uint32_t ) 0x00001010; /* R10 */
|
||||
stack_ptr--;
|
||||
*stack_ptr = ( uint32_t ) 0x00000909; /* R9 */
|
||||
stack_ptr--;
|
||||
*stack_ptr = ( uint32_t ) 0x00000808; /* R8 */
|
||||
stack_ptr--;
|
||||
*stack_ptr = ( uint32_t ) 0x00000707; /* R7 */
|
||||
stack_ptr--;
|
||||
*stack_ptr = ( uint32_t ) 0x00000606; /* R6 */
|
||||
stack_ptr--;
|
||||
*stack_ptr = ( uint32_t ) 0x00000505; /* R5 */
|
||||
stack_ptr--;
|
||||
*stack_ptr = ( uint32_t ) 0x00000404; /* R4 */
|
||||
/**
|
||||
* All thread context has now been initialised. Save the current
|
||||
* stack pointer to the thread's TCB so it knows where to start
|
||||
* looking when the thread is started.
|
||||
*/
|
||||
tcb_ptr->sp_save_ptr = stack_ptr;
|
||||
|
||||
tcb_ptr->sp_save_ptr = stack_ptr ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user