altos: Split out SPI driver.
authorKeith Packard <keithp@keithp.com>
Thu, 23 Dec 2010 05:06:22 +0000 (21:06 -0800)
committerKeith Packard <keithp@keithp.com>
Thu, 23 Dec 2010 05:17:36 +0000 (21:17 -0800)
For TM with the companion connector, the SPI bus will be shared among
multiple devices. Split out the existing SPI code into a common
driver, with the SPI bus protected by a mutex.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/Makefile.proto
src/ao.h
src/ao_ee.c
src/ao_flash.c
src/ao_pins.h
src/ao_spi.c [new file with mode: 0644]
src/ao_telemetrum.c
src/telemetrum-v0.1-sirf/Makefile.defs
src/telemetrum-v0.1-sky/Makefile.defs
src/telemetrum-v1.0/Makefile.defs

index b23eb2571255cdfea257e88c386393b0869a4ab7..c79638acfbd30c62a6047739677979369a9d58b7 100644 (file)
@@ -71,6 +71,12 @@ TELE_DRIVER_SRC = \
        ao_convert.c \
        ao_serial.c
 
+#
+# Spi bus driver
+#
+SPI_DRIVER_SRC = \
+       ao_spi.c
+
 #
 # Debug dongle driver (only on TI)
 #
index 9682e42fb33c9cde8d69122f632acd0f969ecb81..69f4665bca14d84dfcf8acb5863322fe02586512 100644 (file)
--- a/src/ao.h
+++ b/src/ao.h
@@ -736,6 +736,19 @@ void
 ao_serial_init(void);
 #endif
 
+/*
+ * ao_spi.c
+ */
+
+void
+ao_spi_send(void __xdata *block, uint16_t len) __reentrant;
+
+void
+ao_spi_recv(void __xdata *block, uint16_t len) __reentrant;
+
+void
+ao_spi_init(void);
+
 /*
  * ao_gps.c
  */
index 26cfb7fd4cb6a13451a20a529473d0213160c61b..36c8a1000c2c582c5dbd2963100723566e2bafe3 100644 (file)
 #define EE_CS          P1_2
 #define EE_CS_INDEX    2
 
-__xdata uint8_t ao_ee_dma_in_done;
-__xdata uint8_t ao_ee_dma_out_done;
 __xdata uint8_t ao_ee_mutex;
 
-uint8_t        ao_ee_dma_out_id;
-uint8_t ao_ee_dma_in_id;
-
-static __xdata uint8_t ao_ee_const = 0xff;
-
 #define ao_ee_delay() do { \
        _asm nop _endasm; \
        _asm nop _endasm; \
@@ -54,82 +47,6 @@ void ao_ee_cs_high(void)
        ao_ee_delay();
 }
 
