STM8 port: Add RTOS port for IAR EWSTM8 compiler.

* Split assembler routines into -cosmic.s and -iar.s.
* Split Cosmic and IAR specific code using __CSMC__ and __IAR_SYSTEMS_ICC__.
* Context-switch virtual registers on IAR.
* Add detailed description of IAR context-switch scheme.
* Add sample IAR project.
* Add support for IAR to STM8S peripheral driver modules.
* Fix EWSTM8 compiler warnings.
This commit is contained in:
Kelvin Lawson
2010-05-24 22:54:40 +01:00
parent 538a535fe9
commit 394e04ec4a
23 changed files with 6111 additions and 241 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Atomthreads Project. All rights reserved.
* Copyright (c) 2010, Atomthreads Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions

View File

@@ -24,7 +24,7 @@ BUILD_DIR=build
# Port/application object files
APP_OBJECTS = atomport.o tests-main.o stm8_interrupt_vector.o uart.o
APP_ASM_OBJECTS = atomport-asm.o
APP_ASM_OBJECTS = atomport-asm-cosmic.o
# STM8S Peripheral driver object files
PERIPH_OBJECTS = stm8s_gpio.o stm8s_tim1.o stm8s_clk.o stm8s_uart2.o

View File

@@ -1,5 +1,5 @@
;
; Copyright (c) 2005, Atomthreads Project. All rights reserved.
; Copyright (c) 2010, Atomthreads Project. All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; Modification, are permitted provided that the following conditions
@@ -28,6 +28,9 @@
;
; Cosmic assembler routines
; Export functions to other modules
xdef _archContextSwitch, _archFirstThreadRestore
@@ -49,7 +52,7 @@ xdef _archContextSwitch, _archFirstThreadRestore
; void archContextSwitch (ATOM_TCB *old_tcb_ptr, ATOM_TCB *new_tcb_ptr)
_archContextSwitch:
; Parameter locations:
; Parameter locations (Cosmic calling convention):
; old_tcb_ptr = X register (word-width)
; new_tcb_ptr = stack (word-width)

View File

