Proxy pattern for hardware access in embedded C - c

I am reading a book that "Design Patterns for Embedded Systems in C" which is written by Bruce Powel Douglass and ı decided to using Hardware Proxy Pattern for providing encapsulated access to hardware but at some point ı am not sure exactly about impelementing proxy pattern.
For better understanding ı am going to add a scenario:
Let's assume there is a PMIC( power management ic) which can communicate over one of some serial communications.
We write a pmic.c and pmic.h file which are defined and declarated all variables,function and registers address and values to work with pmic. Let's look at definitions and declarations of some of them:
-in pmic.c-
//included already serial communucation header file like as #include "app_I2C.h"
uint32_t pmic_read_battery_voltage(){/*Some serial comm function here*/}
bool pmic_Init(){/*Some serial comm function here*/}
bool pmic_configure(uint32_t pmic_cfg){/*Some serial comm function here*/}
bool pmic_set_charge_current(uint8_t charge_curr){/*Some serial comm function here*/}
-in pmic.h-
uint32_t pmic_read_battery_voltage();
bool pmic_Init();
bool pmic_configure(uint32_t pmic_cfg);
bool pmic_set_charge_current(uint8_t charge_curr);
So you can see that if ı give that pmic.c file directly to client they never access directly hardware side and more than one clients can access this file (maybe another .c files). In fact this is nature of C.
Can we say this pmic.c driver written in proxy pattern because it is hiding hardware side from clients ? ( ı could change basically serial communication side without clients changing anything on their side)
or
have ı to create new pmicproxy.c file which is including above functions again with having generic struct(like as class ) for access all properties of hardware?

Related

Stm32 Log Messages

