I am attempting to write an API for interaction with the GPIO pins in a bare metal environment in C. However , sometimes when I attempt to turn on one of the GPIO pins it turns multiple on. Here is the API :
#include "gpio.h"
void gpio_setOutput(unsigned int gpioNum) {
//Check if the value is valid
if(gpioNum > 53) {
return;
}
//The pointer to the section of memory that contains the function selector
unsigned int* gpio_FunctionPointer = 0;
//Figure out which 4 bytes of memory is the correct one for the gpioNum
if(gpioNum < 10) {
gpio_FunctionPointer = GPFSEL0;
} else if(gpioNum < 20) {
gpio_FunctionPointer = GPFSEL1;
} else if(gpioNum < 30) {
gpio_FunctionPointer = GPFSEL2;
} else if(gpioNum < 40) {
gpio_FunctionPointer = GPFSEL3;
} else if(gpioNum < 50) {
gpio_FunctionPointer = GPFSEL4;
} else if(gpioNum < 60) {
gpio_FunctionPointer = GPFSEL5;
} else {
return;
}
//Get the exact location of the 3 bits for the particular gpioNum
unsigned int memPart = (gpioNum%10)*3;
//Get the 4 bytes of memory at the function memory
unsigned int bytes = *gpio_FunctionPointer;
//Calaculate the 4 bytes to clear the current function setting of gpioNum
unsigned int clearFlag = (0b111 << memPart);
//calculate the 4 bytes in order to set the function to output for gpioNum
unsigned int outputFlag = (0xFFFFFFF9 << memPart) | (0xFFFFFFF9 >> (32 - memPart));
//Clear the function
bytes = bytes | clearFlag;
//Set the function
bytes = bytes & outputFlag;
//Put the 4 bytes back
*gpio_FunctionPointer = bytes;
}
void gpio_outputSet(unsigned int gpioNum) {
//Check if the value is valid
if(gpioNum > 53) {
return;
}
unsigned int* gpio_SetPointer = 0;
unsigned int memPart = 0;
//Figure out which part of the memory relates to gpioNum
if(gpioNum < 32) {
gpio_SetPointer = GPSET0;
memPart = gpioNum;
} else {
gpio_SetPointer = GPSET1;
memPart = gpioNum - 32;
}
//Get the relivant bytes
unsigned int bytes = *gpio_SetPointer;
//Calculate the flag for the specific gpioNum
unsigned int setFlag = 0b1 << memPart;
//Add it to bytes
bytes = bytes | setFlag;
//Set the relevnat memory.
*gpio_SetPointer = bytes;
}
void gpio_outputClr(unsigned int gpioNum) {
//Check if the value is valid
if(gpioNum > 53) {
return;
}
unsigned int* gpio_SetPointer = 0;
unsigned int memPart = 0;
//Figure out which part of the memory relates to gpioNum
if(gpioNum < 32) {
gpio_SetPointer = GPCLR0;
memPart = gpioNum;
} else {
gpio_SetPointer = GPCLR1;
memPart = gpioNum - 32;
}
//Get the relivant bytes
unsigned int bytes = *gpio_SetPointer;
//Calculate the flag for the specific gpioNum
unsigned int setFlag = 0b1 << memPart;
//Add it to bytes
bytes = bytes | setFlag;
//Set the relevnat memory.
*gpio_SetPointer = bytes;
}
The code should set the memory as specified in the bcm2835 arm peripherals manual so that the gpio function is set to output and the gpio pins are turned on and off (by setting the Clr or Set memory to 1) , however , it appears to be turing on multiple pins with one call of the function and I am unable to determine why.
When running this code on my own computer the bytes seem to be correctly set. So I assume there is something I need to do in addition to what this code is doing in order to interact with the GPIO. But I do not know what. What is wrong with my code that is causing multiple GPIO pins to come on when my code is only set to turn on one?
The full code can be found here