# HG changeset patch # User Paul Boddie # Date 1360601310 0 # Node ID 592b63226b52a188e66888fa87c476be8c5f9218 # Parent 744300c992341587ab3b1240de2cdd148b50ef11 Fixed the RESET pin state which, having been cleared, was preventing device initialisation. Removed the superfluous reset function. Added some diagnostic messages showing register contents. Added a simple interrupt handling loop. Added an SPI test program. Undefined the nanosleep and usleep functions since they are probably not needed and may actually be too slow on the NanoNote. Fixed the SS (slave select) initialisation comment. diff -r 744300c99234 -r 592b63226b52 spi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spi.c Mon Feb 11 16:48:30 2013 +0000 @@ -0,0 +1,310 @@ +/* + * Ben NanoNote and Arduino USB Host shield communication. + * + * Copyright 2013 Paul Boddie + * + * SPI functions derived from those in lib/atben.c by Werner Almesberger: + * + * Copyright 2010-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 +#include +#include +#include + +/* Pin assignments: + * + * Sniffer UBB Shield + * ------- ---- ------ + * DAT2 DAT2 9 (INT) + * CD DAT3 10 (SS) + * CMD CMD 7 (RESET) + * VCC VDD VIN + * CLK CLK 13 (SCLK) + * GND GND GND + * DAT0 DAT0 11 (MOSI) + * DAT1 DAT1 12 (MISO) + * 8 (GPX) (not assigned) + */ + +#define MAX_RESET UBB_CMD +#define MAX_SCLK UBB_CLK +#define MAX_MOSI UBB_DAT0 +#define MAX_MISO UBB_DAT1 +#define MAX_INT UBB_DAT2 +#define MAX_SS UBB_DAT3 + +/* MAX3421E definitions. */ + +#define MAX_REG_READ 0x00 +#define MAX_REG_WRITE 0x02 + +#define MAX_REG_USBIRQ 13 +#define MAX_REG_USBIEN 14 +#define MAX_REG_USBCTL 15 +#define MAX_REG_CPUCTL 16 +#define MAX_REG_PINCTL 17 +#define MAX_REG_REVISION 18 +#define MAX_REG_GPINPOL 24 +#define MAX_REG_HIRQ 25 +#define MAX_REG_HIEN 26 +#define MAX_REG_MODE 27 +#define MAX_REG_HCTL 29 +#define MAX_REG_HRSL 31 + +#define MAX_USBIRQ_OSCOKIRQ 1 +#define MAX_USBIRQ_NOVBUSIRQ 32 +#define MAX_USBIRQ_VBUSIRQ 64 + +#define MAX_USBCTL_PWRDOWN 16 +#define MAX_USBCTL_CHIPRES 32 + +#define MAX_CPUCTL_IE 1 + +#define MAX_PINCTL_POSINT_LOW 0 +#define MAX_PINCTL_POSINT_HIGH 4 +#define MAX_PINCTL_INTLEVEL_EDGE 0 +#define MAX_PINCTL_INTLEVEL_LEVEL 8 +#define MAX_PINCTL_FDUPSPI_HALF 0 +#define MAX_PINCTL_FDUPSPI_FULL 16 + +#define MAX_HIRQ_BUSEVENTIRQ 1 +#define MAX_HIRQ_RWUIRQ 2 +#define MAX_HIRQ_RCVDAVIRQ 4 +#define MAX_HIRQ_SNDBAVIRQ 8 +#define MAX_HIRQ_SUSDNIRQ 16 +#define MAX_HIRQ_CONDETIRQ 32 +#define MAX_HIRQ_FRAMEIRQ 64 +#define MAX_HIRQ_HXFRDNIRQ 128 + +#define MAX_HIEN_CONDETIE 32 + +#define MAX_MODE_PERIPHERAL 0 +#define MAX_MODE_HOST 1 +#define MAX_MODE_LOWSPEED 2 +#define MAX_MODE_SOFKAENAB 8 +#define MAX_MODE_SEPIRQ_OFF 0 +#define MAX_MODE_SEPIRQ_ON 16 +#define MAX_MODE_DMPULLDN 64 +#define MAX_MODE_DPPULLDN 128 + +#define MAX_HCTL_SAMPLEBUS 4 + +#define MAX_HRSL_JSTATUS 128 +#define MAX_HRSL_KSTATUS 64 + +#define max_reg(n) ((uint8_t) (n << 3)) +#define max_reg_read(n) (max_reg(n) | MAX_REG_READ) +#define max_reg_write(n) (max_reg(n) | MAX_REG_WRITE) + +#define nanosleep(a, b) if (0) +#define usleep(a) if (0) + +struct timespec tCSS = {0, 20}, + tL = {0, 30}, + tCSW = {0, 200}, + tCL = {0, 17}, + tCH = {0, 17}, + tDS = {0, 5}, + tDH = {0, 10}, + tDO = {0, 15}, + tDI = {0, 15}, + tON = {0, 4}, + tRESET = {0, 200}, + tTEST = {0, 100}; + +void spi_begin() +{ + CLR(MAX_SS); + nanosleep(&tL, NULL); /* tCSS is the minimum, but tL is more conservative */ +} + +void spi_end() +{ + SET(MAX_SS); + nanosleep(&tCSW, NULL); +} + +/** + * Send the given value via MOSI while receiving a value via MISO. + * This requires full-duplex SPI and will produce a status value for the first + * value sent (the command). + */ +uint8_t spi_sendrecv(uint8_t v) +{ + uint8_t result = 0; + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) + { + if (v & mask) + { + #ifdef DEBUG + printf("1"); + #endif + SET(MAX_MOSI); + } + else + { + #ifdef DEBUG + printf("0"); + #endif + CLR(MAX_MOSI); + } + + /* Wait for stable output signal. */ + + nanosleep(&tDS, NULL); + + SET(MAX_SCLK); + + if (PIN(MAX_MISO)) + result |= mask; + + nanosleep(&tCH, NULL); + CLR(MAX_SCLK); + nanosleep(&tCL, NULL); + } + + #ifdef DEBUG + printf("\n"); + #endif + return result; +} + +uint8_t max_read(uint8_t reg, uint8_t *status) +{ + uint8_t result = 0, tmpstatus = 0; + + tmpstatus = 0; + + spi_begin(); + tmpstatus = spi_sendrecv(max_reg_read(reg)); + result = spi_sendrecv(0); + spi_end(); + + if (status != NULL) + *status = tmpstatus; + + return result; +} + +uint8_t max_write(uint8_t reg, uint8_t value) +{ + uint8_t status = 0; + + spi_begin(); + status = spi_sendrecv(max_reg_write(reg)); + spi_sendrecv(value); + spi_end(); + + return status; +} + +void chipreset() +{ + printf("Resetting...\n"); + max_write(MAX_REG_USBCTL, MAX_USBCTL_CHIPRES); + + printf("Clearing the reset...\n"); + max_write(MAX_REG_USBCTL, 0); +} + +uint8_t check() +{ + uint8_t oscillator; + + oscillator = max_read(MAX_REG_USBIRQ, NULL); + + return (oscillator & ~(MAX_USBIRQ_NOVBUSIRQ | MAX_USBIRQ_VBUSIRQ)) == MAX_USBIRQ_OSCOKIRQ; +} + +uint8_t wait() +{ + uint16_t timeout = 1024; + + /* Wait for the oscillator before performing USB activity. */ + + printf("Waiting...\n"); + + while ((timeout > 0) && (!check())) + { + usleep(3000); /* 3ms */ + timeout--; + } + + printf("Iterations remaining: %d\n", timeout); + + return timeout; +} + +int main(int argc, char *argv[]) +{ + uint8_t status = 0, revision = 0, result = 0; + uint16_t count; + + if (ubb_open(0) < 0) { + perror("ubb_open"); + return 1; + } + + ubb_power(1); + printf("Power on.\n"); + + OUT(MAX_SS); + OUT(MAX_MOSI); + OUT(MAX_SCLK); + OUT(MAX_RESET); + IN(MAX_INT); + IN(MAX_MISO); + + /* Initialise SPI. */ + /* Set SS# to 1. */ + + SET(MAX_SS); + CLR(MAX_MOSI); + CLR(MAX_SCLK); + SET(MAX_RESET); + + /* Initialise the MAX3421E. */ + + /* Set full-duplex, interrupt signalling. */ + + printf("Setting pin control...\n"); + max_write(MAX_REG_PINCTL, MAX_PINCTL_INTLEVEL_LEVEL | MAX_PINCTL_FDUPSPI_FULL); + + chipreset(); + printf("Ready? %d\n", wait()); + + /* Read from the REVISION register. */ + + printf("Reading...\n"); + revision = max_read(MAX_REG_REVISION, &status); + printf("Status = %x\n", status); + printf("Revision = %x\n", revision); + + /* Check various registers. */ + + for (count = 0; count < 256; count++) + { + max_write(MAX_REG_GPINPOL, count); + result = max_read(MAX_REG_GPINPOL, NULL); + if (count != result) + { + printf("Count: %d\n", count); + printf("Retrieved: %d\n", result); + printf("Status = %x\n", status); + } + } + + printf("Closing...\n"); + ubb_close(0); + + return 0; +} diff -r 744300c99234 -r 592b63226b52 test.c --- a/test.c Sun Feb 10 20:18:28 2013 +0000 +++ b/test.c Mon Feb 11 16:48:30 2013 +0000 @@ -46,10 +46,15 @@ #define MAX_REG_WRITE 0x02 #define MAX_REG_USBIRQ 13 +#define MAX_REG_USBIEN 14 #define MAX_REG_USBCTL 15 +#define MAX_REG_CPUCTL 16 #define MAX_REG_PINCTL 17 #define MAX_REG_REVISION 18 +#define MAX_REG_HIRQ 25 +#define MAX_REG_HIEN 26 #define MAX_REG_MODE 27 +#define MAX_REG_HCTL 29 #define MAX_REG_HRSL 31 #define MAX_USBIRQ_OSCOKIRQ 1 @@ -59,6 +64,8 @@ #define MAX_USBCTL_PWRDOWN 16 #define MAX_USBCTL_CHIPRES 32 +#define MAX_CPUCTL_IE 1 + #define MAX_PINCTL_POSINT_LOW 0 #define MAX_PINCTL_POSINT_HIGH 4 #define MAX_PINCTL_INTLEVEL_EDGE 0 @@ -66,17 +73,38 @@ #define MAX_PINCTL_FDUPSPI_HALF 0 #define MAX_PINCTL_FDUPSPI_FULL 16 +#define MAX_HIRQ_BUSEVENTIRQ 1 +#define MAX_HIRQ_RWUIRQ 2 +#define MAX_HIRQ_RCVDAVIRQ 4 +#define MAX_HIRQ_SNDBAVIRQ 8 +#define MAX_HIRQ_SUSDNIRQ 16 +#define MAX_HIRQ_CONDETIRQ 32 +#define MAX_HIRQ_FRAMEIRQ 64 +#define MAX_HIRQ_HXFRDNIRQ 128 + +#define MAX_HIEN_CONDETIE 32 + #define MAX_MODE_PERIPHERAL 0 #define MAX_MODE_HOST 1 +#define MAX_MODE_LOWSPEED 2 +#define MAX_MODE_SOFKAENAB 8 #define MAX_MODE_SEPIRQ_OFF 0 #define MAX_MODE_SEPIRQ_ON 16 #define MAX_MODE_DMPULLDN 64 #define MAX_MODE_DPPULLDN 128 +#define MAX_HCTL_SAMPLEBUS 4 + +#define MAX_HRSL_JSTATUS 128 +#define MAX_HRSL_KSTATUS 64 + #define max_reg(n) ((uint8_t) (n << 3)) #define max_reg_read(n) (max_reg(n) | MAX_REG_READ) #define max_reg_write(n) (max_reg(n) | MAX_REG_WRITE) +#define nanosleep(a, b) if (0) +#define usleep(a) if (0) + struct timespec tCSS = {0, 20}, tL = {0, 30}, tCSW = {0, 200}, @@ -116,12 +144,16 @@ { if (v & mask) { + #ifdef DEBUG printf("1"); + #endif SET(MAX_MOSI); } else { + #ifdef DEBUG printf("0"); + #endif CLR(MAX_MOSI); } @@ -139,7 +171,9 @@ nanosleep(&tCL, NULL); } + #ifdef DEBUG printf("\n"); + #endif return result; } @@ -172,13 +206,6 @@ return status; } -void reset() -{ - SET(MAX_RESET); - nanosleep(&tRESET, NULL); - CLR(MAX_RESET); -} - void chipreset() { printf("Resetting...\n"); @@ -197,9 +224,38 @@ return (oscillator & ~(MAX_USBIRQ_NOVBUSIRQ | MAX_USBIRQ_VBUSIRQ)) == MAX_USBIRQ_OSCOKIRQ; } +uint8_t wait() +{ + uint16_t timeout = 1024; + + /* Wait for the oscillator before performing USB activity. */ + + printf("Waiting...\n"); + + while ((timeout > 0) && (!check())) + { + usleep(3000); /* 3ms */ + timeout--; + } + + printf("Iterations remaining: %d\n", timeout); + + return timeout; +} + +uint8_t samplebus() +{ + uint8_t result; + + result = max_read(MAX_REG_HCTL, NULL); + + return !(result & MAX_HCTL_SAMPLEBUS); +} + int main(int argc, char *argv[]) { uint8_t status = 0, revision = 0, hrsl = 0; + uint16_t count; if (ubb_open(0) < 0) { perror("ubb_open"); @@ -217,12 +273,12 @@ IN(MAX_MISO); /* Initialise SPI. */ - /* Set SS to 1 (or SS~ to 0). */ + /* Set SS# to 1. */ SET(MAX_SS); CLR(MAX_MOSI); CLR(MAX_SCLK); - CLR(MAX_RESET); + SET(MAX_RESET); /* Initialise the MAX3421E. */ @@ -231,16 +287,37 @@ printf("Setting pin control...\n"); max_write(MAX_REG_PINCTL, MAX_PINCTL_INTLEVEL_LEVEL | MAX_PINCTL_FDUPSPI_FULL); - reset(); chipreset(); - printf("Ready? %d\n", check()); + printf("Ready? %d\n", wait()); + + /* Check various registers. */ + + printf("Mode: %x\n", max_read(MAX_REG_MODE, &status)); + printf("IRQ: %x\n", max_read(MAX_REG_HIRQ, &status)); /* Set host mode. */ printf("Setting mode...\n"); status = max_write(MAX_REG_MODE, MAX_MODE_HOST | MAX_MODE_SEPIRQ_OFF | MAX_MODE_DMPULLDN | MAX_MODE_DPPULLDN); printf("Status = %x\n", status); - printf("Ready? %d\n", check()); + + printf("Setting INT signalling...\n"); + status = max_write(MAX_REG_CPUCTL, MAX_CPUCTL_IE); + printf("Status = %x\n", status); + + printf("Setting connection signalling...\n"); + status = max_write(MAX_REG_HIEN, MAX_HIEN_CONDETIE); + printf("Status = %x\n", status); + + /* Check various registers. */ + + printf("Mode: %x\n", max_read(MAX_REG_MODE, &status)); + printf("IRQ: %x\n", max_read(MAX_REG_HIRQ, &status)); + printf("IE: %x\n", max_read(MAX_REG_HIEN, &status)); + printf("CPU: %x\n", max_read(MAX_REG_CPUCTL, &status)); + printf("Pin: %x\n", max_read(MAX_REG_PINCTL, &status)); + printf("USBIRQ: %x\n", max_read(MAX_REG_USBIRQ, &status)); + printf("USBIE: %x\n", max_read(MAX_REG_USBIEN, &status)); /* Read from the REVISION register. */ @@ -248,13 +325,26 @@ revision = max_read(MAX_REG_REVISION, &status); printf("Status = %x\n", status); printf("Revision = %x\n", revision); - printf("Ready? %d\n", check()); + + for (count = 0; count < 10; count++) + { + printf("INT? %d\n", PIN(MAX_INT)); + printf("Status = %x\n", status); - printf("HRSL...\n"); - hrsl = max_read(MAX_REG_HRSL, &status); - printf("Status = %x\n", status); - printf("HRSL = %x\n", hrsl); - printf("Ready? %d\n", check()); + if (PIN(MAX_INT)) + { + if (status & (MAX_HIRQ_SUSDNIRQ | MAX_HIRQ_CONDETIRQ)) + { + printf("HRSL...\n"); + hrsl = max_read(MAX_REG_HRSL, &status); + printf("Status = %x\n", status); + printf("HRSL = %x\n", hrsl); + } + + printf("Clearing status...\n"); + max_write(MAX_REG_HIRQ, status & (MAX_HIRQ_SUSDNIRQ | MAX_HIRQ_SNDBAVIRQ | MAX_HIRQ_BUSEVENTIRQ)); + } + } printf("Closing...\n"); ubb_close(0);