C Left shift unexpected behavior - c

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.

Related

LED blinking on TM4C123 fails if not "halting clock cycles"

I'm learning Embedded System by following this tutorial. In their attached code for LED blinking on TM4C123, they created the variable ulLoop which made me confused, since they just asigned the click enabling byte to ulLoop but never used it afterwards. However, I tried deleting the line writing ulLoop = SYSCTL_RCGCGPIO_R; and the LED stop blinking, as they said in the tutorial "The uloop variable and the statement containing uloop is present there only to halt 3 clock cycles before moving to peripherals, which is a must while working with TIVA."
I cannot understand what did they mean by "halt 3 clock cycles" and "moving to peripherals", and why it needs to halt 3 clock cycles, not 4, or 5 cycles, or not at all. In addition, if I know nothing about what's mentioned in the tutorial regarding the magic variable, just finding out the program not working, how am I supposed to know where the problem is without further information, since during building there is 0 errors and warnings. Pealse pardon with me if the question is not asked in a right way or sounds silly.
#define SYSCTL_RCGCGPIO_R (*(( volatile unsigned long *)0x400FE608 ) )
#define GPIO_PORTF_DATA_R (*(( volatile unsigned long *)0x40025038 ) )
#define GPIO_PORTF_DIR_R (*(( volatile unsigned long *)0x40025400 ) )
#define GPIO_PORTF_DEN_R (*(( volatile unsigned long *)0x4002551C ) )
#define GPIO_PORTF_CLK_EN 0x20
#define GPIO_PORTF_PIN1_EN 0x02
#define LED_ON1 0x02
#define GPIO_PORTF_PIN2_EN 0x04
#define LED_ON2 0x04
#define GPIO_PORTF_PIN3_EN 0x08
#define LED_ON3 0x08
#define DELAY_VALUE 1000000
volatile unsigned long j=0;
static void Delay(void){
for (j=0; j<DELAY_VALUE ; j++);
}
int main ( void )
{
volatile unsigned long ulLoop ; // I don't understand why creating this variable
SYSCTL_RCGCGPIO_R |= GPIO_PORTF_CLK_EN ;
ulLoop = SYSCTL_RCGCGPIO_R; // But if not adding this line the LED won't blink
GPIO_PORTF_DIR_R |= GPIO_PORTF_PIN1_EN ;
GPIO_PORTF_DEN_R |= GPIO_PORTF_PIN1_EN ;
GPIO_PORTF_DIR_R |= GPIO_PORTF_PIN2_EN ;
GPIO_PORTF_DEN_R |= GPIO_PORTF_PIN2_EN ;
GPIO_PORTF_DIR_R |= GPIO_PORTF_PIN3_EN ;
GPIO_PORTF_DEN_R |= GPIO_PORTF_PIN3_EN ;
// Loop forever .
while (1)
{
GPIO_PORTF_DATA_R &= LED_ON3;
GPIO_PORTF_DATA_R &= LED_ON2;
GPIO_PORTF_DATA_R |= LED_ON1;
Delay();
GPIO_PORTF_DATA_R &= LED_ON1;
GPIO_PORTF_DATA_R &= LED_ON2;
GPIO_PORTF_DATA_R |= LED_ON3;
Delay();
GPIO_PORTF_DATA_R &= LED_ON3;
GPIO_PORTF_DATA_R &= LED_ON1;
GPIO_PORTF_DATA_R |= LED_ON2;
Delay();
}
}
Since in this the previous line
SYSCTL_RCGCGPIO_R |= GPIO_PORTF_CLK_EN ;
The program is enabling the clock, this line
ulLoop = SYSCTL_RCGCGPIO_R;
is just a dummy code that gives a little bit of time to the microcontroller clock to stabilize.
You will find this valid for any microcontroller you will be working with, that after clock setting you must allow some time for the clock to stabilize.
Now, Why 3 clock cycles? This info you should find when reading the microcontroller datasheet in which it shall be specified how many clock cycles are needed to stabilize the clock?
Why not 5 or more? Of course, you don't want to waste so many clock cycles in this operation, so the rest of the program can be executed as soon as possible.
How does this dummy line correspond to 3 clock cycles?
ulLoop = SYSCTL_RCGCGPIO_R;
Well, this is really different from one controller to another or more specifically from compiler to the other. The compiler does translate this c-code line into assembly code. each assembly line takes one clock cycle for execution. So it seems like whoever wrote this code, just looked out at the generated assembly code from the compiler and finds out this line is translated to 3 assembly instructions.
how am I supposed to know where the problem is without further information
In the embedded system world, this can be achieved by debugging. Some of the issues are really hard to debug especially when it's something in the controller initialization sequence.
You should be very careful when initializing the controller (clock, peripherals) by following the datasheet instructions/recommendations.

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

While LEDs on GPIO2 work OK, but on the GPIO1 with LPC1768

