mirror of
git://projects.qi-hardware.com/wernermisc.git
synced 2024-12-21 17:37:21 +02:00
spiio/: simple SPI I/O example
This commit is contained in:
parent
1ad7db70f1
commit
05bbe9103b
12
spiio/Makefile
Normal file
12
spiio/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
CC=mipsel-openwrt-linux-uclibc-gcc
|
||||
|
||||
CFLAGS=-Wall -g
|
||||
|
||||
.PHONY: all clean spotless
|
||||
|
||||
all: spiio
|
||||
|
||||
clean:
|
||||
rm -f spiio
|
||||
|
||||
spotless: clean
|
179
spiio/spiio.c
Normal file
179
spiio/spiio.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* spiio.c - Very simple SPI I/O example
|
||||
*
|
||||
* Written 2011 by Werner Almesberger
|
||||
* Copyright 2011 Werner Almesberger
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
enum {
|
||||
VDD_OFF = 1 << 2, /* VDD disable, PD02 */
|
||||
MMC_CMD = 1 << 8, /* CMD, PD08 */
|
||||
MMC_CLK = 1 << 9, /* CLK, PD09 */
|
||||
MMC_DAT0 = 1 << 10, /* DAT0, PD10 */
|
||||
MMC_DAT1 = 1 << 11, /* DAT1, PD11 */
|
||||
MMC_DAT2 = 1 << 12, /* DAT2, PD12 */
|
||||
MMC_DAT3 = 1 << 13, /* DAT3/CD, PD13 */
|
||||
};
|
||||
|
||||
#define MOSI MMC_CMD
|
||||
#define MISO MMC_DAT0
|
||||
#define SCLK MMC_DAT2
|
||||
#define nSEL MMC_DAT3
|
||||
|
||||
|
||||
#define SOC_BASE 0x10000000
|
||||
|
||||
#define REG(n) (*(volatile uint32_t *) (mem+(n)))
|
||||
|
||||
#define GPIO(n) REG(0x10000+(n))
|
||||
|
||||
#define PDPIN GPIO(0x300) /* port D pin level */
|
||||
#define PDDATS GPIO(0x314) /* port D data set */
|
||||
#define PDDATC GPIO(0x318) /* port D data clear */
|
||||
#define PDFUNS GPIO(0x344) /* port D function set */
|
||||
#define PDFUNC GPIO(0x348) /* port D function clear */
|
||||
#define PDDIRS GPIO(0x364) /* port D direction set */
|
||||
#define PDDIRC GPIO(0x368) /* port D direction clear */
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
|
||||
static void *mem;
|
||||
|
||||
|
||||
/* ----- Low-level SPI operations ------------------------------------------ */
|
||||
|
||||
|
||||
static void spi_begin(void)
|
||||
{
|
||||
PDDATC = nSEL;
|
||||
}
|
||||
|
||||
|
||||
static void spi_end(void)
|
||||
{
|
||||
PDDATS = nSEL;
|
||||
}
|
||||
|
||||
|
||||
static void spi_send(uint8_t v)
|
||||
{
|
||||
uint8_t mask;
|
||||
|
||||
for (mask = 0x80; mask; mask >>= 1) {
|
||||
if (v & mask)
|
||||
PDDATS = MOSI;
|
||||
else
|
||||
PDDATC = MOSI;
|
||||
PDDATS = SCLK;
|
||||
PDDATC = SCLK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t spi_recv(void)
|
||||
{
|
||||
uint8_t res = 0;
|
||||
uint8_t mask;
|
||||
|
||||
for (mask = 0x80; mask; mask >>= 1) {
|
||||
if (PDPIN & MISO)
|
||||
res |= mask;
|
||||
PDDATS = SCLK;
|
||||
PDDATC = SCLK;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t spi_bidir(uint8_t v)
|
||||
{
|
||||
uint8_t res = 0;
|
||||
uint8_t mask;
|
||||
|
||||
for (mask = 0x80; mask; mask >>= 1) {
|
||||
if (PDPIN & MISO)
|
||||
res |= mask;
|
||||
if (v & mask)
|
||||
PDDATS = MOSI;
|
||||
else
|
||||
PDDATC = MOSI;
|
||||
PDDATS = SCLK;
|
||||
PDDATC = SCLK;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* ---- High-level -------------------------------------------------------- */
|
||||
|
||||
|
||||
static void spi_io(const char *s)
|
||||
{
|
||||
const char *p;
|
||||
uint8_t ch;
|
||||
|
||||
spi_begin();
|
||||
for (p = s; *p; p++) {
|
||||
ch = spi_bidir(*s);
|
||||
if (!ch)
|
||||
continue;
|
||||
if (strchr("\t\n\r", ch) || (ch >= ' ' && ch <= '~'))
|
||||
putchar(ch);
|
||||
else
|
||||
putchar('?');
|
||||
}
|
||||
spi_end();
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
fd = open("/dev/mem", O_RDWR | O_SYNC);
|
||||
if (fd < 0) {
|
||||
perror("/dev/mem");
|
||||
exit(1);
|
||||
}
|
||||
mem = mmap(NULL, PAGE_SIZE*3*16, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, SOC_BASE);
|
||||
if (mem == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* set the output levels */
|
||||
PDDATS = nSEL | VDD_OFF;
|
||||
PDDATC = SCLK;
|
||||
|
||||
PDFUNC = MOSI | MISO | SCLK | nSEL;
|
||||
|
||||
/* set the pin directions */
|
||||
PDDIRC = MISO;
|
||||
PDDIRS = MOSI | SCLK | nSEL;
|
||||
|
||||
for (i = 1; i != argc; i++)
|
||||
spi_io(argv[i]);
|
||||
|
||||
/* make all MMC pins inputs */
|
||||
PDDIRC = MOSI | MISO | SCLK | nSEL;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user