Added unified cache handler for Cortex-M devices.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11233 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2018-01-08 08:58:34 +00:00
parent 4148fb3cb7
commit 7761387ba0
11 changed files with 150 additions and 208 deletions

View File

@ -6,8 +6,6 @@ Driver capability:
The file registry must export: The file registry must export:
STM32_DMAn_CHx_HANDLER - Vector name for IRQ "x" (1..7). If the macro STM32_BDMAn_CHx_HANDLER - Vector name for IRQ "x" (1..7). If the macro
is not exported then the ISR is not declared. is not exported then the ISR is not declared.
STM32_DMAn_CHx_NUMBER - Vector number for IRQ "x" (1..7). STM32_BDMAn_CHx_NUMBER - Vector number for IRQ "x" (1..7).
STM32_DMA_CACHE_HANDLING - TRUE if the device requires explicit cache
handling on DMA buffers.

View File

@ -27,6 +27,8 @@
#ifndef STM32_DMA_H #ifndef STM32_DMA_H
#define STM32_DMA_H #define STM32_DMA_H
#include "cache.h"
/*===========================================================================*/ /*===========================================================================*/
/* Driver constants. */ /* Driver constants. */
/*===========================================================================*/ /*===========================================================================*/
@ -258,34 +260,6 @@ typedef struct {
/* Driver macros. */ /* Driver macros. */
/*===========================================================================*/ /*===========================================================================*/
/**
* @brief Invalidates the data cache lines overlapping a DMA buffer.
* @note It does nothing in this driver, it is supplied for compatibility.
*
* @param[in] saddr start address of the DMA buffer
* @param[in] n size of the DMA buffer in bytes
*
* @api
*/
#define dmaBufferInvalidate(addr, size) { \
(void)(addr); \
(void)(size); \
}
/**
* @brief Flushes the data cache lines overlapping a DMA buffer.
* @note It does nothing in this driver, it is supplied for compatibility.
*
* @param[in] saddr start address of the DMA buffer
* @param[in] n size of the DMA buffer in bytes
*
* @api
*/
#define dmaBufferFlush(addr, size) { \
(void)(addr); \
(void)(size); \
}
/** /**
* @name Macro Functions * @name Macro Functions
* @{ * @{

View File

@ -16,5 +16,3 @@ STM32_ADVANCED_DMA - TRUE not used by the DMA drivers but other
STM32_HAS_DMAx - Support for DMA unit "x" (1..2). STM32_HAS_DMAx - Support for DMA unit "x" (1..2).
STM32_DMAx_CHn_HANDLER - Vector name for channel "n" (0..7). STM32_DMAx_CHn_HANDLER - Vector name for channel "n" (0..7).
STM32_DMAn_CHx_NUMBER - Vector number 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.

View File

@ -25,6 +25,8 @@
#ifndef STM32_DMA_H #ifndef STM32_DMA_H
#define STM32_DMA_H #define STM32_DMA_H
#include "cache.h"
/*===========================================================================*/ /*===========================================================================*/
/* Driver constants. */ /* Driver constants. */
/*===========================================================================*/ /*===========================================================================*/
@ -216,10 +218,6 @@
/* Derived constants and error checks. */ /* 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) #if !defined(STM32_HAS_DMA1)
#error "STM32_HAS_DMA1 missing in registry" #error "STM32_HAS_DMA1 missing in registry"
#endif #endif
@ -385,71 +383,6 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/* Driver macros. */ /* Driver macros. */
/*===========================================================================*/ /*===========================================================================*/
#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 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
* @param[in] n size of the DMA buffer in bytes
*
* @api
*/
#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; \
start += 32U; \
} \
__DSB(); \
__ISB(); \
}
/**
* @brief Flushes the data cache lines overlapping a DMA buffer.
* @details This function is meant to make sure that data written in
* 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 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
* @param[in] n size of the DMA buffer in bytes
*
* @api
*/
#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; \
start += 32U; \
} \
__DSB(); \
__ISB(); \
}
#else
#define dmaBufferInvalidate(addr, size) { \
(void)(addr); \
(void)(size); \
}
#define dmaBufferFlush(addr, size) { \
(void)(addr); \
(void)(size); \
}
#endif
/** /**
* @name Macro Functions * @name Macro Functions
* @{ * @{

View File

@ -10,5 +10,3 @@ The file registry must export:
STM32_HAS_DMAx - Support for DMA unit "x" (1..2). STM32_HAS_DMAx - Support for DMA unit "x" (1..2).
STM32_DMAx_CHn_HANDLER - Vector name for channel "n" (0..7). STM32_DMAx_CHn_HANDLER - Vector name for channel "n" (0..7).
STM32_DMAx_CHn_NUMBER - Vector number for channel "n" (0..7). STM32_DMAx_CHn_NUMBER - Vector number for channel "n" (0..7).
STM32_DMA_CACHE_HANDLING - TRUE if the device requires explicit cache
handling on DMA buffers.

View File

@ -25,6 +25,7 @@
#ifndef STM32_DMA_H #ifndef STM32_DMA_H
#define STM32_DMA_H #define STM32_DMA_H
#include "cache.h"
#include "stm32_dmamux.h" #include "stm32_dmamux.h"
/*===========================================================================*/ /*===========================================================================*/
@ -171,10 +172,6 @@
/* Derived constants and error checks. */ /* 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) #if !defined(STM32_HAS_DMA1)
#error "STM32_HAS_DMA1 missing in registry" #error "STM32_HAS_DMA1 missing in registry"
#endif #endif
@ -341,71 +338,6 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/* Driver macros. */ /* Driver macros. */
/*===========================================================================*/ /*===========================================================================*/
#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 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
* @param[in] n size of the DMA buffer in bytes
*
* @api
*/
#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; \
start += 32U; \
} \
__DSB(); \
__ISB(); \
}
/**
* @brief Flushes the data cache lines overlapping a DMA buffer.
* @details This function is meant to make sure that data written in
* 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 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
* @param[in] n size of the DMA buffer in bytes
*
* @api
*/
#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; \
start += 32U; \
} \
__DSB(); \
__ISB(); \
}
#else
#define dmaBufferInvalidate(addr, size) { \
(void)(addr); \
(void)(size); \
}
#define dmaBufferFlush(addr, size) { \
(void)(addr); \
(void)(size); \
}
#endif
/** /**
* @name Macro Functions * @name Macro Functions
* @{ * @{

View File

@ -130,9 +130,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70
@ -501,9 +498,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70
@ -847,9 +841,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70
@ -1200,9 +1191,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70
@ -1523,9 +1511,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70
@ -1824,9 +1809,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70
@ -2104,9 +2086,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70
@ -2441,9 +2420,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING FALSE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70

View File

@ -111,9 +111,6 @@
#define STM32_HAS_DAC2_CH2 FALSE #define STM32_HAS_DAC2_CH2 FALSE
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_ADVANCED_DMA TRUE
#define STM32_DMA_CACHE_HANDLING TRUE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70

View File

@ -87,8 +87,6 @@
#define STM32_BDMA1_CH7_NUMBER 136 #define STM32_BDMA1_CH7_NUMBER 136
/* DMA attributes.*/ /* DMA attributes.*/
#define STM32_DMA_CACHE_HANDLING TRUE
#define STM32_HAS_DMA1 TRUE #define STM32_HAS_DMA1 TRUE
#define STM32_DMA1_CH0_HANDLER Vector6C #define STM32_DMA1_CH0_HANDLER Vector6C
#define STM32_DMA1_CH1_HANDLER Vector70 #define STM32_DMA1_CH1_HANDLER Vector70