@@ -0,0 +1,391 @@
;
; Copyright (c) 2010, Atomthreads Project. 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.
;
; IAR assembler routines
NAME ATOMPORTASM
SECTION .text:code
; Get definitions for virtual registers used by the compiler
#include "vregs.inc"
; \b archContextSwitch
;
; Architecture-specific context switch routine.
;
; Note that interrupts are always locked out when this routine is
; called. For cooperative switches, the scheduler will have entered
; a critical region. For preemptions (called from an ISR), the
; ISR will have disabled interrupts on entry.
;
; @param[in] old_tcb_ptr Pointer to the thread being scheduled out
; @param[in] new_tcb_ptr Pointer to the thread being scheduled in
;
; @return None
;
; void archContextSwitch (ATOM_TCB *old_tcb_ptr, ATOM_TCB *new_tcb_ptr)
PUBLIC archContextSwitch
archContextSwitch:
; Parameter locations (IAR calling convention):
; old_tcb_ptr = X register (word-width)
; new_tcb_ptr = Y register (word-width)
; STM8 CPU Registers:
;
; A, X, Y: Standard working registers
; SP: Stack pointer
; PC: Program counter
; CC: Code condition register
;
; IAR compiler virtual registers
;
; ?b0 - ?b7: Scratch registers
; ?b8 - ?b15: Preserved registers
;
; The basic scheme is that some registers will already be saved
; onto the stack if the caller wishes them not to be clobbered.
; We only need to context-switch additional registers which the
; caller does not expect to be modified in a subroutine.
;
; If this is a cooperative context switch (a thread has called us
; to schedule itself out), the IAR compiler will have saved any
; of the registers which it does not want us to clobber. For IAR
; only virtual registers ?b8 to ?b15 are expected to retain their
; value across a function call, hence for cooperative context
; switches with this compiler we only need to save ?b8 to ?b15.
;
; If we were called from an interrupt routine (because a thread
; is being preemptively scheduled out), the situation is exactly
; the same. Any ISR which calls out to a subroutine will have
; similarly saved all registers which it needs us not to clobber,
; leaving only ?b8 to ?b15 which must be saved.
;
; The Cosmic compiler version of this context switch routine
; does not require any registers to be saved/restored, whereas
; this IAR equivalent reqires that 8 of the virtual registers
; are.
; We also have to do a little more work in here: we need to store
; the current stack pointer to the current thread's TCB, and
; switch in the new thread by taking the stack pointer from
; the new thread's TCB and making that our new stack pointer.
; (IAR) Compiler will have already saved any scratch registers
; (A, X, Y, CC, and ?b0 to ?b7) which it needs before calling here
; for cooperative switches. So these will already be on the stack
; and do not need to be context-switched. This assumes that
; __interrupt funcs (although EWSTM8 docs say they don't save
; vregs) do actually save ?b0 to ?b7 if they call out to another
; function. Can't verify this with Kickstart edition. If this
; assumption is incorrect then we actually need to save all vregs
; here, and this would be inefficient if called for a cooperative
; switch where we know ?b0 to ?b7 do not need to be saved.
PUSH ?b8
PUSH ?b9
PUSH ?b10
PUSH ?b11
PUSH ?b12
PUSH ?b13
PUSH ?b14
PUSH ?b15
; The parameter pointing to the the old TCB (a word-width
; pointer) is still untouched in the X register.
; (IAR) Take a copy of the new_tcb_ptr parameter from Y-reg in
; a temporary (?b0) register. We need to use Y briefly for SP
; access.
ldw ?b0, Y
; Store current stack pointer as first entry in old_tcb_ptr
ldw Y, SP ; Move current stack pointer into Y register
ldw (X), Y ; Store current stack pointer at first offset in TCB
; At this point, all of the current thread's context has been saved
; so we no longer care about keeping the contents of any registers
; except ?b0 which contains our passed new_tcb_ptr parameter (a
; pointer to the TCB of the thread which we wish to switch in).
;
; Our stack frame now contains all registers which need to be
; preserved or context-switched. It also contains the return address
; which will be either a function called via an ISR (for preemptive
; switches) or a function called from thread context (for cooperative
; switches).
;
; In addition, the thread's stack pointer (after context-save) is
; stored in the thread's TCB.
; We are now ready to restore the new thread's context. We switch
; our stack pointer to the new thread's stack pointer, and pop its
; context off the stack, before returning to the caller (the
; original caller when the new thread was last scheduled out).
; Get the new thread's stack pointer off the TCB (new_tcb_ptr).
; We kept a copy of new_tcb_ptr earlier in ?b0, copy it into X.
ldw X,?b0
; Pull the first entry out of new_tcb_ptr (the new thread's
; stack pointer) into X register.
ldw X,(X)
; Switch our current stack pointer to that of the new thread.
ldw SP,X
; (IAR) We only save/restore ?b8 to ?b15
POP ?b15
POP ?b14
POP ?b13
POP ?b12
POP ?b11
POP ?b10
POP ?b9
POP ?b8
; The return address on the stack will now be the new thread's return
; address - i.e. although we just entered this function from a
; function called by the old thread, now that we have restored the new
; thread's stack, we actually return from this function to wherever
; the new thread was when it was previously scheduled out. This could
; be either a regular C routine if the new thread previously scheduled
; itself out cooperatively, or it could be an ISR if this new thread was
; previously preempted (on exiting the ISR, execution will return to
; wherever the new thread was originally interrupted).
; Return to the caller. Note that we always use a regular RET here
; because this is a subroutine regardless of whether we were called
; during an ISR or by a thread cooperatively switching out. The
; difference between RET and IRET on the STM8 architecture is that
; RET only pops the return address off the stack, while IRET also
; pops from the stack all of the CPU registers saved when the ISR
; started, including restoring the interrupt-enable bits from the CC
; register.
;
; It is important that whenever we call this function (whether from
; an ISR for preemptive switches or from thread context for
; cooperative switches) interrupts are always disabled. This means
; that whichever method by which we leave this routine we always
; have to reenable interrupts, so we can use the same context-switch
; routine for preemptive and cooperative switches.
;
; The possible call/return paths are as follows:
;
; Scenario 1 (cooperative -> cooperative):
; Thread A: cooperatively switches out
; * Thread A relinquishes control / cooperatively switches out
; * Interrupts already disabled by kernel for cooperative reschedules
; * Partial register context saved by calling function
; * Call here at thread context
; * Switch to Thread B
; Thread B (was previously cooperatively switched out):
; * Stack context for Thread B contains its return address
; * Return to function which was called at thread context
; * Interrupts are reenabled by CRITICAL_END() call in kernel
; * Return to Thread B application code
;
; Scenario 2 (preemptive -> preemptive):
; Thread A: preemptively switches out
; * ISR occurs
; * Interrupts disabled by CPU at ISR entry (assume no nesting allowed)
; * Full register context saved by CPU at ISR entry
; * Call here at ISR context
; * Switch to Thread B
; Thread B (was previously preemptively switched out):
; * Stack context for Thread B contains its return address
; and all context saved by the CPU on ISR entry
; * Return to function which was called at ISR context
; * Eventually returns to calling ISR which calls IRET
; * IRET performs full register context restore
; * IRET reenables interrupts
; * Return to Thread B application code
;
; Scenario 3 (cooperative -> preemptive):
; Thread A: cooperatively switches out
; * Thread A relinquishes control / cooperatively switches out
; * Interrupts already disabled by kernel for cooperative reschedules
; * Partial register context saved by calling function
; * Call here at thread context
; * Switch to Thread B
; Thread B (was previously preemptively switched out):
; * Stack context for Thread B contains its return address
; and all context saved by the CPU on ISR entry
; * Return to function which was called at ISR context
; * Eventually returns to calling ISR which calls IRET
; * IRET performs full register context restore
; * IRET reenables interrupts
; * Return to Thread B application code
;
; Scenario 4 (preemptive -> cooperative):
; Thread A: preemptively switches out
; * ISR occurs
; * Interrupts disabled by CPU at ISR entry (assume no nesting allowed)
; * Full register context saved by CPU at ISR entry
; * Call here at ISR context
; * Switch to Thread B
; Thread B (was previously cooperatively switched out):
; * Stack context for Thread B contains its return address
; * Return to function which was called at thread context
; * Interrupts are reenabled by CRITICAL_END() call in kernel
; * Return to Thread B application code
;
; The above shows that it does not matter whether we are rescheduling
; from/to thread context or ISR context. It is perfectly valid to
; enter here at ISR context but leave via a thread which previously
; cooperatively switched out because:
; 1. Although the CPU handles ISRs differently by automatically
; stacking all 6 CPU registers, and restoring them on an IRET,
; we handle this because we switch the stack pointer to a
; different thread's stack. Because the stack pointer is
; switched, it does not matter that on entry via ISRs more
; registers are saved on the original thread's stack than entries
; via non-ISRs. Those extra registers will be restored properly
; by an IRET when the thread is eventually scheduled back in
; (which could be a long way off). This assumes that the CPU does
; not have hidden behaviour that occurs on interrupts, and we can
; in fact trick it into leaving via another thread's call stack,
; and performing the IRET much later.
; 2. Although the CPU handles ISRs differently by setting the CC
; register interrupt-enable bits on entry/exit, we handle this
; anyway by always assuming interrupts are disabled on entry
; and exit regardless of the call path.
; Return from subroutine
ret
; \b archFirstThreadRestore
;
; Architecture-specific function to restore and start the first thread.
; This is called by atomOSStart() when the OS is starting. Its job is to
; restore the context for the first thread and start running at its
; entry point.
;
; All new threads have a stack context pre-initialised with suitable
; data for being restored by either this function or the normal
; function used for scheduling threads in, archContextSwitch(). Only
; the first thread run by the system is launched via this function,
; after which all other new threads will first be run by
; archContextSwitch().
;
; Typically ports will implement something similar here to the
; latter half of archContextSwitch(). In this port the context
; switch does not restore many registers, and instead relies on the
; fact that returning from any function which called
; archContextSwitch() will restore any of the necessary registers.
; For new threads which have never been run there is no calling
; function which will restore context on return, therefore we
; do not restore many register values here. It is not necessary
; for the new threads to have initialised values for the scratch
; registers A, X and Y or the code condition register CC which
; leaves SP and PC. SP is restored because this is always needed to
; switch to a new thread's stack context. It is not necessary to
; restore PC, because the thread's entry point is in the stack
; context (when this function returns using RET the PC is
; automatically changed to the thread's entry point because the
; entry point is stored in the preinitialised stack).
;
; When new threads are started interrupts must be enabled, so there
; is some scope for enabling interrupts in the CC here. It must be
; done for all new threads, however, not just the first thread, so
; we use a different system. We instead use a thread shell routine
; which all functions run when they are first started, and
; interrupts are enabled in there. This allows us to avoid having
; to enable interrupts both in here and in the normal context
; switch routine (archContextSwitch()). For the normal context
; switch routine we would otherwise need to pass in notification of
; and implement special handling for the first time a thread is
; restored.
;
; In summary, first threads do not require a set of CPU registers
; to be initialised to known values, so we only set SP to the new
; thread's stack pointer. PC is restored for free because the RET
; call at the end of this function pops the return address off the
; stack.
;
; Note that you can create more than one thread before starting
; the OS - only one thread is restored using this function, so
; all other threads are actually restored by archContextSwitch().
; This is another reminder that the initial context set up by
; archThreadContextInit() must look the same whether restored by
; archFirstThreadRestore() or archContextSwitch().
;
; @param[in] new_tcb_ptr Pointer to the thread being scheduled in
;
; @return None
;
; void archFirstThreadRestore (ATOM_TCB *new_tcb_ptr)
PUBLIC archFirstThreadRestore
archFirstThreadRestore:
; Parameter locations:
; new_tcb_ptr = X register (word-width)
; As described above, first thread restores in this port do not
; expect any initial register context to be pre-initialised in
; the thread's stack area. The thread's initial stack need only
; contain the thread's initial entry point, and we do not even
; "restore" that within this function. We leave the thread's entry
; point in the stack, and RET at the end of the function pops it
; off and "returns" to the entry point as if we were called from
; there.
;
; The one thing we do need to set in here, though, is the thread's
; stack pointer. This is available from the passed thread TCB
; structure.
; Get the new thread's stack pointer off the TCB (new_tcb_ptr).
; new_tcb_ptr is stored in the parameter register X. The stack
; pointer it conveniently located at the top of the TCB so no
; indexing is required to pull it out.
ldw X,(X)
; Switch our current stack pointer to that of the new thread.
ldw SP,X
; (IAR) We only context switch ?b8 to ?b15
POP ?b15
POP ?b14
POP ?b13
POP ?b12
POP ?b11
POP ?b10
POP ?b9
POP ?b8
; The "return address" left on the stack now will be the new
; thread's entry point. RET will take us there as if we had
; actually been there before calling this subroutine, whereas
; the return address was actually set up by archThreadContextInit().
ret
end

