The GNU linker ld searches and processes libraries and object files in
the order they are specified. Library files are archive files whose
members are object files. The linker handles an archive file by scanning
through it for members that define symbols that have so far been
referenced but not defined. But an ordinary object file is linked in the
usual fashion.
The C library is implicitly linked after all object files and libraries
specified on the command line.
Because of that, if the C library depends on the Contiki target library,
e.g. for the implementation of system calls, then these dependencies are
not linked, which results in undefined references. Actually, the Contiki
target library also needs the C library, hence a circular dependency
between these libraries, which means that explicitly adding -lc anywhere
on the command line can not help. The only solution in that case is to
pass these libraries to ld between --start-group and --end-group.
Archives grouped in this way are searched repeatedly by the linker until
no new undefined references are created.
This archive grouping option has a significant performance cost for the
linking stage. Moreover, having to use it and to pass -lc explicitly on
the command line is unusual, which is disturbing and more complicated
for users needing the C library to depend on the Contiki target library.
The same would be true for circular dependencies between the Contiki
target library and any other library.
Another issue with the Contiki target library is that it may alter the
apparent behavior of the weak vs. strong symbols, because of the way ld
handles archives, which may make it discard archive object files
containing strong versions of referenced symbols:
- If a symbol has a weak and a strong version in this library, both
inside the same object file, then the linker uses the strong
definition.
- If a weak symbol in this library has a strong counterpart in an
object file outside, then the linker uses the strong definition.
- If a strong symbol in this library is inside an object file
containing other referenced symbols, and has a weak counterpart
anywhere, then the linker uses the strong definition.
- If a strong symbol in this library is the only symbol referenced in
its object file, and has a weak counterpart in an object file
outside, then the linker uses the strong definition if this library
is linked first, and the weak one otherwise.
- If a strong symbol in this library is the only symbol referenced in
its object file, and has a weak counterpart in another object file in
this library, then the linker uses the definition from the first of
these objects added when creating this archive.
- If a symbol has a weak and a strong version, one in this library, and
the other in another library, then the rules are the same as if both
were in the Contiki target library.
The existence of cases where the linker uses a weak symbol despite the
presence of its strong counterpart in the sources compiled then passed
to the linker is very error-prone, all the more this behavior depends on
the order the object and archive files are passed on the command lines,
which may just result from the order of source files in lists where it
apparently does not matter. Such cases would be needed in the future,
e.g. to define weak default implementations of some system calls that
can be overridden by platform-specific implementations, both ending up
in the Contiki target library. There was already such a case used to
define the UART and USB ISRs as weak aliases of default_handler(),
relying on this implicit unusual behavior to keep default_handler() if
the UART or USB driver was unused, which was dangerous.
Since the Contiki target library was only used as an intermediate file
during the build, the current commit fixes these issues by simply
directly using the object files instead of building an intermediate
archive from them.
The CONTIKI_OBJECTFILES make variable would be incomplete if it were
used as a simple prerequisite in the %.elf rule in Makefile.cc2538,
because other object files are added to it after this rule. That's why
.SECONDEXPANSION is used to defer its expansion. Another solution would
have been to split Makefile.cc2538, with the variable assignments kept
in it, and the rule definitions moved to Makefile.customrules-cc2538,
but this would have required to add Makefile.customrules-<target> files
to all CC2538 platforms, only to include Makefile.customrules-cc2538.
The solution used here is much simpler.
Because the UART and USB ISRs were weak aliases of default_handler(),
this change would imply that these ISRs would always be used by the
linker instead of default_handler(), even if their drivers were
configured as unused with UART_CONF_ENABLE and USB_SERIAL_CONF_ENABLE,
which would be wrong. This commit fixes this issue by removing these
weak aliases and putting either these ISRs or default_handler() in the
vector table, depending on the configuration. Weak aliases are elegant,
but Contiki's build system does not currently allow to automatically
build or not source files depending on the configuration, so keeping
these weak aliases would have required to add #if constructs somewhere
in the source code, which would have broken their elegance and made them
pointless.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
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>
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>