comp.lang.ada
 help / color / mirror / Atom feed
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
       .      @       .


  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