直接访问树莓派的SPI,不通过驱动程序

/dev/mem是物理内存的全映像,可以用来访问物理内存,一般用法是open("/dev/mem",O_RDWR|O_SYNC),然后mmap,接着就可以用mmap的地址来访问物理内存,这实际上就是实现用户空间驱动的一种方法。

pispi.h:

 1 #ifndef PI_SPI_H
 2 #define PI_SPI_H
 3 
 4 #define SPICLKDIV               32              /* ~8 Mhz */
 5 
 6 #define SPIBUFSIZE              32              /* SPI buffer size */
 7 #define BUFSIZE                 (SPIBUFSIZE/4)
 8 
 9 /* Broadcom defines */
10 
11 #define BCM2835_PERI_BASE       0x20000000
12 #define BCM2835_GPIO_BASE       (BCM2835_PERI_BASE + 0x200000) /* GPIO controller */
13 #define BCM2835_SPI_BASE        (BCM2835_PERI_BASE + 0x204000) /* SPI controller */
14 
15 #define BCM2835_GPFSEL0         *(gpio)
16 #define BCM2835_GPFSEL1         *(gpio + 1)
17 #define BCM2835_GPFSEL2         *(gpio + 2)
18 
19 #define BCM2835_SPICS           *(spi + 0)
20 #define BCM2835_SPIFIFO         *(spi + 1)
21 #define BCM2835_SPICLK          *(spi + 2)
22 
23 #define SPI_CS_LEN_LONG         0x02000000
24 #define SPI_CS_DMA_LEN          0x01000000
25 #define SPI_CS_CSPOL2           0x00800000
26 #define SPI_CS_CSPOL1           0x00400000
27 #define SPI_CS_CSPOL0           0x00200000
28 #define SPI_CS_RXF              0x00100000
29 #define SPI_CS_RXR              0x00080000
30 #define SPI_CS_TXD              0x00040000
31 #define SPI_CS_RXD              0x00020000
32 #define SPI_CS_DONE             0x00010000
33 #define SPI_CS_LEN              0x00002000
34 #define SPI_CS_REN              0x00001000
35 #define SPI_CS_ADCS             0x00000800
36 #define SPI_CS_INTR             0x00000400
37 #define SPI_CS_INTD             0x00000200
38 #define SPI_CS_DMAEN            0x00000100
39 #define SPI_CS_TA               0x00000080
40 #define SPI_CS_CSPOL            0x00000040
41 #define SPI_CS_CLEAR_RX         0x00000020
42 #define SPI_CS_CLEAR_TX         0x00000010
43 #define SPI_CS_CPOL             0x00000008
44 #define SPI_CS_CPHA             0x00000004
45 #define SPI_CS_CS_10            0x00000002
46 #define SPI_CS_CS_01            0x00000001
47 
48 #define BLOCK_SIZE              (4*1024)
49 
50 #endif
51            

pispi.c

/* Copyright (C) 2015 Zhang Wei
 * 
 * Read write Raspberry Pi SPI without SPI driver
 *
 */

#include 
#include 
#include 
#include 
#include "pispi.h"

volatile unsigned *gpio, *spi;

volatile unsigned txBuf[BUFSIZE], rxBuf[BUFSIZE+1];


static int map_gpio();
static void setup_gpio();
static void restore_gpio();
static void transfer_data();

int main(int argc, char *argv[])
{
        /* put "HELLO, WORLD\n" in txBuf */
        txBuf[0] = 0x4C4C4548; //0x48454C4C; "HELL" reversed 
        txBuf[1] = 0x57202C4F; //0x4F2C2057; "O, W" reversed
        txBuf[2] = 0x444C524F; //0x4F524C44; "ORLD" reversed
        txBuf[3] = 0x2020200A; //0x0A202020; "\n   " reversed

        map_gpio();
        setup_gpio();
        transfer_data();
        restore_gpio();
        munmap((void *)gpio, BLOCK_SIZE);
        munmap((void *)spi, BLOCK_SIZE);

        return 0;
}

int map_gpio() {
        int fd;

        fd = open("/dev/mem", O_RDWR | O_SYNC);
        if (fd < 0)
                printf("can't open /dev/mem \n");

        /* mmap GPIO */
        gpio = mmap(
                NULL,
                BLOCK_SIZE,
                PROT_READ | PROT_WRITE,
                MAP_SHARED,
                fd,
                BCM2835_GPIO_BASE);

        if (gpio == MAP_FAILED) {
                printf("can't map gpio \n");
                close(fd);
                return -1;
        }

        /* mmap SPI */
        spi = mmap(
                NULL,
                BLOCK_SIZE,
                PROT_READ | PROT_WRITE,
                MAP_SHARED,
                fd,
                BCM2835_SPI_BASE);

        close(fd);

        if (spi == MAP_FAILED) {
                printf("can't map spi\n");
                return -1;
        }

        return 0;
}

void setup_gpio()
{
        unsigned int x;

        /* change SPI pins */
        x = BCM2835_GPFSEL0;
        x &= ~(0b111 << (9*3));
        x |=   0b111 << (9*3);
        BCM2835_GPFSEL0 = x;

        x = BCM2835_GPFSEL1;
        x &= ~(0b111 << (0*3) | 0b111 << (1*3));
        x |= (0b100 << (0*3) | 0b100 << (1*3));
        BCM2835_GPFSEL1 = x;

        /* set up SPI */
        BCM2835_SPICLK = SPICLKDIV;

        BCM2835_SPICS = 0;

        /* clear FIFOs */
        BCM2835_SPICS |= SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX;

        /* clear done bit */
        BCM2835_SPICS |= SPI_CS_DONE;
}

void restore_gpio() {
        unsigned int x;

        /* change SPI pins to inputs*/
        x = BCM2835_GPFSEL0;
        x &= ~(0b111 << (9*3));
        BCM2835_GPFSEL0 = x;

        x = BCM2835_GPFSEL1;
        x &= ~(0b111 << (0*3) | 0b111 << (1*3));
        BCM2835_GPFSEL1 = x;
}

void transfer_data()
{
        char *buf;
        int i;

        /* acitvate transfer */
        BCM2835_SPICS = SPI_CS_TA;

        /* send txBuf */
        buf = (char *)txBuf;
        for (i=0; i) {
                BCM2835_SPIFIFO = *buf++;
        }

        /* wait until transfer is finished */
        while (!(BCM2835_SPICS & SPI_CS_DONE));

        /* clear done bit */
        BCM2835_SPICS = SPI_CS_DONE;

        /* read buffer */
        buf = (char *)rxBuf + 3; /* ignore 1st byte and align data */
        for (i=0; i) {
                *buf++ = BCM2835_SPIFIFO;
        }
}

 

转载于:https://www.cnblogs.com/brep/p/4270590.html

你可能感兴趣的:(直接访问树莓派的SPI,不通过驱动程序)