Discussion:
STM32F4 Discovery, communication and libraries
(too old to reply)
r***@gmail.com
2014-08-26 22:38:33 UTC
Permalink
I discovered Ada 2 days ago, so stick with me.

I am starting a business which will focus on creating a cheap, modular, open source data logger/controller usable across multiple domains. At the moment I am in the prototyping stage, using the following hardware:

1. STM32F4 Discovery board
2. MikroElektronika STM32F4 Discovery shield (http://www.mikroe.com/stm32/stm32f4-discovery-shield/)
3. Various MikroElektronika click boards (http://www.mikroe.com/click/):
* GPS click board (ublox LEA-6S receiver)
* microSD
* RS485
* RS232
* Ethernet

I don't have experience in C/C++ but I do have a lot of experience in Java, python, structured text (read PLCs) and a few other bits and pieces. I REALLY don't want to develop in C. From what I can make out it looks like a nightmare once the code reaches any substantial size, which mine will. I've started quite a few beginner C books and never got very far before throwing in the towel. However what I've read about Ada has certainly caused me to sit up!

So far I have investigated the following high level language alternatives:

1. www.espruino.com (JavaScript)
2. www.micropython.org
3. www.eluaproject.net

At the moment I am forging ahead with Espruino because:

1. it is quick to get code on the processor as it is interpreted
2. interfacing with external hardware via SPI/I2C/UART is easy...except when you want to access on-chip functionality that isn't yet supported by the Espruino interpreter (which is aimed at STM32F1 powered Espruino board, partially ported to the STM32F4).
3. www.npmjs.org has so many libraries and examples of how to get things done (e.g. MODBUS RTU library...done) which translates to many willing hands/minds.

but I see dragons on the horizon. Here are a few:

1. It is not hard real-time
2. Although you can minify the code, I am uncertain whether everything will fit on when the code base grows.
3. JavaScript on microcontrollers has no track record.

In short, nice for tinkering/prototyping but probably not a wise choice for the long run.

Today I started chatting to Mike Silva over at EmbeddedRelated:

http://www.embeddedrelated.com/showarticle/617.php

For Ada to be a viable option for my project, this is what I think I need [with Mike's comments]:

1. [IN PROGRESS] Easy communication: SPI, I2C, Serial, Ethernet,

[Mike]
I know that AdaCore is working on comms libraries for the ARM Cortex M parts, but I don't know anything about the projected availability.

[Roy]
If they want adopters then they'd better get a move on!

2. [UNSOLVED?] Libraries/examples: MODBUS RTU/Eth at the very least

I have yet to find a repository of libraries covering the major protocols (e.g. MODBUS, CAN, one-wire). There are quite a few in C. Would it be viable to just wrap these in Ada? It seems like a great short term solution but if we are using Ada to make things more stable, it hardly makes sense to use it merely to wrap (flakey) C libraries ;)

[Mike]
It is also true that you can link to C code in Ada with either thin or thick wrappers. A thin wrapper just converts each C function to an equivalent Ada subprogram, while a thick wrapper adds one or more higher-level layers on top of the basic subprograms.

3. [SOLVED] Direct access to chip functionality: STM32F4 RTC, Precision Time Protocol capabilities on chip, etc. I read that binding in C code is fairly easy? That would allow me to directly call the STM32 C drivers provided by STM?

[Mike]
In any case, you will have no problem accessing the chip hardware in Ada.

4. [SOLVED] Someone hosts an open forum to encourage the exchange of ideas, providing an alternative to the normally clandestine military/large corporate approach to code development. If Ada is going to grow then it needs to open up to your average Joe like me.

[Mike]
comp.lang.ada!


I'd appreciate any further feedback from members of this list.

Roy
---
www.infinitefingers.com
Luke A. Guest
2014-08-27 02:40:48 UTC
Permalink
You might be interested in
https://github.com/rowsail/AdaForMicrocontrollers which is being discussed
between some of us on LinkedIn in the Ada for micro controllers group.
Roy Emmerich
2014-08-27 12:35:51 UTC
Permalink
Post by Luke A. Guest
https://github.com/rowsail/AdaForMicrocontrollers which is being discussed
between some of us on LinkedIn in the Ada for micro controllers group.
Thanks Luke. I've just requested to join.
Dmitry A. Kazakov
2014-08-27 07:41:30 UTC
Permalink
Post by r***@gmail.com
[Mike]
I know that AdaCore is working on comms libraries for the ARM Cortex M
parts, but I don't know anything about the projected availability.
What "comms" libraries? Basically it does not make sense to have a library
beyond system's port I/O driver, because higher-level protocols have
nothing in common, e.g. AK, CSLIP, ModBus.
Post by r***@gmail.com
[Roy]
If they want adopters then they'd better get a move on!
2. [UNSOLVED?] Libraries/examples: MODBUS RTU/Eth at the very least
ModBus is very straightforward to implement from scratch. There exist
commercial libraries of course, but you want it for free, I guess...
Post by r***@gmail.com
I have yet to find a repository of libraries covering the major protocols
(e.g. MODBUS, CAN, one-wire). There are quite a few in C. Would it be
viable to just wrap these in Ada?
It depends. Usually middle-layer transports like ModBus, CAN have no use
without integration into some middleware framework. It is a bad idea to
communicate directly to them from the application, even if through a vendor
library.

Then, regarding CAN, the real problems are in the configuration, e.g. DBC
parsing or handling CANOpen. It is a very complicated stuff, which would be
very difficult to handle in an application without a middleware abstracting
away the mess.

And all protocols have issues with polling/event handling policy, you
wouldn't burden the application with that.
Post by r***@gmail.com
It seems like a great short term
solution but if we are using Ada to make things more stable, it hardly
makes sense to use it merely to wrap (flakey) C libraries ;)
You will need lower-level vendor libraries, which are vendor (Vector, IXXAT
etc, I don't know what is the status of Linux CAN driver for ARM boards)
dependent and higher-level libraries implementing the upper-level protocols
like CANOpen.
Post by r***@gmail.com
I'd appreciate any further feedback from members of this list.
I would try to use a Linux instead of running bare board. Debian for ARM is
available. It has a fully working GNAT FSF. [We successfully ran our
middleware (100% Ada) on an ARM board.]

AFAIK, AdaCore offers a cross compiler to ARM Linux. (It is a pain to use
native ARM GNAT).
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Roy Emmerich
2014-08-27 13:35:19 UTC
Permalink
Hi Dmitry,

Thanks for your post. Please note that I reply with the utmost respect and humility. I have very little low level microcontroller experience but it is growing quickly as I get stuck into this stuff.

Having flown through this forum last night for the first time and checking your website, I noticed you have vast experience and accompanying strong opinions. That is not bad, just a bit difficult for some to digest :)

So with this background, I will attempt to probe a bit deeper. Please, no flame wars. I'm new, inexperienced but keen to learn and curious as to why you hold the opinions you do.

[Dmitry]
Post by Dmitry A. Kazakov
Basically it does not make sense to have a library
beyond system's port I/O driver, because higher-level protocols have
nothing in common, e.g. AK, CSLIP, ModBus.
[Roy]
Would you mind explaining what you mean in a bit more detail...for beginners?

[Dmitry]
Post by Dmitry A. Kazakov
ModBus is very straightforward to implement from scratch. There exist
commercial libraries of course, but you want it for free, I guess...
[Roy]
There are MANY implementations but I prefer reuse, allowing me to focus my efforts elsewhere. If I really can't find something then I will (reluctantly) roll my own.

[Dmitry]
Post by Dmitry A. Kazakov
Usually middle-layer transports like ModBus, CAN have no use
without integration into some middleware framework. It is a bad idea to
communicate directly to them from the application, even if through a vendor
library.
[Roy]
Why? It seems to be done in many other projects. Are they all wrong?

[Dmitry]
Post by Dmitry A. Kazakov
Then, regarding CAN, the real problems are in the configuration, e.g. DBC
parsing or handling CANOpen. It is a very complicated stuff, which would be
very difficult to handle in an application without a middleware abstracting
away the mess.
[Roy]
CANOpen is very complicated, I agree. The STM32F4 comes with built-in support for vanilla CAN which is exposed in this C driver:

https://github.com/espruino/Espruino/blob/master/targetlibs/stm32f4/lib/stm32f4xx_can.c

I thought a library was effectively that, a quasi 'middleware' abstracting away the messy stuff from the application?

[Dmitry]
Post by Dmitry A. Kazakov
And all protocols have issues with polling/event handling policy, you
wouldn't burden the application with that.
[Roy]
Why? One of the software layers has to take care of it somehow. If the library can take care of it, great!

[Dmitry]
Post by Dmitry A. Kazakov
You will need lower-level vendor libraries, which are vendor (Vector, IXXAT
etc, I don't know what is the status of Linux CAN driver for ARM boards)
dependent and higher-level libraries implementing the upper-level protocols
like CANOpen.
[Roy]
Lower level vendor libraries implemented in which language? From what I can see that will invariably be C. The STM32F4 comes with a bunch of them for low level access to the chip functionality, some of which I would very much like to use directly in my application.

Let's take an example of something I want to achieve soon, namely accurately synchronising the STM32F4 RTC with GPS time/time pulse. From what I have seen there are a few options to do this accurately:

1. The RTC calendar can be synchronized to a more precise, remote clock using the RTC shift feature (see page 19 of the ST RTC manual for more details):

STM Application note AN3371
Using the hardware real-time clock (RTC) in STM32 F0, F2, F3, F4 and L1 series of MCUs
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00025071.pdf


2. Use the "zero on write" method as described in the "Clock Synchronisation Methods" here:

http://hairy.geek.nz/projects/hardware-ntp-server/clock-synchronisation-methods/

3. Figure out RFC2783 and RFC1589 and hack something using the GPS time pulse signal (e.g. as used in the gpsd Linux project).

* http://tools.ietf.org/html/rfc2783
* http://tools.ietf.org/html/rfc1589
* http://git.savannah.gnu.org/cgit/gpsd.git/tree/ppsthread.c

If you take a look at the relevant STM C firmware to get access to the on-board RTC you will notice most of the hard work has already been done:

https://github.com/espruino/Espruino/blob/master/targetlibs/stm32f4/lib/stm32f4xx_rtc.c

I presume this could be rewritten in Ada but to get started why not just wrap this code and get cracking doing useful stuff?

If somebody could show me how to achieve this quickly and simply I'd be jumping around like a kid in a candy store!

[Dmitry]
Post by Dmitry A. Kazakov
I would try to use a Linux instead of running bare board. Debian for ARM is
available. It has a fully working GNAT FSF. [We successfully ran our
middleware (100% Ada) on an ARM board.]
[Roy]
This does sound very convenient! Thanks for the tip. However my aim is to create a device which can run on a small (e.g. 2000 mAh) lithium battery for weeks or months, depending on the connected peripherals and how they are used of course, with the option of including a solar panel and mini charge controller for operation completely independent of other power sources. My gut feeling tells me your solution would be somewhat more power hungry?

Without spending too much research effort, I took a look at the Raspberry Pi FAQ and found that running it on batteries would be a challenge to say the least:

http://www.raspberrypi.org/help/faqs/#powerBatteries

This intrepid fellow put a lot more effort into power saving:

http://www.daveakerman.com/?page_id=1294

Conclusion:

Assuming:

* each AA battery has 3000 mAh
* 70% efficiency
* 6 AAs (i.e. 18 Ah in total)
* using an more efficient switching regulator

Total run time = 28 hours [only!!!]

That's a lot of energy!

For my device I am aiming for an energy autonomy of 3 days at least. I'd have to use a pretty big battery!

Regards
Roy
---
www.infinitefingers.com
Dmitry A. Kazakov
2014-08-27 16:00:32 UTC
Permalink
Post by Roy Emmerich
[Dmitry]
Post by Dmitry A. Kazakov
Basically it does not make sense to have a library
beyond system's port I/O driver, because higher-level protocols have
nothing in common, e.g. AK, CSLIP, ModBus.
[Roy]
Would you mind explaining what you mean in a bit more detail...for beginners?
It was regarding the "comm libraries". What such a library might provide is
reading and writing raw bytes from a serial port. This is less than 1% of
functionality needed to communicate with the hardware. It is not their
purpose.

What AdaCore libraries are good for is that they provide an OS abstraction
layer, another example of such a library is the GNAT sockets library. They
allow you writing OS-independent implementation of specific protocol stacks
like ModBus. This is a great help not to underestimate, but it has nothing
to do with implementation of higher-level protocols. That will be your job.
Post by Roy Emmerich
[Dmitry]
Post by Dmitry A. Kazakov
ModBus is very straightforward to implement from scratch. There exist
commercial libraries of course, but you want it for free, I guess...
[Roy]
There are MANY implementations but I prefer reuse, allowing me to focus my
efforts elsewhere. If I really can't find something then I will
(reluctantly) roll my own.
I don't know what these implementations offer, usually very little, because
at this level (of OSI) you cannot have useful bindings without some
middleware framework.
Post by Roy Emmerich
[Dmitry]
Post by Dmitry A. Kazakov
Usually middle-layer transports like ModBus, CAN have no use
without integration into some middleware framework. It is a bad idea to
communicate directly to them from the application, even if through a vendor
library.
[Roy]
Why? It seems to be done in many other projects. Are they all wrong?
I know a lot of implementations of various industrial protocols stacks.
None of them you could use off-the-shelf. Not because they are bad, but
because of the nature of things.
Post by Roy Emmerich
[Dmitry]
Post by Dmitry A. Kazakov
Then, regarding CAN, the real problems are in the configuration, e.g. DBC
parsing or handling CANOpen. It is a very complicated stuff, which would be
very difficult to handle in an application without a middleware abstracting
away the mess.
[Roy]
CANOpen is very complicated, I agree. The STM32F4 comes with built-in
https://github.com/espruino/Espruino/blob/master/targetlibs/stm32f4/lib/stm32f4xx_can.c
That looks very basic, but at least there is a buffer for incoming frames.
A good CAN library provides:

1. callback for incoming frames with user data field. Polling CAN
controller buffer might a very expensive depending on the controller.

2. time stamping of the incoming frames. If you do some control or data
logging you need that.

3. means to reset the controller, e.g. the BUS HEAVY state.

4. frame filtering (handy if you have a heavy bus load and cleaning the
controller's buffer might very expensive, as I said)
Post by Roy Emmerich
I thought a library was effectively that, a quasi 'middleware' abstracting
away the messy stuff from the application?
No. The middleware like OPC, LabMap etc would abstract CAN as a set of
channels or process variables. When a CAN frame, considering it is a plain
CAN, comes its contents is split into process variables, these variables
are updated and the application can access them later. Similarly when an
application writes some variables that will have an effect of sending one
or series of CAN frames out with the IDs and data fields encoded as
required. This is a lot of work. There are semi-standard descriptions of
CAN frames built-up, e.g. Vector's DBC format or ASAP2 etc. You won't do
this in an application, each time.
Post by Roy Emmerich
[Dmitry]
Post by Dmitry A. Kazakov
And all protocols have issues with polling/event handling policy, you
wouldn't burden the application with that.
[Roy]
Why? One of the software layers has to take care of it somehow. If the
library can take care of it, great!
The library cannot take care of that. Such libraries (stacks) provide very
basic functionality, like transmitting and receiving CAN frames. This as
about much as reading/writing bytes from RS232 when you need to communicate
with a HTTP server over CSLIP.
Post by Roy Emmerich
[Dmitry]
Post by Dmitry A. Kazakov
You will need lower-level vendor libraries, which are vendor (Vector, IXXAT
etc, I don't know what is the status of Linux CAN driver for ARM boards)
dependent and higher-level libraries implementing the upper-level protocols
like CANOpen.
[Roy]
Lower level vendor libraries implemented in which language? From what I
can see that will invariably be C.
Yes, but this is no problem in most cases. BTW, the lower the level the
better. If the library starts playing things with threading you will be in
trouble soon.
Post by Roy Emmerich
Let's take an example of something I want to achieve soon, namely
accurately synchronising the STM32F4 RTC with GPS time/time pulse. From
I would not adjust clocks, controlling algorithms don't like clocks jumping
forth and back. You may consider translation of timestamps of incoming and
outgoing data according to the estimated clock skew. Usually it is less
offending for the rest of the system.
Post by Roy Emmerich
If you take a look at the relevant STM C firmware to get access to the
https://github.com/espruino/Espruino/blob/master/targetlibs/stm32f4/lib/stm32f4xx_rtc.c
I presume this could be rewritten in Ada but to get started why not just
wrap this code and get cracking doing useful stuff?
Yes. If you have a BSP (board support package) it is wasting time to
rewrite it in Ada. You can call C code directly from Ada, you don't even
need to wrap it.
Post by Roy Emmerich
If somebody could show me how to achieve this quickly and simply I'd be
jumping around like a kid in a candy store!
See:

http://www.ada-auth.org/standards/12rm/html/RM-B-3.html
Post by Roy Emmerich
[Dmitry]
Post by Dmitry A. Kazakov
I would try to use a Linux instead of running bare board. Debian for ARM is
available. It has a fully working GNAT FSF. [We successfully ran our
middleware (100% Ada) on an ARM board.]
[Roy]
This does sound very convenient! Thanks for the tip. However my aim is to
create a device which can run on a small (e.g. 2000 mAh) lithium battery
for weeks or months, depending on the connected peripherals and how they
are used of course, with the option of including a solar panel and mini
charge controller for operation completely independent of other power
sources. My gut feeling tells me your solution would be somewhat more
power hungry?
Power consumption was never a concern to us, but I don't see obvious
reasons why a bare board should consume sufficiently less than the same
board running Debian Linux.

[...]
Post by Roy Emmerich
Total run time = 28 hours [only!!!]
That's a lot of energy!
BTW, I don't know how much juice CAN requires, as I said, our applications
have no problems with power supply, but I guess that CAN eats pretty much.
If you have an external power supply for CAN, you could use it for the
board as well. I suggest you should do some math in order not to run into
problems later.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Dennis Lee Bieber
2014-08-27 13:08:07 UTC
Permalink
Post by r***@gmail.com
I don't have experience in C/C++ but I do have a lot of experience in Java, python, structured text (read PLCs) and a few other bits and pieces. I REALLY don't want to develop in C. From what I can make out it looks like a nightmare once the code reaches any substantial size, which mine will. I've started quite a few beginner C books and never got very far before throwing in the towel. However what I've read about Ada has certainly caused me to sit up!
Do you have any experience with assembler (any) -- since so much of C
mapped to the PDP series instruction set (pre/post increment/decrement
operators, for example).

C, itself, is a fairly small language -- it's main feature being also
its main problem: it assumes the programmer knows what they are doing and
offers easy access to (mis)treating data as addresses in memory.

If you are familiar with Java AND with disciplined software
development, a copy of the K&R book for C should be all you need to learn
the language itself (in my world, it was the even smaller first edition K&R
with my experience of FORTRAN, COBOL, Pascal, and Assembler -- circa 1982).

C++, OTOH... THAT is a nightmare language to pick up... Do NOT think of
it as just a more powerful C.
Post by r***@gmail.com
1. www.espruino.com (JavaScript)
Interpreted... And not even full Java... I've not looked at the link --
JavaScript is the "native" language for the BeagleBone Black, as I recall.
Post by r***@gmail.com
2. www.micropython.org
Interpreted (byte-code)...
Post by r***@gmail.com
3. www.eluaproject.net
Based on LUA?, probably interpreted.

All will require you to have an interpreter running on the board (you
are entering the world of the old BASIC Stamp and PICAxe chips -- PIC
variants with a byte-code interpreter running as the program, and your
program loaded into data memory; the Parallax Javelin didn't last long --
it had a Java interpreter on the chip, supposed to run regular Java byte
code).
Post by r***@gmail.com
1. It is not hard real-time
Few interpreted languages are... Especially if they have dynamic
behavior (that is, you can modify class methods on the fly).

"Real-Time Systems and Programming Languages" covers Ada, C with a
POSIX Real-Time package, and something titled "Real-Time Java"... Might be
of interest...
Post by r***@gmail.com
1. [IN PROGRESS] Easy communication: SPI, I2C, Serial, Ethernet,
[Mike]
I know that AdaCore is working on comms libraries for the ARM Cortex M parts, but I don't know anything about the projected availability.
[Roy]
If they want adopters then they'd better get a move on!
2. [UNSOLVED?] Libraries/examples: MODBUS RTU/Eth at the very least
I have yet to find a repository of libraries covering the major protocols (e.g. MODBUS, CAN, one-wire). There are quite a few in C. Would it be viable to just wrap these in Ada? It seems like a great short term solution but if we are using Ada to make things more stable, it hardly makes sense to use it merely to wrap (flakey) C libraries ;)
I suspect a lot of those are being developed by companies for
proprietary products, possibly using some internal core "OS" for
interfacing between application code and the board support layer. As a
result, even if one got their hands on the driver source, one would have to
replicate the OS environment to make use of it. At work, I believe the
common route is to use IOCTL() calls to manipulate the hardware specific
drivers, leaving a common POSIX (?) interface to C, and wrapping the C
calls for Ada (if not directly wrapping the assembler entry point to the
same functionality).
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Roy Emmerich
2014-08-27 15:44:41 UTC
Permalink
Hi Dennis,

Thanks for your reply. I'm curious to know how/why you opted for your message not to be archived on this forum?
Post by Dennis Lee Bieber
Do you have any experience with assembler (any) -- since so much of C
mapped to the PDP series instruction set (pre/post increment/decrement
operators, for example).
Unfortunately I don't have any assembler experience. It strikes me as even more hairy than C! Something left to those forced to do it under duress or the few for whom this excites. If I had to ever programme in Assembler I would want to keep it to the absolute, absolute minimum. Dare I ask you to recommended some learning materials?
Post by Dennis Lee Bieber
If you are familiar with Java AND with disciplined software
development, a copy of the K&R book for C should be all you need to learn
the language itself.
Thanks for this tip. I think I will start learning it again as I have the hunch it'll be impossible to avoid entirely :)
Post by Dennis Lee Bieber
Post by r***@gmail.com
3. www.eluaproject.net
Based on LUA?, probably interpreted.
Yes it is based on LUA and it looks interpreted. I have played with this the least.
Post by Dennis Lee Bieber
I suspect a lot of those are being developed by companies for
proprietary products, possibly using some internal core "OS" for
interfacing between application code and the board support layer. As a
result, even if one got their hands on the driver source, one would have to
replicate the OS environment to make use of it. At work, I believe the
common route is to use IOCTL() calls to manipulate the hardware specific
drivers, leaving a common POSIX (?) interface to C, and wrapping the C
calls for Ada (if not directly wrapping the assembler entry point to the
same functionality).
Ummm I think I understood you...

All 3 of the projects I listed are using the STM32F4 direct, without any OS. The chip was released with a bunch of C drivers to access I/O and the various on-board peripherals (i.e. in the chip). You can take a look at them here:

https://github.com/espruino/Espruino/tree/master/targetlibs/stm32f4/lib

Regards
Roy
---
www.infinitefingers.com
Dennis Lee Bieber
2014-08-28 01:37:15 UTC
Permalink
On Wed, 27 Aug 2014 08:44:41 -0700 (PDT), Roy Emmerich
Post by Roy Emmerich
Hi Dennis,
Thanks for your reply. I'm curious to know how/why you opted for your message not to be archived on this forum?
Ancient history... Many moons ago, most Usenet servers expired posts on
some regular schedule (text groups may have gone a month to a year
depending on traffic; some of the heavier binary image groups expired in
less than three days -- miss a day and you might really miss a day worth of
traffic).

Then came Google with their "archive for the ages"... No chance to have
the world forget things one had posted... Shortly thereafter the extension
header x-noarchive was implemented. I chose to have my client embed that
header.
Post by Roy Emmerich
Unfortunately I don't have any assembler experience. It strikes me as even more hairy than C! Something left to those forced to do it under duress or the few for whom this excites. If I had to ever programme in Assembler I would want to keep it to the absolute, absolute minimum. Dare I ask you to recommended some learning materials?
Unfortunately, it tends to be specific to the processor chip -- I'm
presently going through a book on the ARM Cortex-M (and while the R in ARM
started life as RISC, it looks like CISC instruction set compared to my
college mainframe in the 70s); I have a book a few books on PIC chips lying
around, and maybe one on AVR).

I don't even want to think about modern CISC processors. The old
Blacksburg "Bug" books are obsolete if one could find them...

However, if you really need responsive device drivers, you'll probably
end up in assembly at some stage; there are things that not even low-level
C allows easy access to...
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Roy Emmerich
2014-08-27 16:03:28 UTC
Permalink
Hi again Dennis,
Post by Dennis Lee Bieber
I suspect a lot of those are being developed by companies for
proprietary products, possibly using some internal core "OS" for
interfacing between application code and the board support layer.
Actually no. All of them are open source, community powered projects.

Espruino and Micro Python are being developed by two very bright individuals, both running their operations as a one-man-band, making use of ever growing communities of users to help them.

Gordon Williams is creating Espruino and was funded by a very successful Kickstarter campaign (£100710):

https://www.kickstarter.com/projects/gfw/espruino-javascript-for-things

Damien George is creating Micro Python and was also funded by an equally successful Kickstarter campaign (£97803):

https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers

Copy and paste from the eLua site:
----------------------------------
eLua is a joint project of Bogdan Marinescu, a software developer from Bucharest and Romania Dado Sutter, head of the Led Lab at PUC-Rio University, in Rio de Janeiro, Brazil.
Its origins come from the ReVaLuaTe project, also developed by Bogdan Marinescu (as a contest entry for the 2005 Renesas M16C Design Contest), and the Volta Project, managed by Dado Sutter at PUC-Rio from 2005 to 2007.

eLua is developed in a fully open, distributed and worldwide collaborative model. An ever-growing list of collaborators, from all over the planet, which are also authors of some modules and features, can be found in our Credits Page.


So as you can see this is a VERY different development model to the one Ada is used to. These are people with substantial experience using C and who basically got fed up and wanted an easier way to interface with hardware.

What I find very interesting is they are challenging previously accepted 'norms' and willing to try something new.

I'm trying to select the right path for what I want to do and am also willing to walk the road less travelled.
Dennis Lee Bieber
2014-08-28 01:48:59 UTC
Permalink
On Wed, 27 Aug 2014 09:03:28 -0700 (PDT), Roy Emmerich
Post by Roy Emmerich
Hi again Dennis,
Post by Dennis Lee Bieber
I suspect a lot of those are being developed by companies for
proprietary products, possibly using some internal core "OS" for
interfacing between application code and the board support layer.
Actually no. All of them are open source, community powered projects.
I wasn't referring to the three you mentioned -- but rather to your
plaint that you wanted libraries for accessing various communications
devices, etc.

THOSE libraries are probably being written for proprietary products in
support of a higher level (though still minimal) OS --
http://en.wikipedia.org/wiki/Integrated_modular_avionics -- The OS is in C
or Ada, the processor board is provided with a board support package (BSP)
that handles extremely low hardware access (driving GPIO,
enabling/disabling memory management, other stuff), and libraries/drivers
are written to provide an interface between the OS and the BSP. The BSP
tends to come from the board manufacturer, the OS from somewhere else
(Windriver, for example, or home-grown). By writing a new driver layer it
is possible to rebuild the OS/applications on a new processor board without
making changes to the high layers.

But those driver layers tend to only be useful in the environment (the
application/OS) above them.
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Roy Emmerich
2014-08-28 10:12:16 UTC
Permalink
Post by Dennis Lee Bieber
I wasn't referring to the three you mentioned -- but rather to your
plaint that you wanted libraries for accessing various communications
devices, etc.
THOSE libraries are probably being written for proprietary products in
support of a higher level (though still minimal) OS --
http://en.wikipedia.org/wiki/Integrated_modular_avionics -- The OS is in C
or Ada, the processor board is provided with a board support package (BSP)
that handles extremely low hardware access (driving GPIO,
enabling/disabling memory management, other stuff), and libraries/drivers
are written to provide an interface between the OS and the BSP. The BSP
tends to come from the board manufacturer, the OS from somewhere else
(Windriver, for example, or home-grown). By writing a new driver layer it
is possible to rebuild the OS/applications on a new processor board without
making changes to the high layers.
But those driver layers tend to only be useful in the environment (the
application/OS) above them.
I have just read that Wikipedia link you sent. Wow! This is very high end stuff. I am not intending to control planes with my project.

My concept is actually very simple. Please, allow me to briefly explain:

I want to use a finite state machine (FSM) approach. There will be a supervisor module which will instantiate sub-modules which communicate with peripherals. Each sub-module will be a separate sub-FSM, reporting its state to the supervisor. Each sub-module will make use of a protocol library (e.g. MODBUS RTU) and a hardware driver library (e.g. UART over RS485/232) to communicate with devices.

That is it. No OS, no middleware.

I realise my approach probably goes against the grain of many classically trained computer scientists using Ada for highly critical systems. I'm largely self-taught and want to develop something quickly and simply for a very specific niche market a couple of levels above the tinkerer.
Dmitry A. Kazakov
2014-08-28 13:00:12 UTC
Permalink
Post by Roy Emmerich
I want to use a finite state machine (FSM) approach. There will be a
supervisor module which will instantiate sub-modules which communicate
with peripherals. Each sub-module will be a separate sub-FSM, reporting
its state to the supervisor. Each sub-module will make use of a protocol
library (e.g. MODBUS RTU) and a hardware driver library (e.g. UART over
RS485/232) to communicate with devices.
That is it. No OS, no middleware.
It is difficult to imagine working. Do you know how ModBus function? It is
basically a client-server protocol. You send a request, e.g. F15 and then
read the response. Whether the request is a read or write request does not
matter. Most of ModBus end devices are half-duplex. Which means one request
at a time. Many have internal cycles and interlocking which make things
much slower than the physical I/O already did. Some would crash if you
queried too frequently.

Anyway, without an OS you will have to wait for the response to come, which
in turn, will block the whole application. It will be extremely slow.

One of the responsibilities of the OS and the middleware is to perform I/O
on things like ModBus in background without blocking the application and
other I/O. Even a very lame board is usually much faster than any ModBus
terminal.

In short, an OS-less design is not suitable for handling many peripheral
devices simultaneously, especially when the devices are attached over slow
asynchronous communication channels.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Mike Silva
2014-08-28 16:28:15 UTC
Permalink
Post by Dmitry A. Kazakov
Post by Roy Emmerich
I want to use a finite state machine (FSM) approach. There will be a
supervisor module which will instantiate sub-modules which communicate
with peripherals. Each sub-module will be a separate sub-FSM, reporting
its state to the supervisor. Each sub-module will make use of a protocol
library (e.g. MODBUS RTU) and a hardware driver library (e.g. UART over
RS485/232) to communicate with devices.
That is it. No OS, no middleware.
It is difficult to imagine working. Do you know how ModBus function? It is
basically a client-server protocol. You send a request, e.g. F15 and then
read the response. Whether the request is a read or write request does not
matter. Most of ModBus end devices are half-duplex. Which means one request
at a time. Many have internal cycles and interlocking which make things
much slower than the physical I/O already did. Some would crash if you
queried too frequently.
Anyway, without an OS you will have to wait for the response to come, which
in turn, will block the whole application. It will be extremely slow.
One of the responsibilities of the OS and the middleware is to perform I/O
on things like ModBus in background without blocking the application and
other I/O. Even a very lame board is usually much faster than any ModBus
terminal.
Maybe there is some confusion being caused by the term "OS" here. Ada's concurrency and realtime functionality can run on top of an OS, but it can also run on bare metal (an "invisible" OS?). The GNAT ARM Cortex M release does have Ravenscar tasking on bare metal.
Post by Dmitry A. Kazakov
In short, an OS-less design is not suitable for handling many peripheral
devices simultaneously, especially when the devices are attached over slow
asynchronous communication channels.
How could this be reworded to remove the "OS"? A single-task or single-thread design is not suitable...?
Roy Emmerich
2014-08-28 17:03:31 UTC
Permalink
Post by Mike Silva
Maybe there is some confusion being caused by the term "OS" here. Ada's
concurrency and realtime functionality can run on top of an OS, but it can also
run on bare metal (an "invisible" OS?). The GNAT ARM Cortex M release does
have Ravenscar tasking on bare metal.
Thanks for chiming in here Mike. I was getting a bit worried, thinking I'd misunderstood all I'd read about Ada being able to natively run concurrent processes on the Cortex M.
Post by Mike Silva
How could this be reworded to remove the "OS"? A single-task or single-thread design is not suitable...?
To get around the threading problem, a fellow collaborator (read C junkie) is trying out one of the free C RTOSs (www.chibios.org) and is starting to make some progress, although it has been tough going! Just getting a blinking LED took 3 days! Admittedly it was his first experience with an RTOS and setting up an open source toolchain.

I take back what I said about JavaScript and loads of libraries! Today I tried to quickly get MODBUS communication going and failed. I couldn't find a single one to use as a MODBUS RTU master :(

I must admit that I'm in a lot of doubt about the right way forward.
Dmitry A. Kazakov
2014-08-28 20:09:05 UTC
Permalink
Post by Mike Silva
Post by Dmitry A. Kazakov
One of the responsibilities of the OS and the middleware is to perform I/O
on things like ModBus in background without blocking the application and
other I/O. Even a very lame board is usually much faster than any ModBus
terminal.
Maybe there is some confusion being caused by the term "OS" here. Ada's
concurrency and realtime functionality can run on top of an OS, but it can
also run on bare metal (an "invisible" OS?).
Not really. OS is more than tasking, it is also a queueing mechanism, which
allows waiting for I/O completion in one task without blocking all other
tasks.
Post by Mike Silva
The GNAT ARM Cortex M
release does have Ravenscar tasking on bare metal.
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
Post by Mike Silva
Post by Dmitry A. Kazakov
In short, an OS-less design is not suitable for handling many peripheral
devices simultaneously, especially when the devices are attached over slow
asynchronous communication channels.
How could this be reworded to remove the "OS"? A single-task or
single-thread design is not suitable...?
A design without a mechanism of postponing and synchronization to multiple
I/O events.

The most simple case is when a task can be blocked until the event happens.

Alternatively it could be an asynchronous system trap. That is when the
task is interrupted upon an I/O event. Such an event-driven schema may
deploy single task. It is frequently used in GUI design and is sufficiently
more difficult to use. It would still require an OS for switching contexts.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
e***@scriptoriumdesigns.com
2014-08-28 20:34:58 UTC
Permalink
Post by Dmitry A. Kazakov
Not really. OS is more than tasking, it is also a queueing mechanism, which
allows waiting for I/O completion in one task without blocking all other
tasks.
......
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
Are you saying that a full Ada implementation on bare metal could not implement an equivalent of I/O queueing?

Or are you saying that Ravenscar tasking on bare metal could not implement such queueing?
Dmitry A. Kazakov
2014-08-29 07:34:06 UTC
Permalink
On Thu, 28 Aug 2014 13:34:58 -0700 (PDT),
Post by e***@scriptoriumdesigns.com
Post by Dmitry A. Kazakov
Not really. OS is more than tasking, it is also a queueing mechanism, which
allows waiting for I/O completion in one task without blocking all other
tasks.
......
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
Are you saying that a full Ada implementation on bare metal could not
implement an equivalent of I/O queueing?
You could, but that would be equivalent to writing a small OS.
Post by e***@scriptoriumdesigns.com
Or are you saying that Ravenscar tasking on bare metal could not implement such queueing?
Ravenscar tasking profile has serious constraints preventing this. The
nature of the constraints is to statically ensure schedulability. Asking
that much you must pay the price...
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Niklas Holsti
2014-08-29 15:59:49 UTC
Permalink
Post by Dmitry A. Kazakov
Ravenscar tasking profile has serious constraints preventing this. The
nature of the constraints is to statically ensure schedulability.
That's what they (= the people whoe defined the profile) often say, but
it is not quite true. Even within Ravenscar constraints, one can build
very dynamic task interactions, which is nice for implementing stuff in
a Ravenscar system, but which makes schedulability analysis difficult.

To ensure simple schedulability analysis, Ravenscar must be supplemented
with further strong design rules, for example limiting each task to have
a single point of suspension, on a single protected object. _Those_
rules can become really nasty from the designer's point of view.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Simon Clubley
2014-08-29 16:59:35 UTC
Permalink
Post by Niklas Holsti
Post by Dmitry A. Kazakov
Ravenscar tasking profile has serious constraints preventing this. The
nature of the constraints is to statically ensure schedulability.
That's what they (= the people whoe defined the profile) often say, but
it is not quite true. Even within Ravenscar constraints, one can build
very dynamic task interactions, which is nice for implementing stuff in
a Ravenscar system, but which makes schedulability analysis difficult.
I have got to ask: how did Ravenscar ever get chosen for an Ada meeting
place ?

I can understand a place like (say) York, or another university town/city,
but of all the places on the planet, how did a little coastal "town
that never was" ever get chosen for an Ada meeting ?

One very curious person,

Simon.

PS: I'm from Yorkshire so I know the area well and I have also walked
through Ravenscar while doing a walk so I know the place personally.
--
Simon Clubley, ***@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Niklas Holsti
2014-08-29 17:18:40 UTC
Permalink
Post by Simon Clubley
Post by Niklas Holsti
Post by Dmitry A. Kazakov
Ravenscar tasking profile has serious constraints preventing this. The
nature of the constraints is to statically ensure schedulability.
That's what they (= the people whoe defined the profile) often say, but
it is not quite true. Even within Ravenscar constraints, one can build
very dynamic task interactions, which is nice for implementing stuff in
a Ravenscar system, but which makes schedulability analysis difficult.
I have got to ask: how did Ravenscar ever get chosen for an Ada meeting
place ?
I don't know... but I have another follow-on question: how is
"Ravenscar" pronounced locally? Does it start like "ray", or like
"Rachmaninoff"?
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Simon Clubley
2014-08-29 17:31:19 UTC
Permalink
Post by Niklas Holsti
Post by Simon Clubley
I have got to ask: how did Ravenscar ever get chosen for an Ada meeting
place ?
I don't know... but I have another follow-on question: how is
"Ravenscar" pronounced locally? Does it start like "ray", or like
"Rachmaninoff"?
I pronounce it as Ray-ven-scar amd I've never heard anyone pronounce
it in a different way. (However, it's such a little place I don't
have much reason to bring it up in normal conversation so there might
be variants I am unaware of.)

Simon.
--
Simon Clubley, ***@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Dennis Lee Bieber
2014-08-30 14:55:13 UTC
Permalink
On Fri, 29 Aug 2014 17:31:19 +0000 (UTC), Simon Clubley
Post by Simon Clubley
Post by Niklas Holsti
Post by Simon Clubley
I have got to ask: how did Ravenscar ever get chosen for an Ada meeting
place ?
I don't know... but I have another follow-on question: how is
"Ravenscar" pronounced locally? Does it start like "ray", or like
"Rachmaninoff"?
I pronounce it as Ray-ven-scar amd I've never heard anyone pronounce
it in a different way. (However, it's such a little place I don't
have much reason to bring it up in normal conversation so there might
be variants I am unaware of.)
Ah, good... I've not been mispronouncing it... though my confusion was
between <blackbird> scar and <blackbirds> car... Considering how many
locations have condensed the old "caer" down to "car". "Ravens Castle"
might have been viable <G>
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Jeffrey Carter
2014-08-29 17:59:53 UTC
Permalink
Post by Simon Clubley
PS: I'm from Yorkshire so I know the area well and I have also walked
through Ravenscar while doing a walk so I know the place personally.
Perhaps being from Yorkshire explains such idiosyncratic usage as "Bringing you
1980s technology to a 21st century world" :)
--
Jeff Carter
"I didn't squawk about the steak, dear. I
merely said I didn't see that old horse
that used to be tethered outside here."
Never Give a Sucker an Even Break
103
Randy Brukardt
2014-08-29 23:30:47 UTC
Permalink
...
Post by Simon Clubley
I have got to ask: how did Ravenscar ever get chosen for an Ada meeting
place ?
I can understand a place like (say) York, or another university town/city,
but of all the places on the planet, how did a little coastal "town
that never was" ever get chosen for an Ada meeting ?
I don't have any knowledge of how IRTAW picks it's meeting sites, but they
do seem to pick smaller places for their meetings. I presume it was close to
whoever was organizing it (probably someone from York).

Even ARG meetings have been held in some pretty weird places. There was one
(before my time) held in Bennington, Vermont. And one held in Sydney,
Canada. (Not to mention Madison, Wisconsin, but that doesn't seem weird to
me. ;-) We've also met in Kemah, Texas, as well as Leuven, Belgium and
Malloca, Spain, the latter of which I had to ask where the heck it was. (The
former, I didn't have to ask because the meeting announcement included
travel instructions.)

So unusual places aren't that unusual for Ada meetings, especially when one
uses the names of suburbs rather than the nearby city.

Randy.
Peter Chapin
2014-08-30 12:36:53 UTC
Permalink
Post by Randy Brukardt
Even ARG meetings have been held in some pretty weird places. There was one
(before my time) held in Bennington, Vermont.
Bennington? Weird? No way!

(Disclaimer... I live in Vermont)

Peter
Simon Clubley
2014-08-30 11:25:26 UTC
Permalink
Post by Randy Brukardt
Post by Simon Clubley
I have got to ask: how did Ravenscar ever get chosen for an Ada meeting
place ?
I can understand a place like (say) York, or another university town/city,
but of all the places on the planet, how did a little coastal "town
that never was" ever get chosen for an Ada meeting ?
I don't have any knowledge of how IRTAW picks it's meeting sites, but they
do seem to pick smaller places for their meetings. I presume it was close to
whoever was organizing it (probably someone from York).
That makes more sense if it was something organised by someone living
in Yorkshire. I had gained the impression it was something organised
by someone more distant like yourself.

Still, there's lots of other nice places in Yorkshire it _could_ have
been held (I've walked through a good number of them :-)) so this
location was obviously of personal interest to someone.

Thanks for the above info, Randy.

Simon.
--
Simon Clubley, ***@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Phil Thornley
2014-08-31 11:09:45 UTC
Permalink
[...]
Post by Simon Clubley
Post by Randy Brukardt
I don't have any knowledge of how IRTAW picks it's meeting sites, but they
do seem to pick smaller places for their meetings. I presume it was close to
whoever was organizing it (probably someone from York).
Yes, the workshop was chaired by Andy Wellings, with Alan Burns also
heavily involved.
[...]
Post by Simon Clubley
Still, there's lots of other nice places in Yorkshire it _could_ have
been held (I've walked through a good number of them :-)) so this
location was obviously of personal interest to someone.
Well, it was a large enough hotel to accommodate all the attendees, but
without any nearby distractions to divert their attention (although I
did take a walk to Robin Hood's Bay one afternoon).

Cheers,

Phil


--- news://freenews.netfront.net/ - complaints: ***@netfront.net ---
Dirk Craeynest
2014-08-31 18:37:45 UTC
Permalink
[ My earlier follow-up never appeared in comp.lang.ada, so I'm sending
this again... -- dc ]
Post by Randy Brukardt
Post by Simon Clubley
I have got to ask: how did Ravenscar ever get chosen for an Ada
meeting place ?
I can understand a place like (say) York, or another university
town/city, but of all the places on the planet, how did a little
coastal "town that never was" ever get chosen for an Ada meeting ?
I don't have any knowledge of how IRTAW picks it's meeting sites,
but they do seem to pick smaller places for their meetings.
I presume it was close to whoever was organizing it (probably
someone from York).
[...]
Post by Randy Brukardt
Randy.
The International Real-Time Ada Workshop (IRTAW) is indeed
traditionally held at a "remote location".

For some background on the structure and location of those workshops,
I refer to John Barnes' report "Some Impressions from IRTAW 11",
published quite some time ago in the Ada User Journal [1] (AUJ,
Volume 23, Number 2, June 2002, pages 97-99).

The introduction includes:

-------
Incidentally, the structure established by those early workshops
has remained. Each day is divided into two sessions with a long
midday break so that the second session works on into the evening.
This has a number of advantages. Attendees can take a long walk or
do other physical exercise in the afternoon - the theory being that
they can revitalise their mental powers by taking exercise and perhaps
ponder matters with colleagues as they do so. It also means that by
keeping on right up to dinner, there is no risk of frittering away
the time in the bar before dinner. It has also been a tradition to
hold the workshops in remote places so that attendees are not tempted
to skive off to local museums or places of unhealthy entertainment.
-------

and further:

-------
The sixth and eighth workshops were held at another remote hamlet,
namely, Ravenscar in Yorkshire; the dates were September 1992 and
April 1997 respectively. An important outcome of the second of these
was the Ravenscar profile which identifies facilities suitable for
safety-critical and other high integrity systems.
-------

A PDF version of AUJ 23-2 is available in Ada-Europe's Online AUJ
Archive [2]. The article mentioned above starts at page 25 of
that PDF.

[1] <http://www.ada-europe.org/auj/home/>
[2] <http://www.ada-europe.org/archive/auj/auj-23-2.pdf>

HTH

Dirk
***@cs.kuleuven.be (for Ada-Belgium/-Europe/SIGAda/WG9 mail)

*** 20th Intl.Conf.on Reliable Software Technologies - Ada-Europe'2015
*** June 22-26, 2015 **** Madrid, Spain **** http://www.ada-europe.org
Simon Clubley
2014-08-31 19:38:56 UTC
Permalink
Post by Dirk Craeynest
The International Real-Time Ada Workshop (IRTAW) is indeed
traditionally held at a "remote location".
That's interesting; I never considered the remote location was by
deliberate choice.
Post by Dirk Craeynest
A PDF version of AUJ 23-2 is available in Ada-Europe's Online AUJ
Archive [2]. The article mentioned above starts at page 25 of
that PDF.
[1] <http://www.ada-europe.org/auj/home/>
[2] <http://www.ada-europe.org/archive/auj/auj-23-2.pdf>
Thanks; I've downloaded a copy.
Post by Dirk Craeynest
HTH
Oh yes it certainly does. Thanks a lot to you and the other replies.

Simon.
--
Simon Clubley, ***@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Mike Silva
2014-08-29 17:24:23 UTC
Permalink
Post by Dmitry A. Kazakov
On Thu, 28 Aug 2014 13:34:58 -0700 (PDT),
Post by e***@scriptoriumdesigns.com
Are you saying that a full Ada implementation on bare metal could not
implement an equivalent of I/O queueing?
You could, but that would be equivalent to writing a small OS.
This is certainly the case - a complete Ada runtime is more complex than e.g. a complete C runtime, but it doesn't have to be built on an OS, and for smaller systems a bare-metal implementation is often going to be more attractive. Interestingly, the original Lego Mindstorms Ada port was built on an RTOS, but later they switched over to bare metal.
Post by Dmitry A. Kazakov
Post by e***@scriptoriumdesigns.com
Or are you saying that Ravenscar tasking on bare metal could not implement
such queueing?
Ravenscar tasking profile has serious constraints preventing this. The
nature of the constraints is to statically ensure schedulability. Asking
that much you must pay the price...
That brings up two points relevant to this thread. One is to find out from AdaCore how much more capability, if any, their current ARM Cortex M runtime actually has beyond the Ravenscar constraints. I'd like to find that out.

Second is a brief comment I received from AdaCore, that they are looking at another tasking subset that removes some of the Ravenscar limitations while still allowing a small and fast bare-metal tasking implementation. In my own words, I think they are looking for another sweet spot re functionaliy vs runtime complexity, one that will be useful to designers not requiring the guarantees that Ravenscar allows. It makes a lot of sense to think that there could be other beneficial tasking/runtime profiles besides just Ravenscar and full Ada.
Randy Brukardt
2014-08-29 23:35:48 UTC
Permalink
"Mike Silva" <***@gmail.com> wrote in message news:9620b2bd-9275-4273-b7ef-***@googlegroups.com...
...
Post by Mike Silva
Second is a brief comment I received from AdaCore, that they are looking at
another tasking subset that removes some of the Ravenscar limitations while
still allowing a small and fast bare-metal tasking implementation. In my
own
words, I think they are looking for another sweet spot re functionaliy vs
runtime
complexity, one that will be useful to designers not requiring the
guarantees that
Ravenscar allows. It makes a lot of sense to think that there could be
other
beneficial tasking/runtime profiles besides just Ravenscar and full Ada.
I know IRTAW (the people who designed Ravenscar in the first place) are
considering a project like that. So that might not turn out to be an
AdaCore-only thing, but rather an Ada thing.

Randy.
Dennis Lee Bieber
2014-08-29 13:06:38 UTC
Permalink
On Thu, 28 Aug 2014 13:34:58 -0700 (PDT),
Post by e***@scriptoriumdesigns.com
Post by Dmitry A. Kazakov
Not really. OS is more than tasking, it is also a queueing mechanism, which
allows waiting for I/O completion in one task without blocking all other
tasks.
......
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
Are you saying that a full Ada implementation on bare metal could not implement an equivalent of I/O queueing?
Or are you saying that Ravenscar tasking on bare metal could not implement such queueing?
Have you looked at the list of restrictions that profile requires?

Max_Task_Entries = 0 (which goes along with)
No_Select_Statements

Max_Protected_Entries = 1 (effectively no queuing up for access to
protected objects by multiple tasks)
Simple_Barriers (plain T/F Boolean variable controlling entries)

No_Relative_Delays (no "delay n" only "delay until m")

Oh, and No_Abort_Statements (and a number of other restrictions)

It works if the entire system including the "user application" level is
built "as one". It is NOT a very dynamic arrangement wherein you may plug
in a new sensor and have it magically install itself to some list of
sensors to be reported.
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Niklas Holsti
2014-08-29 16:52:44 UTC
Permalink
Post by Dmitry A. Kazakov
On Thu, 28 Aug 2014 13:34:58 -0700 (PDT),
Post by e***@scriptoriumdesigns.com
Post by Dmitry A. Kazakov
Not really. OS is more than tasking, it is also a queueing mechanism, which
allows waiting for I/O completion in one task without blocking all other
tasks.
......
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
Are you saying that a full Ada implementation on bare metal could
not implement an equivalent of I/O queueing?
Or are you saying that Ravenscar tasking on bare metal could not implement such queueing?
Have you looked at the list of restrictions that profile requires?
Max_Task_Entries = 0 (which goes along with)
No_Select_Statements
Max_Protected_Entries = 1 (effectively no queuing up for access to
protected objects by multiple tasks)
Simple_Barriers (plain T/F Boolean variable controlling entries)
No_Relative_Delays (no "delay n" only "delay until m")
Oh, and No_Abort_Statements (and a number of other restrictions)
All Ravenscar restrictions are on the _tasking_ system, with the
exception of No_Implicit_Heap_Allocation and forbidding the use of
Ada.Calendar (but _explicit_ heap allocation remains possible).

The rest of Ada remains in its full form.

However, some Ravenscar run-time systems _also_ have other restrictions,
for example limitations on the use of unconstrained array types in
expressions.
Post by Dmitry A. Kazakov
It works if the entire system including the "user application" level is
built "as one".
That same restriction holds for all standard Ada programs (with the
possible exception of distributed programs -- I have no experience
there). At bind time, all the compilation modules forming the program
are identified and included in the program, and no other modules/code
can be added later, unless the program dynamically links to plug-in
libraries, which is not standard Ada.
Post by Dmitry A. Kazakov
It is NOT a very dynamic arrangement wherein you may plug
in a new sensor and have it magically install itself to some list of
sensors to be reported.
It is certainly possible to write a Ravenscar program in which adding a
new sensor can be done by adding a single line, "with My_New_Sensor", to
the main subprogram. At elaboration time, My_New_Sensor can install its
tasks and protected objects in the application's data structures. No
problem.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Shark8
2014-08-31 00:49:23 UTC
Permalink
Post by Niklas Holsti
It is certainly possible to write a Ravenscar program in which adding a
new sensor can be done by adding a single line, "with My_New_Sensor", to
the main subprogram. At elaboration time, My_New_Sensor can install its
tasks and protected objects in the application's data structures. No
problem.
Very nice solution / rebuttal.
Niklas Holsti
2014-08-28 21:17:12 UTC
Permalink
Post by Dmitry A. Kazakov
Post by Mike Silva
Post by Dmitry A. Kazakov
One of the responsibilities of the OS and the middleware is to perform I/O
on things like ModBus in background without blocking the application and
other I/O. Even a very lame board is usually much faster than any ModBus
terminal.
Maybe there is some confusion being caused by the term "OS" here. Ada's
concurrency and realtime functionality can run on top of an OS, but it can
also run on bare metal (an "invisible" OS?).
Not really. OS is more than tasking, it is also a queueing mechanism, which
allows waiting for I/O completion in one task without blocking all other
tasks.
Post by Mike Silva
The GNAT ARM Cortex M
release does have Ravenscar tasking on bare metal.
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
It is certainly possible to implement an I/O request queue in Ravenscar;
I have done so for the platform SW on ESA's GOCE satellite. Multiple
client tasks, one server (interface driver) task. An I/O request
contains (or is, or refers to) a client-specific protected object (PO)
with an "I/O completed" entry, on which the client task waits after
enqueueing the I/O request. The server task processes submitted I/O
requests in any order and concurrency it chooses; when an I/O request is
done, the server task calls an operation on the request's PO, which
unblocks the entry, resuming the client task.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Roy Emmerich
2014-08-29 00:07:20 UTC
Permalink
Post by Niklas Holsti
Post by Dmitry A. Kazakov
Post by Mike Silva
Post by Dmitry A. Kazakov
One of the responsibilities of the OS and the middleware is to perform I/O
on things like ModBus in background without blocking the application and
other I/O. Even a very lame board is usually much faster than any ModBus
terminal.
Maybe there is some confusion being caused by the term "OS" here. Ada's
concurrency and realtime functionality can run on top of an OS, but it can
also run on bare metal (an "invisible" OS?).
Not really. OS is more than tasking, it is also a queueing mechanism, which
allows waiting for I/O completion in one task without blocking all other
tasks.
Post by Mike Silva
The GNAT ARM Cortex M
release does have Ravenscar tasking on bare metal.
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
It is certainly possible to implement an I/O request queue in Ravenscar;
I have done so for the platform SW on ESA's GOCE satellite. Multiple
client tasks, one server (interface driver) task. An I/O request
contains (or is, or refers to) a client-specific protected object (PO)
with an "I/O completed" entry, on which the client task waits after
enqueueing the I/O request. The server task processes submitted I/O
requests in any order and concurrency it chooses; when an I/O request is
done, the server task calls an operation on the request's PO, which
unblocks the entry, resuming the client task.
As I know (almost) nothing about Ravenscar I decided to go reading and found the following article:

Guide for the use of the Ada Ravenscar Profile in high integrity systems
http://www.sigada.org/ada_letters/jun2004/ravenscar_article.pdf

In the following sections:

2.1.1 Tasks Characteristics
2.1.2 Scheduling Model

it very clearly describes what Niklas has pointed out.

To go a little deeper into my design:

Each sub-module will run in its own task with its own timer. If, for example, I am monitoring a solar photovoltaic inverter via MODBUS RTU, it is possible to retrieve a lot of different information. Some information, like voltage and current, I may want to retrieve every second whereas other information like battery temperature I may only want to retrieve every 5 minutes. The module will know the sampling frequency for each variable to be monitored and will trigger itself when it is time to do so.

Using protected objects and hard/firm/soft/non-critical tasks it sounds like this could indeed be a viable approach.

---
Roy Emmerich
www.infinitefingers.com
Niklas Holsti
2014-08-29 17:58:32 UTC
Permalink
Post by Roy Emmerich
Each sub-module will run in its own task with its own timer.
Hmm. I would probably not design it that way, but of course I don't know
all your requirements or plans.

To me, the modular aspect and the tasking/timing aspect should be
orthogonal and (nearly) independent aspects of the design.

I would describe a (functional) module as some coherent, inter-related
set of state variables, and operations which use and update the state
variables. The module does not necessarily have tasks of its own.

A task, on the other hand, defines a time-line of activations of
operations in (usually) several modules, which require similar or
synchronised timing, sequencing, or periodic execution.

In my experience, in a real-time system, most functional modules have
operations with different timing constraints and execution periods, and
which therefore should be executed by different tasks with different
priorities (in a pre-emptive system) or different execution periods (in
a statically scheduled, non-pre-emptive system).

In my designs, tasks contained in sub-modules tend to be sporadically
activated -- for example, the server task in the recent
I/O-request-queue discussion -- rather than cyclic.
Post by Roy Emmerich
If, for example, I am monitoring a solar photovoltaic inverter via
MODBUS RTU, it is possible to retrieve a lot of different information.
Some information, like voltage and current, I may want to retrieve
every second whereas other information like battery temperature
I may only want to retrieve every 5 minutes.
That agrees with my experience.
Post by Roy Emmerich
The module will know the sampling frequency for each variable to be
monitored and will trigger itself when it is time to do so.
If these sampling frequencies are totally unrelated to other frequencies
and sampling phases in other sub-modules, defining a dedicated task (or
even two tasks, with different periods) within the sub-module can be the
sensible thing to do.

However, if many sub-modules have similar timing requirements, I would
use a couple of global tasks -- say, a cyclic task with 1-second period,
and another with a 1 minute period -- and have them call dedicated
procedures in this sub-module, and in other sub-modules with similar
sample-timing requirements. The benefit is avoiding the local timing
calculations; the drawback is that one must consider interference
between the tasks.

Perhaps the simplest design is to have one global task with a 1-second
period, which calls the 1-second operations from all sub-modules in
every period, and the 1-minute operations in every 60th period. But this
assumes that all the 1-minute operations can be finished in less than
one second of execution time.

Reducing the number of tasks in this way reduces the need for
stack-space RAM and tends to make the system's behaviour more regular,
predictable and understandable. But if your processor has plenty of
speed and memory, these effects may not be important to you.

If you want to make it very easy to add/remove sub-modules from the
system, defining local tasks in each sub-module may be the better
choice, because then you can easily avoid explicit calls from the main
application to the sub-module.
Post by Roy Emmerich
Using protected objects and hard/firm/soft/non-critical tasks
it sounds like this could indeed be a viable approach.
Sure. Many systems have been built that way in Ada.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Dmitry A. Kazakov
2014-08-29 07:41:58 UTC
Permalink
Post by Niklas Holsti
Post by Dmitry A. Kazakov
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
It is certainly possible to implement an I/O request queue in Ravenscar;
I have done so for the platform SW on ESA's GOCE satellite. Multiple
client tasks, one server (interface driver) task. An I/O request
contains (or is, or refers to) a client-specific protected object (PO)
with an "I/O completed" entry, on which the client task waits after
enqueueing the I/O request. The server task processes submitted I/O
requests in any order and concurrency it chooses; when an I/O request is
done, the server task calls an operation on the request's PO, which
unblocks the entry, resuming the client task.
Looks ugly to me. But I don't understand how the server's queue is accessed
by multiple tasks concurrently? And how could you cancel a pending request
in this schema?
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Niklas Holsti
2014-08-29 16:31:00 UTC
Permalink
Post by Dmitry A. Kazakov
Post by Niklas Holsti
Post by Dmitry A. Kazakov
You could not implement an equivalent of I/O queueing under the Ravenscar
constraints.
It is certainly possible to implement an I/O request queue in Ravenscar;
I have done so for the platform SW on ESA's GOCE satellite. Multiple
client tasks, one server (interface driver) task. An I/O request
contains (or is, or refers to) a client-specific protected object (PO)
with an "I/O completed" entry, on which the client task waits after
enqueueing the I/O request. The server task processes submitted I/O
requests in any order and concurrency it chooses; when an I/O request is
done, the server task calls an operation on the request's PO, which
unblocks the entry, resuming the client task.
Looks ugly to me.
In the eye of the beholder :-)
Post by Dmitry A. Kazakov
But I don't understand how the server's queue is accessed
by multiple tasks concurrently? And how could you cancel a pending request
in this schema?
For example (from memory, not tested):


protected type IO_Response_T
-- Each client task has an instance of this PO type.
is

procedure Set (Result : in ...);
-- Called by server task when the I/O is done.
-- Stores the Result in the PO and unblocks Get_Result.

entry Get (Result : out ...);
-- Called by client to wait for I/O completion
-- and then get the result.

end IO_Response_T;


type IO_Response_Ref is access all IO_Response_T;


type IO_Request_T is record
Xxx : ... I/O request data;
Response : IO_Response_Ref;
end record;


protected Server_Queue
-- A single instance (for one server).
is

procedure Enqueue (
Request : in IO_Request_T;
Success : out Boolean);
-- Called by clients to request some I/O.
-- If the queue was full, Success is set to False.

entry Dequeue (Request : out IO_Request_T);
-- Called by Server task, returns when the queue has
-- some request(s).

end Server_Queue;


A client task does:

Response : aliased IO_Response_T;
...
Server_Queue.Enqueue (
Request => ( ... , Response => Response'Access),
Success => ...);

if Success then

Response.Get (Result => ...);

else
-- Queue full.
... perhaps delay and retry?

end if;

The server task does:

Request : IO_Request_T;
...
loop

Server_Queue.Dequeue (Request => Request);

.. perform the I/O according to the Request.

Request.Response.Set (Result => ...);

end loop;

A request in the queue can be cancelled by adding such an operation to
Server_Queue, for example:

procedure Cancel (Response : in IO_Response_Ref);
-- Scans the queue for a request with the given Response object,
-- then deletes it from the queue and signals (using
-- Response.Set, or some added Response.Cancelled) the
-- client.

Did that answer your question?
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Roy Emmerich
2014-08-29 16:47:52 UTC
Permalink
Post by Dennis Lee Bieber
It works if the entire system including the "user application" level is
built "as one". It is NOT a very dynamic arrangement wherein you may plug
in a new sensor and have it magically install itself to some list of
sensors to be reported.
My requirements for dynamic behaviour don't extend so far as to be plug and play ready. What I do want, being a modular hardware platform, is to define, in a configuration file, which hardware modules are plugged into which socket. At start up the supervisor will read this file and instantiate the relevant software modules.

To get an idea of what the hardware I am using looks like, take a look at this image:

Loading Image...
Post by Dennis Lee Bieber
Even within Ravenscar constraints, one can build
very dynamic task interactions, which is nice for implementing stuff in
a Ravenscar system, but which makes schedulability analysis difficult.
Keep in mind too what I intend to use this device for and the competition I am up against. Here is a short elevator pitch:

I am a renewable energy engineer and I want, initially, to use this device as a data aggregator/controller in off-grid energy systems (also called hybrid systems). These systems are normally powered by more than one renewable source (e.g. wind/solar) and often include a backup generator. They consist of many different power electronic devices which often stem from different manufacturers (read different communication protocols). This device will effectively aggregate the data from all of these devices into one, unified format and send control signals to the generator/inverters. Systems range from a few kilowatts to hundreds of kilowatts. It is naturally feasible to consider connecting up meteorological equipment to the same logger as well as other devices I probably haven't thought of yet. Modular is the operative word here.

As these systems are often remote it is important for my aggregator to be reliable and able to function even when the off-grid system is not. For that reason I want to independently power it, making it important for it to be a low power device (e.g. much less than say a beaglebone black embedded Linux board), able to run on a battery for at least 3 days, preferably much more and be connected to its own solar panel. It must keep accurate time (syncing once a day via GPS) and (periodically/in emergency) make the data available remotely (via GPRS).

My competitors are:

* Low end - The Arduino gang (cheap, anything is possible, professionalism is normally lacking but wires not)
* In the middle - A myriad of small to medium companies providing domain specific solutions (functionality normally too limited, hardware not extendible)
* High end - PLC manufacturers (normally too expensive)

Let's be frank. This is not a satellite. I WON'T be doing any schedulability analyses.

My Ada learning journey continued today. Quoting once again from:

Guide for the use of the Ada Ravenscar Profile in high integrity systems
http://www.sigada.org/ada_letters/jun2004/ravenscar_article.pdf

======== Extract start ========

5. Examples of Use

...
In the first eight sections of this chapter we give examples that illustrate the straightforward use of Ravenscar. After that, in sections 5.9 to 5.12, we show how Ravenscar can deal with requirements that would appear to lie outside the scope of what is supported by the Profile.
...

5.12 Further Expansions to the Expressive Power of Ravenscar

If static timing analysis is not of interest to the application program and a more general model of tasks and interrupts is required, this can still be achieved with reasonable expressive power within the subset definition. However, as noted earlier, Ravenscar is not a substitute for the full language
when that level of expressive power is needed.

* Dynamic creation and termination of tasks can be simulated by declaring a pool of event-triggered tasks at program start-up, each containing an infinite loop which has a suspending operation as its first statement, such that its execution can be invoked dynamically by one of the task synchronization primitives. Thus, by changing the settings of suspension objects and entry barriers, it is possible for certain tasks to have their execution disabled whilst others have execution enabled.

======== Extract end ========

Today Ada seems like a very good fit, no?
Niklas Holsti
2014-08-29 19:41:18 UTC
Permalink
Post by Roy Emmerich
Post by Dennis Lee Bieber
It works if the entire system including the "user application"
level is built "as one". It is NOT a very dynamic arrangement
wherein you may plug in a new sensor and have it magically install
itself to some list of sensors to be reported.
My requirements for dynamic behaviour don't extend so far as to be
plug and play ready. What I do want, being a modular hardware
platform, is to define, in a configuration file, which hardware
modules are plugged into which socket. At start up the supervisor
will read this file and instantiate the relevant software modules.
So the Ada program contains SW modules that can handle all known and
possible hardware modules, but the SW modules are all "data/table
driven" in the sense that the supervisor can tell each SW module where
(in which socket, &c) its HW, if any, can be found?

As far as I can see, the only problem that the Ravenscar profile can
cause for that design is the restriction No_Dynamic_Attachment, which
means that the connection between an interrupt source and its handler
must be established at elaboration time, by pragmas or aspects, and not
dynamically using a call of Ada.Interrupts.Attach_Handler.

In principle, the configuration file could be read at elaboration time,
and could provide the interrupt numbers to be used in the pragma/aspect
Attach_Handler. However, doing lots of computation at elaboration time
can make it tricky for the compiler to find a feasible elaboration order
(especially if the program has tasks).

The other solution is to attach handlers to all interrupt sources
statically, but to decide in each handler, at run time, based on the
configuration data, which SW module is to handle the interrupt, and to
call the suitable operation from that SW module. A kind of indirection step.
Post by Roy Emmerich
This device will effectively aggregate the
data from all of these devices into one, unified format and send
control signals to the generator/inverters.
What is the highest control frequency, or shortest deadline or response
time, required of the SW?
Post by Roy Emmerich
... making it
important for it to be a low power device (e.g. much less than say a
beaglebone black embedded Linux board), able to run on a battery for
at least 3 days, preferably much more
You may have to modify the Board Support Package and/or the kernel to
let the processor sleep between clock interrupts. I don't know if the
AdaCore ARM BSP has that ability off-the-shelf.
Post by Roy Emmerich
It must keep accurate time (syncing once a day via GPS)
and (periodically/in emergency) make the data available remotely (via
GPRS).
Time in a Ravenscar system is provided by the predefined package
Ada.Real_Time. It is good for relative timing in seconds and ticks, but
does not provide calendar date and time. Probably you will have to write
your own Calendar-like package which is synchronised with GPS. Not a
very big job.
Post by Roy Emmerich
Let's be frank. This is not a satellite. I WON'T be doing any
schedulability analyses.
AFAIK few satellites are subjected to formal schedulability analysis...
typically, some kind of "nominal worst-case scenario" is defined and a
simple computation similar to response-time analysis is used to
demonstrate that all important ("hard real time") tasks are fast enough
in this scenario, and that a reasonable fraction of CPU time is left for
the less urgent tasks.
Post by Roy Emmerich
Today Ada seems like a very good fit, no?
I think so.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Roy Emmerich
2014-08-30 22:00:06 UTC
Permalink
Post by Niklas Holsti
Post by Roy Emmerich
My requirements for dynamic behaviour don't extend so far as to be
plug and play ready. What I do want, being a modular hardware
platform, is to define, in a configuration file, which hardware
modules are plugged into which socket. At start up the supervisor
will read this file and instantiate the relevant software modules.
So the Ada program contains SW modules that can handle all known and
possible hardware modules, but the SW modules are all "data/table
driven" in the sense that the supervisor can tell each SW module where
(in which socket, &c) its HW, if any, can be found?
Yes.
Post by Niklas Holsti
As far as I can see, the only problem that the Ravenscar profile can
cause for that design is the restriction No_Dynamic_Attachment, which
means that the connection between an interrupt source and its handler
must be established at elaboration time, by pragmas or aspects, and not
dynamically using a call of Ada.Interrupts.Attach_Handler.
In principle, the configuration file could be read at elaboration time,
and could provide the interrupt numbers to be used in the pragma/aspect
Attach_Handler. However, doing lots of computation at elaboration time
can make it tricky for the compiler to find a feasible elaboration order
(especially if the program has tasks).
The other solution is to attach handlers to all interrupt sources
statically, but to decide in each handler, at run time, based on the
configuration data, which SW module is to handle the interrupt, and to
call the suitable operation from that SW module. A kind of indirection step.
Okay. I think I got that.
Post by Niklas Holsti
Post by Roy Emmerich
This device will effectively aggregate the
data from all of these devices into one, unified format and send
control signals to the generator/inverters.
What is the highest control frequency, or shortest deadline or response
time, required of the SW?
Okay, some new terminology for me here. For this particular application the response time doesn't have to be very fast (a few seconds). It will be monitoring battery state of charge and active power and turning the generator on or off. I do foresee the need to do reactive power control in larger off-grid systems. For this the phase shift between voltage and current is normally measured by a CE/UL certified power analyser (legal/safety issues) and transmitted, once again, via MODBUS RTU, to my device. As this kind of control is a lot more dynamic, a much faster response time would be required (20 ms thumb suck value, considering one 50 Hz period is 20 ms long). Sorry that it is still so vague. A bit of guidance wouldn't go amiss :)
Post by Niklas Holsti
Post by Roy Emmerich
... making it
important for it to be a low power device (e.g. much less than say a
beaglebone black embedded Linux board), able to run on a battery for
at least 3 days, preferably much more
You may have to modify the Board Support Package and/or the kernel to
let the processor sleep between clock interrupts. I don't know if the
AdaCore ARM BSP has that ability off-the-shelf.
Is there an AdaCore ARM BSP yet? I thought this is what Mike Silva was referring to when he said:

"I know that AdaCore is working on comms libraries for the ARM Cortex M parts, but I don't know anything about the projected availability."

assuming this would include stuff such as I2C, SPI, UART, etc. which is normally also part of the BSP?

Speaking of which...in order to feel like I'm making progress and Ada is going to work for me, I really need to get connecting to my peripherals. The only way I can see it happening within the next week is to call the STM C drivers supplied with their BSP. Does this make sense?
Post by Niklas Holsti
Post by Roy Emmerich
It must keep accurate time (syncing once a day via GPS)
and (periodically/in emergency) make the data available remotely (via
GPRS).
Time in a Ravenscar system is provided by the predefined package
Ada.Real_Time. It is good for relative timing in seconds and ticks, but
does not provide calendar date and time. Probably you will have to write
your own Calendar-like package which is synchronised with GPS. Not a
very big job.
Maybe not if you know what you're doing ;)

This is where it gets a bit vague for me. The STM32F4 has an on-board RTC with full calendar functionality. My thinking is at start up and then once a day to enter a "clock_sync" state, fire up the GPS receiver, somehow sync the processor's RTC and then continue with normal operation. If I need the absolute date/time I can just get it from the RTC, so I don't know why I would want to use the Ada.Calendar functionality in the first place. Could you shed some light on this?
Simon Wright
2014-08-31 10:08:58 UTC
Permalink
Post by Roy Emmerich
Speaking of which...in order to feel like I'm making progress and Ada
is going to work for me, I really need to get connecting to my
peripherals. The only way I can see it happening within the next week
is to call the STM C drivers supplied with their BSP. Does this make
sense?
To me it does. Should make it easier to cope with board revisions.
Niklas Holsti
2014-09-01 20:15:44 UTC
Permalink
...
Post by Roy Emmerich
Post by Niklas Holsti
Post by Roy Emmerich
This device will effectively aggregate the data from all of these
devices into one, unified format and send control signals to the
generator/inverters.
What is the highest control frequency, or shortest deadline or
response time, required of the SW?
Okay, some new terminology for me here. For this particular
application the response time doesn't have to be very fast (a few
seconds).
Then you can probably ignore all interrupt-handling and just poll for
I/O completion -- if that is much simpler to do.
Post by Roy Emmerich
... As this kind of control is
a lot more dynamic, a much faster response time would be required (20
ms thumb suck value, considering one 50 Hz period is 20 ms long).
That might or might not require interrupt-handling -- depends on your
overall design.
Post by Roy Emmerich
Post by Niklas Holsti
Post by Roy Emmerich
... making it important for it to be a low power device (e.g.
much less than say a beaglebone black embedded Linux board), able
to run on a battery for at least 3 days, preferably much more
You may have to modify the Board Support Package and/or the kernel
to let the processor sleep between clock interrupts. I don't know
if the AdaCore ARM BSP has that ability off-the-shelf.
Is there an AdaCore ARM BSP yet? I thought this is what Mike Silva
"I know that AdaCore is working on comms libraries for the ARM Cortex
M parts, but I don't know anything about the projected
availability."
assuming this would include stuff such as I2C, SPI, UART, etc. which
is normally also part of the BSP?
In my experience (space domain), the BSP (at least when it comes from a
compiler vendor) usually includes only the functions needed to make the
compiler's run-time system work. For Ada/Ravenscar, this means mainly
that task switching and protected objects work as expected (including
POs used as interrupt handlers) and that some timer or clock HW is
configured to drive Ada.Real_Time and the "delay until" statements. I/O
drivers are not (in my domain) typically included in the BSP -- well,
perhaps the BSP contains a simple serial-port driver to make some
emasculated form of Ada.Text_IO work. I/O drivers typically come separately.

For ground-based embedded systems, I have seen that some compiler or
chip vendors package I/O drivers with their BSPs. Perhaps Mike Silva is
talking about some AdaCore activity in that direction.
Post by Roy Emmerich
Speaking of which...in order to feel like I'm making progress and Ada
is going to work for me, I really need to get connecting to my
peripherals. The only way I can see it happening within the next week
is to call the STM C drivers supplied with their BSP. Does this make
sense?
Very much so, at least if the C drivers are designed as a passive
library which does not rely on any specific kernel.
Post by Roy Emmerich
Post by Niklas Holsti
Post by Roy Emmerich
It must keep accurate time (syncing once a day via GPS)
Must the SW actions be accurately synchronized with GPS -- for example,
sample something exactly at the GPS pulse-per-second pulse -- or is it
enough that the SW can accurately label each action/sample with the GPS
time when the sample was taken?
Post by Roy Emmerich
Post by Niklas Holsti
Post by Roy Emmerich
and
(periodically/in emergency) make the data available remotely
(via GPRS).
Time in a Ravenscar system is provided by the predefined package
Ada.Real_Time. It is good for relative timing in seconds and ticks,
but does not provide calendar date and time. Probably you will have
to write your own Calendar-like package which is synchronised with
GPS. Not a very big job.
Maybe not if you know what you're doing ;)
This is where it gets a bit vague for me. The STM32F4 has an on-board
RTC with full calendar functionality.
Nice.
Post by Roy Emmerich
My thinking is at start up and
then once a day to enter a "clock_sync" state, fire up the GPS
receiver, somehow sync the processor's RTC and then continue with
normal operation.
By "processor's RTC", you mean the one with full calendar functionality?
Sounds like a good plan, if that RTC device allows such synchronisation.

I would not try to sync or adjust whatever HW is driving Ada.Real_Time,
but would let that run in its own time. If necessary, I would adjust the
period of the cyclic tasks to keep them in phase with the GPS and/or the
RTC. That is, if a 1 Hz task finds that it is falling behind -- doing
fewer cycles than there are GPS/RTC 1-second ticks -- it would do a few
"delay untils" with a smaller period than 1 s until it has caught up.
Post by Roy Emmerich
If I need the absolute date/time I can just get it
from the RTC, so I don't know why I would want to use the
Ada.Calendar functionality in the first place. Could you shed some
light on this?
I agree, you don't need Ada.Calendar if you have a calendar-capable RTC
and do not need to do date/time calculations such as finding the
calendar date of "now + 100_000 seconds".

From what I understand of your application, I think you should be fine
with Ada.Real_Time and the RTC.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Jeffrey Carter
2014-09-01 21:11:37 UTC
Permalink
Post by Niklas Holsti
I agree, you don't need Ada.Calendar if you have a calendar-capable RTC
and do not need to do date/time calculations such as finding the
calendar date of "now + 100_000 seconds".
No, but he'll need something like Ada.Calendar to let him read the H/W RTC, plus
whatever other operations he'll need to do with it (such as sync it to GPS time).
--
Jeff Carter
"People called Romanes, they go the house?"
Monty Python's Life of Brian
79
g***@gmail.com
2014-08-31 04:54:29 UTC
Permalink
Post by Roy Emmerich
My requirements for dynamic behaviour don't extend so far as to be plug and play ready. What I do want, being a modular hardware platform, is to define, in a configuration file, which hardware modules are plugged into which socket. At start up the supervisor will read this file and instantiate the relevant software modules.
That looks a lot like MINIX 3. A microkernel where the user can very easy configure and run drivers.

http://www.minix3.org/other/reliability.html

Another benefit is that with a microkernel communication between drivers and the kernel is standardized. It is relatively easy to create new drivers. I don't know if you can use Ada.

NetBSD rump also looks like that.

https://www.usenix.org/legacy/event/usenix09/tech/full_papers/kantee/kantee_html/
Roy Emmerich
2014-09-09 19:17:01 UTC
Permalink
Post by g***@gmail.com
That looks a lot like MINIX 3. A microkernel where the user can very easy configure and run drivers.
http://www.minix3.org/other/reliability.html
Thanks to your post I started searching using the "microkernel" term. Up until then I had been limited (in my own mind) to RTOS. It opened my eyes to the many different RTOSs out there.

The problem with minix is that the hardware requirements are too high for the Cortex M4 processor:

http://wiki.minix3.org/UsersGuide/HardwareRequirements

The other fear I've always had about an RTOS is power management and whether it would be efficient enough for me needs. As I am going to take www.nuttx.org for a spin I will certainly be delving into this document soon:

Low power embedded software optimization for the NuttX RTOS
http://bibliodigital.itcr.ac.cr/xmlui/bitstream/handle/2238/3051/FinalReport.pdf

Another option in terms of energy efficiency is the F9 microkernel:

https://github.com/f9micro/f9-kernel
Mike Silva
2014-09-09 20:20:11 UTC
Permalink
Post by Roy Emmerich
The other fear I've always had about an RTOS is power management and whether it would be efficient enough for me needs.
Do you even need tasking? You can run a non-tasking Ada runtime and still get all the benefits of writing that code in Ada. For low power you could wake up on a timer or other event, do whatever work you need to do, then go back to sleep. Just the way you'd do it in C without an RTOS.
Roy Emmerich
2014-09-09 21:56:19 UTC
Permalink
Post by Mike Silva
Do you even need tasking? You can run a non-tasking Ada runtime and still get all the benefits of writing that code in Ada. For low power you could wake up on a timer or other event, do whatever work you need to do, then go back to sleep. Just the way you'd do it in C without an RTOS.
This 'sequential' discussion is coming full circle Mike :) My initial intention was to keep things as simple as possible and go without an RTOS. However I still wanted multi-threading. That is why I got so excited at the prospect of running Ada bare-metal with tasking on a Cortex M4.

Let me give a little bit of background to my thinking. Let's say at the top of every minute you want to measure ambient temperature (via analogue input), solar irradiance (via analogue input) and inverter current (via MODBUS RTU to the inverter) with my data logger. Going with a sequential mindset to start with, you will always know that with a single core (or multi-core) processor the samples will be sequential. The one sample follows the other and you have to programme things this way (e.g. iterating through an array of variables to sample). Threading (or tasking in Ada) on a single processor essentially does the same thing but the programming is done in a way that it looks like the three samples are taken at the same time (i.e. simultaneously sample ambient temperature, solar irradiance and inverter current at the top of every minute). The approach, however, is very different.

I know that in a few years from now microcontrollers will have multiple cores as a standard offering. Once this occurs it will then be possible to simultaneously sample as many channels as there are processor cores. If all my software is written with threading in the first place then nothing needs to be changed.

Also, in my mind, it seems to be the right way to tackle the problem from the outset. It may be an overly complicated approach just to solve the logging aspect but I am also hoping to extend it to include control aspects too. Once the complexity increases I have the feeling a multi-threaded approach will be much more modular, allowing me to separate the different aspects of my code into standalone chunks like this:

* thread one, here's your configuration, you take care of inverter current sampling every 5 seconds.
* thread two, here's your configuration, you take care of solar irradiance sampling every 1 second.
* thread 3, here's your configuration, you take care of diesel generator control.
* etc.

To solve inter-thread communication I am looking at some sort of variable publish/subscribe design. Each thread will publish its variables of interest for other threads to subscribe to.

Does this make it clearer? I'm trying to plan for the long term and currently feel like I'm in a state of analysis paralysis :)
Dennis Lee Bieber
2014-09-10 01:41:54 UTC
Permalink
On Tue, 9 Sep 2014 14:56:19 -0700 (PDT), Roy Emmerich
Post by Roy Emmerich
Let me give a little bit of background to my thinking. Let's say at the top of every minute you want to measure ambient temperature (via analogue input), solar irradiance (via analogue input) and inverter current (via MODBUS RTU to the inverter) with my data logger. Going with a sequential mindset to start with, you will always know that with a single core (or multi-core) processor the samples will be sequential. The one sample follows the other and you have to programme things this way (e.g. iterating through an array of variables to sample). Threading (or tasking in Ada) on a single processor essentially does the same thing but the programming is done in a way that it looks like the three samples are taken at the same time (i.e. simultaneously sample ambient temperature, solar irradiance and inverter current at the top of every minute). The approach, however, is very different.
<snip>
Post by Roy Emmerich
* thread one, here's your configuration, you take care of inverter current sampling every 5 seconds.
* thread two, here's your configuration, you take care of solar irradiance sampling every 1 second.
* thread 3, here's your configuration, you take care of diesel generator control.
* etc.
I suspect all you really need is a scheduler based on a priority queue
-- in which the "priority" is really the time-of-next-event... Closest
event is in front. Presuming you initialize all the devices before starting
the scheduler there should not be any problem of a suddenly an event crops
up that needs to go "now".

loop
pull front of queue (event time, device handler/callback)
delay until event time
call device handler/callback
end loop

Device handler/callback is essentially

obtain reading from device
log reading
compute next event time for this device (current trigger time + interval)
put entry on queue (where it sorts to the proper place in the multitude of
items)

Obviously "device handler/callback" needs to somehow incorporate the
parameters for the rate computation, the particular device ID if more than
one device shares the code of a handler, etc.

Since the main loop doesn't pull the next item until the handler has
placed its next invocation onto the queue, even a fast event rate won't
vanish, it just becomes the next entry to be pulled.

You might want to look at "discrete event" information.

Your configuration information would contain something like:

device class (handler name), device ID, offset to first event time, delta
between events
for each instance of a device.

The event queue only needs to be large enough to hold one event from
each configured device (each device only needs one pending event, and when
that event is pulled and the device handler activates, it puts itself back
on the queue).
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Roy Emmerich
2014-09-10 08:52:27 UTC
Permalink
Dennis thanks for your feedback. It is really helping to think of alternative ways to achieve my goal.
Post by Dennis Lee Bieber
I suspect all you really need is a scheduler based on a priority queue
-- in which the "priority" is really the time-of-next-event... Closest
event is in front. Presuming you initialize all the devices before starting
the scheduler there should not be any problem of a suddenly an event crops
up that needs to go "now".
When you say scheduler, is this some specific Ada construct? I have a simple array in mind, or maybe a linkedlist/hashmap (i.e. key/value pairs) with time-of-next-event as the key and values being references to the device handlers.
Post by Dennis Lee Bieber
loop
pull front of queue (event time, device handler/callback)
delay until event time
call device handler/callback
end loop
Device handler/callback is essentially
obtain reading from device
log reading
compute next event time for this device (current trigger time + interval)
put entry on queue (where it sorts to the proper place in the multitude of
items)
How I understand it is the scheduler sorts all events by time whenever a new event is added to the queue. What happens when two events have the same time-of-next-event? Introduce a second priority level?

There will also be house keeping tasks such as syncing the on-board RTC to the GPS time. I am thinking of scheduling these based on time (e.g. once a day) but having a higher priority than the rest of the logging tasks. An additional priority level could be useful in this case. However, having said that, it isn't absolutely critical for the time sync to occur at a particular time. This is getting me thinking about time windows. In other words, do this task at least once a day, at this time +-5 minutes. In terms of RTC syncing this won't help much if you are logging something every second as it takes much longer for the GPS receiver to start up and lock on, in which case a variable being logged every second would just have to wait until the GPS syncing has finished, leaving a gap in the logged data. One could get more sophisticated and get the GPS sync event to have various states (e.g. first start the GPS receiver then wait in the queue until a valid signal is available, allowing other events to take place). This is essentially device specific.
Post by Dennis Lee Bieber
Obviously "device handler/callback" needs to somehow incorporate the
parameters for the rate computation, the particular device ID if more than
one device shares the code of a handler, etc.
My (Java) thinking is leading me to create a generic device handler class for each device to be monitored. Each device will have one or more variables to monitor (e.g a temp sensor is a device with one variable to monitor while an inverter is a device with many possible variables to monitor). Each device handler class will then instantiate separate variable handler classes for each variable to be monitored. It can't be assumed that all possible variables will want to be logged. Each variable will likely have a different sampling rate. These variable handler classes will receive the sampling rate upon instantiation and will contain a callback function which will be inserted into the queue we spoke about above.
Post by Dennis Lee Bieber
Since the main loop doesn't pull the next item until the handler has
placed its next invocation onto the queue, even a fast event rate won't
vanish, it just becomes the next entry to be pulled.
I'm not quite understanding your phrasing here. Could you elaborate?
Post by Dennis Lee Bieber
You might want to look at "discrete event" information.
Okay. This is new territory for me :) Any reading tips?
Post by Dennis Lee Bieber
device class (handler name), device ID, offset to first event time, delta
between events
for each instance of a device.
The event queue only needs to be large enough to hold one event from
each configured device (each device only needs one pending event, and when
that event is pulled and the device handler activates, it puts itself back
on the queue).
That makes sense. Translated to my thinking the queue will be as long as the number of variables to be monitored.

