1
    #include <stdio.h>      // perror
    #include <sys/mman.h>   // mmap
    #include <sys/types.h>  // fd open
    #include <sys/stat.h>   // fd open
    #include <fcntl.h>      // fd open
    #include <unistd.h>     // fd close

    #define BCM2708_PERI_BASE        0x3F000000
    #define GPIO_BASE               (BCM2708_PERI_BASE + 0x200000)   // GPIO controller
    #define UART0_BASE      (BCM2708_PERI_BASE + 0x201000)

    #define BLOCK_SIZE              (4 * 1024)


    #define GPPUD           *(gpio.addr + 0x94)
    #define GPPUDCLK0       *(gpio.addr + 0x98)
    #define UART0_DR        *(uart.addr + 0x00)
    #define UART0_RSRECR    *(uart.addr + 0x04)
    #define UART0_FR        *(uart.addr + 0x18)
    #define UART0_ILPR      *(uart.addr + 0x20)
    #define UART0_IBRD      *(uart.addr + 0x24)
    #define UART0_FBRD      *(uart.addr + 0x28)
    #define UART0_LCRH      *(uart.addr + 0x2C)
    #define UART0_CR        *(uart.addr + 0x30)
    #define UART0_IFLS      *(uart.addr + 0x34)
    #define UART0_IMSC      *(uart.addr + 0x38)
    #define UART0_RIS       *(uart.addr + 0x3C)
    #define UART0_MIS       *(uart.addr + 0x40)
    #define UART0_ICR       *(uart.addr + 0x44)
    #define UART0_DMACR     *(uart.addr + 0x48)
    #define UART0_ITCR      *(uart.addr + 0x80)
    #define UART0_ITIP      *(uart.addr + 0x84)
    #define UART0_ITOP      *(uart.addr + 0x88)
    #define UART0_TDR       *(uart.addr + 0x8C)

    struct bcm2835_peripheral {
        unsigned long addr_p;
        int mem_fd;
        void *map;
        volatile unsigned int *addr;
    };

    struct bcm2835_peripheral gpio = { GPIO_BASE };
    struct bcm2835_peripheral uart = { UART0_BASE };

    // Exposes the physical address defined in the passed structure using mmap on /dev/mem
    int map_peripheral(struct bcm2835_peripheral *p)
    {
        // Open /dev/mem
        if ((p->mem_fd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
            fprintf(stderr, "Failed to open /dev/mem, try checking permissions.");
            return -1;
        }

        p->map = mmap(
                    NULL,
                    BLOCK_SIZE,
                    PROT_READ | PROT_WRITE,
                    MAP_SHARED,
                    p->mem_fd,      // File descriptor to physical memory virtual file '/dev/mem'
                    p->addr_p       // Address in physical map that we want this memory block to expose
                    );

        if (p->map == MAP_FAILED) {
            perror("mmap");
            return -1;
        }

        p->addr = (volatile unsigned int *)p->map;

        return 0;
    }

    void unmap_peripheral(struct bcm2835_peripheral *p)
    {

        munmap(p->map, BLOCK_SIZE);
        close(p->mem_fd);
    }

    static inline void delay(int32_t count)
    {
        asm volatile("__delay_%=: subs %[count], %[count], #1; bne __delay_%=\n"
                     : "=r"(count)
                     : [count] "0"(count)
                     : "cc");
    }


    void uart_init() {
        // Disable UART0.
        UART0_CR = 0x00000000;

        // Disable pull up/down for all GPIO pins & delay for 150 cycles.
        GPPUD = 0x00000000;
        delay(150);

        // Disable pull up/down for pin 14,15 & delay for 150 cycles.
        GPPUDCLK0 = (1 << 14) | (1 << 15);
        delay(150);

        // Write 0 to GPPUDCLK0 to make it take effect.
        GPPUDCLK0 =  0x00000000;

        // Clear pending interrupts.
        UART0_ICR =  0x7FF;

        // Set integer & fractional part of baud rate.
        // Divider = UART_CLOCK/(16 * Baud)
        // Fraction part register = (Fractional part * 64) + 0.5
        // UART_CLOCK = 3000000; Baud = 115200.

        // Divider = 3000000 / (16 * 115200) = 1.627 = ~1.
        UART0_IBRD = 1;

        // Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40.
        UART0_FBRD = 40;

        // Enable FIFO & 8 bit data transmissio (1 stop bit, no parity).
        UART0_LCRH = (1 << 4) | (1 << 5) | (1 << 6);

        // Mask all interrupts.
        UART0_IMSC = (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) |
                                   (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10);

        // Enable UART0, receive & transfer part of UART.
        UART0_CR = (1 << 0) | (1 << 8) | (1 << 9);
    }


    void uart_putc(unsigned char c)
    {

        // Wait for UART to become ready to transmit.
        while (UART0_FR & (1 << 5))
        {}
        UART0_DR = c;
    }

    unsigned char uart_getc()
    {
        // Wait for UART to have received something.
        while (UART0_FR & (1 << 4))
        {}
        return UART0_DR;
    }

    void uart_puts(const char *str)
    {
        for (size_t i = 0; str[i] != '\0'; i++)
            uart_putc((unsigned char)str[i]);
    }

    int main()
    {
        if(map_peripheral(&gpio) == -1) {
            fprintf(stderr, "Failed to map the physical GPIO registers into the virtual memory space.\n");
            return -1;
        }

        if(map_peripheral(&uart) == -1) {
            fprintf(stderr, "Failed to map the physical UART0 registers into the virtual memory space.\n");
            return -1;
        }

        uart_init();

        uart_puts("Hello World \r\n");

        while(1){
            delay(150);
            printf("%c" , uart_getc()); //Not waiting on uart_getc
        }
        return 0;
    }

This code works when I transmit data from RPI but it doesn't wait for response from other side. I expected it to block on uart_getc() until it receives response, instead it shows some garbage as response.

UART base addresses and baud rate calculations are referred from osdev wiki link

When I checked values at UART_0 registers all of them have value=0, even though I updated values in uart_init method.

  • Anybody who can help me here??? – zero Nov 24 '17 at 15:46
1

Register addresses were calculated incorrectly. According to pointer arithmetic in C if unsigned int * is incremented once it will point to 4 location further to its current address.

#define GPPUD           *(gpio.addr + 0x94/4)
#define GPPUDCLK0       *(gpio.addr + 0x98/4)
#define UART0_DR        *(uart.addr + 0x00/4)
#define UART0_RSRECR    *(uart.addr + 0x04/4)
#define UART0_FR        *(uart.addr + 0x18/4)
#define UART0_ILPR      *(uart.addr + 0x20/4)
#define UART0_IBRD      *(uart.addr + 0x24/4)
#define UART0_FBRD      *(uart.addr + 0x28/4)
#define UART0_LCRH      *(uart.addr + 0x2C/4)
#define UART0_CR        *(uart.addr + 0x30/4)
#define UART0_IFLS      *(uart.addr + 0x34/4)
#define UART0_IMSC      *(uart.addr + 0x38/4)
#define UART0_RIS       *(uart.addr + 0x3C/4)
#define UART0_MIS       *(uart.addr + 0x40/4)
#define UART0_ICR       *(uart.addr + 0x44/4)
#define UART0_DMACR     *(uart.addr + 0x48/4)
#define UART0_ITCR      *(uart.addr + 0x80/4)
#define UART0_ITIP      *(uart.addr + 0x84/4)
#define UART0_ITOP      *(uart.addr + 0x88/4)
#define UART0_TDR       *(uart.addr + 0x8C/4)

Also check which uart module you are using mini uart or pl11 in raspberry pi 3

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.