Given that the PIC18 architecture does not provide any bit-addressable RAM, would it be a sane idea to utilize carefully considered unused bit-addressable SFR's? For example, if my project does not make any use of EEPROM, would it be a prudent idea to use EEADR as custom flags space? I am aware you can do bit manipulation in C or asm, but I am asking about a simple, fast and elegant solution to a practical problem. Any thoughts on this topic? Thanks
-
3\$\begingroup\$ what is the problem that you are trying to solve? \$\endgroup\$– jsotolaCommented Apr 10, 2023 at 5:05
-
\$\begingroup\$ My application requires about 7 or 8 global flags. I am trying to find a handy way for working with them throughout the code. I like user4574's approach; unfortunately, I am having trouble getting the code to compile with mcc18. I will do more testing, a union structure may be needed based on what I infer from compiler's documentation. \$\endgroup\$– myoutuberCommented Apr 12, 2023 at 1:36
-
\$\begingroup\$ why does the flag have to be a single bit? \$\endgroup\$– jsotolaCommented Apr 12, 2023 at 4:45
-
\$\begingroup\$ The target uC is 18F14K50 which has 768 bytes of RAM. Using 10% of it just for flags is not an option. \$\endgroup\$– myoutuberCommented Apr 13, 2023 at 1:39
-
\$\begingroup\$ your math is off \$\endgroup\$– jsotolaCommented Apr 13, 2023 at 16:50
3 Answers
Having worked with many PIC18 parts over the years, I am not aware of any bit-addressable registers in the PIC18 series.
There would be little need since the PIC 18 has the ability to test, set, or clear bits in registers or RAM using a single assembly language instruction.
- BTFSS (Bit Test F Skip If Set). Reads a bit in register/RAM and skips next instruction if bit is set.
- BTFSC (Bit Test F Skip If Set). Reads a bit in register/RAM and skips next instruction if bit is clear.
- BSF (Bit Set F). Sets a specific bit in register or RAM.
- BCF (Bit Clear F). Clears a specific bit in register or RAM.
The device header files do define structures for accessing individual bits in registers. But using structures to read/set bits is just syntactic sugar that turns into one of the above instructions.
If you define you flags in a C style structure, then you can benefit from these instructions without having to directly use them. An example is below.
typedef struct {
flag_0 : 1;
flag_1 : 1;
flag_2 : 1;
flag_3 : 1;
flag_4 : 1;
flag_5 : 1;
flag_6 : 1;
flag_7 : 1;
}flags_t;
flags_t flags;
void foo(){
flags.flag_0 = 1;
if(flags.flag_2 == 0){
//do something.
}
}
-
\$\begingroup\$ I finally got the following code to function as intended. Big thanks for the suggestion!
#pragma udata access DATA_FAST_ACCESS volatile near union { struct { unsigned flag_0 : 1; unsigned flag_1 : 1; unsigned flag_2 : 1; unsigned flag_3 : 1; unsigned flag_4 : 1; unsigned flag_5 : 1; unsigned flag_6 : 1; unsigned flag_7 : 1; }; } u_FLAGSbits; #pragma code void main (void) { u_FLAGSbits.flag_6 = 1; u_FLAGSbits.flag_3 = 1; while (1) ; }
\$\endgroup\$ Commented Apr 17, 2023 at 23:23
As you have stated, there are no bit-addressable registers in a PIC18, so you are not really gaining anything in the code efficiency. However if you are cramped for space in RAM, it would be possible to use unused registers for RAM locations. Your concern is that a future code revision might be made by someone who is not aware of your approach. For instance, if the processor was put into sleep mode, the value of EEADR is lost upon wake-up, unlike that of a conventional RAM location. Or it could be as simple as a case where a future revision did utilize EEPROM space. So while possible, it would not be best practice.
Having worked on several space constrained projects, that is definitely an enticing prospect. While it is quite safe to do so (assuming you are absolutely sure it has no side effects), the biggest drawback to this approach comes when the project has to be modified, maybe years later. My suggestion is to VERY clearly document the unconventional use of the SFRs to warn future maintainers (even if it just ends up as a reminder to yourself).