The mists of confusion are starting to disappear! Thanks again for your help.
Dennis Lee Bieber
2014-09-10 13:05:38 UTC
Permalink
On Wed, 10 Sep 2014 01:52:27 -0700 (PDT), Roy Emmerich
Post by Roy Emmerich
Dennis thanks for your feedback. It is really helping to think of alternative ways to achieve my goal.
Post by Dennis Lee Bieber
I suspect all you really need is a scheduler based on a priority queue
-- in which the "priority" is really the time-of-next-event... Closest
event is in front. Presuming you initialize all the devices before starting
the scheduler there should not be any problem of a suddenly an event crops
up that needs to go "now".
When you say scheduler, is this some specific Ada construct? I have a simple array in mind, or maybe a linkedlist/hashmap (i.e. key/value pairs) with time-of-next-event as the key and values being references to the device handlers.
If it helps, change "scheduler" to "dispatcher".

"Sorting" is done by the operation to insert an event into the queue.
Inserting an entry would be done by traversing the queue from the front,
and as soon as you find an entry that has an event time that falls after
the new event being inserted you've found the position. (Of course, if you
reach the end of the queue, then the item goes on the end <G>)

Suggest a linked list with extension. That is, the top level record has
no data, only the event time and the link to the next/previous entries.
Each distinct device class would extend the node with parameters specific
to that device.