View File

@@ -33,7 +33,10 @@
/* Function prototypes */
void archInitSystemTickTimer (void);
@far @interrupt void TIM1_SystemTickISR (void);
#ifdef __CSMC__
@far @interrupt void TIM1_SystemTickISR (void);
#elif __IAR_SYSTEMS_ICC__
__interrupt void TIM1_SystemTickISR (void);
#endif
#endif /* __ATOM_PORT_PRIVATE_H */

View File

@@ -49,7 +49,7 @@
#define TEST_THREAD_STACK_SIZE 128
/* Uncomment to enable logging of stack usage to UART */
/* #define TESTS_LOG_STACK_USAGE */
#define TESTS_LOG_STACK_USAGE
#endif /* __ATOM_PORT_TESTS_H */

View File

@@ -79,7 +79,11 @@ static void thread_shell (void)
* Enable interrupts - these will not be enabled when a thread
* is first restored.
*/
#if defined(__CSMC__)
_asm("rim");
#elif defined(__IAR_SYSTEMS_ICC__)
rim();
#endif
/* Call the thread entry point */
if (curr_tcb && curr_tcb->entry_point)
@@ -101,19 +105,30 @@ static void thread_shell (void)
* and running the thread via archFirstThreadRestore() or
* archContextSwitch().
*
* On this port we take advantage of the fact that when the context
* switch routine is called the compiler will automatically stack
* all registers which should not be clobbered. This means that the
* context switch need only save and restore the stack pointer,
* which is stored in the thread's TCB. Because of this, it is not
* necessary to prefill a new thread's stack with any register
* values here. The only entry we need to make in the stack is the
* thread's entry point - this is not exactly restored when the
* (COSMIC) On this port we take advantage of the fact that when
* the context switch routine is called the compiler will
* automatically stack all registers which should not be clobbered.
* This means that the context switch need only save and restore the
* stack pointer, which is stored in the thread's TCB. Because of
* this, it is not necessary to prefill a new thread's stack with any
* register values here. The only entry we need to make in the stack
* is the thread's entry point - this is not exactly restored when
* the thread is context switched in, but rather is popped off the
* stack by the context switch routine's RET call. That is used to
* direct the program counter to our thread's entry point - we are
* faking a return to a caller which never actually existed.
*
* (IAR) The IAR compiler works around the lack of CPU registers on
* STM8 by allocating some space in low SRAM which is used for
* "virtual" registers. The compiler uses these like normal CPU
* registers, and hence their values must be preserved when
* context-switching between threads. Some of these (?b8 to ?b15)
* are expected to be preserved by called functions, and hence we
* actually need to save/restore those registers (unlike the rest
* of the virtual registers and the standard CPU registers). We
* therefore must prefill the stack with values for ?b8 to ?b15
* here.
*
* We could pre-initialise the stack so that the RET call goes
* directly to the thread entry point, with the thread entry
* parameter filled in. On this architecture, however, we use an
@@ -172,11 +187,28 @@ void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_poi
*/
/**
* In this port we do not initialise any registers via the initial
* stack context at all. All thread context has now been
* initialised. All that is left is to save the current stack
* pointer to the thread's TCB so that it knows where to start
* looking when the thread is started.
* (IAR) Set up initial values for ?b8 to ?b15.
*/
#if defined(__IAR_SYSTEMS_ICC__)
*stack_ptr-- = 0; // ?b8
*stack_ptr-- = 0; // ?b9
*stack_ptr-- = 0; // ?b10
*stack_ptr-- = 0; // ?b11
*stack_ptr-- = 0; // ?b12
*stack_ptr-- = 0; // ?b13
*stack_ptr-- = 0; // ?b14
*stack_ptr-- = 0; // ?b15
#endif
/**
* (COSMIC) We do not initialise any registers via the initial
* stack context at all.
*/
/**
* All thread context has now been initialised. All that is left
* is to save the current stack pointer to the thread's TCB so
* that it knows where to start looking when the thread is started.
*/
tcb_ptr->sp_save_ptr = stack_ptr;
@@ -192,16 +224,16 @@ void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_poi
*/
void archInitSystemTickTimer ( void )
{
/* Reset TIM1 */
/* Reset TIM1 */
TIM1_DeInit();
/* Configure a 10ms tick */
/* Configure a 10ms tick */
TIM1_TimeBaseInit(10000, TIM1_COUNTERMODE_UP, 1, 0);
/* Generate an interrupt on timer count overflow */
/* Generate an interrupt on timer count overflow */
TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);
/* Enable TIM1 */
/* Enable TIM1 */
TIM1_Cmd(ENABLE);
}
@@ -243,7 +275,11 @@ void archInitSystemTickTimer ( void )
*
* @return None
*/
void TIM1_SystemTickISR (void)
#if defined(__IAR_SYSTEMS_ICC__)
#pragma vector = 13
__interrupt
#endif
void TIM1_SystemTickISR (void)
{
/* Call the interrupt entry routine */
atomIntEnter();
@@ -252,7 +288,7 @@ void TIM1_SystemTickISR (void)
atomTimerTick();
/* Ack the interrupt (Clear TIM1:SR1 register bit 0) */
TIM1->SR1 = (uint8_t)(~(uint8_t)TIM1_IT_UPDATE);
TIM1->SR1 = (uint8_t)(~(uint8_t)TIM1_IT_UPDATE);
/* Call the interrupt exit routine */
atomIntExit(TRUE);

View File

@@ -33,6 +33,10 @@
#include "stm8s_type.h"
#if defined(__IAR_SYSTEMS_ICC__)
#include "intrinsics.h"
#endif
/* Required number of system ticks per second (normally 100 for 10ms tick) */
#define SYSTEM_TICKS_PER_SEC 100
@@ -51,10 +55,19 @@
/* Critical region protection */
/* COSMIC: Use inline assembler */
#if defined(__CSMC__)
#define CRITICAL_STORE uint8_t ccr
#define CRITICAL_START() _asm ("push CC\npop a\nld (X),A\nsim", &ccr)
#define CRITICAL_END() _asm ("ld A,(X)\npush A\npop CC", &ccr)
/* IAR: Use intrinsics */
#elif defined(__IAR_SYSTEMS_ICC__)
#define CRITICAL_STORE __istate_t _istate
#define CRITICAL_START() _istate = __get_interrupt_state(); __disable_interrupt()
#define CRITICAL_END() __set_interrupt_state(_istate)
#endif
/* Uncomment to enable stack-checking */
/* #define ATOM_STACK_CHECKING */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,369 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<project>
<fileVersion>2</fileVersion>
<configuration>
<name>Debug</name>
<toolchain>
<name>STM8</name>
</toolchain>
<debug>1</debug>
<settings>
<name>C-SPY</name>
<archiveVersion>1</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>CSpyMandatory</name>
<state>1</state>
</option>
<option>
<name>CSpyInput</name>
<state>1</state>
</option>
<option>
<name>CSpyRunToEnable</name>
<state>1</state>
</option>
<option>
<name>CSpyRunToName</name>
<state>main</state>
</option>
<option>
<name>CSpyMacOverride</name>
<state>0</state>
</option>
<option>
<name>CSpyMacFile</name>
<state></state>
</option>
<option>
<name>DynDriver</name>
<state>STLINK_STM8</state>
</option>
<option>
<name>CSpyDDFOverride</name>
<state>0</state>
</option>
<option>
<name>CSpyDDFFile</name>
<state>$TOOLKIT_DIR$\config\ddf\iostm8s105c6.ddf</state>
</option>
<option>
<name>CSpyEnableExtraOptions</name>
<state>0</state>
</option>
<option>
<name>CSpyExtraOptions</name>
<state></state>
</option>
<option>
<name>CSpyImagesSuppressCheck1</name>
<state>0</state>
</option>
<option>
<name>CSpyImagesPath1</name>
<state></state>
</option>
<option>
<name>CSpyImagesSuppressCheck2</name>
<state>0</state>
</option>
<option>
<name>CSpyImagesPath2</name>
<state></state>
</option>
<option>
<name>CSpyImagesSuppressCheck3</name>
<state>0</state>
</option>
<option>
<name>CSpyImagesPath3</name>
<state></state>
</option>
</data>
</settings>
<settings>
<name>SIMULATOR_STM8</name>
<archiveVersion>1</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>SimMandatory</name>
<state>1</state>
</option>
</data>
</settings>
<settings>
<name>STICE_STM8</name>
<archiveVersion>1</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>STiceMandatory</name>
<state>0</state>
</option>
<option>
<name>STiceSuppressLoad</name>
<state>0</state>
</option>
<option>
<name>STiceVerifyLoad</name>
<state>0</state>
</option>
<option>
<name>STiceLogFileOver</name>
<state>0</state>
</option>
<option>
<name>STiceLogFile</name>
<state>$PROJ_DIR$\cspycomm.log</state>
</option>
<option>
<name>STiceUseSwim</name>
<state>0</state>
</option>
</data>
</settings>
<settings>
<name>STLINK_STM8</name>
<archiveVersion>1</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>STlinkMandatory</name>
<state>0</state>
</option>
<option>
<name>STlinkSuppressLoad</name>
<state>0</state>
</option>
<option>
<name>STlinkVerifyLoad</name>
<state>0</state>
</option>
<option>
<name>STlinkLogFileOver</name>
<state>0</state>
</option>
<option>
<name>STlinkLogFile</name>
<state>$PROJ_DIR$\cspycomm.log</state>
</option>
</data>
</settings>
<debuggerPlugins>
<plugin>
<file>$EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin</file>
<loadFlag>1</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\Profiling\Profiling.ENU.ewplugin</file>
<loadFlag>1</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\Stack\Stack.ENU.ewplugin</file>
<loadFlag>1</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\SymList\SymList.ENU.ewplugin</file>
<loadFlag>1</loadFlag>
</plugin>
</debuggerPlugins>
</configuration>
<configuration>
<name>Release</name>
<toolchain>
<name>STM8</name>
</toolchain>
<debug>0</debug>
<settings>
<name>C-SPY</name>
<archiveVersion>1</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>0</debug>
<option>
<name>CSpyMandatory</name>
<state>1</state>
</option>
<option>
<name>CSpyInput</name>
<state>1</state>
</option>
<option>
<name>CSpyRunToEnable</name>
<state>1</state>
</option>
<option>
<name>CSpyRunToName</name>
<state>main</state>
</option>
<option>
<name>CSpyMacOverride</name>
<state>0</state>
</option>
<option>
<name>CSpyMacFile</name>
<state></state>
</option>
<option>
<name>DynDriver</name>
<state>STLINK_STM8</state>
</option>
<option>
<name>CSpyDDFOverride</name>
<state>0</state>
</option>
<option>
<name>CSpyDDFFile</name>
<state>$TOOLKIT_DIR$\config\ddf\iostm8s105c6.ddf</state>
</option>
<option>
<name>CSpyEnableExtraOptions</name>
<state>0</state>
</option>
<option>
<name>CSpyExtraOptions</name>
<state></state>
</option>
<option>
<name>CSpyImagesSuppressCheck1</name>
<state>0</state>
</option>
<option>
<name>CSpyImagesPath1</name>
<state></state>
</option>
<option>
<name>CSpyImagesSuppressCheck2</name>
<state>0</state>
</option>
<option>
<name>CSpyImagesPath2</name>
<state></state>
</option>
<option>
<name>CSpyImagesSuppressCheck3</name>
<state>0</state>
</option>
<option>
<name>CSpyImagesPath3</name>
<state></state>
</option>
</data>
</settings>
<settings>
<name>SIMULATOR_STM8</name>
<archiveVersion>1</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>0</debug>
<option>
<name>SimMandatory</name>
<state>1</state>
</option>
</data>
</settings>
<settings>
<name>STICE_STM8</name>
<archiveVersion>1</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>0</debug>
<option>
<name>STiceMandatory</name>
<state>0</state>
</option>
<option>
<name>STiceSuppressLoad</name>
<state>0</state>
</option>
<option>
<name>STiceVerifyLoad</name>
<state>0</state>
</option>
<option>
<name>STiceLogFileOver</name>
<state>0</state>
</option>
<option>
<name>STiceLogFile</name>
<state>$PROJ_DIR$\cspycomm.log</state>
</option>
<option>
<name>STiceUseSwim</name>
<state>0</state>
</option>
</data>
</settings>
<settings>
<name>STLINK_STM8</name>
<archiveVersion>1</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>0</debug>
<option>
<name>STlinkMandatory</name>
<state>0</state>
</option>
<option>
<name>STlinkSuppressLoad</name>
<state>0</state>
</option>
<option>
<name>STlinkVerifyLoad</name>
<state>0</state>
</option>
<option>
<name>STlinkLogFileOver</name>
<state>0</state>
</option>
<option>
<name>STlinkLogFile</name>
<state>$PROJ_DIR$\cspycomm.log</state>
</option>
</data>
</settings>
<debuggerPlugins>
<plugin>
<file>$EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin</file>
<loadFlag>1</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\Profiling\Profiling.ENU.ewplugin</file>
<loadFlag>1</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\Stack\Stack.ENU.ewplugin</file>
<loadFlag>1</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\SymList\SymList.ENU.ewplugin</file>
<loadFlag>1</loadFlag>
</plugin>
</debuggerPlugins>
</configuration>
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -580,13 +580,13 @@ Next=Root.Port.atomport.c
[Root.Port.atomport.c]
ElemType=File
PathName=atomport.c
Next=Root.Port.atomport-asm.s
Next=Root.Port.atomport-asm-cosmic.s
[Root.Port.atomport-asm.s]
[Root.Port.atomport-asm-cosmic.s]
ElemType=File
PathName=atomport-asm.s
PathName=atomport-asm-cosmic.s
Next=Root.Port.stm8_interrupt_vector.c
[Root.Port.stm8_interrupt_vector.c]
ElemType=File
PathName=stm8_interrupt_vector.c
PathName=stm8_interrupt_vector.c

View File

@@ -38,7 +38,7 @@ build\stm8s_uart2.o
build\tests-main.o
build\atomport.o
build\uart.o
build\atomport-asm.o
build\atomport-asm-cosmic.o
# Caller passes in test application object name as param1
@1
#<END OBJECT_FILES>

View File

@@ -3,6 +3,9 @@
*/
/* COSMIC: Requires interrupt vector table */
#if defined(__CSMC__)
/* Import Atomthreads system tick ISR prototype */
#include "atomport-private.h"
@@ -58,3 +61,5 @@ struct interrupt_vector const _vectab[] = {
{0x82, NonHandledInterrupt}, /* irq28 */
{0x82, NonHandledInterrupt}, /* irq29 */
};
#endif /* __CSMC__ */

View File

@@ -29,10 +29,16 @@
/* Check the used compiler */
#if defined(__CSMC__)
#undef _RAISONANCE_
#undef _IAR_SYSTEMS_
#define _COSMIC_
#elif defined(__RCST7__)
#undef _COSMIC_
#undef _IAR_SYSTEMS_
#define _RAISONANCE_
#elif defined(__IAR_SYSTEMS_ICC__)
#undef _COSMIC_
#undef _RAISONANCE_
#define _IAR_SYSTEMS_
#else
#error "Unsupported Compiler!" /* Compiler defines not found */
#endif
@@ -42,7 +48,8 @@
Tip: To avoid modifying this file each time you need to switch between these
devices, you can define the device in your toolchain compiler preprocessor. */
#if !defined (STM8S208) && !defined (STM8S207) && !defined (STM8S105) && !defined (STM8S103) && !defined (STM8S903)
#define STM8S208
# error "STM8S device not specified"
/* #define STM8S208 */
/* #define STM8S207 */
/* #define STM8S105 */
/* #define STM8S103 */
@@ -67,12 +74,21 @@
#define NEAR @near
#define TINY @tiny
#define __CONST const
#else /* __RCST7__ */
#endif
#ifdef _RAISONANCE_
#define FAR far
#define NEAR data
#define TINY page0
#define __CONST code
#endif /* __CSMC__ */
#endif
#ifdef _IAR_SYSTEMS_
#define FAR __far
#define NEAR __near
#define TINY __tiny
#define __CONST const
#endif
#ifdef PointerAttr_Far
#define PointerAttr FAR
@@ -2495,7 +2511,9 @@ CFG_TypeDef;
#define trap() _trap_() /* Trap (soft IT) */
#define wfi() _wfi_() /* Wait For Interrupt */
#define halt() _halt_() /* Halt */
#else /* COSMIC */
#endif
#ifdef _COSMIC_
#define enableInterrupts() {_asm("rim\n");} /* enable interrupts */
#define disableInterrupts() {_asm("sim\n");} /* disable interrupts */
#define rim() {_asm("rim\n");} /* enable interrupts */
@@ -2506,6 +2524,18 @@ CFG_TypeDef;
#define halt() {_asm("halt\n");} /* Halt */
#endif
#ifdef _IAR_SYSTEMS_
#include <intrinsics.h>
#define enableInterrupts() __enable_interrupt() /* enable interrupts */
#define disableInterrupts() __disable_interrupt() /* disable interrupts */
#define rim() __enable_interrupt() /* enable interrupts */
#define sim() __disable_interrupt() /* disable interrupts */
#define nop() __no_operation() /* No Operation */
#define trap() __trap_() /* Trap (soft IT) */
#define wfi() __wait_for_interrupt() /* Wait For Interrupt */
#define halt() __halt_() /* Halt */
#endif
/*============================== Handling bits ====================================*/
/*-----------------------------------------------------------------------------
Method : I

View File

@@ -117,47 +117,6 @@ void GPIO_Init(GPIO_TypeDef* GPIOx,
}
/**
* @brief Writes data to the specified GPIO data port.
* @param[in] GPIOx : Select the GPIO peripheral number (x = A to I).
* @param[in] PortVal : Specifies the value to be written to the port output.
* data register.
* @retval None
* @par Required preconditions:
* The port must be configured in output mode.
*/
void GPIO_Write(GPIO_TypeDef* GPIOx, u8 PortVal)
{
GPIOx->ODR = PortVal;
}
/**
* @brief Writes high level to the specified GPIO pins.
* @param[in] GPIOx : Select the GPIO peripheral number (x = A to I).
* @param[in] PortPins : Specifies the pins to be turned high to the port output.
* data register.
* @retval None
* @par Required preconditions:
* The port must be configured in output mode.
*/
void GPIO_WriteHigh(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef PortPins)
{
GPIOx->ODR |= (u8)PortPins;
}
/**
* @brief Writes low level to the specified GPIO pins.
* @param[in] GPIOx : Select the GPIO peripheral number (x = A to I).
* @param[in] PortPins : Specifies the pins to be turned low to the port output.
* data register.
* @retval None
* @par Required preconditions:
* The port must be configured in output mode.
*/
void GPIO_WriteLow(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef PortPins)
{
GPIOx->ODR &= (u8)(~PortPins);
}
/**
* @brief Writes reverse level to the specified GPIO pins.
@@ -173,67 +132,6 @@ void GPIO_WriteReverse(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef PortPins)
GPIOx->ODR ^= (u8)PortPins;
}
/**
* @brief Reads the specified GPIO output data port.
* @param[in] GPIOx : Select the GPIO peripheral number (x = A to I).
* @retval u8 : GPIO output data port value.
* @par Required preconditions:
* The port must be configured in input mode.
*/
u8 GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
{
return ((u8)GPIOx->ODR);
}
/**
* @brief Reads the specified GPIO input data port.
* @param[in] GPIOx : Select the GPIO peripheral number (x = A to I).
* @retval u8 : GPIO input data port value.
* @par Required preconditions:
* The port must be configured in input mode.
*/
u8 GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
{
return ((u8)GPIOx->IDR);
}
/**
* @brief Reads the specified GPIO input data pin.
* @param[in] GPIOx : Select the GPIO peripheral number (x = A to I).
* @param[in] GPIO_Pin : This parameter contains the pin number, it can be one member
* of the @ref GPIO_Pin_TypeDef enumeration.
* @retval BitStatus : GPIO input pin status.
* This parameter can be any of the @ref BitStatus enumeration.
* @par Required preconditions:
* The port must be configured in input mode.
*/
BitStatus GPIO_ReadInputPin(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin)
{
return ((BitStatus)(GPIOx->IDR & (vu8)GPIO_Pin));
}
/**
* @brief Configures the external pull-up on GPIOx pins.
* @param[in] GPIOx : Select the GPIO peripheral number (x = A to I).
* @param[in] GPIO_Pin : This parameter contains the pin number, it can be one or many members
* of the @ref GPIO_Pin_TypeDef enumeration.
* @param[in] NewState : The new state of the pull up pin.
* This parameter can be any of the @ref FunctionalState enumeration.
* @retval None
*/
void GPIO_ExternalPullUpConfig(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN_OK(GPIO_Pin));
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
if (NewState != DISABLE) /* External Pull-Up Set*/
{
GPIOx->CR1 |= (u8)GPIO_Pin;
} else /* External Pull-Up Reset*/
{
GPIOx->CR1 &= (u8)(~(GPIO_Pin));
}
}
/**
* @}

View File

@@ -47,18 +47,18 @@
*/
typedef enum
{
GPIO_MODE_IN_FL_NO_IT = (u8)0b00000000, /*!< Input floating, no external interrupt */
GPIO_MODE_IN_PU_NO_IT = (u8)0b01000000, /*!< Input pull-up, no external interrupt */
GPIO_MODE_IN_FL_IT = (u8)0b00100000, /*!< Input floating, external interrupt */
GPIO_MODE_IN_PU_IT = (u8)0b01100000, /*!< Input pull-up, external interrupt */
GPIO_MODE_OUT_OD_LOW_FAST = (u8)0b10100000, /*!< Output open-drain, low level, 10MHz */
GPIO_MODE_OUT_PP_LOW_FAST = (u8)0b11100000, /*!< Output push-pull, low level, 10MHz */
GPIO_MODE_OUT_OD_LOW_SLOW = (u8)0b10000000, /*!< Output open-drain, low level, 2MHz */
GPIO_MODE_OUT_PP_LOW_SLOW = (u8)0b11000000, /*!< Output push-pull, low level, 2MHz */
GPIO_MODE_OUT_OD_HIZ_FAST = (u8)0b10110000, /*!< Output open-drain, high-impedance level,10MHz */
GPIO_MODE_OUT_PP_HIGH_FAST = (u8)0b11110000, /*!< Output push-pull, high level, 10MHz */
GPIO_MODE_OUT_OD_HIZ_SLOW = (u8)0b10010000, /*!< Output open-drain, high-impedance level, 2MHz */
GPIO_MODE_OUT_PP_HIGH_SLOW = (u8)0b11010000 /*!< Output push-pull, high level, 2MHz */
GPIO_MODE_IN_FL_NO_IT = (u8)0x00, // 0b00000000, /*!< Input floating, no external interrupt */
GPIO_MODE_IN_PU_NO_IT = (u8)0x40, // 0b01000000, /*!< Input pull-up, no external interrupt */
GPIO_MODE_IN_FL_IT = (u8)0x20, // 0b00100000, /*!< Input floating, external interrupt */
GPIO_MODE_IN_PU_IT = (u8)0x60, // 0b01100000, /*!< Input pull-up, external interrupt */
GPIO_MODE_OUT_OD_LOW_FAST = (u8)0xA0, // 0b10100000, /*!< Output open-drain, low level, 10MHz */
GPIO_MODE_OUT_PP_LOW_FAST = (u8)0xE0, // 0b11100000, /*!< Output push-pull, low level, 10MHz */
GPIO_MODE_OUT_OD_LOW_SLOW = (u8)0x80, // 0b10000000, /*!< Output open-drain, low level, 2MHz */
GPIO_MODE_OUT_PP_LOW_SLOW = (u8)0xC0, // 0b11000000, /*!< Output push-pull, low level, 2MHz */
GPIO_MODE_OUT_OD_HIZ_FAST = (u8)0xB0, // 0b10110000, /*!< Output open-drain, high-impedance level,10MHz */
GPIO_MODE_OUT_PP_HIGH_FAST = (u8)0xF0, // 0b11110000, /*!< Output push-pull, high level, 10MHz */
GPIO_MODE_OUT_OD_HIZ_SLOW = (u8)0x90, // 0b10010000, /*!< Output open-drain, high-impedance level, 2MHz */
GPIO_MODE_OUT_PP_HIGH_SLOW = (u8)0xD0 // 0b11010000 /*!< Output push-pull, high level, 2MHz */
}GPIO_Mode_TypeDef;
/**

View File

@@ -45,9 +45,16 @@ u8 ITC_GetCPUCC(void)
_asm("push cc");
_asm("pop a");
return; /* Ignore compiler warning, the returned value is in A register */
#else /* _RAISONANCE_ */
#endif
#ifdef _RAISONANCE_
return _getCC_();
#endif /* _COSMIC_*/
#endif
#ifdef _IAR_SYSTEMS_
__asm("push cc");
__asm("pop a");
#endif
}

