ST意法半导体
直播中

百合子

8年用户 882经验值
擅长:控制/MCU
私信 关注
[问答]

在USART Tx DMA片段上启用DCache,导致USART Tx失败的原因?

我正在尝试在 USART Tx DMA 片段上启用 DCache,这会导致 USART Tx 失败。
我的印象是 MCU 已经写入物理内存并且 DMA 访问写入的内存应该没有问题?
有人可以帮我解决这个问题吗?

马努
附上完整的代码片段。
  • #include "STM32h7xx_ll_bus.h"
  • #include "stm32h7xx_ll_cortex.h"
  • #include "stm32h7xx_ll_dma.h"
  • #include "stm32h7xx_ll_gpio.h"
  • #include "stm32h7xx_ll_pwr.h"
  • #include "stm32h7xx_ll_rcc.h"
  • #include "stm32h7xx_ll_system.h"
  • #include "stm32h7xx_ll_usart.h"
  • #include "stm32h7xx_ll_utils.h"
  • #include "string.h"
  • #include
  • #include
  • #define APB_Div                        4
  • #define ARRAY_LEN(x)            (sizeof(x) / sizeof((x)[0]))
  • __IO uint8_t tx_done = 0, rx_done = 0;
  • const uint8_t exstr[] ="test";
  • uint8_t rxbuf[80];
  • uint8_t rxlen = ARRAY_LEN(exstr);
  • void SystemClock_Config(void)
  • {
  •         LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
  •         if (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4)
  •                 while (1) {}
  •         LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
  •         LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0);
  •         LL_RCC_HSE_EnableBypass();
  •         LL_RCC_HSE_Enable();
  •         while (!LL_RCC_HSE_IsReady()) {}
  •         LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE);
  •         LL_RCC_PLL1P_Enable();
  •         LL_RCC_PLL1Q_Enable();
  •         LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
  •         LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
  •         LL_RCC_PLL1_SetM(1);
  •         LL_RCC_PLL1_SetN(120);
  •         LL_RCC_PLL1_SetP(2);
  •         LL_RCC_PLL1_SetQ(20);
  •         LL_RCC_PLL1_SetR(2);
  •         LL_RCC_PLL1_Enable();
  •         while (!LL_RCC_PLL1_IsReady()) {}
  •         LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
  •         LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
  •         LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
  •         LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
  •         LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
  •         LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
  •         LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
  •         LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
  •         LL_Init1msTick(480000000);
  •         LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);
  •         LL_SetSystemCoreClock(480000000);                        /* 480Mhz */
  •         LL_RCC_SetUSARTClockSource(LL_RCC_USART234578_CLKSOURCE_PCLK1);
  • }
  • void gpio_init(void)
  • {
  •         LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOD);        /* USART GPIO Clk */
  •         LL_GPIO_SetPinMode(GPIOD, LL_GPIO_PIN_8, LL_GPIO_MODE_ALTERNATE);
  •         LL_GPIO_SetAFPin_8_15(GPIOD, LL_GPIO_PIN_8, LL_GPIO_AF_7);
  •         LL_GPIO_SetPinSpeed(GPIOD, LL_GPIO_PIN_8, LL_GPIO_SPEED_FREQ_HIGH);
  •         LL_GPIO_SetPinOutputType(GPIOD, LL_GPIO_PIN_8, LL_GPIO_OUTPUT_PUSHPULL);
  •         LL_GPIO_SetPinPull(GPIOD, LL_GPIO_PIN_8, LL_GPIO_PULL_UP);
  •         LL_GPIO_SetPinMode(GPIOD, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);
  •         LL_GPIO_SetAFPin_8_15(GPIOD, LL_GPIO_PIN_9, LL_GPIO_AF_7);
  •         LL_GPIO_SetPinSpeed(GPIOD, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH);
  •         LL_GPIO_SetPinOutputType(GPIOD, LL_GPIO_PIN_9, LL_GPIO_OUTPUT_PUSHPULL);
  •         LL_GPIO_SetPinPull(GPIOD, LL_GPIO_PIN_9, LL_GPIO_PULL_UP);
  • }
  • __STATIC_INLINE void LL_DMA_EnablePeriphDMA(DMA_TypeDef *DMAx, uint32_t Stream)
  • {
  •         register uint32_t dma_base_addr = (uint32_t)DMAx;
  •         SET_BIT(((DMA_Stream_TypeDef *)(dma_base_addr + LL_DMA_STR_OFFSET_TAB[Stream]))->CR, DMA_SxCR_TRBUFF);
  • }
  • __STATIC_INLINE void LL_DMA_DisablePeriphDMA(DMA_TypeDef *DMAx, uint32_t Stream)
  • {
  •         register uint32_t dma_base_addr = (uint32_t)DMAx;
  •         CLEAR_BIT(((DMA_Stream_TypeDef *)(dma_base_addr + LL_DMA_STR_OFFSET_TAB[Stream]))->CR, DMA_SxCR_TRBUFF);
  • }
  • void config_usart(void)
  • {
  •         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);        /* USART3 Clk */
  •         LL_USART_SetTransferDirection(USART3,
  •                                       LL_USART_DIRECTION_TX_RX);
  •         LL_USART_ConfigCharacter(USART3,
  •                                  LL_USART_DATAWIDTH_8B,
  •                                  LL_USART_PARITY_NONE,
  •                                  LL_USART_STOPBITS_1);
  •         LL_USART_SetBaudRate(USART3,
  •                              (SystemCoreClock / APB_Div),
  •                              LL_USART_PRESCALER_DIV1,
  •                              LL_USART_OVERSAMPLING_16,
  •                              115200);
  •         LL_USART_Enable(USART3);                                /* Enable USART */
  •         while ((!(LL_USART_IsActiveFlag_TEACK(USART3))) ||
  •                (!(LL_USART_IsActiveFlag_REACK(USART3)))) { }
  • }
  • void config_dma(void)
  • {
  •         LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
  •         LL_DMA_SetPeriphRequest(DMA1,
  •                                 LL_DMA_STREAM_0,                /* Request DMA Stream 0 */
  •                                 LL_DMAMUX1_REQ_USART3_TX);        /* for DMAMUX1 USART3 Tx */
  •         LL_DMA_SetPeriphRequest(DMA1,
  •                                 LL_DMA_STREAM_1,                /* Request DMA Stream 1 */
  •                                 LL_DMAMUX1_REQ_USART3_RX);        /* for DMAMUX1 USART3 Rx */
  •         /* Tx DMA */
  •         LL_DMA_SetDataTransferDirection(DMA1,
  •                                         LL_DMA_STREAM_0,
  •                                         LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
  •         LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_0, LL_DMA_PRIORITY_HIGH);
  •         LL_DMA_SetMode(DMA1, LL_DMA_STREAM_0, LL_DMA_MODE_NORMAL);
  •         LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_0, LL_DMA_PERIPH_NOINCREMENT);
  •         LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_0, LL_DMA_MEMORY_INCREMENT);
  •         LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_BYTE);
  •         LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_BYTE);
  •         /* Rx DMA */
  •         LL_DMA_SetDataTransferDirection(DMA1,
  •                                         LL_DMA_STREAM_1,
  •                                         LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
  •         LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_1, LL_DMA_PRIORITY_HIGH);
  •         LL_DMA_SetMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MODE_CIRCULAR);
  •         LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
  •         LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
  •         LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_BYTE);
  •         LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_BYTE);
  •         LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_1);
  •         LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_0);                /* Tx Transfer Complete */
  •         LL_DMA_EnableIT_TE(DMA1, LL_DMA_STREAM_0);                /* Tx Transfer Error */
  •         LL_DMA_EnableIT_HT(DMA1, LL_DMA_STREAM_1);                /* Rx Half Transfer Done */
  •         LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_1);                /* Rx Transfer Complete */
  •         LL_DMA_EnableIT_TE(DMA1, LL_DMA_STREAM_1);                /* Tx Transfer Error */
  •         NVIC_SetPriority(DMA1_Stream0_IRQn, 0);                        /* Stream Priority */
  •         NVIC_SetPriority(DMA1_Stream1_IRQn, 0);
  •         NVIC_EnableIRQ(DMA1_Stream0_IRQn);                        /* Global IRQ */
  •         NVIC_EnableIRQ(DMA1_Stream1_IRQn);
  •         LL_USART_EnableDMAReq_TX(USART3);                        /* Enable Tx DMARQ */
  •         LL_USART_EnableDMAReq_RX(USART3);                        /* Enable Rx DMARQ */
  •         LL_DMA_ClearFlag_TC1(DMA1);                                /* Transfer complete */
  •         LL_DMA_ClearFlag_HT1(DMA1);                                /* Half Transfer done */
  •         LL_DMA_ClearFlag_TE1(DMA1);                                /* Transfer Error */
  •         LL_DMA_ClearFlag_DME1(DMA1);                                /* Direct MODE Error */
  •         LL_DMA_ClearFlag_FE1(DMA1);                                /* FIFO Error */
  •         LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, rxlen);
  •         LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_1, LL_USART_DMA_GetRegAddr(USART3, LL_USART_DMA_REG_DATA_RECEIVE));
  •         LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_1, (uint32_t)rxbuf);
  •         LL_DMA_EnablePeriphDMA(DMA1, LL_DMA_STREAM_1);                /* Enable USART3 Stream DMA */
  •         LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_1);                /* Enable DMA Channel Rx */
  • }
  • void start_dma(uint8_t *buf, uint8_t txlen)
  • {
  •         tx_done = 0;
  •         LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_0);                /* Done: LED OFF */
  •         LL_DMA_ClearFlag_TC0(DMA1);                                /* Transfer complete */
  •         LL_DMA_ClearFlag_HT0(DMA1);                                /* Half Transfer done */
  •         LL_DMA_ClearFlag_TE0(DMA1);                                /* Transfer Error */
  •         LL_DMA_ClearFlag_DME0(DMA1);                                /* Direct MODE Error */
  •         LL_DMA_ClearFlag_FE0(DMA1);                                /* FIFO Error */
  •         LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0, txlen);        /* DMA Stream length */
  •         LL_DMA_ConfigAddresses(DMA1,
  •                                LL_DMA_STREAM_0,                        /* USART3 DMA Stream 0 */
  •                                (uint32_t)buf,                        /* Transmit string */
  •                                LL_USART_DMA_GetRegAddr(USART3, LL_USART_DMA_REG_DATA_TRANSMIT),
  •                                LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_STREAM_0));
  •         LL_DMA_EnablePeriphDMA(DMA1, LL_DMA_STREAM_0);                /* Enable USART3 Stream DMA */
  •         LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0);                /* Enable DMA Channel Tx */
  • }
  • void stop_dma(void)
  • {
  •         while (!tx_done) {}
  •         LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);
  •         LL_DMA_DisablePeriphDMA(DMA1, LL_DMA_STREAM_0);                /* Disable USART3 Stream DMA */
  •         LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_0);                /* Done: LED ON */
  • }
  • void DMA1_Stream0_IRQHandler(void)
  • {
  •         if (LL_DMA_IsEnabledIT_TC(DMA1, LL_DMA_STREAM_0) &&
  •             LL_DMA_IsActiveFlag_TC0(DMA1)) {
  •                 LL_DMA_ClearFlag_TC0(DMA1);
  •                 LL_GPIO_SetOutputPin(GPIOE, LL_GPIO_PIN_1);        /* Done: LED2 ON */
  •                 tx_done = 1;
  •         }
  •         if (LL_DMA_IsEnabledIT_TE(DMA1, LL_DMA_STREAM_0) &&
  •             LL_DMA_IsActiveFlag_TE0(DMA1)) {
  •         }
  • }
  • void DMA1_Stream1_IRQHandler(void)
  • {
  •         if (LL_DMA_IsEnabledIT_HT(DMA1, LL_DMA_STREAM_1) &&
  •             LL_DMA_IsActiveFlag_HT1(DMA1)) {
  •                 LL_DMA_ClearFlag_HT1(DMA1);
  •         }
  •         if (LL_DMA_IsEnabledIT_TC(DMA1, LL_DMA_STREAM_1) &&
  •             LL_DMA_IsActiveFlag_TC1(DMA1)) {
  •                 LL_DMA_ClearFlag_TC1(DMA1);                     /* Clear transfer complete flag */
  •                 LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_14);        /* LED3 Toggle */
  •                 rx_done = 1;
  •         }
  •         if (LL_DMA_IsEnabledIT_TE(DMA1, LL_DMA_STREAM_1) &&
  •             LL_DMA_IsActiveFlag_TE1(DMA1)) {
  •         }
  • }
  • void printh(const char *fmt, ...)
  • {
  •         uint8_t pb[80];
  •         uint8_t len;
  •         va_list argp;
  •         va_start(argp, fmt);
  •         vsprintf((char *)&pb[0], fmt, argp);
  •         va_end(argp);
  •         len = strlen((char *)pb);
  •         start_dma(pb, len);
  •         stop_dma();
  • }
  • int main(void)
  • {
  •         SystemClock_Config();
  •         SCB_EnableICache();                                        /* Enable I-Cache */
  • //        SCB_EnableDCache();                                        /* Enable D-Cache */
  •         gpio_init();
  •         config_usart();
  •         config_dma();
  •         LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_0);                /* Done: LED ON */
  •         LL_mDelay(500);
  •         printh("STM32H743 USART DMA Testrn");
  •         LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_0);                /* Done: LED ON */
  •         LL_mDelay(500);
  •         LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_0);                /* Done: LED ON */
  •         LL_mDelay(500);
  •         printh("Hello Againrn");
  •         LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_0);                /* Done: LED ON */
  •         while (1) { }
  • }









回帖(1)

李军

2023-2-1 11:43:58
AXI SRAM 仅在 WBWA(写回写分配)模式下运行,没有直写地址映射。
> 但为什么缓存需要清理?
在 WBWA 模式下使用缓存时,CPU 仅在必要时写入内存,例如需要为新的缓存行腾出空间时。这是为了提高性能。如果您出于某种原因需要内存有效(例如,如果 DMA 想要从中读取),您可以通过执行干净操作强制 CPU 写入它。
> 或者,这是否意味着 MCU 已写入缓存,而不是实际内存?
举报

更多回帖

发帖
×
20
完善资料,
赚取积分