The queue/linked-list management and dispatcher only need to see the
links and event time to control the order. The dispatcher would have to be
able to invoke the proper process based on the extended type (I'd have to
study my books for this -- "Ada for Software Engineers, 2nd Ed" (Ben-Ari,
2009 Springer-Verlag) section 6.7 is a linked list priority queue (intro,
not fully developed), 12.2.1 introduces call-backs.
Post by Roy Emmerich
How I understand it is the scheduler sorts all events by time whenever a new event is added to the queue. What happens when two events have the same time-of-next-event? Introduce a second priority level?
The insert logic puts them in the order they arrived (so something that
has been waiting longer will get run before a fast-cycle event that has run
and requeued).
Post by Roy Emmerich
There will also be house keeping tasks such as syncing the on-board RTC to the GPS time. I am thinking of scheduling these based on time (e.g. once a day) but having a higher priority than the rest of the logging tasks. An additional priority level could be useful in this case. However, having said that, it isn't absolutely critical for the time sync to occur at a particular time. This is getting me thinking about time windows. In other words, do this task at least once a day, at this time +-5 minutes. In terms of RTC syncing this won't help much if you are logging something every second as it takes much longer for the GPS receiver to start up and lock on, in which case a variable being logged every second would just have to wait until the GPS syncing has finished, leaving a gap in the logged data. One could get more sophisticated and get the GPS sync event to have various states (e.g. first start the GPS receiver then wait in the queue until a valid signal is available, allowing
No real "priority" levels in this scheme -- the scheduled event time is
the only priority.

You delay until the time of the next event, process that event (which
is then responsible for putting /its/ next invocation onto the queue), go
back and do the next event on the queue (always the front of queue).

If multiples end up on the same event time, you basically process them
in order without a delay, only when the event time is greater than "now" do
you need to delay until xxx. Since each event process is in charge of
scheduling its next invocation, there is no way an event could suddenly end
up at the front of the queue while you are delaying (all other events are
already on the queue, and the event to be processed can't add itself until
it runs).


I'm late for work... Hope this helps.
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Simon Wright
2014-09-10 17:16:26 UTC
Permalink
Post by Dennis Lee Bieber
"Sorting" is done by the operation to insert an event into the
queue. Inserting an entry would be done by traversing the queue from
the front, and as soon as you find an entry that has an event time
that falls after the new event being inserted you've found the
position. (Of course, if you reach the end of the queue, then the item
goes on the end <G>)
Suggest a linked list with extension. That is, the top level
record has no data, only the event time and the link to the
next/previous entries. Each distinct device class would extend the
node with parameters specific to that device.
The queue/linked-list management and dispatcher only need to see
the links and event time to control the order. The dispatcher would
have to be able to invoke the proper process based on the extended
type (I'd have to study my books for this -- "Ada for Software
Engineers, 2nd Ed" (Ben-Ari, 2009 Springer-Verlag) section 6.7 is a
linked list priority queue (intro, not fully developed), 12.2.1
introduces call-backs.
OP might be interested in my ColdFrame[1], and in particular the top
page for Events[2], which is based on similar ideas.

Because I'm interested in state modelling, I have four event queues; one
for events-to-self, to be executed as part of one state machine action,
one for state machine events, to be executed in order of posting, one
for inter-domain communication, of lower priority but also to be
executed in order of posting, and one for "held" events, to be executed
in time order.

This is probably more complicated than you need :-)

[1] http://coldframe.sourceforge.net/coldframe/
[2] http://coldframe.sourceforge.net/coldframe/events.html
Mike Silva
2014-09-10 03:20:10 UTC
Permalink
Post by Roy Emmerich
Post by Mike Silva
Do you even need tasking? You can run a non-tasking Ada runtime and still get all the benefits of writing that code in Ada. For low power you could wake up on a timer or other event, do whatever work you need to do, then go back to sleep. Just the way you'd do it in C without an RTOS.
This 'sequential' discussion is coming full circle Mike :) My initial intention was to keep things as simple as possible and go without an RTOS. However I still wanted multi-threading. That is why I got so excited at the prospect of running Ada bare-metal with tasking on a Cortex M4.
Let me give a little bit of background to my thinking. Let's say at the top of every minute you want to measure ambient temperature (via analogue input), solar irradiance (via analogue input) and inverter current (via MODBUS RTU to the inverter) with my data logger. Going with a sequential mindset to start with, you will always know that with a single core (or multi-core) processor the samples will be sequential. The one sample follows the other and you have to programme things this way (e.g. iterating through an array of variables to sample). Threading (or tasking in Ada) on a single processor essentially does the same thing but the programming is done in a way that it looks like the three samples are taken at the same time (i.e. simultaneously sample ambient temperature, solar irradiance and inverter current at the top of every minute). The approach, however, is very different.
I know that in a few years from now microcontrollers will have multiple cores as a standard offering. Once this occurs it will then be possible to simultaneously sample as many channels as there are processor cores. If all my software is written with threading in the first place then nothing needs to be changed.
* thread one, here's your configuration, you take care of inverter current sampling every 5 seconds.
* thread two, here's your configuration, you take care of solar irradiance sampling every 1 second.
* thread 3, here's your configuration, you take care of diesel generator control.
* etc.
To solve inter-thread communication I am looking at some sort of variable publish/subscribe design. Each thread will publish its variables of interest for other threads to subscribe to.
Does this make it clearer? I'm trying to plan for the long term and currently feel like I'm in a state of analysis paralysis :)
I agree that concurrency fits your desired behavior more naturally. It was just that you started to worry if the extra overhead would bust your power budget.

