Merge navaro change into navaro branch.

This commit is contained in:
Kelvin Lawson
2013-02-27 00:24:40 +00:00
58 changed files with 9143 additions and 720 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,844 @@
/**************************************************************************//**
* @file core_cmFunc.h
* @brief CMSIS Cortex-M Core Function Access Header File
* @version V2.01
* @date 06. December 2010
*
* @note
* Copyright (C) 2009-2010 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __CORE_CMFUNC_H__
#define __CORE_CMFUNC_H__
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
#if defined ( __CC_ARM ) /*------------------ RealView Compiler ----------------*/
/* ARM armcc specific functions */
/* intrinsic void __enable_irq(); */
/* intrinsic void __disable_irq(); */
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_CONTROL(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
#endif /* __ARMCC_VERSION */
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
#if (__ARMCC_VERSION < 400000)
extern void __set_CONTROL(uint32_t control);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
#endif /* __ARMCC_VERSION */
/** \brief Get ISPR Register
This function returns the content of the ISPR Register.
\return ISPR Register value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_IPSR(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
#endif /* __ARMCC_VERSION */
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_APSR(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
#endif /* __ARMCC_VERSION */
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_xPSR(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
#endif /* __ARMCC_VERSION */
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_PSP(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
#endif /* __ARMCC_VERSION */
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
#if (__ARMCC_VERSION < 400000)
extern void __set_PSP(uint32_t topOfProcStack);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
#endif /* __ARMCC_VERSION */
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_MSP(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
#endif /* __ARMCC_VERSION */
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
#if (__ARMCC_VERSION < 400000)
extern void __set_MSP(uint32_t topOfMainStack);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
#endif /* __ARMCC_VERSION */
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_PRIMASK(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
#endif /* __ARMCC_VERSION */
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
#if (__ARMCC_VERSION < 400000)
extern void __set_PRIMASK(uint32_t priMask);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#endif /* __ARMCC_VERSION */
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_BASEPRI(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
#endif /* __ARMCC_VERSION */
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
#if (__ARMCC_VERSION < 400000)
extern void __set_BASEPRI(uint32_t basePri);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xff);
}
#endif /* __ARMCC_VERSION */
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
#if (__ARMCC_VERSION < 400000)
extern uint32_t __get_FAULTMASK(void);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
#endif /* __ARMCC_VERSION */
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
#if (__ARMCC_VERSION < 400000)
extern void __set_FAULTMASK(uint32_t faultMask);
#else /* (__ARMCC_VERSION >= 400000) */
static __INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & 1);
}
#endif /* __ARMCC_VERSION */
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
static __INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1)
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
static __INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1)
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif (defined (__ICCARM__)) /*---------------- ICC Compiler ---------------------*/
/* IAR iccarm specific functions */
#if defined (__ICCARM__)
#include <intrinsics.h> /* IAR Intrinsics */
#endif
#pragma diag_suppress=Pe940
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_irq __enable_interrupt
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_irq __disable_interrupt
/* intrinsic unsigned long __get_CONTROL( void ); (see intrinsic.h) */
/* intrinsic void __set_CONTROL( unsigned long ); (see intrinsic.h) */
/** \brief Get ISPR Register
This function returns the content of the ISPR Register.
\return ISPR Register value
*/
static uint32_t __get_IPSR(void)
{
__ASM("mrs r0, ipsr");
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
static uint32_t __get_APSR(void)
{
__ASM("mrs r0, apsr");
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
static uint32_t __get_xPSR(void)
{
__ASM("mrs r0, psr"); // assembler does not know "xpsr"
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
static uint32_t __get_PSP(void)
{
__ASM("mrs r0, psp");
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
static void __set_PSP(uint32_t topOfProcStack)
{
__ASM("msr psp, r0");
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
static uint32_t __get_MSP(void)
{
__ASM("mrs r0, msp");
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
static void __set_MSP(uint32_t topOfMainStack)
{
__ASM("msr msp, r0");
}
/* intrinsic unsigned long __get_PRIMASK( void ); (see intrinsic.h) */
/* intrinsic void __set_PRIMASK( unsigned long ); (see intrinsic.h) */
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
static __INLINE void __enable_fault_irq(void)
{
__ASM ("cpsie f");
}
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
static __INLINE void __disable_fault_irq(void)
{
__ASM ("cpsid f");
}
/* intrinsic unsigned long __get_BASEPRI( void ); (see intrinsic.h) */
/* intrinsic void __set_BASEPRI( unsigned long ); (see intrinsic.h) */
/* intrinsic unsigned long __get_FAULTMASK( void ); (see intrinsic.h) */
/* intrinsic void __set_FAULTMASK(unsigned long); (see intrinsic.h) */
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
static uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1)
__ASM("vmrs r0, fpscr");
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
static void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1)
__ASM("vmsr fpscr, r0");
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#pragma diag_default=Pe940
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __enable_irq(void)
{
__ASM volatile ("cpsie i");
}
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __disable_irq(void)
{
__ASM volatile ("cpsid i");
}
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_CONTROL(void)
{
uint32_t result;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
/** \brief Get ISPR Register
This function returns the content of the ISPR Register.
\return ISPR Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_IPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
return(result);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_APSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
return(result);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_xPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
return(result);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_PSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
return(result);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) );
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_MSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
return(result);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) );
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_PRIMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __enable_fault_irq(void)
{
__ASM volatile ("cpsie f");
}
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __disable_fault_irq(void)
{
__ASM volatile ("cpsid f");
}
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_BASEPRI(void)
{
uint32_t result;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_FAULTMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1)
uint32_t result;
__ASM volatile ("MRS %0, fpscr" : "=r" (result) );
return(result);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1)
__ASM volatile ("MSR fpscr, %0" : : "r" (fpscr) );
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif (defined (__TASKING__)) /*--------------- TASKING Compiler -----------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H__ */

View File

@@ -0,0 +1,775 @@
/**************************************************************************//**
* @file core_cmInstr.h
* @brief CMSIS Cortex-M Core Instruction Access Header File
* @version V2.01
* @date 06. December 2010
*
* @note
* Copyright (C) 2009-2010 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __CORE_CMINSTR_H__
#define __CORE_CMINSTR_H__
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
#if defined ( __CC_ARM ) /*------------------ RealView Compiler ----------------*/
/* ARM armcc specific functions */
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
#define __WFI __wfi
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
#define __ISB() __isb(0xF)
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() __dsb(0xF)
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() __dmb(0xF)
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
#if (__ARMCC_VERSION < 400677)
extern uint32_t __REV16(uint32_t value);
#else /* (__ARMCC_VERSION >= 400677) */
static __INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
#if (__ARMCC_VERSION < 400677)
extern int32_t __REVSH(int32_t value);
#else /* (__ARMCC_VERSION >= 400677) */
static __INLINE __ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#endif /* __ARMCC_VERSION */
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT __rbit
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXB(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXH(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXW(value, ptr) __strex(value, ptr)
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
#if (__ARMCC_VERSION < 400000)
extern void __CLREX(void);
#else /* (__ARMCC_VERSION >= 400000) */
#define __CLREX __clrex
#endif /* __ARMCC_VERSION */
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#endif /* (__CORTEX_M >= 0x03) */
#elif (defined (__ICCARM__)) /*---------------- ICC Compiler ---------------------*/
/* IAR iccarm specific functions */
#include <intrinsics.h> /* IAR Intrinsics */
#pragma diag_suppress=Pe940
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __no_operation
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
static __INLINE void __WFI(void)
{
__ASM ("wfi");
}
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
static __INLINE void __WFE(void)
{
__ASM ("wfe");
}
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
static __INLINE void __SEV(void)
{
__ASM ("sev");
}
/* intrinsic void __ISB(void) (see intrinsics.h) */
/* intrinsic void __DSB(void) (see intrinsics.h) */
/* intrinsic void __DMB(void) (see intrinsics.h) */
/* intrinsic uint32_t __REV(uint32_t value) (see intrinsics.h) */
/* intrinsic __SSAT (see intrinsics.h) */
/* intrinsic __USAT (see intrinsics.h) */
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
static uint32_t __REV16(uint32_t value)
{
__ASM("rev16 r0, r0");
}
/* intrinsic uint32_t __REVSH(uint32_t value) (see intrinsics.h */
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
static uint32_t __RBIT(uint32_t value)
{
__ASM("rbit r0, r0");
}
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
static uint8_t __LDREXB(volatile uint8_t *addr)
{
__ASM("ldrexb r0, [r0]");
}
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
static uint16_t __LDREXH(volatile uint16_t *addr)
{
__ASM("ldrexh r0, [r0]");
}
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
/* intrinsic unsigned long __LDREX(unsigned long *) (see intrinsics.h) */
static uint32_t __LDREXW(volatile uint32_t *addr)
{
__ASM("ldrex r0, [r0]");
}
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
static uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
__ASM("strexb r0, r0, [r1]");
}
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
static uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
{
__ASM("strexh r0, r0, [r1]");
}
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
/* intrinsic unsigned long __STREX(unsigned long, unsigned long) (see intrinsics.h )*/
static uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
{
__ASM("strex r0, r0, [r1]");
}
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
static __INLINE void __CLREX(void)
{
__ASM ("clrex");
}
/* intrinsic unsigned char __CLZ( unsigned long ) (see intrinsics.h) */
#endif /* (__CORTEX_M >= 0x03) */
#pragma diag_default=Pe940
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __NOP(void)
{
__ASM volatile ("nop");
}
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) static __INLINE void __WFI(void)
{
__ASM volatile ("wfi");
}
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) static __INLINE void __WFE(void)
{
__ASM volatile ("wfe");
}
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
__attribute__( ( always_inline ) ) static __INLINE void __SEV(void)
{
__ASM volatile ("sev");
}
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
__attribute__( ( always_inline ) ) static __INLINE void __ISB(void)
{
__ASM volatile ("isb");
}
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
__attribute__( ( always_inline ) ) static __INLINE void __DSB(void)
{
__ASM volatile ("dsb");
}
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
__attribute__( ( always_inline ) ) static __INLINE void __DMB(void)
{
__ASM volatile ("dmb");
}
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __REV(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) static __INLINE int32_t __REVSH(int32_t value)
{
uint32_t result;
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
__attribute__( ( always_inline ) ) static __INLINE uint8_t __LDREXB(volatile uint8_t *addr)
{
uint8_t result;
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
__attribute__( ( always_inline ) ) static __INLINE uint16_t __LDREXH(volatile uint16_t *addr)
{
uint16_t result;
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __LDREXW(volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
uint32_t result;
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
{
uint32_t result;
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
__attribute__( ( always_inline ) ) static __INLINE void __CLREX(void)
{
__ASM volatile ("clrex");
}
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
__attribute__( ( always_inline ) ) static __INLINE uint8_t __CLZ(uint32_t value)
{
uint8_t result;
__ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
#endif /* (__CORTEX_M >= 0x03) */
#elif (defined (__TASKING__)) /*--------------- TASKING Compiler -----------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
#endif /* __CORE_CMINSTR_H__ */

View File

@@ -0,0 +1,64 @@
/**************************************************************************//**
* @file system_LPC17xx.h
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File
* for the NXP LPC17xx Device Series
* @version V1.02
* @date 08. September 2009
*
* @note
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __SYSTEM_LPC17xx_H
#define __SYSTEM_LPC17xx_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/**
* Initialize the system
*
* @param none
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System and update the SystemCoreClock variable.
*/
extern void SystemInit (void);
/**
* Update SystemCoreClock variable
*
* @param none
* @return none
*
* @brief Updates the SystemCoreClock with current core Clock
* retrieved from cpu registers.
*/
extern void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* __SYSTEM_LPC17xx_H */

View File

@@ -0,0 +1,339 @@
/**************************************************************************//**
* @file core_cm3.c
* @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File
* @version V2.00
* @date 13. September 2010
*
* @note
* Copyright (C) 2009-2010 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#include <stdint.h>
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
/* ########################## Core Instruction Access ######################### */
#if defined ( __CC_ARM ) /*------------------ RealView Compiler ----------------*/
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
#if (__ARMCC_VERSION < 400677)
__ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
#if (__ARMCC_VERSION < 400677)
__ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
#if (__ARMCC_VERSION < 400000)
__ASM void __CLREX(void)
{
clrex
}
#endif /* __ARMCC_VERSION */
#elif (defined (__ICCARM__)) /*---------------- ICC Compiler ---------------------*/
/* obsolete */
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* obsolete */
#elif (defined (__TASKING__)) /*--------------- TASKING Compiler -----------------*/
/* obsolete */
#endif
/* ########################### Core Function Access ########################### */
#if defined ( __CC_ARM ) /*------------------ RealView Compiler ----------------*/
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_CONTROL(void)
{
mrs r0, control
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
#if (__ARMCC_VERSION < 400000)
__ASM void __set_CONTROL(uint32_t control)
{
msr control, r0
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Get ISPR Register
This function returns the content of the ISPR Register.
\return ISPR Register value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_IPSR(void)
{
mrs r0, ipsr
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_APSR(void)
{
mrs r0, apsr
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_xPSR(void)
{
mrs r0, xpsr
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_PSP(void)
{
mrs r0, psp
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
#if (__ARMCC_VERSION < 400000)
__ASM void __set_PSP(uint32_t topOfProcStack)
{
msr psp, r0
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_MSP(void)
{
mrs r0, msp
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
#if (__ARMCC_VERSION < 400000)
__ASM void __set_MSP(uint32_t mainStackPointer)
{
msr msp, r0
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_BASEPRI(void)
{
mrs r0, basepri
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
#if (__ARMCC_VERSION < 400000)
__ASM void __set_BASEPRI(uint32_t basePri)
{
msr basepri, r0
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_PRIMASK(void)
{
mrs r0, primask
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
#if (__ARMCC_VERSION < 400000)
__ASM void __set_PRIMASK(uint32_t priMask)
{
msr primask, r0
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask Register.
\return Fault Mask value
*/
#if (__ARMCC_VERSION < 400000)
__ASM uint32_t __get_FAULTMASK(void)
{
mrs r0, faultmask
bx lr
}
#endif /* __ARMCC_VERSION */
/** \brief Set the Fault Mask
This function assigns the given value to the Fault Mask Register.
\param [in] faultMask Fault Mask value value to set
*/
#if (__ARMCC_VERSION < 400000)
__ASM void __set_FAULTMASK(uint32_t faultMask)
{
msr faultmask, r0
bx lr
}
#endif /* __ARMCC_VERSION */
#elif (defined (__ICCARM__)) /*---------------- ICC Compiler ---------------------*/
/* obsolete */
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* obsolete */
#elif (defined (__TASKING__)) /*--------------- TASKING Compiler -----------------*/
/* obsolete */
#endif

View File

@@ -0,0 +1,532 @@
/**************************************************************************//**
* @file system_LPC17xx.c
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File
* for the NXP LPC17xx Device Series
* @version V1.08
* @date 12. May 2010
*
* @note
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#include <stdint.h>
#include "LPC17xx.h"
/*
//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
*/
/*--------------------- Clock Configuration ----------------------------------
//
// <e> Clock Configuration
// <h> System Controls and Status Register (SCS)
// <o1.4> OSCRANGE: Main Oscillator Range Select
// <0=> 1 MHz to 20 MHz
// <1=> 15 MHz to 24 MHz
// <e1.5> OSCEN: Main Oscillator Enable
// </e>
// </h>
//
// <h> Clock Source Select Register (CLKSRCSEL)
// <o2.0..1> CLKSRC: PLL Clock Source Selection
// <0=> Internal RC oscillator
// <1=> Main oscillator
// <2=> RTC oscillator
// </h>
//
// <e3> PLL0 Configuration (Main PLL)
// <h> PLL0 Configuration Register (PLL0CFG)
// <i> F_cco0 = (2 * M * F_in) / N
// <i> F_in must be in the range of 32 kHz to 50 MHz
// <i> F_cco0 must be in the range of 275 MHz to 550 MHz
// <o4.0..14> MSEL: PLL Multiplier Selection
// <6-32768><#-1>
// <i> M Value
// <o4.16..23> NSEL: PLL Divider Selection
// <1-256><#-1>
// <i> N Value
// </h>
// </e>
//
// <e5> PLL1 Configuration (USB PLL)
// <h> PLL1 Configuration Register (PLL1CFG)
// <i> F_usb = M * F_osc or F_usb = F_cco1 / (2 * P)
// <i> F_cco1 = F_osc * M * 2 * P
// <i> F_cco1 must be in the range of 156 MHz to 320 MHz
// <o6.0..4> MSEL: PLL Multiplier Selection
// <1-32><#-1>
// <i> M Value (for USB maximum value is 4)
// <o6.5..6> PSEL: PLL Divider Selection
// <0=> 1
// <1=> 2
// <2=> 4
// <3=> 8
// <i> P Value
// </h>
// </e>
//
// <h> CPU Clock Configuration Register (CCLKCFG)
// <o7.0..7> CCLKSEL: Divide Value for CPU Clock from PLL0
// <1-256><#-1>
// </h>
//
// <h> USB Clock Configuration Register (USBCLKCFG)
// <o8.0..3> USBSEL: Divide Value for USB Clock from PLL0
// <0-15>
// <i> Divide is USBSEL + 1
// </h>
//
// <h> Peripheral Clock Selection Register 0 (PCLKSEL0)
// <o9.0..1> PCLK_WDT: Peripheral Clock Selection for WDT
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.2..3> PCLK_TIMER0: Peripheral Clock Selection for TIMER0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.4..5> PCLK_TIMER1: Peripheral Clock Selection for TIMER1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.6..7> PCLK_UART0: Peripheral Clock Selection for UART0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.8..9> PCLK_UART1: Peripheral Clock Selection for UART1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.12..13> PCLK_PWM1: Peripheral Clock Selection for PWM1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.14..15> PCLK_I2C0: Peripheral Clock Selection for I2C0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.16..17> PCLK_SPI: Peripheral Clock Selection for SPI
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.20..21> PCLK_SSP1: Peripheral Clock Selection for SSP1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.22..23> PCLK_DAC: Peripheral Clock Selection for DAC
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.24..25> PCLK_ADC: Peripheral Clock Selection for ADC
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.26..27> PCLK_CAN1: Peripheral Clock Selection for CAN1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// <o9.28..29> PCLK_CAN2: Peripheral Clock Selection for CAN2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// <o9.30..31> PCLK_ACF: Peripheral Clock Selection for ACF
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// </h>
//
// <h> Peripheral Clock Selection Register 1 (PCLKSEL1)
// <o10.0..1> PCLK_QEI: Peripheral Clock Selection for the Quadrature Encoder Interface
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.2..3> PCLK_GPIO: Peripheral Clock Selection for GPIOs
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.4..5> PCLK_PCB: Peripheral Clock Selection for the Pin Connect Block
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.6..7> PCLK_I2C1: Peripheral Clock Selection for I2C1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.10..11> PCLK_SSP0: Peripheral Clock Selection for SSP0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.12..13> PCLK_TIMER2: Peripheral Clock Selection for TIMER2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.14..15> PCLK_TIMER3: Peripheral Clock Selection for TIMER3
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.16..17> PCLK_UART2: Peripheral Clock Selection for UART2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.18..19> PCLK_UART3: Peripheral Clock Selection for UART3
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.20..21> PCLK_I2C2: Peripheral Clock Selection for I2C2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.22..23> PCLK_I2S: Peripheral Clock Selection for I2S
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.26..27> PCLK_RIT: Peripheral Clock Selection for the Repetitive Interrupt Timer
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.28..29> PCLK_SYSCON: Peripheral Clock Selection for the System Control Block
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.30..31> PCLK_MC: Peripheral Clock Selection for the Motor Control PWM
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// </h>
//
// <h> Power Control for Peripherals Register (PCONP)
// <o11.1> PCTIM0: Timer/Counter 0 power/clock enable
// <o11.2> PCTIM1: Timer/Counter 1 power/clock enable
// <o11.3> PCUART0: UART 0 power/clock enable
// <o11.4> PCUART1: UART 1 power/clock enable
// <o11.6> PCPWM1: PWM 1 power/clock enable
// <o11.7> PCI2C0: I2C interface 0 power/clock enable
// <o11.8> PCSPI: SPI interface power/clock enable
// <o11.9> PCRTC: RTC power/clock enable
// <o11.10> PCSSP1: SSP interface 1 power/clock enable
// <o11.12> PCAD: A/D converter power/clock enable
// <o11.13> PCCAN1: CAN controller 1 power/clock enable
// <o11.14> PCCAN2: CAN controller 2 power/clock enable
// <o11.15> PCGPIO: GPIOs power/clock enable
// <o11.16> PCRIT: Repetitive interrupt timer power/clock enable
// <o11.17> PCMC: Motor control PWM power/clock enable
// <o11.18> PCQEI: Quadrature encoder interface power/clock enable
// <o11.19> PCI2C1: I2C interface 1 power/clock enable
// <o11.21> PCSSP0: SSP interface 0 power/clock enable
// <o11.22> PCTIM2: Timer 2 power/clock enable
// <o11.23> PCTIM3: Timer 3 power/clock enable
// <o11.24> PCUART2: UART 2 power/clock enable
// <o11.25> PCUART3: UART 3 power/clock enable
// <o11.26> PCI2C2: I2C interface 2 power/clock enable
// <o11.27> PCI2S: I2S interface power/clock enable
// <o11.29> PCGPDMA: GP DMA function power/clock enable
// <o11.30> PCENET: Ethernet block power/clock enable
// <o11.31> PCUSB: USB interface power/clock enable
// </h>
//
// <h> Clock Output Configuration Register (CLKOUTCFG)
// <o12.0..3> CLKOUTSEL: Selects clock source for CLKOUT
// <0=> CPU clock
// <1=> Main oscillator
// <2=> Internal RC oscillator
// <3=> USB clock
// <4=> RTC oscillator
// <o12.4..7> CLKOUTDIV: Selects clock divider for CLKOUT
// <1-16><#-1>
// <o12.8> CLKOUT_EN: CLKOUT enable control
// </h>
//
// </e>
*/
#define CLOCK_SETUP 1
#define SCS_Val 0x00000020
#define CLKSRCSEL_Val 0x00000001
#define PLL0_SETUP 1
#define PLL0CFG_Val 0x00050063
#define PLL1_SETUP 1
#define PLL1CFG_Val 0x00000023
#define CCLKCFG_Val 0x00000003
#define USBCLKCFG_Val 0x00000000
#define PCLKSEL0_Val 0x00000000
#define PCLKSEL1_Val 0x00000000
#define PCONP_Val 0x042887DE
#define CLKOUTCFG_Val 0x00000000
/*--------------------- Flash Accelerator Configuration ----------------------
//
// <e> Flash Accelerator Configuration
// <o1.12..15> FLASHTIM: Flash Access Time
// <0=> 1 CPU clock (for CPU clock up to 20 MHz)
// <1=> 2 CPU clocks (for CPU clock up to 40 MHz)
// <2=> 3 CPU clocks (for CPU clock up to 60 MHz)
// <3=> 4 CPU clocks (for CPU clock up to 80 MHz)
// <4=> 5 CPU clocks (for CPU clock up to 100 MHz)
// <5=> 6 CPU clocks (for any CPU clock)
// </e>
*/
#define FLASH_SETUP 0
#define FLASHCFG_Val 0x00004000
/*
//-------- <<< end of configuration section >>> ------------------------------
*/
/*----------------------------------------------------------------------------
Check the register settings
*----------------------------------------------------------------------------*/
#define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
#define CHECK_RSVD(val, mask) (val & mask)
/* Clock Configuration -------------------------------------------------------*/
#if (CHECK_RSVD((SCS_Val), ~0x00000030))
#error "SCS: Invalid values of reserved bits!"
#endif
#if (CHECK_RANGE((CLKSRCSEL_Val), 0, 2))
#error "CLKSRCSEL: Value out of range!"
#endif
#if (CHECK_RSVD((PLL0CFG_Val), ~0x00FF7FFF))
#error "PLL0CFG: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PLL1CFG_Val), ~0x0000007F))
#error "PLL1CFG: Invalid values of reserved bits!"
#endif
#if (PLL0_SETUP) /* if PLL0 is used */
#if (CCLKCFG_Val < 2) /* CCLKSEL must be greater then 1 */
#error "CCLKCFG: CCLKSEL must be greater then 1 if PLL0 is used!"
#endif
#endif
#if (CHECK_RANGE((CCLKCFG_Val), 2, 255))
#error "CCLKCFG: Value out of range!"
#endif
#if (CHECK_RSVD((USBCLKCFG_Val), ~0x0000000F))
#error "USBCLKCFG: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCLKSEL0_Val), 0x000C0C00))
#error "PCLKSEL0: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCLKSEL1_Val), 0x03000300))
#error "PCLKSEL1: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCONP_Val), 0x10100821))
#error "PCONP: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((CLKOUTCFG_Val), ~0x000001FF))
#error "CLKOUTCFG: Invalid values of reserved bits!"
#endif
/* Flash Accelerator Configuration -------------------------------------------*/
#if (CHECK_RSVD((FLASHCFG_Val), ~0x0000F000))
#error "FLASHCFG: Invalid values of reserved bits!"
#endif
/*----------------------------------------------------------------------------
DEFINES
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
Define clocks
*----------------------------------------------------------------------------*/
#define XTAL (12000000UL) /* Oscillator frequency */
#define OSC_CLK ( XTAL) /* Main oscillator frequency */
#define RTC_CLK ( 32000UL) /* RTC oscillator frequency */
#define IRC_OSC ( 4000000UL) /* Internal RC oscillator frequency */
/* F_cco0 = (2 * M * F_in) / N */
#define __M (((PLL0CFG_Val ) & 0x7FFF) + 1)
#define __N (((PLL0CFG_Val >> 16) & 0x00FF) + 1)
#define __FCCO(__F_IN) ((2/*ULL*/ * __M * __F_IN) / __N)
#define __CCLK_DIV (((CCLKCFG_Val ) & 0x00FF) + 1)
/* Determine core clock frequency according to settings */
#if (PLL0_SETUP)
#if ((CLKSRCSEL_Val & 0x03) == 1)
#define __CORE_CLK (__FCCO(OSC_CLK) / __CCLK_DIV)
#elif ((CLKSRCSEL_Val & 0x03) == 2)
#define __CORE_CLK (__FCCO(RTC_CLK) / __CCLK_DIV)
#else
#define __CORE_CLK (__FCCO(IRC_OSC) / __CCLK_DIV)
#endif
#else
#if ((CLKSRCSEL_Val & 0x03) == 1)
#define __CORE_CLK (OSC_CLK / __CCLK_DIV)
#elif ((CLKSRCSEL_Val & 0x03) == 2)
#define __CORE_CLK (RTC_CLK / __CCLK_DIV)
#else
#define __CORE_CLK (IRC_OSC / __CCLK_DIV)
#endif
#endif
/*----------------------------------------------------------------------------
Clock Variable definitions
*----------------------------------------------------------------------------*/
uint32_t SystemCoreClock = __CORE_CLK;/*!< System Clock Frequency (Core Clock)*/
/*----------------------------------------------------------------------------
Clock functions
*----------------------------------------------------------------------------*/
void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
{
/* Determine clock frequency according to clock register values */
if (((LPC_SC->PLL0STAT >> 24) & 3) == 3) { /* If PLL0 enabled and connected */
switch (LPC_SC->CLKSRCSEL & 0x03) {
case 0: /* Int. RC oscillator => PLL0 */
case 3: /* Reserved, default to Int. RC */
SystemCoreClock = (IRC_OSC *
((2/*ULL*/ * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
case 1: /* Main oscillator => PLL0 */
SystemCoreClock = (OSC_CLK *
((2/*ULL*/ * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
case 2: /* RTC oscillator => PLL0 */
SystemCoreClock = (RTC_CLK *
((2/*ULL*/ * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
}
} else {
switch (LPC_SC->CLKSRCSEL & 0x03) {
case 0: /* Int. RC oscillator => PLL0 */
case 3: /* Reserved, default to Int. RC */
SystemCoreClock = IRC_OSC / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
case 1: /* Main oscillator => PLL0 */
SystemCoreClock = OSC_CLK / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
case 2: /* RTC oscillator => PLL0 */
SystemCoreClock = RTC_CLK / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
}
}
}
/**
* Initialize the system
*
* @param none
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System.
*/
void SystemInit (void)
{
#if (CLOCK_SETUP) /* Clock Setup */
LPC_SC->SCS = SCS_Val;
if (SCS_Val & (1 << 5)) { /* If Main Oscillator is enabled */
while ((LPC_SC->SCS & (1<<6)) == 0);/* Wait for Oscillator to be ready */
}
LPC_SC->CCLKCFG = CCLKCFG_Val; /* Setup Clock Divider */
LPC_SC->PCLKSEL0 = PCLKSEL0_Val; /* Peripheral Clock Selection */
LPC_SC->PCLKSEL1 = PCLKSEL1_Val;
LPC_SC->CLKSRCSEL = CLKSRCSEL_Val; /* Select Clock Source for PLL0 */
#if (PLL0_SETUP)
LPC_SC->PLL0CFG = PLL0CFG_Val; /* configure PLL0 */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0 */
LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */
#endif
#if (PLL1_SETUP)
LPC_SC->PLL1CFG = PLL1CFG_Val;
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
LPC_SC->PLL1CON = 0x01; /* PLL1 Enable */
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
while (!(LPC_SC->PLL1STAT & (1<<10)));/* Wait for PLOCK1 */
LPC_SC->PLL1CON = 0x03; /* PLL1 Enable & Connect */
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
while (!(LPC_SC->PLL1STAT & ((1<< 9) | (1<< 8))));/* Wait for PLLC1_STAT & PLLE1_STAT */
#else
LPC_SC->USBCLKCFG = USBCLKCFG_Val; /* Setup USB Clock Divider */
#endif
LPC_SC->PCONP = PCONP_Val; /* Power Control for Peripherals */
LPC_SC->CLKOUTCFG = CLKOUTCFG_Val; /* Clock Output Configuration */
#endif
#if (FLASH_SETUP == 1) /* Flash Accelerator Setup */
LPC_SC->FLASHCFG = (LPC_SC->FLASHCFG & ~0x0000F000) | FLASHCFG_Val;
#endif
}

View File

@@ -0,0 +1,94 @@
ifeq ($(TARGET_NAME),)
TARGET_NAME=boot
endif
ifeq ($(ATOMTHREADS),)
ATOMTHREADS = $(shell pwd)/../../
endif
ifeq ($(TEST_NAME),)
TEST_NAME = kern1
endif
CC = arm-none-eabi-gcc
LN = arm-none-eabi-gcc
AS = arm-none-eabi-gcc
CFLAGS := $(CFLAGS) -O3 -Os -g3 -Wall -c -mcpu=cortex-m3 -mthumb
AFLAGS := $(AFLAGS) -O3 -Os -g3 -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections -mcpu=cortex-m3 -mthumb
LFLAGS := $(LFLAGS) -O3 -Os -Wall -mcpu=cortex-m3 -mthumb -Wl,-Map=system.map -Tsystem.ld
CDEFS := $(CDEFS) -DATOMTHREADS_TEST='"$(TEST_NAME)"' -DBOARD_MBED_LP1768
ADEFS := $(ADEFS) -D__thumb2__ -DARM_RDI_MONITOR
LLIBS := $(LLIBS)
SRCS := $(SRCS) \
./CMSISv2p00_LPC17xx/src/core_cm3.c \
./CMSISv2p00_LPC17xx/src/system_LPC17xx.c \
./drivers/lpc17xx_uart.c \
startup.c \
modules.c \
$(ATOMTHREADS)/tests/$(TEST_NAME).c \
main.c \
ASMS := $(ASMS) \
INCLUDES := $(INCLUDES) \
-I$(ATOMTHREADS)/platforms/lpc17xx/CMSISv2p00_LPC17xx/inc \
-I$(ATOMTHREADS)/platforms/lpc17xx \
-I$(ATOMTHREADS)
include $(ATOMTHREADS)/ports/cortex_m/Makefile
OBJS = $(SRCS:.c=.o) $(ASMS:.S=.o)
include ../rules.mk
run_test: clean all
cp boot.bin bin/$(TEST_NAME).bin
all_tests:
echo "Starting atomthreads test suite"
make run_test "TEST_NAME=mutex1"
make run_test "TEST_NAME=mutex2"
make run_test "TEST_NAME=mutex3"
make run_test "TEST_NAME=mutex4"
make run_test "TEST_NAME=mutex5"
make run_test "TEST_NAME=mutex6"
make run_test "TEST_NAME=mutex7"
make run_test "TEST_NAME=mutex8"
make run_test "TEST_NAME=mutex9"
make run_test "TEST_NAME=kern1"
make run_test "TEST_NAME=kern2"
make run_test "TEST_NAME=kern3"
make run_test "TEST_NAME=kern4"
make run_test "TEST_NAME=timer1"
make run_test "TEST_NAME=timer2"
make run_test "TEST_NAME=timer3"
make run_test "TEST_NAME=timer4"
make run_test "TEST_NAME=timer5"
make run_test "TEST_NAME=timer6"
make run_test "TEST_NAME=timer7"
make run_test "TEST_NAME=queue1"
make run_test "TEST_NAME=queue2"
make run_test "TEST_NAME=queue3"
make run_test "TEST_NAME=queue4"
make run_test "TEST_NAME=queue5"
make run_test "TEST_NAME=queue6"
make run_test "TEST_NAME=queue7"
make run_test "TEST_NAME=queue8"
make run_test "TEST_NAME=queue9"
make run_test "TEST_NAME=sem1"
make run_test "TEST_NAME=sem2"
make run_test "TEST_NAME=sem3"
make run_test "TEST_NAME=sem4"
make run_test "TEST_NAME=sem5"
make run_test "TEST_NAME=sem6"
make run_test "TEST_NAME=sem7"
make run_test "TEST_NAME=sem8"
make run_test "TEST_NAME=sem9"

24
platforms/lpc17xx/README Normal file
View File

@@ -0,0 +1,24 @@
---------------------------------------------------------------------------
Library: Atomthreads NXP LPC17xx Platform.
Author: Natie van Rooyen <natie@navaro.nl>
License: BSD Revised
---------------------------------------------------------------------------
NXP LPC17xx Platform
The "lpc17xx" platform contains sources for building the Atomthreads test
suite for the NXP LPC17xx microcontroller.
The build was tested on the "mbed NXP LPC1768" board (http://www.mbed.org)
but it should work on any LPC17xx development board where UART0 can be used
to monitor the output of the test.
The NXP LPC17xx microcontrollers use the ARM Cortex M3 processor core. The
source code in this example uses the ARM CMSIS Cortex-M Access Library V2.01
to initialize the platform and Newlib as the runtime library. Also it uses a
driver provided by NXP for the UART. The CMSIS library and the UART driver
are provided as source with the sample and Newlib is expected to be installed
together with the GNU ARM tool chain.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,179 @@
/**************************************************************************//**
* @file lpc17xx_uart.c
* @brief Drivers for UART peripheral in lpc17xx.
* @version 1.0
* @date 18. Nov. 2010
*
* @note
* Copyright (C) 2010 NXP Semiconductors(NXP). All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
******************************************************************************/
#include <stdarg.h>
#include <stdio.h>
#include "lpc17xx_uart.h"
#include "lpc17xx.h"
/**
* @brief Initializes the UART0.
*
* @param baudrate: Specifies the baud rate
* @retval None
*/
void LPC17xx_UART_Init(uint32_t baudrate)
{
uint32_t Fdiv;
uint32_t pclkdiv, pclk;
/***/
LPC_PINCON->PINSEL0 &= ~0x000000F0;
LPC_PINCON->PINSEL0 |= 0x00000050; /* RxD0 and TxD0 */
/* PCLK_UART0=CCLK/2 */
//**LPC_SC->PCLKSEL1 &= ~(3<<6); /* PCLK_UART0 = CCLK/4 (18MHz) */
//**LPC_SC->PCLKSEL1 |= (2<<6); /* PCLK_UART0 = CCLK/2 (36MHz) */
//**pclk = SystemCoreClock/2;
/* By default, the PCLKSELx value is zero, thus, the PCLK for
all the peripherals is 1/4 of the SystemFrequency. */
/* Bit 6~7 is for UART0 */
pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
switch ( pclkdiv )
{
case 0x00:
default:
pclk = SystemCoreClock/4;
break;
case 0x01:
pclk = SystemCoreClock;
break;
case 0x02:
pclk = SystemCoreClock/2;
break;
case 0x03:
pclk = SystemCoreClock/8;
break;
}
LPC_UART0->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
Fdiv = ( pclk / 16 ) / baudrate ; /*baud rate */
LPC_UART0->DLM = Fdiv / 256;
LPC_UART0->DLL = Fdiv % 256;
LPC_UART0->LCR = 0x03; /* DLAB = 0 */
LPC_UART0->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
}
/**
* @brief Write one character to UART0.
*
* @param ch: Character to be written
* @retval None
*/
void LPC17xx_UART_PutChar (uint8_t ch)
{
while (!(LPC_UART0->LSR & 0x20));
LPC_UART0->THR = ch;
}
/**
* @brief Read one character from UART0 (blocking read).
*
* @param None
* @retval Received character
*/
uint8_t LPC17xx_UART_GetChar (void)
{
while (!(LPC_UART0->LSR & 0x01));
return (LPC_UART0->RBR);
}
/**
* @brief Read one character from UART0 (non blocking read).
*
* @param None
* @retval Received character
*/
uint8_t LPC17xx_UART_GetChar_nb (void)
{
if (LPC_UART0->LSR & 0x01)
return (LPC_UART0->RBR);
else
return 0;
}
/**
* @brief Write a string to UART0.
*
* @param str: NULL-terminated char string to be written
* @retval None
*/
void LPC17xx_UART_PutString (uint8_t *str)
{
/* usage: LPC1700_UART_Printf("xxx\n\r");*/
#if 1
while (*str != 0)
{
LPC17xx_UART_PutChar(*str++);
}
#else
/* usage: LPC1700_UART_Printf("xxx\n");*/
while ((*str) != 0) {
if (*str == '\n') {
LPC17xx_UART_PutChar(*str++);
LPC17xx_UART_PutChar('\r');
} else {
LPC17xx_UART_PutChar(*str++);
}
}
#endif
}
/**
* @brief Write a buffer to UART0.
*
* @param buffer: buffer to be written
* @retval None
*/
void LPC17xx_UART_WriteBuffer (uint8_t *buffer, uint32_t len)
{
while (len-- != 0) {
LPC17xx_UART_PutChar(*buffer++);
}
}
/**
* @brief Print formatted string. This function takes variable length arguments.
*
* @param format
* @param ...
* @retval None
*
* Note: using library functions "vsprintf" will increase the RO size by about 6KB
*/
//void LPC17xx_UART_Printf (const uint8_t *format, ...)
//{
// static uint8_t buffer[40 + 1];
// va_list vArgs;
//
// va_start(vArgs, format);
// vsprintf((char *)buffer, (char const *)format, vArgs);
// va_end(vArgs);
// LPC17xx_UART_PutString((uint8_t *) buffer);
//}
/* --------------------------------- End Of File ------------------------------ */

View File

@@ -0,0 +1,37 @@
/**************************************************************************//**
* @file lpc17xx_uart.h
* @brief Header file for lpc17xx_uart.c.
* @version 1.0
* @date 18. Nov. 2010
*
* @note
* Copyright (C) 2010 NXP Semiconductors(NXP). All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
******************************************************************************/
#ifndef __LPC17xx_UART_H_
#define __LPC17xx_UART_H_
#include <stdint.h>
/* external functions */
void LPC17xx_UART_PutChar (uint8_t);
uint8_t LPC17xx_UART_GetChar (void);
void LPC17xx_UART_Init(uint32_t baudrate);
void LPC17xx_UART_PutString (uint8_t *str) ;
void LPC17xx_UART_WriteBuffer (uint8_t *buffer, uint32_t len) ;
#endif // __LPC17xx_UART_H_
/* --------------------------------- End Of File ------------------------------ */

122
platforms/lpc17xx/main.c Normal file
View File

@@ -0,0 +1,122 @@
/*
* 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
* 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.
*/
#include <stdio.h>
#include "LPC17xx.h"
#include "drivers/lpc17xx_uart.h"
#include "modules.h"
#include "atom.h"
#include "tests/atomtests.h"
#ifndef ATOMTHREADS_TEST
#define ATOMTHREADS_TEST "kern1"
#endif
// for mbed board
#define MBED_LED1_GPIO (1 << 18)
#define MBED_LED2_GPIO (1 << 20)
#define MBED_LED3_GPIO (1 << 21)
#define MBED_LED4_GPIO (1 << 23)
#define MBED_LED_GET(led) (LPC_GPIO1->FIOSET & led)
#define MBED_LED_SET(led, on) { if (on) LPC_GPIO1->FIOSET = led ; else LPC_GPIO1->FIOCLR = led ; }
#define MBED_LED_TOGGLE(led) MBED_LED_SET(led, !MBED_LED_GET(led))
#define MBED_LED_COUNT(count) MBED_LED_SET(MBED_LED1_GPIO, count & 1) ; MBED_LED_SET(MBED_LED2_GPIO, count & 2) ; \
MBED_LED_SET(MBED_LED3_GPIO, count & 4) ; MBED_LED_SET(MBED_LED4_GPIO, count & 8) ;
#define TEST_STACK_BYTE_SIZE 512
#define IDLE_STACK_BYTE_SIZE 128
static unsigned char test_stack[TEST_STACK_BYTE_SIZE] ;
static unsigned char idle_stack[IDLE_STACK_BYTE_SIZE] ;
ATOM_TCB test_tcb ;
/**
* \b test_thread
*
* Function calling the test function of the Atomthreads test suite.
*
*/
void
test_thread (uint32_t param)
{
uint32_t failures ;
CRITICAL_STORE ;
failures = test_start () ;
atomTimerDelay (10) ;
CRITICAL_START() ;
dbg_format_msg ("%s %s\r\n", ATOMTHREADS_TEST, failures ? "FAIL" : "PASS") ;
CRITICAL_END() ;
while(1) {
#ifdef BOARD_MBED_LP1768
MBED_LED_TOGGLE(MBED_LED1_GPIO) ;
#endif
atomTimerDelay (65) ;
}
}
/**
* \b main
*
* Initialize atomthreads and start a test_thread to run the Atomthreads test suite.
*
*/
int
main(void)
{
#ifdef BOARD_MBED_LP1768
LPC_GPIO1->FIODIR |= MBED_LED1_GPIO | MBED_LED2_GPIO | MBED_LED3_GPIO | MBED_LED4_GPIO ;
MBED_LED_SET(MBED_LED1_GPIO | MBED_LED2_GPIO | MBED_LED3_GPIO | MBED_LED4_GPIO, 1);
#endif
dbg_format_msg ("\r\nLPC17xx SystemCoreClock = %d\r\n",SystemCoreClock) ;
//atomthreads_stress_test (36) ;
dbg_format_msg ("Atomthreads starting %s... \r\n", ATOMTHREADS_TEST) ;
atomOSInit(&idle_stack[0], IDLE_STACK_BYTE_SIZE, TRUE) ;
atomThreadCreate ((ATOM_TCB *)&test_tcb, TEST_THREAD_PRIO, test_thread, 0,
&test_stack[0], TEST_STACK_BYTE_SIZE, TRUE);
atomOSStart() ;
while(1) ;
return 0 ;
}

179
platforms/lpc17xx/modules.c Normal file
View File

@@ -0,0 +1,179 @@
/*
* 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
* 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.
*/
#include "modules.h"
#include <stdio.h>
#include <stdarg.h>
#include "atomport_private.h"
#include "atom.h"
#include "atomport.h"
/**
* \b dbg_format_msg
*
* Same as printf.
*
*/
void
dbg_format_msg (char *format, ...)
{
va_list args;
static char msg[256] ;
//CRITICAL_STORE ;
va_start (args, format) ;
//CRITICAL_START() ;
vsniprintf ((char*)msg, 256, (char*)format, args) ;
LPC17xx_UART_PutString (msg) ;
//CRITICAL_END() ;
}
/**
* \b low_level_init
*
* Initializes the PIC and start the system timer tick intrerupt.
*
*/
int
low_level_init (void)
{
SystemInit () ;
SystemCoreClockUpdate ();
//contextInit () ;
NVIC_SetPriority (PendSV_IRQn, 0xFF) ;
LPC17xx_UART_Init (115200) ;
SysTick_Config (1000000) ;
return 0 ;
}
/**
* \b __context_preempt_handler
*
* System timer tic interupt handler.
*
*/
void
__context_tick_handler (void)
{
/* Call the interrupt enter routine */
atomIntEnter();
/* Call the OS system tick handler */
atomTimerTick();
/* Call the interrupt exit routine */
atomIntExit(TRUE);
}
/**
* \b dbg_mem_dump_40
*
* Dumps size bytes of memory from data.
*
*/
void dbg_mem_dump_40 (unsigned int* data, int size)
{
int j ;
dbg_format_msg ("Dump %d bytes at %.8X:\r\n",size * 4, (unsigned int)data) ;
data = (unsigned int*)((unsigned int)data & ~0x3) ;
for (j=0; j<size-3; j+=4) {
dbg_format_msg (" :%.8X: %.8X %.8X %.8X %.8X\r\n", (unsigned int)&data[j], data[j+0], data[j+1], data[j+2], data[j+3]) ;
}
if (size-j == 3) {
dbg_format_msg (" :%.8X: %.8X %.8X %.8X\r\n", (unsigned int)&data[j], data[j+0], data[j+1], data[j+2]) ;
} else if (size-j == 2) {
dbg_format_msg (" :%.8X: %.8X %.8X\r\n", (unsigned int)&data[j], data[j+0], data[j+1]) ;
} else if (size-j == 1) {
dbg_format_msg (" :%.8X: %.8X\r\n", (unsigned int)&data[j], data[j+0]) ;
}
}
/**
* \b dbg_fault_handler
*
* Prints cortex m exception debug information.
*
*/
void
dbg_fault_handler (unsigned int * hardfault_args)
{
unsigned int stacked_r0;
unsigned int stacked_r1;
unsigned int stacked_r2;
unsigned int stacked_r3;
unsigned int stacked_r12;
unsigned int stacked_lr;
unsigned int stacked_pc;
unsigned int stacked_psr;
stacked_r0 = ((unsigned long) hardfault_args[0]);
stacked_r1 = ((unsigned long) hardfault_args[1]);
stacked_r2 = ((unsigned long) hardfault_args[2]);
stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);
dbg_format_msg ("\r\n\r\n[Hard fault handler - all numbers in hex]\r\n");
dbg_format_msg ("SP = 0x%x\r\n", hardfault_args);
dbg_format_msg ("R0 = 0x%x\r\n", stacked_r0);
dbg_format_msg ("R1 = 0x%x\r\n", stacked_r1);
dbg_format_msg ("R2 = 0x%x\r\n", stacked_r2);
dbg_format_msg ("R3 = 0x%x\r\n", stacked_r3);
dbg_format_msg ("R12 = 0x%x\r\n", stacked_r12);
dbg_format_msg ("LR [R14] = 0x%x subroutine call return address\r\n", stacked_lr);
dbg_format_msg ("PC [R15] = 0x%x program counter\r\n", stacked_pc);
dbg_format_msg ("PSR = 0x%x\r\n", stacked_psr);
//printf ("BFAR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED38))));
//printf ("CFSR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED28))));
//printf ("HFSR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED2C))));
//printf ("DFSR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED30))));
//printf ("AFSR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED3C))));
// printf ("SCB_SHCSR = %x\n", SCB->SHCSR);
dbg_mem_dump_40 (hardfault_args, 0x40) ;
while (1);
}

View File

@@ -0,0 +1,46 @@
/*
* 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
* 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 __MODULES_H__
#define __MODULES_H__
/*
* Module definitions to use with the Stellaris LM3S6965 Microcontroller
*/
#include "LPC17xx.h"
#include "drivers/lpc17xx_uart.h"
/* Function prototypes */
extern int low_level_init (void) ;
extern void dbg_format_msg (char *format, ...) ;
extern void dbg_fault_handler (unsigned int * hardfault_args) ;
#endif /* __MODULES_H__ */

297
platforms/lpc17xx/startup.c Normal file
View File

@@ -0,0 +1,297 @@
/**************************************************************************//**
* @file startup.c
* @brief
* @version
* @date
*
* @note
* Copyright (C) 2010 NXP Semiconductors(NXP). All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
******************************************************************************/
#define WEAK __attribute__ ((weak))
#define ALIAS(f) __attribute__ ((weak, alias (#f)))
#include "system_LPC17xx.h"
#include "atomport_private.h"
void ResetISR(void);
WEAK void NMI_Handler(void);
WEAK void HardFault_Handler(void);
WEAK void MemManage_Handler(void);
WEAK void BusFault_Handler(void);
WEAK void UsageFault_Handler(void);
WEAK void SVC_Handler(void);
WEAK void DebugMon_Handler(void);
WEAK void PendSV_Handler(void);
WEAK void SysTick_Handler(void);
WEAK void IntDefault_Handler(void);
//*****************************************************************************
//
// The entry point for the application.
// __main() is the entry point for Redlib based applications
// main() is the entry point for Newlib based applications
//
//*****************************************************************************
extern int main(void);
extern void low_level_init(void);
//*****************************************************************************
//
// External declaration for the pointer to the stack top from the Linker Script
//
//*****************************************************************************
extern void _vStackTop(void);
//*****************************************************************************
//
// The vector table.
// This relies on the linker script to place at correct location in memory.
//
//*****************************************************************************
extern void (* const g_pfnVectors[])(void);
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) = {
// Core Level - CM3
&_vStackTop, // The initial stack pointer
ResetISR, // The reset handler
NMI_Handler, // The NMI handler
HardFault_Handler, // The hard fault handler
MemManage_Handler, // The MPU fault handler
BusFault_Handler, // The bus fault handler
UsageFault_Handler, // The usage fault handler
0, // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
SVC_Handler, // SVCall handler
DebugMon_Handler, // Debug monitor handler
0, // Reserved
archPendSVHandler, // The PendSV handler
archTickHandler /*SysTick_Handler*/, // The SysTick handler
// Chip Level - LPC17
IntDefault_Handler, // 16, 0x40 - WDT
IntDefault_Handler, // 17, 0x44 - TIMER0
IntDefault_Handler, // 18, 0x48 - TIMER1
IntDefault_Handler, // 19, 0x4c - TIMER2
IntDefault_Handler, // 20, 0x50 - TIMER3
IntDefault_Handler, // 21, 0x54 - UART0
IntDefault_Handler, // 22, 0x58 - UART1
IntDefault_Handler, // 23, 0x5c - UART2
IntDefault_Handler, // 24, 0x60 - UART3
IntDefault_Handler, // 25, 0x64 - PWM1
IntDefault_Handler, // 26, 0x68 - I2C0
IntDefault_Handler, // 27, 0x6c - I2C1
IntDefault_Handler, // 28, 0x70 - I2C2
IntDefault_Handler, // 29, 0x74 - SPI
IntDefault_Handler, // 30, 0x78 - SSP0
IntDefault_Handler, // 31, 0x7c - SSP1
IntDefault_Handler, // 32, 0x80 - PLL0 (Main PLL)
IntDefault_Handler, // 33, 0x84 - RTC
IntDefault_Handler, // 34, 0x88 - EINT0
IntDefault_Handler, // 35, 0x8c - EINT1
IntDefault_Handler, // 36, 0x90 - EINT2
IntDefault_Handler, // 37, 0x94 - EINT3
IntDefault_Handler, // 38, 0x98 - ADC
IntDefault_Handler, // 39, 0x9c - BOD
IntDefault_Handler, // 40, 0xA0 - USB
IntDefault_Handler, // 41, 0xa4 - CAN
IntDefault_Handler, // 42, 0xa8 - GP DMA
IntDefault_Handler, // 43, 0xac - I2S
IntDefault_Handler, // 44, 0xb0 - Ethernet
IntDefault_Handler, // 45, 0xb4 - RITINT
IntDefault_Handler, // 46, 0xb8 - Motor Control PWM
IntDefault_Handler, // 47, 0xbc - Quadrature Encoder
IntDefault_Handler, // 48, 0xc0 - PLL1 (USB PLL)
IntDefault_Handler, // 49, 0xc4 - USB Activity interrupt to wakeup
IntDefault_Handler, // 50, 0xc8 - CAN Activity interrupt to wakeup
};
//*****************************************************************************
// Functions to carry out the initialization of RW and BSS data sections. These
// are written as separate functions rather than being inlined within the
// ResetISR() function in order to cope with MCUs with multiple banks of
// memory.
//*****************************************************************************
__attribute__ ((section(".after_vectors")))
void data_init(unsigned int romstart, unsigned int start, unsigned int len) {
unsigned int *pulDest = (unsigned int*) start;
unsigned int *pulSrc = (unsigned int*) romstart;
unsigned int loop;
for (loop = 0; loop < len; loop = loop + 4)
*pulDest++ = *pulSrc++;
}
__attribute__ ((section(".after_vectors")))
void bss_init(unsigned int start, unsigned int len) {
unsigned int *pulDest = (unsigned int*) start;
unsigned int loop;
for (loop = 0; loop < len; loop = loop + 4)
*pulDest++ = 0;
}
//*****************************************************************************
// The following symbols are constructs generated by the linker, indicating
// the location of various points in the "Global Section Table". This table is
// created by the linker via the Code Red managed linker script mechanism. It
// contains the load address, execution address and length of each RW data
// section and the execution and length of each BSS (zero initialized) section.
//*****************************************************************************
extern unsigned int __data_section_table;
extern unsigned int __data_section_table_end;
extern unsigned int __bss_section_table;
extern unsigned int __bss_section_table_end;
//*****************************************************************************
// Reset entry point for your code.
// Sets up a simple runtime environment and initializes the C/C++
// library.
//*****************************************************************************
__attribute__ ((section(".after_vectors")))
void
ResetISR(void) {
//
// Copy the data sections from flash to SRAM.
//
unsigned int LoadAddr, ExeAddr, SectionLen;
unsigned int *SectionTableAddr;
// Load base address of Global Section Table
SectionTableAddr = &__data_section_table;
// Copy the data sections from flash to SRAM.
while (SectionTableAddr < &__data_section_table_end) {
LoadAddr = *SectionTableAddr++;
ExeAddr = *SectionTableAddr++;
SectionLen = *SectionTableAddr++;
data_init(LoadAddr, ExeAddr, SectionLen);
}
// At this point, SectionTableAddr = &__bss_section_table;
// Zero fill the bss segment
while (SectionTableAddr < &__bss_section_table_end) {
ExeAddr = *SectionTableAddr++;
SectionLen = *SectionTableAddr++;
bss_init(ExeAddr, SectionLen);
}
low_level_init();
main();
//
// main() shouldn't return, but if it does, we'll just enter an infinite loop
//
while (1) ;
}
//*****************************************************************************
// Default exception handlers. Override the ones here by defining your own
// handler routines in your application code.
//*****************************************************************************
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void NMI_Handler(void)
{
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void HardFault_Handler(void)
{
__asm volatile
(
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" b dbg_fault_handler \n"
);
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void MemManage_Handler(void)
{
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void BusFault_Handler(void)
{
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void UsageFault_Handler(void)
{
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void SVC_Handler(void)
{
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void DebugMon_Handler(void)
{
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void PendSV_Handler(void)
{
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void SysTick_Handler(void)
{
while(1) ;
}
__attribute__ ((section(".after_vectors"))) __attribute__( ( naked ) )
void IntDefault_Handler(void)
{
while(1) ;
}

148
platforms/lpc17xx/system.ld Normal file
View File

@@ -0,0 +1,148 @@
/**************************************************************************//**
* @file system.ld
* @brief
* @version
* @date
*
* @note
* Copyright (C) 2010 NXP Semiconductors(NXP). All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
******************************************************************************/
MEMORY
{
/* Define each memory region */
MFlash512 (rx) : ORIGIN = 0x0, LENGTH = 0x80000 /* 512k */
RamLoc32 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x8000 /* 32k */
RamAHB32 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x8000 /* 32k */
}
/* Define a symbol for the top of each memory region */
__top_MFlash512 = 0x0 + 0x80000;
__top_RamLoc32 = 0x10000000 + 0x8000;
__top_RamAHB32 = 0x2007c000 + 0x8000;
ENTRY(ResetISR)
SECTIONS
{
/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
FILL(0xff)
KEEP(*(.isr_vector))
/* Global Section Table */
. = ALIGN(4) ;
__section_table_start = .;
__data_section_table = .;
LONG(LOADADDR(.data));
LONG( ADDR(.data)) ;
LONG( SIZEOF(.data));
LONG(LOADADDR(.data_RAM2));
LONG( ADDR(.data_RAM2)) ;
LONG( SIZEOF(.data_RAM2));
__data_section_table_end = .;
__bss_section_table = .;
LONG( ADDR(.bss));
LONG( SIZEOF(.bss));
LONG( ADDR(.bss_RAM2));
LONG( SIZEOF(.bss_RAM2));
__bss_section_table_end = .;
__section_table_end = . ;
/* End of Global Section Table */
*(.after_vectors*)
*(.text*)
*(.rodata .rodata.*)
. = ALIGN(4);
} > MFlash512
/*
* for exception handling/unwind - some Newlib functions (in common
* with C++ and STDC++) use this.
* Use KEEP so not discarded with --gc-sections
*/
.ARM.extab : ALIGN(4)
{
KEEP(*(.ARM.extab* .gnu.linkonce.armextab.*))
} > MFlash512
__exidx_start = .;
.ARM.exidx : ALIGN(4)
{
KEEP(*(.ARM.exidx* .gnu.linkonce.armexidx.*))
} > MFlash512
__exidx_end = .;
_etext = .;
.data_RAM2 : ALIGN(4)
{
FILL(0xff)
*(.data.$RAM2*)
*(.data.$RamAHB32*)
. = ALIGN(4) ;
} > RamAHB32 AT>MFlash512
/* MAIN DATA SECTION */
.uninit_RESERVED : ALIGN(4)
{
KEEP(*(.bss.$RESERVED*))
. = ALIGN(4) ;
_end_uninit_RESERVED = .;
} > RamLoc32
.data : ALIGN(4)
{
FILL(0xff)
_data = .;
*(vtable)
*(.data*)
. = ALIGN(4) ;
_edata = .;
} > RamLoc32 AT>MFlash512
.bss_RAM2 : ALIGN(4)
{
*(.bss.$RAM2*)
*(.bss.$RamAHB32*)
. = ALIGN(4) ;
} > RamAHB32
/* MAIN BSS SECTION */
.bss : ALIGN(4)
{
__bss_start__ = . ;
_bss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4) ;
__bss_end__ = . ;
_ebss = .;
PROVIDE(end = .);
} > RamLoc32
PROVIDE(_pvHeapStart = .);
PROVIDE(_vStackTop = __top_RamLoc32 - 0);
}

View File

@@ -90,5 +90,5 @@ all_tests:
make run_test "TEST_NAME=sem9"
run_last:
qemu-system-arm -M integratorcp -kernel boot.elf -monitor stdio -semihosting
qemu-system-arm -M integratorcp -kernel boot.elf -semihosting

View File

@@ -0,0 +1,15 @@
---------------------------------------------------------------------------
Library: Atomthreads QEMU ARM Integrator/CP (ARM926EJ-S) Platform.
Author: Natie van Rooyen <natie@navaro.nl>
License: BSD Revised
---------------------------------------------------------------------------
QEMU ARM Integrator/CP (ARM926EJ-S) Platform
The "qemu_integratorcp" platform contains sources for building a sample
Atomthreads application for the ARM Integrator/CP (ARM926EJ-S) platform.
BUGS:
kern4 testcase fails (sometimes).

View File

@@ -1,79 +1,79 @@
/*
* 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
* 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.
*/
#include <stdio.h>
#include "modules.h"
#include "atom.h"
#include "tests/atomtests.h"
#ifndef ATOMTHREADS_TEST
#define ATOMTHREADS_TEST "kern1"
#endif
#define TEST_STACK_BYTE_SIZE 1024
#define IDLE_STACK_BYTE_SIZE 512
static unsigned char test_stack[TEST_STACK_BYTE_SIZE] ;
static unsigned char idle_stack[IDLE_STACK_BYTE_SIZE] ;
ATOM_TCB test_tcb ;
/**
* \b test_thread
*
* Function calling the test function of the Atomthreads test suite.
*
*/
void
test_thread (uint32_t param)
{
uint32_t failures ;
failures = test_start () ;
/*
* 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
* 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.
*/
#include <stdio.h>
#include "modules.h"
#include "atom.h"
#include "tests/atomtests.h"
#ifndef ATOMTHREADS_TEST
#define ATOMTHREADS_TEST "kern1"
#endif
#define TEST_STACK_BYTE_SIZE 1024
#define IDLE_STACK_BYTE_SIZE 512
static unsigned char test_stack[TEST_STACK_BYTE_SIZE] ;
static unsigned char idle_stack[IDLE_STACK_BYTE_SIZE] ;
ATOM_TCB test_tcb ;
/**
* \b test_thread
*
* Function calling the test function of the Atomthreads test suite.
*
*/
void
test_thread (uint32_t param)
{
uint32_t failures ;
failures = test_start () ;
printf ("%s %s\r\n", ATOMTHREADS_TEST, failures ? "FAIL" : "PASS") ;
return;
}
/**
* \b main
*
* Initialize atomthreads and start a test_thread to run the Atomthreads test suite.
*
*/
int
main (void)
{
printf ("atomthreads starting %s... ", ATOMTHREADS_TEST) ;
atomOSInit(&idle_stack[0], IDLE_STACK_BYTE_SIZE, TRUE) ;
atomThreadCreate ((ATOM_TCB *)&test_tcb, TEST_THREAD_PRIO, test_thread, 0, &test_stack[0], TEST_STACK_BYTE_SIZE, FALSE);
atomOSStart() ;
return 0 ;
}
}
/**
* \b main
*
* Initialize atomthreads and start a test_thread to run the Atomthreads test suite.
*
*/
int
main (void)
{
printf ("atomthreads starting %s... ", ATOMTHREADS_TEST) ;
atomOSInit(&idle_stack[0], IDLE_STACK_BYTE_SIZE, TRUE) ;
atomThreadCreate ((ATOM_TCB *)&test_tcb, TEST_THREAD_PRIO, test_thread, 0, &test_stack[0], TEST_STACK_BYTE_SIZE, TRUE);
atomOSStart() ;
return 0 ;
}

View File

@@ -56,16 +56,16 @@ ICP_PIC_T * const board_pic = (ICP_PI
void
dbg_format_msg (char *format, ...)
{
va_list args;
static char msg[256] ;
va_list args;
static char msg[256] ;
CRITICAL_STORE ;
va_start (args, format) ;
CRITICAL_START() ;
vsnprintf ((char*)msg, 256, (char*)format, args) ;
vsnprintf ((char*)msg, 256, (char*)format, args) ;
printf (msg) ;
CRITICAL_END() ;
printf (msg) ;
}

View File

@@ -29,16 +29,12 @@
#ifndef __MODULES_H__
#define __MODULES_H__
/*
* Module definitions to use with the ARM Integrator/CP (ARM926EJ-S)
*/
#include "atomport.h"
extern void dbg_format_msg (char *format, ...) ;
#define DBG_MESSAGE(fmt_str) { dbg_format_msg fmt_str ; }
typedef volatile unsigned int REG_DWORD ;// Hardware register definition
typedef volatile unsigned short REG_WORD ;
typedef volatile unsigned char REG_BYTE ;
// *****************************************************************************
@@ -46,34 +42,34 @@ typedef volatile unsigned char REG_BYTE ;
// *****************************************************************************
typedef struct ICP_TIMER_S {
// offset read/write word size reset Description
REG_DWORD LOAD ; // 0x0000 Read/write 32 0x00000000 Load value for Timer
REG_DWORD VALUE ; // 0x0004 Read 32 0xFFFFFFFF The current value for Timer
REG_BYTE CONTROL ; // 0x0008 Read/write 8 0x20 Timer control register
REG_DWORD INTCLR ; // 0x000C Write - - Timer interrupt clear
REG_DWORD RIS ; // 0x0010 Read 1 0x0 Timer raw interrupt status
REG_DWORD MIS ; // 0x0014 Read 1 0x0 Timer masked interrupt status
REG_DWORD BGLOAD ; // 0x0018 Read/write 32 0x00000000 Background load value for Timer
__IO uint32_t LOAD ; // 0x0000 Read/write 32 0x00000000 Load value for Timer
__I uint32_t VALUE ; // 0x0004 Read 32 0xFFFFFFFF The current value for Timer
__IO uint8_t CONTROL ; // 0x0008 Read/write 8 0x20 Timer control register
__O uint32_t INTCLR ; // 0x000C Write - - Timer interrupt clear
__I uint32_t RIS ; // 0x0010 Read 1 0x0 Timer raw interrupt status
__I uint32_t MIS ; // 0x0014 Read 1 0x0 Timer masked interrupt status
__IO uint32_t BGLOAD ; // 0x0018 Read/write 32 0x00000000 Background load value for Timer
} ICP_TIMER_T, *PICP_TIMER_T ;
// -------- ICP_TIMER_LOAD : (LOAD Offset: 0x00) Load value for Timer --------
// -------- ICP_TIMER_VALUE : (LOAD Offset: 0x04) The current value for Timer --------
// -------- ICP_TIMER_CONTROL : (CONTROL Offset: 0x04) Timer control register --------
#define ICP_TIMER_CONTROL_MASK ((unsigned int)0x0F << 0) // Timer control mask
#define ICP_TIMER_CONTROL_ENABLE ((unsigned int)0x01 << 7) // Timer enable: 0 = disabled 1 = enabled.
#define ICP_TIMER_CONTROL_MODE ((unsigned int)0x01 << 6) // Timer mode: 0 = free running, counts once and then wraps to 0xFFFF 1 = periodic, reloads from load register at the end of each count..
#define ICP_TIMER_CONTROL_IE ((unsigned int)0x01 << 5) // Interrupt enable.
#define ICP_TIMER_CONTROL_R ((unsigned int)0x01 << 4) // Unused, always write as 0s.
#define ICP_TIMER_CONTROL_PRESCALE_MASK ((unsigned int)0x03 << 2) // Prescale divisor
#define ICP_TIMER_CONTROL_PRESCALE_NONE ((unsigned int)0x00 << 2) //
#define ICP_TIMER_CONTROL_PRESCALE_16 ((unsigned int)0x01 << 2) //
#define ICP_TIMER_CONTROL_PRESCALE_256 ((unsigned int)0x02 << 2) //
#define ICP_TIMER_CONTROL_TIMER_SIZE ((unsigned int)0x01 << 1) // Selects 16/32 bit counter operation: 0 = 16-bit counter (default) 1 = 32-bit counter For 16-bit mode, write the high 16 bits of the 32-bit value as 0.
#define ICP_TIMER_CONTROL_ONE_SHOT ((unsigned int)0x01 << 0) // Selects one-shot or wrapping counter mode: 0 = wrapping mode (default) 1 = one-shot mode
#define ICP_TIMER_CONTROL_MASK ((unsigned int)0x0F << 0) // Timer control mask
#define ICP_TIMER_CONTROL_ENABLE ((unsigned int)0x01 << 7) // Timer enable: 0 = disabled 1 = enabled.
#define ICP_TIMER_CONTROL_MODE ((unsigned int)0x01 << 6) // Timer mode: 0 = free running, counts once and then wraps to 0xFFFF 1 = periodic, reloads from load register at the end of each count..
#define ICP_TIMER_CONTROL_IE ((unsigned int)0x01 << 5) // Interrupt enable.
#define ICP_TIMER_CONTROL_R ((unsigned int)0x01 << 4) // Unused, always write as 0s.
#define ICP_TIMER_CONTROL_PRESCALE_MASK ((unsigned int)0x03 << 2) // Prescale divisor
#define ICP_TIMER_CONTROL_PRESCALE_NONE ((unsigned int)0x00 << 2) //
#define ICP_TIMER_CONTROL_PRESCALE_16 ((unsigned int)0x01 << 2) //
#define ICP_TIMER_CONTROL_PRESCALE_256 ((unsigned int)0x02 << 2) //
#define ICP_TIMER_CONTROL_TIMER_SIZE ((unsigned int)0x01 << 1) // Selects 16/32 bit counter operation: 0 = 16-bit counter (default) 1 = 32-bit counter For 16-bit mode, write the high 16 bits of the 32-bit value as 0.
#define ICP_TIMER_CONTROL_ONE_SHOT ((unsigned int)0x01 << 0) // Selects one-shot or wrapping counter mode: 0 = wrapping mode (default) 1 = one-shot mode
// -------- ICP_TIMER_INTCLR : (INTCLR Offset: 0x0C) Timer interrupt clear --------
// -------- ICP_TIMER_RIS : (RIS Offset: 0x10) Timer raw interrupt status --------
// -------- ICP_TIMER_MIS : (MIS Offset: 0x14) Timer masked interrupt status --------
#define ICP_TIMER_INT ((unsigned int)0x01 << 0) // Interrupt
#define ICP_TIMER_INT ((unsigned int)0x01 << 0) // Interrupt
// -------- ICP_TIMER_BGLOAD : (BGLOAD Offset: 0x18) Timer masked interrupt status --------
@@ -82,17 +78,17 @@ typedef struct ICP_TIMER_S {
// *****************************************************************************
typedef struct ICP_PIC_S {
// offset read/write word size reset Description
REG_DWORD IRQ_STATUS ; // 0x0000 Read 22 IRQ gated interrupt status
REG_DWORD IRQ_RAWSTAT ; // 0x0004 Read 22 IRQ raw interrupt status
REG_DWORD IRQ_ENABLESET ; // 0x0008 Read/write 22 IRQ enable set
REG_DWORD IRQ_ENABLECLR ; // 0x000C Write 22 IRQ enable clear
REG_DWORD INT_SOFTSET ; // 0x0010 Read/write 16 Software interrupt set
REG_DWORD INT_SOFTCLR ; // 0x0014 Write 16 Software interrupt clear
REG_DWORD RESERVED[2] ; // 0x0018
REG_DWORD FIQ_STATUS ; // 0x0020 Read 22 FIQ gated interrupt status
REG_DWORD FIQ_RAWSTAT ; // 0x0024 Read 22 FIQ raw interrupt status
REG_DWORD FIQ_ENABLESET ; // 0x0028 Read/write 22 FIQ enable set
REG_DWORD FIQ_ENABLECLR ; // 0x002C Write-only 22 FIQ enable clear
__I uint32_t IRQ_STATUS ; // 0x0000 Read 22 IRQ gated interrupt status
__I uint32_t IRQ_RAWSTAT ; // 0x0004 Read 22 IRQ raw interrupt status
__IO uint32_t IRQ_ENABLESET ; // 0x0008 Read/write 22 IRQ enable set
__O uint32_t IRQ_ENABLECLR ; // 0x000C Write 22 IRQ enable clear
__IO uint32_t INT_SOFTSET ; // 0x0010 Read/write 16 Software interrupt set
__O uint32_t INT_SOFTCLR ; // 0x0014 Write 16 Software interrupt clear
uint32_t RESERVED[2] ; // 0x0018
__I uint32_t FIQ_STATUS ; // 0x0020 Read 22 FIQ gated interrupt status
__I uint32_t FIQ_RAWSTAT ; // 0x0024 Read 22 FIQ raw interrupt status
__IO uint32_t FIQ_ENABLESET ; // 0x0028 Read/write 22 FIQ enable set
__O uint32_t FIQ_ENABLECLR ; // 0x002C Write-only 22 FIQ enable clear
} ICP_PIC_T, *PICP_PIC_T ;
@@ -100,25 +96,29 @@ typedef struct ICP_PIC_S {
// -------- ICP_PIC_IRQ_RAWSTAT : (IRQ_RAWSTAT Offset: 0x04) IRQ raw interrupt status --------
// -------- ICP_PIC_IRQ_ENABLESET : (IRQ_ENABLESET Offset: 0x08) IRQ enable set --------
// -------- ICP_PIC_IRQ_ENABLECLR : (IRQ_ENABLECLR Offset: 0x0C) IRQ enable clear --------
#define ICP_PIC_IRQ_MASK ((unsigned int)0x3FFFFF << 0) // IRQ mask
#define ICP_PIC_IRQ_TIMERINT2 ((unsigned int)0x01 << 7) // TIMERINT2 Counter-timer 2 interrupt
#define ICP_PIC_IRQ_TIMERINT1 ((unsigned int)0x01 << 6) // TIMERINT1 Counter-timer 1 interrupt
#define ICP_PIC_IRQ_TIMERINT0 ((unsigned int)0x01 << 5) // TIMERINT0 Counter-timer 0 interrupt
#define ICP_PIC_IRQ_SOFTINT ((unsigned int)0x01 << 0) // OFTINT Software interrupt
#define ICP_PIC_IRQ_MASK ((unsigned int)0x3FFFFF << 0) // IRQ mask
#define ICP_PIC_IRQ_TIMERINT2 ((unsigned int)0x01 << 7) // TIMERINT2 Counter-timer 2 interrupt
#define ICP_PIC_IRQ_TIMERINT1 ((unsigned int)0x01 << 6) // TIMERINT1 Counter-timer 1 interrupt
#define ICP_PIC_IRQ_TIMERINT0 ((unsigned int)0x01 << 5) // TIMERINT0 Counter-timer 0 interrupt
#define ICP_PIC_IRQ_SOFTINT ((unsigned int)0x01 << 0) // OFTINT Software interrupt
// -------- ICP_PIC_INT_SOFTSET : (INT_SOFTSET Offset: 0x10) Software interrupt set --------
// -------- ICP_PIC_INT_SOFTCLR : (INT_SOFTCLR Offset: 0x14) Software interrupt clear --------
#define BOARD_BASE_ADDRESS_TIMER_0 0x13000000
#define BOARD_BASE_ADDRESS_PIC 0x14000000
/* module definitions */
#define BOARD_BASE_ADDRESS_TIMER_0 0x13000000
#define BOARD_BASE_ADDRESS_PIC 0x14000000
extern ICP_TIMER_T* const board_timer_0 ;
extern ICP_PIC_T* const board_pic ;
/* Function prototypes */
extern int low_level_init (void) ;
extern void dbg_format_msg (char *format, ...) ;
#define DBG_MESSAGE(fmt_str) { dbg_format_msg fmt_str ; }
#endif /* __MODULES_H__ */

View File

@@ -1,13 +1,9 @@
.section .vectors, "x"
.global __interrupt_vector_table
.global __irq_stack_top__
.global __fiq_stack_top__
.global __svc_stack_top__
.global bsp_ints_enable
.global bsp_ints_disable
.global bsp_ints_restore
.extern __irq_stack_top__
.extern __fiq_stack_top__
.extern __svc_stack_top__
.equ USR_MODE, 0x10

View File

@@ -82,10 +82,6 @@ SECTIONS
__stack_end__ = .;
} >sram
/*DISCARD :
{
*(.eh_*)
}*/
}
__end__ = .;
_end = .;

View File

@@ -0,0 +1,96 @@
ifeq ($(TARGET_NAME),)
TARGET_NAME=boot
endif
ifeq ($(ATOMTHREADS),)
ATOMTHREADS = $(shell pwd)/../../
endif
ifeq ($(TEST_NAME),)
TEST_NAME = kern1
endif
CC = arm-none-eabi-gcc
LN = arm-none-eabi-gcc
AS = arm-none-eabi-gcc
CFLAGS := $(CFLAGS) -Wall -g -c -mcpu=cortex-m3 -mthumb -mthumb-interwork -ffreestanding
AFLAGS := $(AFLAGS) -Wall -g -c -mcpu=cortex-m3 -mthumb -mthumb-interwork -ffreestanding
LFLAGS := $(LFLAGS) -Wall -mcpu=cortex-m3 -mthumb -Wl,-Map=system.map -Tsystem.ld
CDEFS := $(CDEFS) -DATOMTHREADS_TEST='"$(TEST_NAME)"' -DPLATFORM_QEMU_LM3S_HACK
ADEFS := $(ADEFS) -D__thumb2__ -DARM_RDI_MONITOR -DPLATFORM_QEMU_LM3S_HACK
LLIBS := $(LLIBS)
SRCS := $(SRCS) \
modules.c \
main.c \
$(ATOMTHREADS)/tests/$(TEST_NAME).c \
ASMS := $(ASMS) \
startup.S \
INCLUDES := $(INCLUDES) \
-I$(ATOMTHREADS)
include $(ATOMTHREADS)/ports/cortex_m/Makefile
OBJS = $(SRCS:.c=.o) $(ASMS:.S=.o)
include ../rules.mk
run_test: clean all
echo "START TEST $(TEST_NAME)"
qemu-system-arm -M lm3s6965evb -kernel boot.elf -semihosting >> atomthreads_test.out
all_tests:
echo "Starting atomthreads test suite" > atomthreads_test.out
make run_test "TEST_NAME=mutex1"
make run_test "TEST_NAME=mutex2"
make run_test "TEST_NAME=mutex3"
make run_test "TEST_NAME=mutex5"
make run_test "TEST_NAME=mutex6"
make run_test "TEST_NAME=mutex7"
make run_test "TEST_NAME=mutex8"
make run_test "TEST_NAME=mutex9"
make run_test "TEST_NAME=kern1"
make run_test "TEST_NAME=kern2"
make run_test "TEST_NAME=kern3"
make run_test "TEST_NAME=kern4"
make run_test "TEST_NAME=timer1"
make run_test "TEST_NAME=timer2"
make run_test "TEST_NAME=timer3"
make run_test "TEST_NAME=timer5"
make run_test "TEST_NAME=timer6"
make run_test "TEST_NAME=timer7"
make run_test "TEST_NAME=queue1"
make run_test "TEST_NAME=queue2"
make run_test "TEST_NAME=queue3"
make run_test "TEST_NAME=queue4"
make run_test "TEST_NAME=queue5"
make run_test "TEST_NAME=queue6"
make run_test "TEST_NAME=queue7"
make run_test "TEST_NAME=queue8"
make run_test "TEST_NAME=queue9"
make run_test "TEST_NAME=sem1"
make run_test "TEST_NAME=sem2"
make run_test "TEST_NAME=sem3"
make run_test "TEST_NAME=sem5"
make run_test "TEST_NAME=sem6"
make run_test "TEST_NAME=sem7"
make run_test "TEST_NAME=sem8"
make run_test "TEST_NAME=sem9"
fail_tests:
make run_test "TEST_NAME=mutex4"
make run_test "TEST_NAME=timer4"
make run_test "TEST_NAME=sem4"
run_last:
qemu-system-arm -M lm3s6965evb -kernel boot.elf -semihosting

View File

@@ -0,0 +1,37 @@
---------------------------------------------------------------------------
Library: Atomthreads QEMU Stellaris LM3S6965 Platform.
Author: Natie van Rooyen <natie@navaro.nl>
License: BSD Revised
---------------------------------------------------------------------------
QEMU Stellaris LM3S6965 Platform
The "qemu_lm3s" platform contains sources for building a sample Atomthreads
application for the Stellaris LM3S6965 platform.
ISSUES:
There seems to be several problems for the QEMU Cortex M3 processor. The
platform and port contains specific hacks to make it work on the QEMU 1.2.0
release it was tested on. Also see the latest patches for QEMU.
Fixes implemented for the QEMU 1.2.0 release:
1. Install the patch http://patchwork.ozlabs.org/patch/180315/
2. Use the PLATFORM_QEMU_LM3S_HACK define in the Makefile:
- Disabling interrupts on the processor does not work (verified).
- Disabling interrupts of the Cortex M Sys Tick Interrupt does not
work (verified).
- NVIC Interrupt priorities not implemented correctly (not verified).
Because of the problems with the Sys Tick Interrupt the The Stellaris
General-Purpose Timer Module (GPTM) was used to generate the system timer
tick.
BUGS:
mutex4 testcase fails.
sem4 testcase fails.

View File

@@ -0,0 +1,88 @@
/*
* 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
* 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.
*/
#include <stdio.h>
#include "modules.h"
#include "atom.h"
#include "tests/atomtests.h"
#ifndef ATOMTHREADS_TEST
#define ATOMTHREADS_TEST "kern1"
#endif
#define TEST_STACK_BYTE_SIZE 1024
#define IDLE_STACK_BYTE_SIZE 512
static unsigned char test_stack[TEST_STACK_BYTE_SIZE] ;
static unsigned char idle_stack[IDLE_STACK_BYTE_SIZE] ;
ATOM_TCB test_tcb ;
/**
* \b test_thread
*
* Function calling the test function of the Atomthreads test suite.
*
*/
void
test_thread (uint32_t param)
{
uint32_t failures ;
CRITICAL_STORE ;
failures = test_start () ;
atomTimerDelay (10) ;
CRITICAL_START() ;
printf ("%s %s\r\n", ATOMTHREADS_TEST, failures ? "FAIL" : "PASS") ;
exit (failures) ;
CRITICAL_END() ;
}
/**
* \b main
*
* Initialize atomthreads and start a test_thread to run the Atomthreads test suite.
*
*/
int
main (void)
{
int i = 0 ;
uint32_t failures ;
printf ("Atomthreads starting %s... \r\n", ATOMTHREADS_TEST) ;
atomOSInit(&idle_stack[0], IDLE_STACK_BYTE_SIZE, TRUE) ;
atomThreadCreate ((ATOM_TCB *)&test_tcb, TEST_THREAD_PRIO, test_thread, 0, &test_stack[0], TEST_STACK_BYTE_SIZE, TRUE);
atomOSStart() ;
return 0 ;
}

View File

@@ -0,0 +1,164 @@
/*
* 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
* 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.
*/
#include "modules.h"
#include <stdio.h>
#include <stdarg.h>
#include "atomport_private.h"
#include "atom.h"
#include "atomport.h"
#include "types.h"
SYSTICK_T* const board_systick = (SYSTICK_T*) BOARD_BASE_ADDRESS_SYSTICK ;
NVIC_T* const board_nvic = (NVIC_T*) BOARD_BASE_ADDRESS_NVIC ;
SCB_T * const board_scb = (SCB_T*) BOARD_BASE_ADDRESS_SCB ;
GPTM_TIMER_T * const board_gptm0 = (GPTM_TIMER_T*) BOARD_BASE_ADDRESS_GPTIMER0 ;
/**
* \b dbg_format_msg
*
* Same as printf.
*
*/
void
dbg_format_msg (char *format, ...)
{
va_list args;
static char msg[256] ;
CRITICAL_STORE ;
va_start (args, format) ;
CRITICAL_START() ;
vsnprintf ((char*)msg, 256, (char*)format, args) ;
printf (msg) ;
CRITICAL_END() ;
}
/**
* \b low_level_init
*
* Initializes the PIC and start the system timer tick intrerupt.
*
*/
int
low_level_init (void)
{
contextInit () ;
//board_systick->STRELOAD = 0x010000 ;
//board_systick->STCTRL = NVIC_STCTRL_CLK |
// NVIC_STCTRL_INTEN |
// NVIC_STCTRL_ENABLE ;
board_gptm0->CTL &= ~GPTM_TIMER_CTL_TAEN ;
board_gptm0->CFG = 0 ;
board_gptm0->TAMR = GPTM_TIMER_TMR_TMR_PERIODIC ;
board_gptm0->TAILR = 0x10000 ;
board_gptm0->IMR |= GPTM_TIMER_INT_TATOIM ;
board_gptm0->CTL |= GPTM_TIMER_CTL_TAEN ;
// board_nvic->ISER[0] = 0x80000 ;
return 0 ;
}
/**
* \b __context_tick_handler
*
* System timer tic interupt handler.
*
*/
void
__context_tick_handler (void)
{
atomIntEnter();
/* Call the OS system tick handler */
atomTimerTick();
board_gptm0->ICR |= GPTM_TIMER_INT_TATOIM ;
/* Call the interrupt exit routine */
atomIntExit(TRUE);
}
/**
* \b dbg_hard_fault_handler_c
*
* Dumps the registers pushed on the stack after a fault.
*
*/
void
dbg_hard_fault_handler_c (unsigned int * hardfault_args)
{
unsigned int stacked_r0;
unsigned int stacked_r1;
unsigned int stacked_r2;
unsigned int stacked_r3;
unsigned int stacked_r12;
unsigned int stacked_lr;
unsigned int stacked_pc;
unsigned int stacked_psr;
stacked_r0 = ((unsigned long) hardfault_args[0]);
stacked_r1 = ((unsigned long) hardfault_args[1]);
stacked_r2 = ((unsigned long) hardfault_args[2]);
stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);
printf ("\r\n\r\n[Hard fault handler - all numbers in hex]\r\n");
printf ("SP = 0x%x\r\n", hardfault_args);
printf ("R0 = 0x%x\r\n", stacked_r0);
printf ("R1 = 0x%x\r\n", stacked_r1);
printf ("R2 = 0x%x\r\n", stacked_r2);
printf ("R3 = 0x%x\r\n", stacked_r3);
printf ("R12 = 0x%x\r\n", stacked_r12);
printf ("LR [R14] = 0x%x subroutine call return address\r\n", stacked_lr);
printf ("PC [R15] = 0x%x program counter\r\n", stacked_pc);
printf ("PSR = 0x%x\r\n", stacked_psr);
//printf ("BFAR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED38))));
//printf ("CFSR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED28))));
//printf ("HFSR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED2C))));
//printf ("DFSR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED30))));
//printf ("AFSR = 0x%x\r\n", (*((volatile unsigned long *)(0xE000ED3C))));
// printf ("SCB_SHCSR = %x\n", SCB->SHCSR);
while (1);
}

View File

@@ -0,0 +1,208 @@
/*
* 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
* 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 __MODULES_H__
#define __MODULES_H__
/*
* Module definitions to use with the Stellaris LM3S6965 Microcontroller
*/
#include "atomport.h"
// *****************************************************************************
// The Stellaris General-Purpose Timer Module (GPTM)
// *****************************************************************************
typedef struct GPTM_TIMER_S {
// offset read/write reset Description
__IO uint32_t CFG ; // 0x000 R/W 0x00000000 GPTM Configuration 345
__IO uint32_t TAMR ; // 0x004 R/W 0x00000000 GPTM TimerA Mode 346
__IO uint32_t TBMR ; // 0x008 R/W 0x00000000 GPTM TimerB Mode 348
__IO uint32_t CTL ; // 0x00C R/W 0x00000000 GPTM Control 350
uint32_t Reserved[2] ; // 0x010
__IO uint32_t IMR ; // 0x018 R/W 0x00000000 GPTM Interrupt Mask 353
__I uint32_t RIS ; // 0x01C RO 0x00000000 GPTM Raw Interrupt Status 355
__I uint32_t MIS ; // 0x020 RO 0x00000000 GPTM Masked Interrupt Status 356
__O uint32_t ICR ; // 0x024 W1C 0x00000000 GPTM Interrupt Clear 357
__IO uint32_t TAILR ; // 0x028 R/W 0xFFFFFFFF GPTM TimerA Interval Load 359
__IO uint32_t TBILR ; // 0x02C R/W 0x0000FFFF GPTM TimerB Interval Load 360
__IO uint32_t TAMATCHR ; // 0x030 R/W 0xFFFFFFFF GPTM TimerA Match 361
__IO uint32_t TBMATCHR ; // 0x034 R/W 0x0000FFFF GPTM TimerB Match 362
__IO uint32_t TAPR ; // 0x038 R/W 0x00000000 GPTM TimerA Prescale 363
__IO uint32_t TBPR ; // 0x03C R/W 0x00000000 GPTM TimerB Prescale 364
__IO uint32_t TAPMR ; // 0x040 R/W 0x00000000 GPTM TimerA Prescale Match 365
__IO uint32_t TBPMR ; // 0x044 R/W 0x00000000 GPTM TimerB Prescale Match 366
__I uint32_t TAR ; // 0x048 RO 0xFFFFFFFF GPTM TimerA 367
__I uint32_t TBR ; // 0x04C RO 0x0000FFFF GPTM TimerB 368
} GPTM_TIMER_T, *PGPTM_TIMER_T ;
// -------- GPTM_TIMER_CFG : (CFG Offset: 0x00) This register configures the global operation of the GPTM module --------
#define GPTM_TIMER_CFG_MASK ((unsigned int)0x07 << 0) //
#define GPTM_TIMER_CFG_32BIT ((unsigned int)0x00 << 0) // 32-bit timer configuration
#define GPTM_TIMER_CFG_32BIT_RT ((unsigned int)0x01 << 0) // 32-bit real-time clock (RTC) counter configuration
// -------- GPTM_TIMER_TAMR : (TAMR Offset: 0x04) This register configures the GPTM based on the configuration selected in the GPTMCFG register --------
// -------- GPTM_TIMER_TBMR : (TBMR Offset: 0x08) This register configures the GPTM based on the configuration selected in the GPTMCFG register --------
#define GPTM_TIMER_TMR_TAMS ((unsigned int)0x01 << 3) // GPTM TimerA Alternate Mode Select. 0 Capture mode is enabled. 1 PWM mode is enabled
#define GPTM_TIMER_TMR_TCMR ((unsigned int)0x01 << 2) // GPTM TimerA Capture Mode. 0 Edge-Count mode. 1 Edge-Time mode.
#define GPTM_TIMER_TMR_TMR_ONE_SHOT ((unsigned int)0x01 << 0) // One-Shot Timer mode
#define GPTM_TIMER_TMR_TMR_PERIODIC ((unsigned int)0x02 << 0) // Periodic Timer mode
#define GPTM_TIMER_TMR_TMR_CAPTURE ((unsigned int)0x03 << 0) // Capture mode
// -------- GPTM_TIMER_CTL : (CTL Offset: 0x0C) This register is used alongside the GPTMCFG and GMTMTnMR registers to fine-tune the timer configuration --------
#define GPTM_TIMER_CTL_TBPWML ((unsigned int)0x01 << 14) // GPTM TimerB PWM Output Level. 0 Output is unaffected. 1 Output is inverted.
#define GPTM_TIMER_CTL_TBOTE ((unsigned int)0x01 << 13) // GPTM TimerB Output Trigger Enable. 0 The output TimerB ADC trigger is disabled. 1 The output TimerB ADC trigger is enabled.
#define GPTM_TIMER_CTL_TBEVENT_MASK ((unsigned int)0x03 << 10) // GPTM TimerB Event Mode
#define GPTM_TIMER_CTL_TBEVENT_PE ((unsigned int)0x00 << 10) // Positive edge
#define GPTM_TIMER_CTL_TBEVENT_NE ((unsigned int)0x01 << 10) // Negative edge
#define GPTM_TIMER_CTL_TBEVENT ((unsigned int)0x03 << 10) // Both edges
#define GPTM_TIMER_CTL_TBSTALL ((unsigned int)0x01 << 9) // GPTM Timer B Stall Enable. 0 Timer B continues counting while the processor is halted by the debugger
#define GPTM_TIMER_CTL_TBEN ((unsigned int)0x01 << 8) // GPTM TimerB Enable
// --------
#define GPTM_TIMER_CTL_TAPWML ((unsigned int)0x01 << 6) // GPTM TimerA PWM Output Level. 0 Output is unaffected. 1 Output is inverted.
#define GPTM_TIMER_CTL_TAOTE ((unsigned int)0x01 << 5) // GPTM TimerA Output Trigger Enable. 0 The output TimerB ADC trigger is disabled. 1 The output TimerB ADC trigger is enabled.
#define GPTM_TIMER_CTL_RTCEN ((unsigned int)0x01 << 4) // GPTM RTC Enable
#define GPTM_TIMER_CTL_TAEVENT_MASK ((unsigned int)0x03 << 2) // GPTM TimerA Event Mode
#define GPTM_TIMER_CTL_TAEVENT_PE ((unsigned int)0x00 << 2) // Positive edge
#define GPTM_TIMER_CTL_TAEVENT_NE ((unsigned int)0x01 << 2) // Negative edge
#define GPTM_TIMER_CTL_TAEVENT ((unsigned int)0x03 << 2) // Both edges
#define GPTM_TIMER_CTL_TASTALL ((unsigned int)0x01 << 1) // GPTM Timer A Stall Enable. 0 Timer B continues counting while the processor is halted by the debugger
#define GPTM_TIMER_CTL_TAEN ((unsigned int)0x01 << 0) // GPTM TimerA Enable
// -------- GPTM_TIMER_IMR : (IMR Offset: 0x18) This register allows software to enable/disable GPTM controller-level interrupts. --------
// -------- GPTM_TIMER_RIS : (RIS Offset: 0x1C) This register shows the state of the GPTM's internal interrupt signal. --------
// -------- GPTM_TIMER_MIS : (MIS Offset: 0x20) This register show the state of the GPTM's controller-level interrupt. --------
// -------- GPTM_TIMER_ICR : (ICR Offset: 0x24) This register is used to clear the status bits in the GPTMRIS and GPTMMIS registers. --------
#define GPTM_TIMER_INT_CBEIM ((unsigned int)0x01 << 10) // GPTM CaptureB Event Interrupt Mask
#define GPTM_TIMER_INT_CBMIM ((unsigned int)0x01 << 9) // GPTM CaptureB Match Interrupt Mask
#define GPTM_TIMER_INT_TBTOIM ((unsigned int)0x01 << 8) // GPTM TimerB Time-Out Interrupt Mask
// --------
#define GPTM_TIMER_INT_RTCIM ((unsigned int)0x01 << 3) // GPTM RTC Interrupt Mask
#define GPTM_TIMER_INT_CAEIM ((unsigned int)0x01 << 2) // GPTM CaptureA Event Interrupt Mask
#define GPTM_TIMER_INT_CAMIM ((unsigned int)0x01 << 1) // GPTM CaptureA Match Interrupt Mask
#define GPTM_TIMER_INT_TATOIM ((unsigned int)0x01 << 0) // GPTM TimerA Time-Out Interrupt Mask
// *****************************************************************************
// Cortex M System Timer (SysTick)
// *****************************************************************************
typedef struct SYSTICK_S {
uint32_t Res0[1] ; // 0xE000E000
__IO uint32_t ICT ; // 0xE000E004
uint32_t Res1[2] ; // 0xE000E008
__IO uint32_t STCTRL ; // 0xE000E010
__IO uint32_t STRELOAD ; // 0xE000E014
__IO uint32_t STCURRENT; // 0xE000E018
__IO uint32_t STCALIB ; // 0xE000E01C
uint32_t Res2[56] ; // 0xE000E020
} SYSTICK_T, *PSYSTICK_T ;
// -------- SYSTICK_STCTRL : (STCTRL Offset: 0xE000E010) SysTick Control and Status Register --------
#define SYSTICK_STCTRL_COUNT ((unsigned int)0x1 << 16) // 0 - The SysTick timer has not counted to 0 since the last time this bit was read.
#define SYSTICK_STCTRL_CLK ((unsigned int)0x1 << 2) // 1 - System clock
#define SYSTICK_STCTRL_INTEN ((unsigned int)0x1 << 1) // 1 - An interrupt is generated to the NVIC when SysTick counts to 0.
#define SYSTICK_STCTRL_ENABLE ((unsigned int)0x1 << 1) // Enables SysTick to operate in a multi-shot way.
// -------- SYSTICK_STRELOAD : (STRELOAD Offset: 0xE000E014) Reload Value --------
#define SYSTICK_STRELOAD_MASK ((unsigned int)0xFFFFFF << 0) // IRQ mask
// -------- SYSTICK_STCURRENT : (STCURRENT Offset: 0xE000E018) SysTick Current Value Register --------
// *****************************************************************************
// Cortex M Nested Vectored Interrupt Controller
// *****************************************************************************
typedef struct NVIC_S {
__IO uint32_t ISER[2] ; // 0xE000E100
uint32_t Res3[30] ; // 0xE000E120
__IO uint32_t ICER[2] ; // 0xE000E180
uint32_t Res4[30] ; // 0xE000E1A0
__IO uint32_t ISPR[2] ; // 0xE000E200
uint32_t Res5[30] ; // 0xE000E220
__IO uint32_t ICPR[2] ; // 0xE000E280
uint32_t Res6[30] ; // 0xE000E2A0
__IO uint32_t IABR[2] ; // 0xE000E300
uint32_t Res7[64] ; // 0xE000E320
__IO uint32_t IPR[2] ; // 0xE000E400
// uint32_t Res7[515] ; // 0xE000E4F4
} NVIC_T, *PNVIC_T ;
#define NVIC_EXCEPTION_RESET 1
#define NVIC_EXCEPTION_NMI 2
#define NVIC_EXCEPTION_HARD_FAULT 3
#define NVIC_EXCEPTION_MEM_MANAGEMENT 4
#define NVIC_EXCEPTION_BUS_FAULT 5
#define NVIC_EXCEPTION_USAGE_FAULT 6
#define NVIC_EXCEPTION_SVCALL 11
#define NVIC_EXCEPTION_DEBUG_MON 12
#define NVIC_EXCEPTION_PEND_SV 14
#define NVIC_EXCEPTION_SYS_TICK 15
// *****************************************************************************
// System Control Block (SCB) Registers
// *****************************************************************************
typedef struct SCB_S {
__IO uint32_t CPUID ; // 0xE000ED00
__IO uint32_t ICSR ; // 0xE000ED04
__IO uint32_t VTOR ; // 0xE000ED08
__IO uint32_t AIRCR ; // 0xE000ED0C
__IO uint32_t SCR ; // 0xE000ED10
__IO uint32_t CCR ; // 0xE000ED14
__IO uint32_t SYS_PRIO[3] ; // 0xE000ED18
__IO uint32_t SYSHNDCTRL ; // 0xE000ED24
//__IO uint32_t FAULTSTAT ; // 0xE000ED28
//__IO uint32_t HFAULTSTAT ; // 0xE000ED2C
} SCB_T, *PSCB_T ;
/* module definitions */
#define BOARD_BASE_ADDRESS_SYSTICK 0xE000E000
#define BOARD_BASE_ADDRESS_NVIC 0xE000E100
#define BOARD_BASE_ADDRESS_SCB 0xE000ED00
#define BOARD_BASE_ADDRESS_GPTIMER0 0x40030000
extern SYSTICK_T* const board_systick ;
extern NVIC_T* const board_nvic ;
extern SCB_T* const board_scb ;
extern GPTM_TIMER_T* const board_gptm0 ;
/* Function prototypes */
extern int low_level_init (void) ;
extern void dbg_format_msg (char *format, ...) ;
extern void dbg_hard_fault_handler_c (unsigned int * hardfault_args) ;
#define DBG_MESSAGE(fmt_str) { dbg_format_msg fmt_str ; }
#endif /* __MODULES_H__ */

View File

@@ -0,0 +1,215 @@
/*
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
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.
*/
/* lm3s Startup Script */
.section .vectors,"x",%progbits
.syntax unified
.thumb
.global __interrupt_vector_table
.extern archTickHandler
.extern archPendSVHandler
.extern dbg_hard_fault_handler_c
/**
* \b __interrupt_vector_table
*
*/
__interrupt_vector_table:
.long __c_stack_top__
.long reset_Handler
.long fault_Handler
.long fault_Handler
.long fault_Handler
.long fault_Handler
.long fault_Handler
.long 0
.long 0
.long 0
.long 0
.long sys_Handler
.long sys_Handler
.long 0
.long archPendSVHandler
.long sys_Handler
/* External interrupts */
.long default_Handler // GPIO Port A
.long default_Handler // GPIO Port B
.long default_Handler // GPIO Port C
.long default_Handler // GPIO Port D
.long default_Handler // GPIO Port E
.long default_Handler // UART0 Rx and Tx
.long default_Handler // UART1 Rx and Tx
.long default_Handler // SSI0 Rx and Tx
.long default_Handler // I2C0 Master and Slave
.long default_Handler // PWM Fault
.long default_Handler // PWM Generator 0
.long default_Handler // PWM Generator 1
.long default_Handler // PWM Generator 2
.long default_Handler // Quadrature Encoder 0
.long default_Handler // ADC Sequence 0
.long default_Handler // ADC Sequence 1
.long default_Handler // ADC Sequence 2
.long default_Handler // ADC Sequence 3
.long default_Handler // Watchdog timer
.long archTickHandler // Timer 0 subtimer A
.long default_Handler // Timer 0 subtimer B
.long default_Handler // Timer 1 subtimer A
.long default_Handler // Timer 1 subtimer B
.long default_Handler // Timer 2 subtimer A
.long default_Handler // Timer 2 subtimer B
.long default_Handler // Analog Comparator 0
.long default_Handler // Analog Comparator 1
.long default_Handler // Analog Comparator 2
.long default_Handler // System Control (PLL, OSC, BO)
.long default_Handler // FLASH Control
.long default_Handler // GPIO Port F
.long default_Handler // GPIO Port G
.long default_Handler // GPIO Port H
.long default_Handler // UART2 Rx and Tx
.long default_Handler // SSI1 Rx and Tx
.long default_Handler // Timer 3 subtimer A
.long default_Handler // Timer 3 subtimer B
.long default_Handler // I2C1 Master and Slave
.long default_Handler // Quadrature Encoder 1
.long default_Handler // CAN0
.long default_Handler // CAN1
.long default_Handler // CAN2
.long default_Handler // Ethernet
.long default_Handler // Hibernate
/**
* \b sys_Handler
*
* @return None
*/
.thumb_func
sys_Handler:
B .
/**
* \b default_Handler
*
* @return None
*/
.thumb_func
default_Handler:
B .
/**
* \b fault_Handler
*
* @return None
*/
.thumb_func
fault_Handler:
tst lr, #4
ite eq
mrseq r0, MSP
mrsne r0, PSP
b dbg_hard_fault_handler_c
.section .startup,"x",%progbits
.syntax unified
.thumb
.global reset_Handler
.extern initialise_monitor_handles
.extern low_level_init
.extern main
/**
* \b reset_Handler
*
*
*
* @return None
*/
.thumb_func
reset_Handler:
/*
* Initialize the data and bss sections.
*/
init_data:
ldr r0, .ETEXT
ldr r1, .DATA
ldr r2, .EDATA
sub r2, r2, r1
cmp r2, #0
beq init_bss
init_data_copy:
ldrb r4, [r0], #1
strb r4, [r1], #1
subs r2, r2, #1
bne init_data_copy
init_bss:
mov r0, #0
ldr r1, = .BSS
ldr r2, = .EBSS
sub r2, r2, r1
cmp r2, #0
beq init_done
init_bss_zero:
strb r0, [r1], #1
subs r2, r2, #1
bne init_bss_zero
init_done:
/*
* The following call initializes the function pointers for stdio etc.
* These are used by the semihosting interface.
*
* This function is implemented in newlib.
*/
bl initialise_monitor_handles
/*
* Platform specific low level initialization.
*/
bl low_level_init
/*
* Call the application's entry point.
*/
bl main
.BSS: .long _bss
.EBSS: .long _ebss
.ETEXT: .long _etext
.DATA: .long _data
.EDATA: .long _edata
.end

View File

@@ -0,0 +1,72 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000
}
SECTIONS
{
_vRamTop = 0x20000000 + 0x00010000;
.text :
{
KEEP(*(.vectors))
*(.startup)
*(.text*)
*(.rodata*)
} > FLASH
/*
* for exception handling/unwind - some Newlib functions (in common with
* C++ and STDC++) use this.
*/
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
_etext = .;
.data : AT (__exidx_end)
{
_data = .;
*(vtable)
*(.data*)
_edata = .;
} > SRAM
/* zero initialized data */
.bss :
{
__bss_start__ = . ;
_bss = .;
*(.bss*)
*(COMMON)
__bss_end__ = . ;
_ebss = .;
} > SRAM
/* Where we put the heap with cr_clib */
.cr_heap :
{
end = .;
_pvHeapStart = .;
} > SRAM
_vStackTop = _vRamTop - 16;
.stack _vStackTop :
{
__c_stack_top__ = . ;
}
}

View File

@@ -20,6 +20,8 @@ all: target
target: $(OBJS)
$(LN) $(LFLAGS) $(LIBFLAGS) $(OBJS) $(LLIBS) -o $(TARGET_NAME).elf
@echo $(TARGET_NAME).elf was compiled
arm-none-eabi-objcopy -O binary $(TARGET_NAME).elf $(TARGET_NAME).bin
arm-none-eabi-objdump -dxS $(TARGET_NAME).elf > $(TARGET_NAME).out
clean:
rm -f $(OBJS)

View File

@@ -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.

View File

@@ -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 */
/* ... */
}

View File

@@ -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__ */

View File

@@ -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__ */

View File

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

View File

@@ -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__ */

40
ports/atomvm/README Normal file
View File

@@ -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.

View File

@@ -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__ */

View File

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

View File

@@ -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__ */

View File

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

View File

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

270
ports/atomvm/msvc/main.c Normal file
View File

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

View File

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

View File

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

View File

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

61
ports/atomvm/types.h Normal file
View File

@@ -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__ */

View File

@@ -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.

View File

@@ -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 */
/* ... */
}

View File

@@ -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__ */

View File

@@ -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__ */

View File

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

View File

@@ -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__ */

176
tests/stress1.c Normal file
View File

@@ -0,0 +1,176 @@
#include <stdio.h>
#include "stress1.h"
#include "atom.h"
#include "atommutex.h"
#include "atomsem.h"
#include "atomport.h"
#include "atomport-tests.h"
#define MAX_TEST_THREADS 36
static unsigned char idle_stack[IDLE_STACK_BYTE_SIZE] ;
static unsigned char monitor_stack[MONITOR_STACK_BYTE_SIZE] ;
static unsigned char stress_test_stack[MAX_TEST_THREADS+1][TEST_STACK_BYTE_SIZE] ;
static unsigned int test_counter[MAX_TEST_THREADS+1] = {0} ;
//static unsigned char test_idle_stack[TEST_STACK_BYTE_SIZE] ;
static uint8_t test_prio[120] = {
005,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,
005,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[120] = {
002,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,
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[MAX_TEST_THREADS+1] ;
ATOM_TCB monitor_tcb ;
ATOM_TCB test2_tcb ;
ATOM_TCB test3_tcb ;
ATOM_TCB test_idle_tcb ;
void
monitor_thread (uint32_t parm)
{
CRITICAL_STORE;
int i ;
unsigned int counter = 0 ;
ATOM_TCB *tcb ;
uint32_t print_lines_count = 0 ;
tcb = atomCurrentContext() ;
if (parm) {
print_lines_count = ((parm-1)>>2) + 1;
}
for (;;counter++)
{
uint32_t time = atomTimeGet() ;
CRITICAL_START();
ATOMLOG (_STR("\r\nMonitor %d threads # %d (%08d)\r\n"), parm, counter, (unsigned int)time) ;
ATOMLOG (_STR("------------------------------\r\n")) ;
//CRITICAL_END();
for (i=0; i<print_lines_count; i++) {
//CRITICAL_START();
ATOMLOG (_STR("Thr %.2d cnt %08d\tThr %.2d cnt %08d\tThr %.2d cnt %08d\tThr %.2d cnt %08d\r\n"),
i,test_counter[i],
i+print_lines_count,test_counter[i+print_lines_count],
i+print_lines_count*2,test_counter[i+print_lines_count*2],
i+print_lines_count*3,test_counter[i+print_lines_count*3]);
//CRITICAL_END();
}
CRITICAL_END();
atomTimerDelay (200) ;
}
}
void
stress_test_thread (uint32_t parm)
{
CRITICAL_STORE;
for (;;) {
CRITICAL_START();
test_counter[parm]++ ;
CRITICAL_END();
atomTimerDelay (test_interv[parm]) ;
}
}
uint32_t test_start (void)
{
uint32_t i ;
uint32_t failures = 0 ;
CRITICAL_STORE;
CRITICAL_START();
ATOMLOG (_STR("\r\natomthreads_stress_test %.3d threads\r\n"), TEST_THREADS) ;
ATOMLOG (_STR("-----------------------------------\r\n")) ;
CRITICAL_END();
for (i=0; i< TEST_THREADS;i++) {
CRITICAL_START();
ATOMLOG (_STR("stress_test_thread %.3d creating...\r\n"), i) ;
CRITICAL_END();
if (atomThreadCreate ((ATOM_TCB *)&test_tcb[i], test_prio[i], stress_test_thread, i,
&stress_test_stack[i][0], TEST_STACK_BYTE_SIZE, TRUE) != ATOM_OK) {
failures++ ;
break ;
}
}
if (atomThreadCreate ((ATOM_TCB *)&monitor_tcb, 150, monitor_thread, TEST_THREADS,
&monitor_stack[0], MONITOR_STACK_BYTE_SIZE, TRUE) != ATOM_OK) {
failures++ ;
}
if (failures == 0) {
while (1) {
atomTimerDelay (1000) ;
}
}
return failures ;
}
void
atomthreads_stress_test (uint32_t thread_count)
{
unsigned int i ;
if (thread_count > MAX_TEST_THREADS) {
thread_count = MAX_TEST_THREADS ;
}
ATOMLOG (_STR("\r\natomthreads_stress_test %.3d threads\r\n"), thread_count) ;
ATOMLOG (_STR("-----------------------------------\r\n")) ;
atomOSInit(&idle_stack[0], IDLE_STACK_BYTE_SIZE, TRUE) ;
for (i=0; i< thread_count;i++) {
atomThreadCreate ((ATOM_TCB *)&test_tcb[i], test_prio[i], stress_test_thread, i,
&stress_test_stack[i][0], TEST_STACK_BYTE_SIZE, TRUE);
}
atomThreadCreate ((ATOM_TCB *)&monitor_tcb, 150, monitor_thread, thread_count,
&monitor_stack[0], MONITOR_STACK_BYTE_SIZE, TRUE);
atomOSStart() ;
}

18
tests/stress1.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef __STRESS1_H__
#define __STRESS1_H__
#include "types.h"
#define TEST_STACK_BYTE_SIZE 0x200
#define IDLE_STACK_BYTE_SIZE 0x200
#define MONITOR_STACK_BYTE_SIZE 0x400
#ifndef TEST_THREADS
#define TEST_THREADS 16
#endif
extern void atomthreads_stress_test (uint32_t thread_count) ;
extern uint32_t test_start (void) ;
#endif /* __STRESS1_H__ */