-/* Send bytes over SPI.
- *
- * This sets up two DMA engines, one writing the data and another reading
- * bytes coming back.  We use the bytes coming back to tell when the transfer
- * is complete, as the transmit register is double buffered and hence signals
- * completion one byte before the transfer is actually complete
- */
-static void
-ao_ee_send(void __xdata *block, uint16_t len)
-{
-       ao_dma_set_transfer(ao_ee_dma_in_id,
-                           &U0DBUFXADDR,
-                           &ao_ee_const,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_URX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_set_transfer(ao_ee_dma_out_id,
-                           block,
-                           &U0DBUFXADDR,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_UTX0,
-                           DMA_CFG1_SRCINC_1 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_start(ao_ee_dma_in_id);
-       ao_dma_start(ao_ee_dma_out_id);
-       ao_dma_trigger(ao_ee_dma_out_id);
-       __critical while (!ao_ee_dma_in_done)
-               ao_sleep(&ao_ee_dma_in_done);
-}
-
-/* Receive bytes over SPI.
- *
- * This sets up tow DMA engines, one reading the data and another
- * writing constant values to the SPI transmitter as that is what
- * clocks the data coming in.
- */
-static void
-ao_ee_recv(void __xdata *block, uint16_t len)
-{
-       ao_dma_set_transfer(ao_ee_dma_in_id,
-                           &U0DBUFXADDR,
-                           block,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_URX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_1 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_set_transfer(ao_ee_dma_out_id,
-                           &ao_ee_const,
-                           &U0DBUFXADDR,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_UTX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_start(ao_ee_dma_in_id);
-       ao_dma_start(ao_ee_dma_out_id);
-       ao_dma_trigger(ao_ee_dma_out_id);
-       __critical while (!ao_ee_dma_in_done)
-               ao_sleep(&ao_ee_dma_in_done);
-}
 
 #define EE_BLOCK       256
 
@@ -143,7 +60,7 @@ ao_ee_write_enable(void)
 {
        ao_ee_cs_low();
        ao_ee_instruction.instruction = EE_WREN;
-       ao_ee_send(&ao_ee_instruction, 1);
+       ao_spi_send(&ao_ee_instruction, 1);
        ao_ee_cs_high();
 }
 
@@ -152,8 +69,8 @@ ao_ee_rdsr(void)
 {
        ao_ee_cs_low();
        ao_ee_instruction.instruction = EE_RDSR;
-       ao_ee_send(&ao_ee_instruction, 1);
-       ao_ee_recv(&ao_ee_instruction, 1);
+       ao_spi_send(&ao_ee_instruction, 1);
+       ao_spi_recv(&ao_ee_instruction, 1);
        ao_ee_cs_high();
        return ao_ee_instruction.instruction;
 }
@@ -164,7 +81,7 @@ ao_ee_wrsr(uint8_t status)
        ao_ee_cs_low();
        ao_ee_instruction.instruction = EE_WRSR;
        ao_ee_instruction.address[0] = status;
-       ao_ee_send(&ao_ee_instruction, 2);
+       ao_spi_send(&ao_ee_instruction, 2);
        ao_ee_cs_high();
 }
 
@@ -191,8 +108,8 @@ ao_ee_write_block(void)
        ao_ee_instruction.address[0] = ao_ee_block >> 8;
        ao_ee_instruction.address[1] = ao_ee_block;
        ao_ee_instruction.address[2] = 0;
-       ao_ee_send(&ao_ee_instruction, 4);
-       ao_ee_send(ao_ee_data, EE_BLOCK);
+       ao_spi_send(&ao_ee_instruction, 4);
+       ao_spi_send(ao_ee_data, EE_BLOCK);
        ao_ee_cs_high();
        for (;;) {
                uint8_t status = ao_ee_rdsr();
@@ -210,8 +127,8 @@ ao_ee_read_block(void)
        ao_ee_instruction.address[0] = ao_ee_block >> 8;
        ao_ee_instruction.address[1] = ao_ee_block;
        ao_ee_instruction.address[2] = 0;
-       ao_ee_send(&ao_ee_instruction, 4);
-       ao_ee_recv(ao_ee_data, EE_BLOCK);
+       ao_spi_send(&ao_ee_instruction, 4);
+       ao_spi_recv(ao_ee_data, EE_BLOCK);
        ao_ee_cs_high();
 }
 
@@ -423,39 +340,5 @@ ao_ee_init(void)
        P1DIR |= (1 << EE_CS_INDEX);
        P1SEL &= ~(1 << EE_CS_INDEX);
 
-       /* Set up the USART pin assignment */
-       PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
-
-       /* Ensure that USART0 takes precidence over USART1 for pins that
-        * they share
-        */
-       P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0;
-
-       /* Make the SPI pins be controlled by the USART peripheral */
-       P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3));
-
-       /* Set up OUT DMA */
-       ao_ee_dma_out_id = ao_dma_alloc(&ao_ee_dma_out_done);
-
-       /* Set up IN DMA */
-       ao_ee_dma_in_id = ao_dma_alloc(&ao_ee_dma_in_done);
-
-       /* Set up the USART.
-        *
-        * SPI master mode
-        */
-       U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER);
-
-       /* Set the baud rate and signal parameters
-        *
-        * 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));
        ao_cmd_register(&ao_ee_cmds[0]);
 }
index 638e51e0ce7bc932e43b8c12cd5e81a332c97117..4f3618ee1ca3214286c00f1230302a8577ca8b31 100644 (file)
 #include "ao.h"
 #include "at45db161d.h"
 
-/*
- * Using SPI on USART 0, with P1_1 as the chip select
- */
-
 #define FLASH_CS               P1_1
 #define FLASH_CS_INDEX         1
 
-__xdata uint8_t ao_flash_dma_in_done;
-__xdata uint8_t ao_flash_dma_out_done;
 __xdata uint8_t ao_flash_mutex;
 
-uint8_t        ao_flash_dma_out_id;
-uint8_t ao_flash_dma_in_id;
-
-static __xdata uint8_t ao_flash_const = 0xff;
-
 #define ao_flash_delay() do { \
        _asm nop _endasm; \
        _asm nop _endasm; \