BTW, a multi-core microcontroller would not (presumably) be able to do simultaneous samples, because (presumably) all the cores would share the same GPIO, ADC and other I/O resources and would thus compete for those resources via some form of critical sections.
Dmitry A. Kazakov
2014-09-10 07:22:21 UTC
Permalink
Post by Mike Silva
BTW, a multi-core microcontroller would not (presumably) be able to do
simultaneous samples, because (presumably) all the cores would share the
same GPIO, ADC and other I/O resources and would thus compete for those
resources via some form of critical sections.
There are other reasons too. A/D converters, even quality ones (which you
don't get as a GPIO), are quite slow. Furthermore integrated converters are
few (probably one), so there are multiplexed between all the inputs.

Not that it would matter for sampling outdoor temperature or pressure.

Even in a tight loop control application synchronous sampling is not really
needed or could be replaced with asynchronous one with exact time stamping.
Though designers of controlling algorithms are usually too lazy to use time
stamps differences for adjustments.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Roy Emmerich
2014-09-10 09:35:36 UTC
Permalink
Post by Mike Silva
I agree that concurrency fits your desired behavior more naturally. It was just that you started to worry if the extra overhead would bust your power budget.
Not only busting my power budget but also the angst of spiralling complexity when using an RTOS. Using something like www.nuttx.org seems good as it brings a lot of benefits but I know it will be a steep learning curve, while topics like power management will probably be less than ideally dealt with.

Having said that, my project is pretty simple, initially. An RTOS will be an overkill to start with but what about later on? I'm finding this a difficult decision to make.
Post by Mike Silva
BTW, a multi-core microcontroller would not (presumably) be able to do simultaneous samples, because (presumably) all the cores would share the same GPIO, ADC and other I/O resources and would thus compete for those resources via some form of critical sections.
Now this is providing some good perspective! Thanks. What could be parallelised is any form of calculations not requiring I/O or tasks such as data compression prior to remote transmission.
Stephen Leake
2014-09-10 14:11:49 UTC
Permalink
Post by Roy Emmerich
Let me give a little bit of background to my thinking. Let's say at
the top of every minute you want to measure ambient temperature (via
analogue input), solar irradiance (via analogue input) and inverter
current (via MODBUS RTU to the inverter) with my data logger. Going
with a sequential mindset to start with, you will always know that
with a single core (or multi-core) processor the samples will be
sequential. The one sample follows the other and you have to programme
things this way (e.g. iterating through an array of variables to
sample). Threading (or tasking in Ada) on a single processor
essentially does the same thing but the programming is done in a way
that it looks like the three samples are taken at the same time (i.e.
simultaneously sample ambient temperature, solar irradiance and
inverter current at the top of every minute). The approach, however,
is very different.
The samples will each take a few milliseconds at most; that's negligible
compared to the once per minute period. Sequential is fine.

Also, the analog hardware determines the inter-sample rate. To sample
three channels truly simultaneously, you need three A/D's, with a
trigger pulse to start the sample. Way overkill for this application.

Most likely, you'll have one A/D, so all your samples will be
sequential. Then you have a choice of triggering each one individually,
or just continuously looping thru all of them.
Post by Roy Emmerich
Also, in my mind, it seems to be the right way to tackle the problem
from the outset. It may be an overly complicated approach just to
solve the logging aspect but I am also hoping to extend it to include
control aspects too.
Yes, control may have tighter timing requirements. But if they can all
be expressed as fixed periods, and it all fits within your CPU budget,
then a timer-driven single thread is the way to go. Anything more
complicated just makes the system harder to understand, and eats power.

If it doesn't fit within your CPU budget, and you are trying to do the
"best" in some degraded mode, then tasking might be useful, if you can
design an approprite scheduling algorithm.
Post by Roy Emmerich
Once the complexity increases I have the feeling a multi-threaded
approach will be much more modular,
"module" /= "thread"

"module" = "package"

threads are required when different functions truly overlap in time, in
ways that are too complex to handle with a timer-driven design.

You may have several threads, each running several modules.

If the application really needs multiple CPUs/cores in order to get
everything done in time, then you need threads.
Post by Roy Emmerich
* thread one, here's your configuration, you take care of inverter
current sampling every 5 seconds.
* thread two, here's your configuration, you take care of solar
irradiance sampling every 1 second.
* thread 3, here's your configuration, you take care of diesel generator control.
* etc.
Timer interrupt config:

period 5 seconds: inverter current sampling

period 1 second: solar irradiance sampling

period ?: diesel generator control

At those slow periods, you'll have plenty of CPU time.

In Ada, timer interrupts are most easily handled as protected entries.
These can simply call the appropriate module subprograms, or they can
release a thread, by changing a guard variable on another entry.
Post by Roy Emmerich
To solve inter-thread communication I am looking at some sort of
variable publish/subscribe design.
Way overkill. Global variables is all you need.

If it gets very complex, you might want a symbol table, with name lookup
at elaboration time (which may be what you mean by publish/subscribe).
That way, you can have more than one instance of a module, with variable
names that include the module name: analog_sampler_1.value,
analog_sampler_2.value.

What do the three modules mentioned above have to say to each other? The
diesel generator needs the sensor values; just read the global variables.
Post by Roy Emmerich
Does this make it clearer? I'm trying to plan for the long term and
currently feel like I'm in a state of analysis paralysis :)
It takes three tries to get it right; just relax and do the first
implementation, for an actual application that you might get paid for
soon. It will be wrong, but you'll learn a lot, and maybe you'll make
some money if it's good enough.
--
-- Stephe
Jeffrey Carter
2014-09-10 17:46:49 UTC
Permalink
Post by Stephen Leake
Yes, control may have tighter timing requirements. But if they can all
be expressed as fixed periods, and it all fits within your CPU budget,
then a timer-driven single thread is the way to go. Anything more
complicated just makes the system harder to understand, and eats power.
What makes the system harder to understand is an implementation that doesn't
model the problem. For example, the problem description doesn't exactly scream
"priority queue", a possible implementation suggested in another post.

To my mind, the problem description sounds like a loop that wakes up every T
seconds and does whatever sampling/control is required at that time (where T is
the largest interval such that all the sampling/control intervals are integral
multiples of T).

A task per sampled/controlled device would be the next possible implementation I
would consider.

As always, one should always write the clearest implementation and then measure
it before making it less clear to meet timing or power-consumption requirements.
Post by Stephen Leake
Way overkill. Global variables is all you need.
While a publish/subscribe mechanism is probably overkill, global variables
should never be used. Global variables are a guaranteed way to make your S/W
hard to understand and modify.
--
Jeff Carter
"Why don't you bore a hole in yourself and let the sap run out?"
Horse Feathers
49
Dmitry A. Kazakov
2014-09-10 18:37:30 UTC
Permalink
Post by Jeffrey Carter
Post by Stephen Leake
Way overkill. Global variables is all you need.
While a publish/subscribe mechanism is probably overkill, global variables
should never be used. Global variables are a guaranteed way to make your S/W
hard to understand and modify.
Not really overkill. Much depends on the protocol role the application must
play. If the application is a master it could control slaves from the main
control loop, forcing them to send or accept data. But if it is a slave,
many protocols require slaves or are time triggered or are not
client-server at all, then it has no say when data arrive or go. A
publisher/subscriber service resolves this. The global variables pool does
this too, but it has issues with data consistency, e.g. logically coherent
variables, one updated, one not. Even bigger problems arise with
non-physical valued variables, when you must handle each variable update.
All commands are like that. With global variables it quickly ends up with
toggle bits and other mess.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Stephen Leake
2014-09-11 09:53:43 UTC
Permalink
Post by Jeffrey Carter
Post by Stephen Leake
Way overkill. Global variables is all you need.
While a publish/subscribe mechanism is probably overkill, global variables
should never be used. Global variables are a guaranteed way to make your S/W
hard to understand and modify.
I disagree. One way is:

package Global_Variables is

Sensor_1 : float;
Sensor_2 : float;
Actuator_1 : float;

end global_variables;

package Sensor_1 is

function Read return Float;

end Sensor_1;

package Controller is

procedure Execute
(Sensor_1 : in Float;
Sensor_2 : in Float;
Actuator : out Float);

end controller;

procedure Main is
begin
loop
wait_for_cycle;

case cycle_type is
when Sensor_1 =>
Global_Variables.Sensor_1 := Sensor_1.read;

when Sensor_2 =>
Global_Variables.Sensor_2 := Sensor_2.read;

when Control =>
Controller.Execute
(Global_Variables.Sensor_1,
Global_Variables.Sensor_2,
Global_Variables.Actuator_1);

-- output to actuator

end case;

end loop;
end Main;

That is well documented by the structure of the code.

I agree that having "Read" be a procedure that updates
Global_Variables.Sensor_1 in the body, and having Execute read it in the
body, is a bad design.

Global variables are not bad per se, if they are used carefully and
clearly.

What would you propose as an alternative to the above?
--
-- Stephe
Jeffrey Carter
2014-09-11 17:19:58 UTC
Permalink
Post by Stephen Leake
What would you propose as an alternative to the above?
In this case, and for this kind of structure, I would put the variables in the
main procedure. Putting them in a separate package when they are only accessed
by the main procedure serves no purpose except to unnecessarily complicate the code.
--
Jeff Carter
"Clear? Why, a 4-yr-old child could understand this
report. Run out and find me a 4-yr-old child. I can't
make head or tail out of it."
Duck Soup
94
Brian Drummond
2014-09-10 20:58:36 UTC
Permalink
Post by Roy Emmerich
I know that in a few years from now microcontrollers will have multiple
cores as a standard offering. Once this occurs it will then be possible
to simultaneously sample as many channels as there are processor cores.
If all my software is written with threading in the first place then
nothing needs to be changed.
They already do have multiple cores, if you buy them from http://
www.xmos.com/

Don't know about ADCs and other peripherals on these, though.

I'm not sure but I believe their compiler is based on gcc, which suggests
that building it with Ada support may not be totally out of the question.

All comes back to the RTS then...

- Brian
Dennis Lee Bieber
2014-09-10 23:40:26 UTC
Permalink
On Wed, 10 Sep 2014 20:58:36 GMT, Brian Drummond
Post by Brian Drummond
Post by Roy Emmerich
I know that in a few years from now microcontrollers will have multiple
cores as a standard offering. Once this occurs it will then be possible
to simultaneously sample as many channels as there are processor cores.
If all my software is written with threading in the first place then
nothing needs to be changed.
They already do have multiple cores, if you buy them from http://
www.xmos.com/
Probably too small for this application, but there is also the Parallax
Propeller -- which has 8 cores... and NO interrupts. The concept is that
one assigns a core to a polling loop rather than triggering an interrupt.
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Niklas Holsti
2014-08-29 16:58:20 UTC
Permalink
Post by Niklas Holsti
protected type IO_Response_T
-- Each client task has an instance of this PO type.
is
procedure Set (Result : in ...);
-- Called by server task when the I/O is done.
-- Stores the Result in the PO and unblocks Get_Result.
Should be: "... unblocks Get."
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Dmitry A. Kazakov
2014-08-31 07:02:35 UTC
Permalink
[...]
Post by Niklas Holsti
Did that answer your question?
Sort of.

No_Local_Protected_Objects means all requests are pre-allocated at the
library level and distributed by another protected object? With busy
waiting for a free request?

When I evaluated Ravenscar for our middleware (long ago), the concern was
publisher/subscriber services. I/O queue viewed as one of them. I didn't
consider a solution like yours because the requirement was that more than
one task could await for same I/O event. You reserve the event for single
task and other publisher/subscriber services (e.g. the data logger, network
data server, health monitor etc) may not use it because of
Max_Protected_Entries = 1. The event cannot propagate because of
No_Requeue_Statements. Tasks could flood the queue with their
requests/events but they cannot do that for more than one queue.

It seems that Ravenscar has a barrier that does not allow crossing the
border between 1-1 to 1-n or n-1.

It might do what you wanted, but it does not look scalable for the OP's
purpose.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Brad Moore
2014-08-31 15:44:26 UTC
Permalink
Post by Dmitry A. Kazakov
[...]
Post by Niklas Holsti
Did that answer your question?
Sort of.
No_Local_Protected_Objects means all requests are pre-allocated at the
library level and distributed by another protected object?
Not necessarily, see below.

With busy
Post by Dmitry A. Kazakov
waiting for a free request?
Not necessarily, see below.
Post by Dmitry A. Kazakov
When I evaluated Ravenscar for our middleware (long ago), the concern was
publisher/subscriber services. I/O queue viewed as one of them. I didn't
consider a solution like yours because the requirement was that more than
one task could await for same I/O event. You reserve the event for single
task and other publisher/subscriber services (e.g. the data logger, network
data server, health monitor etc) may not use it because of
Max_Protected_Entries = 1. The event cannot propagate because of
No_Requeue_Statements. Tasks could flood the queue with their
requests/events but they cannot do that for more than one queue.
I don't see this is an obstacle for Ravenscar. The clients could
register their interest in an event type by passing in a reference to
their IO_Response_T object, and when an event of that type occurs, the
server could call 'Set' on the list of all registered IO_Response_T
objects associated with that I/O event type.

Or am I not understanding your requirements?

Incidentally, IO_Response_T could also be modified to be just a regular
record type, or private type that contains a reference to a suspension
object. There are no Ravenscar restrictions that forbid suspension
objects from being declared at nested levels. So, if a particular task
can create multiple requests, and does not always have to wait for the
request to complete, then it should be able to declare IO_Response_T
objects at nested levels, if implemented to use suspension objects
instead of protected objects. While the client task is waiting on a
suspension object it is blocked, and thus not spin waiting (competing
for the available execution resources that it requires to run)
Post by Dmitry A. Kazakov
It seems that Ravenscar has a barrier that does not allow crossing the
border between 1-1 to 1-n or n-1.
It might do what you wanted, but it does not look scalable for the OP's
purpose.
Dmitry A. Kazakov
2014-08-31 16:15:34 UTC
Permalink
Post by Brad Moore
Post by Dmitry A. Kazakov
When I evaluated Ravenscar for our middleware (long ago), the concern was
publisher/subscriber services. I/O queue viewed as one of them. I didn't
consider a solution like yours because the requirement was that more than
one task could await for same I/O event. You reserve the event for single
task and other publisher/subscriber services (e.g. the data logger, network
data server, health monitor etc) may not use it because of
Max_Protected_Entries = 1. The event cannot propagate because of
No_Requeue_Statements. Tasks could flood the queue with their
requests/events but they cannot do that for more than one queue.
I don't see this is an obstacle for Ravenscar. The clients could
register their interest in an event type by passing in a reference to
their IO_Response_T object, and when an event of that type occurs, the
server could call 'Set' on the list of all registered IO_Response_T
objects associated with that I/O event type.
You mean one request queued in several queues? This would have a race
condition and also have no guarantee that no event is lost. The schema has
a procedure to pulse the event, as the entry is already spent. So the stuff
will leak.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Brad Moore
2014-09-01 16:15:52 UTC
Permalink
Post by Dmitry A. Kazakov
Post by Brad Moore
Post by Dmitry A. Kazakov
When I evaluated Ravenscar for our middleware (long ago), the concern was
publisher/subscriber services. I/O queue viewed as one of them. I didn't
consider a solution like yours because the requirement was that more than
one task could await for same I/O event. You reserve the event for single
task and other publisher/subscriber services (e.g. the data logger, network
data server, health monitor etc) may not use it because of
Max_Protected_Entries = 1. The event cannot propagate because of
No_Requeue_Statements. Tasks could flood the queue with their
requests/events but they cannot do that for more than one queue.
I don't see this is an obstacle for Ravenscar. The clients could
register their interest in an event type by passing in a reference to
their IO_Response_T object, and when an event of that type occurs, the
server could call 'Set' on the list of all registered IO_Response_T
objects associated with that I/O event type.
You mean one request queued in several queues? This would have a race
condition and also have no guarantee that no event is lost. The schema has
a procedure to pulse the event, as the entry is already spent. So the stuff
will leak.
No, I mean one request queued in one queue, where the processing of that
request involves calling registered callbacks in some callback list for
other clients that are interested in hearing about the servicing of that
request.
Dmitry A. Kazakov
2014-09-01 16:42:23 UTC
Permalink
Post by Brad Moore
Post by Dmitry A. Kazakov
Post by Brad Moore
Post by Dmitry A. Kazakov
When I evaluated Ravenscar for our middleware (long ago), the concern was
publisher/subscriber services. I/O queue viewed as one of them. I didn't
consider a solution like yours because the requirement was that more than
one task could await for same I/O event. You reserve the event for single
task and other publisher/subscriber services (e.g. the data logger, network
data server, health monitor etc) may not use it because of
Max_Protected_Entries = 1. The event cannot propagate because of
No_Requeue_Statements. Tasks could flood the queue with their
requests/events but they cannot do that for more than one queue.
I don't see this is an obstacle for Ravenscar. The clients could
register their interest in an event type by passing in a reference to
their IO_Response_T object, and when an event of that type occurs, the
server could call 'Set' on the list of all registered IO_Response_T
objects associated with that I/O event type.
You mean one request queued in several queues? This would have a race
condition and also have no guarantee that no event is lost. The schema has
a procedure to pulse the event, as the entry is already spent. So the stuff
will leak.
No, I mean one request queued in one queue, where the processing of that
request involves calling registered callbacks in some callback list for
other clients that are interested in hearing about the servicing of that
request.
OK. You don't need to care about Ravenscar if you use synchronous
callbacks.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Niklas Holsti
2014-08-31 18:41:15 UTC
Permalink
Post by Dmitry A. Kazakov
[...]
Post by Niklas Holsti
Did that answer your question?
Sort of.
Good.
Post by Dmitry A. Kazakov
No_Local_Protected_Objects means all requests are pre-allocated at the
library level and distributed by another protected object? With busy
waiting for a free request?
No, the _request_ in my example code is not a protected object; it is an
ordinary record type. It _refers_ to a protected object which is a kind
of "I/O wait object".

The PO "wait object" is of course statically allocated (by Ravenscar
rules). Any task that will issue I/O requests must allocate such a PO
for itself. (If the task uses several different I/O servers, which have
different "wait object" types, the task has to allocate one PO for each
such I/O server it will use.)

(Oh well, of course one could also statically allocate a shared pool of
such POs and use some kind of protocol by which tasks can reserve a PO
from the pool when they need one, but why make things difficult?)

The example code I gave assumed that each client issues at most one
request at a time, to one server, and then waits for the request to be
completed. This requires one request object (which can be locally
allocated, or can even have value-semantics and be constructed in the
I/O call as in my example code), and one PO, which can be reused for any
number of requests.

By adding request identifiers and other data-structure complexities one
can implement multiple concurrent requests, waiting for any one of
multiple requests to complete ("select"), etc.
Post by Dmitry A. Kazakov
When I evaluated Ravenscar for our middleware (long ago), the concern was
publisher/subscriber services. I/O queue viewed as one of them. I didn't
consider a solution like yours because the requirement was that more than
one task could await for same I/O event. You reserve the event for single
task and other publisher/subscriber services (e.g. the data logger, network
data server, health monitor etc) may not use it because of
Max_Protected_Entries = 1. The event cannot propagate because of
No_Requeue_Statements. Tasks could flood the queue with their
requests/events but they cannot do that for more than one queue.
You list a lot of things there... I don't really see how they are
related to each other, or if they are separate problems.

If for some reason you want to wake up two tasks when one I/O finishes,
the sample principle can be used: record two references, to two
protected objects - one per task - in the I/O request, and signal both
of them when the I/O completes.

For publish/subscribe, I would do something like this (not tested):


protected type Mailbox_T
--
-- Each subscriber has an object of this type.
--
is

procedure Signal (Event : in Event_Data_T);
-- Called by the Publisher (through Publication_Channel, see
-- below) to broadcast the Event to each subscriber.

procedure Get_Last (
Signalled : out Boolean;
Event : out Event_Data_T);
-- Called by the Subscriber to poll (ask) if a new
-- Event has been Signalled (i.e. non-blocking).

entry Await (Event : out Event_Data_T);
-- Called by the Subscriber when it wants to wait for
-- the next broadcast Event.
...

end Mailbox_T;


type Mailbox_Ref is access all Mailbox_T;
-- What the Publisher knows about a Subscriber.


protected Publication_Channel is

procedure Subscribe (
Mailbox : in Mailbox_Ref;
Success : out Boolean);
-- Called by a new Subcriber.
-- Enters the Mailbox (reference) in the subscriber list, or
-- fails if the list is full (Success returned as False).

procedure Publish (Event : in Event_Data_T);
-- Called by the Publisher to broadcast a new Event
-- to all subscribers in the list, by calling the Signal
-- operation of the Mailbox for each subscriber.

private

Subscribers : array (1 .. 100) of Mailbox_Ref;

Num_Subscribers : Natural := 0;
-- The active subscriptions are indexed 1 .. Num_Subscribers.

end Publication_Channel;


Depending on the timing and on whether it is important not to lose any
events, Mailbox_T may need an internal Event queue, or there may be a
global queue of past events to which the queue in Mailbox_T holds
references, and other such data structure refinements, all orthogonal to
Ravenscar constraints.
Post by Dmitry A. Kazakov
It might do what you wanted, but it does not look scalable for the OP's
purpose.
So far, I don't see anything in the OP's requirements that could not be
implemented with Ravenscar tasking.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Dmitry A. Kazakov
2014-09-01 16:42:19 UTC
Permalink
Post by Niklas Holsti
Post by Dmitry A. Kazakov
No_Local_Protected_Objects means all requests are pre-allocated at the
library level and distributed by another protected object? With busy
waiting for a free request?
No, the _request_ in my example code is not a protected object; it is an
ordinary record type. It _refers_ to a protected object which is a kind
of "I/O wait object".
That was clear.
Post by Niklas Holsti
Post by Dmitry A. Kazakov
When I evaluated Ravenscar for our middleware (long ago), the concern was
publisher/subscriber services. I/O queue viewed as one of them. I didn't
consider a solution like yours because the requirement was that more than
one task could await for same I/O event. You reserve the event for single
task and other publisher/subscriber services (e.g. the data logger, network
data server, health monitor etc) may not use it because of
Max_Protected_Entries = 1. The event cannot propagate because of
No_Requeue_Statements. Tasks could flood the queue with their
requests/events but they cannot do that for more than one queue.
You list a lot of things there... I don't really see how they are
related to each other, or if they are separate problems.
If for some reason you want to wake up two tasks when one I/O finishes,
the sample principle can be used: record two references, to two
protected objects - one per task - in the I/O request, and signal both
of them when the I/O completes.
That is what I said. But this is only one queue.
[...]

You don't need anything this complex so long you monitor a single channel.
The challenge is to subscribe to several channels and also to avoid
unnecessary copying of I/O data. Theoretically you could create channels
that are combinations of queues of events to monitor register them by the
queues. I don't know how much overhead it will be (I was trying to reduce
number of protected actions per event), but it looks ugly and overly
complicated.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
G.B.
2014-09-01 17:21:49 UTC
Permalink
Post by Dmitry A. Kazakov
I don't know how much overhead it will be (I was trying to reduce
number of protected actions per event), but it looks ugly and overly
complicated.
By design, and of necessity, I think, Ravenscar tasking looks ugly
and complicated for a reasons, even if not used for something close
to emulating the full Ada run-time support for tasking and I/O:
everything that you'd think is normally implied by the language,
such as some queues, requires manifestation.