I have a custom board with device LPC1768. While every other functionalities (such as LCD on SPI, Ethernet, I2C EEPROM, etc.) are OK,
for some reason, while I can turn ON and OFF LEDs on the GPIO2 but I can't do the same for the pins on the GPIO1. Maybe I shouldn't blame whole GPIO1 (or myself) but at least the part I try to use.
If I connect a button on one of the the GPIO1 pins (with internal pull-ups and as an OUTPUT)
I can read the button inputs as it should be.
Here is the definition part as per the user manual;
#define FIO_BASE_ADDR (0x2009C000)
#define FIO1CLR (*(volatile unsigned int *)(FIO_BASE_ADDR + 0x3C))
#define FIO2CLR (*(volatile unsigned int *)(FIO_BASE_ADDR + 0x5C))
#define FIO1SET (*(volatile unsigned int *)(FIO_BASE_ADDR + 0x38))
#define FIO2SET (*(volatile unsigned int *)(FIO_BASE_ADDR + 0x58))
While a LED on the pin P2.5 turns ON and OFF as it should be;
FIO2SET = (1uL << 5); // P2.5
FIO2CLR = (1uL << 5); // P2.5
A LED on P1.18 doesn't turn ON;
FIO1SET = (1uL << 18); // P1.18
In order to test all the LEDs connected to the GPIO1 pins, I wrote two lines of code using LPC17xx.h and then proofed that it works, all the LEDs are turning ON and OFF accordingly.
LPC_GPIO1->FIOSET = 0xffffffff;
LPC_GPIO1->FIOCLR = 0xffffffff;
Any input highly appreciated.

led and switchs program failure Tiva C board

I'm trying to run this code on TIVA C board. sw2 connected to PF0, sw1 connected to PF4 and RGB LED connected to PF1, PF2 and PF3.
When I press sw2 it shall turn the led blue and if sw1 is pressed it shall turn the led green otherwise it shall be red.
The code doesn't function properly. I hope you can point out what I did wrong.
/*************************
PORT F Addresses
*************************/
#define RCGCGPIO (*((volatile unsigned long*)0x400FE608)) //CLOCK
#define PORTFDATA (*((volatile unsigned long*)0x400253FC)) //DATA
#define PORTFDIR (*((volatile unsigned long*)0x40025400)) //DIRECTION
#define PORTFDEN (*((volatile unsigned long*)0x4002551C)) //ENABLE
#define PORTFLOCK (*((volatile unsigned long*)0x40025520)) //LOCK (lock or unlocks PF0)
#define PORTFCR (*((volatile unsigned long*)0x40025524)) //COMMIT (uncommit PF0)
#define PORTFPUR (*((volatile unsigned long*)0x40025510)) // PULL UP resistor
#define PORTFPDR (*((volatile unsigned long*)0x40025514)) // PULL Down resistor
/*************************/
int sw1;
int sw2;
int delay;
int main (void)
{
RCGCGPIO = 0x20; //Enable clock for PORT F
delay = RCGCGPIO;
PORTFLOCK = 0x4C4F434B; // unlock commit reg
PORTFCR = 0x01; // unlock PF0
PORTFDEN = 0x1F; //Enable pins 0 to 4
PORTFDIR = 0x0E; // pins 0 and 4 input - pins 1,2,3 output
PORTFPUR = 0x11;
while (1)
{
sw2 = PORTFDATA & 0x00000001;
sw1 = PORTFDATA & 0x00000010;
if (sw1 == 1)
PORTFDATA |= 0x00000002;
else if (sw2 == 1)
PORTFDATA |= 0x00000004;
else
PORTFDATA |= 0x00000008;
}
}
Here are two obvious problems with your code. There are probably more...
You set sw1 = PORTFDATA & 0x00000010, so the only possible values sw1 can have are 0x10 or 0x00. Then you test if (sw1 == 1). But this test will never be true because sw1 can never equal 1.
You use the |= operator to set the bits of PORTFDATA. But nowhere do you ever clear the bits of PORTFDATA. So your LEDs may turn on but they will never turn off.
Have you tried the sample code comming with CCS to make sure that hardware are functional?
The sample code uses TI library instead of plain register Read & Write, however you can dig out the acutal register by go to defination. Anyway, I'm a bit curious about why you use plain register in the first place instead of TI library? ARM MCU is not 8051 anymore.
A couple of things to keep in mind:
The launchpad buttons are negative logic, so if your switch1== 0x01, it is NOT being pressed.
Try something like:
If
sw1 == 0x01 //switch not pressed
PORTFDATA &= ~(0x0E); //ledz off
else
PORTFDATA ^= 0x02; //toggle red
I am also learning ARM & C solely self-study, so I feel your pain. It took many hours of toggling single leds with bitwise operators just to fathom what is going on. Stick with it!!!
/e

LUT in a macro C

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

Resources