Thanks everyone for your replies!
It's hard to answer to everyone, but I'll try to cover most of the stuff:
You might want to document the MCU's pin assignment and fuse programming.
The pins are largely self-documented in io_map_... files. But more info on active high/low, etc. is a good idea. And fuses, yes, that was on my todo list.
On this forum,that's a bit like standing there with a "kick me" sign on your back!
Better this, than to destroy some expensive equipment or harm someone with my poorly written code.
So in the end, I guess, it was a good idea with a "Kick me" sign
Just some strange code conventions. Like function and define naming and things in types.h. Is defining "u08" instead of just using "uint8_t" just for convenience?
Yes, it is mostly for convenience and to have a consistent code on different platforms and compilers. Also writing u08 instead of uint8_t even with autocomplete function is always easier. )
But I'll look closer into this later, the PLC part seems interesting.
Well it's pretty far from PLC, but some things are alike.
Does it fit in the m168? (It looks the way people want their code to look before they discover that it doesn't fit and/or doesn't run fast enough...)
I did have one complaint. Some of your command names are awful:
Yes, it does fit just fine. I was writing this program with MCU's limited resources in mind.
Currently it takes:
Program Memory Usage : 12044 bytes 73.5 % Full
Data Memory Usage : 345 bytes 33.7 % Full
About command names - those might change in near future. I've used such names during debug stage to be able to enter them pretty fast and frequently, like "rst" instead of "reset".
I saw many #ifdef else {} etc etc replicated of the same everywhere, only a suggestion... you can use macro for that. type once change all. if they are slightly different version (even with operators) maybe you can do macro with arguments since it will direct replace the arguments... eg
I haven't thought about passing operators as a parameter to macro function. Got to try that.
if you still dont know you can use \ as linefeed for multiline macro. i'll check another files
Yep, check another files
You're inflating the firmware size by beautifying the source code too much.
For example:
u08 EEPROM_ReadByte(const u08 *addr)
{
return eeprom_read_byte(addr);
}
Well not really beautifying. It's been added for an abstraction. What if I would like to use external EEPROM? But to use inline functions in this case is a good idea, although I haven't used them because the current compiler is smart enough to make it as an inline function. I guess I just need to state than explicitly.
Another one:
bool PLC_GetManualControlStatus(void)
{
return gManualModeEnabled;
}
A function to return a global variable? Make global variables really global, not just inside the source file where that function is located.
The reason is simple. The variable itself is not global, I made it static to restrict its scope.
Why not make that variable global, but have getter, setter and function that returns its value? Because the type of that variable is "home-made" bool, which is not standard type for C lang., therefore to avoid setting that variable to something other than true(1) or false(0) I've used getter and setter.
If you run into RAM problems combine bit-sized variables. A "bool" is one byte, but you can fit 8 boolean variables into one byte using bitmasks.
Thought about using bitfields, but I was not even close to RAM size problems.
Other observations:
Don't have variables or functions which are the same as standard library ones, but behave differently - thinking of "errno" here especially. Experienced programmers expect such things to behave, well, as expected
You are a bit cavalier with data types - eg using StrToUInt32 and then casting to an unsigned 8 bit value without checking that the value fits. You might "know" that the string is "0"-"255" but the day someone decides it needs to be "0"-"65535" without checking everywhere it is used might be in for some head scratching.
Good point about standard functions/variables behavior! I'll change that.
About conversion from 32bit to 8bit, I haven't written StrToUInt8 function yet, and that's why I temporarily substituted it with (u08)StrToUInt32 - which was wrong, of course. I should've at least written "TODO:" comment there, to return and fix that in future.
There's not too much to be gained by making a simple argument to a function const because assignments to it will not affect anything outside the function anyway.
It's a pretty good practice, IMHO, because you can accidentally change that parameter in the beginning of the function and the rest of the function would use that wrong value. It allows to avoid some simple mistakes, like typos.
I think my post is already too long.. )