Skip to content

Add support for nRF52-series targets. #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 1, 2019
Merged

Conversation

damaki
Copy link
Contributor

@damaki damaki commented Dec 15, 2018

Overview

This pull request adds support for the Nordic Semi nRF52 series MCUs, based on the Cortex-M4, specifically the nRF52840 and nRF52832.

Support for three new targets is added:

  • nrf52840
  • nrf52832
  • dwm1001-dev

The nrf52840 and nrf52832 targets should be suitable for any board based on those MCUs, provided that the board is fitted with a 32 kHz external oscillator. Both of these targets use the null Text_IO implementation.

The dwm1001-dev target is an extension of nrf52832 to add Text_IO support (output only) for the DecaWave DWM1001 Development Board. This board is based on the nRF52832, and contains an on-chip J-Link debugger that provides a virtual COM port that is used for Text_IO output.

In the rest of this description I will describe the design and rationale for the Board_Support alarm implementation in this runtime for the nRF52.

Tick-less Scheduler

The most significant feature of this nRF52 runtime is an alternative implementation of System.BB.Board_Support to replace the SysTick-based alarm handler with a "tick-less" implementation. This new implementation is based on the nRF52 real-time clock (RTC) peripheral. It removes the periodic (e.g. 1 kHz) tick interrupt, and instead generates a single alarm interrupt at the exact time specified in the call to System.BB.Board_Support.Set_Alarm.

Rationale

The primary rationale for this tick-less Board_Support is to target ultra-low power Ravenscar-based applications using this runtime that can operate for years on AA batteries. To do this, the CPU needed to be allowed to sleep as much as possible to get the average current draw as low as possible, since the CPU draws typ. 6.3 mA while active. My target was to get the average current draw to below 10 µA. This eliminated the possibility of using the SysTick timer for the following reasons:

  1. The SysTick timer ticks at (usually) 1 kHz, which results in a lot of unnecessary CPU wake-ups during long task delays.
  2. I discovered that the power management on the nRF52 powers down the entire CPU - including the SysTick - when the CPU enters WFI sleep. This results in the SysTick pausing when the CPU sleeps, making it useless as a low-power timer base.
  3. The SysTick (and any other high-resolution timer peripherals) requires the high-frequency clock (HFCLK) to be active, which has a relatively high current draw of approximately 200 µA, which exceeds my target current draw by an order of magnitude.

My solution was to instead use one of the three RTC peripherals with 32.768 kHz low-frequency clock (LFCLK) as the time base for the Ravenscar runtime. Using the RTC would allow the HFCLK to be turned off and the CPU to be put to sleep, while keeping the task scheduler (alarms) alive.

Implementation

The existing Ravenscar scheduler is very well designed and can already support a tick-less implementation without changes. The only work needed to implement a tick-less scheduler was to implement the alarm handler System.BB.Board_Support package in a way that avoids a periodic interrupt.

The RTC is a 24-bit counter, which overflows every 512 seconds when operating at 32.768 kHz. The RTC also has a "compare" feature which allows an interrupt to be generated then the RTC counter reaches a configurable 24-bit value. This compare feature is what is used to implement the tick-less alarm.

Read_Clock just needs to read and return the current value of the RTC's 24-bit counter. This provides a high-resolution time base that ticks every 30.518 µs.

When Set_Alarm is called, it sets the RTC compare value to the specified alarm time. The alarm time is guaranteed to be a 24-bit value since the existing runtime ensures the provided alarm time does not exceed the value returned by the Max_Timer_Interval function, which in this runtime for the nRF52 returns 2**24 - 1.

Once the alarm time is set, a single interrupt will be generated at the specified alarm time, which wakes up the scheduler and unblocks the delayed task. This results in task delays that are much more accurate than SysTick-based runtimes, since the alarm interrupt is triggered at the exact alarm time. The resolution of the alarm is 1 timer tick, which is 30.518 µs.