View File

@@ -31,6 +31,14 @@
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/
/**
* IAR EWSTM8: Ignore unused variable warning on dummy variable.
*/
#ifdef __IAR_SYSTEMS_ICC__
#pragma diag_suppress=Pe550
#endif
/** @}
* @addtogroup UART2_Public_Functions
* @{
@@ -149,7 +157,7 @@ void UART2_Init(u32 BaudRate, UART2_WordLength_TypeDef WordLength, UART2_StopBit
UART2->CR3 |= (u8)((u8)SyncMode & UART2_CR3_CKEN);
}
}
/**
* @brief Returns the most recent received data by the UART2 peripheral.
@@ -179,7 +187,7 @@ void UART2_SendData8(u8 Data)
/* Transmit Data */
UART2->DR = Data;
}
/**
* @brief Checks whether the specified UART2 flag is set or not.
@@ -253,8 +261,8 @@ FlagStatus UART2_GetFlagStatus(UART2_Flag_TypeDef UART2_FLAG)
/* Return the UART2_FLAG status*/
return status;
}
}
/**
* @}

View File

@@ -32,6 +32,7 @@
#include "atom.h"
#include "atomport-private.h"
#include "atomport-tests.h"
#include "atomtests.h"
#include "atomtimer.h"
#include "uart.h"
@@ -104,10 +105,10 @@ extern int _stack;
static ATOM_TCB main_tcb;
/* Main thread's stack area (large so place outside of the small page0 area on STM8) */
@near static uint8_t main_thread_stack[MAIN_STACK_SIZE_BYTES];
NEAR static uint8_t main_thread_stack[MAIN_STACK_SIZE_BYTES];
/* Idle thread's stack area (large so place outside of the small page0 area on STM8) */
@near static uint8_t idle_thread_stack[IDLE_STACK_SIZE_BYTES];
NEAR static uint8_t idle_thread_stack[IDLE_STACK_SIZE_BYTES];
/* Forward declarations */
@@ -162,9 +163,6 @@ void main ( void )
}
}
while (1)
;
/* There was an error starting the OS if we reach here */
return;
}

