* the GNU General Public License.
*
* Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
- * Copyright 2000 Bernardo Innocenti <bernie@codewiz.org>
+ * Copyright 2000 Bernie Innocenti <bernie@codewiz.org>
*
* -->
*
* \brief ARM UART and SPI I/O driver
*
*
- * \version $Id: ser_at91.c 20881 2008-03-04 14:07:02Z batt $
+ * \version $Id$
* \author Daniele Basile <asterix@develer.com>
*/
+#include "hw/hw_ser.h" /* Required for bus macros overrides */
+#include <hw/hw_cpufreq.h> /* CPU_FREQ */
+
+#include "cfg/cfg_ser.h"
+#include <cfg/debug.h>
+
+
#include <io/arm.h>
#include <cpu/attr.h>
+
#include <drv/ser.h>
#include <drv/ser_p.h>
-#include <hw/hw_ser.h> /* Required for bus macros overrides */
-#include <hw/hw_cpu.h> /* CLOCK_FREQ */
+#include <struct/fifobuf.h>
-#include <mware/fifobuf.h>
-#include <cfg/debug.h>
-
-#include <appconfig.h>
#define SERIRQ_PRIORITY 4 ///< default priority for serial irqs.
*
* - Disable GPIO on USART0 tx/rx pins
*/
- #if !CPU_ARM_AT91SAM7S256 && !CPU_ARM_AT91SAM7X256 && !CPU_ARM_AT91SAM7X128
+ #if !CPU_ARM_SAM7S_LARGE && !CPU_ARM_SAM7X
#warning Check USART0 pins!
#endif
#define SER_UART0_BUS_TXINIT do { \
*
* - Disable GPIO on USART1 tx/rx pins
*/
- #if !CPU_ARM_AT91SAM7S256 && !CPU_ARM_AT91SAM7X256 && !CPU_ARM_AT91SAM7X128
+ #if !CPU_ARM_SAM7S_LARGE && !CPU_ARM_SAM7X
#warning Check USART1 pins!
#endif
#define SER_UART1_BUS_TXINIT do { \
#define SER_SPI0_BUS_TXCLOSE
#endif
-#if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
+#if CPU_ARM_SAM7X
#ifndef SER_SPI1_BUS_TXINIT
/**
/*\}*/
-/**
- * \def CONFIG_SER_STROBE
- *
- * This is a debug facility that can be used to
- * monitor SER interrupt activity on an external pin.
- *
- * To use strobes, redefine the macros SER_STROBE_ON,
- * SER_STROBE_OFF and SER_STROBE_INIT and set
- * CONFIG_SER_STROBE to 1.
- */
-#if !defined(CONFIG_SER_STROBE) || !CONFIG_SER_STROBE
- #define SER_STROBE_ON do {/*nop*/} while(0)
- #define SER_STROBE_OFF do {/*nop*/} while(0)
- #define SER_STROBE_INIT do {/*nop*/} while(0)
-#endif
/* From the high-level serial driver */
-extern struct Serial ser_handles[SER_CNT];
+extern struct Serial *ser_handles[SER_CNT];
/* TX and RX buffers */
static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE];
static unsigned char spi0_txbuffer[CONFIG_SPI0_TXBUFSIZE];
static unsigned char spi0_rxbuffer[CONFIG_SPI0_RXBUFSIZE];
-#if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
+#if CPU_ARM_SAM7X
static unsigned char spi1_txbuffer[CONFIG_SPI1_TXBUFSIZE];
static unsigned char spi1_rxbuffer[CONFIG_SPI1_RXBUFSIZE];
#endif
volatile bool sending;
};
-
-/*
- * These are to trick GCC into *not* using absolute addressing mode
- * when accessing ser_handles, which is very expensive.
- *
- * Accessing through these pointers generates much shorter
- * (and hopefully faster) code.
- */
-struct Serial *ser_uart0 = &ser_handles[SER_UART0];
-struct Serial *ser_uart1 = &ser_handles[SER_UART1];
-
-struct Serial *ser_spi0 = &ser_handles[SER_SPI0];
-#if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
-struct Serial *ser_spi1 = &ser_handles[SER_SPI1];
-#endif
-
static void uart0_irq_dispatcher(void);
static void uart1_irq_dispatcher(void);
static void spi0_irq_handler(void);
-#if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
+#if CPU_ARM_SAM7X
static void spi1_irq_handler(void);
#endif
/*
static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
/* Compute baud-rate period */
- US0_BRGR = CLOCK_FREQ / (16 * rate);
+ US0_BRGR = CPU_FREQ / (16 * rate);
//DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
}
static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
/* Compute baud-rate period */
- US1_BRGR = CLOCK_FREQ / (16 * rate);
+ US1_BRGR = CPU_FREQ / (16 * rate);
//DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
}
{
struct ArmSerial *hw = (struct ArmSerial *)_hw;
- cpuflags_t flags;
+ cpu_flags_t flags;
IRQ_SAVE_DISABLE(flags);
/* Send data only if the SPI is not already transmitting */
- if (!hw->sending && !fifo_isempty(&ser_spi0->txfifo))
+ if (!hw->sending && !fifo_isempty(&ser_handles[SER_SPI0]->txfifo))
{
hw->sending = true;
- SPI0_TDR = fifo_pop(&ser_spi0->txfifo);
+ SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
}
IRQ_RESTORE(flags);
{
SPI0_CSR0 &= ~SPI_SCBR;
- ASSERT((uint8_t)DIV_ROUND(CLOCK_FREQ, rate));
- SPI0_CSR0 |= DIV_ROUND(CLOCK_FREQ, rate) << SPI_SCBR_SHIFT;
+ ASSERT((uint8_t)DIV_ROUND(CPU_FREQ, rate));
+ SPI0_CSR0 |= DIV_ROUND(CPU_FREQ, rate) << SPI_SCBR_SHIFT;
}
-#if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
+#if CPU_ARM_SAM7X
/* SPI driver */
static void spi1_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
{
{
struct ArmSerial *hw = (struct ArmSerial *)_hw;
- cpuflags_t flags;
+ cpu_flags_t flags;
IRQ_SAVE_DISABLE(flags);
/* Send data only if the SPI is not already transmitting */
- if (!hw->sending && !fifo_isempty(&ser_spi1->txfifo))
+ if (!hw->sending && !fifo_isempty(&ser_handles[SER_SPI1]->txfifo))
{
hw->sending = true;
- SPI1_TDR = fifo_pop(&ser_spi1->txfifo);
+ SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
}
IRQ_RESTORE(flags);
{
SPI1_CSR0 &= ~SPI_SCBR;
- ASSERT((uint8_t)DIV_ROUND(CLOCK_FREQ, rate));
- SPI1_CSR0 |= DIV_ROUND(CLOCK_FREQ, rate) << SPI_SCBR_SHIFT;
+ ASSERT((uint8_t)DIV_ROUND(CPU_FREQ, rate));
+ SPI1_CSR0 |= DIV_ROUND(CPU_FREQ, rate) << SPI_SCBR_SHIFT;
}
#endif
C99INIT(txStart, spi0_starttx),
C99INIT(txSending, tx_sending),
};
-#if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
+#if CPU_ARM_SAM7X
static const struct SerialHardwareVT SPI1_VT =
{
C99INIT(init, spi1_init),
},
C99INIT(sending, false),
},
- #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
+ #if CPU_ARM_SAM7X
{
C99INIT(hw, /**/) {
C99INIT(table, &SPI1_VT),
{
SER_STROBE_ON;
- struct FIFOBuffer * const txfifo = &ser_uart0->txfifo;
+ struct FIFOBuffer * const txfifo = &ser_handles[SER_UART0]->txfifo;
if (fifo_isempty(txfifo))
{
SER_STROBE_ON;
/* Should be read before US_CRS */
- ser_uart0->status |= US0_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
+ ser_handles[SER_UART0]->status |= US0_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
+ US0_CR = BV(US_RSTSTA);
char c = US0_RHR;
- struct FIFOBuffer * const rxfifo = &ser_uart0->rxfifo;
+ struct FIFOBuffer * const rxfifo = &ser_handles[SER_UART0]->rxfifo;
if (fifo_isfull(rxfifo))
- ser_uart0->status |= SERRF_RXFIFOOVERRUN;
+ ser_handles[SER_UART0]->status |= SERRF_RXFIFOOVERRUN;
else
fifo_push(rxfifo, c);
{
SER_STROBE_ON;
- struct FIFOBuffer * const txfifo = &ser_uart1->txfifo;
+ struct FIFOBuffer * const txfifo = &ser_handles[SER_UART1]->txfifo;
if (fifo_isempty(txfifo))
{
SER_STROBE_ON;
/* Should be read before US_CRS */
- ser_uart1->status |= US1_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
+ ser_handles[SER_UART1]->status |= US1_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
+ US1_CR = BV(US_RSTSTA);
char c = US1_RHR;
- struct FIFOBuffer * const rxfifo = &ser_uart1->rxfifo;
+ struct FIFOBuffer * const rxfifo = &ser_handles[SER_UART1]->rxfifo;
if (fifo_isfull(rxfifo))
- ser_uart1->status |= SERRF_RXFIFOOVERRUN;
+ ser_handles[SER_UART1]->status |= SERRF_RXFIFOOVERRUN;
else
fifo_push(rxfifo, c);
char c = SPI0_RDR;
/* Read incoming byte. */
- if (!fifo_isfull(&ser_spi0->rxfifo))
- fifo_push(&ser_spi0->rxfifo, c);
+ if (!fifo_isfull(&ser_handles[SER_SPI0]->rxfifo))
+ fifo_push(&ser_handles[SER_SPI0]->rxfifo, c);
/*
* FIXME
else
- ser_spi0->status |= SERRF_RXFIFOOVERRUN;
+ ser_handles[SER_SPI0]->status |= SERRF_RXFIFOOVERRUN;
*/
/* Send */
- if (!fifo_isempty(&ser_spi0->txfifo))
- SPI0_TDR = fifo_pop(&ser_spi0->txfifo);
+ if (!fifo_isempty(&ser_handles[SER_SPI0]->txfifo))
+ SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
else
UARTDescs[SER_SPI0].sending = false;
}
-#if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
+#if CPU_ARM_SAM7X
/**
* SPI1 interrupt handler
*/
char c = SPI1_RDR;
/* Read incoming byte. */
- if (!fifo_isfull(&ser_spi1->rxfifo))
- fifo_push(&ser_spi1->rxfifo, c);
+ if (!fifo_isfull(&ser_handles[SER_SPI1]->rxfifo))
+ fifo_push(&ser_handles[SER_SPI1]->rxfifo, c);
/*
* FIXME
else
- ser_spi1->status |= SERRF_RXFIFOOVERRUN;
+ ser_handles[SER_SPI1]->status |= SERRF_RXFIFOOVERRUN;
*/
/* Send */
- if (!fifo_isempty(&ser_spi1->txfifo))
- SPI1_TDR = fifo_pop(&ser_spi1->txfifo);
+ if (!fifo_isempty(&ser_handles[SER_SPI1]->txfifo))
+ SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
else
UARTDescs[SER_SPI1].sending = false;