Also, maybe you'd only think that this and that is implied by the
language: now what about bugs in programs using full Ada tasking?
Are they easier or more difficult to find when much more features
of concurrency are stated explicitly in Ravenscar programs?

Will a small board made for the ubiquitous, penniless underlings
working in cost-optimized production warrant a full Ada run-time?
Why, if systems are not meant to be flexible?
And what will be its overhead?
Dmitry A. Kazakov
2014-09-02 08:21:04 UTC
Permalink
Post by G.B.
Also, maybe you'd only think that this and that is implied by the
language: now what about bugs in programs using full Ada tasking?
Are they easier or more difficult to find when much more features
of concurrency are stated explicitly in Ravenscar programs?
I don't know. The most frequent bugs with tasking I had, involved
initialization/finalization issues. The second frequent bug was live-lock.
Usually a task services two sources/queues which requires load balancing.
Typical bug is when one source is serviced and other starves.
Post by G.B.
Will a small board made for the ubiquitous, penniless underlings
working in cost-optimized production warrant a full Ada run-time?
Why not? Full Ada 83 ran on 2MB mini VAX, if I correctly remember.
Post by G.B.
Why, if systems are not meant to be flexible?
And what will be its overhead?
The overhead will be maintenance of board revisions. Software maintenance
is typically 10 times more expensive in a normal software life-cycle. In an
embedded cycle it is probably 100 times. So I'd rather risk more
unnecessary flexibility than less.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
G.B.
2014-09-02 13:04:40 UTC
Permalink
Post by Dmitry A. Kazakov
Post by G.B.
Will a small board made for the ubiquitous, penniless underlings
working in cost-optimized production warrant a full Ada run-time?
Why not? Full Ada 83 ran on 2MB mini VAX, if I correctly remember.
RAM on STM32 F4 is not measured in MB or higher, AFAICT, but in KB.
Post by Dmitry A. Kazakov
Post by G.B.
Why, if systems are not meant to be flexible?
And what will be its overhead?
The overhead will be maintenance of board revisions.
I thought you were talking about overheads measured in
protected actions per event and similar.
Dmitry A. Kazakov
2014-09-02 14:18:34 UTC
Permalink
Post by G.B.
Post by Dmitry A. Kazakov
The overhead will be maintenance of board revisions.
I thought you were talking about overheads measured in
protected actions per event and similar.
x number of tasks awaiting the event, when queue of an entry is replaced by
a queue of protected object (references to) to satisfy Ravenscar
constraints + further actions to support reference counting etc. Without
Ravenscar this is either not needed or done within single action.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Jeffrey Carter
2014-09-02 16:44:42 UTC
Permalink
Post by Dmitry A. Kazakov
Why not? Full Ada 83 ran on 2MB mini VAX, if I correctly remember.
Full Ada 83 ran on a 640 KB PC.
--
Jeff Carter
"I don't know why I ever come in here. The
flies get the best of everything."
Never Give a Sucker an Even Break
102
Niklas Holsti
2014-09-02 19:02:16 UTC
Permalink
Post by Jeffrey Carter
Post by Dmitry A. Kazakov
Why not? Full Ada 83 ran on 2MB mini VAX, if I correctly remember.
Full Ada 83 ran on a 640 KB PC.
ISTR full Ada 83 ran on a 128 KB MIL-STD-1750B processor, with TLD Ada,
but I may have forgotten some limitations in the RTS -- we did not use
the RTS in the project we did back then.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Randy Brukardt
2014-09-02 23:19:46 UTC
Permalink
...
Post by Dmitry A. Kazakov
Why not? Full Ada 83 ran on 2MB mini VAX, if I correctly remember.
Full Ada 83 ran on 256K MS-DOS systems (still does, in fact). Indeed, 64K
code, 64K data was enough for programs. (The compiler needed 640K, of
course). We had a number of customers using 186 processors this way. Modern
processors would need more code memory, but 500K would be plenty.