View File

@@ -1,78 +1,138 @@
#include <stdio.h>
#include "stm8s.h"
#include "atom.h"
#include "atommutex.h"
#include "uart.h"
/*
* Semaphore for single-threaded access to UART device
*/
static ATOM_MUTEX uart_mutex;
/*
* Initialize the UART to requested baudrate, tx/rx, 8N1.
*/
int uart_init(uint32_t baudrate)
{
int status;
/**
* Set up UART2 for putting out debug messages.
* This the UART used on STM8S Discovery, change if required.
*/
UART2_DeInit();
UART2_Init (baudrate, UART2_WORDLENGTH_8D, UART2_STOPBITS_1, UART2_PARITY_NO,
UART2_SYNCMODE_CLOCK_DISABLE, UART2_MODE_TXRX_ENABLE);
/* Create a mutex for single-threaded putchar() access */
if (atomMutexCreate (&uart_mutex) != ATOM_OK)
{
status = -1;
}
else
{
status = 0;
}
/* Finished */
return (status);
}
/**
* \b putchar
*
* Retarget putchar() to use UART2
*
* @param[in] c Character to send
*
* @return Character sent
*/
char putchar (char c)
{
/* Block on private access to the UART */
if (atomMutexGet(&uart_mutex, 0) == ATOM_OK)
{
/* Convert \n to \r\n */
if (c == '\n')
putchar('\r');
/* Write a character to the UART2 */
UART2_SendData8(c);
/* Loop until the end of transmission */
while (UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET)
;
#include <stdio.h>
#include <stddef.h>
#include "stm8s.h"
#include "atom.h"
#include "atommutex.h"
#include "uart.h"
/*
* Semaphore for single-threaded access to UART device
*/
static ATOM_MUTEX uart_mutex;
/*
* Initialize the UART to requested baudrate, tx/rx, 8N1.
*/
int uart_init(uint32_t baudrate)
{
int status;
/**
* Set up UART2 for putting out debug messages.
* This the UART used on STM8S Discovery, change if required.
*/
UART2_DeInit();
UART2_Init (baudrate, UART2_WORDLENGTH_8D, UART2_STOPBITS_1, UART2_PARITY_NO,
UART2_SYNCMODE_CLOCK_DISABLE, UART2_MODE_TXRX_ENABLE);
/* Create a mutex for single-threaded putchar() access */
if (atomMutexCreate (&uart_mutex) != ATOM_OK)
{
status = -1;
}
else
{
status = 0;
}
/* Finished */
return (status);
}
/**
* \b uart_putchar
*
* Write a char out via UART2
*
* @param[in] c Character to send
*
* @return Character sent
*/
char uart_putchar (char c)
{
/* Block on private access to the UART */
if (atomMutexGet(&uart_mutex, 0) == ATOM_OK)
{
/* Convert \n to \r\n */
if (c == '\n')
putchar('\r');
/* Write a character to the UART2 */
UART2_SendData8(c);
/* Loop until the end of transmission */
while (UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET)
;
/* Return mutex access */
atomMutexPut(&uart_mutex);
}
return (c);
}
}
return (c);
}
/* COSMIC: Requires putchar() routine to override stdio */
#if defined(__CSMC__)
/**
* \b putchar
*
* Retarget putchar() to use UART2
*
* @param[in] c Character to send
*
* @return Character sent
*/
char putchar (char c)
{
return (uart_putchar(c));
}
#endif /* __CSMC__ */
/* IAR: Requires __write() routine to override stdio */
#if defined(__IAR_SYSTEMS_ICC__)
/**
* \b __write
*
* Override for IAR stream output
*
* @param[in] handle Stdio handle. -1 to flush.
* @param[in] buf Pointer to buffer to be written
* @param[in] bufSize Number of characters to be written
*
* @return Number of characters sent
*/
size_t __write(int handle, const unsigned char *buf, size_t bufSize)
{
size_t chars_written = 0;
/* Ignore flushes */
if (handle == -1)
{
chars_written = (size_t)0;
}
/* Only allow stdout/stderr output */
else if ((handle != 1) && (handle != 2))
{
chars_written = (size_t)-1;
}
/* Parameters OK, call the low-level character output routine */
else
{
while (chars_written < bufSize)
{
uart_putchar (buf[chars_written]);
chars_written++;
}
}
return (chars_written);
}
#endif /* __IAR_SYSTEMS_ICC__ */

