Bitwise macro not working (Avr C) - c

I'm facing some issues with this macro:
#define SHOW(val) PORTB = ((PORTB & 0xFF^OUT_PINS) | ((val) & OUT_PINS));
Let's say I have (defined earlier)
#define OUT_PINS 0b00011110
and PORTB has some values on other bits that I want to preserve.
The macro was intended to apply val to PORTB (OUT_PINS only) and leave the rest alone.
However, I'm just getting 1's on all output pins.
What's wrong with my code?

Okay so this was a silly mistake.
#define SEG_DOT _BV(PB1)
#define SEG_DIAG1 _BV(PB2)
#define SEG_DIAG2 _BV(PB3)
#define SEG_HORIZ _BV(PB4)
#define BUTTON _BV(PB0)
#define OUT_PINS SEG_DOT | SEG_DIAG1 | SEG_DIAG2 | SEG_HORIZ
#define IN_PINS BUTTON
#define BTN() (PINB & BUTTON == 0)
#define SHOW(val) PORTB = ((PORTB & ~OUT_PINS) | ((val) & OUT_PINS));
As you can see the OUT_PINS macro does not have brackets around it, so when it's expanded in the SHOW macro, it all becomes a huge nonsense.
Two possible fixes:
#define OUT_PINS (SEG_DOT | SEG_DIAG1 | SEG_DIAG2 | SEG_HORIZ)
OR
#define SHOW(val) PORTB = ((PORTB & ~(OUT_PINS)) | ((val) & (OUT_PINS)));
I like the first fix better, because the second looks very Lispy. Though, why not use both, after all.

Related

GPIO Output Register Bit value not updating

I just started learning about embedded systems and I'm having a bit of trouble with correctly setting up the led pin on my stm32f746ng-discovery board. I am not sure if I am not typecasting correctly or have the wrong address for the pin however, I do believe I have addressed everything correctly and I'm not seeing a value change for the GPIO output data register in the watch window which leads me to believe there might be an issue with my code.
To define the registers and their respective addresses this is the approach I took:
//Referring to STM32F746xx Memory Map and Register Boundary Addresses:
#define PERIPH_BASE (0x40000000UL)
#define AHB1PERIPH_OFFSET (0x00020000UL)
#define AHB1PERIPH_BASE (PERIPH_BASE + AHB1PERIPH_OFFSET)
#define GPIOI_OFFSET (0x2000UL)
#define GPIOI_BASE (AHB1PERIPH_BASE + GPIOI_OFFSET)
#define RCC_OFFSET (0x3800UL)
#define RCC_BASE (AHB1PERIPH_BASE + RCC_OFFSET)
#define RCC_AHB1EN_R_OFFSET (0x30UL)
#define RCC_AHB1EN_R (*(volatile unsigned int *)(RCC_BASE + RCC_AHB1EN_R_OFFSET)) //register
#define MODE_R_OFFSET (0x00UL)
#define GPIOI_MODE_R (*(volatile unsigned int *)(GPIOI_BASE + MODE_R_OFFSET)) //register
#define OD_R_OFFSET (0x14UL)
#define GPIOI_OD_R (*(volatile unsigned int *)(GPIOI_BASE + OD_R_OFFSET)) //register
#define GPIOIEN (1U << 0)
#define PIN_1 (1U << 1)
#define LED_PIN PIN_1
The above hex addresses I located from the stm32f746xx datasheet's memory map/table and RM0385 reference manual for the stm32f74xxx.
The code below is the main function where I try to change the bit value of the GPIOI_OD_R register:
int main(void)
{
/* 1. Enable clock access for GPIOI.*/
/* 1.1 I use the OR operator to only change the first bit instead of the whole 32bit chain. */
RCC_AHB1EN_R |= GPIOIEN;
/* 2. Sets PIN_1 as output.*/
GPIOI_MODE_R |= (1U << 2);
GPIOI_MODE_R &=~(1U << 3);
while(1)
{
/* 3. Sets PIN_1 high */
GPIOI_OD_R |= LED_PIN;
}
}
The problem that I am having is that the bit value for the GPIOI_OD_R register is not updating correctly and gets set to 00 instead of 01 which is the required value for the GPIOI Pin_1 (LED) to be set to the general-purpose output mode.
The above parameters I got from the RM0385 reference manual for the stm32f74xxx which can be seen in the image below:
However, when running the code the GPIOI_MODE_R and the GPIOI_OD_R bit values do not change which can be seen in the image below:
I need the values of the registers to be correct to set the LED PIN high on my stm32f746ng-discovery board.
I tried combining the GPIOI_MODE_R setting operation into a single one: GPIOI_MODE_R = (GPIOI_MODE_R | (1U << 2)) & ~(1U << 3) however that causes the program to loose connection with the debugger.
I am using the STM32CubeIDE with the following MCU GCC Compiler Settings:
Thanks in advance and if have referenced something incorrectly please excuse me im new to embedded systems.
I found the issue and realised that I was addressing the wrong bit value for the GPIOIEN. Instead of looking at the bit address for GPIOIEN with:#define GPIOIEN (1U << 8) I was making the mistake to look at the bit address for GPIOAEN with:#define GPIOIEN (1U << 0).
A super silly mistake from my side however I think it might be a mistake that many beginners like myself may make. The only advice that I can give from what I experienced and the process it took to solve the issue is to try and be extra accurate and properly focus when reading through the various board's references manuals and datasheets. When it comes to solving the issue I would say it is important to stay consistent with your code which makes it much easier during the debugging process because I followed this methodology I was able to trace each srep of my code and compare what I expected the values to be versus what I was actually getting.
The final code solution I have attached below:
//Referring to STM32F746xx Memory Map and Register Boundary Addresses:
#define PERIPH_BASE (0x40000000UL)
#define AHB1PERIPH_OFFSET (0x00020000UL)
#define AHB1PERIPH_BASE (PERIPH_BASE + AHB1PERIPH_OFFSET)
#define GPIOI_OFFSET (0x2000UL)
#define GPIOI_BASE (AHB1PERIPH_BASE + GPIOI_OFFSET)
#define RCC_OFFSET (0x3800UL)
#define RCC_BASE (AHB1PERIPH_BASE + RCC_OFFSET)
#define RCC_AHB1EN_R_OFFSET (0x30UL)
#define RCC_AHB1EN_R (*(volatile unsigned int *)(RCC_BASE + RCC_AHB1EN_R_OFFSET))
#define MODE_R_OFFSET (0x00UL)
#define GPIOI_MODE_R (*(volatile unsigned int *)(GPIOI_BASE + MODE_R_OFFSET))
#define OD_R_OFFSET (0x14UL)
#define GPIOI_OD_R (*(volatile unsigned int *)(GPIOI_BASE + OD_R_OFFSET))
#define GPIOIEN (1U << 8) // updated from (1U << 0)
#define PIN_1 (1U << 1)
#define LED_PIN PIN_1
int main(void)
{
/* 1. Enable clock access for GPIOI.*/
/* 1.1 I use the OR operator to only change the first bit instead of the whole 32bit chain. */
RCC_AHB1EN_R |= GPIOIEN;
/* 2. Sets PIN_1 as output.*/
GPIOI_MODE_R |= (1U << 2);
GPIOI_MODE_R &=~(1U << 3);
while(1)
{
/* 3. Sets PIN_1 high */
GPIOI_OD_R |= LED_PIN;
}
}

