AdaCore / Ada_Drivers_Library

Ada source code and complete sample GNAT projects for selected bare-board platforms supported by GNAT.
BSD 3-Clause "New" or "Revised" License
240 stars 141 forks source link

MicroBit development with default ADA libs and tasking #281

Closed Skjelsbek closed 4 years ago

Skjelsbek commented 5 years ago

Hello! I'm currently at my third and final year of studying computer engineering, and we have an assignment in a course called Real-Time Systems where we are supposed to program the Micro:bit in Ada. For this specific task I need to utilize the Ada.Real_Time library and use tasking combined with the Ada_Drivers_Library. It seems like I'm not able to figure out how to do this, so I am wondering if it is possible for you to create an example on how to do this?

Regards, Jon

pat-rogers commented 5 years ago

Hi Jon,

Welcome!

Have you installed and built other projects successfully for the Micro:bit with Ada and the ADL, or is this your initial effort?

Have you seen this page: https://github.com/AdaCore/Ada_Drivers_Library/blob/master/examples/MicroBit/README.md

Note that to use tasking and the Ada.Real_Time package you'll need to use one of the Ravenscar run-time libraries, rather than the ZFP run-time.

Best regards,

Pat

Skjelsbek commented 5 years ago

Hi Pat,

I've had a look at the page you linked, and I've also tested some of the example projects included in the ADL. I am new to both the language and the library, but from what I've seen so far, it is how things change when using a different run-time library that is the hardest part to wrap one's head around.

Does the ADL repo include any examples on how to use the Ravenscar run-time libraries with the Micro:bit? Also, the way tasking works when using Ravenscar is confusing to me, so I would be very happy if it was an explanation of that somewhere as well.

Thanks for the quick response. Best regards, Jon

Skjelsbek commented 5 years ago

I managed to compile without errors when using Ravenscar, but as soon as I added "with Ada.Real_Time;", I got the error shown in the image below.

ravenscar_with_real_time_error_message

Please feel free to take a look at my implementation here: https://github.com/Skjelsbek/ada_projects/tree/master/ravenscar_test

pat-rogers commented 5 years ago

On 11/1/2018 1:08 PM, Jon Skjelsbæk wrote:

I managed to compile without errors when using Ravenscar, but as soon as I added "with Ada.Real_Time;", I got the error shown in the image below.

ravenscar_with_real_time_error_message https://user-images.githubusercontent.com/25771335/47869731-fd438c80-de07-11e8-9d80-19dc191561e1.png

Please feel free to take a look at my implementation here: https://github.com/Skjelsbek/ada_projects/tree/master/ravenscar_test

The linker error is likely due to inadvertently using both the ZFP and the ravenscar-sfp runtimes:

with "../Ada_Drivers_Library/boards/MicroBit/microbit_zfp.gpr"; -- ZFP project Microbit_Example is ... for Runtime ("ada") use "ravenscar-sfp-microbit"; -- SFP is the right one...

Currently there is no gpr file in boards/MicroBit for the ravenscar-sfp so we will use a different approach. The ravenscar-* runtimes exist for the MicroBit so we will get them a different way. You'll still have access to the MicroBit-specific sources in the ADL.

Except for having to edit a config file, this is the intended way to use the ADL.

In your clone of the ADL, edit this ADL script file:

Ada_Drivers_Library\scripts\config\boards.py

so that lines 132:133 specify True instead of False, like so:

     config.pre_define('Has_Ravenscar_SFP_Runtime', 'True', origin)
     config.pre_define('Has_Ravenscar_Full_Runtime', 'True', origin)

Then, in your app directory, invoke this ADL script file to prepare your ADL cloned copy for use:

  Ada_Drivers_Library\scripts\project_wizard.py

Invoke it without any arguments. It is interactive so you will answer prompts. When it asks, select #8 for the MicroBit option, then #1 for the ravenscar-sfp runtime, then take the rest as defaults. Press Enter until it returns.

After it returns you will have a new directory in your app dir named Ada_Drivers_Library, and in there will be a gpr file named "ada_drivers_library.gpr" that you can reference in your app's gpr file.

