Date:2011-09-21 14:20:23 (7 years 11 months ago)
Author:Werner Almesberger
Commit:05bbe9103b38c87bf137fc796046f843e38e9392
Message:spiio/: simple SPI I/O example

Files: spiio/Makefile (1 diff)
spiio/spiio.c (1 diff)

Change Details

spiio/Makefile
1CC=mipsel-openwrt-linux-uclibc-gcc
2
3CFLAGS=-Wall -g
4
5.PHONY: all clean spotless
6
7all: spiio
8
9clean:
10        rm -f spiio
11
12spotless: clean
spiio/spiio.c
1/*
2 * spiio.c - Very simple SPI I/O example
3 *
4 * Written 2011 by Werner Almesberger
5 * Copyright 2011 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdint.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <string.h>
19#include <fcntl.h>
20#include <sys/mman.h>
21
22
23enum {
24    VDD_OFF = 1 << 2, /* VDD disable, PD02 */
25    MMC_CMD = 1 << 8, /* CMD, PD08 */
26    MMC_CLK = 1 << 9, /* CLK, PD09 */
27    MMC_DAT0 = 1 << 10, /* DAT0, PD10 */
28    MMC_DAT1 = 1 << 11, /* DAT1, PD11 */
29    MMC_DAT2 = 1 << 12, /* DAT2, PD12 */
30    MMC_DAT3 = 1 << 13, /* DAT3/CD, PD13 */
31};
32
33#define MOSI MMC_CMD
34#define MISO MMC_DAT0
35#define SCLK MMC_DAT2
36#define nSEL MMC_DAT3
37
38
39#define SOC_BASE 0x10000000
40
41#define REG(n) (*(volatile uint32_t *) (mem+(n)))
42
43#define GPIO(n) REG(0x10000+(n))
44
45#define PDPIN GPIO(0x300) /* port D pin level */
46#define PDDATS GPIO(0x314) /* port D data set */
47#define PDDATC GPIO(0x318) /* port D data clear */
48#define PDFUNS GPIO(0x344) /* port D function set */
49#define PDFUNC GPIO(0x348) /* port D function clear */
50#define PDDIRS GPIO(0x364) /* port D direction set */
51#define PDDIRC GPIO(0x368) /* port D direction clear */
52
53#define PAGE_SIZE 4096
54
55
56static void *mem;
57
58
59/* ----- Low-level SPI operations ------------------------------------------ */
60
61
62static void spi_begin(void)
63{
64    PDDATC = nSEL;
65}
66
67
68static void spi_end(void)
69{
70    PDDATS = nSEL;
71}
72
73
74static void spi_send(uint8_t v)
75{
76    uint8_t mask;
77
78    for (mask = 0x80; mask; mask >>= 1) {
79        if (v & mask)
80            PDDATS = MOSI;
81        else
82            PDDATC = MOSI;
83        PDDATS = SCLK;
84        PDDATC = SCLK;
85    }
86}
87
88
89static uint8_t spi_recv(void)
90{
91    uint8_t res = 0;
92        uint8_t mask;
93
94    for (mask = 0x80; mask; mask >>= 1) {
95        if (PDPIN & MISO)
96            res |= mask;
97        PDDATS = SCLK;
98        PDDATC = SCLK;
99    }
100        return res;
101}
102
103
104static uint8_t spi_bidir(uint8_t v)
105{
106    uint8_t res = 0;
107    uint8_t mask;
108
109    for (mask = 0x80; mask; mask >>= 1) {
110        if (PDPIN & MISO)
111            res |= mask;
112        if (v & mask)
113            PDDATS = MOSI;
114        else
115            PDDATC = MOSI;
116        PDDATS = SCLK;
117        PDDATC = SCLK;
118    }
119        return res;
120}
121
122
123/* ---- High-level -------------------------------------------------------- */
124
125
126static void spi_io(const char *s)
127{
128    const char *p;
129    uint8_t ch;
130
131    spi_begin();
132    for (p = s; *p; p++) {
133        ch = spi_bidir(*s);
134        if (!ch)
135            continue;
136        if (strchr("\t\n\r", ch) || (ch >= ' ' && ch <= '~'))
137            putchar(ch);
138        else
139            putchar('?');
140    }
141    spi_end();
142    putchar('\n');
143}
144
145
146int main(int argc, char **argv)
147{
148    int fd, i;
149
150    fd = open("/dev/mem", O_RDWR | O_SYNC);
151    if (fd < 0) {
152        perror("/dev/mem");
153        exit(1);
154    }
155    mem = mmap(NULL, PAGE_SIZE*3*16, PROT_READ | PROT_WRITE,
156        MAP_SHARED, fd, SOC_BASE);
157        if (mem == MAP_FAILED) {
158                perror("mmap");
159                exit(1);
160        }
161
162    /* set the output levels */
163    PDDATS = nSEL | VDD_OFF;
164    PDDATC = SCLK;
165
166    PDFUNC = MOSI | MISO | SCLK | nSEL;
167
168    /* set the pin directions */
169    PDDIRC = MISO;
170    PDDIRS = MOSI | SCLK | nSEL;
171
172    for (i = 1; i != argc; i++)
173        spi_io(argv[i]);
174
175    /* make all MMC pins inputs */
176    PDDIRC = MOSI | MISO | SCLK | nSEL;
177
178    return 0;
179}

Archive Download the corresponding diff file

Branches:
master



interactive