@@ -54,83 +43,6 @@ void ao_flash_cs_high(void)
        ao_flash_delay();
 }
 
-/* Send bytes over SPI.
- *
- * This sets up two DMA engines, one writing the data and another reading
- * bytes coming back.  We use the bytes coming back to tell when the transfer
- * is complete, as the transmit register is double buffered and hence signals
- * completion one byte before the transfer is actually complete
- */
-static void
-ao_flash_send(void __xdata *block, uint16_t len)
-{
-       ao_dma_set_transfer(ao_flash_dma_in_id,
-                           &U0DBUFXADDR,
-                           &ao_flash_const,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_URX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_set_transfer(ao_flash_dma_out_id,
-                           block,
-                           &U0DBUFXADDR,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_UTX0,
-                           DMA_CFG1_SRCINC_1 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_start(ao_flash_dma_in_id);
-       ao_dma_start(ao_flash_dma_out_id);
-       ao_dma_trigger(ao_flash_dma_out_id);
-       __critical while (!ao_flash_dma_in_done)
-               ao_sleep(&ao_flash_dma_in_done);
-}
-
-/* Receive bytes over SPI.
- *
- * This sets up tow DMA engines, one reading the data and another
- * writing constant values to the SPI transmitter as that is what
- * clocks the data coming in.
- */
-static void
-ao_flash_recv(void __xdata *block, uint16_t len)
-{
-       ao_dma_set_transfer(ao_flash_dma_in_id,
-                           &U0DBUFXADDR,
-                           block,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_URX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_1 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_set_transfer(ao_flash_dma_out_id,
-                           &ao_flash_const,
-                           &U0DBUFXADDR,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_UTX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_start(ao_flash_dma_in_id);
-       ao_dma_start(ao_flash_dma_out_id);
-       ao_dma_trigger(ao_flash_dma_out_id);
-       __critical while (!ao_flash_dma_in_done)
-               ao_sleep(&ao_flash_dma_in_done);
-}
-
 struct ao_flash_instruction {
        uint8_t instruction;
        uint8_t address[3];
@@ -144,7 +56,7 @@ ao_flash_set_pagesize_512(void)
        ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0;
        ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1;
        ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2;
-       ao_flash_send(&ao_flash_instruction, 4);
+       ao_spi_send(&ao_flash_instruction, 4);
        ao_flash_cs_high();
 }
 
@@ -154,8 +66,8 @@ ao_flash_read_status(void)
 {
        ao_flash_cs_low();
        ao_flash_instruction.instruction = FLASH_READ_STATUS;
-       ao_flash_send(&ao_flash_instruction, 1);
-       ao_flash_recv(&ao_flash_instruction, 1);
+       ao_spi_send(&ao_flash_instruction, 1);
+       ao_spi_recv(&ao_flash_instruction, 1);
        ao_flash_cs_high();
        return ao_flash_instruction.instruction;
 }
@@ -268,8 +180,8 @@ ao_flash_write_block(void)
        ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
        ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
        ao_flash_instruction.address[2] = 0;
-       ao_flash_send(&ao_flash_instruction, 4);
-       ao_flash_send(ao_flash_data, FLASH_BLOCK_SIZE);
+       ao_spi_send(&ao_flash_instruction, 4);
+       ao_spi_send(ao_flash_data, FLASH_BLOCK_SIZE);
        ao_flash_cs_high();
        ao_flash_write_pending = 1;
 }
@@ -286,8 +198,8 @@ ao_flash_read_block(void)
        ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
        ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
        ao_flash_instruction.address[2] = 0;
-       ao_flash_send(&ao_flash_instruction, 4);
-       ao_flash_recv(ao_flash_data, FLASH_BLOCK_SIZE);
+       ao_spi_send(&ao_flash_instruction, 4);
+       ao_spi_recv(ao_flash_data, FLASH_BLOCK_SIZE);
        ao_flash_cs_high();
 }
 
@@ -543,40 +455,5 @@ ao_ee_init(void)
        FLASH_CS = 1;
        P1DIR |= (1 << FLASH_CS_INDEX);
        P1SEL &= ~(1 << FLASH_CS_INDEX);
-
-       /* Set up the USART pin assignment */
-       PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
-
-       /* Ensure that USART0 takes precidence over USART1 for pins that
-        * they share
-        */
-       P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0;
-
-       /* Make the SPI pins be controlled by the USART peripheral */
-       P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3));
-
-       /* Set up OUT DMA */
-       ao_flash_dma_out_id = ao_dma_alloc(&ao_flash_dma_out_done);
-
-       /* Set up IN DMA */
-       ao_flash_dma_in_id = ao_dma_alloc(&ao_flash_dma_in_done);
-
-       /* Set up the USART.
-        *
-        * SPI master mode
-        */
-       U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER);
-
-       /* Set the baud rate and signal parameters
-        *
-        * The cc1111 is limited to a 24/8 MHz SPI clock,
-        * while the at45db161d.h 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));
        ao_cmd_register(&ao_flash_cmds[0]);
 }
index e9a265b0837a4c300f54f1c8e51e94b4b6d1ee54..edbb4908aab0c619c017b9ecf3290bc0328f7152 100644 (file)
@@ -31,6 +31,8 @@
        #define AO_LED_RED              1
        #define LEDS_AVAILABLE          (AO_LED_RED)
        #define HAS_EXTERNAL_TEMP       0
+       #define SPI_CS_ON_P1            1
+       #define SPI_CS_ON_P0            0
 #endif
 
 #if defined(TELEDONGLE_V_0_2)
@@ -45,6 +47,8 @@
        #define AO_LED_RED              1
        #define AO_LED_GREEN            2
        #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define SPI_CS_ON_P1            1
+       #define SPI_CS_ON_P0            0
 #endif
 
 #if defined(TELEMETRUM_V_0_1)
@@ -60,6 +64,8 @@
        #define AO_LED_GREEN            1
        #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
        #define HAS_EXTERNAL_TEMP       1
+       #define SPI_CS_ON_P1            1
+       #define SPI_CS_ON_P0            0
 #endif
 
 #if defined(TELEDONGLE_V_0_1)
@@ -74,6 +80,8 @@
        #define AO_LED_RED              2
        #define AO_LED_GREEN            1
        #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define SPI_CS_ON_P1            0
+       #define SPI_CS_ON_P0            1
 #endif
 
 #if defined(TIDONGLE)
@@ -87,6 +95,8 @@
        #define PACKET_HAS_SLAVE        0
        #define AO_LED_RED              2
        #define LEDS_AVAILABLE          (AO_LED_RED)
+       #define SPI_CS_ON_P1            0
+       #define SPI_CS_ON_P0            1
 #endif
 
 #if DBG_ON_P1
 
 #endif /* DBG_ON_P0 */
 