Add that new gpr file to you application gpr file. For example, if your app gpr file is named buttons.gpr you would have this as the start of the file:

with "Ada_Drivers_Library/ada_drivers_library.gpr";

project Buttons is

   for Runtime ("ada") use "ravenscar-sfp-microbit";

   ...

Now you should be able to build correctly. It would be a good idea to first delete the previous build products, ie the .o and .ali files, etc.

As you can see there is some extra work here and it may be that I am not using the optimal approach. I haven't worked much with the MicroBit so there may be a better way to do this but this will get you going for now.

pat-rogers commented 5 years ago

Hi Jon,

I am new to both the language and the library, but from what I've seen so far, it is how things change when using a different run-time library that is the hardest part to wrap one's head around.

The run-time libraries define the additional set of facilities and language-defined packages that are available to the application. That's over and above what the compiler already supports. Indeed, there is a lot of capability in Ada without them, but not, for example, tasking.

Speaking of tasking, Ravenscar is a language-defined subset of Ada tasking (named the Ravenscar Profile) that we support on these targets. The runtime libraries with the "ravenscar-" prefix in their names are such libraries. In contrast the runtimes with ZFP in the names have almost no runtime library code at all. (These are intended for certification, for example, so must be minimal.)

You may choose between the ravenscar-sfp (Small FootPrint) and the ravenscar-full runtimes. In essence the SFP runtimes just add Ravenscar tasking to the ZFP runtimes, whereas the "full" runtimes add that and a lot more. (Not absolutely the full language, but close.) The full runtimes even have an additional profile that is based on Ravenscar but not quite as restrictive.

As you are new to Ada let me suggest you visit learn.adacore.com for some on-line instruction. The Ada 2012 book by John Barnes is also very good if you want a book.

Good luck!

Pat

Skjelsbek commented 5 years ago

Many thanks, Pat, I really appreciate your effort! I'll look into it tommorow.

pat-rogers commented 5 years ago

On 11/1/2018 6:24 PM, Jon Skjelsbæk wrote:

Many thanks, Pat, I really appreciate your effort! I'll look into it tommorow.

You're very welcome. Let me know how it goes.

Skjelsbek commented 5 years ago

Then, in your app directory, invoke this ADL script file to prepare your ADL cloned copy for use: Ada_Drivers_Library\scripts\project_wizard.py Invoke it without any arguments. It is interactive so you will answer prompts. When it asks, select #8 for the MicroBit option, then #1 for the ravenscar-sfp runtime, then take the rest as defaults. Press Enter until it returns.

Hi, Pat I've tried invoking the script Ada_Drivers_Library\scripts\project_wizard.py using Anaconda, and after fixing the error saying that i have to encapsulate every print statement in parenthesis, I still get the following error. I am currently trying to figure it out, but I figured it would be a good idea to post here while looking for solutions. image

EDIT: I managed to resolve that error, and I think the reason why I have to change all of these things is because I'm running python 3 and the code seems to be written for python 2.

Regards, Jon

Skjelsbek commented 5 years ago

I managed to get the script working, and it generated the folder as expected. I tried to follow every step from your description as strictly as possible from that point on, but it seems like i keep getting the same linker error as I did earlier. Any ideas why?

Error message: error_message.txt

Project github repo: https://github.com/Skjelsbek/ada_projects/tree/master/ravenscar_test

pat-rogers commented 5 years ago

On 11/2/2018 10:03 AM, Jon Skjelsbæk wrote:

I managed to get the script working, and it generated the folder as expected. I tried to follow every step from your description as strictly as possible from that point on, but it seems like i keep getting the same linker error as I did earlier. Any ideas why?

Error message: error_message.txt https://github.com/AdaCore/Ada_Drivers_Library/files/2542989/error_message.txt

Project github repo: https://github.com/Skjelsbek/ada_projects/tree/master/ravenscar_test

I checked the files in that project, and all looks good.

My only guess is something remains from the attempt to build with the previous version in the gpr file that referenced both the ZFP and the ravenscar-sfp runtimes at the same time.

Therefore, using the command line (ie, not the gprclean tool), delete everything under the following directories:

ravenscar_test/obj/

