From: Niklas Holsti <niklas.holsti@tidorum.invalid>
Subject: Re: Understanding GNAT Bare Board Run-time for Cortex-M
Date: Mon, 8 Apr 2019 10:46:56 +0300
Date: 2019-04-08T10:46:56+03:00 [thread overview]
Message-ID: <gh0cjgF13cU1@mid.individual.net> (raw)
In-Reply-To: <2d99a259-3288-4981-9bda-97145077a5bd@googlegroups.com>
On 19-04-08 05:13 , Daniel Way wrote:
> I'm trying to port the bare-board GNAT run-time to a Coretex-M0+ (NXP
> KV11Z7) processor. I'm new to concurrency and have been reading
> through the run-times for the STM32 targets to understand how the
> tasks and protected objects are implemented, however, there seems to
> be a web of dependencies between the different packages and wrappers
> of wrappers of wrappers for types and subprograms.
The wrappers of course try to isolate the target-specific code from the
target-independent code.
> * Is there any tool available to scan through the source code and
> generate a graphical call graph to help visualize the different
> dependencies?
I know of no free tool that generates graphical call-graphs. I've used
the non-graphical call tree information from GPS.
> * Has anyone on the forum successfully ported a bare-board run-time?
> What was your experience and do you have any tips?
In my last project, I ported the small-footprint Ravenscar run-time for
the SPARC architecture from the generic off-the-shelf AdaCore version to
a specific SPARC LEON2 processor embedded in an SoC for processing
satellite navigation signals, the AGGA-4 SoC.
My advice is to first understand the differences between the original
target processor and the new target processor, especially in these areas:
- Basic processor architecture, and especially if there is some
difference in the instruction set or in the sets of registers that must
be saved and restored in a task switch. In my case there was no
difference, so I did not have to modify the task-switch code nor the
Task Control Block structure. For porting across various models of the
same processsor architecture, perhaps the most likely difference is in
the presence or absence of a floating-point unit and dedicated
floating-point registers.
- The HW timers. In my case the RTS used two HW timers, and there were
some differences: the bit-width was different (32 instead of 24) and the
HW addresses and interrupt numbers were different. The corresponding
parts of the RTS had to be adapted, but in my case the changes were
small, and the logic of the code did not change.
- Interrupts and traps. Differences may have to be implemented in the
assembly-language code that initially handles interrupts and traps. In
my case, the architecture was the same (the structure of the trap table
and most of the HW error traps) but the set of external interrupt traps
was different, because of the particular I/O devices available on the
new target. This difference (if any) becomes visible to application
programs through Ada.Interrupts.
- "Console" I/O, usually some form of UART accessible via GNAT.Text_IO.
In my case, the UARTs in the new target were quite different from the
standard LEON2 UARTs, so I had to reimplement the low-level I/O
operations (Put character, Put string, etc.).
- Memory layout. Where in the address space is the ROM (or flash), where
is the RAM, where are the I/O control registers? Any differences in the
layout must be implemented in the linker command script, which in my
case was a file called leon.ld. The Ada RTS code probably does not have
to change for this reason, and did not change in my case.
Once all that is sorted out, you will probably have to modify the
start-up assembly-language code, which in my case was in the file
crt0.S. This deals with HW initialization (clearing registers, stopping
any I/O that might be running, disabling interrupts, etc.) and SW
initialization, which means to set up the stack for the environment task
and then enter the body of that task.
> * Is porting the run-time just a matter of updating the linker, a few
> packages, and a GPR script, or is there some fundamental
> implementation changes to consider?
If you are porting from one implementation of the same architecture to
another (in your case ARM Cortex M<n> with the Thumb-1/2 instruction
sets, if I understand right), IMO it is unlikely that any fundamental
changes are required. However, if there are differences in the
instruction set (with M0+ omitting some instructions available larger
members and perhaps used in the original RTS) be sure to use the correct
target options for the compiler so as to avoid generating code that will
not run on the M0+. If there is a major difference in instruction sets
(say, porting from Thumb-2 to Thumb-1) you will have to review and
perhaps modify all the assembly-language RTS parts, and all
assembly-language code insertions in the Ada RTS code, and all the code
in crt0.S.
HTH. I think others on this group have more experience with ARM Cortex
run-time systems and can probably offer better advice.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
next prev parent reply other threads:[~2019-04-08 7:46 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-08 2:13 Understanding GNAT Bare Board Run-time for Cortex-M Daniel Way
2019-04-08 7:36 ` Simon Wright
2019-04-08 12:47 ` Daniel Way
2019-04-08 15:52 ` Simon Wright
2019-04-08 7:46 ` Niklas Holsti [this message]
2019-04-08 8:06 ` J-P. Rosen
2019-04-08 12:49 ` Daniel Way
2019-04-08 12:56 ` Daniel Way
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox