aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/platforms/AT91SAM7
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-10-23 11:51:19 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-10-23 11:51:19 +0000
commit66f21d9c87a9916e6737dc3de617c5496c1ea160 (patch)
treeaae676e2a896df83aaa2841571a0cdfbeaf9e52a /os/hal/platforms/AT91SAM7
parentbb0f6c9e9a3b4d2ffcb89c7f661c94a51f192dd3 (diff)
downloadChibiOS-66f21d9c87a9916e6737dc3de617c5496c1ea160.tar.gz
ChibiOS-66f21d9c87a9916e6737dc3de617c5496c1ea160.tar.bz2
ChibiOS-66f21d9c87a9916e6737dc3de617c5496c1ea160.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2270 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/platforms/AT91SAM7')
-rw-r--r--os/hal/platforms/AT91SAM7/spi_lld.c93
1 files changed, 81 insertions, 12 deletions
diff --git a/os/hal/platforms/AT91SAM7/spi_lld.c b/os/hal/platforms/AT91SAM7/spi_lld.c
index 592bc092e..9cc7ce31d 100644
--- a/os/hal/platforms/AT91SAM7/spi_lld.c
+++ b/os/hal/platforms/AT91SAM7/spi_lld.c
@@ -48,6 +48,34 @@ SPIDriver SPID2;
/* Driver local variables. */
/*===========================================================================*/
+/**
+ * @brief Idle line value.
+ * @details This thing's DMA apparently does not allow to *not* increment
+ * the memory pointer so a buffer filled with ones is required
+ * somewhere.
+ * @note This buffer size also limits the maximum transfer size, 512B,
+ * for @p spiReceive() and @p spiIgnore(). @p spiSend() and
+ * @p spiExchange are not affected.
+ */
+static const uint16_t idle_buf[] = {
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
+};
+
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
@@ -60,6 +88,7 @@ SPIDriver SPID2;
* @param[in] txbuf the pointer to the transmit buffer or @p NULL
* @param[out] rxbuf the pointer to the receive buffer or @p NULL
*/
+#if 0
void rw8(size_t n, const uint8_t *txbuf, uint8_t *rxbuf) {
size_t ntx = n;
@@ -81,6 +110,28 @@ void rw8(size_t n, const uint8_t *txbuf, uint8_t *rxbuf) {
}
}
}
+#endif
+
+#if defined(__GNUC__)
+__attribute__((noinline))
+#endif
+/**
+ * @brief Shared interrupt handling code.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ */
+static void spi_lld_serve_interrupt(SPIDriver *spip) {
+ uint32_t sr = spip->spd_spi->SPI_SR;
+
+ if ((sr & AT91C_SPI_ENDRX) != 0) {
+ (void)spip->spd_spi->SPI_RDR; /* Clears eventual overflow.*/
+ spip->spd_spi->SPI_IDR = AT91C_SPI_ENDRX; /* Interrupt disabled. */
+ spip->spd_spi->SPI_CR = AT91C_SPI_SPIDIS; /* SPI disabled. */
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+ }
+}
/*===========================================================================*/
/* Driver interrupt handlers. */
@@ -132,6 +183,8 @@ void spi_lld_init(void) {
/* Software reset must be written twice (errata for revision B parts).*/
AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SWRST;
AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SWRST;
+ AT91C_BASE_SPI0->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS;
+ AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
AT91C_BASE_PIOA->PIO_PDR = SPI0_MISO | SPI0_MOSI | SPI0_SCK;
AT91C_BASE_PIOA->PIO_ASR = SPI0_MISO | SPI0_MOSI | SPI0_SCK;
AT91C_BASE_PIOA->PIO_PPUDR = SPI0_MISO | SPI0_MOSI | SPI0_SCK;
@@ -146,6 +199,8 @@ void spi_lld_init(void) {
/* Software reset must be written twice (errata for revision B parts).*/
AT91C_BASE_SPI1->SPI_CR = AT91C_SPI_SWRST;
AT91C_BASE_SPI1->SPI_CR = AT91C_SPI_SWRST;
+ AT91C_BASE_SPI1->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS;
+ AT91C_BASE_SPI1->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
AT91C_BASE_PIOA->PIO_PDR = SPI1_MISO | SPI1_MOSI | SPI1_SCK;
AT91C_BASE_PIOA->PIO_BSR = SPI1_MISO | SPI1_MOSI | SPI1_SCK;
AT91C_BASE_PIOA->PIO_PPUDR = SPI1_MISO | SPI1_MOSI | SPI1_SCK;
@@ -186,9 +241,7 @@ void spi_lld_start(SPIDriver *spip) {
else
spip->spd_spi->SPI_CR = AT91C_SPI_SPIDIS;
/* Configuration.*/
- spip->spd_spi->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS;
spip->spd_spi->SPI_CSR[0] = spip->spd_config->spc_csr;
- spip->spd_spi->SPI_CR = AT91C_SPI_SPIEN;
}
/**
@@ -204,14 +257,14 @@ void spi_lld_stop(SPIDriver *spip) {
#if AT91SAM7_SPI_USE_SPI0
if (&SPID1 == spip) {
spip->spd_spi->SPI_CR = AT91C_SPI_SPIDIS;
- spip->spd_spi->PMC_PCDR = (1 << AT91C_ID_SPI0);
+ AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_SPI0);
AIC_DisableIT(AT91C_ID_SPI0);
}
#endif
#if AT91SAM7_SPI_USE_SPI1
if (&SPID1 == spip) {
spip->spd_spi->SPI_CR = AT91C_SPI_SPIDIS;
- spip->spd_spi->PMC_PCDR = (1 << AT91C_ID_SPI1);
+ AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_SPI1);
AIC_DisableIT(AT91C_ID_SPI0);
}
#endif
@@ -256,8 +309,12 @@ void spi_lld_unselect(SPIDriver *spip) {
*/
void spi_lld_ignore(SPIDriver *spip, size_t n) {
- (void)spip;
- rw8(n, NULL, NULL);
+ spip->spd_spi->SPI_TCR = n;
+ spip->spd_spi->SPI_RCR = n;
+ spip->spd_spi->SPI_TPR = (AT91_REG)idle_buf;
+ spip->spd_spi->SPI_RPR = (AT91_REG)idle_buf;
+ spip->spd_spi->SPI_IER = AT91C_SPI_ENDRX;
+ spip->spd_spi->SPI_CR = AT91C_SPI_SPIEN;
}
/**
@@ -275,8 +332,12 @@ void spi_lld_ignore(SPIDriver *spip, size_t n) {
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf) {
- (void)spip;
- rw8(n, txbuf, rxbuf);
+ spip->spd_spi->SPI_TCR = n;
+ spip->spd_spi->SPI_RCR = n;
+ spip->spd_spi->SPI_TPR = (AT91_REG)txbuf;
+ spip->spd_spi->SPI_RPR = (AT91_REG)rxbuf;
+ spip->spd_spi->SPI_IER = AT91C_SPI_ENDRX;
+ spip->spd_spi->SPI_CR = AT91C_SPI_SPIEN;
}
/**
@@ -291,8 +352,12 @@ void spi_lld_exchange(SPIDriver *spip, size_t n,
*/
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
- (void)spip;
- rw8(n, txbuf, NULL);
+ spip->spd_spi->SPI_TCR = n;
+ spip->spd_spi->SPI_RCR = n;
+ spip->spd_spi->SPI_TPR = (AT91_REG)txbuf;
+ spip->spd_spi->SPI_RPR = (AT91_REG)idle_buf;
+ spip->spd_spi->SPI_IER = AT91C_SPI_ENDRX;
+ spip->spd_spi->SPI_CR = AT91C_SPI_SPIEN;
}
/**
@@ -307,8 +372,12 @@ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
*/
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
- (void)spip;
- rw8(n, NULL, rxbuf);
+ spip->spd_spi->SPI_TCR = n;
+ spip->spd_spi->SPI_RCR = n;
+ spip->spd_spi->SPI_TPR = (AT91_REG)idle_buf;
+ spip->spd_spi->SPI_RPR = (AT91_REG)rxbuf;
+ spip->spd_spi->SPI_IER = AT91C_SPI_ENDRX;
+ spip->spd_spi->SPI_CR = AT91C_SPI_SPIEN;
}
#endif /* CH_HAL_USE_SPI */