ravenscar_test/Ada_Drivers_Library/obj_Debug/

ravenscar_test/Ada_Drivers_Library/obj_lib_Debug/

Then rebuild.

If that doesn't work, we'll have to wait for the MicroBit expert to be available.

Best regards,

Pat

-- Patrick Rogers, PhD rogers@adacore.com +1 646 375 0739 office +1 646 358 3289 fax

pat-rogers commented 5 years ago

On 11/2/2018 11:04 AM, Pat Rogers wrote:

On 11/2/2018 10:03 AM, Jon Skjelsbæk wrote:

I managed to get the script working, and it generated the folder as expected. I tried to follow every step from your description as strictly as possible from that point on, but it seems like i keep getting the same linker error as I did earlier. Any ideas why?

Error message: error_message.txt https://github.com/AdaCore/Ada_Drivers_Library/files/2542989/error_message.txt

Looking at the above again, I see that only the app code is being compiled, which reinforces the guess that there is a left-over file(s) in the ADL object directories.

Best regards,

Pat

-- Patrick Rogers, PhD rogers@adacore.com +1 646 375 0739 office +1 646 358 3289 fax

Skjelsbek commented 5 years ago

I've deleted everything in the directories you mentioned, and built the code yet again. As you can see in the images below, it compiles just fine when user either one of the libraries, but as soon as I try to use both at the same time, the same problem occurs.

image

image

image

I guess we have to call in the expert for this one.

Best regards, Jon

pat-rogers commented 5 years ago

On 11/2/2018 1:36 PM, Jon Skjelsbæk wrote:

I've deleted everything in the directories you mentioned, and built the code yet again. As you can see in the images below, it compiles just fine when user either one of the libraries, but as soon as I try to use both at the same time, the same problem occurs.

In fact it is doing exactly that to me as well. I had not tried the combination because it took a while to get the tools installed and set up again.

I guess we have to call in the expert for this one.

I'll look into the runtimes' code now that we know it is likely not just an installation issue.

Best regards,

Pat

-- Patrick Rogers, PhD rogers@adacore.com +1 646 375 0739 office +1 646 358 3289 fax

pat-rogers commented 5 years ago

On 11/2/2018 2:55 PM, Pat Rogers wrote:

I'll look into the runtimes' code now that we know it is likely not just an installation issue.

Yeah, package body nRF51.Interrupts also defines that symbol, in the ADL:

Ada_Drivers_Library\arch\ARM\Nordic\drivers\nrf51-interrupts.adb

so it conflicts with the one in the runtime library:

arm-eabi\lib\gnat\ravenscar-sfp-microbit\gnarl\s-bbcppr.adb

which is what the error message said but I didn't believe it was not an installation error.

Let me give some thought how best to work around it.

Best regards,

Pat

-- Patrick Rogers, PhD rogers@adacore.com +1 646 375 0739 office +1 646 358 3289 fax

Skjelsbek commented 5 years ago

Yet again i would like to express how much i appreciate the time and effort you put into helping me out with this issue. It really means alot to me as the assignment kind of forces me to figure this out!

Many thanks!

pat-rogers commented 5 years ago

On 11/2/2018 4:04 PM, Jon Skjelsbæk wrote:

Yet again i would like to express how much i appreciate the time and effort you put into helping me out with this issue. It really means alot to me as the assignment kind of forces me to figure this out!

You're very welcome.

The bad news: although you can use the Ravenscar-SFP runtime library (at least) with the MicroBit and, thereby, get Ravenscar tasking, you won't be able to do much that is specific to the nFR51 without rolling your own drivers. The current drivers in the Ada Drivers Library are not set up for use with any other than the ZFP runtime library. I may be wrong about this, as I am not very active with the MicroBit in the ADL, but that's what I see.

The good news, if you're allowed, is that full support for the Ravenscar-based runtimes is definitely possible with the ADL device drivers for other very low-cost boards besides the MicroBit. I'm thinking of some of the STMicro Discovery boards, in particular.

For example, the 429 Discovery board is available here:

https://www.mouser.com/ProductDetail/STMicroelectronics/STM32F429I-DISC1?qs=sGAEpiMZZMvJkDqKJH80dBW9Ucpez89T%252byheH8hFi38%3d

