Page 1 of 1

C using MMAP I/O for raspberry pi

Posted: Fri Oct 17, 2014 3:18 am
by nizam
I try to follow the gerboard manual but still without using the gertboard, only by using raspberry pi. Could somebody tell me what is wrong with it? I already compile it but there is nothing.This is the code I took from Gert van Loo and Dom blinking LED code and use it for ultrasonic sensor.Anyway thanks for helping :)

Code: Select all

#define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */


#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <time.h>

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

int mem_fd;
void *gpio_map;

// I/O access
volatile unsigned *gpio;


// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))

#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0

#define GET_GPIO *(gpio+13)

#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock

void setup_io();

int main(int argc, char **argv)
{
int distance;
time_t start= 0;
time_t end= 0;
time_t elapsed = 0;
// Set up gpi pointer for direct register access
setup_io();
INP_GPIO(23); // must use INP_GPIO before we can use OUT_GPIO
OUT_GPIO(23);
INP_GPIO(7); //input for echo pin

GPIO_CLR = (1 << 23);
sleep(0.1) // allow module to settle
GPIO_SET = (1<<23);
sleep(0.00001); // send pulse 10us 
GPIO_CLR = (1<<23);

while ((GET_GPIO = ( 0<<7)))
{} // i already change the get_gpio
start = time(NULL);
while ((GET_GPIO = ( 1<<7))) 
{} // input HIGH
end = time(NULL);
elapsed = end- start;
distance = (elapsed*34000)/2 ; //in cm
printf("distance: %d cm¥n", distance);


return 0;

} // main


//
// Set up a memory regions to access GPIO
//
void setup_io()
{
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem \n");
exit(-1);
}

/* mmap GPIO */
gpio_map = mmap(
NULL, //Any adddress in our space will do
BLOCK_SIZE, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
GPIO_BASE //Offset to GPIO peripheral
);

close(mem_fd); //No need to keep mem_fd open after mmap

if (gpio_map == MAP_FAILED) {
printf("mmap error %d\n", (int)gpio_map);//errno also set!
exit(-1);
}

// Always use volatile pointer!
gpio = (volatile unsigned *)gpio_map;


} // setup_io

Re: C using MMAP I/O for raspberry pi

Posted: Fri Oct 17, 2014 5:48 am
by Heater
What do you mean "there is nothing"?

Do yo get the error message "can't open /dev/mem"?

Are you running your code as root user?

I played with mmap code from here: http://elinux.org/RPi_Low-level_peripherals which looks like it should be the same. Worked fine.

Re: C using MMAP I/O for raspberry pi

Posted: Fri Oct 17, 2014 6:02 am
by nizam
Thanks for replying my post. I didn't get any error. But when compiling there seems like it stuck. It should be state the distance detected from the ultrasonic sensor but it doesn't come out :(

Re: C using MMAP I/O for raspberry pi

Posted: Fri Oct 17, 2014 7:49 am
by joan
You are probably not sending a trigger pulse.

man 3 sleep # there are several sleep commands, you want manual 3

will show that sleep is in units of a second, so sleep(0.1) and sleep(0.0001) etc. will result in sleep(0) which is no delay at all.

Perhaps you meant to use usleep which is in units of microseconds,

man usleep

clock on my laptop returns units of 1/100ths of a second. You probably won't get the resolution you need.

man 3 clock

Have a look at gettimeofday.

man gettimeofday

Re: C using MMAP I/O for raspberry pi

Posted: Fri Oct 17, 2014 8:37 am
by nizam
Thanks Joan. I follow your advice and end up rewrite back my code. But still the same problem appear.

this my code.

Code: Select all

#include <sys/time.h>
int main(int argc, char **argv)
{
int distance;
struct timeval start,end;;
double elapsed ;
// Set up gpi pointer for direct register access
setup_io();
INP_GPIO(23); // must use INP_GPIO before we can use OUT_GPIO
OUT_GPIO(23);
INP_GPIO(7); //input for echo pin

GPIO_CLR = (1 << 23);
usleep(30000) // allow module to settle

printf("starting measurement")
GPIO_SET = (1<<23);
usleep(10); // send pulse 10us 
GPIO_CLR = (1<<23);


while ((GPIO_CLR = ( 0<<7)))
{} 
gettimeofday(&start,NULL);
while ((GPIO_SET = ( 1<<7))) 
{} // input HIGH
gettimeofday(&end,NULL);
elapsed = (end.tv_sec - start.tv_sec);
distance = (elapsed)/2 ; //in cm
printf("distance: %d cm¥n", distance);


return 0;

}

Re: C using MMAP I/O for raspberry pi

Posted: Sun Oct 19, 2014 8:05 am
by joan
I'm not a great fan of those macros.

while ((GPIO_CLR = ( 0<<7)))

Should that be

while ((GPIO_CLR = ( 1<<7)))

Re: C using MMAP I/O for raspberry pi

Posted: Sun Oct 19, 2014 10:07 am
by Redrobes
I think you may need an == instead of = as well. Maybe. Its hard to read the code like that. Looks to me like you need to set the GPIO_CLR value in which case putting that in a while loop seems like it might loop forever.

Using macros like this is poor style. You should only do this if you need the absolute max performance and even then the format that you have used is not great. You would be better off writing small functions to write and read values and then return a code which you could put into the loop test. Something like.

while( !GPIO_Clr() ) { }

etc.