In our previous C code we were reading and writing to physical address directly to 0x10000000. This is because ADS project has MMU programmed in flat segments where virtual address is directly mapping to corresponding physical address. That is why we did not encounter any MMU fault.

Now we cannot do this same if we are running in Linux or Windows. OS runs in protected paging mode of MMU where each process has translation tables named as page directory and child page tables. So physical address is never mapped to virtual unless we do it explicitly. Usermode program can map unmapped physical address my /dev/mem device file. This device gives mmap() operations to map physical pages to user address space. mmap() takes physical offset , size and read/write protection flags and uses remap_pfn_range() kernel call to map pages in the page table in device driver .

Once mapping is done with mmap() this user mode program will look same as ADS project code. Only difference is interrupt from EINT3 will be suppressed/masked as prom user mode there is no way to handle it.

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <errno.h> 
#include <signal.h> 
#include <fcntl.h> 
#include <ctype.h> 
#include <termios.h> 
#include <sys/types.h> 
#include <sys/mman.h> 

#define LEDBASE 0x10000000
#define MAP_SIZE 4096UL 

int main(int argc, char **argv) { 
   int fd; 
   void *map_base;
   unsigned char *led_val;
   off_t offset; 
    offset = LEDBASE; 

    if ((fd = open ("/dev/mem", O_RDWR | O_SYNC)) == -1) {
    printf ("/dev/mem not opened.\n");
    return -1;

    map_base = mmap (0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); 
    if (map_base == (void *) -1) {
    printf ("/dev/mem mapping failed.\n");
  led_val = map_base;
    printf ("LED is %s \n", (*led_val & 1) ? "On""off");
    fflush (stdout); 
    printf ("Changing LED Status\n");
    fflush (stdout); 
    *led_val ^= 1;

  if (munmap(map_base, MAP_SIZE) == -1) {
    printf("unmap failed\n");
  close (fd); 
  return 0;