+#if SPI_CS_ON_P1
+       #define SPI_CS_PORT     P1
+       #define SPI_CS_SEL      P1SEL
+       #define SPI_CS_DIR      P1DIR
+#endif
+
+#if SPI_CS_ON_P0
+       #define SPI_CS_PORT     P0
+       #define SPI_CS_SEL      P0SEL
+       #define SPI_CS_DIR      P0DIR
+#endif
+
 #ifndef HAS_SERIAL_1
 #error Please define HAS_SERIAL_1
 #endif
diff --git a/src/ao_spi.c b/src/ao_spi.c
new file mode 100644 (file)
index 0000000..bd52a0d
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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 "ao.h"
+
+__xdata uint8_t        ao_spi_mutex;
+__xdata uint8_t ao_spi_dma_in_done;
+__xdata uint8_t ao_spi_dma_out_done;
+
+uint8_t        ao_spi_dma_out_id;
+uint8_t ao_spi_dma_in_id;
+
+static __xdata uint8_t ao_spi_const = 0xff;
+
+/* Send bytes over SPI.
+ *
+ * This sets up two DMA engines, one writing the data and another reading
+ * bytes coming back.  We use the bytes coming back to tell when the transfer
+ * is complete, as the transmit register is double buffered and hence signals
+ * completion one byte before the transfer is actually complete
+ */
+void
+ao_spi_send(void __xdata *block, uint16_t len) __reentrant
+{
+       ao_mutex_get(&ao_spi_mutex);
+       ao_dma_set_transfer(ao_spi_dma_in_id,
+                           &U0DBUFXADDR,
+                           &ao_spi_const,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_URX0,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_NORMAL);
+
+       ao_dma_set_transfer(ao_spi_dma_out_id,
+                           block,
+                           &U0DBUFXADDR,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_UTX0,
+                           DMA_CFG1_SRCINC_1 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_NORMAL);
+
+       ao_dma_start(ao_spi_dma_in_id);
+       ao_dma_start(ao_spi_dma_out_id);
+       ao_dma_trigger(ao_spi_dma_out_id);
+       __critical while (!ao_spi_dma_in_done)
+               ao_sleep(&ao_spi_dma_in_done);
+       ao_mutex_put(&ao_spi_mutex);
+}
+
+/* Receive bytes over SPI.
+ *
+ * This sets up tow DMA engines, one reading the data and another
+ * writing constant values to the SPI transmitter as that is what
+ * clocks the data coming in.
+ */
+void
+ao_spi_recv(void __xdata *block, uint16_t len) __reentrant
+{
+       ao_mutex_get(&ao_spi_mutex);
+       ao_dma_set_transfer(ao_spi_dma_in_id,
+                           &U0DBUFXADDR,
+                           block,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_URX0,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_1 |
+                           DMA_CFG1_PRIORITY_NORMAL);
+
+       ao_dma_set_transfer(ao_spi_dma_out_id,
+                           &ao_spi_const,
+                           &U0DBUFXADDR,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_UTX0,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_NORMAL);
+
+       ao_dma_start(ao_spi_dma_in_id);
+       ao_dma_start(ao_spi_dma_out_id);
+       ao_dma_trigger(ao_spi_dma_out_id);
+       __critical while (!ao_spi_dma_in_done)
+               ao_sleep(&ao_spi_dma_in_done);
+       ao_mutex_put(&ao_spi_mutex);
+}
+
+/*
+ * Initialize USART0 for SPI using config alt 2
+ *
+ *     MO      P1_5
+ *     MI      P1_4
+ *     CLK     P1_3
+ *
+ * Chip select is the responsibility of the caller
+ */
+
+void
+ao_spi_init(void)
+{
+       /* Set up the USART pin assignment */
+       PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
+
+       /* Ensure that USART0 takes precidence over USART1 for pins that
+        * they share
+        */
+       P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0;
+
+       /* Make the SPI pins be controlled by the USART peripheral */
+       P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3));
+
+       /* Set up OUT DMA */
+       ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done);
+
+       /* Set up IN DMA */
+       ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done);
+
+       /* Set up the USART.
+        *
+        * SPI master mode
+        */
+       U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER);
+
+       /* Set the baud rate and signal parameters
+        *
+        * The cc1111 is limited to a 24/8 MHz SPI clock.
+        * Every peripheral I've ever seen goes faster than that,
+        * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0)
+        */
+       U0BAUD = 0;
+       U0GCR = (UxGCR_CPOL_NEGATIVE |
+                UxGCR_CPHA_FIRST_EDGE |
+                UxGCR_ORDER_MSB |
+                (17 << UxGCR_BAUD_E_SHIFT));
+}
index fd0adae8f419abd7489ea761dca584be64a32439..1209c820ff3f9f42b49312492ef73d3940f96d9a 100644 (file)
@@ -48,6 +48,7 @@ main(void)
        ao_adc_init();
        ao_beep_init();
        ao_cmd_init();
