I searched far and wide and information on the net seems to suggest that conditional compilation using the preprocessor works exclusively on environment variables.
Basically, I would like to have an inline function or macro perform different operations based in its input arguments. Example of what I want to achieve:
inline void foo(int x) {
#if (x < 32)
register0 |= (1 << x);
#else
register1 |= (1 << (x - 32));
#endif
}
The main goal here is that the resulting inline code will not contain conditional code for constant inputs.
Basically, I currently program for a microcontroller (lpc213x) and would like to have an inline function or macro to do pin configuration setup. Since pin configurations are split across multiple registers (e.g. 0 and 1 above), I would like to perform some conditional checks to decide which register is supposed to be written to for a given pin constant.
However, the pin configurations are all constant at compile time, so I would like to eliminate the conditional checks from compile code. I know that optimization would likely get rid of unnecessary conditionals anyway, but I'm wondering whether there is a way to achieve this behavior explicitly, because I might need to disable optimization in the future.
Thanks,
FRob
With C++, you could use template functions, like this:
template <bool B>
void doSetRegister(int x);
template<>
inline void doSetRegister<true>(int x) {
register0 |= (1 << x);
}
template<>
inline void doSetRegister<false>(int x) {
register1 |= (1 << (x - 32));
}
template <int X>
inline void setRegister() {
doSetRegister<X <= 32>(X);
}
int main() {
setRegister<1>();
setRegister<33>();
}
Here's an ugly way for C:
#include <stdio.h>
volatile unsigned long register0 = 0, register1 = 0;
#define DEF0X(_X_) \
static inline void SetPin##_X_() { register0 |= 1ul << _X_; }
#define DEF1X(_X_) \
static inline void SetPin##_X_() { register1 |= 1ul << (_X_ - 32); }
DEF0X(0) DEF0X(1) DEF0X(2) DEF0X(3) DEF0X(4)
DEF0X(5) DEF0X(6) DEF0X(7) DEF0X(8) DEF0X(9)
DEF0X(10) DEF0X(11) DEF0X(12) DEF0X(13) DEF0X(14)
DEF0X(15) DEF0X(16) DEF0X(17) DEF0X(18) DEF0X(19)
DEF0X(20) DEF0X(21) DEF0X(22) DEF0X(23) DEF0X(24)
DEF0X(25) DEF0X(26) DEF0X(27) DEF0X(28) DEF0X(29)
DEF0X(30) DEF0X(31) DEF1X(32) DEF1X(33) DEF1X(34)
DEF1X(35) DEF1X(36) DEF1X(37) DEF1X(38) DEF1X(39)
DEF1X(40) DEF1X(41) DEF1X(42) DEF1X(43) DEF1X(44)
DEF1X(45) DEF1X(46) DEF1X(47) DEF1X(48) DEF1X(49)
DEF1X(50) DEF1X(51) DEF1X(52) DEF1X(53) DEF1X(54)
DEF1X(55) DEF1X(56) DEF1X(57) DEF1X(58) DEF1X(59)
DEF1X(60) DEF1X(61) DEF1X(62) DEF1X(63)
#define SET_PIN(_X_) SetPin##_X_()
int main(void)
{
SET_PIN(0);
SET_PIN(1);
SET_PIN(32);
SET_PIN(63);
printf("register0=0x%08lX register1=0x%08lX\n",
register0, register1);
return 0;
}
Output:
register0=0x00000003 register1=0x80000001
And if you are coding in C, only thing you can do is to define two versions of foo().
You can remove conditional code by using short-circuit evaluation trick:
void foo(int x) {
x < 32 && (register0 |= (1 << x));
x >= 32 && (register1 |= (1 << (x - 32)));
}
try this
#define X 15 // or some else
#if X <= 32
# define SET_X register0 |= (1 << X)
#else
# define SET_X register1 |= (1 << (x - 32))
#endif
If you use the C Preprocessor to create a set of defines composed of two unsigned longs and then use these as arguments to your function foo(), the code is pretty straightforward. And if you need to add another register, you can modify the defines.
#define PIN_00 0x00000001, 0x00000000
#define PIN_01 0x00000002, 0x00000000
// defines left out here
#define PIN_31 0x80000000, 0x00000000
#define PIN_32 0x00000000, 0x00000001
// defines left out here
#define PIN_63 0x00000000, 0x80000000
inline void foo (unsigned long reg1, unsigned long reg2)
{
register0 |= reg1;
register1 |= reg2;
}
Then to use this function foo() you would specify the appropriate define. Since bitwise ORing with zero makes no change, the registers will be updated appropriately.
foo (PIN_00);
foo (PIN_01);
foo (PIN_32);
foo (PIN_63);
If you needed to add a way to remove bits you can make a new function using the same defines as follows:
inline void fooRemove (unsigned long reg1, unsigned long reg2)
{
register0 &= ~reg1;
register1 &= ~reg2;
}
Related
I've tried in C to make the WS2812 works in mplab with pic18f4550, the energy reach the led, but it doesn't turn on and I can't select the led that I ant to use, but it doesn't, how can I solve this? This is the code that I'm using:
Thanks
main.c
#define _XTAL_FREQ 4000000UL
#include "config.h"
#include "ws2812.h"
void main(void) {
ADCON1=0b00001111;
TRISB=0b00000001;
if (energy_port==1){
pin_strip_led=1;
ws2812_setPixelColorLed(1, ws2812_Color(255, 0, 0));
}
else{
pin_strip_led=0;
}
return;
}
This is what I'm using in ws2812.h:
#define STRIP_SIZE 8
#define pin_strip_led PORTBbits.RB1
#define energy_port PORTBbits.RB0
void ws2812_setPixelColorLed(unsigned char pixel, unsigned long color) {
Strip_RGBData[pixel][0] = (char) (color >> 16);
Strip_RGBData[pixel][1] = (char) (color >> 8);
Strip_RGBData[pixel][2] = (char) (color);
}
unsigned long ws2812_Color(unsigned char r, unsigned char g, unsigned char b) {
return ((unsigned long) r << 16) | ((unsigned long) g << 8) | b;
}
The program shown will read port B0, set B1 to the same state, and if set, populate one row of the array Strip_RGBData (which is neither declared nor used). It will do this one time. You ask, "How can I solve this?"
A good place to start is with the WS2812 datasheet. Use it to determine how to compose the signal required to control the LEDs. In your code set up a timer to clock out the bits of that signal in compliance with the timing requirements.
After that is working, you can add a loop to read the input to select an individual LED.
So I am trying to write a function which takes a pointer to a struct, an element of the struct (representing a register) and an int which represents the bit in the register we want to set
My idea was
SET_GPIO_BIT(GPIO_TypeDef *PORT, volatile uint32_t reg, uint32_t bit) {
PORT->reg |= (1 << bit);
}
where my struct in my header file looks like
typedef struct {
volatile uint32_t MODER;
volatile uint32_t OTYPER;
//insert more registers here
volatile uint32_t BSRR;
} GPIO_TypeDef;
but then I get a (arm-none-eabi-gcc) compiler error:
error: 'GPIO_TypeDef {aka struct <anonymous>}' has no member named 'reg'
The basic idea is that I want to be able to write something like
SET_GPIO_BIT(GPIOA, BSRR, 7);
which will select the GPIO port A and set the seventh bit in the BSRR register (for example). Is there a way to do something like this?
Since what you're looking for is text substitution, you need a macro for this:
#define SET_GPIO_BIT(port, reg, bit) ((port)->reg |= (1 << (bit)))
Alternately, since all registers are of the same type, you could instead use a function and pass in the address of the register in question depending on the situation:
void SET_GPIO_BIT(volatile uint32_t *reg, uint32_t bit) {
*reg |= (1 << bit);
}
Then you would call it like this:
if (set_MODER) {
SET_GPIO_BIT(&GPIOA->MODER, 7);
} else if (set_OTYPER) {
SET_GPIO_BIT(&GPIOA->OTYPER, 7);
...
This is not an answer to the stated question; it is rather a suggestion to solve the underlying problem in a different way.
Rather than having the "registers" as separately named members in a structure, use an array instead:
enum {
IOREG_MODE = 0,
IOREG_OTYPE,
/* All registers, in order */
IOREG_COUNT
};
typedef struct {
volatile uint32_t ioreg[IOREG_COUNT];
} ioregs;
This lets you use either a macro,
#define IOREG_SET(port, reg, bit) (((port)->ioreg[reg]) |= (1u << (bit)))
#define IOREG_UNSET(port, reg, bit) (((port)->ioreg[reg]) &= ~(1u << (bit)))
#define IOREG_TOGGLE(port, reg, bit) (((port)->ioreg[reg]) ^= (1u << (bit)))
or a static inline function,
static inline uint32_t ioreg_set(regs *const port,
const int reg,
const unsigned char bit)
{
return port->ioreg[reg] |= 1u << bit;
}
static inline uint32_t ioreg_unset(regs *const port,
const int reg,
const unsigned char bit)
{
return port->ioreg[reg] &= ~(1u << bit);
}
static inline uint32_t ioreg_toggle(regs *const port,
const int reg,
const unsigned char bit)
{
return port->ioreg[reg] ^= 1u << bit;
}
On any modern C compiler, both are equally fast, but the static inline functions provide compile-time type checking, and make it easier to debug cases where wrong data is output (via, for example, duplicating the writes to a debug text stream).
(If your I/O registers supports also 8-bit and/or 16-bit accesses, you can make the structure an union of arrays, with different static inline accessors depending on the size of the register.)
I'm using some macros that initializes & writes & reads port or port pin:
(And it works fine)
/* GPIO port operations */
#define GPIO_InitPort(CONTROL, DIRECTION) ((CONTROL) = ((DIRECTION)? (~GPIO_OUT):(GPIO_OUT)))
#define GPIO_WritePort(PORT, DATA) ((PORT) = (DATA))
#define GPIO_ReadPort(PORT) (PORT)
/* GPIO port pin operations */
#define GPIO_InitPortPin(CONTROL, PIN, DIRECTION) ((CONTROL) = (CONTROL & (~(1 << PIN)))|(DIRECTION << PIN))
#define GPIO_WritePortPin(PORT, PIN, DATA) ((PORT) = (PORT & (~(1 << PIN)))|(DATA << PIN))
#define GPIO_ReadPortPin(PORT, PIN) (((PORT) & (1 << PIN)) >> (PIN))
And, i was thinking to make a GPIO module, its functions implemented as follows:
void GPIO_InitPort(uint8 PortControl, uint8 PortDir){
PortControl = ((PortDir) ? (~GPIO_OUT) : (GPIO_OUT));
}
void GPIO_WritePort(uint8 PortData, uint8 PortLevel){
PortData = PortLevel;
}
uint8 GPIO_ReadPort(uint8 PortData){
return PortData;
}
void GPIO_InitPortPin(uint8 PortControl, uint8 Pin, uint8 PinDir){
PortControl &= ( ~(1<<Pin) | (PinDir<<Pin) );
}
uint8 GPIO_ReadPortPin(uint8 PortData, uint8 PinLevel){
return (( PortData & (1<<PinLevel) ) >> PinLevel);
}
void GPIO_WritePortPin(uint8 PortData, uint8 Pin, uint8 PinLevel){
PortData &= ( ~(1<<Pin) | (PinLevel<<Pin) );
}
Unfortunately, that doesn't work, although same logic used.
Remember that macros are just text substitutions - macro arguments are not evaluated, they are simply expanded in place. If you write something like
GPIO_InitPort( foo, bar );
the preprocessor expands that to
((foo) = ((bar) ? (~GPIO_OUT) : (GPIO_OUT)));
Function arguments, OTOH, are evaluated, and the result of that evaluation is passed to the function. Remember that C uses pass-by-value semantics - the formal argument is a different object in memory than the actual argument, so updating one has no effect on the other. If you call the function
GPIO_InitPort( foo, bar );
the formal argument PortControl is a different object in memory from the actual argument foo, and similarly PortDir is a separate object from bar. Writing to PortControl has absolutely no effect on foo.
If you want a function to write to the actual parameter in the caller, then you must pass a pointer to that parameter. So GPIO_InitPort would need to be written as
void GPIO_InitPort( uint8 *PortControl, uint8 PortDir )
{
*PortControl = PortDir ? ~GPIO_OUT : GPIO_OUT;
}
and called as
GPIO_InitPort( &foo, bar );
You need to learn about pointers.
Example:
void changeVar(int *var, int source)
{
*var = source;
}
int main()
{
int foobar;
changeVar(&foobar, 5);
return 0;
}
I am working on a embedded project trying to learn some of the ins and outs of programming an embedded board. As one might have guessed, this involves writing code in C. I am not having too much trouble getting the grasp of setting things up correctly (in terms of ports/pins/etc..) but I am looking to abstract some of my code to make it a bit more readable.
For example, the following code turns on a Green LED that is on the board:
// Required CPU Speed Define
#define F_CPU 16000000
// Include the necissary library header files
#include <avr/io.h>
int main() {
DDRD |= (1 << DDD5);
PORTD |= (1 << PD5);
PORTD ^= (1 << PD5);
for(;;) { }
}
On the other hand, I can #define the names of the ports so they are more clear, but that doesn't seem like the ideal solution (and it's unfortunately the method that I am currently using).
I would like to abstract some of the setting/functionality of enabling the on board leds (which I eventually hope to extend to other concepts such as timers/interrupts/etc..).
How do I use Struct/Pointers to properly abstract this?
I am currently trying the following method, but it is falling flat, and the LED is failing to turn on:
OnBoardLED.h
typedef struct {
unsigned int dataDirectionRegister;
unsigned int portNumber;
unsigned int pinNumber;
} OnBoardLED;
void setDataDirectionRegister(OnBoardLED* led, unsigned int DDR);
void setPortNumber(OnBoardLED* led, unsigned int port);
void setPinNumber(OnBoardLED* led, unsigned int pin);
void turnOn(OnBoardLED* led);
void turnOff(OnBoardLED* led);
and
main.c
#include "inc/OnBoardLED.h"
int main(void) {
OnBoardLED greenLED;
setDataDirectionRegister(&greenLED, DDRD);
setPortNumber(&greenLED, PORTD);
setPinNumber(&greenLED, 5);
turnOn(&greenLED);
for(;;) { }
}
I know that I should be using pointers in this instance, specifically for the Data Direction Registers and the Port (so that I am properly referencing that memory location), but I do not know how to properly reference them.
What am I missing here?
Note: If needed I will post my current implementations of each function, defined in OnBoardLED.c
Edit:
OnBoardLED.c
#include "inc/OnBoardLED.h"
void setDataDirectionRegister(OnBoardLED* led, unsigned int DDR) {
led->dataDirectionRegister = DDR;
}
void setPortNumber(OnBoardLED* led, unsigned int port) {
led->portNumber = port;
}
void setPinNumber(OnBoardLED* led, unsigned int pin) {
led->pinNumber = pin;
}
void turnOn(OnBoardLED* led) {
led->dataDirectionRegister |= (1 << led->pinNumber);
led->portNumber |= (1 << led->pinNumber);
led->portNumber ^= (1 << led->pinNumber);
}
I'm not too much practical with AVR toolchain but from what I remember and understand things like DDRD are macro which map addresses from address space to register of the CPU.
So by inspecting the source code you obtain something like:
#define __SFR_OFFSET 0
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#define DDRD _SFR_IO8(0x0A)
This means that replacing DDRD yields something like:
*(volatile uint8_t*)((0x0A) + 0)
which is a smart macro, when used as a left-hand operand allows you to store a value at that memory address, when used as a right-hand operand you can read the value of the register. But this is still a macro and macros can hide evil details like in this situation.
What happens is that your code is
led->dataDirectionRegister = *(volatile uint8_t*)((0x0A) + 0);
led->dataDirectionRegister |= (1 << led->pinNumber);
so what you are doing is just saving the value of the data direction register into the struct member and then overwrite it with the value you would like to save into the register. So nothing basically happens.
What you need is to save the address of the data direction register to be able to dereference it later when calling the turnOn method. This is easily accomplished by having a member declared as
volatile uint8_t* dataDirectionRegister;
So that you can do
void setDataDirectionRegister(OnBoardLED* led, volatile uint8_t* DDR) {
led->dataDirectionRegister = DDR;
}
and invoke it as setDataDirectionRegister(&led, &DDRD);. Notice the & operator used to obtain the address of the memory location of the register.
But now you have an address so in your turnOn method you must dereference the variable to store data into it:
void turnOn(OnBoardLED* led) {
*led->dataDirectionRegister |= (1 << led->pinNumber);
...
So let's make a concrete example to show you the problem and how to fix it:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define __SFR_OFFSET 0
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(&buffer[0] + mem_addr))
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#define DDRD _SFR_IO8(0x0A)
uint8_t buffer[256];
int main(void) {
memset(&buffer[0], 0, 256);
DDRD = 0x40;
printf("value: %x\n", (int)DDRD);
*(volatile uint8_t*)(&buffer[0] + (0x0A + 0)) = 0x41;
printf("value: %x\n", (int)DDRD);
// now let's do what you are doing in your struct
unsigned int dataDirectionRegister = DDRD; // value of register is copied into variable
dataDirectionRegister = 0x80; // variable is changed but not real register
printf("register: %x, variable: %x\n", (int)DDRD, dataDirectionRegister);
// you must save an address to do what you need
volatile uint8_t* realDataDirectionRegister = &DDRD;
*realDataDirectionRegister = 0x80;
printf("register: %x, variable: %x\n", (int)DDRD, (int)*realDataDirectionRegister);
return 0;
}
Mind that I used a buffer as my fake memory space, since you don't have a flat memory model free to use like in a x86 architecture like you have in a microcontroller.
I'm getting into micro-controller hacking and while I'm very comfortable with bitwise operators and talking right to the hardware, I'm finding the resulting code very verbose and boilerplate. The higher level programmer in me wants to find an effective but efficient way to clean it up.
For instance, there's a lot of setting flags in registers:
/* Provided by the compiler */
#define SPIE 7
#define SPE 6
#define DORD 5
#define MSTR 5
#define CPOL 4
#define CPHA 3
void init_spi() {
SPCR = (1 << SPE) | (1 << SPIE) | (1 << MSTR) | (1 << SPI2X);
}
Thankfully there are macros that hide actual port IO operations (the left hand side), so it looks like a simple assignment. But all that syntax to me is messy.
Requirements are:
it only has to handle up to 8 bits,
the bit positions must be able to be passed in any order, and
should only require set bits to be passed.
The syntax I'd like is:
SPCR = bits(SPE, SPIE, MSTR, SPI2X);
The best I've come up with so far is a combo macro/function:
#define bits(...) __pack_bits(__VA_ARGS__, -1)
uint8_t __pack_bits(uint8_t bit, ...) {
uint8_t result = 0;
va_list args;
va_start(args, bit);
result |= (uint8_t) (1 << bit);
for (;;) {
bit = (uint8_t) va_arg(args, int);
if (bit > 7)
break;
result |= (uint8_t) (1 << bit);
}
}
This compiles to 32 bytes on my particular architecure and takes 61-345 cycles to execute (depends on how many bits were passed).
Ideally this should be done in preprocessor since the result is a constant, and the output machine instructions shouldbe just an assignment of an 8 bit value to a register.
Can this be done any better?
Yea, redefine the macros ABC as 1 << ABC, and you simplify that. ORing together bit masks is a very common idiom that anyone will recognize. Getting the shift positions out of your face will help a lot.
Your code goes from
#define SPIE 7
#define SPE 6
#define DORD 5
#define MSTR 5
#define CPOL 4
#define CPHA 3
void init_spi() {
SPCR = (1 << SPE) | (1 << SPIE) | (1 << MSTR) | (1 << SPI2X);
}
to this
#define BIT(n) (1 << (n))
#define SPIE BIT(7)
#define SPE BIT(6)
#define DORD BIT(5)
#define MSTR BIT(5)
#define CPOL BIT(4)
#define CPHA BIT(3)
void init_spi() {
SPCR = SPE | SPIE | MSTR | SPI2X;
}
This suggestion does assume that the bit-field definitions are used many times more than there are definitions of them.
I feel like there might be some way to use variadic macros for this, but I can't figure on anything that could easily be used as an expression. Consider, however, creating an array literal inside a function generating your constant:
#define BITS(name, ...) \
char name() { \
char[] bits = { __VA_ARGS__ }; \
char byte = 0, i; \
for (i = 0; i < sizeof(bits); ++i) byte |= (1 << bits[i]); \
return byte; }
/* Define the bit-mask function for this purpose */
BITS(SPCR_BITS, SPE, SPIE, MSTR, SPI2X)
void init_spi() {
SPCR = SPCR_BITS();
}
If your compiler is good, it will see that the entire function is constant at compile-time, and inline the resultant value.
Why not create your own definitions in addition to the pre-defined ones...
#define BIT_TO_MASK(n) (1 << (n))
#define SPIE_MASK BIT_TO_MASK(SPIE)
#define SPE_MASK BIT_TO_MASK(SPE)
#define DORD_MASK BIT_TO_MASK(DORD)
#define MSTR_MASK BIT_TO_MASK(MSTR)
#define CPOL_MASK BIT_TO_MASK(CPOL)
#define CPHA_MASK BIT_TO_MASK(CPHA)
void init_spi() {
SPCR = SPE_MASK | SPIE_MASK | MSTR_MASK | SPI2X_MASK;
}