X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=cctools%2Ftarget%2Fee%2Fee.c;fp=cctools%2Ftarget%2Fee%2Fee.c;h=9ea22cdcc41fe74081e0a94c9ea0c10c22afe1df;hp=0000000000000000000000000000000000000000;hb=208bc15714c7b4020c017eef19011c4eb9ab51e2;hpb=17d2432a8b9c15963cd3b821f025ad33972ef477 diff --git a/cctools/target/ee/ee.c b/cctools/target/ee/ee.c new file mode 100644 index 00000000..9ea22cdc --- /dev/null +++ b/cctools/target/ee/ee.c @@ -0,0 +1,407 @@ +/* + * Copyright © 2008 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +/* + * Validate the SPI-connected EEPROM + */ + +sfr at 0x80 P0; +sfr at 0x90 P1; +sfr at 0xA0 P2; +sfr at 0xC6 CLKCON; +sfr at 0xbe SLEEP; + +# define SLEEP_USB_EN (1 << 7) +# define SLEEP_XOSC_STB (1 << 6) + +sfr at 0xF1 PERCFG; +#define PERCFG_T1CFG_ALT_1 (0 << 6) +#define PERCFG_T1CFG_ALT_2 (1 << 6) + +#define PERCFG_T3CFG_ALT_1 (0 << 5) +#define PERCFG_T3CFG_ALT_2 (1 << 5) + +#define PERCFG_T4CFG_ALT_1 (0 << 4) +#define PERCFG_T4CFG_ALT_2 (1 << 4) + +#define PERCFG_U1CFG_ALT_1 (0 << 1) +#define PERCFG_U1CFG_ALT_2 (1 << 1) + +#define PERCFG_U0CFG_ALT_1 (0 << 0) +#define PERCFG_U0CFG_ALT_2 (1 << 0) + +sfr at 0xF2 ADCCFG; +sfr at 0xF3 P0SEL; +sfr at 0xF4 P1SEL; +sfr at 0xF5 P2SEL; + +sfr at 0xFD P0DIR; +sfr at 0xFE P1DIR; +sfr at 0xFF P2DIR; +sfr at 0x8F P0INP; +sfr at 0xF6 P1INP; +sfr at 0xF7 P2INP; + +sfr at 0x89 P0IFG; +sfr at 0x8A P1IFG; +sfr at 0x8B P2IFG; + +sbit at 0x90 P1_0; +sbit at 0x91 P1_1; +sbit at 0x92 P1_2; +sbit at 0x93 P1_3; +sbit at 0x94 P1_4; +sbit at 0x95 P1_5; +sbit at 0x96 P1_6; +sbit at 0x97 P1_7; + +/* + * UART registers + */ + +sfr at 0x86 U0CSR; +sfr at 0xF8 U1CSR; + +# define UxCSR_MODE_UART (1 << 7) +# define UxCSR_MODE_SPI (0 << 7) +# define UxCSR_RE (1 << 6) +# define UxCSR_SLAVE (1 << 5) +# define UxCSR_MASTER (0 << 5) +# define UxCSR_FE (1 << 4) +# define UxCSR_ERR (1 << 3) +# define UxCSR_RX_BYTE (1 << 2) +# define UxCSR_TX_BYTE (1 << 1) +# define UxCSR_ACTIVE (1 << 0) + +sfr at 0xc4 U0UCR; +sfr at 0xfb U1UCR; + +sfr at 0xc5 U0GCR; +sfr at 0xfc U1GCR; + +# define UxGCR_CPOL_NEGATIVE (0 << 7) +# define UxGCR_CPOL_POSITIVE (1 << 7) +# define UxGCR_CPHA_FIRST_EDGE (0 << 6) +# define UxGCR_CPHA_SECOND_EDGE (1 << 6) +# define UxGCR_ORDER_LSB (0 << 5) +# define UxGCR_ORDER_MSB (1 << 5) +# define UxGCR_BAUD_E_MASK (0x1f) +# define UxGCR_BAUD_E_SHIFT 0 + +sfr at 0xc1 U0DBUF; +sfr at 0xf9 U1DBUF; +sfr at 0xc2 U0BAUD; +sfr at 0xfa U1BAUD; + +#define MOSI P1_5 +#define MISO P1_4 +#define SCK P1_3 +#define CS P1_2 + +#define DEBUG P1_1 + +#define BITBANG 0 +#define USART 1 + +#define nop() _asm nop _endasm; + +void +delay (unsigned char n) +{ + unsigned char i = 0; + unsigned char j = 0; + + while (--n != 0) + while (--i != 0) + while (--j != 0) + nop(); +} + +#if BITBANG + +/* + * This version directly manipulates the GPIOs to synthesize SPI + */ + +void +bitbang_cs(uint8_t b) +{ + SCK = 0; + CS = b; + delay(1); +} + +void +bitbang_out_bit(uint8_t b) +{ + MOSI = b; + delay(1); + SCK = 1; + delay(1); + SCK = 0; +} + +void +bitbang_out_byte(uint8_t byte) +{ + uint8_t s; + + for (s = 0; s < 8; s++) { + uint8_t b = (byte & 0x80) ? 1 : 0; + bitbang_out_bit(b); + byte <<= 1; + } +} + +uint8_t +bitbang_in_bit(void) +{ + uint8_t b; + + delay(1); + SCK = 1; + delay(1); + b = MISO; + SCK = 0; + return b; +} + +uint8_t +bitbang_in_byte(void) +{ + uint8_t byte = 0; + uint8_t s; + uint8_t b; + + for (s = 0; s < 8; s++) { + b = bitbang_in_bit(); + byte = byte << 1; + byte |= b; + } + return byte; +} + +void +bit_bang_init(void) +{ + CS = 1; + SCK = 0; + P1DIR = ((1 << 5) | + (0 << 4) | + (1 << 3) | + (1 << 2) | + (1 << 1)); +} + +#define spi_init() bitbang_init() +#define spi_out_byte(b) bitbang_out_byte(b) +#define spi_in_byte() bitbang_in_byte() +#define spi_cs(b) bitbang_cs(b) +#endif + +#if USART + +/* + * This version uses the USART in SPI mode + */ +void +usart_init(void) +{ + /* + * Configure our chip select line + */ + CS = 1; + P1DIR |= (1 << 2); + /* + * Configure the peripheral pin choices + * for both of the serial ports + * + * Note that telemetrum will use U1CFG_ALT_2 + * but that overlaps with SPI ALT_2, so until + * we can test that this works, we'll set this + * to ALT_1 + */ + PERCFG = (PERCFG_U1CFG_ALT_1 | + PERCFG_U0CFG_ALT_2); + + /* + * Make the SPI pins controlled by the SPI + * hardware + */ + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + + /* + * SPI in master mode + */ + U0CSR = (UxCSR_MODE_SPI | + UxCSR_MASTER); + + /* + * The cc1111 is limited to a 24/8 MHz SPI clock, + * while the 25LC1024 is limited to 20MHz. So, + * use the 3MHz clock (BAUD_E 17, BAUD_M 0) + */ + U0BAUD = 0; + U0GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); +} + +void +usart_cs(uint8_t b) +{ + CS = b; +} + +uint8_t +usart_in_out(uint8_t byte) +{ + U0DBUF = byte; + while ((U0CSR & UxCSR_TX_BYTE) == 0) + ; + U0CSR &= ~UxCSR_TX_BYTE; + return U0DBUF; +} + +void +usart_out_byte(uint8_t byte) +{ + (void) usart_in_out(byte); +} + +uint8_t +usart_in_byte(void) +{ + return usart_in_out(0xff); +} + +#define spi_init() usart_init() +#define spi_out_byte(b) usart_out_byte(b) +#define spi_in_byte() usart_in_byte() +#define spi_cs(b) usart_cs(b) + +#endif + +uint8_t +rdsr(void) +{ + uint8_t status; + spi_cs(0); + spi_out_byte(0x05); + status = spi_in_byte(); + spi_cs(1); + return status; +} + +void +wrsr(uint8_t status) +{ + spi_cs(0); + spi_out_byte(0x01); + spi_out_byte(status); + spi_cs(1); +} + +void +wren(void) +{ + spi_cs(0); + spi_out_byte(0x06); + spi_cs(1); +} + +void +write(uint32_t addr, uint8_t *bytes, uint16_t len) +{ + wren(); + spi_cs(0); + spi_out_byte(0x02); + spi_out_byte(addr >> 16); + spi_out_byte(addr >> 8); + spi_out_byte(addr); + while (len-- > 0) + spi_out_byte(*bytes++); + spi_cs(1); + for (;;) { + uint8_t status = rdsr(); + if ((status & (1 << 0)) == 0) + break; + } +} + +void +read(uint32_t addr, uint8_t *bytes, uint16_t len) +{ + spi_cs(0); + spi_out_byte(0x03); + spi_out_byte(addr >> 16); + spi_out_byte(addr >> 8); + spi_out_byte(addr); + while (len-- > 0) + *bytes++ = spi_in_byte(); + spi_cs(1); +} + +void +debug_byte(uint8_t byte) +{ + uint8_t s; + + for (s = 0; s < 8; s++) { + DEBUG = byte & 1; + delay(5); + byte >>= 1; + } +} + +#define STRING "\360\252" +#define LENGTH 2 + +main () +{ + uint8_t status; + uint8_t buf[LENGTH]; + int i; + + P1DIR |= 2; + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; + + spi_init(); + + status = rdsr(); + /* + * Turn off both block-protect bits + */ + status &= ~((1 << 3) | (1 << 2)); + /* + * Turn off write protect enable + */ + status &= ~(1 << 7); + wrsr(status); + write(0x0, STRING, LENGTH); + for (;;) { + read(0x0, buf, LENGTH); + for (i = 0; i < LENGTH; i++) + debug_byte(buf[i]); + } +}