The runtime already guarantees that an alarm will be set at least once every Max_Timer_Interval to keep the scheduler alive during long periods of sleep. This will result in unnecessary alarm interrupts during very long periods of sleep, but since the RTC overflows very slowly - every 512 seconds (8.5 minutes) - these will occur very infrequently. The RTC uses a "safety factor" of 7/8 of the Max_Timer_Interval, resulting in one unnecessary interrupt every 448 seconds (7.5 minutes) which is perfectly acceptable since the CPU is only awake for a very short time before sleeping again.

Considerations for Ada RM D.8 (30)

The runtime in this repository derives the resolution of Ada.Real_Time.Time_Unit directly from the clock source (specified in System.BB.Board_Parameters). The other runtimes in this repository specify their main clock speed (e.g. 64 MHz), so Time_Unit is very fine. This runtime, however, uses a 32.768 kHz clock source which would result in a much more coarse Time_Unit.

Ada RM Annex D.8 "Monotonic Time" item 30 states: "Time_Unit shall be less than or equal to 20 microseconds. ". A Time_Unit derived from a 32.768 kHz clock source would violate this requirement, as it would have Time_Unit of 30.518 µs.

To ensure that the requirement in ARM D.8 (30 is met, the package spec for System.BB.Board_Support deals in units that are scaled up in multiples of 32.768 kHz, and is the unit exposed to the rest of the runtime (including Ada.Real_Time). The Board_Support package body divides these scaled-up units back down to 32.768 kHz when interacting with the RTC. This scaling factor is configured in the constant: System.BB.Board_Parameters.RTC_Tick_Scaling_Factor. I have set this value to 32, so that Time_Unit has a resolution of 1 / (32.768 kHz * 32) = 0.954 µs, which satisfies ARM D.8 (30).

Current Measurements

I have measured the average power consumption on an nRF52840 Development Kit and with this tick-less runtime the average current draw was approximately 3 µA. This was measured using a Power Profiler Kit with the runtime running from the internal 32.768 kHz RC oscillator.

@CLAassistant
Copy link

CLAassistant commented Dec 15, 2018

CLA assistant check
All committers have signed the CLA.

@Fabien-Chouteau
Copy link
Member

Hi @damaki,

Thank you very much for your contribution. It will take some time for us to process this 🙂

Your choice of using the RTC for time keeping is interesting. I think the explanation/rational that you provide above deserves to go into a README file in arm/nordic/nrf52/.

I have a first batch of comments/questions right away:

  • We do not add the SVD file in this repository (arm/nordic/nrf52/nrf52832/nrf52.svd). Please can you move it to svd2ada?
  • I didn't look that much into the code so I'm curious to know why/if the GPIO package is required.
  • What is the difference between the NRF52840 and NRF52832 in terms of SVD?
  • It would be nice to have some explanation of the different Errata_X functions.
  • It would also be nice to merge all the commits into a single one. It will be cleaner for the repository.
  • Since the nRF52 is an ARM device, semihosting IO should be enabled. It provides an basic an standard text output.
  • Since the only difference between DWM1001DEV and NRF52832 is the Text_IO. I don't think it is necessary to have a run-time just for DWM1001DEV. You can use the NRF52832 run-time and implement the serial port driver on the "user code" side, for instance in the Ada_Drivers_Library.

Thanks,

@damaki
Copy link
Contributor Author

damaki commented Dec 17, 2018

Thanks for the feedback, @Fabien-Chouteau

That's a good idea to add a README with the radionale. I notice there are similar READMEs for other targets, e.g. STM32, so I will try follow a similar format to be consistent.

To address your immediate comments:

  • OK, I'll open a separate pull request on svd2ada to submit the SVD files there.
  • The GPIO package is only used to (optionally) enable SWD pins first thing during the Setup_Board procedure.
  • Are you wondering if the same .svd file and generated code can be shared between the two targets? I have not performed a detailed comparison between the two .svd files, but the two MCUs seem to have basically the same peripherals (but the nRF52840 has more instances of some peripherals than the nRF52832). I took the two .svd files from Nordic's nRF5 SDK (version 15.1.0). Despite the fact that most peripherals are identical between the two MCUs, the two .svd files have some obvious differences. The main difference I have noticed is that the nrf52840.svd file defines the appropriate <fields> elements for TASKS and EVENTS registers, but the nrf52.svd file is missing these elements. This caused a problem when I was writing s-bbbosu__nrf52.adb because the generated RTC register definitions were different for the two targets. I solved this problem by manually editing nrf52.svd to add the missing <fields> definitions.
  • I copied the Errata_X checks from nRF5 SDK's startup code which is written in C. These functions check if certain errata are applicable to the specific chip revision and rely on some registers that are not documented by Nordic. If these functions detect that some errata are applicable, then they apply a workaround for the errata which I also followed from the nRF5 SDK. I will update the source files with a more detailed explanation.
  • OK. I'll try to squash the commits.
  • OK, that makes sense. I'll enable semihosting.
  • OK. I'll remove the dwm1001-dev target.

Thanks,
Dan

@Fabien-Chouteau
Copy link
Member

Thanks for the Update Daniel 👍

I have an nRF52832 dev kit and the run-time seems to work on it :)