Randy.
g***@gmail.com
2014-09-03 01:40:55 UTC
Permalink
Roy, if you ever decide to give C another shot, not necessarily for this project, try deitel and deitel C how to program, it's an easy read. and make sure you use comp.lang.c. they a active, helpful and nice too.


as a newbie, i like Ada. i hope you can do your project completely in Ada.
Roy Emmerich
2014-09-04 09:26:15 UTC
Permalink
Post by g***@gmail.com
Roy, if you ever decide to give C another shot, not necessarily for this project, try deitel and deitel C how to program, it's an easy read. and make sure you use comp.lang.c. they a active, helpful and nice too.
Thanks for the tip and thanks to all the wonderful folk on this form for their fantastically vibrant discussion. It is much appreciated!

To be honest, I am taking a serious look at www.nuttx.org. It looks very mature and there are a number of projects doing similar things that are using it (e.g. https://pixhawk.org)

I realise that from reading the Ada for Micontrollers Linkedin post and the subsequent discussions that will begin to take place at http://www.adaformicrocontrollers.com that it will be a while yet before the dust settles following the launch of the GNAT GPL for ARM. The foundations are certainly there for a great foundation to build on but for somebody like me I would feel very alone going with Ada since there is still so much low level stuff which needs to be generated and I'd prefer to be working at the system level (i.e. combining building blocks).
Post by g***@gmail.com
as a newbie, i like Ada. i hope you can do your project completely in Ada.
I will certainly keep an eye on it. Maybe for the next project or unless I can be convinced otherwise ;)