C Left shift unexpected behavior

I have this code:
void GPIO_InitPortPin(uint8* PortControl, uint8 Pin, uint8 PinDir){
*PortControl &= (~(1U << Pin));
*PortControl |= (PinDir << Pin);
}
If the PortControl register is 11111111, the first line should clear the bit of whatever the corresponding Pin is, but unexpectedly it clears all the register.
My Client Function is: GPIO_InitPortPin(&TRISB, GPIO_PIN_0, GPIO_IN);
GPIO_PIN_0 and GPIO_IN are macros defined as follows:
#define GPIO_PIN_0 (0)
#define GPIO_PIN_1 (1)
...
#define GPIO_PIN_7 (7)
#define GPIO_OUT (0)
#define GPIO_IN (1)
So, I tried to cast Pin to sint8: *PortControl &= (~(1U << (sint8) Pin));
and it worked. Also, I tried to hard-code the Pin as 1 and it worked fine. I know the problem is that Pin is uint8 or specifically to be unsigned since
*PortControl &= (~(1U << 1));
also worked fine.
My Question is: why the right operand type affects the shifting operation, although I've red otherwise before(That RHS doesn't affect operation)?
Iam using SDCC compiler.
Edit : I've tested the function without casting on gcc and it worked as expected.

What is the purpose of bitshifting by 0

I am reviewing the open source AMD GPU drivers for Linux. I noticed something I haven't seen before, and I would like to know the purpose. On line 1441 of the sid.h file, there are a series of defines that are integers being bitshifted left by 0. Wouldn't this just result in the original integer being operated on?
Here is an excerpt and a link to the head
#define VGT_EVENT_INITIATOR 0xA2A4
#define SAMPLE_STREAMOUTSTATS1 (1 << 0)
#define SAMPLE_STREAMOUTSTATS2 (2 << 0)
#define SAMPLE_STREAMOUTSTATS3 (3 << 0)
https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/amd/amdgpu/sid.h#L1441
Also, I am learning to access the performance counter registers of AMD GPUs in order to calculate the GPU load. Any tips on that would be appreciated as well.
Things like that could be done just for the sake of consistency (not necessarily applicable to your specific case). For example, I can describe a set of single-bit flags as
#define FLAG_1 0x01
#define FLAG_2 0x02
#define FLAG_3 0x04
#define FLAG_4 0x08
or as
#define FLAG_1 (1u << 0)
#define FLAG_2 (1u << 1)
#define FLAG_3 (1u << 2)
#define FLAG_4 (1u << 3)
In the first line of the latter approach I did not have to shift by 0. But it just looks more consistent that way and emphasizes the fact that FLAG_1 has the same nature as the rest of the flags. And 0 acts as a placeholder for a different value, if I some day decide to change it.
You can actually see exactly that in the linked code with shift by 0 in the definitions of DYN_OR_EN and DYN_RR_EN macros.
The approach can be extended to multi-bit fields within a word, like in the following (contrived) example
// Bits 0-3 - lower counter, bits 4-7 - upper counter
#define LOWER_0 (0u << 0)
#define LOWER_1 (1u << 0)
#define LOWER_2 (2u << 0)
#define LOWER_3 (3u << 0)
#define UPPER_0 (0u << 4)
#define UPPER_1 (1u << 4)
#define UPPER_2 (2u << 4)
#define UPPER_3 (3u << 4)
unsigned packed_counters = LOWER_2 + UPPER_3; /* or `LOWER_2 | UPPER_3` */
Again, shifts by 0 bits are present purely for visual consistency. As well as shifts of 0 values.
You can actually see exactly that in the linked code with shift by 0 in the definitions of LC_XMIT_N_FTS and LC_XMIT_N_FTS_MASK macros.

Atmel C Pin Manipulation Macros

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

A C preprocessor macro to pack bitfields into a byte?

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;
}

Resources