ARM: Add comments describing port operation.

This commit is contained in:
Kelvin Lawson
2013-03-05 01:08:53 +00:00
parent 033ff4fd8d
commit 02d14edd9e

View File

@@ -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 ;
}