sam3n spi: revert to "end of transmit" interrupt instead of "tx buffer empty",
[bertos.git] / bertos / cpu / cortex-m3 / drv / ser_sam3.c
index 6222ece5e9180fc3bd912b1473f929a9932445e0..0c5f8c3988b5124767cb833a581859f2abf663c1 100644 (file)
@@ -35,6 +35,7 @@
  *
  *
  * \author Daniele Basile <asterix@develer.com>
+ * \author Stefano Fedrigo <aleph@develer.com>
  */
 
 #include "hw/hw_ser.h"  /* Required for bus macros overrides */
        #if CPU_CM3_AT91SAM3
                #define SER_SPI0_BUS_TXINIT do { \
                        /* Disable PIO on SPI pins */ \
-                       PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO) | BV(30); \
+                       PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO); \
                        /* PIO is peripheral A */ \
                        PIOA_ABCDSR1 &= ~(BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO)); \
                        PIOA_ABCDSR2 &= ~(BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO)); \
-                       /* Peripheral B for chip select for display */ \
-                       PIOA_ABCDSR1 |= BV(30); \
-                       PIOA_ABCDSR2 &= ~BV(30); \
                } while (0)
        #else
                #define SER_SPI0_BUS_TXINIT do { \
@@ -532,14 +530,19 @@ static void spi0_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struc
         * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
         * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
         */
-       SPI0_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS); // | SPI_PCS_2;
+       SPI0_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
 
        /*
         * Set SPI mode.
         * At reset clock division factor is set to 0, that is
         * *forbidden*. Set SPI clock to minimum to keep it valid.
+        * Set all possible chip select registers in case user manually
+        * change CPS field in SPI_MR.
         */
        SPI0_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI0_CSR1 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI0_CSR2 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI0_CSR3 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
 
        /* Disable all irqs */
        SPI0_IDR = 0xFFFFFFFF;
@@ -548,9 +551,6 @@ static void spi0_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struc
        sysirq_setHandler(INT_SPI0, spi0_irq_handler);
        PMC_PCER = BV(SPI0_ID);
 
-       /* Enable interrupt on tx buffer empty */
-       SPI0_IER = BV(SPI_TXEMPTY);
-
        /* Enable SPI */
        SPI0_CR = BV(SPI_SPIEN);
 
@@ -580,6 +580,8 @@ static void spi0_starttx(struct SerialHardware *_hw)
        {
                hw->sending = true;
                SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
+               /* Enable interrupt on tx buffer empty */
+               SPI0_IER = BV(SPI_TXEMPTY);
        }
 
        IRQ_RESTORE(flags);
@@ -612,8 +614,13 @@ static void spi1_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struc
         * Set SPI mode.
         * At reset clock division factor is set to 0, that is
         * *forbidden*. Set SPI clock to minimum to keep it valid.
+        * Set all possible chip select registers in case user manually
+        * change chip select.
         */
        SPI1_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI1_CSR1 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI1_CSR2 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI1_CSR3 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
 
        /* Disable all SPI irqs */
        SPI1_IDR = 0xFFFFFFFF;
@@ -622,9 +629,6 @@ static void spi1_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struc
        sysirq_setHandler(INT_SPI1, spi1_irq_dispatcher);
        PMC_PCER = BV(SPI1_ID);
 
-       /* Enable interrupt on tx buffer empty */
-       SPI1_IER = BV(SPI_TXEMPTY);
-
        /* Enable SPI */
        SPI1_CR = BV(SPI_SPIEN);
 
@@ -654,6 +658,8 @@ static void spi1_starttx(struct SerialHardware *_hw)
        {
                hw->sending = true;
                SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
+               /* Enable interrupt on tx buffer empty */
+               SPI1_IER = BV(SPI_TXEMPTY);
        }
 
        IRQ_RESTORE(flags);
@@ -935,7 +941,11 @@ static DECLARE_ISR(spi0_irq_handler)
        if (!fifo_isempty(&ser_handles[SER_SPI0]->txfifo))
                SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
        else
+       {
                UARTDescs[SER_SPI0].sending = false;
+               /* Disable interrupt on tx buffer empty */
+               SPI0_IDR = BV(SPI_TXEMPTY);
+       }
 
        SER_INT_ACK;
 
@@ -965,7 +975,11 @@ static DECLARE_ISR(spi1_irq_handler)
        if (!fifo_isempty(&ser_handles[SER_SPI1]->txfifo))
                SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
        else
+       {
                UARTDescs[SER_SPI1].sending = false;
+               /* Disable interrupt on tx buffer empty */
+               SPI1_IDR = BV(SPI_TXEMPTY);
+       }
 
        SER_INT_ACK;