Did you test the interrupt handling?

@damaki
Copy link
Contributor Author

damaki commented Jan 18, 2019

Glad to hear you got the runtime up and running on your board!

I have had a couple of other projects using interrupts on both the nRF52840 and nRF52832 runtimes (ravenscar-full) and they worked without problems. But since you asked about interrupts, I spent some time this evening creating a simple test program which blinks two LEDs on one of my boards using the nRF52832 runtime so that I can test the interrupt handling in a bit more detail. The first LED is driven by a "delay until" infinite loop in the environment task. The second LED is driven from a Protected Object which uses the interrupt from the RTC1 peripheral that I configured.

The interrupts on this test program work perfectly when the PO using RTC1 is configured with an Interrupt_Priority greater than Interrupt_Priority'First, but a program error is raised when my interrupt handler is called if the PO is set to Interrupt_Priority'First.

The program error is raised by System.Tasking.Protected_Objects.Lock. Looking at the source (s-taprob.adb) the exception is probably caused by the check Caller_Priority > Object.Ceiling evaluating to true. I suspect that for some reason, Caller_Priority is greater than Interrupt_Priority'First. I'll see if I can track down the root cause of this problem.

@damaki
Copy link
Contributor Author

damaki commented Jan 19, 2019

@Fabien-Chouteau I've tracked down the cause of the fault and the root cause is that the definitions for Interrupt_Priority in package System assumes 4-bit interrupt priorities for ARM Cortex-M architectures (giving 15 levels of usable interrupt priority, 241..255, since the highest level is reserved for the kernel). This assumption is violated for this nRF52 runtime since the nRF52 only supports 3 priority bits (the minimum required), so we can only support 8 interrupt priority levels on this runtime. When I attempted to use Interrupt_Priority'First (241) in my test program, one of the bits was masked away when written to the NVIC interrupt priority registers. When the interrupt is invoked, this register is read back and reads a priority different (higher) than the original priority, resulting in the program_error being raised.

The fix for this problem would be to define a new version of theSystem package for this runtime which defines Interrupt_Priority with the range 249..255. Then the interrupt handling code should all work fine for any Cortex-M runtimes that support 3-bit interrupt priorities.

My proposal to solve this problem is to create new variants of src/system/system-xi-cortexm4-full.ads (and also the sfp version) which contain new definitions of Priority and Interrupt_Priority supporting a 3-bit interrupt priority range. These new versions of the file can then be selected by runtimes that support the 3-bit interrupt priority ranges. Perhaps it can be named system-xi-cortexm4-3bitprio-full.ads.

