I am working with an STM32F1 microcontroller, for which a header is provided that defines bit masks and values for registers as follows:
#define RCC_CFGR_PLLMULL //Mask of PLL multiplier setting bits
#define RCC_CFGR_PLLMULL1 //Value of PLL multiplier bits for PLL x1
#define RCC_CFGR_PLLMULL2 //Value of PLL multiplier bits for PLL x2
#define RCC_CFGR_PLLMULL3 //Value of PLL multiplier bits for PLL x3
etc etc.
What I want to do is define my PLL multiplier as an integer so I can use it to derive the clock value - ie PLLCLK = IN_CLK * PLL_MULT - and paste the value onto RCC_CFGR_PLLMULL to obtain the correct setting bits. The macros I would normally use for this are as follows:
#define APPEND_VAL_HELPER(A, B) A##B
#define APPEND_VAL(A, B) APPEND_VAL_HELPER(A,B)
Then if I define SOME_NUM as, say, 123:
#define FOO APPEND_VAL(BAR, SOME_NUM)
Results in the FOO defining as BAR123. Normally this works. Here's the problem: in this case, RCC_CFGR_PLLMULL is a valid token before being pasted. This results in it expanding in the invocation of APPEND_VAL and I get something like ((uint32_t)0x003C0000)123. I can't figure out how to get B to expand without also expanding A, at least in GCC. There are workarounds to this but I'm looking for a clean solution. Does it exist?
I'm not sure what you would consider a "clean" solution, but this works for me and doesn't seem too bad:
/* target header */
#define RCC_CFGR_PLLMULL 0x003C
#define RCC_CFGR_PLLMULL1 0x0003
/* pasting macros */
#define APPEND_VAL_HELPER(A, B) A ## B
#define APPEND_VAL(A, B) APPEND_VAL_HELPER(A, B)
#define RCC_CFGR(T, N) APPEND_VAL(RCC_CFGR_, APPEND_VAL(T, N))
You use that as, for example,
#define FOO RCC_CFGR(PLLMUL, 1)
You can also do
#define BAR RCC_CFGR(PLLMUL, )
to define BAR to RCC_CFGR_PLLMUL (no tail).
Obviously, this is specific to a subset of possible target macros, but it does the job and reads cleanly. To the best of my knowledge there is no way to write a fully general token-pasting macro -- those that are most general suffer from issues such as the one you described.
Related
PIC microcontrollers have 3 basic registers to set GPIO (General Purpose I/O) pin status. These are:
TRIS (Tri-status, the direction register. Sets the pin as in or out)
PORT (The input buffer)
LAT (Latch, the output burffer).
Ports can be A, B, C... etc.
So the TRIS register for the port A is TRISA.
Then finally there is the pin number. For example, TRISA1.
TRISA1 is defined as:
// TRISA<TRISA1>
extern volatile __bit TRISA1 __at(0x461); // # (0x8C * 8 + 1)
#define TRISA1_bit BANKMASK(TRISA), 1
I would like to define a macro to easily name the pins as:
#define _DATA_OUTPUT A2
So I can do code like:
LAT_DATA_OUTPUT = 1;
PORT_DATA_OUTPUT = 0;
and have it converted by the preprocessor to:
LATA2 = 1;
PORTA2 = 0;
so I can later expand to other pin registers such as ANSEL, WPU, etc, without rewriting the macros or add special cases.
Is this possible? Or what's the closest thing I can do to emulate this?
You can do that by create macro like that:
#define _DATA_OUTPUT A2
#define LAT_DATA(X) LAT##X
#define LAT_DATA_OUTPUT LAT_DATA(_DATA_OUTPUT)
#define PORT_DATA(X) PORT##X
#define PORT_DATA_OUTPUT PORT_DATA(_DATA_OUTPUT)
you can use it as example .
You can already do this. You haven't noted your PIC model or your IDE version or what toolchain you are using, but assuming you're on MPLAB X with an XC compiler this functionality is already there. Make sure you're including <xc.h> and it should read what chip you have from the project configuration and have the macros already made for you.
You can then set entire registers (using TRISA as an example):
TRISA = 0x0000; //All A pins outputs
Or set individual pins in that register:
TRISAbits.TRISA0 = 0;
TRISAbits.TRISA8 = 0;
You could also define your own macros:
#define TRISA0 TRISAbits.TRISA0
#define SET_TRISA0_IN TRISAbits.TRISA0 = 1
So I have been programming in Atmel C for a while and I have gotten used to all the C bit manipulation, so now I want to hide it. I want to hide the bit manipulation not only to make my code more readable but also make it easier to maintain and modify in case our hardware changes or we make new hardware.
So I am asking you what are the best macros for Atmel C for basic pin manipulation.
The features I am looking for are:
Set a Pin to be Input or Output
Set an Output Pin HIGH or LOW
Read the Value of an Input Pin
So I have found a few macros that I could use but none really fit my bill.
Links:
http://www.piconomic.co.za/fwlib/group___a_v_r___p_i_o.html (still have to keep multiple defines per pin)
http://www.starlino.com/port_macro.html (doesn't compile, AVR Studio 6.2)
Changing a global variable in C (best one, near the top of the question under "/* LCD DEFINES */"
What I would really like is something like this:
#define LED1 PA1
#define BUTTON1 PB0
set_output(LED1);
output_high(LED1);
delay_ms(100);
output_low(LED1);
set_input(BUTTON1);
uint8_t tmpVal = get_input(BUTTON1);
if( tmpVal == 1 )
{
// assuming button IS pressed here
}
else
{
// assuming button IS NOT pressed here
}
Any ideas on the cleanest way to do this?
I could handle keeping around a few more defines per pin but I feel like that shouldn't be needed. Shouldn't PA1 and PB0 be able to tell us everything or do they get defined into a single value?
EDIT: Using Atmel Studio 6.2 on Windows
Thanks,
Rob R.
Nevermind this does compile
http://www.starlino.com/port_macro.html
// MACROS FOR EASY PIN HANDLING FOR ATMEL GCC-AVR
//these macros are used indirectly by other macros , mainly for string concatination
#define _SET(type,name,bit) type ## name |= _BV(bit)
#define _CLEAR(type,name,bit) type ## name &= ~ _BV(bit)
#define _TOGGLE(type,name,bit) type ## name ^= _BV(bit)
#define _GET(type,name,bit) ((type ## name >> bit) & 1)
#define _PUT(type,name,bit,value) type ## name = ( type ## name & ( ~ _BV(bit)) ) | ( ( 1 & (unsigned char)value ) << bit )
//these macros are used by end user
#define OUTPUT(pin) _SET(DDR,pin)
#define INPUT(pin) _CLEAR(DDR,pin)
#define HIGH(pin) _SET(PORT,pin)
#define LOW(pin) _CLEAR(PORT,pin)
#define TOGGLE(pin) _TOGGLE(PORT,pin)
#define READ(pin) _GET(PIN,pin)
/*
BASIC STAMPS STYLE COMMANDS FOR ATMEL GCC-AVR
Usage Example:
———————————————–
#define pinLed B,5 //define pins like this
OUTPUT(pinLed); //typo fixed
//OUTPUT(pinLED); //compiles as DDRB |= (1<<5);
HIGH(pinLed); //compiles as PORTB |= (1<<5);
———————————————–
*/
There is just one typo which I have fixed
For embedded C applications I have always used the following convention for defining GPIO pin masks:
'Traditional' Example: 32-bit CPU with 32-bit GPIO port
Assert bit5 in the GPIO output register to turn an led on.
#define BIT5 (1u << 5) //or maybe even just hardcode as 0x20
...
#define PIN_LED_CTRL (BIT5) //LED_CTRL is Pin #5
...
void gpio_set(uint16_t pin_mask) {
GPIO_OUT |= pin_mask;
}
...
//turn the led on
gpio_set(PIN_LED_CTRL);
On a recent multi-developer embedded project, one developer has chosen the following syntax
'Alternative Example: 32-bit CPU with 32-bit GPIO port
#define PIN(x) (1u << (x##_PIN_NUM))
...
#define LED_CTRL_PIN_NUM (5)
...
void gpio_set(uint16_t pin_mask) {
GPIO_OUT |= pin_mask;
}
...
//turn the led on
gpio_set(PIN(LED_CTRL));
No real clear explanation of why this was chosen was given. As with all lightly documented code, it seems mysterious enough to 'cleary' warrant its implementation. Surely the developer knew something I did not. And in this case, the guy is a smart cookie from the CPU-driver world.
Objection
I don't like the 'alt' method at all. It seems too cute for its own good. But the only justifications I can give are:
'LED_CTRL' is not a compile time constant
additionally you then can't descend/inspect it within an IDE
'LED_CTRL_PIN_NUM' is the complete opposite of a uri-naming-schema
e.g. PIN_NUM_abc is preferred
No one else does it*
It looks weird
But this just appears to me like complaining; none of these are real objections
to using the 'alt' method.
Question
Why would someone use the 'alt' method at all? Is this a hand-me-down from register-usage in the desktop driver land perhaps?
Do any common embedded MCU libraries, alternative targets or programming languages use this 'alt' method?
Thanks!
*at the end of the day; I'm likely to stick with 'it looks weird' :).
Both methods are nearly the same, only the style is different, but the problems are the same.
Normally a pin isn't defined by a bit number only, you also need to know the port.
So when changing the port, you need to modify not only the definitions, you also need to modify code.
#define PIN_LED_CTRL (BIT5) //LED_CTRL is Pin #5
...
void gpio_set_port2(uint16_t pin_mask) {
GPIO2_OUT |= pin_mask;
}
...
//turn the led on
gpio_set_port2(PIN_LED_CTRL);
I prefere to define the pin only once and all the different dependencies are build by macros or in functions.
#define HW_SPI_CLOCK 2,5 // uses port2,bit5
#define HW_RESET_EXT 4,3 // uses port4,bit3
Then I use some macros to define get the port direction, pushPull and other registers.
These macros depends hardly on the plattform and the toolchain.
/**
* Generic GH-Macros
*/
#define PASTE2(a,b) a##b
#define PASTE3(a,b,c) a##b##c
#define __PASTE3(a,b,c) PASTE3(a,b,c)
#define PASTE4(a,b,c,d) a##b##c##d
#define PASTE6(a,b,c,d,e,f) a##b##c##d##e##f
#define __PASTE6(a,b,c,d,e,f) PASTE6(a,b,c,d,e,f)
#define GH_PORT(port,pin) port
#define GH_PIN(port,pin) pin
#define GPIO_PIN(gh) __PASTE6(FIO,GH_PORT(gh),PIN_bit.P,GH_PORT(gh),_,GH_PIN(gh))
#define GPIO_DIR(gh) __PASTE6(FIO,GH_PORT(gh),DIR_bit.P,GH_PORT(gh),_,GH_PIN(gh))
With the first method, the compiler will interpret the last line as following:
gpio_set(((1u << 5)));
And with the second method, the compiler will interpret the last line as following:
gpio_set((1u << ((5)));
You may fail to count without me saying it, but there is a parenthesis issue there. Either you have mistyped the #define PIN(x) (1u << x##_PIN_NUM) as #define PIN(x) (1u << (x##_PIN_NUM), or the one that you call looks weird won't even work.
In case you have simply just mistyped it, then both of them get simplified into the same thing:
gpio_set(1u << 5);
In the end, it is just a matter of style.
Note: If you are asking for opinions, you shouldn't.
Edit #1:
Okay, with the second approach, assuming that there are some other special pins, you can do things like this:
#define NAMEFOR0_PIN_NUM (0)
#define NAMEFOR1_PIN_NUM (1)
#define NAMEFOR2_PIN_NUM (2)
#define NAMEFOR3_PIN_NUM (3)
#define NAMEFOR4_PIN_NUM (4)
#define LED_CTRL_PIN_NUM (5)
#define NAMEFOR6_PIN_NUM (6)
#define NAMEFOR7_PIN_NUM (7)
#define NAMEFOR8_PIN_NUM (8)
// and so on...
#define PIN(x) (1u << (x##_PIN_NUM))
...
// and then gpio_set(PIN(nameyouwant)) whichever pin you want
// for example
gpio_set(PIN(LED_CTRL));
// or
gpio_set(PIN(NAMEFOR3));
However, I personally wouldn't do it with token concatenation; I would rather directly define like:
#define LED_CTRL 5
...
#define PIN(x) (1u << x)
...
gpio_set(PIN(LED_CTRL));
But then again, if you take this literally, defining LED_CTRL as 5 would imply LED_CTRL is 5, although actually rather it's pin number is 5. So it would make more sense to use it that way, the alternate way you've shown. Both more natural and makes literal sense, so, yeah...
Edit #2:
Of course, you could do something for the traditional approach as well, but then you'd have to write more lines, more defines:
#define BIT0 (1u << 0)
#define BIT1 (1u << 1)
...
#define BIT5 (1u << 5)
// and so on...
#define PIN_NAMEFOR0 (BIT0)
#define PIN_NAMEFOR1 (BIT1)
...
#define PIN_LED_CTRL (BIT5)
// and so on...
#define PIN(x) (1u << (x##_PIN_NUM))
...
// and then gpio_set(PIN_nameyouwant) whichever pin you want
// for example
gpio_set(PIN_LED_CTRL);
// or
gpio_set(PIN_NAMEFOR3);
It still makes just as much syntactic sense, but requires more lines to get written...
Assuming a typo in the "Alternative" example (in the last line, where you specify "LED_CTRL", which is not defined... I assume you meant "LED_CTRL_PIN_NUM"), then I believe these two examples will produce identical machine code. So, between these two choices... it's just a matter of style preference. (the ## in the second example is just an embedded comment.)
Personally, I would use a different approach entirely. I would use the built-in bit-field construct to modify a bit-wise field, and that way the compiler can decide what is the most efficient way to do this. Example follows:
struct {
unsigned int :4, LED_CTRL:1, :27;
} GPIO_OUT;
...
GPIO_OUT.LED_CTRL = 1;
Note that the ":4" and ":27" refer to the other bits in the register... you would likely want to map the entire I/O register, not just one bit of it.
Bitfields: SGeorgiades put an answer above that is risky business*
if you're making use of C Bitfields to define your pins, be very darn careful with it.
bitfield 'type' is implementation-dependent (needs quote; int/uint)
fields aren't contiguous bitwise by default and get promoted to impl-dependent size
bitfields that span across the int-bitsize boundary will not be contiguous in bitfield-mapping! (needs quote)
for GCC/C11 the following bitfield-syntax is what I would use (if I were to use it)
struct gpio_out {
int b0 : 1;
int led_ctrl : 1;
....
int b30 : 1;
int b31 : 1;
} __attribute__((packed));
Notes
by merging the concept of pin location into the struct, you can't share it with other
registers in gpio (i.e. maybe DIR, IN, INT_EN, IFG, etc).
I will put up x86 disassembly examples of the points made here tmrw. they are very dependent on implementation and compiler configuration!
*correct me if I'm mistaken.
I'm working with embedded C for a microcontroller right now and I find that sometimes there are several peripherals that differ only by a single letter (for example UARTA, UARTB, etc). The code for each peripheral is often times identical except for lettering of otherwise identical registers. For example to setup peripheral A I would do something like:
UCA2CTL1 |= UCSWRST; // Put state machine in reset
UCA2CTL0 |= UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI slave
// Continue initializing peripheral registers with "A" in name
And to setup peripheral B I have exactly the same code, except that the register names are transposed by 1 letter:
UCB2CTL1 |= UCSWRST; // Put state machine in reset
UCB2CTL0 |= UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI slave
// Continue initializing peripheral registers with "B" in name
I would like to have the ability to change which peripheral I target without having to #ifdef/copy/paste code or find/replace. Is there some compiler directive or clever trick that can implement this behavior so that I only have to write the code once? I would love to just #define the last letter in the peripheral, but something like that seems to wander dangerously close to code stink to me.
Will this work for you?
#define INITUC(device) \
UC ## device ## 2CTL1 |= UCSWRST; \
UC ## device ## 2CTL0 |= UCSYNC+UCCKPL+UCMSB
...
INITUC(A);
INITUC(B);
Assuming those constants are const and not defines You can do something like that:
#define MAKECONST(X) const int X ## 1; \
const int X ## 0; \
X ## 1 |= UCSWRST; \
X ## 0 |= UCSYNC+UCCKPL+UCMSB;
And then:
MAKECONST(UCA2CTL)
MAKECONST(UCB2CTL)
Note that my example includes declaration, which I don't know if you need, if not, omit first two lines of the define. E.g.:
#define SETUP(X) X ## 1 |= UCSWRST; \
X ## 0 |= UCSYNC+UCCKPL+UCMSB;
I am currently working on setting up a framework in C for usage between several microcontrollers.
The framework has to carry all device specific code, so the application only contains the abstract usage of peripherals (like SerialPort_Read, write, SetBaudRate, etc etc.)
One of the things I am struggling with to find a solution for in C are the I/O pin map. I've seen projects (like the very very popular Arduino) where the pin map is putten in a LUT (look up table) which is used during runtime. However, this LUT will never be modified during runtime, so there is no use to have this in the memory.
For example, this function resolves some bit indexes and registers from some 'const uint' tables, and either sets or clears a bit:
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
if (mode == INPUT) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
SREG = oldSREG;
} else {
uint8_t oldSREG = SREG;
cli();
*reg |= bit;
SREG = oldSREG;
}
}
Because this is actual C code running on the controller it's draining effiency and speed. I'd rather define some sort of macro that does the same thing, but is already resolved during compilation to a 'one-liner' that can be compiled much more efficiently:
GPIO_Write(PORTA, 5, 1); // Write '1' to pin 5 on PORTA
> LATA |= 1<<5; // Sets bit 5 high
GPIO_Tris(PORTA, 4, OUTPUT); // Set pin 4 on PORTA to output
> PORTA &= ~(1<<4); // sets pin 4 as output I/O type
Does anyone know if it's possible (and how) to define and use a look-up table with a macro in C?
At this moment I am using the MicroChip C30 compiler, which I believe is based in GCC. It's supposed to be portable between different compilers, including MicroChip C18, C32 and in further also ARM and AVR.
For your specific example, something along these lines will work:
#define WRITE_PORTA LATA
#define GPIO_Write(port, pin, value) \
(value ? WRITE_##port |= (1U << (pin)) \
: WRITE_##port &= ~(1U << (pin)))
#define INPUT 0
#define OUTPUT 1
#define GPIO_Tris(port, pin, direction) \
((direction) == INPUT ? port |= (1U << (pin)) \
: port &= ~(1U << (pin)))
You'll have to make sure to define LATA and PORTA in a way the system will understand - in particular trying to overload its meaning the way it seems to be in your example might be hard to resolve.
Which processor or microcontroller are you targeting?
You might be underestimating the usefulness of the LUT.
For many processors, the LUT does more than map a 'logical' pin number to a single value, the 'physical' pin number. The LUT maps the 'logical' pin number to several pieces of information.
In general, the 'logical' pin is mapped to the port address of the appropriate read/input or write/output register, and the bit offset within the read or write register. So the pin value, on many MCU's, is really mapped to a struct. It might also include a mapping to the data direction register and fields within it, as well as registers which set the state of pull-up or pull-down resistors.
For example, I have code to multiplex a 8x8 display. At run-time, I need to use pinMode to turn a pin from an output to a high impedance input, and so that information needs to be encoded somehow.
It is possible to do this sort of thing, with some ingenuity, on some MCU's.
ARM MCU's (and I believe 8051, though I've never used one) using 'bit band addressing' http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/CHDJHIDF.html
This assigns a unique memory address for each port pin, and fixed offsets can derive the address of the pin for the other data register, and other functions. This is not magic, the code encodes the information that is often stored in the LUT.
For other MCU's, they really do need both port and bit position, so it is two values for each pin number.
If you are willing to ditch the idea of using integers for pins, and instead use names, like P0, P1, then you could initialise a lot of const struct's, one per pin name, and your functions would take the const struct values. The struct would contain the initialised port and bit offset or bit mask values. The compiler may be able to optimise for speed. This would avoid having a LUT, but would still use similar amounts of space for pins that are used. You might be able to arrange it so that unused pins would not need to be included in the code, and hence saving space.
Edit: If you are willing to use C++, I'd suggest C++ templates which can give a much better solution than macros. They can be type safe, and are often easier to debug (if you have hardware debugging, e.g. JTAG and gdb)
Consider the following macro:
#define write(port, pin, value) do { \
if (value) \
LAT##port |= 1 << pin; \
else \
LAT##port &= ~(1 << pin); \
} while (0)
Usage:
write(A, 3, 1); // compiles to LATA |= 1 << 3;
write(B, 2, 0); // compiles to LATB &= ~(1 << 2);
Is that the kind of thing you were after?
I've seen it done (https://github.com/triffid/Teacup_Firmware/blob/Gen7/arduino.h) with a couple macros:
/// Read a pin
#define _READ(IO) (IO ## _RPORT & MASK(IO ## _PIN))
/// write to a pin
#define _WRITE(IO, v) do { if (v) { IO ## _WPORT |= MASK(IO ## _PIN); } else { IO ## _WPORT &= ~MASK(IO ## _PIN); }; } while (0)
/// set pin as input
#define _SET_INPUT(IO) do { IO ## _DDR &= ~MASK(IO ## _PIN); } while (0)
/// set pin as output
#define _SET_OUTPUT(IO) do { IO ## _DDR |= MASK(IO ## _PIN); } while (0)
// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
/// Read a pin wrapper
#define READ(IO) _READ(IO)
/// Write to a pin wrapper
#define WRITE(IO, v) _WRITE(IO, v)
/// set pin as input wrapper
#define SET_INPUT(IO) _SET_INPUT(IO)
/// set pin as output wrapper
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
with:
#define DIO0_PIN PIND0
#define DIO0_RPORT PIND
#define DIO0_WPORT PORTD
#define DIO0_PWM &OCR0B
#define DIO0_DDR DDRD
#define DIO1_PIN PIND1
#define DIO1_RPORT PIND
#define DIO1_WPORT PORTD
#define DIO1_PWM &OCR2B
#define DIO1_DDR DDRD
...
You could modify the macros to take straight integers rather than DIOn