View File

@ -0,0 +1,138 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file common/ARMCMx/cache.h
* @brief Cortex-Mx cache support macros and structures.
*
* @addtogroup COMMON_ARMCMx_CACHE
* @{
*/
#ifndef CACHE_H
#define CACHE_H
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
#if defined(__DCACHE_PRESENT) || defined(__DOXYGEN__)
#if (__DCACHE_PRESENT != 0) || defined(__DOXYGEN__)
/**
* @brief Invalidates the data cache lines overlapping a memory buffer.
* @details This function is meant to make sure that data written in
* data cache is invalidated.
* @note On devices without data cache this function does nothing.
* @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
* @param[in] n size of the DMA buffer in bytes
*
* @api
*/
#define cacheBufferInvalidate(saddr, n) { \
uint8_t *start = (uint8_t *)(saddr); \
uint8_t *end = start + (size_t)(n); \
__DSB(); \
while (start < end) { \
SCB->DCIMVAC = (uint32_t)start; \
start += 32U; \
} \
__DSB(); \
__ISB(); \
}
/**
* @brief Flushes the data cache lines overlapping a DMA buffer.
* @details This function is meant to make sure that data written in
* data cache is flushed to RAM.
* @note On devices without data cache this function does nothing.
* @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
* @param[in] n size of the DMA buffer in bytes
*
* @api
*/
#define cacheBufferFlush(saddr, n) { \
uint8_t *start = (uint8_t *)(saddr); \
uint8_t *end = start + (size_t)(n); \
__DSB(); \
while (start < end) { \
SCB->DCCIMVAC = (uint32_t)start; \
start += 32U; \
} \
__DSB(); \
__ISB(); \
}
#else /* __DCACHE_PRESENT == 0 */
#define dmaBufferInvalidate(addr, size) { \
(void)(addr); \
(void)(size); \
}
#define dmaBufferFlush(addr, size) { \
(void)(addr); \
(void)(size); \
}
#endif
#else /* !defined(__DCACHE_PRESENT) */
#define dmaBufferInvalidate(addr, size) { \
(void)(addr); \
(void)(size); \
}
#define dmaBufferFlush(addr, size) { \
(void)(addr); \
(void)(size); \
}
#endif
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* CACHE_H */
/** @} */

