Updated: Apr 10
In this post you will get an overview of the resources you have at your disposal when developing your devices, some of them will allow you to add functionality to your system while others will determine the way it behaves as a piece of metal responding to impulses, both internal and external.
STRUCTURAL VS BEHAVIORAL RESOURCES
I like to separate these two topics, under the Structural umbrella I will describe all the resources (both physical and APIs) that can be used to define the architecture of your device, on the other hand, the Behavioral umbrella will cover every resource, again, both physical and API that will provide you some help to do what ever you want to do. If you are a software engineer it would be similar to separating technical and functional features. Both types of resources will enable you to achieve your goals.
I will also share the way I see any project because I think it is a simple way to do it. I like to match my goals with some features and try to identify how each feature supports my goals, sometimes, I even set a weight to each specific feature; this approach allows me to clearly identify what is relevant for me. I tend to set those relationships as simple graphics to connect dots. I use circles to represent goals and rectangles to represent features. I am sharing this ideas because I think it is a good way to keep things under control from the very beginning, even to determine if I am being too ambitious on my goals considering the type of equipment or software I will employ. As an example I will use my devices; in the next graphic you will see how each goal is supported by something.
This graphic is good for two reasons, the first one is that it puts a context for these posts. This is the kind of device we are going to explore through the pages of this work.
The second good point about it is that it shows a constraint (The yellow rectangle), something that affects features, that imposition comes from the nature of the problem to solve. EDGE solutions must be power efficient because, in most cases, they will be deployed in areas where energy sources are not abundant. In other words, these devices must run on Batteries and make them last a lot of time.
While most of the equipment I use is proven to be power efficient in the way they are fabricated, we are responsible of not abusing from power consumption. A quick example: Cameras broadcasting image samples all the time won’t do any favor to the goal of making the device last as long as it can with a single charge of energy. Besides the high level separation I made before, power consumption will be something that will have to be addressed across the entire project.
To get into the subject, this simple graphic will show you all the resources you have at hand by using the Spresense (No matter if you use the Arduino IDE platform or the native SDK, the arrangement of the packages might be different though and others more visible on the SDK, such is the case of the API provided to support the board by the Operating System)
In this graphic you see a clear separation of some of the Spresense features, some of them oriented to help you in the architectural design of your
device, others will help you to add functionality and a third one in the middle that are generic for both domains. In the Structural features you see three packages, again, their names and packing will change if you use the Arduino IDE extension or the native SDK, but the general concepts will remain the same. We will focus first on the first column and some things in the middle; the following is a brief description of each package (plus something inherited from the NuttX POSIX interface which is something quite useful to further take advantage of a device).
The multi-core library (or ASMP for Asymmetric Multi Processing) is the package that contains everything you need to manage each core on the Spresense, manage their statuses and you will find there some easy ways to communicate information between cores such as messaging, shared portions of memory and the like. Some other packages will contribute to this multi-core architecture to make it even more stable and effective, specially, two of them, the pthread implementation on the NuttX (more details about this below) and the watchdog. As mentioned before, the power management package will allow you to affect the entire device by, for instance, specifying at what clock speed you want the processor to work (slower clock speed will use less energy, more on this below).
The Sensing Library (or Sensor control unit) and this is my particular view on things,you might think of sensing capabilities of the Spresense as something related with functionality, however, this package imposes a particular architecture for your device (alongside with other related DSP, Digital Signal Processing). In this package you will find an already made publisher / subscriber method for dealing with the data gathered by the sensors connected to the Spresense. I have to mention that you can use this effective way or the pin reading according to your needs and type of sensor / driver.
As complementary resources you will find some packages like those related with the board management (including PIN definitions, watchdogs and, of course the power management utilities) that will allow you to manipulate the necessary resources on the Spresense.
Why is POSIX important? POSIX is a standard (IEEE, some ANSI C related things too) that defines a series of interfaces that an Operating System should implement. POSIX stands for Portable Operating System Interface. It defines a series of system calls (among other things) dealing with tasks, shared memory, concurrency and more; here the key word is portable.
Portable means that your code will compile OK on any system implementing those interfaces. The Native Spresense SDK has some mp_task* high level calls you can use but you still can use the pthread functions in your code, so, if you have code written using these standard you won’t have the extra cost of porting it. Code is an investment and an asset, standards are important to make it sure your code will be usable for a long time.
The application domain of the Spresense is divided into six cores, one of the them is the main core and it is responsible for keeping the rest under control, that means, initializing the rest of the cores, sharing information and notifications with them. The key difference is all the entire functionality on the Spresense can be executed on main core and some of them cannot be executed on the sub-cores; and allow me to say that that makes sense since a sub-core cannot compromise the controlling unit (for instance by changing the clock speed)
Having multiple cores is a good thing for two reasons, one could be performance and responsiveness and the other one a clear functionality separation. Small and simple things are a great design principle, that’s the way UNIX was designed a long time ago and it is still healthy today. Pipelines to allow small functional units to cooperate for a higher goal was a very good thing.
We will start covering the details of each API in the upcoming posts. For now, keep the pipeline concept in your mind, it will be useful; next post will complete the view on the behavioral packages.