aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-08-27 11:43:17 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-08-27 11:43:17 +0000
commite4df1ff09dbf2f53accb9f93eacc4c9db15a4c6f (patch)
tree3f35d6e6c2198744f9573fbcee7b05645eec3c4d
parentb19f4e38da58ee3a6025775ebcb63b6878904291 (diff)
downloadChibiOS-e4df1ff09dbf2f53accb9f93eacc4c9db15a4c6f.tar.gz
ChibiOS-e4df1ff09dbf2f53accb9f93eacc4c9db15a4c6f.tar.bz2
ChibiOS-e4df1ff09dbf2f53accb9f93eacc4c9db15a4c6f.zip
Improved M7 cache handling.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8246 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--os/hal/ports/STM32/LLD/DMAv2/notes.txt2
-rw-r--r--os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h170
-rw-r--r--os/hal/ports/STM32/STM32F4xx/stm32_registry.h4
-rw-r--r--os/hal/ports/STM32/STM32F7xx/stm32_registry.h1
-rw-r--r--testhal/STM32/STM32F7xx/GPT-ADC/main.c6
-rw-r--r--testhal/STM32/STM32F7xx/SPI/main.c8
6 files changed, 172 insertions, 19 deletions
diff --git a/os/hal/ports/STM32/LLD/DMAv2/notes.txt b/os/hal/ports/STM32/LLD/DMAv2/notes.txt
index 4c01d8309..a4e14d38d 100644
--- a/os/hal/ports/STM32/LLD/DMAv2/notes.txt
+++ b/os/hal/ports/STM32/LLD/DMAv2/notes.txt
@@ -16,3 +16,5 @@ STM32_ADVANCED_DMA - TRUE not used by the DMA drivers but other
STM32_HAS_DMAx - Support for DMA unit "x" (1..2).
STM32_DMAx_CHn_HANDLER - Vector name for channel "n" (0..7).
STM32_DMAn_CHx_NUMBER - Vector number for channel "n" (0..7).
+STM32_DMA_CACHE_HANDLING - TRUE if the device requires explicit cache
+ handling on DMA buffers. \ No newline at end of file
diff --git a/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h b/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h
index fdc76ee59..b64bc525f 100644
--- a/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h
+++ b/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h
@@ -208,6 +208,146 @@
/* Derived constants and error checks. */
/*===========================================================================*/
+#if !defined(STM32_DMA_CACHE_HANDLING)
+#error "STM32_DMA_CACHE_HANDLING missing in registry"
+#endif
+
+#if !defined(STM32_HAS_DMA1)
+#error "STM32_HAS_DMA1 missing in registry"
+#endif
+
+#if !defined(STM32_HAS_DMA2)
+#error "STM32_HAS_DMA2 missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH0_HANDLER)
+#error "STM32_DMA1_CH0_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH1_HANDLER)
+#error "STM32_DMA1_CH1_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH2_HANDLER)
+#error "STM32_DMA1_CH2_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH3_HANDLER)
+#error "STM32_DMA1_CH3_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH4_HANDLER)
+#error "STM32_DMA1_CH4_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH5_HANDLER)
+#error "STM32_DMA1_CH5_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH6_HANDLER)
+#error "STM32_DMA1_CH6_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH7_HANDLER)
+#error "STM32_DMA1_CH7_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH0_HANDLER)
+#error "STM32_DMA2_CH0_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH1_HANDLER)
+#error "STM32_DMA2_CH1_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH2_HANDLER)
+#error "STM32_DMA2_CH2_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH3_HANDLER)
+#error "STM32_DMA2_CH3_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH4_HANDLER)
+#error "STM32_DMA2_CH4_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH5_HANDLER)
+#error "STM32_DMA2_CH5_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH6_HANDLER)
+#error "STM32_DMA2_CH6_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH7_HANDLER)
+#error "STM32_DMA2_CH7_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH0_NUMBER)
+#error "STM32_DMA1_CH0_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH1_NUMBER)
+#error "STM32_DMA1_CH1_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH2_NUMBER)
+#error "STM32_DMA1_CH2_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH3_NUMBER)
+#error "STM32_DMA1_CH3_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH4_NUMBER)
+#error "STM32_DMA1_CH4_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH5_NUMBER)
+#error "STM32_DMA1_CH5_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH6_NUMBER)
+#error "STM32_DMA1_CH6_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH7_NUMBER)
+#error "STM32_DMA1_CH7_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH0_NUMBER)
+#error "STM32_DMA2_CH0_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH1_NUMBER)
+#error "STM32_DMA2_CH1_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH2_NUMBER)
+#error "STM32_DMA2_CH2_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH3_NUMBER)
+#error "STM32_DMA2_CH3_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH4_NUMBER)
+#error "STM32_DMA2_CH4_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH5_NUMBER)
+#error "STM32_DMA2_CH5_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH6_NUMBER)
+#error "STM32_DMA2_CH6_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH7_NUMBER)
+#error "STM32_DMA2_CH7_NUMBER missing in registry"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@@ -237,23 +377,25 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/* Driver macros. */
/*===========================================================================*/
-#if defined(STM32F7XX) || defined(__DOXYGEN__)
+#if STM32_DMA_CACHE_HANDLING || defined(__DOXYGEN__)
/**
* @brief Invalidates the data cache lines overlapping a DMA buffer.
* @details This function is meant to make sure that data written in
* data cache is invalidated. It is used for DMA buffers that
* must have been written by a DMA stream.
* @note On devices without data cache this function does nothing.
- * @note The function takes care of cache lines alignment.
+ * @note The function does not consider the lower 5 bits of addresses,
+ * the buffers are meant to be aligned to a 32 bytes boundary or
+ * adjacent data can be invalidated as side effect.
*
- * @param[in] saddr start address of the DMA buffer, inclusive
- * @param[in] eaddr end address of the DMA buffer, not inclusive
+ * @param[in] saddr start address of the DMA buffer
+ * @param[in] n size of the DMA buffer in bytes
*
* @api
*/
-#define dmaBufferInvalidate(saddr, eaddr) { \
- uint8_t *start = (uint8_t *)(((uint32_t)(saddr)) & ~0x1FU); \
- uint8_t *end = (uint8_t *)(((((uint32_t)(eaddr)) - 1U) | 0x1FU) + 1U); \
+#define dmaBufferInvalidate(saddr, n) { \
+ uint8_t *start = (uint8_t *)(saddr); \
+ uint8_t *end = start + (size_t)(n); \
__DSB(); \
while (start < end) { \
SCB->DCIMVAC = (uint32_t)start; \
@@ -269,16 +411,18 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
* data cache is flushed to RAM. It is used for DMA buffers that
* must be read by a DMA stream.
* @note On devices without data cache this function does nothing.
- * @note The function takes care of cache lines alignment.
+ * @note The function does not consider the lower 5 bits of addresses,
+ * the buffers are meant to be aligned to a 32 bytes boundary or
+ * adjacent data can be flushed as side effect.
*
- * @param[in] saddr start address of the DMA buffer, inclusive
- * @param[in] eaddr end address of the DMA buffer, not inclusive
+ * @param[in] saddr start address of the DMA buffer
+ * @param[in] n size of the DMA buffer in bytes
*
* @api
*/
-#define dmaBufferFlush(saddr, eaddr) { \
- uint8_t *start = (uint8_t *)(((uint32_t)(saddr)) & ~0x1FU); \
- uint8_t *end = (uint8_t *)(((((uint32_t)(eaddr)) - 1U) | 0x1FU) + 1U); \
+#define dmaBufferFlush(saddr, n) { \
+ uint8_t *start = (uint8_t *)(saddr); \
+ uint8_t *end = start + (size_t)(n); \
__DSB(); \
while (start < end) { \
SCB->DCCIMVAC = (uint32_t)start; \
diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_registry.h b/os/hal/ports/STM32/STM32F4xx/stm32_registry.h
index d8778a6a0..9e2311a88 100644
--- a/os/hal/ports/STM32/STM32F4xx/stm32_registry.h
+++ b/os/hal/ports/STM32/STM32F4xx/stm32_registry.h
@@ -106,6 +106,7 @@
/* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C
@@ -455,6 +456,7 @@
/* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C
@@ -778,6 +780,7 @@
/* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C
@@ -1043,6 +1046,7 @@
/* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C
diff --git a/os/hal/ports/STM32/STM32F7xx/stm32_registry.h b/os/hal/ports/STM32/STM32F7xx/stm32_registry.h
index 75ff872c4..ff317028c 100644
--- a/os/hal/ports/STM32/STM32F7xx/stm32_registry.h
+++ b/os/hal/ports/STM32/STM32F7xx/stm32_registry.h
@@ -100,6 +100,7 @@
/* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_CACHE_HANDLING TRUE
#define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C
diff --git a/testhal/STM32/STM32F7xx/GPT-ADC/main.c b/testhal/STM32/STM32F7xx/GPT-ADC/main.c
index 4e1b27520..d0e810201 100644
--- a/testhal/STM32/STM32F7xx/GPT-ADC/main.c
+++ b/testhal/STM32/STM32F7xx/GPT-ADC/main.c
@@ -52,8 +52,10 @@ static adcsample_t samples1[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];
size_t nx = 0, ny = 0;
static void adccallback(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
- /* DMA buffer invalidation because data cache.*/
- dmaBufferInvalidate(buffer, buffer + (n * adcp->grpp->num_channels));
+ /* DMA buffer invalidation because data cache, only invalidating the
+ half buffer just filled.*/
+ dmaBufferInvalidate(buffer,
+ n * adcp->grpp->num_channels * sizeof (adcsample_t));
/* Updating counters.*/
if (samples1 == buffer) {
diff --git a/testhal/STM32/STM32F7xx/SPI/main.c b/testhal/STM32/STM32F7xx/SPI/main.c
index cd7b3ed07..bfed6c07c 100644
--- a/testhal/STM32/STM32F7xx/SPI/main.c
+++ b/testhal/STM32/STM32F7xx/SPI/main.c
@@ -87,7 +87,7 @@ static THD_FUNCTION(spi_thread_1, p) {
/* Preparing data buffer and flushing cache.*/
for (i = 0; i < SPI_BUFFERS_SIZE; i++)
txbuf[i] = (uint8_t)i;
- dmaBufferFlush(txbuf, txbuf + SPI_BUFFERS_SIZE);
+ dmaBufferFlush(txbuf, SPI_BUFFERS_SIZE);
/* Slave selection and data exchange.*/
spiSelect(&SPID2);
@@ -97,7 +97,7 @@ static THD_FUNCTION(spi_thread_1, p) {
#if defined(SPI_LOOPBACK)
/* Invalidating cache over the buffer then checking the
loopback result.*/
- dmaBufferInvalidate(rxbuf, rxbuf + SPI_BUFFERS_SIZE);
+ dmaBufferInvalidate(rxbuf, SPI_BUFFERS_SIZE);
if (memcmp(txbuf, rxbuf, SPI_BUFFERS_SIZE) != 0)
chSysHalt("loopback failure");
#endif
@@ -125,7 +125,7 @@ static THD_FUNCTION(spi_thread_2, p) {
/* Preparing data buffer and flushing cache.*/
for (i = 0; i < SPI_BUFFERS_SIZE; i++)
txbuf[i] = (uint8_t)(128U + i);
- dmaBufferFlush(txbuf, txbuf + SPI_BUFFERS_SIZE);
+ dmaBufferFlush(txbuf, SPI_BUFFERS_SIZE);
/* Slave selection and data exchange.*/
spiSelect(&SPID2);
@@ -135,7 +135,7 @@ static THD_FUNCTION(spi_thread_2, p) {
#if defined(SPI_LOOPBACK)
/* Invalidating cache over the buffer then checking the
loopback result.*/
- dmaBufferInvalidate(rxbuf, rxbuf + SPI_BUFFERS_SIZE);
+ dmaBufferInvalidate(rxbuf, SPI_BUFFERS_SIZE);
if (memcmp(txbuf, rxbuf, SPI_BUFFERS_SIZE) != 0)
chSysHalt("loopback failure");
#endif