View File

@ -42,8 +42,8 @@ static THD_FUNCTION(spi_thread_1, p) {
spiExchange(&PORTAB_SPI1, 512, spiExchange(&PORTAB_SPI1, 512,
txbuf, rxbuf); /* Atomic transfer operations. */ txbuf, rxbuf); /* Atomic transfer operations. */
spiUnselect(&PORTAB_SPI1); /* Slave Select de-assertion. */ spiUnselect(&PORTAB_SPI1); /* Slave Select de-assertion. */
dmaBufferInvalidate(&txbuf[0], /* Cache invalidation over the */ cacheBufferInvalidate(&txbuf[0], /* Cache invalidation over the */
sizeof txbuf); /* buffer. */ sizeof txbuf);/* buffer. */
spiReleaseBus(&PORTAB_SPI1); /* Ownership release. */ spiReleaseBus(&PORTAB_SPI1); /* Ownership release. */
} }
} }
@ -64,8 +64,8 @@ static THD_FUNCTION(spi_thread_2, p) {
spiExchange(&PORTAB_SPI1, 512, spiExchange(&PORTAB_SPI1, 512,
txbuf, rxbuf); /* Atomic transfer operations. */ txbuf, rxbuf); /* Atomic transfer operations. */
spiUnselect(&PORTAB_SPI1); /* Slave Select de-assertion. */ spiUnselect(&PORTAB_SPI1); /* Slave Select de-assertion. */
dmaBufferInvalidate(&txbuf[0], /* Cache invalidation over the */ cacheBufferInvalidate(&txbuf[0], /* Cache invalidation over the */
sizeof txbuf); /* buffer. */ sizeof txbuf);/* buffer. */
spiReleaseBus(&PORTAB_SPI1); /* Ownership release. */ spiReleaseBus(&PORTAB_SPI1); /* Ownership release. */
} }
} }
@ -112,7 +112,7 @@ int main(void) {
*/ */
for (i = 0; i < sizeof(txbuf); i++) for (i = 0; i < sizeof(txbuf); i++)
txbuf[i] = (uint8_t)i; txbuf[i] = (uint8_t)i;
dmaBufferFlush(&txbuf[0], sizeof txbuf); cacheBufferFlush(&txbuf[0], sizeof txbuf);
/* /*
* Starting the transmitter and receiver threads. * Starting the transmitter and receiver threads.