Once again, Im not a developer but a wood worker so my questions might be, well, stupid.
I forgot something really important I've to use gcc-3.8 to compile as the original code I'm working with can't compile with newer version. I totaly forgot to talk about that, sorry.
I'm sending data from a tool to an autonomous robot. Robot receive data as unsigned char* I read a lot and it seems that malloc isn't interrupt safe.
As the robot could do bad & dangerous things, I try to make every parts safe (at least as much as I can).
This malloc happens after an interrupt raised by data received. This code segment is now giving me an hard time to make it safe, also my syntax is probably bad..
char* _Xp = (char*) malloc(strlen((char*)_X)*sizeof(char));
strcpy(_Xp, (char*)_X);
1) is malloc really not interrupt safe? information I found are from 2004.
2) is there a more efficient way to initialize the buffer?
3) why are unsigned char "bad"? (read something about that).
4) last question is strcpy also not interrupt safe? sources I read differ on that point.
===== answering some questions:
Robot doesn't have operating system, target is an STR911FFM44 at 25Mhz (if it helps)
Input arrays are all nul-terminated.
Code is not in the interruption handler but in the infinite loop and processed only if the IrHandler as set the flag for it.
I don't know the rate of the data stream to "hard code" the safety. but interruption should be in [500ms to 1500ms].
1) is malloc really not interrupt safe?
malloc accesses and modifys a global resource, the common memory pool of you running program. If the access happens from two unsynchronized places, such as your normal program flow and the ISR1, then it can mess up the pool. If your ISR doesn't call malloc itself it won't be a problem.
If it does, you'd need to put in place a system for preventing such reentry into malloc. For instance, wrap the call to malloc in a function that turns interrupt handling off, and then on again.
2) is there a more efficient way to initialize the buffer?
If you need a buffer with allocated storage duration (i.e. that you decide when its lifetime ends, and not the scope it's allocated in) then there isn't really a standard C alternative. By the way, sizeof(char) is always 1, so no need to specify it. And since C allows implicit conversion of pointer types from void*, the call can at least be prettified a bit2:
char* _Xp = malloc(strlen((char*)_X));
3) why are unsigned char "bad"?
They aren't bad. In fact when you need to know exactly whether or not the character type is signed or not, you have to use signed char or unsigned char. The regular char can be signed on one platform and unsigned on another.
1 Interrupt Service Routine.
2 C has a notion of reserved identifiers. In particular, any identifier the starts with an underscore followed by an uppercase letter is always reserved. So renaming your variables may help with portability.
First of all, you say that you are using a bare metal microcontroller, so malloc never makes sense. It is not a PC - you don't share your RAM with anyone else. So all the dangers and disadvantages of malloc don't even enter the discussion, since malloc makes no sense for you to use at all.
1) is malloc really not interrupt safe? information I found are from 2004.
4) last question is strcpy also not interrupt safe? sources I read differ on that point.
No function using shared resources between an ISR and the main application is interrupt safe. You should avoid calling library functions from an ISR, they should be kept minimal.
All data shared between an ISR and the caller has to be treated with care. You must ensure atomic access of individual objects. You must declare such variables as volatile to prevent optimizer bugs. You might have to use semaphores or other synchronization means. This applies to all such data, whether you change it by yourself or through a library function.
Failing to do all of the above will lead to very mysterious and subtle bugs, causing data corruption, race conditions or code that is never executed. Overall, interrupts are always hard to work with because of all this extra complexity. Only use them when your real-time requirements give you no other options.
2) is there a more efficient way to initialize the buffer?
Yes, use an array. static char _Xp [LARGE_ENOUGH_FOR_WORST_CASE]; Usually it is a good idea to keep such buffers in the .data segment rather than on the stack, hence the static keyword.
3) why are unsigned char "bad"? (read something about that).
There is nothing bad with them as such. The different char types are problematic though, because in theory they could have other sizes than 8 bits. Worse, char without signed/unsigned has implementation-defined signedness, meaning it might be signed or unsigned depending on compiler. Meaning that you should never use the char type for storing anything else but text strings.
If you need a variable type to hold bytes of data, always use uint8_t from stdint.h.
As the robot could do bad & dangerous things, I try to make every parts safe (at least as much as I can).
Writing safe software for embedded systems is a highly qualified task. I wouldn't recommend anyone with less than 5 years of experience working full-time with embedded firmware programming to even consider it, unless there's at least one hardened C veteran who is part of your team and all code passes through peer review and static analysis.
It sounds like you would benefit a lot from reading through the MISRA-C:2012 coding guidelines. It is a safe subset of the C language, intended to be used in safety-critical applications, or any form of application where bugs are bad. Unfortunately the MISRA-C document is not free, but it is becoming an industry standard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With