I'd better get back to reading that C book and finally come to terms with pointers...
Niklas Holsti
2014-09-04 17:58:17 UTC
Permalink
Post by Roy Emmerich
To be honest, I am taking a serious look at www.nuttx.org. It looks
very mature
The functionality certainly looks impressive, but probably not all of it
is available on the smallest targets listed -- nothing wrong with
subsets, of course.

Could this be a possible target OS for AVR-Ada, or an ARM-GNAT? That is,
implement an Ada RTS (perhaps Ravenscar-limited) on top of NuttX.

Alternatively, just run Ada code, without tasking ("no run time" option)
on top of NuttX, using the NuttX native threading system. Plenty of Ada
embedded systems have used this approach (in fact I am working now on
such an application, but not using NuttX). All you need here is an Ada
compiler such as GNAT that has the "no run time" option and generates
object code in a format that can be executed under, or linked with, the
chosen kernel.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Simon Clubley
2014-09-05 11:47:37 UTC
Permalink
Post by Niklas Holsti
Post by Roy Emmerich
To be honest, I am taking a serious look at www.nuttx.org. It looks
very mature
The functionality certainly looks impressive, but probably not all of it
is available on the smallest targets listed -- nothing wrong with
subsets, of course.
Could this be a possible target OS for AVR-Ada, or an ARM-GNAT? That is,
implement an Ada RTS (perhaps Ravenscar-limited) on top of NuttX.
Another RTOS option is RTEMS which has support for running Ada
applications. See http://www.rtems.org/ for details. I've used it in
some small hobbyist projects, but not for the last couple of years.

Simon.
--
Simon Clubley, ***@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Roy Emmerich
2014-09-09 19:04:47 UTC
Permalink
Post by Simon Clubley
Another RTOS option is RTEMS which has support for running Ada
applications. See http://www.rtems.org/ for details. I've used it in
some small hobbyist projects, but not for the last couple of years.
Thanks for this feedback Simon. Another one I found browsing through this forum is:

http://marte.unican.es/
Niklas Holsti
2014-09-01 18:39:52 UTC
Permalink
Post by Dmitry A. Kazakov
Post by Niklas Holsti
Post by Dmitry A. Kazakov
No_Local_Protected_Objects means all requests are pre-allocated at the
library level and distributed by another protected object? With busy
waiting for a free request?
No, the _request_ in my example code is not a protected object; it is an
ordinary record type. It _refers_ to a protected object which is a kind
of "I/O wait object".
That was clear.
Good, but in that case your comment, quoted above, was rather
misleading, because it clerly implies that requests are affected by
No_Local_Protected_Object.
Post by Dmitry A. Kazakov
[...]
You don't need anything this complex so long you monitor a single channel.
The challenge is to subscribe to several channels and also to avoid
unnecessary copying of I/O data.
So, explain how you do it with the full Ada tasking profile, and I'll
see if I can implement the same thing under Ravenscar rules. Or show a
simpler solution for one channel under Ravenscar rules, that would also
be interesting.