What do you think about this? If you agree with my proposed solution then I'll go ahead and make the changes.

@Fabien-Chouteau
Copy link
Member

Thanks for the investigation Daniel,

We would like to avoid the multiplication of system.ads packages, but I don't see any other way here.

@damaki
Copy link
Contributor Author

damaki commented Jan 23, 2019

Indeed, the ARM specifications state that there may be up to 256 interrupt priorities (8 bits), which would require many variants of system.ads to support the different number of interrupt priorities.

Another alternative to avoid excessive variants of system.ads could be to generate the file from a common template file. At the moment, build_rts.py just copies the appropriate system.ads file from src/system into the source tree. The script could be extended to optionally do a string substitution within the file after copying it to the source tree. For example, it could replace instances of ${max_interrupt_priority} and ${max_priority} with the specific values for the runtime being generated. The template file would then contain (for example):

   Max_Interrupt_Priority   : constant Positive := ${max_interrupt_priority};
   Max_Priority             : constant Positive := ${max_priority};

   subtype Any_Priority       is Integer range         0 .. Max_Interrupt_Priority;
   subtype Priority           is Any_Priority range    0 .. Max_Priority;
   subtype Interrupt_Priority is Any_Priority range  Max_Priority+1 .. Max_Interrupt_Priority;

The values for these two parameters would be defined by the specific target in arm/cortexm.py.

Thoughts?

@Fabien-Chouteau
Copy link
Member

Sounds like a good idea to me, I do think that going forward we will need more "code" generation in bb-runtimes.

@lambourg @burratoo @pat-rogers what do you think?

@pat-rogers
Copy link
Contributor

Impressive work!
I think the template idea makes sense.

@damaki
Copy link
Contributor Author

damaki commented Apr 19, 2019

Hello again @Fabien-Chouteau

I've created custom system.ads files for the nRF52, which I have placed in arm/nordic/nrf52 to avoid cluttering src/system. This was made possible by the recent changes in commit c2c2cc4 by @lambourg which allows system.ads files to be located outside of src/system.

I've tested these new system.ads files and the previous problem with Program_Error being raised at some interrupt priorities has now been fixed.

I think this is a simpler solution than my previous proposal of using template files. The only potential downside I can think of right now could be ensuring any changes to the system implementation parameters in system.ads in src/system are replicated to these new nRF52-specific files. This is unlikely to be a problem if these parameters rarely change.

@Fabien-Chouteau
Copy link
Member

Thank you @damaki !

I will have a look next week, in the meantime can bump all the copyright years?

Thanks,

@Fabien-Chouteau
Copy link
Member

Thank you @damaki

There are still a few style problems (copyright year, trailing white space), can you apply the patch below?

Also I would need a single patch rather than 27. This is to make the integration process easier on our side (This GitHub repo is a mirror of our work repository). You can do that with git rebase -i and replace the skip words by fixup except for the first commit. You then have to force push the branch git push -f. Of course as for any unusual git operation, it is recommended to do a backup :)

I could do this myself but the commit hash will change, and GitHub will not be able to relate it to this pull-request.

--- b/arm/cortexm.py
+++ b/arm/cortexm.py
@@ -436,11 +436,12 @@
                          ['arm/nordic/nrf51/s-bbbopa__microbit.ads',
                           'src/s-textio__microbit.adb'])
 
+
 class NRF52(ArmV7MTarget):
     @property
     def name(self):
         return 'nRF52'
-        
+
     @property
     def parent(self):
         return CortexMArch
@@ -471,7 +472,7 @@
 
     def __init__(self):
         super(NRF52, self).__init__()
-        
+
         self.add_linker_script('arm/nordic/nrf52/common-ROM.ld', loader='ROM')
 
         self.add_sources('crt0', [
@@ -479,12 +480,13 @@
             'arm/nordic/nrf52/start-common.S',
             'arm/nordic/nrf52/start-rom.S',
             'arm/nordic/nrf52/setup_board.ads'])
