lm3s1968: Synchronous Serial Interface (SSI) driver.
authorarighi <arighi@38d2e660-2303-0410-9eaa-f027e97ec537>
Wed, 7 Apr 2010 09:44:26 +0000 (09:44 +0000)
committerarighi <arighi@38d2e660-2303-0410-9eaa-f027e97ec537>
Wed, 7 Apr 2010 09:44:26 +0000 (09:44 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3399 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/cpu/cortex-m3/drv/ssi_lm3s.c [new file with mode: 0644]
bertos/cpu/cortex-m3/drv/ssi_lm3s.h [new file with mode: 0644]
bertos/cpu/cortex-m3/io/lm3s.h
bertos/cpu/cortex-m3/io/lm3s_ssi.h [new file with mode: 0644]

diff --git a/bertos/cpu/cortex-m3/drv/ssi_lm3s.c b/bertos/cpu/cortex-m3/drv/ssi_lm3s.c
new file mode 100644 (file)
index 0000000..f67f1a1
--- /dev/null
@@ -0,0 +1,197 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief LM3S1968 Synchronous Serial Interface (SSI) driver.
+ *
+ * \author Andrea Righi <arighi@develer.com>
+ */
+
+#include <cfg/compiler.h>
+#include <cfg/debug.h>
+#include "io/lm3s.h"
+#include "drv/ssi_lm3s.h"
+
+/* SSI clocking informations (CPSDVSR + SCR) */
+struct ssi_clock
+{
+       unsigned int cpsdvsr;
+       unsigned int scr;
+};
+
+/*
+ * Evaluate the SSI clock prescale (SSICPSR) and SSI serial clock rate (SCR).
+ */
+INLINE struct ssi_clock
+lm3s_ssi_prescale(unsigned int bitrate)
+{
+       struct ssi_clock ret;
+
+       for (ret.cpsdvsr = 2, ret.scr = CPU_FREQ / bitrate / ret.cpsdvsr - 1;
+                       ret.scr > 255; ret.cpsdvsr += 2);
+       ASSERT(ret.cpsdvsr < 255);
+
+       return ret;
+}
+
+/*
+ * Initialize the SSI interface.
+ *
+ * @base: the SSI port base address.
+ * @frame: the data transfer protocol (SSI_FRF_MOTO_MODE_0,
+ * SSI_FRF_MOTO_MODE_1, SSI_FRF_MOTO_MODE_2, SSI_FRF_MOTO_MODE_3, SSI_FRF_TI or
+ * SSI_FRF_NMW)
+ * @mode: the mode of operation (SSI_MODE_MASTER, SSI_MODE_SLAVE,
+ * SSI_MODE_SLAVE_OD)
+ * @bitrate: the SSI clock rate
+ * @data_width: number of bits per frame
+ *
+ * Return 0 in case of success, a negative value otherwise.
+ */
+int lm3s_ssi_init(uint32_t base, uint32_t frame, int mode,
+                   unsigned int bitrate, unsigned int data_width)
+{
+       struct ssi_clock ssi_clock;
+
+       ASSERT(base == SSI0_BASE || base == SSI1_BASE);
+       /* Configure the SSI operating mode */
+       switch (mode)
+       {
+               /* SSI Slave Mode Output Disable */
+               case SSI_MODE_SLAVE_OD:
+                       HWREG(base + SSI_O_CR1) = SSI_CR1_SOD;
+                       break;
+               /* SSI Slave */
+               case SSI_MODE_SLAVE:
+                       HWREG(base + SSI_O_CR1) = SSI_CR1_MS;
+                       break;
+               /* SSI Master */
+               case SSI_MODE_MASTER:
+                       HWREG(base + SSI_O_CR1) = 0;
+                       break;
+               default:
+                       ASSERT(0);
+                       return -1;
+       }
+       /* Configure the peripheral clock and frame format */
+       ssi_clock = lm3s_ssi_prescale(bitrate);
+       HWREG(base + SSI_O_CPSR) = ssi_clock.cpsdvsr;
+       HWREG(base + SSI_O_CR0) =
+                       (ssi_clock.scr << 8)    |
+                       ((frame & 3) << 6)      |
+                       (frame & SSI_CR0_FRF_M) |
+                       (data_width - 1);
+       return 0;
+}
+
+/* Enable the SSI interface */
+void lm3s_ssi_enable(uint32_t base)
+{
+       HWREG(base + SSI_O_CR1) |= SSI_CR1_SSE;
+}
+
+/* Disable the SSI interface */
+void lm3s_ssi_disable(uint32_t base)
+{
+       HWREG(base + SSI_O_CR1) &= ~SSI_CR1_SSE;
+}
+
+/*
+ * Put a frame into the SSI transmit FIFO.
+ *
+ * NOTE: the upper bits of the frame will be automatically discarded by the
+ * hardware according to the frame data width, configured by lm3s_ssi_init().
+ */
+void lm3s_ssi_write_frame(uint32_t base, uint32_t val)
+{
+       /* Wait for available space in the TX FIFO */
+       while (!(HWREG(base + SSI_O_SR) & SSI_SR_TNF))
+               cpu_relax();
+       /* Enqueue data to the TX FIFO */
+       HWREG(base + SSI_O_DR) = val;
+}
+
+/*
+ * Put a frame into the SSI transmit FIFO without blocking.
+ *
+ * NOTE: the upper bits of the frame will be automatically discarded by the
+ * hardware according to the frame data width, configured by lm3s_ssi_init().
+ *
+ * Return the number of frames written to the TX FIFO.
+ */
+int lm3s_ssi_write_frame_nonblocking(uint32_t base, uint32_t val)
+{
+       /* Check for available space in the TX FIFO */
+       if (!(HWREG(base + SSI_O_SR) & SSI_SR_TNF))
+               return 0;
+       /* Enqueue data to the TX FIFO */
+       HWREG(base + SSI_O_DR) = val;
+       return 1;
+}
+
+/*
+ * Get a frame from the SSI receive FIFO.
+ */
+void lm3s_ssi_read_frame(uint32_t base, uint32_t *val)
+{
+       /* Wait for data available in the RX FIFO */
+       while (!(HWREG(base + SSI_O_SR) & SSI_SR_RNE))
+               cpu_relax();
+       /* Read data from SSI RX FIFO */
+       *val = HWREG(base + SSI_O_DR);
+}
+
+/*
+ * Get a frame into the SSI receive FIFO without blocking.
+ *
+ * Return the number of frames read from the RX FIFO.
+ */
+int lm3s_ssi_read_frame_nonblocking(uint32_t base, uint32_t *val)
+{
+       /* Check for data available in the RX FIFO */
+       if (!(HWREG(base + SSI_O_SR) & SSI_SR_RNE))
+               return 0;
+       /* Read data from SSI RX FIFO */
+       *val = HWREG(base + SSI_O_DR);
+       return 1;
+}
+
+/*
+ * Check if the SSI transmitter is busy or not
+ *
+ * This allows to determine whether the TX FIFO have been cleared by the
+ * hardware, so the transmission can be safely considered completed.
+ */
+bool lm3s_ssi_txdone(uint32_t base)
+{
+       /* Check if the SSI is busy */
+       return (HWREG(base + SSI_O_SR) & SSI_SR_BSY) ? true : false;
+}
diff --git a/bertos/cpu/cortex-m3/drv/ssi_lm3s.h b/bertos/cpu/cortex-m3/drv/ssi_lm3s.h
new file mode 100644 (file)
index 0000000..69b88ac
--- /dev/null
@@ -0,0 +1,78 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief LM3S1968 Synchronous Serial Interface (SSI) driver.
+ */
+
+#ifndef SSI_LM3S_H
+#define SSI_LM3S_H
+
+#include <cpu/power.h> /* cpu_relax() */
+
+/**
+ * LM3S1968 SSI frame format
+ */
+/*\{*/
+#define SSI_FRF_MOTO_MODE_0     0x00000000  //< Moto fmt, polarity 0, phase 0
+#define SSI_FRF_MOTO_MODE_1     0x00000002  //< Moto fmt, polarity 0, phase 1
+#define SSI_FRF_MOTO_MODE_2     0x00000001  //< Moto fmt, polarity 1, phase 0
+#define SSI_FRF_MOTO_MODE_3     0x00000003  //< Moto fmt, polarity 1, phase 1
+#define SSI_FRF_TI              0x00000010  //< TI frame format
+#define SSI_FRF_NMW             0x00000020  //< National MicroWire frame format
+/*\}*/
+
+/**
+ * LM3S1968 SSI operational mode
+ */
+/*\{*/
+#define SSI_MODE_MASTER         0x00000000  //< SSI master
+#define SSI_MODE_SLAVE          0x00000001  //< SSI slave
+#define SSI_MODE_SLAVE_OD       0x00000002  //< SSI slave with output disabled
+/*\}*/
+
+int lm3s_ssi_init(uint32_t base, uint32_t frame, int mode,
+                   unsigned int bitrate, unsigned int data_width);
+void lm3s_ssi_enable(uint32_t base);
+void lm3s_ssi_disable(uint32_t base);
+void lm3s_ssi_write_frame(uint32_t base, uint32_t val);
+int lm3s_ssi_write_frame_nonblocking(uint32_t base, uint32_t val);
+void lm3s_ssi_read_frame(uint32_t base, uint32_t *val);
+int lm3s_ssi_read_frame_nonblocking(uint32_t base, uint32_t *val);
+bool lm3s_ssi_txdone(uint32_t base);
+
+INLINE void lm3s_ssi_wait_txdone(uint32_t base)
+{
+       while (!lm3s_ssi_txdone(base))
+               cpu_relax();
+}
+
+#endif /* LM3S_SSI_H */
index c920d35eaf1436d64a8dfed263e78e7d71930f37..0dd7e11058d7d8529ead64c81a3edb1cd15fb12a 100644 (file)
@@ -49,6 +49,7 @@
        #include "lm3s_gpio.h"
        #include "lm3s_memmap.h"
        #include "lm3s_uart.h"
+       #include "lm3s_ssi.h"
 #else
        #error Missing I/O definitions for CPU.
 #endif
diff --git a/bertos/cpu/cortex-m3/io/lm3s_ssi.h b/bertos/cpu/cortex-m3/io/lm3s_ssi.h
new file mode 100644 (file)
index 0000000..001da81
--- /dev/null
@@ -0,0 +1,228 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief LM3S1968 SSI hardware definitions.
+ */
+
+#ifndef LM3S_SSI_H
+#define LM3S_SSI_H
+
+/**
+ * The following are defines for the SSI register offsets.
+ */
+/*\{*/
+#define SSI_O_CR0               0x00000000  //< SSI Control 0
+#define SSI_O_CR1               0x00000004  //< SSI Control 1
+#define SSI_O_DR                0x00000008  //< SSI Data
+#define SSI_O_SR                0x0000000C  //< SSI Status
+#define SSI_O_CPSR              0x00000010  //< SSI Clock Prescale
+#define SSI_O_IM                0x00000014  //< SSI Interrupt Mask
+#define SSI_O_RIS               0x00000018  //< SSI Raw Interrupt Status
+#define SSI_O_MIS               0x0000001C  //< SSI Masked Interrupt Status
+#define SSI_O_ICR               0x00000020  //< SSI Interrupt Clear
+#define SSI_O_DMACTL            0x00000024  //< SSI DMA Control
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_CR0 register.
+ */
+/*\{*/
+#define SSI_CR0_SCR_M           0x0000FF00  //< SSI Serial Clock Rate
+#define SSI_CR0_SPH             0x00000080  //< SSI Serial Clock Phase
+#define SSI_CR0_SPO             0x00000040  //< SSI Serial Clock Polarity
+#define SSI_CR0_FRF_M           0x00000030  //< SSI Frame Format Select
+#define SSI_CR0_FRF_MOTO        0x00000000  //< Freescale SPI Frame Format
+#define SSI_CR0_FRF_TI          0x00000010  //< Texas Instruments Synchronous
+                                            //< Serial Frame Format
+#define SSI_CR0_FRF_NMW         0x00000020  //< MICROWIRE Frame Format
+#define SSI_CR0_DSS_M           0x0000000F  //< SSI Data Size Select
+#define SSI_CR0_DSS_4           0x00000003  //< 4-bit data
+#define SSI_CR0_DSS_5           0x00000004  //< 5-bit data
+#define SSI_CR0_DSS_6           0x00000005  //< 6-bit data
+#define SSI_CR0_DSS_7           0x00000006  //< 7-bit data
+#define SSI_CR0_DSS_8           0x00000007  //< 8-bit data
+#define SSI_CR0_DSS_9           0x00000008  //< 9-bit data
+#define SSI_CR0_DSS_10          0x00000009  //< 10-bit data
+#define SSI_CR0_DSS_11          0x0000000A  //< 11-bit data
+#define SSI_CR0_DSS_12          0x0000000B  //< 12-bit data
+#define SSI_CR0_DSS_13          0x0000000C  //< 13-bit data
+#define SSI_CR0_DSS_14          0x0000000D  //< 14-bit data
+#define SSI_CR0_DSS_15          0x0000000E  //< 15-bit data
+#define SSI_CR0_DSS_16          0x0000000F  //< 16-bit data
+#define SSI_CR0_SCR_S           8
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_CR1 register.
+ */
+/*\{*/
+#define SSI_CR1_EOT             0x00000010  //< End of Transmission
+#define SSI_CR1_SOD             0x00000008  //< SSI Slave Mode Output Disable
+#define SSI_CR1_MS              0x00000004  //< SSI Master/Slave Select
+#define SSI_CR1_SSE             0x00000002  //< SSI Synchronous Serial Port
+                                            //< Enable
+#define SSI_CR1_LBM             0x00000001  //< SSI Loopback Mode
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_DR register.
+ */
+/*\{*/
+#define SSI_DR_DATA_M           0x0000FFFF  //< SSI Receive/Transmit Data
+#define SSI_DR_DATA_S           0
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_SR register.
+ */
+/*\{*/
+#define SSI_SR_BSY              0x00000010  //< SSI Busy Bit
+#define SSI_SR_RFF              0x00000008  //< SSI Receive FIFO Full
+#define SSI_SR_RNE              0x00000004  //< SSI Receive FIFO Not Empty
+#define SSI_SR_TNF              0x00000002  //< SSI Transmit FIFO Not Full
+#define SSI_SR_TFE              0x00000001  //< SSI Transmit FIFO Empty
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_CPSR register.
+ */
+/*\{*/
+#define SSI_CPSR_CPSDVSR_M      0x000000FF  //< SSI Clock Prescale Divisor
+#define SSI_CPSR_CPSDVSR_S      0
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_IM register.
+ */
+/*\{*/
+#define SSI_IM_TXIM             0x00000008  //< SSI Transmit FIFO Interrupt Mask
+#define SSI_IM_RXIM             0x00000004  //< SSI Receive FIFO Interrupt Mask
+#define SSI_IM_RTIM             0x00000002  //< SSI Receive Time-Out Interrupt
+                                            //< Mask
+#define SSI_IM_RORIM            0x00000001  //< SSI Receive Overrun Interrupt
+                                            //< Mask
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_RIS register.
+ */
+/*\{*/
+#define SSI_RIS_TXRIS           0x00000008  //< SSI Transmit FIFO Raw Interrupt
+                                            //< Status
+#define SSI_RIS_RXRIS           0x00000004  //< SSI Receive FIFO Raw Interrupt
+                                            //< Status
+#define SSI_RIS_RTRIS           0x00000002  //< SSI Receive Time-Out Raw
+                                            //< Interrupt Status
+#define SSI_RIS_RORRIS          0x00000001  //< SSI Receive Overrun Raw
+                                            //< Interrupt Status
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_MIS register.
+ */
+/*\{*/
+#define SSI_MIS_TXMIS           0x00000008  //< SSI Transmit FIFO Masked
+                                            //< Interrupt Status
+#define SSI_MIS_RXMIS           0x00000004  //< SSI Receive FIFO Masked
+                                            //< Interrupt Status
+#define SSI_MIS_RTMIS           0x00000002  //< SSI Receive Time-Out Masked
+                                            //< Interrupt Status
+#define SSI_MIS_RORMIS          0x00000001  //< SSI Receive Overrun Masked
+                                            //< Interrupt Status
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_ICR register.
+ */
+/*\{*/
+#define SSI_ICR_RTIC            0x00000002  //< SSI Receive Time-Out Interrupt
+                                            //< Clear
+#define SSI_ICR_RORIC           0x00000001  //< SSI Receive Overrun Interrupt
+                                            //< Clear
+/*\}*/
+
+/**
+ * The following are defines for the bit fields in the SSI_O_DMACTL register.
+ */
+/*\{*/
+#define SSI_DMACTL_TXDMAE       0x00000002  //< Transmit DMA Enable
+#define SSI_DMACTL_RXDMAE       0x00000001  //< Receive DMA Enable
+/*\}*/
+
+/**
+ * The following definitions are deprecated.
+ */
+/*\{*/
+#ifndef DEPRECATED
+/*\}*/
+
+/**
+ * The following are deprecated defines for the bit fields in the SSI_O_CR0
+ * register.
+ */
+/*\{*/
+#define SSI_CR0_SCR             0x0000FF00  //< Serial clock rate
+#define SSI_CR0_FRF_MASK        0x00000030  //< Frame format mask
+#define SSI_CR0_DSS             0x0000000F  //< Data size select
+/*\}*/
+
+/**
+ * The following are deprecated defines for the bit fields in the SSI_O_CPSR
+ * register.
+ */
+/*\{*/
+#define SSI_CPSR_CPSDVSR_MASK   0x000000FF  //< Clock prescale
+/*\}*/
+
+/**
+ * The following are deprecated defines for the SSI controller's FIFO size.
+ */
+/*\{*/
+#define TX_FIFO_SIZE            (8)         //< Number of entries in the TX FIFO
+#define RX_FIFO_SIZE            (8)         //< Number of entries in the RX FIFO
+/*\}*/
+
+/**
+ * The following are deprecated defines for the bit fields in the interrupt
+ * mask set and clear, raw interrupt, masked interrupt, and interrupt clear
+ * registers.
+ */
+/*\{*/
+#define SSI_INT_TXFF            0x00000008  //< TX FIFO interrupt
+#define SSI_INT_RXFF            0x00000004  //< RX FIFO interrupt
+#define SSI_INT_RXTO            0x00000002  //< RX timeout interrupt
+#define SSI_INT_RXOR            0x00000001  //< RX overrun interrupt
+/*\}*/
+
+#endif /* DEPRECATED */
+
+#endif /* LM3S_SSI_H */