I was wandering, why there are no implementations of the devices written in CMSIS-Driver?
I mean that I have few peripherals: LCD, temperature and pressure sensor, current meter etc. - all of them very popular used in arduino and learning sets.
Each of these devices uses some protocol to communicate with the uC. some are for i2C, some communicate by SPI, some by UART. I was wondering if there are drivers that handle those devices, and as a backend use CMSIS-Driver API.
I think that it is a decent api, and after all standard develop by ARM, so why I can not find any drivers using it?
For example when I was looking for s18b20 (temperature sensor for 1-wire), I was easily able to find driver for this device written in RUST language, but I was not able to find any implementation for C that would use CMSIS. (in this case compare to rust is quite solid, because Rust has nice embedded API, and you can easily use the driver on multiple targets, just like CMSIS-Driver is spouse to work)
I was able to find some projects using this peripheral, but they all operated on HAL that is different for every uC, so the implementation is not portable ( unlike RUST, and potentially CMSIS-Driver)
So my main questions are:
Why there are so little implementations based on CMSIS-Driver? Maybe there is some hidden implementation repository that I do not know about?
Am I missing something? Is the CMSIS-Driver not designed for the casual developers? Who is it designed for then ?
CMSIS is not concerned with external devices, it deals primarily with interface drivers for interfaces on the microcontroller die. So if you have an SPI device, you might use the CMSIS. SPI driver for that part, but it is then your responsibility as a developer to write the higher-level driver for the external device.
Higher-level software platforms such as ARM's embed, or ST's CubeMX use CMSIS interface drivers, and include drivers for common higher level devices. They tend to be for more complex devices related to networking, filesystems and displays. I would not expect much support for such trivially simple devices such as a temperature sensor.
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.
I am post-newbie to Embedded Linux driver development, have developed Character, UART & simple USB drivers, and have worked with SBC (Raspberry Pi 2). My main learning resources are: Essential Linux Device Drivers, Embedded Linux System Design & Development, youtube tutorials and LDD3. Because of lack of real life driver experience, I have some questions that I would like to share:
Templates: are there some sort of driver templates for speeding up the coding process e.g. have the regularly used structures & functions for being modified & customized for the specific drivers.
What’s suitable minimum distribution:
What I am doing now is either building a kernel image using Buildroot then inserting the developed USB driver into it OR inserting the developed USB driver into a Ubuntu. And for proper testing I have to unload the default USB driver (usb_storage); otherwise can’t test my module. So, my question is regarding real-life development & how-to get minimum kernel that has no drivers, & how-to include my module into it (to be part of it) while building with Buildroot?
What Embedded Linux Driver Development community do you suggest for detailed Q&A?
i.e. In future if I want to ask about low level detail such as what is this x structure, or I am getting this error while using this y function .... is there a specialized community? because all I found are for Linux in general, for Kernel hacking, or don’t have experiences.
What is the missed link in the chain?
Developing applications for Microcontrollers relies on Datasheet, User Guide, Registers, C, etc. Developing Drivers for Embedded Linux relies on C, Linux API, Subsystems, etc. In most learning resources, I never found a relationship between both. So, are there really separated? OR there is a missed link between them??
e.g. for this I2C sensor http://www.robot-electronics.co.uk/htm/srf10tech.htm we have to manipulate it (send hexa to & receive values from its registers). If we imagine that we want to develop an I2C driver for it, then for sure we would need to do the same from within the driver, which is explained in Essential Linux Device Drivers (page#278). The main point behind it is that I2C core hides many complexes & simplifies driver development process.
However, I expect the case in real life is not for a sensor, instead it might be a Microcontroller or a complicated device. So, how would we manipulate the Registers & Peripherals of this Microcontroller? Also, I didn’t find tutorial for such a case!
I'm thinking about creating my own pure-C software SPI library because there are none available (as far as I can tell).
Which also worries me - why aren't there any software SPI libraries? Is there some hardware limitation I'm not considering?
EDIT:
I've decided to write my own library due to how buggy the SPI peripheral is in STM32. Especially in 8 bit mode, but I've also had a lot of problems with 16 bit mode. Many other issues I didn't even bother documenting.
I've now written the software implementation (it is pretty easy) and in works just fine.
why aren't there any software SPI libraries?
Because it's about 10 lines of code each for the WriteByte and ReadByte functions, and most of that is bit banging processor-specific registers. The higher level protocol depends on the device connected to the SPI. Here's what wikipedia has to say on the subject
The SPI bus is a de facto standard. However, the lack of a formal
standard is reflected in a wide variety of protocol options. Different
word sizes are common. Every device defines its own protocol,
including whether or not it supports commands at all. Some devices are
transmit-only; others are receive-only. Chip selects are sometimes
active-high rather than active-low. Some protocols send the least
significant bit first.
So there's really no point in making a library. You just write the code for each specific situation, and combination of devices.
Although the others have answered that its just bitbanging; I would argue that there is benefit to writing a small layer:
If you don't use a HAL, or the Standard Libs (like myself) you can write a layer to deal with initialization which can do things as per the initialisation sequence of the chip.
You can map all your interrupt vectors for a specific peripheral in this layer utilising callback mechanisms
Create separation between application and system domains which is a core principle for modular design
Increase of code reusability utilising techniques such as function pointers and common interfaces
Add input validation on settings/parameters that would otherwise cause code duplication if no layer was used. For example, ensuring that the HCLK does not exceed 180MHz on the stm32f429 when initialising it.
Whilst it is true that to send data generally all you need to do is set a register, but more often that not the initialisation sequence is complicated.
With the increase in power and capacity in microcontrollers along with project size, its important to implement balanced design choices that promote scalability and maintainability - especially in commercial projects.
If you are asking for microcontrollers then you can have your own SPI library.
You need to use bit-banging technique for that.
There are software SPI libraries available.
As every microcontroller have different PORT architecture and registers those are not generic and they are specific for that controller only.
e.g. For 8051 architecture you can find this.
I have a dsPIC33 with ECAN and wish to establish a protocol (using SDO if possible) in such way that it communicate between terminal software and dsPIC33 where I can perform diagnostics within dsPIC33 and supporting ICs.
I do not know what is required, so what is a low cost way of doing this? I could use a CAN-to-USB device, but I am unsure if this will work. What kind of protocol inside CANUSB wraps around the ASCII-based message?
What hardware can I use? Can it be used to monitor the CAN bus as well? I do not wish to invest in an expensive setup as in Vector or similar heavy-weight solution.
When you purchase CAN interface hardware, it does not typically include software to work with specific upper-level CAN protocols (like CANopen). They do usually come with a set of DLL files that allow you to write custom PC applications to interface with your hardware.
If you do not want to purchase any third-party software, then you must:
Implement a basic CAN driver for the dsPIC33 (transmit and receive a basic frame).
Implement the CANopen SDO protocol on top of your basic driver on the dsPIC33.
Purchase a low-cost CAN<->USB interface (which should come with DLLs that allow you to develop in C, C++ or C#.
Write a PC application using the DLL files which implements the CANopen SDO protocol.
You may want to look for open-source implementations of the protocol. One such implementation is CanFestival. However, I have never used this library.
You can download an open source project for CANopen from DATALINK ENGINEERING as this seems to be just what you need.
I am interested in learning how to do embedded system programming in c. However, I will need some hardware.
I am wondering is there any software that can simulate what the control board will do?
The control board is listed in the following tutorial
http://www.learn-c.com/hardware.htm
Many thanks for any advice
The board you linked to is not an embedded system board, it is an I/O interface for a PC. If you want to simulate that, you can simply write PC code stubs for the I/O functions that simulate connected devices' behaviour. However, you will not learn much about embedded systems from this. You may learn a little about PC based control, but since the board does not support interrupts or DMA, I suggest again that you will not learn much of that either.
Moreover the board is designed for an ISA bus slot. Modern PCs no longer have such slots. And modern operating systems prevent access to hardware I/O in user level code.
If you are serious about learning embedded systems development, you might for example download Keil's MDK-ARM evaluation; it includes an ARM simulator with on-chip peripheral simulation for a number of commonly available ARM based micro-controllers, and real hardware is available at reasonable cost.
If PC based control is of more interest, then you would be better off starting with a USB based I/O device, such as this example.