-            
+
         self.add_sources('gnarl', [
             'src/s-bbpara__nrf52.ads',
             'src/s-bbbosu__nrf52.adb',
             'src/s-bcpcst__pendsv.adb'])
 
+
 class NRF52840(NRF52):
     @property
     def name(self):
@@ -496,7 +498,7 @@
 
     def __init__(self):
         super(NRF52840, self).__init__()
-        
+
         self.add_linker_script('arm/nordic/nrf52/memory-map_nRF52840.ld',
                                loader='ROM')
 
@@ -513,11 +515,12 @@
             'arm/nordic/nrf52/nrf52840/svd/i-nrf52-rtc.ads',
             'arm/nordic/nrf52/nrf52840/svd/i-nrf52-temp.ads',
             'src/s-textio__null.adb'])
-        
+
         self.add_sources('gnarl', [
             'arm/nordic/nrf52/nrf52840/svd/handler.S',
             'arm/nordic/nrf52/nrf52840/svd/a-intnam.ads'])
 
+
 class NRF52832(NRF52):
     @property
     def name(self):
@@ -529,7 +532,7 @@
 
     def __init__(self):
         super(NRF52832, self).__init__()
-        
+
         self.add_linker_script('arm/nordic/nrf52/memory-map_nRF52832.ld',
                                loader='ROM')
 
@@ -545,7 +548,7 @@
             'arm/nordic/nrf52/nrf52832/svd/i-nrf52-rtc.ads',
             'arm/nordic/nrf52/nrf52832/svd/i-nrf52-temp.ads',
             'src/s-textio__null.adb'])
-        
+
         self.add_sources('gnarl', [
             'arm/nordic/nrf52/nrf52832/svd/handler.S',
             'arm/nordic/nrf52/nrf52832/svd/a-intnam.ads'])
diff -u b/arm/nordic/nrf52/nrf52832/svd/a-intnam.ads b/arm/nordic/nrf52/nrf52832/svd/a-intnam.ads
--- b/arm/nordic/nrf52/nrf52832/svd/a-intnam.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/a-intnam.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-clock.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-clock.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-clock.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-clock.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-ficr.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-ficr.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-ficr.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-ficr.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-gpio.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-gpio.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-gpio.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-gpio.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-nvmc.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-nvmc.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-nvmc.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-nvmc.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-rtc.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-rtc.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-rtc.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-rtc.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-temp.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-temp.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-temp.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-temp.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-uart.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-uart.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-uart.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-uart.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-uicr.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-uicr.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-uicr.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52-uicr.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52832/svd/i-nrf52.ads b/arm/nordic/nrf52/nrf52832/svd/i-nrf52.ads
--- b/arm/nordic/nrf52/nrf52832/svd/i-nrf52.ads
+++ b/arm/nordic/nrf52/nrf52832/svd/i-nrf52.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
@@ -49,7 +49,7 @@
 with System;
 
 --  nRF52832 reference description for radio MCU with ARM 32-bit Cortex-M4
---  Microcontroller 
+--  Microcontroller
 package Interfaces.NRF52 is
    pragma Preelaborate;
    pragma No_Elaboration_Code_All;
diff -u b/arm/nordic/nrf52/nrf52840/svd/a-intnam.ads b/arm/nordic/nrf52/nrf52840/svd/a-intnam.ads
--- b/arm/nordic/nrf52/nrf52840/svd/a-intnam.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/a-intnam.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-ccm.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-ccm.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-ccm.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-ccm.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-clock.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-clock.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-clock.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-clock.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-ficr.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-ficr.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-ficr.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-ficr.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-gpio.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-gpio.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-gpio.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-gpio.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-nvmc.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-nvmc.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-nvmc.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-nvmc.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-rtc.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-rtc.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-rtc.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-rtc.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-temp.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-temp.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-temp.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-temp.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-uicr.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-uicr.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-uicr.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52-uicr.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
diff -u b/arm/nordic/nrf52/nrf52840/svd/i-nrf52.ads b/arm/nordic/nrf52/nrf52840/svd/i-nrf52.ads
--- b/arm/nordic/nrf52/nrf52840/svd/i-nrf52.ads
+++ b/arm/nordic/nrf52/nrf52840/svd/i-nrf52.ads
@@ -1,5 +1,5 @@
 --
