Several keys can be kept at the same time in the key store, and several
keys can be loaded at once. Give access to these features.
The ccm-test example is also improved to better demonstrate the use of
the key store.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
Using the AES interrupt allows the user process not to waste time
polling for the completion of the operation. This time can be used by
the user process to do something else, or to let the system enter PM0.
Since the system is now free to perform various operations during a
crypto operation, a protection of the crypto resource is added, and PM1+
is prohibited in order not to stall crypto operations.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
The CC2538 the WDT cannot be stopped once it has been started.
The CC2530/1 WDT can be stopped if it is running in timer mode,
but it cannot be stopped once it has been started in watchdog mode.
Both platforms currently provide "dummy" implementations of `watchdog_stop()`,
one does nothing and the other one basically re-maps `_stop()` to
`_periodic()`.
This was originally done in order to provide implementations for all prototypes
declared in `core/dev/watchdog.h`. In hindsight and as per the discussion
in #1088, this is bad practice since, if the build succeeds, the caller will
expect that the WDT has in fact been stopped, when in reality it has not.
Since the feature (stopping the WDT) is unsupported by the hardware, this pull
removes those dummy implementations. Thus, we will now be able to reliably
detect - at build time - attempts at using this unsupported feature.
This is safer because the previous code assumed that the start and end
VMAs of .data and .bss were word-aligned, which is not always the case,
so the initialization code could write data outside these sections. The
ROM functions support any address boundary.
This is faster because the ROM functions are ultra optimized, using
realignment and the LDM/STM instructions, which is much better than the
previous simple loops of single word accesses.
This is smaller because the ROM functions don't require to add any code
to the target device other than simple function calls.
This makes the code simpler and more maintainable because standard
functions are not reimplemented and no assembly is used.
Note that this is also faster and smaller than the corresponding
functions from the standard string library.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
The initialization code clearing .bss is allowed to use the stack, so
the stack can not be in .bss, or this code will badly fail if it uses
the stack.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
In order to be fast, the reset_handler() function uses word accesses to
initialize the .data output section. However, most toolchains do not
automatically force the alignment of an output section LMA to use the
maximum alignment of all its input sections. Because of that, assuming
that .data contains some words, the LMA of the .data output section was
not word-aligned in some cases, resulting in an initialization performed
using slow unaligned word accesses.
This commit forces the alignment of the LMA of the .data output section
with a word boundary in order to always use fast aligned word accesses
to read the .data load area.
Note that this solution is better than using ALIGN_WITH_INPUT, both
because the latter is a new feature incompatible with older toolchains,
and because it could create a big gap between _etext and the LMA of
.data if strongly-aligned data were added to .data, although only a word
alignment is required here.
The same considerations apply to the VMA of .data. However, it is
already automatically word-aligned, both because .data contains words,
and because the end VMA of the previous output section (.socdata) is
word-aligned. Moreover, if the VMA of .data were forcibly word-aligned,
then a filled gap could appear at the beginning of this section if
strongly-aligned data were added to it, thus wasting flash memory.
Consequently, it's better not to change anything for the VMA of .data,
all the more it's very unlikely that it does not contain any word and
that the end VMA of .socdata becomes non-word-aligned, and this would
only result in a slower initialization.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
Some toolchains, like Sourcery CodeBench Lite 2013.05-23 arm-none-eabi
(http://sourcery.mentor.com/public/gnu_toolchain/arm-none-eabi/)
automatically force the alignment of an output section LMA to use the
maximum alignment of all its input sections. This toolchain uses GNU
binutils 2.23, and this automatic behavior is the same as the manual
behavior of the ALIGN_WITH_INPUT feature of GNU binutils 2.24+.
This behavior is not an issue per se, but it creates a gap between
_etext and the LMA of the .data output section if _etext does not have
the same alignment, while reset_handler() initialized this section by
copying the data from _etext to its VMA, hence an offset in the
addresses of loaded data, and missing data.
This commit fixes this issue by making reset_handler() directly use the
LMA of the .data section using LOADADDR(.data), rather than assuming
that _etext is this LMA.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
Only the interrupt flags that have been handled must be cleared.
Otherwise, if a new interrupt occurs after the interrupt statuses are
read and before they are cleared, then it is discarded without having
been handled. This issue was particularly likely with two interrupt
trigger conditions occurring on different pins of the same port in a
short period of time.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
Power-up interrupts do not always update the regular interrupt status.
Because of that, in order not to miss power-up interrupts, the ISR must
handle both the regular and the power-up interrupt statuses.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
Introduce new useful GPIO macros to:
- get the raw interrupt status of a port,
- get the masked interrupt status of a port,
- get the power-up interrupt status of a port.
These macros are cleaner and less error-prone than raw register access
code copied all over the place.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
OR-ing an offset to a base address instead of adding it is dangerous
because it can only work if the base address is aligned enough for the
offset.
Moreover, if the base address or the offset has a value unknown at
compile time, then the assembly instructions dedicated to 'base +
offset' addressing on most CPUs can't be emitted by the compiler because
this would require the alignment of the base address against the offset
to be known in order to optimize 'base | offset' into 'base + offset'.
In that case, the compiler has to emit more instructions in order to
compute 'base | offset' on most CPUs, e.g. on ARM, which means larger
binary size and slower execution.
Hence, replace all occurrences of 'base | offset' with 'base + offset'.
This must become a coding rule.
Here are the results for the cc2538-demo example:
- Compilation of uart_init():
* before:
REG(regs->base | UART_CC) = 0;
200b78: f446 637c orr.w r3, r6, #4032 ; 0xfc0
200b7c: f043 0308 orr.w r3, r3, #8
200b80: 2200 movs r2, #0
200b82: 601a str r2, [r3, #0]
* now:
REG(regs->base + UART_CC) = 0;
200b7a: 2300 movs r3, #0
200b7c: f8c4 3fc8 str.w r3, [r4, #4040] ; 0xfc8
- Size of the .text section:
* before: 0x4c7c
* now: 0x4c28
* saved: 84 bytes
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
Instead of requiring all calls to `watchdog_start` to be
wrapped inside `#if WATCHDOG_CONF_ENABLE` guards, we control
things from within the WDT driver itself.
This commit also includes some minor documentation and
indentation cleanups
* Decouple 64-bit address from LINKADDR_SIZE
* get and set object from/to the start/end of the src/dest buffer
* We expect size == 8 (rather than size < 8) for both get_ and set_object. Error otherwise
* The RF no longer sets parameters by itself. We let the platform do this, using the extended API.
This avoids the limitation of having a single UART available at runtime, without
duplicating code.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Because the CC2538 has a multi-byte SPI RX FIFO, flushing the buffer
requires more than just a single read. This adds a loop that empties the
entire RX buffer on a FLUSH().
Different SPI chips needs different SPI settings. This commit adds a
function that allows chip drivers to configure the SPI peripheral before
using it.
The frame pin the driver was using as a chip select does not work as
most devices expect it to. It toggles after every byte, and most chips
interpret that as end of message. To make drivers more reliable, each
chip driver should setup a GPIO and assert it as needed.
Contiki sometimes fails to boot correctly and locks up in
random_init()
This problem only manifests itself for specific versions
of the arm-gcc toolchain and then again only for specific
levels of optimisation (-Os vs -O2, depending on the
value of the SMALL make variable)
The lockup is caused when we write an RFCORE XREG before
the RF clock ungating has taken effect, which in turn
only occurs depending on the assembly generated for those
two instructions:
REG(SYS_CTRL_RCGCRFC) = 1;
REG(RFCORE_XREG_FRMCTRL0) = 0x00000008;
This commit makes the RNG wait for the ungating to take
effect before attempting to write the register
The CC2538 currently has two addressing options: a hardcoded address set
at compile time or the address stored in primary address section of the
info page. This commit adds the option to choose the secondary location
of the ieee address from the info page, or any memory address.
To use, define `IEEE_ADDR_CONF_USE_SECONDARY_LOCATION` in `project-conf.h`
or similar.
For example:
#define IEEE_ADDR_CONF_USE_SECONDARY_LOCATION 1
Some CFLAGS and LDFLAGS previously only enabled with SMALL=1 have
now been enabled for all builds, regardless of the value of SMALL.
Therefore, from now on, SMALL only chooses between -Os and -O2
As discussed in #503, -Os was broken with one of the toolchains
recommended in the platform's README and for that reason we were
using -O2 by default.
This commit sets the default to -Os and updates the README to no
longer recommend the toolchain in question
lpm.c needs to #include lpm.h in order to get the definition of
lpm_periph_permit_pm1_func_t, which made the replacement macros conflict with
the function definitions for the LPM_CONF_ENABLE == 0 case. This change fixes
this issue by #if-ing out the code in lpm.c in that case. Also, the replacement
macro for lpm_register_peripheral() was missing in that case, which is fixed
here.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
If a project needs to use some libraries at link stage, then the corresponding
linker options (e.g. '-lm') have to be passed after any .o file depending on
these libraries. Hence, LDFLAGS cannot be used to add such options when invoking
$(LD) in Makefile.cc2538, or it should be moved to the correct location.
Instead, this change adds TARGET_LIBFILES to the correct location, like most
other Contiki targets.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Some SoC data requires huge alignments. E.g., the µDMA channel control table has
to be 1024-byte aligned. This table was simply aligned to 1024 bytes in the C
code, which had the following consequences, wasting a lot of RAM:
- As this table could be placed anywhere in .bss, there could be an alignment
gap of up to 1023 bytes between the preceding data and this table.
- The size of this table was also aligned to 1024 bytes, regardless of
UDMA_CONF_MAX_CHANNEL, making this configuration option supposed to save RAM
just useless.
- .bss was also aligned to at least 1024 bytes, creating a huge alignment gap
between .data and .bss.
Instead of relying on the compiler to force this alignment, and on the linker to
automatically place data, this change places carefully such SoC data in RAM
using the linker script. A dedicated section is created to place such SoC data
requiring huge alignments, and it is put at the beginning of the SRAM in order
to ensure a maximal alignment without any gap. In this way, the alignment of
.bss also remains normal, and the size of this table is not constrained by its
alignment, but only by its contents (i.e. by UDMA_CONF_MAX_CHANNEL).
In the case of the µDMA channel control table, the data is still zeroed by
udma_init() (instead of also being zeroed as part of .bss).
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Normally, the linker does not sort files and sections matched by wildcards, so
they are placed in the order in which they are seen during link. If numerous
objects with different alignments are mixed, or if objects with unusually large
alignments are present, this very likely leads to a lot of space being wasted
because of accumulated alignment gaps.
This commit forces input sections to be sorted by alignment (unless this is
overridden by the linker script), which decreases the number and the size of
alignment gaps, thus saving space.
For a typical Contiki project, this change saves nearly 1 kiB, mainly in .bss.
Note that this behavior is only enabled if the SMALL make variable is set to 1,
because this makes more sense for a size optimization.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
The .nrdata section is volatile, so its initialization must be controlled by the
application, and not be automatically done by the startup code. It should
neither be zeroed like .bss, nor be initialized from data in flash memory like
.data. This was already supposed to be the case, but the output section type of
.nrdata was not set to NOLOAD, causing the generated ELF .nrdata section header
to be of type PROGBITS instead of NOBITS, i.e. load data was generated to be
programmed in RAM, thus producing huge unprogrammable .bin files.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
The clock adjustments made when waking up from PM1/2 were very inaccurate. If
relying on ContikiMAC's rtimer to sleep, this led to Contiki's software clock
time, seconds and etimers to be 2.5 s slower after each min, i.e. 1 hour slower
after each day, which is a show stopper issue for most real-life applications.
This was caused by a lack of accuracy in several pieces of code during sleep
entry and wake-up:
- It was difficult to synchronize the calls to RTIMER_NOW() before and after
sleep with the deactivation and activation of the SysTick peripheral caused
by PM1/2. This caused an inaccuracy in the corrective number of ticks passed
to clock_adjust().
- The value passed to clock_adjust() was truncated from an rtimer_clock_t
value, but the accumulated error caused by these truncated bits was ignored.
- The SysTick peripheral had to be stopped during the call to clock_adjust().
Rather than creating even more complicated clock adjustment mechanisms that
would probably still have mixed results as to accuracy, this change simply uses
the Sleep Timer counter as a base value for Contiki's clock and seconds
counters. The tick from the Systick peripheral is still used as the interrupt
source to update Contiki's clocks and timers. When running, the SysTick
peripheral and the Sleep Timer are synchronized, so combining both is not an
issue, and this allows not to alter the rtimer interrupt mechanism using the
Sleep Timer. The purpose of the Sleep Timer is to be an RTC, so it is the
perfect fit for the clock module, all the more it can not be disturbed by PM1/2.
If the 32-kHz XOSC is used, the Sleep Timer is also very accurate. If the
32-kHZ RCOSC is used, it is calibrated from the 32-MHz XOSC, so it is also
accurate, and the 32753-Hz vs. 32768-Hz systematic error in that case is
negligible, all the more one would use the 32-kHz XOSC for better accuracy.
Besides fixing this time drift issue, this change has several benefits:
- clock_time(), clock_seconds() and RTIMER_NOW() start synchronized, and they
change at the same source pace.
- If clock_set_seconds() is called, then clock_seconds() indicates one more
second almost exactly one second later, then exactly each second. Before this
change, clock_seconds() was not synchronized with clock_set_seconds(), so the
value returned by the former could be incremented immediately after the call
to the latter in some cases.
- The code tied to the clock module is simpler and more robust.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Whole elapsed seconds are added to secs first, so only the remaining subsecond
ticks should then be subtracted from second_countdown in order to decide whether
secs should be incremented again.
Otherwise, secs is not correctly updated in some cases, typically if the bit 7
of ticks is 1. E.g., with ticks = 128 (i.e. exactly 1 s elapsed) and
second_countdown = 128, secs was first incremented as expected, then 128 was
subtracted from second_countdown, giving 0 and triggering an unwanted second
increment of secs. Or with ticks = 129 (i.e. 1 s + 1 tick) and
second_countdown = 1, secs was first incremented as expected, then 129 was
subtracted from second_countdown, giving 128 and missing a second increment of
secs that should have occurred because second_countdown wrapped around.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
During PM1+, the hardware timer used to implement the Contiki clock is frozen,
so clock_adjust() needs to be called when exiting those modes in order to
compensate for the clock ticks missed while the timer was frozen. Doing so
changes the Contiki clock time, so etimer_request_poll() needs to be called in
order to inform the etimer library that an etimer might have expired.
Note that waiting for the next clock ISR to call etimer_request_poll() is
unreliable because the system might go back to sleep beforehand.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
When returning from PM1/2, the sleep timer value (used by RTIMER_NOW()) is not
up-to-date until a positive edge on the 32-kHz clock has been detected after the
system clock restarted. To ensure an updated value is read, wait for a positive
transition on the 32-kHz clock by polling the SYS_CTRL_CLOCK_STA.SYNC_32K bit,
before reading the sleep timer value.
Because of this RTIMER_NOW() fixup, lpm_exit() has to be called at the very
beginning of ISRs waking up the SoC. This also ensures that all clocks and
timers are enabled at the correct frequency and updated before using them
following wake-up.
Without this fix, etimers could sometimes (randomly, depending on timings)
become ultra slow (observed from 10x to 40x slower than normal) if the system
exited PM1/2 very often. This issue occurred more often with PM1.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
As recommended by the CC2538 User's Guide, set SYS_CTRL_CLOCK_CTRL.OSC_PD to 0
before asserting WFI, and set it to 1 after the system clock is sourced from the
32-MHz XOSC following wake-up. This allows to automatically start both
oscillators upon wake-up in order to partially hide the 32-MHz XOSC startup time
by the 16-MHz RCOSC startup time.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
As a matter of precaution, always make sure that pending system clock
transitions are complete before requesting a new change of the system clock
source.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
In one of the abort cases in lpm_enter(), the energest context has previously
been set to LPM, so the abort code needs to set it back to CPU.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>