good day, stm32 nucleo board I want to write informative Log messages using.
For example, I want to display the message that the program has started by using the Log("Program started") function when the program starts during this period, or I want to give the error message to the screen by using the Log("Program Failed') function when the program fails.
I using C programming langue and stm32cubeide & Nucleo f207zg board thanks in advance for your help
Thanks I solved the problem
Given that:
You know what the UART/USART peripheral is
You connected the right pins to a serial interface
You connected the other end of the interface (for instance an FTDI chip) to your computer
You can implement the logging with printf as you would do in C. Why? Because printf already takes care for you the formatting of the strings, which no one wants to reimplement, and then you redirect the printf output to the UART peripheral that handles low level serial protocol.
Following this guide the steps are easy enough:
Add #include <stdio.h> to the Includes section at the top of the main.c
#include "stdio.h"
Copy and paste the following code into the main.c file before the main() function but after the UART handle declaration
Note that you need to replace the question mark with the actual UART handle declaration, for instance huart1
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart?, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
As pointed out by Fra93, you need to implement UART/USART protocol communication and print stuff to there. I'm writing this reply, because I'm getting a feeling you have some basic experience writing desktop applications, but not embedded, so I will clarify a few points.
There is no console to print to. There are no logs. They simply don't exist. At all. Not in a desktop app development sense.
What's usually done is that one of the UARTs of the MCU is used to print characters to the ST-Link, which converts it to USB (alternatively, can be FTDI IC, CP2102 or other USB-UART bridges/converters). So then your MCU will send out characters over UART, and the USB-UART converter will display them in a COM port terminal (programs like PuTTy)
If you start with empty project and no external libraries used, you will need 3 dozen lines of code alone just to be able to print stuff. Initially, you have nothing. You have to initialize UART, configure it, then implement how it handles characters, numbers. You need to literally write a basic UART driver. And you can call printing function whatever you want. You can call it Log("hello world"), you can call it Whisper("hi there"). Because you will actually create this function. You're the boss.
Now, given you are not very familiar with all of this, it may sound like a difficult task. And it most certainly is. Writing a driver from scratch on your day 1 is not a thing you want to do (unless you're into that kind of stuff on day 1).
I would strongly advise you to get some library, such as HAL by STMicroelectronics, and familiarize yourself with what it can do - including how to print stuff with UART. Internet is flooded with articles and videos of how to use UART with HAL, it's literally one of the first things to be implemented. Specifically for the reason, that it works like logs and simplifies further development/learning.
So, in order to get "logs" working, I would do the following:
Get HAL for your specific MCU
Familiarize yourself with UART - basic stuff about what it is and how it works. No need to be an expert, just learn what it is.
Familiarize yourself with how to use UART with HAL
From the schematic of the PCB of your nucleo board, find out which UART of the MCU is connected to ST-Link (I checked the schematic: it's USART3)
Get serial port (COM) terminal program for your computer
Use HAL to initialize USART3 and print to USART3. Whatever you print there will be visible in the terminal. Yes, you will not see anything in the IDE. You need a separate program to display what you receive via USB COM port.
In the end, your print function will be the one proposed by Fra93. HAL_UART_Transmit is the most basic HAL function to send stuff via UART. If you're very picky about using "Log" as a function you call to print via UART, you can always wrap HAL_UART_Transmit into your own function called Log.

How to simulate multiple instances of the same program communicating in C?

I need to write code in C that will ultimately run on an embedded system and its purpose is that multiple physical instances of these embedded systems can communicate with each other.
I want to test this first in simulation, but I am not very experienced in C. In C++ or other object oriented languages, I would just create multiple instances of the same class and let them communicate in the simulation.
How could I do that in C?
Edit: To avoid misunderstandings: I am interested in how I can start up multiple instances of the code, so that every instance then has its own data.
You're being very vague in how exactly the two devices are going to communicate, so I'm going to assume the microchip (or whatever) you're using has some kind of interface, that will get digital pulses and store them in some fixed address in memory. If that's the case, you can make two functions:
send_data(char data), will send the other machine data
receive_data(), will get the most recently sent byte of data
Then, you can make use of the C's preprocessor:
#if SIMULATION
// Code for simulated data communication
#else
// Code for real data communication
#endif
void send_data(char data) {
#if SIMULATION
// Code for simulated data communication
#else
// Code for real data communication
#endif
}
char receive_data() {
#if SIMULATION
// Code for simulated data communication
#else
// Code for real data communication
#endif
}
Then, when simulating the program, just compile with gcc ... -D SIMULATION=1
You could then use some sort of multithreading to start up the main function multiple times. This is the easiest way I can think of

How to structure an embedded application while decoupling application and driver code for a peripheral (UART)?

So I'm writing drivers for UART on STM32 and even though I kind of have an idea on laying out the structure, I'd still want to clarify prior to implementing, and also considering how essential it is to keep the code clean and organized.
So I have main.c, sensor.c (application file that uses UART layer), hal_usart.c (which is the driver file).
I have heard different things regarding how application code should have no clue whatsoever about the driver APIs, and read up an article the other day that you could decouple the sensor code from HAL driver code using function pointers but not sure how I could do that here, and if that will decouple it considering I'm still passing a reference to USART_Handle struct that contains info like baudRate, parityControl, wordLength, reference to USART_TypeDef etc.
Below is a snippet of my idea:
// main.c
static USART_Handle pUSART;
int main(void) {
// initialize clocks/HAL
// ...initialize USART struct
// Get data via UART (calling application API)
GetData(&pUSART);
}
// sensor.c (application)
void GetData(USART_Handle *pUSART) {
HAL_USART_TX();
HAL_USART_RX(); // assuming data is stored in one of the struct members
}
// hal_usart.c (Driver file)
void HAL_USART_TX() {}
void HAL_USART_RX() {}
Since you would like to separate Application code and Driver code in an embedded system, I suggest you study how to implement callback functions in C also embedded systems.
Here is the reference.
The utility of function pointers is maximum when you want to change the pointer while the program is running; or, in other words, when you have at least two different functions and, based on some condition, you want to use one or another.
For example, let's say you have a routine which reads a sensor using a serial port, and the user can switch from a sensor to another (two serial ports or even two different methods). In that case, the sensor routine could call a function, to read, using a function pointer, and manage the back read data. The main program, by changing the function pointer, can instruct the sensor routine to use one or the other sensor.
If you don't need to change things at runtime, you can simply write your sensor routine making it call a reading function (external) defined in some other file. The documentation of the sensor routine simply has to state that somewhere must be defined a routine called "int sensor_get_data()".
This involves to design your own "internal protocol" based on what data goes and comes from the "detached drivers". For example, the sensor routine, which copes with a precise model of a sensor, can have the need to send a command and receive a response. You can write your sensor routine which construct the command and decodes the answer, and take away the low level details wrapping all them in the single function "int sensor_get_data(int command)". You then link or include the sensor code, and implement the function sensor_get_data() in the main.
The main() does not know the details of the sensor, it only knows that the sensor code, when needed, will call the function sensor_get_data(). But this function can use an UART, or an i2c or a spi, without the sensor routine even noticing that; moreover, this routine can use any of the three ports, perhaps basing on parameters the user can modify at runtime.
All this can be named "callback mechanism", and implements a sort of separation between declaration and implementation, as mentioned in the other answer. What I depicted is not different from that, but it is static - the program is compiled with a fixed callback, instead of passing a function pointer in every call.

Implementation of linux char driver with multiple parameters to access

I am writing a simple char driver which accesses a PCI card. It is registered to sysfs with the help of a new class and accessible under /dev/foodev. Using standard file operations I can perform simple read and write operations to the device.
My problem: I have multiple parameters stored at different addresses on the card (version, status, control, ...) which I would like access independently. Currently having only one read and one write function I therefore have to change the address every time again in the driver code.
Obviously there is a more convenient way to implement this. I stumbled about the two following approaches and was wondering which is the better one in terms of sustainability and user accessibility:
Using ioctl commands setting the address/parameter before an
access.
Having the device already nicely set up in udev using multiple attributes
(device_create_file()) of which the user than just can write/read from
different "files":
/dev/foodev
../version
../status
../control
I think you should take a look at the PCI framework to implement your driver.
Don't (mis)use ioctls; you'll have race conditions. Use the attributes as files. That scheme is already used in sysfs. E.G. look at GPIO LEDs and keys. – sawdust

Linux device model: Same device but different drivers

I'm customising Linux for an ARM9 Atmel AT91SAM960 board.
In the device file Atmel named all the USART the same atmel_usart. Of course with id enumeration:
static struct platform_device at91sam9260_uart0_device = {
.name = "atmel_usart",
.id = 1,
.dev = { ...}
}
According to the Linux Device model, all these devices (5 UARTS on a SAM9260) would be bind to the driver named atmel_usart.
I don't want to set a TTYS driver on all UARTS which will be registerd. I have several own drivers which serve for different specialised purposes (LON, RS-485 etc.) I want the control which driver does serve a certain USART. So what could I do:
The Atmel device files are unsatisfiable and I can do it better. So I rename (patch) the devices in the device file. However, in case I want a TTYS driver on UART4 I would be in trouble.
I manipulate (patch) the device file,
so that I'm able the access the
structures platform_device. I could
change their names before I would
register them. But as far as I
understood the idea of the Linux Driver Model,
devices should be
registered early during boot-up but the binding to a driver follows .... later.
I could write a driver, which has an
alias name and which would be binded
to a specific bus_Id ->
atmel_usart.4. Can I really?
What solutions else exist. I want to touch a minimal set of Kernel files but I want all the freedom possible?
Addendum what freedom means to me: I can specify at runtime how the UARTS can be used
with the Atmel-Serial driver (ttyS)
with my own drivers
It means also, that changes to the kernel source are minimal.
I built my own line discipline drivers. You can build them as kernel modules and attach them to the UARTs at runtime. No changes to the Linux source are necessary.
Any funny timing or control stuff can be done through ioctl(). Specifically, I implemented a timing-sensitive RS-485 protocol in this way.
When I did this (Linux 2.6.17) there was no dynamic registration mechanism, so I overwrote the existing line disciplines. The Linux code is (was) pretty straightforward, and I was satisfied that this would be a safe thing to do.
Your problem is quite easily solved. The 5 UART devices are presently registered at kernel startup and their function is locked. This is now how it normally works for PCI or USB devices, right? So what you need to do is pull the device registration out of the startup code and register it dynamically. You can even register/unregister as needed.
at91_register_uart() is being called from your board file for every UART that needs registered. at91_add_device_serial() will then platform_device_register all those you what setup. One solution is to let at91_register_uart() be called for all 5 UARTS, but then remove the call to at91_add_device_serial() from your board. You can then make it an exported function that can be called by your loadable drivers. You can even add an argument to it (int) so that instead of looping on all UARTS, you can select which ones to register individually. You can also mirror this function by making one that unregisters the devices.
NOTE: I think you'll need to always leave one UART dedicated as your console, if you are using one that way. You could probably hide that in the exported function by only allowing index 0->3 as in input and then mapping 0->3 to 0-4, skipping the UART that you want to use for console.

Resources