I/O data copying can be avoided by passing references and using
reference counting. I don't see any particular drawback of Ravenscar
rules here -- one either copies data from one task to another, or refers
to shared data, which then needs some sort of cross-task life-time
management.
Post by Dmitry A. Kazakov
Theoretically you could create channels
that are combinations of queues of events to monitor register them by the
queues. I don't know how much overhead it will be (I was trying to reduce
number of protected actions per event), but it looks ugly and overly
complicated.
General rule: a simpler, less powerful language (Ravenscar) leads to
more complex application programs, when the application functionality is
kept constant. You pays your money and you takes your choice.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Dmitry A. Kazakov
2014-09-02 08:19:07 UTC
Permalink
Post by Niklas Holsti
Post by Dmitry A. Kazakov
Post by Niklas Holsti
Post by Dmitry A. Kazakov
No_Local_Protected_Objects means all requests are pre-allocated at the
library level and distributed by another protected object? With busy
waiting for a free request?
No, the _request_ in my example code is not a protected object; it is an
ordinary record type. It _refers_ to a protected object which is a kind
of "I/O wait object".
That was clear.
Good, but in that case your comment, quoted above, was rather
misleading, because it clerly implies that requests are affected by
No_Local_Protected_Object.
Because you don't want to expose these objects in the interfaces. So,
normally one would use a local object or better an object on the server
side, which Ravescar prevents.
Post by Niklas Holsti
Post by Dmitry A. Kazakov
[...]
You don't need anything this complex so long you monitor a single channel.
The challenge is to subscribe to several channels and also to avoid
unnecessary copying of I/O data.
So, explain how you do it with the full Ada tasking profile, and I'll
see if I can implement the same thing under Ravenscar rules. Or show a
simpler solution for one channel under Ravenscar rules, that would also
be interesting.
You have I/O channels. You can start I/O on them. You can await for I/O
completion of the specific I/O request or any request. You can await for
I/O request completion in any channel. You can end a specific I/O request
on the channel. Emitters of I/O state changes (publishers) are not blocked
by any subscribers (e.g. no priority inversion, hence, no direct
callbacks). Event/data loss on the subscriber side is detectable. Number of
protected actions per event is constant.
Post by Niklas Holsti
I/O data copying can be avoided by passing references and using
reference counting.
Reference counting requires further protected actions for dealing with
counters and this is the number of waiting tasks x the number of operations
x fixed multiplicand, at least, 2. In my design a lock-free-read blackboard
is used, but that has issues with Ravenscar's entry count limitation at the
write-end.
Post by Niklas Holsti
Post by Dmitry A. Kazakov
Theoretically you could create channels
that are combinations of queues of events to monitor register them by the
queues. I don't know how much overhead it will be (I was trying to reduce
number of protected actions per event), but it looks ugly and overly
complicated.
General rule: a simpler, less powerful language (Ravenscar) leads to
more complex application programs, when the application functionality is
kept constant. You pays your money and you takes your choice.
This is certainly true. Ada has enough silly limitations to add Ravenscar
on top of it. From the software and general engineering POV you better
invest in advance into reusable stuff, e.g. into the language, into
libraries, than face complexity later at the application side.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Dennis Lee Bieber
2014-08-28 13:10:40 UTC
Permalink
On Thu, 28 Aug 2014 03:12:16 -0700 (PDT), Roy Emmerich
Post by Roy Emmerich
I want to use a finite state machine (FSM) approach. There will be a supervisor module which will instantiate sub-modules which communicate with peripherals. Each sub-module will be a separate sub-FSM, reporting its state to the supervisor. Each sub-module will make use of a protocol library (e.g. MODBUS RTU) and a hardware driver library (e.g. UART over RS485/232) to communicate with devices.
Your supervisor module will, in essence, be a minimal OS if it has to
handle switching among the I/O modules while also handling an upper level
application vs the "simpler" "direct" approach (if an application wants to
send something over a serial port, that is all it is doing until the
transaction is complete -- then it can look at some other device; or the
devices are all linked to an interrupt handler to collect inbound/transmit
outbound data through buffers that the application later reads/writes --
but that needs a protocol to identify when the application layer is allowed
to transfer data).

They aren't cheap, and for being three volumes in a course sequence,
were written such that each duplicates most of the first third (how many
people working a microcontroller really need to see how to build a binary
full adder circuit from logic gates?) -- they also focus on the Texas
Instrument Launchpad boards -- but those are ARM Cortex-M4 so the
information should be portable.

http://www.amazon.com/Embedded-Systems-Introduction-Cortex-Microcontrollers/dp/1477508996/ref=sr_1_1?ie=UTF8&qid=1409231142&sr=8-1&keywords=valvano
http://www.amazon.com/Embedded-Systems-Real-Time-Interfacing-Microcontrollers/dp/1463590156/ref=sr_1_2?ie=UTF8&qid=1409231142&sr=8-2&keywords=valvano
http://www.amazon.com/Embedded-Systems-Real-Time-Operating-Microcontrollers/dp/1466468866/ref=sr_1_3?ie=UTF8&qid=1409231142&sr=8-3&keywords=valvano

First and third may be the desired pair for your level. As mentioned,
the introductory material tends to be duplicated between them. Introduces
the ARM Cortex assembly language.
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Dennis Lee Bieber
2014-08-29 02:52:09 UTC
Permalink
On Thu, 28 Aug 2014 09:10:40 -0400, Dennis Lee Bieber
Post by Dennis Lee Bieber
http://www.amazon.com/Embedded-Systems-Introduction-Cortex-Microcontrollers/dp/1477508996/ref=sr_1_1?ie=UTF8&qid=1409231142&sr=8-1&keywords=valvano
http://www.amazon.com/Embedded-Systems-Real-Time-Interfacing-Microcontrollers/dp/1463590156/ref=sr_1_2?ie=UTF8&qid=1409231142&sr=8-2&keywords=valvano
http://www.amazon.com/Embedded-Systems-Real-Time-Operating-Microcontrollers/dp/1466468866/ref=sr_1_3?ie=UTF8&qid=1409231142&sr=8-3&keywords=valvano
First and third may be the desired pair for your level. As mentioned,
the introductory material tends to be duplicated between them. Introduces
the ARM Cortex assembly language.
I downgraded the middle as the assignment of GPIO pins, A/D converters,
etc. tends to be specific to the chip -- the ARM Cortex is just the
processor portion, and each maker adds their own peripheral devices onto
the silicon.
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
David Thompson
2014-09-20 20:50:56 UTC
Permalink
On Wed, 27 Aug 2014 09:08:07 -0400, Dennis Lee Bieber
<***@ix.netcom.com> wrote:
<snip>
Post by Dennis Lee Bieber
Do you have any experience with assembler (any) -- since so much of C
mapped to the PDP series instruction set (pre/post increment/decrement
operators, for example).
That's not really true -- and the related idea that these operators
are *based on* hardware is an urban legend. The PDP-11 (but not other
quite different machines in DEC's PDP "family") has post-inc and
pre-dec (not pre-inc and post-dec) for pointers that happen to be in
registers, and if you look at it slantways pre-inc and pre-dec for
8-bit or 16-bit integers. C has all 4 operations on all scalar data
types, and predecessor B had all 4 on its sole data type "word".

Ritchie's paper on C in ACM HOPL 2 used to be available on his
bell-labs page, and I saw it still there after his death, but it's
Post by Dennis Lee Bieber
Thompson went a step further by inventing the ++ and -- operators,
which increment or decrement; their prefix or postfix position
determines whether the alteration occurs before or after noting
the value of the operand. They were not in the earliest versions
of B, but appeared along the way. People often guess that they were
created to use the auto-increment and auto-decrement address modes
provided by the DEC PDP-11 on which C and Unix first became popular.
This is historically impossible, since there was no PDP-11 when B
was developed. The PDP-7, however, did have a few `auto-increment'
memory cells, with the property that an indirect memory reference
through them incremented the cell. This feature probably suggested
such operators to Thompson; the generalization to make them both
prefix and postfix was his own. Indeed, the auto-increment cells
were not used directly in implementation of the operators, and a
stronger motivation for the innovation was probably his observation
that the translation of ++x was smaller than that of x=x+1.
A confirming post is available at http://yarchive.net/comp/c.html .

OTOH the ambiguity whether C type 'char' is signed or unsigned does
trace largely to the PDP-11 preferring sign extension (MOVB) where
other systems either don't or have an equal choice.
Post by Dennis Lee Bieber
C, itself, is a fairly small language -- it's main feature being also
its main problem: it assumes the programmer knows what they are doing and
offers easy access to (mis)treating data as addresses in memory.
Or treating garbage as addresses. Or garbage as data.
Post by Dennis Lee Bieber
If you are familiar with Java AND with disciplined software
development, a copy of the K&R book for C should be all you need to learn
the language itself (in my world, it was the even smaller first edition K&R
with my experience of FORTRAN, COBOL, Pascal, and Assembler -- circa 1982).
Bearing in mind that even K&R 2ed is C89 aka C90 and there are
two later versions of the C standard (three if you count C90 NA1).
Although if you understand K&R2 well and some language-independent
fundamentals, looking at the specific items called out as changes in
C99 and C11 may be enough. And if you don't want to pay for the actual
standards, committee drafts that are equivalent for all practical
purposes are free-beer on http://www.open-std.org/jtc1/sc22/wg14/ .
Post by Dennis Lee Bieber
C++, OTOH... THAT is a nightmare language to pick up... Do NOT think of
it as just a more powerful C.
Post by r***@gmail.com
1. www.espruino.com (JavaScript)
Interpreted... And not even full Java... I've not looked at the link --
JavaScript is the "native" language for the BeagleBone Black, as I recall.
Javascript and Java are almost completely unrelated except for the
latters J a v a and a little syntax copied from C. As wikipedia
correctly says, Javascript semantics are closer to Scheme.

<snip rest>

Mike Silva
2014-08-27 16:17:24 UTC
Permalink
Roy,

The problem with reuse is that it is hardly ever as clean and simple as one would hope. In my experience, by the time you find some code, determine if it meets your needs, identify the areas that will need to be changed, and figure out how to bind to it if in C, it would have been quicker to write the code from scratch (perhaps using the code you found as a general guide). I don't claim that's a universal, just my experience.

For example, on the MODBUS drivers, I've used such code in the past, and even though our company paid for custom drivers, we spent a lot of time fixing and adjusting them. I doubt we gained anything over writing from scratch (using whatever code we could have found as a guide).

Speaking of reuse, since you're just discovering Ada, you should read about the Ariane 5 reuse fiasco (which some people foolishly tried to blame on the use of Ada, but which is really about the perils of reuse of perfectly good code).
Roy Emmerich
2014-08-27 16:36:23 UTC
Permalink
Hi Mike,
Post by Mike Silva
The problem with reuse is that it is hardly ever as clean and simple as one
would hope.
Funny you say that. I've spent the last 3 days coming to grips with a ublox GPS receiver, spending much time deeply immersed in the documentation and fiddling with bits and bytes.

To get up to speed I just found a few example libraries written in C and Arduino speak and created my own in JavaScript. It works! So effectively I've already started doing this but thanks for the further encouragement! One can never get enough...
Post by Mike Silva
Speaking of reuse, since you're just discovering Ada, you should read about the
Ariane 5 reuse fiasco (which some people foolishly tried to blame on the use of
Ada, but which is really about the perils of reuse of perfectly good code).
Oh, my, word!!! You see, that's why I don't like working on rockets :)
Simon Clubley
2014-08-27 16:58:43 UTC
Permalink
Post by Roy Emmerich
Hi Mike,
Post by Mike Silva
The problem with reuse is that it is hardly ever as clean and simple as one
would hope.
Hello Roy,

First off, welcome to the world of Ada.

Second, when you reply to messages, can you please leave the attributions
at the start of the message in place so we can see who you are replying to.

If you don't do that, then it's impossible to see who is replying to who
especially when you are a couple of levels deep into a conversation.

Thanks.

Simon.

PS: In case you are not aware, the Google Groups client you are using
is _not_ Usenet; it is merely an interface to the global distributed
network which _is_ Usenet and which was around long before Google came
onto the scene. I tell you this before you wonder why people can't
just scroll back up in the client you happen to be using.

As a result of Usenet's nature, there are many Usenet clients; for
example I use a client known as slrn.

PPS: I hope you enjoy Ada.
--
Simon Clubley, ***@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
j***@googlemail.com
2014-08-29 19:36:09 UTC
Permalink
The GNAT compiler comes with a collection of packages that
might make using ravenscar easier.

If you download the the GNAT source code (from
the Libre site) then you'll find the code in the
gnatcoll directory:

.../x86_64-linux/adagpl-2014/gnatcoll/gnatcoll-gpl-2014-src/src

The code itself looks intimidating, but most of
the .ads files have sample code that shows how to
use them. Here's the list:

gnatcoll-ravenscar-utils.ads
gnatcoll-ravenscar-utils.adb
gnatcoll-ravenscar-timers-one_shot_timer.ads
gnatcoll-ravenscar-timers-one_shot_timer.adb
gnatcoll-ravenscar-timers.ads
gnatcoll-ravenscar-timed_out_sporadic_server.ads
gnatcoll-ravenscar-timed_out_sporadic_server.adb
gnatcoll-ravenscar-sporadic_server_with_callback.ads
gnatcoll-ravenscar-sporadic_server_with_callback.adb
gnatcoll-ravenscar-sporadic_server.ads
gnatcoll-ravenscar-sporadic_server.adb
gnatcoll-ravenscar-simple_sporadic_task.ads
gnatcoll-ravenscar-simple_sporadic_task.adb
gnatcoll-ravenscar-simple_cyclic_task.ads
gnatcoll-ravenscar-simple_cyclic_task.adb
gnatcoll-ravenscar-multiple_queue_sporadic_server.ads
gnatcoll-ravenscar-multiple_queue_sporadic_server.adb
gnatcoll-ravenscar-multiple_queue_cyclic_server.ads
gnatcoll-ravenscar-multiple_queue_cyclic_server.adb
gnatcoll-ravenscar.ads

Also

http://www.adacore.com/adaanswers/gems/gem-89-code-archetypes-for-real-time-programming-part-1/

might help.


-- Jonathan
Stephen Leake
2014-08-30 15:06:29 UTC
Permalink
Post by j***@googlemail.com
The GNAT compiler comes with a collection of packages that
might make using ravenscar easier.
If you download the the GNAT source code (from
the Libre site) then you'll find the code in the
gnatcoll is a package in its own right; no need to download the GPS
source.
--
-- Stephe
r***@gmail.com
2014-09-02 21:40:51 UTC
Permalink
Post by r***@gmail.com
I discovered Ada 2 days ago, so stick with me.
I am starting a business which will focus on creating a cheap, modular, open
source data logger/controller usable across multiple domains. At the moment I
...
A few biased remarks from the original author of AVR-Ada. I wouldn't completely exclude the AVR microcontrollers from your thoughts.

1. They are reasonably priced. You can start with some hobby boards like some Arduino clones for less than 20 EURO.

2. a data logger typically does not need the processing power of the 32bit ARM mcus. With a step up dcdc converter and well choosen sleep modes you can run your logger for years on a single AA battery.

3. You can program them in Ada. See the AVR-Ada project on SF: http://sourceforge.net/p/avr-ada/wiki/Home/
The project includes drivers for
- I2C (called TWI on AVR),
- OneWire (you can get lots of quite cheap sensors for the OneWire bus)
- debouncing code for direct inputs like keys or switches
- UART for a serial console
- FAT filesystem for writing your collected data to a (micro)SD card

Admittedly you don't get tasking with AVR-Ada. Despite all the discussions in this thread I don't think it would be helpful in your case anyway. You can read out all your sensors and write them to the SD card in a single loop. Even if you do that several times per second (e.g. for filtering your input data) your board will be in sleep mode most of the time.

3 There is a big community for related electronics and programming on mikrocontroller.net. It's mostly in German language, some discussions are in English, too.

4 There is small but very helpful bunch of people on the AVR-Ada devel mailing list. I know that at least one of them once programmed data acquisition and control systems (SCADA) professionally :-)

HTH
Rolf
Roy Emmerich
2014-09-04 10:00:40 UTC
Permalink
Post by r***@gmail.com
A few biased remarks from the original author of AVR-Ada. I wouldn't completely exclude the AVR microcontrollers from your thoughts.
1. They are reasonably priced. You can start with some hobby boards like some Arduino clones for less than 20 EURO.
2. a data logger typically does not need the processing power of the 32bit ARM mcus. With a step up dcdc converter and well choosen sleep modes you can run your logger for years on a single AA battery.
3. You can program them in Ada. See the AVR-Ada project on SF: http://sourceforge.net/p/avr-ada/wiki/Home/
The project includes drivers for
- I2C (called TWI on AVR),
- OneWire (you can get lots of quite cheap sensors for the OneWire bus)
- debouncing code for direct inputs like keys or switches
- UART for a serial console
- FAT filesystem for writing your collected data to a (micro)SD card
Admittedly you don't get tasking with AVR-Ada. Despite all the discussions in this thread I don't think it would be helpful in your case anyway. You can read out all your sensors and write them to the SD card in a single loop. Even if you do that several times per second (e.g. for filtering your input data) your board will be in sleep mode most of the time.
3 There is a big community for related electronics and programming on mikrocontroller.net. It's mostly in German language, some discussions are in English, too.
4 There is small but very helpful bunch of people on the AVR-Ada devel mailing list. I know that at least one of them once programmed data acquisition and control systems (SCADA) professionally :-)
Thanks for your super response Rolf. Although a simple data logger doesn't need a 32 bit processor, my solution is intended as a multi-purpose logger/controller platform. I have many other applications in mind, the first and simplest being a data logger for the (lower end) renewable energy industry.

What I am aiming to do is (hopefully) use one processor or family of processors and stick with them. It should be able to (at the same time) communicate with a GPS receiver, a GSM transciever, perform RS485/232 communication as well as CAN communication. It should also be able to host custom control algorithms, switch relays on and off, have a number of analogue/digital in/outputs. I would also like to be able to do precise time synchronisation with precision time protocol (supported by the STM32F4) for certain scientific applications and I am sure there are other desires that will surface once the basics are in place.

I have the feeling AVR micros would run out of puff when faced with this list of requirements?
Continue reading on narkive:
Loading...