I have an aplication running on a K64F board with ARM Mbed OS. I takes advantage of the RTOS capabilities and is runnign some different threads to perform various actions. Communication between threads is done using queues defined as global variables on the first part of the code (as defined in the RTOS examples).
MemoryPool<cMsg, 16> NMPool;
Queue<cMsg, 16> NMQueue;
This way every thread can access the queue.
I want to convert these threads to uvisor isolated boxes. I have succesfully run independent threads this way but I have found no way of sharing common variables among diferent boxes. I have found no reference on how to make available the variables to the code defined in the box files that are compiled as a single project using uvisor. Any idea, example or help?
You cannot share memory between boxes, uVisor boxes run in isolated memory spaces (which is the whole point of using uVisor).
The only way to communicate between boxes is through RPC channels. See this article under the 'Expose public secure entry points to the secure box' section.
I think you can only pass primitives and struct's (because they're fixed size) over the RPC channel, but that's worth an experiment.
Related
I need to develop device libraries like uBlox, IMUs, BLE, ecc.. from scratch (almost). Is there any doc or tutorial that can help me?
Question is, how to write a device library using C/C++ (Arduino style if you want) given a datasheet and a platform like STM32 or other ARMs?
Thanks so much
I've tried to read device libraries from Arduino library and various Github, but I would like to have a guide/template to follow (general rules) to write proper device libraries from a given datasheet.
I'm not asking a full definitive guide, just where to start, docs, methods approach.
I've found this one below, but is very basic and quite lite for my targets.
http://blog.atollic.com/device-driver-development-the-ultimate-guide-for-embedded-system-developers
I don't think that you can actually write libraries for STM32 in Arduino style. Most Arduino libraries you can find in the wild promote ease of usage rather than performance. For example, a simple library designed for a specific sensor works well if reading the sensor and reporting the results via serial port is the only thing that firmware must do. When you work on more complex projects where uC has lots to do and satisfy some real time constraints, the general Arduino approach doesn't solve your problems.
The problem with STM32 library development is the complex connection between peripherals, DMA and interrupts. I code them in register level without using the Cube framework and I often find myself digging the reference manual for tables that shows the connections between DMA channels or things like timer master-slave relations. Some peripherals (timers mostly) work similar but each one of them has small differences. It makes development of a hardware library that fits all scenarios practically impossible.
The tasks you need to accomplish are also more complex in STM32 projects. For example, in one of my projects, I fool SPI with a dummy/fake DMA transfer triggered by a timer, so that it can generate periodic 8-pulse trains from its clock pin (data pins are unused). No library can provide you this kind of flexibility.
Still, I believe not all is lost. I think it may be possible to build an hardware abstraction layer (HAL, but not The HAL by ST). So, it's possible to create useful libraries if you can abstract them from the hardware. A USB library can be a good example for this approach, as the STM32 devices have ~3 different USB peripheral hardware variations and it makes sense to write a separate HAL for each one of them. The upper application layer however can be the same.
Maybe that was the reason why ST created Cube framework. But as you know, Cube relies on external code generation tools which are aware of the hardware of each device. So, some of the work can be avoided in runtime. You can't achieve the same result when you write your own libraries unless you also design a similar external code generation tool. And also, the code Cube generates is bloated in most cases. You trade development time for runtime performance and code space.
I assume you will be using a cross toolchain on some platform like Linux, and that the cross toolchain is compatible with some method to load object code on the target CPU. I also assume that you already have a working STM32 board that is documented well enough to figure out how the sensors will connect to the board or to the CPU.
First, you should define what your library is supposed to provide. This part is usually surprisingly difficult. It’s a bit hard to know what it can provide, without knowing a bit about what the hardware sensors are capable of providing. Some iteration on the requirements is expected.
You will need to have access to the documentation for the sensors, usually in the form of the manufacturer’s data sheets. Using the datasheet, and knowing how the device is connected to the target CPU/board, you will need to access the STM32 peripherals that comprise the interface to the sensors. Back to the datasheets, this time for the STM32, to see how to access its peripheral interfaces. That might be simple GPIO bits and bytes, or might be how to use built-in peripherals such as SPI or I2C.
The datasheets for the sensors will detail a bunch of registers, describing the meaning of each, including the meanings of each bit, or group of bits, in certain registers. You will write code in C that accesses the STM32 peripherals, and those peripherals will access the sensors across the electrical interface that is part of the STM32 board.
The workflow usually starts out by writing to a register or three to see if there is some identifiable effect. For example, if you are exercising a digital IO port, you might wire up an LED to see if you can turn it on or off, or a switch to see if you can correctly read its state. This establishes that your code can poke or peek at IO using register level access. There may be existing helper functions to do this work as part of the cross toolchain. Or you might have to develop your own, using pointer indirection to access memory mapped IO. Or there might be specially instructions needed that can only be accessed from inline assembler code. This answer is generic as I don’t know the specifics of the STM32 processor or its typical ecosystem.
Then you move on to more complex operations that might involve sequences of operations, like cycling a bit or two to effect some communication with the device. Or it might be as simple as finding the proper sequence of registers to access for operation of a SPI interface. Often, you will find small chunks of code are complete enough to be re-used by your driver; like how to read or write an individual byte. You can then make that a reusable function to simplify the rest of the work, like accessing certain registers in sequence and printing the contents of register that you read to see if they make sense. Ultimately, you will have two important pieces of information: and understanding of the low-level register accesses needed to create a formal driver, and an understanding of what components and capabilities make up the hardware (ie, you know how the device(s) work).
Now, throw away most of what you’ve done, and develop a formal spec. Use what you now know to include everything that can be useful. Use what you now know to develop a spec that includes an appropriate interface API that your application code can use. Rewrite the driver, armed with the knowledge of how are the pieces work, and taking advantage of the blank canvas afforded you by the fresh rewrite of the spec. Only reuse code that you are completely confident is optimal and appropriate to the format dictated by the spec. Write test code for all of the modules, and use the test code to actually test that the code works and that it conforms to the spec. Re-use the test code every time you modify anything it tests.
The situation is that multiple MIB custom handlers that access a hardware component if ever there was a time where 2 handlers we running in parallel it would cause errors. NOTE: Get and Set request use the same hardware component.
Net-SNMP is single-threaded. It can only run one piece of code at a time.
Net-SNMP is a protocol stack and not the framework, to make it run on the required platform or hardware you need to give the specific environment or encapsulation which can pick and poke hardware entities and other housekeeping.
For example: A single SNMP stack can run on distributed system having multiple blades and OS instances. And therefore scaling needs to be done by the platform.
I am writing a block device driver for linux.
It is crucial to support unsafe removal (like usb unplug). In other words, I want to be able to shut down the block device without creating memory leaks / crashes even while applications hold open files or performing IO on my device or if it is mounted with file system.
Surely unsafe removal would possibly corrupt the data which is stored on the device, but that is something the customers are willing to accept.
Here is the basics steps I have done:
Upon unsafe removal, block device spawns a zombie which will automatically fail all new IO requests, ioctls, etc. The zombie substitutes make_request function and changes other function pointers so kernel would not need the original block device.
Block device waits for all IO which is running now (and use my internal resources) to complete
It does del_gendisk(); however this does not really free's kernel resources because they are still used.
Block device frees itself.
The zombie keeps track of the amount of opens() and close() on the block device and when last close() occurs it automatically free() itself
Result - I am not leaking the blockdevice, request queue, gen disk, etc.
However this is a very difficult mechanism which requires a lot of code and is extremely prone to race conditions. I am still struggling with corner cases, per_cpu counting of io's and occasional crashes
My questions: Is there a mechanism in the kernel which already does that? I searched manuals, literature, and countless source code examples of block device drivers, ram disks and USB drivers but could not find a solution. I am sure, that I am not the first one to encounter this problem.
Edited:
I learned from the answer below, by Dave S about the hot-plug mechanism but it does not help me. I need a solution of how to safely shut down the driver and not how to notify the kernel that driver was shut down.
Example of one problem:
blk_queue_make_request() registers a function through which my block devices serves IO. In that function I increment per_cpu counters to know how many IO's are in flight by each cpu. However there is a race condition of function being called but counter was not increased yet, so my device thinks there are 0 IO's, releases the resources and then IO comes and crashes the system. Hotplug will not assist me with this problem as far as I understand
About a decade ago I used hotplugging on a software driver project to safely add/remove an external USB disk drive which interfaced to an embedded Linux driven Set-top Box.
For your project you will also need to write a hot plug. A hotplug is a program which is used by the kernel to notify user mode software when some significant (usually hardware-related) events take place. An example is when a USB device has just been plugged in or removed.
From Linux 2.6 kernel onwards, hotplugging has been integrated with the driver model core so that any bus or class can report hotplug events when devices are added or removed.
In the kernel tree, /usr/src/linux/Documentation/usb/hotplug.txt has basic information about USB Device Driver API support for hotplugging.
See also this link, and GOOGLE as well for examples and documentation.
http://linux-hotplug.sourceforge.net/
Another very helpful document which discusses hotplugging with block devices can be found here:
https://www.kernel.org/doc/pending/hotplug.txt
This document also gives a good example of illustrating hotplug events handling:
Below is a table of the main variables you should be aware of:
Hotplug event variables:
Every hotplug event should provide at least the following variables:
ACTION
The current hotplug action: "add" to add the device, "remove" to remove it.
The 2.6.22 kernel can also generate "change", "online", "offline", and
"move" actions.
DEVPATH
Path under /sys at which this device's sysfs directory can be found.
SUBSYSTEM
If this is "block", it's a block device. Anything other subsystem is
either a char device or does not have an associated device node.
The following variables are also provided for some devices:
MAJOR and MINOR
If these are present, a device node can be created in /dev for this device.
Some devices (such as network cards) don't generate a /dev node.
DRIVER
If present, a suggested driver (module) for handling this device. No
relation to whether or not a driver is currently handling the device.
INTERFACE and IFINDEX
When SUBSYSTEM=net, these variables indicate the name of the interface
and a unique integer for the interface. (Note that "INTERFACE=eth0" could
be paired with "IFINDEX=2" because eth0 isn't guaranteed to come before lo
and the count doesn't start at 0.)
FIRMWARE
The system is requesting firmware for the device.
If the driver is creating device it could be possible to suddenly delete it:
echo 1 > /sys/block/device-name/device/delete where device-name may be sde, for example,
or
echo 1 > /sys/class/scsi_device/h:c:t:l/device/delete, where h is the HBA number, c is the channel on the HBA, t is the SCSI target ID, and l is the LUN.
In my case, it perfectly simulates scenarios for crushing writes and recovery of data from journaling.
Normally to safely remove device more steps is needed so deleting device is a pretty drastic event for data and could be useful for testing :)
please consider this:
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/online_storage_reconfiguration_guide/removing_devices
http://www.sysadminshare.com/2012/09/add-remove-single-disk-device-in-linux.html
I am hung up on how to move forward with FreeRTOS in my application. Let me propose a simple scenario. Assume I have main and a module which has some hardware specific code. This code could be for controlling a specific motor in a system or a sensor... any bit of hardware with a defined role. Within module.c I have a function called ModuleNameTask. In main I create the task using xTaskCreate and I pass ModuleNameTask. Since my ModuleNameTask is defined in module.c and not main.c, I now have to include bits of FreeRTOS within module.c in order to use functions like vTaskDelay. I don't like the fact that I am including these files within module.c as I feel its no longer portable.
So, how do I handle this? Should I remove that ModuleNameTask from module.c and place it in main.c? Or just accept the fact that I have to include bits of FreeRTOS into module.c. Any advice?
What functionality do you require from FreeRTOS for your module to work. Obviously there are some things or you wouldn't need to include the headers and you wouldn't be calling the functions.
Take these functions and put them in a separate header called os/<operating_sys>/freertos.h and wrap them in your own function names (e.g. my_createtask(<args>).). Now to port to a different OS you will need to provide a new file with new wrappers for your own functions.
If you do this poorly you'll notice that your createtask function looks exactly like the FreeRTOS function and can be easily mapped but when you want to use linux/vxWorks/other OS that the function doesn't have the right arguments.
Your createtask function should only contain the parameters that you care about. The others should be hard coded in the wrapper. This will make it easier to port (you'll have different parameters to hard code in other operating systems).
Abstract both the RTOS and the device layer.
Define an OS interface of your design (this may only be a subset of FreeRTOS functionality or even include higher level interfaces implemented using RTOS primitives) and implement this interface using FreeRTOS.
You then define your entire application including your device layer using only your RTOS abstraction layer interface. When you port your application to another platform or RTOS, you only need change the abstraction layer implementation, being sure to maintain the same semantics as the original implementation. If the device layer is also suitably abstracted so as to be able to be generic across different hardware you can do the same for hardware dependencies (i.e. abstract them from the physical implementation).
I have successfully used this approach for many years, using an RTOS abstraction in C++ that I have ported to FreeRTOS, VxWorks, Segger embOS and Keil RTX and even Windows and Linux (for test and simulation). You need not of course use C++, but it is well suited to the task.
In your abstraction you need to consider the following:
Threading
IPC (queues, pipes, event flags, mailboxes etc.)
Synchronisation (mutex, semaphores)
Timers
Interrupt handlers
Your interface might look very different from FreeRTOS itself, and it may be worth looking at a number of other RTOS interfaces to see what kind of features yours may need.
I noticed that on a single threaded application, SDL still spawns some threads on initialization. It's usually not of my concern by I noticed cURL requires its initialization to be done before any thread creation for thread-safety. Can they generally be ignored [for cURL initialization] or not? [Also, are they just a sign of using an external library etc.?]
grepping the source, it looks like the audio subsystem can utilize threading on most platforms, as well as the event subsystem on some platforms (mostly X11 it seems).
cURL requires its initialization to be done before any thread creation for thread-safety
It doesn't mean the universe will implode if you create any thread (well, you've already created one by starting the process) before initialising it. It means that you can't have multiple threads calling cURL routines before initialisation (because it has to create synchronisation primitives, etc.).
Since SDL doesn't call cURL at any point, the initialisation order doesn't matter in this case.