mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-01-24 16:53:14 +01:00
Compare commits
22 Commits
release1.1
...
release1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bc174d316 | ||
|
|
babfd6b9c5 | ||
|
|
5635706d4b | ||
|
|
7f2b53dd61 | ||
|
|
4b42544c3c | ||
|
|
62c2ae9fec | ||
|
|
af47062d90 | ||
|
|
b39b4eac47 | ||
|
|
91793d1398 | ||
|
|
f050c44d73 | ||
|
|
98547058bf | ||
|
|
0a2df500dc | ||
|
|
d4f68440a2 | ||
|
|
02c9cd040c | ||
|
|
973e2fb4aa | ||
|
|
205c05dc25 | ||
|
|
5402faf224 | ||
|
|
c0c953b476 | ||
|
|
619c8c3e4a | ||
|
|
08098370d4 | ||
|
|
394e04ec4a | ||
|
|
538a535fe9 |
@@ -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
|
||||
|
||||
@@ -7,10 +7,11 @@ License: BSD Revised
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
STM8 PORT
|
||||
STM8 PORT - COSMIC COMPILER
|
||||
|
||||
This folder contains a port of the Atomthreads real time kernel for the
|
||||
STM8 processor architecture.
|
||||
STM8 processor architecture. These instructions cover usage of Atomthreads
|
||||
with the Cosmic compiler (CXSTM8).
|
||||
|
||||
All of the cross-platform kernel code is contained in the top-level
|
||||
'kernel' folder, while ports to specific CPU architectures are contained in
|
||||
@@ -20,7 +21,7 @@ as the context-switch routine which saves and restores processor registers
|
||||
on a thread switch. In this case, the kernel port is split into two files:
|
||||
|
||||
* atomport.c: Those functions which can be written in C
|
||||
* atomport-asm.s: The main register save/restore assembler routines
|
||||
* atomport-asm-cosmic.s: The main register save/restore assembler routines
|
||||
|
||||
Each Atomthreads port requires also a header file which describes various
|
||||
architecture-specific details such as appropriate types for 8-bit, 16-bit
|
||||
@@ -43,10 +44,12 @@ provides an easy mechanism for building, downloading and running the test
|
||||
suite to prove the OS on your target.
|
||||
|
||||
The port was carried out and tested on an STM8S105C6 running within an
|
||||
STM8S-Discovery board, utilising the Cosmic compiler tools. It is possible
|
||||
to use it with other processors in the STM8 range, as well as other
|
||||
hardware platforms and compilers, with minimal changes. Platform and
|
||||
compiler specific code has been kept to an absolute minimum.
|
||||
STM8S-Discovery board, and supports both the Cosmic and IAR compiler tools.
|
||||
It is possible to use it with other processors in the STM8 range, as well
|
||||
as other hardware platforms and compilers, with minimal changes. Platform
|
||||
and compiler specific code has been kept to an absolute minimum. This
|
||||
README covers usage of Atomthreads with the Cosmic compiler. Instructions
|
||||
for users of the IAR compiler are available in README-IAR.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
@@ -56,8 +59,8 @@ PREREQUISITES
|
||||
The port works out-of-the-box with the Cosmic compiler tools for building.
|
||||
Applications are generated in .s19 form and can be programmed with any
|
||||
supporting programming software, including the free STVP (visual
|
||||
programmer tool). At this time ST do not provide a command-line programmer
|
||||
application suitable for use with STM8.
|
||||
programmer tool). At this time there does not appear to be a command-line
|
||||
programmer application suitable for use with STM8.
|
||||
|
||||
The Cosmic compiler and STVP are currently Windows-only applications. For
|
||||
users of other operating systems the Cosmic compiler may work in
|
||||
@@ -73,7 +76,7 @@ The core software prerequisites are therefore:
|
||||
Optionally, application build, program and debug can be carried out
|
||||
using ST's visual debug tool, STVD.
|
||||
|
||||
Use with alternative compiler tools may require some modification, but you
|
||||
Use with alternative compiler tools will require some modification, but you
|
||||
can easily replace STVP by your own favourite programmer if required.
|
||||
|
||||
|
||||
@@ -113,9 +116,9 @@ automated tests.
|
||||
BUILD VIA STVD PROJECT
|
||||
|
||||
For building applications using STVD you can use the sample project file
|
||||
atomthreads-sample.stw. This builds a sample full application which runs
|
||||
the "sem1" automated test. Applications can be downloaded directly to the
|
||||
target hardware (e.g. STM8S-Discovery) and run via the integrated
|
||||
atomthreads-sample-cosmic.stw. This builds a sample full application which
|
||||
runs the "sem1" automated test. Applications can be downloaded directly to
|
||||
the target hardware (e.g. STM8S-Discovery) and run via the integrated
|
||||
debugger. Press the exclamation button to run, and confirm that the LED
|
||||
flashes once per second (if running on an STM8S-Discovery) to ensure that
|
||||
the test has passed.
|
||||
@@ -152,25 +155,25 @@ should set up your environment variables as follows:
|
||||
|
||||
The full build is carried out using simply:
|
||||
|
||||
* make
|
||||
* make -f cosmic.mak
|
||||
|
||||
All objects are built into the 'build' folder under ports/stm8. The build
|
||||
process builds separate target applications for each automated test, and
|
||||
appropriate .stm8 or .s19 files can be found in the build folder ready for
|
||||
downloading to and running on the target. Because of the limited resources
|
||||
on the STM8, and the large amount of automated tests, each test is built
|
||||
and run as a separate application.
|
||||
All objects are built into the 'build-cosmic' folder under ports/stm8. The
|
||||
build process builds separate target applications for each automated test,
|
||||
and appropriate .stm8 or .s19 files can be found in the build folder ready
|
||||
for downloading to and running on the target. Because of the limited
|
||||
resources on the STM8, and the large amount of automated tests, each test
|
||||
is built and run as a separate application.
|
||||
|
||||
|
||||
All built objects etc can be cleaned using:
|
||||
|
||||
* make clean
|
||||
* make -f cosmic.mak clean
|
||||
|
||||
|
||||
The Atomthreads sources are documented using Doxygen markup. You can build
|
||||
both the kernel and STM8 port documentation from this folder using:
|
||||
|
||||
* make doxygen
|
||||
* make -f cosmic.mak doxygen
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
@@ -241,11 +244,12 @@ The STM8 device on the Discovery only offers UART2. If you are using a
|
||||
different device or wish to use an alternative UART then you must change
|
||||
the stm8s_conf.h file.
|
||||
|
||||
If you are using a CPU other than the STM8S105C6 you should modify
|
||||
PART in the Makefile (or the preprocessor settings for both Debug and
|
||||
Release projects if using the STVD project) to specify your CPU. You may
|
||||
also wish to enable any CPU peripherals which you wish to use in the
|
||||
stm8s_conf.h file.
|
||||
If you are using a CPU other than the STM8S105C6 you should change the
|
||||
PART macro from "STM8S105" to your target CPU. This can be changed in the
|
||||
cosmic.mak Makefile. If you are using the STVD project it should be
|
||||
changed in the project preprocessor settings for both Debug and Release
|
||||
builds. You may also wish to enable any CPU peripherals which you wish to
|
||||
use in the stm8s_conf.h file.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
@@ -255,10 +259,16 @@ RUNNING THE AUTOMATED TESTS
|
||||
Atomthreads contains a set of generic kernel tests which can be run on any
|
||||
port to prove that all core functionality is working on your target.
|
||||
|
||||
The full set of tests can be found in the top-level 'tests' folder. Each of
|
||||
these tests is built as an independent application in the 'build' folder.
|
||||
Run them individually using the STVP process described above. For example
|
||||
to run the 'kern1.c' test use STVP to program and run it.
|
||||
The full set of tests can be found in the top-level 'tests' folder. The
|
||||
Makefile builds each of these tests as independent applications in the
|
||||
'build' folder. Run them individually using the STVP process described
|
||||
above. For example to run the 'kern1.c' test use STVP to program and run
|
||||
it.
|
||||
|
||||
You may also build the tests using the STVD project, but to run each
|
||||
different test you must manually remove the previous test module (e.g.
|
||||
kern1.c) and replace it with one of other tests, which can be quite time
|
||||
consuming compared to building all tests in one command via the Makefile.
|
||||
|
||||
To view the test results, watch the LED on the STM8S-Discovery. This will
|
||||
flash once per second if the test passed, and once every 1/8 second if the
|
||||
@@ -292,9 +302,9 @@ functions. You can generally simply replace the call to the test modules by
|
||||
a call to your own application startup code.
|
||||
|
||||
Projects developed within STVD can be started using the sample workspace
|
||||
atomthreads-sample.stw. If you wish to create your own STVD project from
|
||||
scratch, then you should ensure you change the project settings for both
|
||||
Debug and Release builds as follows:
|
||||
atomthreads-sample-cosmic.stw. If you wish to create your own STVD project
|
||||
from scratch, then you should ensure you change the project settings for
|
||||
both Debug and Release builds as follows:
|
||||
|
||||
* Toolset: "STM8 Cosmic"
|
||||
* MCU Selection: Appropriate for your platform (STM8S10C56 for Discovery)
|
||||
@@ -347,9 +357,9 @@ what level of stack the application code in question requires.
|
||||
|
||||
At this time the maximum stack consumed by the test threads within the
|
||||
automated test modules is 95 bytes of stack, and the main test thread has
|
||||
been seen to consume 161 bytes of stack. At this time the timer2 test is
|
||||
the largest consumer of test thread stack (95 bytes) and the sem4 test
|
||||
consumes the largest main thread stack (161 bytes). If your applications
|
||||
been seen to consume 163 bytes of stack. At this time the timer2 test is
|
||||
the largest consumer of test thread stack (95 bytes) and the sem3 test
|
||||
consumes the largest main thread stack (163 bytes). If your applications
|
||||
have large amounts of local data or call several subroutines then you may
|
||||
find that you need larger than 128 bytes.
|
||||
|
||||
@@ -436,4 +446,73 @@ included in any STM8 products. If it is included in future products then
|
||||
you will need to put the device in the stack compatible mode described.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
WRITING NEW INTERRUPT HANDLERS
|
||||
|
||||
All interrupt handlers which will call out to the OS kernel and potentially
|
||||
cause a thread switch must call atomIntEnter() and atomIntExit(). An
|
||||
example of this can be seen in the timer tick ISR in atomport.c.
|
||||
|
||||
With the Cosmic compiler port it is also necessary to add the @svlreg
|
||||
modifier to any interrupt handlers which call out to the OS kernel.
|
||||
Alternatively you may use the INTERRUPT macro from atomport-private.h which
|
||||
always adds the @svlreg modifier. This modifier ensures that the c_lreg
|
||||
virtual register is saved on the interrupted thread's stack for any
|
||||
preemptive context switches. It also ensures that longs are available for
|
||||
use within any OS kernel code called as part of the interrupt handling.
|
||||
|
||||
You may also implement fast interrupt handlers in the system which do not
|
||||
call atomIntEnter()/atomIntExit() and which do not need the @svlreg
|
||||
modifier, however these ISRs cannot perform OS functions such as posting
|
||||
semaphores or effecting a thread switch.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
COSMIC COMPILER VIRTUAL REGISTERS
|
||||
|
||||
The STM8 has only very few CPU registers, so the Cosmic compiler augments
|
||||
them with three "virtual" registers, which are simply locations in fast
|
||||
memory. These registers are called c_x, c_y and c_lreg.
|
||||
|
||||
The Atomthreads context switch for Cosmic/STM8 takes advantage of the fact
|
||||
that all CPU and virtual registers are automatically saved on the stack by
|
||||
the compiler when calling out to C functions (and even then only if
|
||||
necessary).
|
||||
|
||||
For cooperative context switches (where a thread calls an OS kernel
|
||||
function to schedule itself out), any of these registers which should be
|
||||
preserved across the function call are automatically saved on the stack by
|
||||
the compiler before the context switch is even called. This means that no
|
||||
CPU or virtual registers actually have to be saved in the context switch
|
||||
routine, making cooperative switches potentially very cheap if few
|
||||
registers must be preserved.
|
||||
|
||||
For preemptive switches (where an ISR has interrupted a thread and wishes
|
||||
to switch to a new thread), the interrupt handler prologue automatically
|
||||
saves all CPU registers (actually done automatically by the CPU) and all
|
||||
of the virtual registers. In this case all registers must always be saved
|
||||
because the ISR has no knowledge of what registers the interrupted thread
|
||||
was using, so we cannot take advantage of the potential for saving fewer
|
||||
than the full set of registers that we achieve with cooperative switches.
|
||||
With the Cosmic compiler, interrupt handlers that call out to C functions
|
||||
(as would happen on a thread switch) always save the CPU registers (done by
|
||||
the CPU in fact) and the virtual registers c_x and c_y. For the Atomthreads
|
||||
port we force interrupt handlers to also save the virtual register c_lreg.
|
||||
This is to ensure that the interrupted thread's c_lreg value is preserved
|
||||
across a thread switch, but also ensures that longs can be used within the
|
||||
OS kernel code called by interrupt handlers (c_lreg is used by the compiler
|
||||
for handling longs and floats).
|
||||
|
||||
An alternative scheme would be to not save c_lreg in all interrupt
|
||||
handlers and instead save it in the context-switch function. This would
|
||||
allow interrupt handlers to avoid saving the 4-byte c_lreg on the stack,
|
||||
but it would mean that any OS kernel code called by interrupt handlers
|
||||
could not deal with longs, which would be an unfortunate burden on the
|
||||
core portable OS code just for the benefit of this one architecture and
|
||||
compiler. It would also mean that c_lreg is always saved unnecessarily
|
||||
for every cooperative context switch.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
448
ports/stm8/README-IAR
Normal file
448
ports/stm8/README-IAR
Normal file
@@ -0,0 +1,448 @@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Library: Atomthreads
|
||||
Author: Kelvin Lawson <kelvinl@users.sf.net>
|
||||
Website: http://atomthreads.com
|
||||
License: BSD Revised
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
STM8 PORT - IAR COMPILER
|
||||
|
||||
This folder contains a port of the Atomthreads real time kernel for the
|
||||
STM8 processor architecture. These instructions cover usage of Atomthreads
|
||||
with the IAR Embedded Workbench compiler (EWSTM8).
|
||||
|
||||
All of the cross-platform kernel code is contained in the top-level
|
||||
'kernel' folder, while ports to specific CPU architectures are contained in
|
||||
the 'ports' folder tree. A port to a CPU architecture can comprise just one
|
||||
or two modules which provide the architecture-specific functionality, such
|
||||
as the context-switch routine which saves and restores processor registers
|
||||
on a thread switch. In this case, the kernel port is split into two files:
|
||||
|
||||
* atomport.c: Those functions which can be written in C
|
||||
* atomport-asm-iar.s: The main register save/restore assembler routines
|
||||
|
||||
Each Atomthreads port requires also a header file which describes various
|
||||
architecture-specific details such as appropriate types for 8-bit, 16-bit
|
||||
etc variables, the port's system tick frequency, and macros for performing
|
||||
interrupt lockouts / critical sections:
|
||||
|
||||
* atomuser.h: Port-specific header required by the kernel for each port
|
||||
|
||||
A few additional source files are also included here:
|
||||
|
||||
* tests-main.c: Main application file (used for launching automated tests)
|
||||
* uart.c: UART wrapper to allow use of stdio/printf()
|
||||
* stm8s-periphs/*.*: Peripheral drivers as delivered by ST (no changes
|
||||
to distributed code).
|
||||
|
||||
Atomthreads includes a suite of automated tests which prove the key OS
|
||||
functionality, and can be used with any architecture ports. This port
|
||||
provides an easy mechanism for building, downloading and running the test
|
||||
suite to prove the OS on your target.
|
||||
|
||||
The port was carried out and tested on an STM8S105C6 running within an
|
||||
STM8S-Discovery board, and supports both the Cosmic and IAR compiler tools.
|
||||
It is possible to use it with other processors in the STM8 range, as well
|
||||
as other hardware platforms and compilers, with minimal changes. Platform
|
||||
and compiler specific code has been kept to an absolute minimum. This
|
||||
README covers usage of Atomthreads with the IAR compiler. Instructions for
|
||||
users of the Cosmic compiler are available in README-COSMIC.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
PREREQUISITES
|
||||
|
||||
The port works out-of-the-box with the IAR compiler tools for building.
|
||||
Applications are generated in ELF format and can be programmed and debugged
|
||||
using the IAR Embedded Workbench GUI or the free STVP (visual programmer
|
||||
tool). At this time there does not appear to be a command-line programmer
|
||||
application suitable for use with STM8.
|
||||
|
||||
IAR Embedded Workbench for STM8 is a Windows-only application. For
|
||||
users of other operating systems the IAR tools may work in environments
|
||||
like Wine, but the USB programming tools are less likely to be supported.
|
||||
Embedded Workbench for STM8 can, however, be run successfully within a VM
|
||||
such as VirtualBox, including USB download and debug.
|
||||
|
||||
The core software prerequisites are therefore:
|
||||
* IAR Embedded Workbench STM8
|
||||
|
||||
Use with alternative compiler tools will require some modification, but you
|
||||
can easily replace the EWSTM8 IDE by your own favourite programmer if
|
||||
required (e.g. STVP).
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
BUILDING THE SOURCE
|
||||
|
||||
You may build Atomthreads using whichever build environment you desire. For
|
||||
your convenience we provide both a ready-rolled Makefile-based build system
|
||||
and an Embedded Workbench (EWSTM8) project. The EWSTM8 project permits easy
|
||||
building, programming and debugging, but does not easily support building
|
||||
a wide range of application builds within the same project, which is
|
||||
useful for building the numerous automated tests. For the automated tests
|
||||
you may find it easier to use the Makefile which automatically builds all
|
||||
automated tests.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
BUILD VIA EWSTM8 PROJECT
|
||||
|
||||
For building applications using the EWSTM8 IDE you can use the sample
|
||||
project file atomthreads-sample-iar.ewp. This builds a sample full
|
||||
application which runs the "sem1" automated test. Applications can be
|
||||
downloaded directly to the target hardware (e.g. STM8S-Discovery) and run
|
||||
via the integrated debugger. You can start the application running, and
|
||||
confirm that the LED flashes once per second (if running on an
|
||||
STM8S-Discovery) to ensure that the test has passed.
|
||||
|
||||
This is also a good starting point for building your own applications:
|
||||
simply modify the file tests-main.c which starts the test application.
|
||||
You can run any of the other automated tests by replacing the file sem1.c
|
||||
within the project by another of the tests within the atomthreads tests
|
||||
folder. This is rather painful using a GUI interface due to the large
|
||||
number of test files, and you may prefer to use the Makefile-based system
|
||||
instead which builds all automated tests in one command.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
BUILD VIA MAKEFILE
|
||||
|
||||
A Makefile is also provided for building the kernel, port and automated
|
||||
tests. This is particularly useful for building the automated tests
|
||||
because many different independent applications need to be built which is
|
||||
not easily achieved within the EWSTM8 environment.
|
||||
|
||||
For a Windows system you can obtain a Make application suitable for use
|
||||
with the IAR compiler from:
|
||||
|
||||
* http://www.cosmic-software.com/comp_utils/GNU_Make.zip
|
||||
|
||||
Assuming you install the above into C:\Program Files\GNU_MAKE, you
|
||||
should set up your environment variables as follows:
|
||||
|
||||
* set PATH=%PATH%;C:\Program Files\GNU_MAKE;C:\Program Files\IAR Systems\Embedded Workbench 6.0\stm8\bin
|
||||
* set MAKE_MODE=DOS
|
||||
|
||||
|
||||
The full build is carried out using simply:
|
||||
|
||||
* make -f iar.mak
|
||||
|
||||
All objects are built into the 'build-iar' folder under ports/stm8. The
|
||||
build process builds separate target applications for each automated test,
|
||||
and appropriate .elf or .s19 files can be found in the build folder ready
|
||||
for downloading to and running on the target. Because of the limited
|
||||
resources on the STM8, and the large amount of automated tests, each test
|
||||
is built and run as a separate application.
|
||||
|
||||
|
||||
All built objects etc can be cleaned using:
|
||||
|
||||
* make -f iar.mak clean
|
||||
|
||||
|
||||
The Atomthreads sources are documented using Doxygen markup. You can build
|
||||
both the kernel and STM8 port documentation from this folder using:
|
||||
|
||||
* make -f iar.mak doxygen
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
PROGRAMMING MAKEFILE-BUILT APPLICATIONS TO THE TARGET DEVICE
|
||||
|
||||
When developing within EWSTM8, programs can be downloaded directly to the
|
||||
target. If, however, you are building applications separately using a
|
||||
Makefile or similar, then you are not able to program the application
|
||||
using EWSTM8. None of the tools delivered by ST appear to be designed to
|
||||
cater for those who build applications externally, but it is possible using
|
||||
STVP.
|
||||
|
||||
The following development workflow can be used (note that these settings
|
||||
apply to the STM8S-Discovery):
|
||||
|
||||
* Build app using Makefile.
|
||||
* Open STVP and configure to use Swim ST-Link for CPU STM8105C6.
|
||||
* Open application .s19 file and program using "Program All Tabs".
|
||||
|
||||
Unfortunately STVP does not have a command to reset and start the CPU
|
||||
running, but it can be forced into doing so by reconfiguring the
|
||||
programmer:
|
||||
|
||||
* Select "Configure ST Visual Programmer" from the Configure menu.
|
||||
|
||||
Your application should now be programmed and running.
|
||||
|
||||
If you wish to program and run another application then you can open and
|
||||
program it in STVP, then use the Configure menu again to reset the
|
||||
device and start it running.
|
||||
|
||||
Other programming tools may exist but are not apparent in the toolset
|
||||
delivered for use the STM8S Discovery platform.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
STM8S-DISCOVERY SPECIFICS
|
||||
|
||||
There are very minimal board-specific aspects to the STM8 port so it is
|
||||
trivial to run Atomthreads on other STM8 platforms.
|
||||
|
||||
The test applications make use of a LED to indicate test pass/fail status.
|
||||
This is currently configured to use a bit in GPIOD, which on the Discovery
|
||||
board maps to the board's only LED. You may change the port and register
|
||||
bit in tests-main.c to utilise a different pin on other hardware platforms.
|
||||
You may also completely omit the LED flashing in the test application if
|
||||
you prefer to use the UART for monitoring test status.
|
||||
|
||||
The test applications also make use of the UART to print out pass/fail
|
||||
indications and other information. For this you should connect a serial
|
||||
cable to the Discovery board via the external pin connectors. Use of
|
||||
a UART is not required if you prefer to use the LED or some other method
|
||||
of notifying test pass/fail status.
|
||||
|
||||
To connect a serial cable to the Discovery you will need to connect to
|
||||
the following pins on the external connectors:
|
||||
Vcc: CN2 pin 8
|
||||
GND: CN2 pin 7
|
||||
UART TX: CN4 pin 10 (connect to RX at the PC end)
|
||||
UART RX: CN4 pin 9 (connect to TX at the PC end)
|
||||
Note that the board uses TTL levels so you may need to use a level
|
||||
converter. External level converters may need to be powered using
|
||||
a Vdd of 5v, which can be achieved by positioning JP1 on the Discovery.
|
||||
|
||||
The STM8 device on the Discovery only offers UART2. If you are using a
|
||||
different device or wish to use an alternative UART then you must change
|
||||
the stm8s_conf.h file.
|
||||
|
||||
If you are using a CPU other than the STM8S105C6 you should change the
|
||||
PART macro from "STM8S105" to your target CPU. This can be changed in the
|
||||
iar.mak Makefile. If you are using the EWSTM8 project it should be
|
||||
changed in the project C/C++ Compiler Preprocessor settings for both Debug
|
||||
and Release builds, and you must also change the target device in the
|
||||
project's "General Options". You may also wish to enable any CPU
|
||||
peripherals which you wish to use in the stm8s_conf.h file.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
RUNNING THE AUTOMATED TESTS
|
||||
|
||||
Atomthreads contains a set of generic kernel tests which can be run on any
|
||||
port to prove that all core functionality is working on your target.
|
||||
|
||||
The full set of tests can be found in the top-level 'tests' folder. The
|
||||
Makefile builds each of these tests as independent applications in the
|
||||
'build' folder. Run them individually using the STVP process described
|
||||
above. For example to run the 'kern1.c' test use STVP to program and run
|
||||
it.
|
||||
|
||||
You may also build the tests using the EWSTM8 project, but to run each
|
||||
different test you must manually remove the previous test module (e.g.
|
||||
kern1.c) and replace it with one of other tests, which can be quite time
|
||||
consuming compared to building all tests in one command via the Makefile.
|
||||
|
||||
To view the test results, watch the LED on the STM8S-Discovery. This will
|
||||
flash once per second if the test passed, and once every 1/8 second if the
|
||||
test failed.
|
||||
|
||||
If you wish to use the UART, connect a serial debug cable to your target
|
||||
platform (defaults to 9600bps 8N1). On starting, the test applications
|
||||
print out "Go" on the UART. Once the test is complete they will print
|
||||
out "Pass" or "Fail", along with other information if the test failed.
|
||||
|
||||
Most of the tests complete within a few seconds, but some (particularly
|
||||
the stress tests) can take several seconds, so be patient.
|
||||
|
||||
The full suite of tests endeavours to exercise as much of the kernel code
|
||||
as possible, and can be used for quick confirmation of core OS
|
||||
functionality if you ever need to make a change to the kernel or port.
|
||||
|
||||
The test application main() is contained in tests-main.c. This initialises
|
||||
the OS, creates a main thread, and calls out to the test modules. It also
|
||||
initialises the UART driver for use by stdout.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
WRITING APPLICATIONS
|
||||
|
||||
The easiest way to start a new application which utilises the Atomthreads
|
||||
scheduler is to base your main application startup on tests-main.c. This
|
||||
initialises the OS, sets up a UART and calls out to the test module entry
|
||||
functions. You can generally simply replace the call to the test modules by
|
||||
a call to your own application startup code.
|
||||
|
||||
Projects developed within EWSTM8 can be started using the sample project
|
||||
atomthreads-sample-iar.ewp. If you wish to create your own EWSTM8 project
|
||||
from scratch, then you should ensure you change the project settings for
|
||||
both Debug and Release builds as follows:
|
||||
|
||||
* General Options -> Target -> Device: CPU part (e.g. "STM8S105C6")
|
||||
* C/C++ Compiler -> Diagnostics: Suppress "Pa050"
|
||||
* C/C++ Compiler -> Preprocessor -> Defined Symbols:
|
||||
CPU part (e.g. "STM8S105")
|
||||
Thread stack-checking if required ("ATOM_STACK_CHECKING")
|
||||
For example "STM8S105, ATOM_STACK_CHECKING"
|
||||
* Assembler -> Diagnostics: Suppress "Pa050"
|
||||
* Repeat above for Debug and Release projects (you may want to
|
||||
disable ATOM_STACK_CHECKING for Release builds).
|
||||
|
||||
Other options you may wish to change:
|
||||
|
||||
* Tools -> Options -> Editor -> EOL Characters: "Preserve". This preserves
|
||||
the line endings, bearing in mind that the Atomthreads kernels works
|
||||
with many host operating system toolchains.
|
||||
* Options -> Debugger -> "ST Link" (e.g. for STM8S Discovery)
|
||||
|
||||
Add the .C and .S modules from the following folders:
|
||||
* kernel
|
||||
* ports/stm8
|
||||
* ports/stm8s-periphs
|
||||
|
||||
Set include paths as appropriate.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
RAM FOOTPRINT & STACK USAGE
|
||||
|
||||
The Atomthreads kernel is written in well-structured pure C which is highly
|
||||
portable and not targeted at any particular compiler or CPU architecture.
|
||||
For this reason it is not highly optimised for the STM8 architecture, and
|
||||
by its nature will likely have a higher text and data footprint than an
|
||||
RTOS targeted at the STM8 architecture only. The emphasis here is on
|
||||
C-based portable, readable and maintainable code which can run on any CPU
|
||||
architecture, from the 8-bitters up.
|
||||
|
||||
A good rule of thumb when using Atomthreads on the STM8 architecture is
|
||||
that a minimum of 1KB RAM is required in order to support an application
|
||||
with 4 or 5 threads and the idle thread. If a minimum of approximately
|
||||
128 bytes per thread stack is acceptable then you will benefit from the
|
||||
easy-to-read, portable implementation of an RTOS herein.
|
||||
|
||||
The major consumer of RAM when using Atomthreads is your thread stacks.
|
||||
Functionality that is shared between several kernel modules is farmed out
|
||||
to separate functions, resulting in readable and maintainable code but
|
||||
with some associated stack cost of calling out to subroutines. Further,
|
||||
each thread stack is used for saving its own registers on a context
|
||||
switch, and there is no separate interrupt stack which means that each
|
||||
thread stack has to be able to cope with the maximum stack usage of the
|
||||
kernel (and application) interrupt handlers.
|
||||
|
||||
Clearly the stack requirement for each thread depends on what your
|
||||
application code does, and what memory model is used etc, but generally
|
||||
you should find that 128 bytes is enough to allow for the thread to be
|
||||
switched out (and thus save its registers) while deep within a kernel
|
||||
or application call stack, and similarly enough to provide stack for
|
||||
interrupt handlers interrupting while the thread is deep within a kernel
|
||||
or application call stack. You will need to increase this depending on
|
||||
what level of stack the application code in question requires.
|
||||
|
||||
At this time the maximum stack consumed by the test threads within the
|
||||
automated test modules is 85 bytes of stack, and the main test thread has
|
||||
been seen to consume 193 bytes of stack. At this time the queue9 test is
|
||||
the largest consumer of test thread stack (85 bytes) and the sem8 test
|
||||
consumes the largest main thread stack (193 bytes). If your applications
|
||||
have large amounts of local data or call several subroutines then you may
|
||||
find that you need larger than 128 bytes.
|
||||
|
||||
You may monitor the stack usage of your application threads during runtime
|
||||
by defining the macro ATOM_STACK_CHECKING and calling
|
||||
atomThreadStackCheck(). This macro is defined by default in the EWSTM8
|
||||
Debug project so that the automated test modules can check for stack
|
||||
overflows, but you may wish to undefine this in your application
|
||||
when you are happy that the stack usage is acceptable. Enabling
|
||||
ATOM_STACK_CHECKING will increase the size of your threads' TCBs
|
||||
slightly, and will incur a minor CPU cycles overhead whenever threads are
|
||||
created due to prefilling the thread stack with a known value.
|
||||
|
||||
With careful consideration and few threads it would be possible to use
|
||||
a platform with 512 bytes RAM, but not all of the automated test suite
|
||||
would run on such a platform (some of the test modules use 6 threads: a
|
||||
main thread together with 4 test threads and the idle thread).
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
INTERRUPT HANDLING
|
||||
|
||||
Interrupt handlers use the stack of the thread which was running when the
|
||||
interrupt occurred. If no thread rescheduling occurs during the ISR then
|
||||
on exit from the ISR any data stacked by the ISR on the thread's stack is
|
||||
popped off the stack and execution of the thread resumes. If a reschedule
|
||||
during the ISR causes a context switch to a new thread, then the ISR's
|
||||
data will remain on the thread's stack until the thread is scheduled back
|
||||
in.
|
||||
|
||||
Interrupt priorities (via the ITC_SPRx registers) are left in their
|
||||
default power-on state, which disables interrupt nesting. Kernel changes
|
||||
may be required to support interrupt nesting.
|
||||
|
||||
Note that the STM8 programming manual currently describes the following
|
||||
feature:
|
||||
|
||||
"Fast interrupt handling through alternate register files (up to 4
|
||||
contexts) with standard stack compatible mode (for real time OS
|
||||
kernels)"
|
||||
|
||||
This feature was implemented by ST in the core but has to date never been
|
||||
included in any STM8 products. If it is included in future products then
|
||||
you will need to put the device in the stack compatible mode described.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
WRITING NEW INTERRUPT HANDLERS
|
||||
|
||||
All interrupt handlers which will call out to the OS kernel and potentially
|
||||
cause a thread switch must call atomIntEnter() and atomIntExit(). An
|
||||
example of this can be seen in the timer tick ISR in atomport.c.
|
||||
|
||||
You may also implement fast interrupt handlers in the system which do not
|
||||
call atomIntEnter()/atomIntExit(), however these ISRs cannot perform OS
|
||||
functions such as posting semaphores or effecting a thread switch.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
IAR COMPILER VIRTUAL REGISTERS
|
||||
|
||||
The STM8 has only very few CPU registers, so the IAR compiler augments
|
||||
them with sixteen "virtual" registers, which are simply locations in fast
|
||||
memory. These registers are called ?b0 to ?b15.
|
||||
|
||||
The Atomthreads context switch for IAR/STM8 takes advantage of the fact
|
||||
that all CPU and most virtual registers are automatically saved on the
|
||||
stack by the compiler when calling out to C functions (and even then only
|
||||
if necessary). Only the virtual registers ?b8 to ?b15 are expected to be
|
||||
preserved by called functions, so these are the only registers that
|
||||
callers to the context switch routine will not automatically save if
|
||||
necessary.
|
||||
|
||||
For cooperative context switches (where a thread calls an OS kernel
|
||||
function to schedule itself out), most registers will therefore already
|
||||
be saved on a thread's stack if necessary. Only ?b8 to ?b15 actually have
|
||||
to be saved in the context switch routine, making cooperative switches
|
||||
potentially very cheap if few registers must be preserved.
|
||||
|
||||
For preemptive switches (where an ISR has interrupted a thread and wishes
|
||||
to switch to a new thread), the interrupt handler prologue automatically
|
||||
saves all CPU registers (actually done automatically by the CPU) and the
|
||||
virtual registers ?b0 to ?b7. Still only the registers ?b8 to ?b15 have to
|
||||
be saved by the context-switch routine, but in this case ?b0 to ?b7 and the
|
||||
CPU registers are always saved on the thread's stack by the ISR prologue.
|
||||
This is because the ISR has no knowledge of what registers the interrupted
|
||||
thread was using, so we cannot take advantage of the potential for saving
|
||||
fewer than the full set of registers that we achieve with cooperative
|
||||
switches.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
@@ -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,28 +28,31 @@
|
||||
;
|
||||
|
||||
|
||||
; Cosmic assembler routines
|
||||
|
||||
|
||||
; Export functions to other modules
|
||||
xdef _archContextSwitch, _archFirstThreadRestore
|
||||
|
||||
|
||||
; \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)
|
||||
_archContextSwitch:
|
||||
|
||||
; Parameter locations:
|
||||
; Parameter locations (Cosmic calling convention):
|
||||
; old_tcb_ptr = X register (word-width)
|
||||
; new_tcb_ptr = stack (word-width)
|
||||
|
||||
@@ -60,7 +63,11 @@ _archContextSwitch:
|
||||
; PC: Program counter
|
||||
; CC: Code condition register
|
||||
;
|
||||
;
|
||||
; Cosmic compiler virtual registers:
|
||||
;
|
||||
; c_x, c_y: Scratch memory areas saved by ISRs
|
||||
; c_lreg: Scratch memory area only saved by ISRs with @svlreg
|
||||
;
|
||||
; If this is a cooperative context switch (a thread has called us
|
||||
; to schedule itself out), the Cosmic compiler will have saved any
|
||||
; of the registers which it does not want us to clobber. There are
|
||||
@@ -74,15 +81,19 @@ _archContextSwitch:
|
||||
; similarly saved all registers which it needs us not to clobber
|
||||
; which in the case of this compiler is all registers. Again, we
|
||||
; do not need to save any registers because no registers are
|
||||
; expected to be unclobbered by a subroutine.
|
||||
; expected to be unclobbered by a subroutine. Note that it is
|
||||
; necessary to add the @svlreg modifier to ISRs which call out to
|
||||
; the OS in order to force a save of c_lreg. The rest of the CPU
|
||||
; registers and the c_x and c_y virtual registers are, however,
|
||||
; always saved by ISRs which call out to C subroutines.
|
||||
;
|
||||
; This is an unusual context switch routine, because it does not
|
||||
; need to actually save any registers. Instead, the act of
|
||||
; calling this function causes all registers which must not be
|
||||
; clobbered to be saved on the stack anyway in the case of
|
||||
; clobbered to be saved on the stack anyway in the case of
|
||||
; cooperative context switches. For preemptive switches, the
|
||||
; interrupt service routine which calls out to here causes all
|
||||
; registers to be saved in a similar fashion.
|
||||
; interrupt service routine which calls out to here also causes
|
||||
; all registers to be saved in a similar fashion.
|
||||
|
||||
; We do have to do some work in here though: we need to store
|
||||
; the current stack pointer to the current thread's TCB, and
|
||||
@@ -106,7 +117,7 @@ _archContextSwitch:
|
||||
; Our stack frame now contains all registers (if this is a preemptive
|
||||
; switch due to an interrupt handler) or those registers which the
|
||||
; calling function did not wish to be clobbered (if this is a
|
||||
; cooperative context switch). It also contains the return address
|
||||
; cooperative context switch). 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). Finally, the stack also contains the aforementioned
|
||||
@@ -115,7 +126,7 @@ _archContextSwitch:
|
||||
; 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. In most
|
||||
; We are now ready to restore the new thread's context. In most
|
||||
; architecture ports we would typically switch our stack pointer
|
||||
; to the new thread's stack pointer, and pop all of its context
|
||||
; off the stack, before returning to the caller (the original
|
||||
@@ -132,11 +143,11 @@ _archContextSwitch:
|
||||
|
||||
; Pull the new_tcb_ptr parameter from the stack into X register
|
||||
ldw X,($3,SP)
|
||||
|
||||
; Pull the first entry out of new_tcb_ptr (the new thread's
|
||||
|
||||
; 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
|
||||
|
||||
@@ -158,7 +169,7 @@ _archContextSwitch:
|
||||
; 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
|
||||
; 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.
|
||||
@@ -240,8 +251,8 @@ _archContextSwitch:
|
||||
; 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
|
||||
; 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,
|
||||
@@ -266,7 +277,7 @@ _archContextSwitch:
|
||||
; 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
|
||||
; after which all other new threads will first be run by
|
||||
; archContextSwitch().
|
||||
;
|
||||
; Typically ports will implement something similar here to the
|
||||
@@ -274,21 +285,21 @@ _archContextSwitch:
|
||||
; 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
|
||||
; 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
|
||||
; 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
|
||||
; 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).
|
||||
; 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
|
||||
; 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
|
||||
@@ -324,7 +335,7 @@ _archFirstThreadRestore:
|
||||
; 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
|
||||
; 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
|
||||
@@ -339,7 +350,7 @@ _archFirstThreadRestore:
|
||||
; 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
|
||||
|
||||
@@ -350,4 +361,4 @@ _archFirstThreadRestore:
|
||||
ret
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
396
ports/stm8/atomport-asm-iar.s
Normal file
396
ports/stm8/atomport-asm-iar.s
Normal file
@@ -0,0 +1,396 @@
|
||||
;
|
||||
; 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. The same goes for
|
||||
; __interrupt functions (i.e. preemptive switches): with the IAR
|
||||
; compiler A, X, Y and CC will already be saved by interrupt handlers
|
||||
; (those are actually automatically done by the CPU), and (because
|
||||
; we call out from interrupt handlers to C kernel code (e.g.
|
||||
; atomIntExit()) before calling here for a context-switch, the
|
||||
; compiler will also have saved ?b0 to ?b7. This is because those
|
||||
; called C functions cannot know they were called from an interrupt
|
||||
; and will assume that they have ?b0 to ?b7 available as scratch
|
||||
; registers. Either way (cooperative or interrupt/preemptive) we
|
||||
; know that the only registers which must be preserved that are not
|
||||
; already on the stack-frame are ?b8 to ?b15.
|
||||
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
|
||||
@@ -31,9 +31,40 @@
|
||||
#define __ATOM_PORT_PRIVATE_H
|
||||
|
||||
|
||||
/**
|
||||
* Compiler-specific modifier to prevent some functions from saving
|
||||
* and restoring registers on entry and exit, if the function is
|
||||
* known to never complete (e.g. thread entry points).
|
||||
* Reduces stack usage on supporting compilers.
|
||||
*/
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#define NO_REG_SAVE __task
|
||||
#else
|
||||
#define NO_REG_SAVE
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Compiler-specific modifiers for interrupt handler functions.
|
||||
*
|
||||
* COSMIC: Uses @interrupt modifier for interrupt handlers. We
|
||||
* also force all interrupts to save c_lreg, a separate memory
|
||||
* area which Cosmic uses for longs and floats. This memory
|
||||
* area must be saved by interrupt handlers for context
|
||||
* switch purposes, and to avoid making it impossible to use
|
||||
* longs in any OS kernel code accessed by interrupt handlers.
|
||||
*
|
||||
* IAR: Uses __interrupt modifier for interrupt handlers.
|
||||
*/
|
||||
#ifdef __CSMC__
|
||||
#define INTERRUPT @far @interrupt @svlreg
|
||||
#else
|
||||
#define INTERRUPT __interrupt
|
||||
#endif
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
void archInitSystemTickTimer (void);
|
||||
@far @interrupt void TIM1_SystemTickISR (void);
|
||||
|
||||
INTERRUPT void TIM1_SystemTickISR (void);
|
||||
|
||||
#endif /* __ATOM_PORT_PRIVATE_H */
|
||||
|
||||
@@ -49,7 +49,15 @@
|
||||
#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
|
||||
|
||||
/**
|
||||
* IAR EWSTM8: Ignore warnings on volatile ordering thrown up
|
||||
* by ATOMLOG() statements in the test modules.
|
||||
*/
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#pragma diag_suppress=Pa082
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __ATOM_PORT_TESTS_H */
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
|
||||
/** Forward declarations */
|
||||
static void thread_shell (void);
|
||||
static NO_REG_SAVE void thread_shell (void);
|
||||
|
||||
|
||||
/**
|
||||
@@ -66,9 +66,16 @@ static void thread_shell (void);
|
||||
* first time because you can preinitialise the stack context with
|
||||
* a suitable register value that will enable interrupts.
|
||||
*
|
||||
* If the compiler supports it, stack space can be saved by preventing
|
||||
* the function from saving registers on entry. This is because we
|
||||
* are called directly by the context-switch assembler, and know that
|
||||
* threads cannot return from here. The NO_REG_SAVE macro is used to
|
||||
* denote such functions in a compiler-agnostic way, though not all
|
||||
* compilers support it.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static void thread_shell (void)
|
||||
static NO_REG_SAVE void thread_shell (void)
|
||||
{
|
||||
ATOM_TCB *curr_tcb;
|
||||
|
||||
@@ -79,7 +86,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 +112,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 +194,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 +231,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 +282,10 @@ void archInitSystemTickTimer ( void )
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void TIM1_SystemTickISR (void)
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
#pragma vector = 13
|
||||
#endif
|
||||
INTERRUPT void TIM1_SystemTickISR (void)
|
||||
{
|
||||
/* Call the interrupt entry routine */
|
||||
atomIntEnter();
|
||||
@@ -252,7 +294,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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -83,10 +83,10 @@ String.100.0=STM8S105C6
|
||||
|
||||
[Root.Config.0.Settings.3]
|
||||
String.2.0=Compiling $(InputFile)...
|
||||
String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt-no -customC-pp -customLst -l -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt -no +split -customC-pp -customLst -l -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
|
||||
String.5.0=$(IntermPath)$(InputName).ls
|
||||
String.6.0=2010,3,6,17,19,51
|
||||
String.6.0=2010,5,27,22,48,49
|
||||
|
||||
[Root.Config.0.Settings.4]
|
||||
String.2.0=Assembling $(InputFile)...
|
||||
@@ -166,10 +166,10 @@ String.100.0=STM8S105C6
|
||||
|
||||
[Root.Config.1.Settings.3]
|
||||
String.2.0=Compiling $(InputFile)...
|
||||
String.3.0=cxstm8 +modsl0 -customC-pp -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.3.0=cxstm8 +modsl0 -customOpt +split -customC-pp -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
|
||||
String.5.0=$(IntermPath)$(InputName).ls
|
||||
String.6.0=2010,3,6,17,19,51
|
||||
String.6.0=2010,5,27,22,48,49
|
||||
|
||||
[Root.Config.1.Settings.4]
|
||||
String.2.0=Assembling $(InputFile)...
|
||||
@@ -189,7 +189,7 @@ String.3.0=clnk $(ToolsetLibOpts) -o $(OutputPath)$(TargetSName).sm8 -fakeIntege
|
||||
String.3.1=cvdwarf $(OutputPath)$(TargetSName).sm8
|
||||
String.4.0=$(OutputPath)$(TargetFName)
|
||||
String.5.0=$(OutputPath)$(ProjectSFile).elf
|
||||
String.6.0=2010,3,9,0,24,9
|
||||
String.6.0=2010,5,27,22,49,45
|
||||
String.100.0=
|
||||
String.101.0=crtsi.st7
|
||||
String.102.0=+seg .const -b 0x8080 -m 0x7f80 -n .const -it
|
||||
@@ -206,7 +206,7 @@ String.103.1=Eeprom[0x4000-0x43ff]=.eeprom
|
||||
String.103.2=Zero Page[0x2-0xff]=.bsct,.ubsct,.bit,.share
|
||||
String.103.3=Ram[0x100-0x7bf]=.data,.bss
|
||||
String.104.0=0x7ff
|
||||
String.105.0=libis0.sm8;libm0.sm8
|
||||
String.105.0=libisl0.sm8;libm0.sm8
|
||||
Int.0=0
|
||||
Int.1=0
|
||||
|
||||
@@ -247,10 +247,10 @@ Int.1=0
|
||||
|
||||
[Root.Kernel.Config.0.Settings.1]
|
||||
String.2.0=Compiling $(InputFile)...
|
||||
String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt-no -customC-pp -customLst -l -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt -no +split -customC-pp -customLst -l -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
|
||||
String.5.0=$(IntermPath)$(InputName).ls
|
||||
String.6.0=2010,3,6,17,19,51
|
||||
String.6.0=2010,5,27,22,48,49
|
||||
|
||||
[Root.Kernel.Config.0.Settings.2]
|
||||
String.2.0=Assembling $(InputFile)...
|
||||
@@ -271,10 +271,10 @@ Int.1=0
|
||||
|
||||
[Root.Kernel.Config.1.Settings.1]
|
||||
String.2.0=Compiling $(InputFile)...
|
||||
String.3.0=cxstm8 +modsl0 -customC-pp -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.3.0=cxstm8 +modsl0 -customOpt +split -customC-pp -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
|
||||
String.5.0=$(IntermPath)$(InputName).ls
|
||||
String.6.0=2010,3,6,17,19,51
|
||||
String.6.0=2010,5,27,22,48,49
|
||||
|
||||
[Root.Kernel.Config.1.Settings.2]
|
||||
String.2.0=Assembling $(InputFile)...
|
||||
@@ -364,10 +364,10 @@ Int.1=0
|
||||
|
||||
[Root.Peripherals.Config.0.Settings.1]
|
||||
String.2.0=Compiling $(InputFile)...
|
||||
String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt-no -customC-pp -customLst -l -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt -no +split -customC-pp -customLst -l -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
|
||||
String.5.0=$(IntermPath)$(InputName).ls
|
||||
String.6.0=2010,3,6,17,19,51
|
||||
String.6.0=2010,5,27,22,48,49
|
||||
|
||||
[Root.Peripherals.Config.0.Settings.2]
|
||||
String.2.0=Assembling $(InputFile)...
|
||||
@@ -391,10 +391,10 @@ Int.1=0
|
||||
|
||||
[Root.Peripherals.Config.1.Settings.1]
|
||||
String.2.0=Compiling $(InputFile)...
|
||||
String.3.0=cxstm8 +modsl0 -customC-pp -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.3.0=cxstm8 +modsl0 -customOpt +split -customC-pp -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
|
||||
String.5.0=$(IntermPath)$(InputName).ls
|
||||
String.6.0=2010,3,6,17,19,51
|
||||
String.6.0=2010,5,27,22,48,49
|
||||
|
||||
[Root.Peripherals.Config.1.Settings.2]
|
||||
String.2.0=Assembling $(InputFile)...
|
||||
@@ -491,10 +491,10 @@ Int.1=0
|
||||
|
||||
[Root.Port.Config.0.Settings.1]
|
||||
String.2.0=Compiling $(InputFile)...
|
||||
String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt-no -customC-pp -customLst -l -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt -no +split -customC-pp -customLst -l -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
|
||||
String.5.0=$(IntermPath)$(InputName).ls
|
||||
String.6.0=2010,3,6,17,19,51
|
||||
String.6.0=2010,5,27,22,48,49
|
||||
|
||||
[Root.Port.Config.0.Settings.2]
|
||||
String.2.0=Assembling $(InputFile)...
|
||||
@@ -518,10 +518,10 @@ Int.1=0
|
||||
|
||||
[Root.Port.Config.1.Settings.1]
|
||||
String.2.0=Compiling $(InputFile)...
|
||||
String.3.0=cxstm8 +modsl0 -customC-pp -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.3.0=cxstm8 +modsl0 -customOpt +split -customC-pp -dSTM8S105 -dATOM_STACK_CHECKING -istm8s-periphs -i../../kernel -i../../tests $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
|
||||
String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
|
||||
String.5.0=$(IntermPath)$(InputName).ls
|
||||
String.6.0=2010,3,6,17,19,51
|
||||
String.6.0=2010,5,27,22,48,49
|
||||
|
||||
[Root.Port.Config.1.Settings.2]
|
||||
String.2.0=Assembling $(InputFile)...
|
||||
@@ -580,11 +580,11 @@ 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]
|
||||
@@ -4,9 +4,9 @@
|
||||
Keyword=ST7Workspace-V0.7
|
||||
|
||||
[Project0]
|
||||
Filename=atomthreads-sample.stp
|
||||
Filename=atomthreads-sample-cosmic.stp
|
||||
Dependencies=
|
||||
[Options]
|
||||
ActiveProject=atomthreads
|
||||
ActiveConfig=Debug
|
||||
ActiveConfig=Release
|
||||
AddSortedElements=0
|
||||
369
ports/stm8/atomthreads-sample-iar.ewd
Normal file
369
ports/stm8/atomthreads-sample-iar.ewd
Normal 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>
|
||||
|
||||
|
||||
3132
ports/stm8/atomthreads-sample-iar.ewp
Normal file
3132
ports/stm8/atomthreads-sample-iar.ewp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
# Settings #
|
||||
############
|
||||
|
||||
# Set up build environment (using GNU Make)
|
||||
# set PATH=%PATH%;C:\Program Files\GNU_MAKE;C:\Program Files\COSMIC\CXSTM8_16K
|
||||
# set MAKE_MODE=DOS
|
||||
|
||||
# Build all test applications:
|
||||
# make
|
||||
# make -f cosmic.mak
|
||||
|
||||
|
||||
# Location of build tools and atomthreads sources
|
||||
KERNEL_DIR=../../kernel
|
||||
@@ -14,17 +19,19 @@ CC=cxstm8
|
||||
ASM=castm8
|
||||
LINK=clnk
|
||||
CHEX=chex
|
||||
|
||||
# CPU part number
|
||||
PART=STM8S105
|
||||
|
||||
# Enable stack-checking
|
||||
STACK_CHECK=true
|
||||
|
||||
# Directory for built objects
|
||||
BUILD_DIR=build
|
||||
BUILD_DIR=build-cosmic
|
||||
|
||||
# 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
|
||||
@@ -49,8 +56,8 @@ vpath %.elf .\$(BUILD_DIR)
|
||||
vpath %.hex .\$(BUILD_DIR)
|
||||
|
||||
# Compiler/Assembler flags
|
||||
CFLAGS=+modsl0 -pp -d$(PART)
|
||||
DBG_CFLAGS=+modsl0 +debug -pxp -no -pp -l -d$(PART)
|
||||
CFLAGS=+modsl0 +split -pp -d$(PART)
|
||||
DBG_CFLAGS=+modsl0 +split +debug -pxp -no -pp -l -d$(PART)
|
||||
ASMFLAGS=
|
||||
DBG_ASMFLAGS=-xx -u
|
||||
|
||||
@@ -66,7 +73,7 @@ endif
|
||||
#################
|
||||
|
||||
# All tests
|
||||
all: $(BUILD_DIR) $(TEST_S19S) Makefile
|
||||
all: $(BUILD_DIR) $(TEST_S19S) cosmic.mak
|
||||
|
||||
# Make build/output directory
|
||||
$(BUILD_DIR):
|
||||
@@ -79,7 +86,7 @@ $(TEST_S19S): %.s19: %.stm8
|
||||
|
||||
# Test ELF files (one application build for each test)
|
||||
$(TEST_STM8S): %.stm8: %.o $(KERNEL_OBJECTS) $(PERIPH_OBJECTS) $(APP_OBJECTS) $(APP_ASM_OBJECTS)
|
||||
$(LINK) -l$(LIBS_DIR) -o $(BUILD_DIR)/$@ atomthreads.lkf $(BUILD_DIR)/$(notdir $<)
|
||||
$(LINK) -l$(LIBS_DIR) -o $(BUILD_DIR)/$@ -m $(BUILD_DIR)/$(basename $@).map atomthreads.lkf $(BUILD_DIR)/$(notdir $<)
|
||||
|
||||
# Kernel objects builder
|
||||
$(KERNEL_OBJECTS): %.o: $(KERNEL_DIR)/%.c
|
||||
@@ -106,7 +113,7 @@ clean:
|
||||
rm -f *.o *.elf *.map *.hex *.bin *.lst *.stm8 *.s19
|
||||
rm -rf doxygen-kernel
|
||||
rm -rf doxygen-stm8
|
||||
rm -rf build
|
||||
rm -rf build-cosmic
|
||||
|
||||
doxygen:
|
||||
doxygen $(KERNEL_DIR)/Doxyfile
|
||||
137
ports/stm8/iar.mak
Normal file
137
ports/stm8/iar.mak
Normal file
@@ -0,0 +1,137 @@
|
||||
############
|
||||
# Settings #
|
||||
############
|
||||
|
||||
# Set up build environment (using GNU Make)
|
||||
# set PATH=%PATH%;C:\Program Files\GNU_MAKE;C:\Program Files\IAR Systems\Embedded Workbench 6.0\stm8\bin
|
||||
# set MAKE_MODE=DOS
|
||||
|
||||
# Build all test applications:
|
||||
# make -f iar.mak
|
||||
|
||||
|
||||
# Location of build tools and atomthreads sources
|
||||
EWSTM8_DIR=C:\Program Files\IAR Systems\Embedded Workbench 6.0\stm8
|
||||
KERNEL_DIR=../../kernel
|
||||
TESTS_DIR=../../tests
|
||||
PERIPHS_DIR=stm8s-periphs
|
||||
CC=iccstm8
|
||||
ASM=iasmstm8
|
||||
LINK=ilinkstm8
|
||||
HEX=ielftool
|
||||
|
||||
# CPU part number
|
||||
PART=STM8S105
|
||||
|
||||
# Enable stack-checking
|
||||
STACK_CHECK=true
|
||||
|
||||
# Directory for built objects
|
||||
BUILD_DIR=build-iar
|
||||
|
||||
# Port/application object files
|
||||
APP_OBJECTS = atomport.o tests-main.o uart.o
|
||||
APP_ASM_OBJECTS = atomport-asm-iar.o
|
||||
|
||||
# STM8S Peripheral driver object files
|
||||
PERIPH_OBJECTS = stm8s_gpio.o stm8s_tim1.o stm8s_clk.o stm8s_uart2.o
|
||||
|
||||
# Kernel object files
|
||||
KERNEL_OBJECTS = atomkernel.o atomsem.o atommutex.o atomtimer.o atomqueue.o
|
||||
|
||||
# Collection of built objects (excluding test applications)
|
||||
ALL_OBJECTS = $(APP_OBJECTS) $(APP_ASM_OBJECTS) $(PERIPH_OBJECTS) $(KERNEL_OBJECTS)
|
||||
BUILT_OBJECTS = $(patsubst %,$(BUILD_DIR)/%,$(ALL_OBJECTS))
|
||||
|
||||
# Test object files (dealt with separately as only one per application build)
|
||||
TEST_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(TESTS_DIR)/*.c)))
|
||||
|
||||
# Target application filenames (.elf) for each test object
|
||||
TEST_ELFS = $(patsubst %.o,%.elf,$(TEST_OBJECTS))
|
||||
TEST_S19S = $(patsubst %.o,%.s19,$(TEST_OBJECTS))
|
||||
|
||||
# Search build/output directory for dependencies
|
||||
vpath %.o .\$(BUILD_DIR)
|
||||
vpath %.elf .\$(BUILD_DIR)
|
||||
vpath %.hex .\$(BUILD_DIR)
|
||||
|
||||
# Compiler/Assembler flags
|
||||
CFLAGS=-e -Oh --code_model small --data_model medium \
|
||||
--dlib_config "$(EWSTM8_DIR)\lib\dlstm8smn.h" -D NDEBUG -D $(PART) \
|
||||
--diag_suppress Pa050
|
||||
DBG_CFLAGS=-e -Ol --no_cse --no_unroll --no_inline --no_code_motion --no_tbaa \
|
||||
--no_cross_call --debug --code_model small --data_model medium \
|
||||
--dlib_config "$(EWSTM8_DIR)\lib\dlstm8smn.h" -D $(PART) \
|
||||
--diag_suppress Pa050
|
||||
|
||||
ASMFLAGS=-M'<>' -ld $(BUILD_DIR)\list --diag_suppress Pa050 --code_model small \
|
||||
--data_model medium
|
||||
DBG_ASMFLAGS=-M'<>' -r -ld $(BUILD_DIR)\list --diag_suppress Pa050 --code_model small \
|
||||
--data_model medium
|
||||
|
||||
LINKFLAGS=--redirect _Printf=_PrintfSmall --redirect _Scanf=_ScanfSmall \
|
||||
--config "$(EWSTM8_DIR)\config\lnkstm8s105c6.icf" --config_def \
|
||||
_CSTACK_SIZE=0x100 --config_def _HEAP_SIZE=0x100 \
|
||||
--entry __iar_program_start
|
||||
DBG_LINKFLAGS=--redirect _Printf=_PrintfSmall --redirect _Scanf=_ScanfSmall \
|
||||
--config "$(EWSTM8_DIR)\config\lnkstm8s105c6.icf" --config_def \
|
||||
_CSTACK_SIZE=0x100 --config_def _HEAP_SIZE=0x100 \
|
||||
--entry __iar_program_start
|
||||
|
||||
# Enable stack-checking (disable if not required)
|
||||
ifeq ($(STACK_CHECK),true)
|
||||
CFLAGS += -D ATOM_STACK_CHECKING
|
||||
DBG_CFLAGS += -D ATOM_STACK_CHECKING
|
||||
endif
|
||||
|
||||
|
||||
#################
|
||||
# Build targets #
|
||||
#################
|
||||
|
||||
# All tests
|
||||
all: $(BUILD_DIR) $(TEST_S19S) iar.mak
|
||||
|
||||
# Make build/output directory
|
||||
$(BUILD_DIR):
|
||||
mkdir $(BUILD_DIR)
|
||||
|
||||
# Test HEX files (one application build for each test)
|
||||
$(TEST_S19S): %.s19: %.elf
|
||||
@echo Building $@
|
||||
$(HEX) $(BUILD_DIR)/$(notdir $<) $(BUILD_DIR)/$@ --srec
|
||||
|
||||
# Test ELF files (one application build for each test)
|
||||
$(TEST_ELFS): %.elf: %.o $(KERNEL_OBJECTS) $(PERIPH_OBJECTS) $(APP_OBJECTS) $(APP_ASM_OBJECTS)
|
||||
$(LINK) $(BUILD_DIR)/$(notdir $<) $(BUILT_OBJECTS) $(LINKFLAGS) -o $(BUILD_DIR)/$@
|
||||
|
||||
# Kernel objects builder
|
||||
$(KERNEL_OBJECTS): %.o: $(KERNEL_DIR)/%.c
|
||||
$(CC) $< $(CFLAGS) -I . -I $(PERIPHS_DIR) -o $(BUILD_DIR)
|
||||
|
||||
# Test objects builder
|
||||
$(TEST_OBJECTS): %.o: $(TESTS_DIR)/%.c
|
||||
$(CC) $< $(CFLAGS) -I . -I $(KERNEL_DIR) -I $(PERIPHS_DIR) -o $(BUILD_DIR)
|
||||
|
||||
# Kernel objects builder
|
||||
$(PERIPH_OBJECTS): %.o: $(PERIPHS_DIR)/%.c
|
||||
$(CC) $< $(CFLAGS) -I . -I $(PERIPHS_DIR) -o $(BUILD_DIR)
|
||||
|
||||
# Application C objects builder
|
||||
$(APP_OBJECTS): %.o: ./%.c
|
||||
$(CC) $< $(CFLAGS) -I $(KERNEL_DIR) -I $(TESTS_DIR) -I $(PERIPHS_DIR) -o $(BUILD_DIR)
|
||||
|
||||
# Application asm objects builder
|
||||
$(APP_ASM_OBJECTS): %.o: ./%.s
|
||||
$(ASM) $< $(ASMFLAGS) -I $(KERNEL_DIR) -o $(BUILD_DIR)/$(notdir $@)
|
||||
|
||||
# Clean
|
||||
clean:
|
||||
rm -f *.o *.elf *.map *.hex *.bin *.lst *.stm8 *.s19 *.out
|
||||
rm -rf doxygen-kernel
|
||||
rm -rf doxygen-stm8
|
||||
rm -rf build-iar
|
||||
|
||||
doxygen:
|
||||
doxygen $(KERNEL_DIR)/Doxyfile
|
||||
doxygen ./Doxyfile
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -49,549 +49,6 @@ uc8 CLKPrescTable[8] = {1, 2, 4, 8, 10, 16, 20, 40}; /*!< Holds the different CL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Deinitializes the CLK peripheral registers to their default reset
|
||||
* values.
|
||||
* @par Parameters:
|
||||
* None
|
||||
* @retval None
|
||||
* @par Warning:
|
||||
* Resetting the CCOR register: \n
|
||||
* When the CCOEN bit is set, the reset of the CCOR register require
|
||||
* two consecutive write instructions in order to reset first the CCOEN bit
|
||||
* and the second one is to reset the CCOSEL bits.
|
||||
*/
|
||||
void CLK_DeInit(void)
|
||||
{
|
||||
|
||||
CLK->ICKR = CLK_ICKR_RESET_VALUE;
|
||||
CLK->ECKR = CLK_ECKR_RESET_VALUE;
|
||||
CLK->SWR = CLK_SWR_RESET_VALUE;
|
||||
CLK->SWCR = CLK_SWCR_RESET_VALUE;
|
||||
CLK->CKDIVR = CLK_CKDIVR_RESET_VALUE;
|
||||
CLK->PCKENR1 = CLK_PCKENR1_RESET_VALUE;
|
||||
CLK->PCKENR2 = CLK_PCKENR2_RESET_VALUE;
|
||||
CLK->CSSR = CLK_CSSR_RESET_VALUE;
|
||||
CLK->CCOR = CLK_CCOR_RESET_VALUE;
|
||||
while (CLK->CCOR & CLK_CCOR_CCOEN)
|
||||
{}
|
||||
CLK->CCOR = CLK_CCOR_RESET_VALUE;
|
||||
CLK->CANCCR = CLK_CANCCR_RESET_VALUE;
|
||||
CLK->HSITRIMR = CLK_HSITRIMR_RESET_VALUE;
|
||||
CLK->SWIMCCR = CLK_SWIMCCR_RESET_VALUE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the High Speed Internal oscillator (HSI).
|
||||
* @par Full description:
|
||||
* If CLK_FastHaltWakeup is enabled, HSI oscillator is automatically
|
||||
* switched-on (HSIEN=1) and selected as next clock master
|
||||
* (CKM=SWI=HSI) when resuming from HALT/ActiveHalt modes.\n
|
||||
* @param[in] NewState this parameter is the Wake-up Mode state.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_FastHaltWakeUpCmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Set FHWU bit (HSI oscillator is automatically switched-on) */
|
||||
CLK->ICKR |= CLK_ICKR_FHWU;
|
||||
}
|
||||
else /* FastHaltWakeup = DISABLE */
|
||||
{
|
||||
/* Reset FHWU bit */
|
||||
CLK->ICKR &= (u8)(~CLK_ICKR_FHWU);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or Disable the External High Speed oscillator (HSE).
|
||||
* @param[in] NewState new state of HSEEN, value accepted ENABLE, DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_HSECmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Set HSEEN bit */
|
||||
CLK->ECKR |= CLK_ECKR_HSEEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset HSEEN bit */
|
||||
CLK->ECKR &= (u8)(~CLK_ECKR_HSEEN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the Internal High Speed oscillator (HSI).
|
||||
* @param[in] NewState new state of HSIEN, value accepted ENABLE, DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_HSICmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Set HSIEN bit */
|
||||
CLK->ICKR |= CLK_ICKR_HSIEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset HSIEN bit */
|
||||
CLK->ICKR &= (u8)(~CLK_ICKR_HSIEN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the Internal Low Speed oscillator (LSI).
|
||||
* @param[in] NewState new state of LSIEN, value accepted ENABLE, DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_LSICmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Set LSIEN bit */
|
||||
CLK->ICKR |= CLK_ICKR_LSIEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset LSIEN bit */
|
||||
CLK->ICKR &= (u8)(~CLK_ICKR_LSIEN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disablle the Configurable Clock Output (CCO).
|
||||
* @param[in] NewState : New state of CCEN bit (CCO register).
|
||||
* This parameter can be any of the @ref FunctionalState enumeration.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_CCOCmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Set CCOEN bit */
|
||||
CLK->CCOR |= CLK_CCOR_CCOEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset CCOEN bit */
|
||||
CLK->CCOR &= (u8)(~CLK_CCOR_CCOEN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts or Stops manually the clock switch execution.
|
||||
* @par Full description:
|
||||
* NewState parameter set the SWEN.
|
||||
* @param[in] NewState new state of SWEN, value accepted ENABLE, DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_ClockSwitchCmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE )
|
||||
{
|
||||
/* Enable the Clock Switch */
|
||||
CLK->SWCR |= CLK_SWCR_SWEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the Clock Switch */
|
||||
CLK->SWCR &= (u8)(~CLK_SWCR_SWEN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the slow active halt wake up
|
||||
* @param[in] NewState: specifies the Slow Active Halt wake up state.
|
||||
* can be set of the following values:
|
||||
* - DISABLE: Slow Active Halt mode disabled;
|
||||
* - ENABLE: Slow Active Halt mode enabled.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_SlowActiveHaltWakeUpCmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Set S_ACTHALT bit */
|
||||
CLK->ICKR |= CLK_ICKR_SWUAH;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset S_ACTHALT bit */
|
||||
CLK->ICKR &= (u8)(~CLK_ICKR_SWUAH);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the specified peripheral CLK.
|
||||
* @param[in] CLK_Peripheral : This parameter specifies the peripheral clock to gate.
|
||||
* This parameter can be any of the @ref CLK_Peripheral_TypeDef enumeration.
|
||||
* @param[in] NewState : New state of specified peripheral clock.
|
||||
* This parameter can be any of the @ref FunctionalState enumeration.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_PeripheralClockConfig(CLK_Peripheral_TypeDef CLK_Peripheral, FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
assert_param(IS_CLK_PERIPHERAL_OK(CLK_Peripheral));
|
||||
|
||||
if (((u8)CLK_Peripheral & (u8)0x10) == 0x00)
|
||||
{
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Enable the peripheral Clock */
|
||||
CLK->PCKENR1 |= (u8)((u8)1 << ((u8)CLK_Peripheral & (u8)0x0F));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the peripheral Clock */
|
||||
CLK->PCKENR1 &= (u8)(~(u8)(((u8)1 << ((u8)CLK_Peripheral & (u8)0x0F))));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Enable the peripheral Clock */
|
||||
CLK->PCKENR2 |= (u8)((u8)1 << ((u8)CLK_Peripheral & (u8)0x0F));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the peripheral Clock */
|
||||
CLK->PCKENR2 &= (u8)(~(u8)(((u8)1 << ((u8)CLK_Peripheral & (u8)0x0F))));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configures the Switch from one clock to another
|
||||
* @param[in] CLK_SwitchMode select the clock switch mode.
|
||||
* It can be set of the values of @ref CLK_SwitchMode_TypeDef
|
||||
* @param[in] CLK_NewClock choice of the future clock.
|
||||
* It can be set of the values of @ref CLK_Source_TypeDef
|
||||
* @param[in] NewState Enable or Disable the Clock Switch interrupt.
|
||||
* @param[in] CLK_CurrentClockState current clock to switch OFF or to keep ON.
|
||||
* It can be set of the values of @ref CLK_CurrentClockState_TypeDef
|
||||
* @retval ErrorStatus this shows the clock switch status (ERROR/SUCCESS).
|
||||
*/
|
||||
ErrorStatus CLK_ClockSwitchConfig(CLK_SwitchMode_TypeDef CLK_SwitchMode, CLK_Source_TypeDef CLK_NewClock, FunctionalState ITState, CLK_CurrentClockState_TypeDef CLK_CurrentClockState)
|
||||
{
|
||||
|
||||
CLK_Source_TypeDef clock_master;
|
||||
u16 DownCounter = CLK_TIMEOUT;
|
||||
ErrorStatus Swif = ERROR;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CLK_SOURCE_OK(CLK_NewClock));
|
||||
assert_param(IS_CLK_SWITCHMODE_OK(CLK_SwitchMode));
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(ITState));
|
||||
assert_param(IS_CLK_CURRENTCLOCKSTATE_OK(CLK_CurrentClockState));
|
||||
|
||||
/* Current clock master saving */
|
||||
clock_master = (CLK_Source_TypeDef)CLK->CMSR;
|
||||
|
||||
/* Automatic switch mode management */
|
||||
if (CLK_SwitchMode == CLK_SWITCHMODE_AUTO)
|
||||
{
|
||||
|
||||
/* Enables Clock switch */
|
||||
CLK->SWCR |= CLK_SWCR_SWEN;
|
||||
|
||||
/* Enables or Disables Switch interrupt */
|
||||
if (ITState != DISABLE)
|
||||
{
|
||||
CLK->SWCR |= CLK_SWCR_SWIEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLK->SWCR &= (u8)(~CLK_SWCR_SWIEN);
|
||||
}
|
||||
|
||||
/* Selection of the target clock source */
|
||||
CLK->SWR = (u8)CLK_NewClock;
|
||||
|
||||
while (((CLK->SWCR & CLK_SWCR_SWBSY) && (DownCounter != 0)))
|
||||
{
|
||||
DownCounter--;
|
||||
}
|
||||
|
||||
if (DownCounter != 0)
|
||||
{
|
||||
Swif = SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Swif = ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
else /* CLK_SwitchMode == CLK_SWITCHMODE_MANUAL */
|
||||
{
|
||||
|
||||
/* Enables or Disables Switch interrupt if required */
|
||||
if (ITState != DISABLE)
|
||||
{
|
||||
CLK->SWCR |= CLK_SWCR_SWIEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLK->SWCR &= (u8)(~CLK_SWCR_SWIEN);
|
||||
}
|
||||
|
||||
/* Selection of the target clock source */
|
||||
CLK->SWR = (u8)CLK_NewClock;
|
||||
|
||||
/* In manual mode, there is no risk to be stucked in a loop, value returned
|
||||
is then always SUCCESS */
|
||||
Swif = SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* Switch OFF current clock if required */
|
||||
if ((CLK_CurrentClockState == CLK_CURRENTCLOCKSTATE_DISABLE) && ( clock_master == CLK_SOURCE_HSI))
|
||||
{
|
||||
CLK->ICKR &= (u8)(~CLK_ICKR_HSIEN);
|
||||
}
|
||||
else if ((CLK_CurrentClockState == CLK_CURRENTCLOCKSTATE_DISABLE) && ( clock_master == CLK_SOURCE_LSI))
|
||||
{
|
||||
CLK->ICKR &= (u8)(~CLK_ICKR_LSIEN);
|
||||
}
|
||||
else if ((CLK_CurrentClockState == CLK_CURRENTCLOCKSTATE_DISABLE) && ( clock_master == CLK_SOURCE_HSE))
|
||||
{
|
||||
CLK->ECKR &= (u8)(~CLK_ECKR_HSEEN);
|
||||
}
|
||||
|
||||
return(Swif);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the HSI clock dividers.
|
||||
* @param[in] HSIPrescaler : Specifies the HSI clock divider to apply.
|
||||
* This parameter can be any of the @ref CLK_Prescaler_TypeDef enumeration.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_HSIPrescalerConfig(CLK_Prescaler_TypeDef HSIPrescaler)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_HSIPRESCALER_OK(HSIPrescaler));
|
||||
|
||||
/* Clear High speed internal clock prescaler */
|
||||
CLK->CKDIVR &= (u8)(~CLK_CKDIVR_HSIDIV);
|
||||
|
||||
/* Set High speed internal clock prescaler */
|
||||
CLK->CKDIVR |= (u8)HSIPrescaler;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Output the selected clock on a dedicated I/O pin.
|
||||
* @param[in] CLK_CCO : Specifies the clock source.
|
||||
* This parameter can be any of the @ref CLK_Output_TypeDef enumeration.
|
||||
* @retval None
|
||||
* @par Required preconditions:
|
||||
* The dedicated I/O pin must be set at 1 in the corresponding Px_CR1 register \n
|
||||
* to be set as input with pull-up or push-pull output.
|
||||
*/
|
||||
void CLK_CCOConfig(CLK_Output_TypeDef CLK_CCO)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_OUTPUT_OK(CLK_CCO));
|
||||
|
||||
/* Clears of the CCO type bits part */
|
||||
CLK->CCOR &= (u8)(~CLK_CCOR_CCOSEL);
|
||||
|
||||
/* Selects the source provided on cco_ck output */
|
||||
CLK->CCOR |= (u8)CLK_CCO;
|
||||
|
||||
/* Enable the clock output */
|
||||
CLK->CCOR |= CLK_CCOR_CCOEN;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the specified CLK interrupts.
|
||||
* @param[in] CLK_IT This parameter specifies the interrupt sources.
|
||||
* It can be one of the values of @ref CLK_IT_TypeDef.
|
||||
* @param[in] NewState New state of the Interrupt.
|
||||
* Value accepted ENABLE, DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_ITConfig(CLK_IT_TypeDef CLK_IT, FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
assert_param(IS_CLK_IT_OK(CLK_IT));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
switch (CLK_IT)
|
||||
{
|
||||
case CLK_IT_SWIF: /* Enable the clock switch interrupt */
|
||||
CLK->SWCR |= CLK_SWCR_SWIEN;
|
||||
break;
|
||||
case CLK_IT_CSSD: /* Enable the clock security system detection interrupt */
|
||||
CLK->CSSR |= CLK_CSSR_CSSDIE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /*(NewState == DISABLE)*/
|
||||
{
|
||||
switch (CLK_IT)
|
||||
{
|
||||
case CLK_IT_SWIF: /* Disable the clock switch interrupt */
|
||||
CLK->SWCR &= (u8)(~CLK_SWCR_SWIEN);
|
||||
break;
|
||||
case CLK_IT_CSSD: /* Disable the clock security system detection interrupt */
|
||||
CLK->CSSR &= (u8)(~CLK_CSSR_CSSDIE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the HSI and CPU clock dividers.
|
||||
* @param[in] ClockPrescaler Specifies the HSI or CPU clock divider to apply.
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_SYSCLKConfig(CLK_Prescaler_TypeDef ClockPrescaler)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_PRESCALER_OK(ClockPrescaler));
|
||||
|
||||
if (((u8)ClockPrescaler & (u8)0x80) == 0x00) /* Bit7 = 0 means HSI divider */
|
||||
{
|
||||
CLK->CKDIVR &= (u8)(~CLK_CKDIVR_HSIDIV);
|
||||
CLK->CKDIVR |= (u8)((u8)ClockPrescaler & (u8)CLK_CKDIVR_HSIDIV);
|
||||
}
|
||||
else /* Bit7 = 1 means CPU divider */
|
||||
{
|
||||
CLK->CKDIVR &= (u8)(~CLK_CKDIVR_CPUDIV);
|
||||
CLK->CKDIVR |= (u8)((u8)ClockPrescaler & (u8)CLK_CKDIVR_CPUDIV);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Configures the SWIM clock frequency on the fly.
|
||||
* @param[in] CLK_SWIMDivider Specifies the SWIM clock divider to apply.
|
||||
* can be one of the value of @ref CLK_SWIMDivider_TypeDef
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_SWIMConfig(CLK_SWIMDivider_TypeDef CLK_SWIMDivider)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_SWIMDIVIDER_OK(CLK_SWIMDivider));
|
||||
|
||||
if (CLK_SWIMDivider != CLK_SWIMDIVIDER_2)
|
||||
{
|
||||
/* SWIM clock is not divided by 2 */
|
||||
CLK->SWIMCCR |= CLK_SWIMCCR_SWIMDIV;
|
||||
}
|
||||
else /* CLK_SWIMDivider == CLK_SWIMDIVIDER_2 */
|
||||
{
|
||||
/* SWIM clock is divided by 2 */
|
||||
CLK->SWIMCCR &= (u8)(~CLK_SWIMCCR_SWIMDIV);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the divider for the external CAN clock.
|
||||
* @param[in] CLK_CANDivider Specifies the CAN clock divider to apply.
|
||||
* can be one of the value of @ref CLK_CANDivider_TypeDef
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_CANConfig(CLK_CANDivider_TypeDef CLK_CANDivider)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_CANDIVIDER_OK(CLK_CANDivider));
|
||||
|
||||
/* Clear the CANDIV bits */
|
||||
CLK->CANCCR &= (u8)(~CLK_CANCCR_CANDIV);
|
||||
|
||||
/* Select divider */
|
||||
CLK->CANCCR |= (u8)CLK_CANDivider;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the Clock Security System.
|
||||
* @par Full description:
|
||||
* once CSS is enabled it cannot be disabled until the next reset.
|
||||
* @par Parameters:
|
||||
* None
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_ClockSecuritySystemEnable(void)
|
||||
{
|
||||
/* Set CSSEN bit */
|
||||
CLK->CSSR |= CLK_CSSR_CSSEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the clock source used as system clock.
|
||||
* @par Parameters:
|
||||
* None
|
||||
* @retval Clock source used.
|
||||
* can be one of the values of @ref CLK_Source_TypeDef
|
||||
*/
|
||||
CLK_Source_TypeDef CLK_GetSYSCLKSource(void)
|
||||
{
|
||||
return((CLK_Source_TypeDef)CLK->CMSR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function returns the frequencies of different on chip clocks.
|
||||
@@ -628,164 +85,8 @@ u32 CLK_GetClockFreq(void)
|
||||
return((u32)clockfrequency);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adjusts the Internal High Speed oscillator (HSI) calibration value.
|
||||
* @par Full description:
|
||||
* @param[in] CLK_HSICalibrationValue calibration trimming value.
|
||||
* can be one of the values of @ref CLK_HSITrimValue_TypeDef
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_AdjustHSICalibrationValue(CLK_HSITrimValue_TypeDef CLK_HSICalibrationValue)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_HSITRIMVALUE_OK(CLK_HSICalibrationValue));
|
||||
|
||||
/* Store the new value */
|
||||
CLK->HSITRIMR = (u8)((CLK->HSITRIMR & (u8)(~CLK_HSITRIMR_HSITRIM))|((u8)CLK_HSICalibrationValue));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the SWBSY flag (SWICR Reister)
|
||||
* @par Full description:
|
||||
* This function reset SWBSY flag in order to reset clock switch operations (target
|
||||
* oscillator is broken, stabilization is longing too much, etc.). If at the same time \n
|
||||
* software attempts to set SWEN and clear SWBSY, SWBSY action takes precedence.
|
||||
* @par Parameters:
|
||||
* None
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_SYSCLKEmergencyClear(void)
|
||||
{
|
||||
CLK->SWCR &= (u8)(~CLK_SWCR_SWBSY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether the specified CLK flag is set or not.
|
||||
* @par Full description:
|
||||
* @param[in] CLK_FLAG Flag to check.
|
||||
* can be one of the values of @ref CLK_Flag_TypeDef
|
||||
* @retval FlagStatus, status of the checked flag
|
||||
*/
|
||||
FlagStatus CLK_GetFlagStatus(CLK_Flag_TypeDef CLK_FLAG)
|
||||
{
|
||||
|
||||
u16 statusreg = 0;
|
||||
u8 tmpreg = 0;
|
||||
FlagStatus bitstatus = RESET;
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_FLAG_OK(CLK_FLAG));
|
||||
|
||||
/* Get the CLK register index */
|
||||
statusreg = (u16)((u16)CLK_FLAG & (u16)0xFF00);
|
||||
|
||||
|
||||
if (statusreg == 0x0100) /* The flag to check is in ICKRregister */
|
||||
{
|
||||
tmpreg = CLK->ICKR;
|
||||
}
|
||||
else if (statusreg == 0x0200) /* The flag to check is in ECKRregister */
|
||||
{
|
||||
tmpreg = CLK->ECKR;
|
||||
}
|
||||
else if (statusreg == 0x0300) /* The flag to check is in SWIC register */
|
||||
{
|
||||
tmpreg = CLK->SWCR;
|
||||
}
|
||||
else if (statusreg == 0x0400) /* The flag to check is in CSS register */
|
||||
{
|
||||
tmpreg = CLK->CSSR;
|
||||
}
|
||||
else /* The flag to check is in CCO register */
|
||||
{
|
||||
tmpreg = CLK->CCOR;
|
||||
}
|
||||
|
||||
if ((tmpreg & (u8)CLK_FLAG) != (u8)RESET)
|
||||
{
|
||||
bitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitstatus = RESET;
|
||||
}
|
||||
|
||||
/* Return the flag status */
|
||||
return((FlagStatus)bitstatus);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether the specified CLK interrupt has is enabled or not.
|
||||
* @param[in] CLK_IT specifies the CLK interrupt.
|
||||
* can be one of the values of @ref CLK_IT_TypeDef
|
||||
* @retval ITStatus, new state of CLK_IT (SET or RESET).
|
||||
*/
|
||||
ITStatus CLK_GetITStatus(CLK_IT_TypeDef CLK_IT)
|
||||
{
|
||||
|
||||
ITStatus bitstatus = RESET;
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_IT_OK(CLK_IT));
|
||||
|
||||
if (CLK_IT == CLK_IT_SWIF)
|
||||
{
|
||||
/* Check the status of the clock switch interrupt */
|
||||
if ((CLK->SWCR & (u8)CLK_IT) == (u8)0x0C)
|
||||
{
|
||||
bitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitstatus = RESET;
|
||||
}
|
||||
}
|
||||
else /* CLK_IT == CLK_IT_CSSDIE */
|
||||
{
|
||||
/* Check the status of the security system detection interrupt */
|
||||
if ((CLK->CSSR & (u8)CLK_IT) == (u8)0x0C)
|
||||
{
|
||||
bitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitstatus = RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the CLK_IT status */
|
||||
return bitstatus;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the CLK’s interrupt pending bits.
|
||||
* @param[in] CLK_IT specifies the interrupt pending bits.
|
||||
* can be one of the values of @ref CLK_IT_TypeDef
|
||||
* @retval None
|
||||
*/
|
||||
void CLK_ClearITPendingBit(CLK_IT_TypeDef CLK_IT)
|
||||
{
|
||||
|
||||
/* check the parameters */
|
||||
assert_param(IS_CLK_IT_OK(CLK_IT));
|
||||
|
||||
if (CLK_IT == (u8)CLK_IT_CSSD)
|
||||
{
|
||||
/* Clear the status of the security system detection interrupt */
|
||||
CLK->CSSR &= (u8)(~CLK_CSSR_CSSD);
|
||||
}
|
||||
else /* CLK_PendingBit == (u8)CLK_IT_SWIF */
|
||||
{
|
||||
/* Clear the status of the clock switch interrupt */
|
||||
CLK->SWCR &= (u8)(~CLK_SWCR_SWIF);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,335 +157,6 @@ void UART2_Init(u32 BaudRate, UART2_WordLength_TypeDef WordLength, UART2_StopBit
|
||||
UART2->CR3 |= (u8)((u8)SyncMode & UART2_CR3_CKEN);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Enable the UART2 peripheral.
|
||||
* @par Full description:
|
||||
* Enable the UART2 peripheral.
|
||||
* @param[in] NewState new state of the UART2 Communication.
|
||||
* This parameter can be:
|
||||
* - ENABLE
|
||||
* - DISABLE
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_Cmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
UART2->CR1 &= (u8)(~UART2_CR1_UARTD); /**< UART2 Enable */
|
||||
}
|
||||
else
|
||||
{
|
||||
UART2->CR1 |= UART2_CR1_UARTD; /**< UART2 Disable (for low power consumption) */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the specified UART2 interrupts.
|
||||
* @par Full description:
|
||||
* Enables or disables the specified UART2 interrupts.
|
||||
* @param[in] UART2_IT specifies the UART2 interrupt sources to be enabled or disabled.
|
||||
* This parameter can be one of the following values:
|
||||
* - UART2_IT_LBDF: LIN Break detection interrupt
|
||||
* - UART2_IT_LHDF: LIN Break detection interrupt
|
||||
* - UART2_IT_TXE: Tansmit Data Register empty interrupt
|
||||
* - UART2_IT_TC: Transmission complete interrupt
|
||||
* - UART2_IT_RXNE_OR: Receive Data register not empty/Over run error interrupt
|
||||
* - UART2_IT_IDLE: Idle line detection interrupt
|
||||
* - UART2_IT_PE: Parity Error interrupt
|
||||
* @param[in] NewState new state of the specified UART2 interrupts.
|
||||
* This parameter can be: ENABLE or DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_ITConfig(UART2_IT_TypeDef UART2_IT, FunctionalState NewState)
|
||||
{
|
||||
u8 uartreg, itpos = 0x00;
|
||||
assert_param(IS_UART2_CONFIG_IT_OK(UART2_IT));
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
/* Get the UART2 register index */
|
||||
uartreg = (u8)(UART2_IT >> 0x08);
|
||||
|
||||
/* Get the UART2 IT index */
|
||||
itpos = (u8)((u8)1 << (u8)((u8)UART2_IT & (u8)0x0F));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/**< Enable the Interrupt bits according to UART2_IT mask */
|
||||
if (uartreg == 0x01)
|
||||
{
|
||||
UART2->CR1 |= itpos;
|
||||
}
|
||||
else if (uartreg == 0x02)
|
||||
{
|
||||
UART2->CR2 |= itpos;
|
||||
}
|
||||
else if (uartreg == 0x03)
|
||||
{
|
||||
UART2->CR4 |= itpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
UART2->CR6 |= itpos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**< Disable the interrupt bits according to UART2_IT mask */
|
||||
if (uartreg == 0x01)
|
||||
{
|
||||
UART2->CR1 &= (u8)(~itpos);
|
||||
}
|
||||
else if (uartreg == 0x02)
|
||||
{
|
||||
UART2->CR2 &= (u8)(~itpos);
|
||||
}
|
||||
else if (uartreg == 0x03)
|
||||
{
|
||||
UART2->CR4 &= (u8)(~itpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
UART2->CR6 &= (u8)(~itpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Configures the UART2’s IrDA interface.
|
||||
* @par Full description:
|
||||
* Configures the UART2’s IrDA interface.
|
||||
* @par This function is valid only for UART2.
|
||||
* @param[in] UART2_IrDAMode specifies the IrDA mode.
|
||||
* This parameter can be any of the @ref UART2_IrDAMode_TypeDef values.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_IrDAConfig(UART2_IrDAMode_TypeDef UART2_IrDAMode)
|
||||
{
|
||||
assert_param(IS_UART2_IRDAMODE_OK(UART2_IrDAMode));
|
||||
|
||||
if (UART2_IrDAMode != UART2_IRDAMODE_NORMAL)
|
||||
{
|
||||
UART2->CR5 |= UART2_CR5_IRLP;
|
||||
}
|
||||
else
|
||||
{
|
||||
UART2->CR5 &= ((u8)~UART2_CR5_IRLP);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the UART2’s IrDA interface.
|
||||
* @par Full description:
|
||||
* Enables or disables the UART2’s IrDA interface.
|
||||
* @par This function is related to IrDA mode.
|
||||
* @param[in] NewState new state of the IrDA mode.
|
||||
* This parameter can be: ENABLE or DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_IrDACmd(FunctionalState NewState)
|
||||
{
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Enable the IrDA mode by setting the IREN bit in the CR3 register */
|
||||
UART2->CR5 |= UART2_CR5_IREN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the IrDA mode by clearing the IREN bit in the CR3 register */
|
||||
UART2->CR5 &= ((u8)~UART2_CR5_IREN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the UART2 LIN Break detection length.
|
||||
* @par Full description:
|
||||
* Sets the UART2 LIN Break detection length.
|
||||
* @param[in] UART2_LINBreakDetectionLength specifies the LIN break detection length.
|
||||
* This parameter can be any of the @ref UART2_LINBreakDetectionLength_TypeDef values.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_LINBreakDetectionConfig(UART2_LINBreakDetectionLength_TypeDef UART2_LINBreakDetectionLength)
|
||||
{
|
||||
assert_param(IS_UART2_LINBREAKDETECTIONLENGTH_OK(UART2_LINBreakDetectionLength));
|
||||
|
||||
if (UART2_LINBreakDetectionLength != UART2_LINBREAKDETECTIONLENGTH_10BITS)
|
||||
{
|
||||
UART2->CR4 |= UART2_CR4_LBDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
UART2->CR4 &= ((u8)~UART2_CR4_LBDL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configue the UART2 peripheral.
|
||||
* @par Full description:
|
||||
* Configue the UART2 peripheral.
|
||||
* @param[in] UART2_Mode specifies the LIN mode.
|
||||
* This parameter can be any of the @ref UART2_LinMode_TypeDef values.
|
||||
* @param[in] UART2_Autosync specifies the LIN automatic resynchronization mode.
|
||||
* This parameter can be any of the @ref UART2_LinAutosync_TypeDef values.
|
||||
* @param[in] UART2_DivUp specifies the LIN divider update method.
|
||||
* This parameter can be any of the @ref UART2_LinDivUp_TypeDef values.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_LINConfig(UART2_LinMode_TypeDef UART2_Mode, UART2_LinAutosync_TypeDef UART2_Autosync, UART2_LinDivUp_TypeDef UART2_DivUp)
|
||||
{
|
||||
assert_param(IS_UART2_SLAVE_OK(UART2_Mode));
|
||||
|
||||
assert_param(IS_UART2_AUTOSYNC_OK(UART2_Autosync));
|
||||
|
||||
assert_param(IS_UART2_DIVUP_OK(UART2_DivUp));
|
||||
|
||||
if (UART2_Mode != UART2_LIN_MODE_MASTER)
|
||||
{
|
||||
UART2->CR6 |= UART2_CR6_LSLV;
|
||||
}
|
||||
else
|
||||
{
|
||||
UART2->CR6 &= ((u8)~UART2_CR6_LSLV);
|
||||
}
|
||||
|
||||
if (UART2_Autosync != UART2_LIN_AUTOSYNC_DISABLE)
|
||||
{
|
||||
UART2->CR6 |= UART2_CR6_LASE ;
|
||||
}
|
||||
else
|
||||
{
|
||||
UART2->CR6 &= ((u8)~ UART2_CR6_LASE );
|
||||
}
|
||||
|
||||
if (UART2_DivUp != UART2_LIN_DIVUP_LBRR1)
|
||||
{
|
||||
UART2->CR6 |= UART2_CR6_LDUM;
|
||||
}
|
||||
else
|
||||
{
|
||||
UART2->CR6 &= ((u8)~ UART2_CR6_LDUM);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the UART2 LIN mode.
|
||||
* @par Full description:
|
||||
* Enables or disables the UART2’s LIN mode.
|
||||
* @param[in] NewState is new state of the UART2 LIN mode.
|
||||
* This parameter can be:
|
||||
* - ENABLE
|
||||
* - DISABLE
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_LINCmd(FunctionalState NewState)
|
||||
{
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Enable the LIN mode by setting the LINE bit in the CR2 register */
|
||||
UART2->CR3 |= UART2_CR3_LINEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the LIN mode by clearing the LINE bit in the CR2 register */
|
||||
UART2->CR3 &= ((u8)~UART2_CR3_LINEN);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Enables or disables the UART2 Smart Card mode.
|
||||
* @par Full description:
|
||||
* Enables or disables the UART2 Smart Card mode.
|
||||
* @par This function is related to SmartCard mode.
|
||||
* @param[in] NewState: new state of the Smart Card mode.
|
||||
* This parameter can be: ENABLE or DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_SmartCardCmd(FunctionalState NewState)
|
||||
{
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Enable the SC mode by setting the SCEN bit in the CR5 register */
|
||||
UART2->CR5 |= UART2_CR5_SCEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the SC mode by clearing the SCEN bit in the CR5 register */
|
||||
UART2->CR5 &= ((u8)(~UART2_CR5_SCEN));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables NACK transmission.
|
||||
* @par Full description:
|
||||
* Enables or disables NACK transmission.
|
||||
* @par This function is valid only for UART2 because is related to SmartCard mode.
|
||||
* @param[in] NewState: new state of the Smart Card mode.
|
||||
* This parameter can be: ENABLE or DISABLE.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_SmartCardNACKCmd(FunctionalState NewState)
|
||||
{
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Enable the NACK transmission by setting the NACK bit in the CR5 register */
|
||||
UART2->CR5 |= UART2_CR5_NACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the NACK transmission by clearing the NACK bit in the CR5 register */
|
||||
UART2->CR5 &= ((u8)~(UART2_CR5_NACK));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Selects the UART2 WakeUp method.
|
||||
* @par Full description:
|
||||
* Selects the UART2 WakeUp method.
|
||||
* @param[in] UART2_WakeUp: specifies the UART2 wakeup method.
|
||||
* This parameter can be any of the @ref UART2_WakeUp_TypeDef values.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_WakeUpConfig(UART2_WakeUp_TypeDef UART2_WakeUp)
|
||||
{
|
||||
assert_param(IS_UART2_WAKEUP_OK(UART2_WakeUp));
|
||||
|
||||
UART2->CR1 &= ((u8)~UART2_CR1_WAKE);
|
||||
UART2->CR1 |= (u8)UART2_WakeUp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines if the UART2 is in mute mode or not.
|
||||
* @par Full description:
|
||||
* Determines if the UART2 is in mute mode or not.
|
||||
* @param[in] NewState: new state of the UART2 mode.
|
||||
* This parameter can be:
|
||||
* - ENABLE
|
||||
* - DISABLE
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_ReceiverWakeUpCmd(FunctionalState NewState)
|
||||
{
|
||||
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
|
||||
|
||||
if (NewState != DISABLE)
|
||||
{
|
||||
/* Enable the mute mode UART2 by setting the RWU bit in the CR2 register */
|
||||
UART2->CR2 |= UART2_CR2_RWU;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the mute mode UART2 by clearing the RWU bit in the CR1 register */
|
||||
UART2->CR2 &= ((u8)~UART2_CR2_RWU);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -493,20 +172,6 @@ u8 UART2_ReceiveData8(void)
|
||||
return ((u8)UART2->DR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the most recent received data by the UART2 peripheral.
|
||||
* @par Full description:
|
||||
* Returns the most recent received data by the UART2 peripheral.
|
||||
* @retval u16 Received Data
|
||||
* @par Required preconditions:
|
||||
* UART2_Cmd(ENABLE);
|
||||
*/
|
||||
u16 UART2_ReceiveData9(void)
|
||||
{
|
||||
return (u16)((((u16)UART2->DR) | ((u16)(((u16)((u16)UART2->CR1 & (u16)UART2_CR1_R8)) << 1))) & ((u16)0x01FF));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Transmits 8 bit data through the UART2 peripheral.
|
||||
@@ -523,95 +188,6 @@ void UART2_SendData8(u8 Data)
|
||||
UART2->DR = Data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmits 9 bit data through the UART2 peripheral.
|
||||
* @par Full description:
|
||||
* Transmits 9 bit data through the UART2 peripheral.
|
||||
* @param[in] Data: the data to transmit.
|
||||
* @retval None
|
||||
* @par Required preconditions:
|
||||
* UART2_Cmd(ENABLE);
|
||||
*/
|
||||
void UART2_SendData9(u16 Data)
|
||||
{
|
||||
UART2->CR1 &= ((u8)~UART2_CR1_T8); /* Clear the transmit data bit 8 */
|
||||
UART2->CR1 |= (u8)(((u8)(Data >> 2)) & UART2_CR1_T8); /* Write the transmit data bit [8] */
|
||||
UART2->DR = (u8)(Data); /* Write the transmit data bit [0:7] */
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Transmits break characters.
|
||||
* @par Full description:
|
||||
* Transmits break characters on the UART2 peripheral.
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_SendBreak(void)
|
||||
{
|
||||
UART2->CR2 |= UART2_CR2_SBK;
|
||||
}
|
||||
/**
|
||||
* @brief Sets the address of the UART2 node.
|
||||
* @par Full description:
|
||||
* Sets the address of the UART2 node.
|
||||
* @param[in] UART2_Address: Indicates the address of the UART2 node.
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void UART2_SetAddress(u8 UART2_Address)
|
||||
{
|
||||
/*assert_param for x UART2_Address*/
|
||||
assert_param(IS_UART2_ADDRESS_OK(UART2_Address));
|
||||
|
||||
/* Clear the UART2 address */
|
||||
UART2->CR4 &= ((u8)~UART2_CR4_ADD);
|
||||
/* Set the UART2 address node */
|
||||
UART2->CR4 |= UART2_Address;
|
||||
}
|
||||
/**
|
||||
* @brief Sets the specified UART2 guard time.
|
||||
* @par Full description:
|
||||
* Sets the address of the UART2 node.
|
||||
* @par This function is related to SmartCard mode.
|
||||
* @param[in] UART2_GuardTime: specifies the guard time.
|
||||
* @retval None
|
||||
* @par Required preconditions:
|
||||
* SmartCard Mode Enabled
|
||||
*/
|
||||
void UART2_SetGuardTime(u8 UART2_GuardTime)
|
||||
{
|
||||
/* Set the UART2 guard time */
|
||||
UART2->GTR = UART2_GuardTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the system clock prescaler.
|
||||
* @par Full description:
|
||||
* Sets the system clock prescaler.
|
||||
* @par This function is related to SmartCard and IrDa mode.
|
||||
* @param[in] UART2_Prescaler: specifies the prescaler clock.
|
||||
* This parameter can be one of the following values:
|
||||
* @par IrDA Low Power Mode
|
||||
* The clock source is diveded by the value given in the register (8 bits)
|
||||
* - 0000 0000 Reserved
|
||||
* - 0000 0001 divides the clock source by 1
|
||||
* - 0000 0010 divides the clock source by 2
|
||||
* - ...........................................................
|
||||
* @par Smart Card Mode
|
||||
* The clock source is diveded by the value given in the register (5 significant bits) multipied by 2
|
||||
* - 0 0000 Reserved
|
||||
* - 0 0001 divides the clock source by 2
|
||||
* - 0 0010 divides the clock source by 4
|
||||
* - 0 0011 divides the clock source by 6
|
||||
* - ...........................................................
|
||||
* @retval None
|
||||
* @par Required preconditions:
|
||||
* IrDA Low Power mode or smartcard mode enabled
|
||||
*/
|
||||
void UART2_SetPrescaler(u8 UART2_Prescaler)
|
||||
{
|
||||
/* Load the UART2 prescaler value*/
|
||||
UART2->PSCR = UART2_Prescaler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether the specified UART2 flag is set or not.
|
||||
@@ -686,210 +262,8 @@ FlagStatus UART2_GetFlagStatus(UART2_Flag_TypeDef UART2_FLAG)
|
||||
/* Return the UART2_FLAG status*/
|
||||
return status;
|
||||
}
|
||||
/**
|
||||
* @brief Clears the UART2 flags.
|
||||
* @par Full description:
|
||||
* Clears the UART2 flags.
|
||||
* @param[in] UART2_FLAG specifies the flag to clear
|
||||
* This parameter can be any combination of the following values:
|
||||
* - UART2_FLAG_LBDF: LIN Break detection flag.
|
||||
* - UART2_FLAG_LHDF: LIN Header detection flag.
|
||||
* - UART2_FLAG_LSF: LIN synchrone field flag.
|
||||
* - UART2_FLAG_RXNE: Receive data register not empty flag.
|
||||
* @par Notes:
|
||||
* - PE (Parity error), FE (Framing error), NE (Noise error), OR (OverRun error)
|
||||
* and IDLE (Idle line detected) flags are cleared by software sequence: a read
|
||||
* operation to UART2_SR register (UART2_GetFlagStatus())followed by a read operation
|
||||
* to UART2_DR register(UART2_ReceiveData8() or UART2_ReceiveData9()).
|
||||
* - RXNE flag can be also cleared by a read to the UART2_DR register
|
||||
* (UART2_ReceiveData8()or UART2_ReceiveData9()).
|
||||
* - TC flag can be also cleared by software sequence: a read operation to UART2_SR
|
||||
* register (UART2_GetFlagStatus()) followed by a write operation to UART2_DR register
|
||||
* (UART2_SendData8() or UART2_SendData9()).
|
||||
* - TXE flag is cleared only by a write to the UART2_DR register (UART2_SendData8() or
|
||||
* UART2_SendData9()).
|
||||
* - SBK flag is cleared during the stop bit of break.
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void UART2_ClearFlag(UART2_Flag_TypeDef UART2_FLAG)
|
||||
{
|
||||
assert_param(IS_UART2_CLEAR_FLAG_OK(UART2_FLAG));
|
||||
|
||||
/*< Clear the Receive Register Not Empty flag */
|
||||
if (UART2_FLAG == UART2_FLAG_RXNE)
|
||||
{
|
||||
UART2->SR = (u8)~(UART2_SR_RXNE);
|
||||
}
|
||||
/*< Clear the LIN Break Detection flag */
|
||||
else if (UART2_FLAG == UART2_FLAG_LBDF)
|
||||
{
|
||||
UART2->CR4 &= (u8)(~UART2_CR4_LBDF);
|
||||
}
|
||||
/*< Clear the LIN Header Detection Flag */
|
||||
else if (UART2_FLAG == UART2_FLAG_LHDF)
|
||||
{
|
||||
UART2->CR6 &= (u8)(~UART2_CR6_LHDF);
|
||||
}
|
||||
/*< Clear the LIN Synch Field flag */
|
||||
else
|
||||
{
|
||||
UART2->CR6 &= (u8)(~UART2_CR6_LSF);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether the specified UART2 interrupt has occurred or not.
|
||||
* @par Full description:
|
||||
* Checks whether the specified UART2 interrupt has occurred or not.
|
||||
* @param[in] UART2_IT: Specifies the UART2 interrupt pending bit to check.
|
||||
* This parameter can be one of the following values:
|
||||
* - UART2_IT_LBDF: LIN Break detection interrupt
|
||||
* - UART2_IT_TXE: Tansmit Data Register empty interrupt
|
||||
* - UART2_IT_TC: Transmission complete interrupt
|
||||
* - UART2_IT_RXNE: Receive Data register not empty interrupt
|
||||
* - UART2_IT_IDLE: Idle line detection interrupt
|
||||
* - UART2_IT_OR: OverRun Error interrupt
|
||||
* - UART2_IT_PE: Parity Error interrupt
|
||||
* @retval
|
||||
* ITStatus The new state of UART2_IT (SET or RESET).
|
||||
*/
|
||||
ITStatus UART2_GetITStatus(UART2_IT_TypeDef UART2_IT)
|
||||
{
|
||||
ITStatus pendingbitstatus = RESET;
|
||||
u8 itpos = 0;
|
||||
u8 itmask1 = 0;
|
||||
u8 itmask2 = 0;
|
||||
u8 enablestatus = 0;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_UART2_GET_IT_OK(UART2_IT));
|
||||
|
||||
/* Get the UART2 IT index*/
|
||||
itpos = (u8)((u8)1 << (u8)((u8)UART2_IT & (u8)0x0F));
|
||||
/* Get the UART2 IT index*/
|
||||
itmask1 = (u8)((u8)UART2_IT >> (u8)4);
|
||||
/* Set the IT mask*/
|
||||
itmask2 = (u8)((u8)1 << itmask1);
|
||||
|
||||
|
||||
|
||||
/* Check the status of the specified UART2 pending bit*/
|
||||
if (UART2_IT == UART2_IT_PE)
|
||||
{
|
||||
/* Get the UART2_ITPENDINGBIT enable bit status*/
|
||||
enablestatus = (u8)((u8)UART2->CR1 & itmask2);
|
||||
/* Check the status of the specified UART2 interrupt*/
|
||||
|
||||
if (((UART2->SR & itpos) != (u8)0x00) && enablestatus)
|
||||
{
|
||||
/* Interrupt occurred*/
|
||||
pendingbitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Interrupt not occurred*/
|
||||
pendingbitstatus = RESET;
|
||||
}
|
||||
}
|
||||
|
||||
else if (UART2_IT == UART2_IT_LBDF)
|
||||
{
|
||||
/* Get the UART2_IT enable bit status*/
|
||||
enablestatus = (u8)((u8)UART2->CR4 & itmask2);
|
||||
/* Check the status of the specified UART2 interrupt*/
|
||||
if (((UART2->CR4 & itpos) != (u8)0x00) && enablestatus)
|
||||
{
|
||||
/* Interrupt occurred*/
|
||||
pendingbitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Interrupt not occurred*/
|
||||
pendingbitstatus = RESET;
|
||||
}
|
||||
}
|
||||
else if (UART2_IT == UART2_IT_LHDF)
|
||||
{
|
||||
/* Get the UART2_IT enable bit status*/
|
||||
enablestatus = (u8)((u8)UART2->CR6 & itmask2);
|
||||
/* Check the status of the specified UART2 interrupt*/
|
||||
if (((UART2->CR6 & itpos) != (u8)0x00) && enablestatus)
|
||||
{
|
||||
/* Interrupt occurred*/
|
||||
pendingbitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Interrupt not occurred*/
|
||||
pendingbitstatus = RESET;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the UART2_IT enable bit status*/
|
||||
enablestatus = (u8)((u8)UART2->CR2 & itmask2);
|
||||
/* Check the status of the specified UART2 interrupt*/
|
||||
if (((UART2->SR & itpos) != (u8)0x00) && enablestatus)
|
||||
{
|
||||
/* Interrupt occurred*/
|
||||
pendingbitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Interrupt not occurred*/
|
||||
pendingbitstatus = RESET;
|
||||
}
|
||||
}
|
||||
/* Return the UART2_IT status*/
|
||||
return pendingbitstatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the UART2 pending flags.
|
||||
* @par Full description:
|
||||
* Clears the UART2 pending bit.
|
||||
* @param[in] UART2_IT specifies the pending bit to clear
|
||||
* This parameter can be one of the following values:
|
||||
* - UART2_IT_LBDF: LIN Break detection interrupt
|
||||
* - UART2_IT_LHDF: LIN Header detection interrupt
|
||||
* - UART2_IT_RXNE: Receive Data register not empty interrupt.
|
||||
*
|
||||
* @par Notes:
|
||||
* - PE (Parity error), FE (Framing error), NE (Noise error), OR (OverRun error) and
|
||||
* IDLE (Idle line detected) pending bits are cleared by software sequence: a read
|
||||
* operation to UART2_SR register (UART2_GetITStatus()) followed by a read operation
|
||||
* to UART2_DR register (UART2_ReceiveData8() or UART2_ReceiveData9() ).
|
||||
* - RXNE pending bit can be also cleared by a read to the UART2_DR register
|
||||
* (UART2_ReceiveData8() or UART2_ReceiveData9() ).
|
||||
* - TC (Transmit complet) pending bit can be cleared by software sequence: a read
|
||||
* operation to UART2_SR register (UART2_GetITStatus()) followed by a write operation
|
||||
* to UART2_DR register (UART2_SendData8()or UART2_SendData9()).
|
||||
* - TXE pending bit is cleared only by a write to the UART2_DR register
|
||||
* (UART2_SendData8() or UART2_SendData9()).
|
||||
* @retval None
|
||||
*/
|
||||
void UART2_ClearITPendingBit(UART2_IT_TypeDef UART2_IT)
|
||||
{
|
||||
assert_param(IS_UART2_CLEAR_IT_OK(UART2_IT));
|
||||
|
||||
/*< Clear the Receive Register Not Empty pending bit */
|
||||
if (UART2_IT == UART2_IT_RXNE)
|
||||
{
|
||||
UART2->SR = (u8)~(UART2_SR_RXNE);
|
||||
}
|
||||
/*< Clear the LIN Break Detection pending bit */
|
||||
else if (UART2_IT == UART2_IT_LBDF)
|
||||
{
|
||||
UART2->CR4 &= (u8)~(UART2_CR4_LBDF);
|
||||
}
|
||||
/*< Clear the LIN Header Detection pending bit */
|
||||
else
|
||||
{
|
||||
UART2->CR6 &= (u8)(~UART2_CR6_LHDF);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -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 */
|
||||
@@ -121,8 +122,15 @@ static void main_thread_func (uint32_t data);
|
||||
*
|
||||
* Sets up the STM8 hardware resources (system tick timer interrupt) necessary
|
||||
* for the OS to be started. Creates an application thread and starts the OS.
|
||||
*
|
||||
* If the compiler supports it, stack space can be saved by preventing
|
||||
* the function from saving registers on entry. This is because we
|
||||
* are called directly by the C startup assembler, and know that we will
|
||||
* never return from here. The NO_REG_SAVE macro is used to denote such
|
||||
* functions in a compiler-agnostic way, though not all compilers support it.
|
||||
*
|
||||
*/
|
||||
void main ( void )
|
||||
NO_REG_SAVE void main ( void )
|
||||
{
|
||||
int8_t status;
|
||||
|
||||
@@ -162,11 +170,11 @@ void main ( void )
|
||||
}
|
||||
}
|
||||
|
||||
while (1)
|
||||
;
|
||||
|
||||
/* There was an error starting the OS if we reach here */
|
||||
return;
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -63,16 +63,16 @@ uint32_t test_start (void)
|
||||
uint8_t eight = 8;
|
||||
uint8_t nine = 9;
|
||||
uint8_t ten = 10;
|
||||
uint8_t eleven = 11;
|
||||
uint8_t twelve = 12;
|
||||
uint8_t thirteen = 13;
|
||||
uint8_t fourteen = 14;
|
||||
uint8_t fifteen = 15;
|
||||
uint8_t sixteen = 16;
|
||||
uint8_t seventeen = 17;
|
||||
uint8_t eighteen = 18;
|
||||
uint8_t nineteen = 19;
|
||||
uint8_t twenty = 20;
|
||||
uint16_t eleven = 11;
|
||||
uint16_t twelve = 12;
|
||||
uint16_t thirteen = 13;
|
||||
uint16_t fourteen = 14;
|
||||
uint16_t fifteen = 15;
|
||||
uint32_t sixteen = 16;
|
||||
uint32_t seventeen = 17;
|
||||
uint32_t eighteen = 18;
|
||||
uint32_t nineteen = 19;
|
||||
uint32_t twenty = 20;
|
||||
|
||||
/* Default to zero failures */
|
||||
failures = 0;
|
||||
@@ -83,106 +83,106 @@ uint32_t test_start (void)
|
||||
/* Check all variables contain expected values */
|
||||
if (one != 1)
|
||||
{
|
||||
ATOMLOG (_STR("1(%d)\n"), one);
|
||||
ATOMLOG (_STR("1(%d)\n"), (int)one);
|
||||
failures++;
|
||||
}
|
||||
if (two != 2)
|
||||
{
|
||||
ATOMLOG (_STR("2(%d)\n"), two);
|
||||
ATOMLOG (_STR("2(%d)\n"), (int)two);
|
||||
failures++;
|
||||
}
|
||||
if (three != 3)
|
||||
{
|
||||
ATOMLOG (_STR("3(%d)\n"), three);
|
||||
ATOMLOG (_STR("3(%d)\n"), (int)three);
|
||||
failures++;
|
||||
}
|
||||
if (four != 4)
|
||||
{
|
||||
ATOMLOG (_STR("4(%d)\n"), four);
|
||||
ATOMLOG (_STR("4(%d)\n"), (int)four);
|
||||
failures++;
|
||||
}
|
||||
if (five != 5)
|
||||
{
|
||||
ATOMLOG (_STR("5(%d)\n"), five);
|
||||
ATOMLOG (_STR("5(%d)\n"), (int)five);
|
||||
failures++;
|
||||
}
|
||||
if (six != 6)
|
||||
{
|
||||
ATOMLOG (_STR("6(%d)\n"), six);
|
||||
ATOMLOG (_STR("6(%d)\n"), (int)six);
|
||||
failures++;
|
||||
}
|
||||
if (seven != 7)
|
||||
{
|
||||
ATOMLOG (_STR("7(%d)\n"), seven);
|
||||
ATOMLOG (_STR("7(%d)\n"), (int)seven);
|
||||
failures++;
|
||||
}
|
||||
if (eight != 8)
|
||||
{
|
||||
ATOMLOG (_STR("8(%d)\n"), eight);
|
||||
ATOMLOG (_STR("8(%d)\n"), (int)eight);
|
||||
failures++;
|
||||
}
|
||||
if (nine != 9)
|
||||
{
|
||||
ATOMLOG (_STR("9(%d)\n"), nine);
|
||||
ATOMLOG (_STR("9(%d)\n"), (int)nine);
|
||||
failures++;
|
||||
}
|
||||
if (ten != 10)
|
||||
{
|
||||
ATOMLOG (_STR("10(%d)\n"), ten);
|
||||
ATOMLOG (_STR("10(%d)\n"), (int)ten);
|
||||
failures++;
|
||||
}
|
||||
if (eleven != 11)
|
||||
{
|
||||
ATOMLOG (_STR("11(%d)\n"), eleven);
|
||||
ATOMLOG (_STR("11(%d)\n"), (int)eleven);
|
||||
failures++;
|
||||
}
|
||||
if (twelve != 12)
|
||||
{
|
||||
ATOMLOG (_STR("12(%d)\n"), twelve);
|
||||
ATOMLOG (_STR("12(%d)\n"), (int)twelve);
|
||||
failures++;
|
||||
}
|
||||
if (thirteen != 13)
|
||||
{
|
||||
ATOMLOG (_STR("13(%d)\n"), thirteen);
|
||||
ATOMLOG (_STR("13(%d)\n"), (int)thirteen);
|
||||
failures++;
|
||||
}
|
||||
if (fourteen != 14)
|
||||
{
|
||||
ATOMLOG (_STR("14(%d)\n"), fourteen);
|
||||
ATOMLOG (_STR("14(%d)\n"), (int)fourteen);
|
||||
failures++;
|
||||
}
|
||||
if (fifteen != 15)
|
||||
{
|
||||
ATOMLOG (_STR("15(%d)\n"), fifteen);
|
||||
ATOMLOG (_STR("15(%d)\n"), (int)fifteen);
|
||||
failures++;
|
||||
}
|
||||
if (sixteen != 16)
|
||||
{
|
||||
ATOMLOG (_STR("16(%d)\n"), sixteen);
|
||||
ATOMLOG (_STR("16(%d)\n"), (int)sixteen);
|
||||
failures++;
|
||||
}
|
||||
if (seventeen != 17)
|
||||
{
|
||||
ATOMLOG (_STR("17(%d)\n"), seventeen);
|
||||
ATOMLOG (_STR("17(%d)\n"), (int)seventeen);
|
||||
failures++;
|
||||
}
|
||||
if (eighteen != 18)
|
||||
{
|
||||
ATOMLOG (_STR("18(%d)\n"), eighteen);
|
||||
ATOMLOG (_STR("18(%d)\n"), (int)eighteen);
|
||||
failures++;
|
||||
}
|
||||
if (nineteen != 19)
|
||||
{
|
||||
ATOMLOG (_STR("19(%d)\n"), nineteen);
|
||||
ATOMLOG (_STR("19(%d)\n"), (int)nineteen);
|
||||
failures++;
|
||||
}
|
||||
if (twenty != 20)
|
||||
{
|
||||
ATOMLOG (_STR("20(%d)\n"), twenty);
|
||||
ATOMLOG (_STR("20(%d)\n"), (int)twenty);
|
||||
failures++;
|
||||
}
|
||||
|
||||
/* Quit */
|
||||
return failures;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ static ATOM_TIMER timer_cb[4];
|
||||
/* Global test data */
|
||||
static volatile uint32_t cb_order[4];
|
||||
static int cb_cnt = 0;
|
||||
static uint32_t cb_time[4];
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
@@ -136,7 +135,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++;
|
||||
}
|
||||
}
|
||||
@@ -165,9 +164,6 @@ static void testCallback (POINTER cb_data)
|
||||
/* Store our callback order in cb_order[] */
|
||||
cb_order[cb_cnt] = expected_order;
|
||||
|
||||
/* Store the current time for debug purposes */
|
||||
cb_time[cb_cnt] = atomTimeGet();
|
||||
|
||||
/* Interrupts are locked out so we can modify cb_cnt without protection */
|
||||
cb_cnt++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user