View File

@@ -139,7 +139,7 @@ uint32_t test_start (void)
/* Check that time has advanced by exactly 1 tick */
if ((end_time - start_time) != 1)
{
ATOMLOG (_STR("Tick1:%d\n"), (end_time-start_time));
ATOMLOG (_STR("Tick1:%d\n"), (int)(end_time-start_time));
failures++;
}
}
@@ -175,7 +175,7 @@ uint32_t test_start (void)
/* Check that time has advanced by exactly 2 ticks */
if ((end_time - start_time) != 2)
{
ATOMLOG (_STR("Tick2:%d\n"), (end_time-start_time));
ATOMLOG (_STR("Tick2:%d\n"), (int)(end_time-start_time));
failures++;
}
}
@@ -211,7 +211,7 @@ uint32_t test_start (void)
/* Check that time has advanced by exactly 500 ticks */
if ((end_time - start_time) != 500)
{
ATOMLOG (_STR("Tick500:%d\n"), (end_time-start_time));
ATOMLOG (_STR("Tick500:%d\n"), (int)(end_time-start_time));
failures++;
}
}

View File

@@ -136,7 +136,7 @@ uint32_t test_start (void)
{
if (cb_order[i] != i)
{
ATOMLOG (_STR("T%d=%d\n"), i, cb_order[i]);
ATOMLOG (_STR("T%d=%d\n"), i, (int)cb_order[i]);
failures++;
}
}