Driving Beaglebone GPIO through /dev/mem

前端 未结 7 1657
温柔的废话
温柔的废话 2020-12-04 08:34

I\'m trying to write a C program for blinking a LED on the Beaglebone. I know I can use the sysfs way...but I\'d like to see if it is possible to get the same result mapping

7条回答
  •  有刺的猬
    2020-12-04 09:24

    You might also need to enable the clock for any piece of hardware you are trying to control in user-space. Fortunately, you can use dev/mem and mmap() to fiddle with the clock control register for your particular piece of hardware, like this code I wrote to enable SPI0: (define values are all from spruh73i.pdf register descriptions)

    #define CM_PER_BASE     0x44E00000  /* base address of clock control regs */
    #define CM_PER_SPI0_CLKCTRL     0x4C        /* offset of SPI0 clock control reg */
    
    #define SPIO_CLKCTRL_MODE_ENABLE 2          /* value to enable SPI0 clock */
    
    int mem;            // handle for /dev/mem
    
    int  InitSlaveSPI(void) // maps the SPI hardware into user space
    {
        char *pClockControl;    // pointer to clock controlregister block (virtualized by OS)
        unsigned int value;
    
        // Open /dev/mem:
        if ((mem = open ("/dev/mem", O_RDWR | O_SYNC)) < 0)
        {
            printf("Cannot open /dev/mem\n");
            return 1;
        }
        printf("Opened /dev/mem\n");
    
        // map a pointer to the clock control block:
        pClockControl = (char *)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, mem, CM_PER_BASE);
    
        if(pClockControl == (char *)0xFFFFFFFF) 
        {
            printf("Memory map failed. error %i\n", (uint32_t)pClockControl);
            close( mem );
            return 2;
        }
    
        value = *(uint32_t *)(pClockControl + CM_PER_SPI0_CLKCTRL);
        printf("CM_PER_SPI0_CLKCTRL was 0x%08X\n", value);
    
        *(uint32_t *)(pClockControl + CM_PER_SPI0_CLKCTRL) = SPIO_CLKCTRL_MODE_ENABLE;
    
        value = *(uint32_t *)(pClockControl + CM_PER_SPI0_CLKCTRL);
        printf("CM_PER_SPI0_CLKCTRL now 0x%08X\n", value);
    
        munmap( pClockControl, 4096 );              // free this memory map element
    

    Once I have executed this code fragment, I can access SPI0 registers using another mmap() pointer. If I don't enable the SPI0 module clock first, then I get a bus error when I try to access those SPI registers. Enabling the clock is persistent: Once enabled this way it stays on until you disable it, or maybe until you use the spidev and then close it, or reboot. So if your application is finished with the hardware you enabled, you might want to disable it to save power.

提交回复
热议问题