and other places too. Of course free is hard to compete with!

Your choices appear to be either

1) use the ADL device drivers but the ZFP runtime, and thus not have Ada tasking available, or

2) use the Ravenscar-based runtimes without the ADL. That means you will have to do the device drivers yourself, for those that your app requires. If there isn't much required by your application that may be reasonably possible.

Since this is an assignment, let me ask if your instructor has already done what you have been assigned to do.

Best regards,

Pat

-- Patrick Rogers, PhD rogers@adacore.com +1 646 375 0739 office +1 646 358 3289 fax

Skjelsbek commented 5 years ago

Alright, then I guess I have a decision to make. My teacher hasn't done what we're assigned, and is to little to non help when it comes to the questions discussed in this issue. Initially he wanted us to use Arduino instead of the MicroBit which seemed impossible, hence the change to MicroBit. The due date for this task is the upcoming friday, so I guess I just have to make the best of it and explain the situation to him by referring to this issue if I'm not able to get ahold of a supported board by then.

Thanks for all the help Best regards, Jon

pat-rogers commented 5 years ago

On 11/2/2018 6:17 PM, Jon Skjelsbæk wrote:

Alright, then I guess I have a decision to make. My teacher hasn't done what we're assigned, and is to little to non help when it comes to the questions discussed in this issue. Initially he wanted us to use Arduino instead of the MicroBit which seemed impossible, hence the change to MicroBit. The due date for this task is the upcoming friday, so I guess I just have to make the best of it and explain the situation to him by referring to this issue if I'm not able to get ahold of a supported board by then.

It may still be possible, depending on the functionality required.

The issue is that the highest level API for the MicroBit in the ADL (i.e., the set of packages named MicroBit.) uses a package that defines interrupt handling support for the ZFP runtime. (The ZFP runtimes don't have that, unlike the Ravenscar runtimes). That's package nFR51.Interrupts, a device-specific package used by the MicroBit. packages, and it conflicts withe the interrupt handling defined in the Ravenscar runtimes. Hence the linker error.

If you can avoid any code that depends directly or indirectly on nRF51.Interrupts you may be good to go.

In particular, you can use the HAL. packages, and those nRF51. packages that don't use the nRF51.Interrupts package.

That said, it could be a lot more work than using the MicroBit.* packages. For example, the high level API for the LED display package would not be available.

However, the MicroBit. and nRF51. packages are quite powerful. You could likely do what you need to do without Ada tasking, if your instructor would allow that.

Best regards,

Pat

-- Patrick Rogers, PhD rogers@adacore.com +1 646 375 0739 office +1 646 358 3289 fax

Skjelsbek commented 5 years ago

I understand the situation, and it's basically up to me to decide how to approach this. The reason why I would prefer to have Ada tasking is that I want to be able to read sensor data in one task, and use it to control actuators in another. This was the initial plan, but now I might do it sequential as of the complications. My instructors' requirements for the assignment is that we use Ada programming langue to program a real-time system, so I guess a sequential approach will do the job.

Anyway, I have to test things out to see what turns out to be the best approach for my project. The complications have annoyed me up until this point, but atleast now I know how I can work around it. Thanks!

Best regards, Jon

pat-rogers commented 5 years ago

On 11/3/2018 5:47 AM, Jon Skjelsbæk wrote:

I understand the situation, and it's basically up to me to decide how to approach this. The reason why I would prefer to have Ada tasking is that I want to be able to read sensor data in one task, and use it to control actuators in another. This was the initial plan, but now I might do it sequential as of the complications. My instructors' requirements for the assignment is that we use Ada programming langue to program a real-time system, so I guess a sequential approach will do the job.

Yes, absolutely. I am a strong advocate of Ada tasking for real-time/embedded systems but it need not be used in every situation.

Anyway, I have to test things out to see what turns out to be the best approach for my project. The complications have annoyed me up until this point, but atleast now I know how I can work around it. Thanks!

Best of luck!

Best regards,

Pat

-- Patrick Rogers, PhD rogers@adacore.com +1 646 375 0739 office +1 646 358 3289 fax