---  Copyright (C) 2018, AdaCore
+--  Copyright (C) 2019, AdaCore
 --
 
 --  Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
@@ -49,7 +49,7 @@
 with System;
 
 --  nRF52840 reference description for radio MCU with ARM 32-bit Cortex-M4
---  Microcontroller 
+--  Microcontroller
 package Interfaces.NRF52 is
    pragma Preelaborate;
    pragma No_Elaboration_Code_All;
diff -u b/src/s-bbpara__nrf52.ads b/src/s-bbpara__nrf52.ads
--- b/src/s-bbpara__nrf52.ads
+++ b/src/s-bbpara__nrf52.ads
@@ -8,7 +8,7 @@
 --                                                                          --
 --        Copyright (C) 1999-2002 Universidad Politecnica de Madrid         --
 --             Copyright (C) 2003-2005 The European Space Agency            --
---                     Copyright (C) 2003-2016, AdaCore                     --
+--                     Copyright (C) 2003-2019, AdaCore                     --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --

This implements runtime support for the nRF52 series microcontrollers
from Nordic Semiconductor. Specifically, the nRF52840 based on the
nRF52840 Development Kit board.

An alternative implementation of System.BB.Board_Support is created
for the nRF52 which uses RTC0 as the clock source for task delays
in the Ravenscar runtime. RTC0 is used instead of the SysTick timer
since the WFI instruction seems to power down the entire CPU,
including the SysTick which prevents the CPU from being woken up
by task delays while in WFI sleep.

Furthermore, the use of RTC0 allows very low power consumption as
the CPU and high-speed clocks can be powered down during WFI sleep.

This implementation of System.BB.Board_Support for nRF52 also
provides a "tick-less" alarm mechanism. Instead of generting a
1 kHz tick interrupt, the RTC's "compare" feature is used to
dynamically generate alarm interrupts at precisely the desired
alarm time. For very long delays the RTC will still overflow every
512 seconds, but there are no other unnecessary RTC interrupts
within this period. This allows the CPU to spend almost all of its
time sleeping during long task delays.

This approach has the following benefits:
  1. Very low average power consumption due to very few "useless"
     interrupts. I have measured an average power consumption of
     approximately 3 µA while sleeping.
  2. Tasks can be woken up at a much more precise time than is
     possible with a 1 kHz tick; with a resolution of 30.5 µs.
@damaki
Copy link
Contributor Author

damaki commented Apr 24, 2019

Hi @Fabien-Chouteau

I've applied your patch and squashed everything to a single commit (I encountered some conflicts with git rebase -i, so I used a git reset --soft master approach instead).

Let me know if there are any other changes required.

Thanks

@Fabien-Chouteau
Copy link
Member

Thanks @damaki,

I did a test on my nRF52 dev kit and it works!

I will do the merge process as soon as possible.

@adacore-bot adacore-bot merged commit f1262ab into AdaCore:master May 1, 2019
adacore-bot pushed a commit that referenced this pull request May 1, 2019
This comes from the GitHub pull request #12

Change-Id: I5da940adb34cf4ac5d9a2586951f7f2db1818a6f
@Fabien-Chouteau
Copy link
Member

@damaki the patch is merged, thank you again.

@damaki
Copy link
Contributor Author

damaki commented May 3, 2019

Glad I could contribute!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants