Segmentation fault?

nemka
#include <stdio.h>
#include <stdlib.h>
#define rGPFCON (*(volatile unsigned *)0x56000050)  //Port F control
#define rGPFDAT (*(volatile unsigned *)0x56000054)  //Port F data

int main()
{
    volatile unsigned *ptr_control=(volatile unsigned *)rGPFCON;
    volatile unsigned *ptr_data=(volatile unsigned *)rGPFDAT;
    int ex=1;
    unsigned char led_state=0;
    *ptr_control=0;
    *ptr_data=0;
    while(ex!=0)
    {
        *ptr_control=(*ptr_control)|(1<<14);
        printf("turn led on or off? ON(1),OFF(0)\n");
        scanf("%c",&led_state);
        *ptr_data=(*ptr_data)|(led_state<<7);
        printf("exit?yes(0),no(1)");
        scanf("%d",&ex);
    }
    return 0;
}


im getting Segmentation fault on the mini2440 when i run it.
on my notebook i compiled it with arm-linux-gcc then i used file command:
arkady_ilan_rozbaum@ubuntu:~/led1$ file led2
led2: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked
(uses shared libs), for GNU/Linux 2.6.14, not stripped
as you can see it is for ARM,as i said once i copy it to the mini using
diskonkey (i copy it to the mini i don't run it throw the diskonkey) i get
the segmentation fault.
also im just a beginner and my code may not be the best but as you can see
it basically is supposed to turn one led on or off.

davef
Try running a simple Hello program first to check your build system, then
move on to the more serious stuff.

Juergen Beisert
Did you try to run your program on the Mini2440 from within Linux? If yes,
search in the web how to handle "memory protection" on an operation system 
like Linux. Other keywords are "virtual address space", "MMU (Memory
Managamenet Unit)" and the "mmap()" system call.

nemka
yes davef i did run the hello world.
also updated the code to this:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#define rGPFCON    (*(volatile unsigned *)0x56000050)  //Port F control
#define rGPFDAT    (*(volatile unsigned *)0x56000054)  //Port F data
#define rGPFUP     (*(volatile unsigned *)0x56000058)  //Pull-up control F

int main()
{
        printf("%d,zero on sucess\n",mprotect((unsigned
*)0x56000050,12,PROT_WRITE|PROT_READ));
  printf("printf0\n");
        fflush(stdout);
    rGPFCON=0x55aa;//all outputs
  printf("printf1\n");
  fflush(stdout);
    rGPFDAT=0x56ae;//no pull up
    rGPFDAT=0xf0;//all leds are on
  printf("printf2\n");
        fflush(stdout);
    int ex=1;
    unsigned char led_state=0;
    while(ex!=0)
    {
        printf("turn led on or off? ON(1),OFF(0)\n");
        scanf("%c",&led_state);
        rGPFDAT|=(led_state<<7);
        printf("exit?yes(0),no(1)");
        scanf("%d",&ex);
    }
    return 0;
}
but mprotect returns -1 so it doesnt succed,any ideas?

nemka
Juergen Beisert can you be more clear please?

Juergen Beisert
You can't access the hardware in the way you try it. The operating system
prevents you from doing so. You need to be root and to re-map the IO
address space into the virtual address space of your process to get access
to it. You should read first some basic concepts, how current operating
systems are working and how they do their memory management and protection.

nemka
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
        int fd;
        char* mem_ptr;
        fd=open("/dev/leds",O_RDWR);
        if(fd==-1)//open returns -1 if fails,else open returns handle of
open file
        {
            printf("cant open the file\n ");
            return 0;
        }
        mem_ptr=mmap(0,10,PROT_READ|PROT_WRITE,MAP_FILE |
MAP_SHARED,fd,10);
        printf("mem_ptr points to 0x%lX.\n",(unsigned long) mem_ptr);
        close(fd);
        return 0;
}

ive read that i should first make the os let me use the addresses i want
to,can you tell me why i get:
mem_ptr points to 0xFFFFFFFF.
this makes no sense to me since i know that:
#define rGPFCON (*(volatile unsigned *)0x56000050)  //Port F control
#define rGPFDAT (*(volatile unsigned *)0x56000054)  //Port F data 
shouldnt it be like:
mem_ptr points to 0x56000050 ?
is /dev/leds the right file?
------------------------------------------------
1.how can i make sure im the root on the mini2440 console?
it doesnt have sudo su command like in ubuntu.
2.would i be right saying the adresses i need to remap are:
0x56000050 to 0x56000060 (if including pull up)?

Juergen Beisert
> can you tell me why i get: mem_ptr points to 0xFFFFFFFF

$ man mmap

> 1.how can i make sure im the root on the mini2440 console?

You should google how Linux manages users.

> 2.would i be right saying the adresses i need to remap are 0x56000050 to
0x56000060

You should try with '/dev/mem' and this address-space instead.
On the other hand: why do you want to access the hardware in this way? It's
the job of kernel drivers, not a userland program.

nemka
directly accessing addresses seems most natural to me.
im trying it this way cuz i want to know how to do it this way,ill probably
learn the way you would do it afterwards,im just a beginner and im also an
electronics engineer my knowledge of programing,os and so on isnt from
college and its as you can see really poor atm im trying,but its hard for
me to know what is related and what isnt.
could you by any chance give me an example of how to do what i want so i
can see it working and then find the right read about it,knowing what im
looking for,you may say this way i wont learn it but i think i would and
spend the gained time on learning something new.

Juergen Beisert
1. rule: never use the physical address anymore
2. rule: always map the physical address to the virtual first
3. rule: do all accesses only via the virtual address
4. rule: better let the operating handle the details
5. rule: do not do hardware access from userland

And here an example how to do hardware access from userland. Never do it in
this way in real life ;)

#include <sys/mman.h>
#define PHYSICAL_ADDRESS 0x56000000
#define PHYSICAL_ADDRESS_SIZE 0x00001000
volatile uint32_t *reg;
int fd;

 fd = open("/dev/mem", O_RDWR);
 reg = mmap(NULL, PHYSICAL_ADDRESS_SIZE, PROT_WRITE | PROT_READ,
       MAP_SHARED, fd, PHYSICAL_ADDRESS);
 printf("Content of 0x56000060 is %x\n", *(reg + 0x18));
 /* change the 0x56000050 register content */
 *(reg + 0x14) = 0xaa551122;
 munmap(reg, PHYSICAL_ADDRESS_SIZE);

MSH
Hi everybody.
Like nemka, I need to access physical memory. I connect a IC to the
external bus interface and want to monitor and access its registers.
All the way you say end with segmentation fault!

nemka
Juergen Beisert thank you.
i had my finals so i wasnt able to do anything else including this.
it works great id be happy to know what is the right way to do this.
MSH if you could give more details about your issue id help you.

Samyukta Ramnath
Hello,
I realized that running code to modify registers and compiling it from
within linux creates problems, so I used an IDE (CodeBlocks) and built it.
It is pretty similar to nemka's code, and I included all the required
libraries and source files describing the various registers.
But on compiling it, it is again giving a segmentation fault while running
on the mini2440.  I had thought that working with an IDE would remove the
memory protection problems.
I don't know exactly how to go about mapping physical addresses : do you
run a code which does this for you?
Could someone give me some idea of what to do further?

Juergen
> I had thought that working with an IDE would remove the
> memory protection problems.

Funny. What let you think so? Memory protection is an OS security feature.