+       ao_spi_init();
        ao_ee_init();
        ao_flight_init();
        ao_log_init();
index a7310fbc8ac6d00bbddc408d4531afa73e634fa4..ac8dcdb966df218140a9b92149174c59d0ee6cb5 100644 (file)
@@ -2,6 +2,7 @@ PROG = telemetrum-v0.1-sirf-$(VERSION).ihx
 
 SRC = \
        $(TM_BASE_SRC) \
+       $(SPI_DRIVER_SRC) \
        $(EE_DRIVER_SRC) \
        $(SIRF_DRIVER_SRC) \
        $(DBG_SRC)
index 000287ba2a983ac4c4f28f32afc2f1d3ec099149..e032d1eb488ffcef8fb33504af5dea7bff1a19db 100644 (file)
@@ -2,6 +2,7 @@ PROG = telemetrum-v0.1-sky-$(VERSION).ihx
 
 SRC = \
        $(TM_BASE_SRC) \
+       $(SPI_DRIVER_SRC) \
        $(EE_DRIVER_SRC) \
        $(SKY_DRIVER_SRC) \
        $(DBG_SRC)
index 010578df6bad6ec0928d5fecd79a8658302f7cd2..a60a501aabb42532e2ef594db94cbf6480d43fee 100644 (file)
@@ -2,6 +2,7 @@ PROG = telemetrum-v1.0-$(VERSION).ihx
 
 SRC = \
        $(TM_BASE_SRC) \
+       $(SPI_DRIVER_SRC) \
        $(FLASH_DRIVER_SRC) \
        $(SKY_DRIVER_SRC) \
        $(DBG_SRC)