0

Just few days ago I bought Rasberry Pi 3 for education, and try my best at low-level programming. For now I wrote a simple GPIO code to set low and high level on controller's pin. My functions can write digital high and low on pins, by GPIO number (0-53). Without with functions to set high/low on pin I must find required register to set pin to output as GPFSEL0-GPFSEL5 and find required bit (every 3 bit refers to next pin). Then I need to find required GPSET register (GPSET0-GPSET1), every bit of this refers to next pin. So it will looks like:

     //To set high GPIO4 pin (GPFSEL0 and GPSET0 assumed to be adresses)
            #define GPIO4_GPFSEL 12
            #define GPIO4 4
            *GPFSEL0 |= (1 << GPIO4_GPFSEL);
            *GPSET0 |= (1 << 4);

So, I wrote more high-level functions to avoid remebering bits and registers:

gpio_set_mode(GPIO4, GPIO_OUTPUT);
gpio_set_high(GPIO4);

And how looks my functions:

void gpio_set_mode(uint32_t gpio, gpio_mode mode)
{
   uint32_t gpfsel_addr = GPIO_BASE;
   uint32_t gpfsel_num = (uint32_t)(gpio / 10);
   uint32_t gpio_bit = ((((uint32_t)(gpio % 10)) * 3));

   for (int i = 0; i < 6; i++)
   {
       if (i == gpfsel_num)
           break;
       else
           gpfsel_addr += 0x04;
   }

   volatile uint32_t* GPFSEL = (volatile uint32_t*) gpfsel_addr;
   switch (mode)
   {
       case GPIO_OUTPUT:
           *GPFSEL |= (1 << gpio_bit);
       case GPIO_INPUT:
       {
       *GPFSEL &= ~(1 << gpio_bit);
       *GPFSEL &= ~(1 << (gpio_bit+1));
       *GPFSEL &= ~(1 << (gpio_bit+2));
       }
   }
}

void gpio_set_high(uint32_t gpio)
{
    volatile uint32_t* GPSET = ((gpio < 32) ? ( (volatile uint32_t*)(GPSET0)) : ( (volatile uint32_t*)(GPSET1) ));
    uint32_t gpio_bit = (gpio < 32) ? gpio : (gpio - 32);
    *GPSET |= (1 << gpio_bit);
}


void gpio_set_low(uint32_t gpio)
{
   volatile uint32_t* GPCLR = ((gpio < 32) ? ( (volatile uint32_t*)(GPCLR0) ) : ( (volatile uint32_t*)(GPCLR1)));
   uint32_t gpio_bit = ((gpio < 32) ? gpio : (gpio - 32));
   *GPCLR |= (1 << gpio_bit);
}

uint32_t gpio_status(uint32_t gpio)
{
   volatile  uint32_t* GPLEV = ((gpio < 32) ? ((volatile uint32_t*)(GPLEV0)) : ((volatile uint32_t*)(GPLEV1)));
   uint32_t  gpio_bit = ((gpio < 32) ? gpio : (gpio - 32));
   return (*GPLEV & (1 << gpio_bit));
}

And for some reason my code doesnt works. But I sure, it must work. I compile it with arm-none-eabi-gcc with args:

-Wall -O2 -nostdlib -nostartfiles -ffreestanding 

There are no error messages.

  • You say your code doesn't work, so what is the error message you get when you run the code? – Darth Vader Mar 27 '17 at 18:44
  • There are no error messages. When I insert SD-card, and RPi runs my code, i get very unexpected result. I have rechecked for logic errors this code, but all seems to be ok. – shizumia Mar 27 '17 at 18:59
  • 2
    You give no indication of whether you are using an operating system or not. You give no evidence that you have been given permission to access the area of memory used by the GPIO. – joan Mar 27 '17 at 19:58
3

Well, maybe you forgot to put "break" into your switch block case?

switch (mode)
   {
       case GPIO_OUTPUT:
           *GPFSEL |= (1 << gpio_bit);
            break;
       case GPIO_INPUT:
       {
       *GPFSEL &= ~(1 << gpio_bit);
       *GPFSEL &= ~(1 << (gpio_bit+1));
       *GPFSEL &= ~(1 << (gpio_bit+2));
        break;
       }
   }

As for me, if I were writing gpio_set_mode function i would write it like:

#define GPFSEL0 0
#define GPFSEL5 5
void gpio_set_mode(uint32_t gpio, gpio_mode mode)
{
   volatile uint32_t* GPIO = (uint32_t*) GPIO_BASE;
   uint32_t gpfsel_num = (uint32_t)(gpio / 10);
   uint32_t gpio_bit = (gpio % 10) * 3;

   for (int i = GPFSEL0; i < GPFSEL5; i++)
   {
       if (i == gpfsel_num)
       {
            switch (mode)
            {
              case GPIO_OUTPUT:
              {
                GPIO[i] |= (1 << gpio_bit);
                break;
              }
               case GPIO_INPUT:
              {
                GPIO[i] &= ~(1 << gpio_bit);
                GPIO[i] &= ~(1 << (gpio_bit+1));
                GPIO[i] &= ~(1 << (gpio_bit+2));
                break;
              }
            }
        }
     } 
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.