配置STM32 DMA寄存器时无法访问
I cannot access STM32 DMA register when configuring it
我目前使用标准外设库编写一个驱动程序,使内存能够在 STM32 F407 ZGT6 芯片上进行 USART6_TX DMA 传输。但是,我尝试了很长时间,但初始化一直失败:DMA_GetCmdStatus always returns DISABLE。通过使用GDB,我发现DMA_Init尝试将配置写入DMA寄存器后,DMA CR寄存器仍然为0。DMA初始化代码和执行如下:
void DMA_USART6_Init(char* DMA_Start_Pos, uint32_t DMA_Buffer_Size){
DMA_Buffer_Size_GV = DMA_Buffer_Size;
DMA_Start_Pos_GV = DMA_Start_Pos;
/*RCC config*/
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE);
/*DMA init*/
//DMA_DeInit(DMA2_Stream7);
DMA_Cmd(DMA2_Stream7, DISABLE);
while ((DMA_GetCmdStatus(DMA2_Stream7) == ENABLE)){}
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_Channel = DMA_Channel_5;
DMA_InitStruct.DMA_PeripheralBaseAddr = USART6_BASE + 0x04;//(uint32_t)&USART6->DR;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t) dubuff;//(uint32_t) DMA_Start_Pos;
DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStruct.DMA_BufferSize = (uint16_t)sizeof(dubuff);//DMA_Buffer_Size;
printf("buffer size should be %d \r\n", (uint16_t)sizeof(dubuff));
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_Init(DMA2_Stream7, &DMA_InitStruct);
printf("data counter after init %d \r\n", DMA_GetCurrDataCounter(DMA2_Stream7));
}
用于启用代码
void DMA_USART6_Enable_DMA(char* DMA_Start_Pos, uint32_t DMA_Buffer_Size, int MB){
Max_Buffer = MB;
USART6_init_for_DMA();
DMA_USART6_Init(DMA_Start_Pos, DMA_Buffer_Size);
DMA_USART6_NVIC_Init();
DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Stream7, ENABLE);
while ((DMA_GetCmdStatus(DMA2_Stream7) == DISABLE)){}//program stucked in this loop
}
USART6代码:
void USART6_init_for_DMA(void){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 57600;//115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART6, &USART_InitStructure);
USART_Cmd(USART6, ENABLE);
USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE);
}
和 GDB 结果:
the value that should be written into DMA CR register
图1中的文字:
367 DMAy_Streamx->CR = tmpreg;
(gdb) print tmpreg
= 167904576
the DMA CR register remains 0
图中文字2:
371 tmpreg = DMAy_Streamx->FCR;
(gdb) print *DMAy_Streamx
= {CR = 0, NDTR = 0, PAR = 0, M0AR = 0, M1AR = 0, FCR = 0}
请告诉我是否可以提供有关我的问题的任何信息或我可以进一步尝试的事情...
注:在同一个程序中,我的USART6和GPIO工作正常。
激活所需的流后,将无法再配置相关寄存器。只有在双缓冲区模式下,才能根据位 CT 功能更新内存地址 0 和 1。您必须先停用相关频道,然后应用更改。
我是OP。
一开始,我觉得这可能是一个明显的错误,这是真的。
事实证明,我应该使用 RCC_AHB1PeriphClockCmd 而不是 RCC_AHB1PeriphResetCmd,因为显然后来访问的 RSTR(RCC 复位寄存器)而不是 ENR,因此时钟未启用(关于 Codo 是正确的)。
嗯,希望看到这个问题的小伙伴不要再犯这个尴尬的错误了;(
我目前使用标准外设库编写一个驱动程序,使内存能够在 STM32 F407 ZGT6 芯片上进行 USART6_TX DMA 传输。但是,我尝试了很长时间,但初始化一直失败:DMA_GetCmdStatus always returns DISABLE。通过使用GDB,我发现DMA_Init尝试将配置写入DMA寄存器后,DMA CR寄存器仍然为0。DMA初始化代码和执行如下:
void DMA_USART6_Init(char* DMA_Start_Pos, uint32_t DMA_Buffer_Size){
DMA_Buffer_Size_GV = DMA_Buffer_Size;
DMA_Start_Pos_GV = DMA_Start_Pos;
/*RCC config*/
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE);
/*DMA init*/
//DMA_DeInit(DMA2_Stream7);
DMA_Cmd(DMA2_Stream7, DISABLE);
while ((DMA_GetCmdStatus(DMA2_Stream7) == ENABLE)){}
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_Channel = DMA_Channel_5;
DMA_InitStruct.DMA_PeripheralBaseAddr = USART6_BASE + 0x04;//(uint32_t)&USART6->DR;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t) dubuff;//(uint32_t) DMA_Start_Pos;
DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStruct.DMA_BufferSize = (uint16_t)sizeof(dubuff);//DMA_Buffer_Size;
printf("buffer size should be %d \r\n", (uint16_t)sizeof(dubuff));
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_Init(DMA2_Stream7, &DMA_InitStruct);
printf("data counter after init %d \r\n", DMA_GetCurrDataCounter(DMA2_Stream7));
}
用于启用代码
void DMA_USART6_Enable_DMA(char* DMA_Start_Pos, uint32_t DMA_Buffer_Size, int MB){
Max_Buffer = MB;
USART6_init_for_DMA();
DMA_USART6_Init(DMA_Start_Pos, DMA_Buffer_Size);
DMA_USART6_NVIC_Init();
DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Stream7, ENABLE);
while ((DMA_GetCmdStatus(DMA2_Stream7) == DISABLE)){}//program stucked in this loop
}
USART6代码:
void USART6_init_for_DMA(void){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 57600;//115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART6, &USART_InitStructure);
USART_Cmd(USART6, ENABLE);
USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE);
}
和 GDB 结果:
the value that should be written into DMA CR register
图1中的文字:
367 DMAy_Streamx->CR = tmpreg;
(gdb) print tmpreg
= 167904576
the DMA CR register remains 0
图中文字2:
371 tmpreg = DMAy_Streamx->FCR;
(gdb) print *DMAy_Streamx
= {CR = 0, NDTR = 0, PAR = 0, M0AR = 0, M1AR = 0, FCR = 0}
请告诉我是否可以提供有关我的问题的任何信息或我可以进一步尝试的事情... 注:在同一个程序中,我的USART6和GPIO工作正常。
激活所需的流后,将无法再配置相关寄存器。只有在双缓冲区模式下,才能根据位 CT 功能更新内存地址 0 和 1。您必须先停用相关频道,然后应用更改。
我是OP。 一开始,我觉得这可能是一个明显的错误,这是真的。 事实证明,我应该使用 RCC_AHB1PeriphClockCmd 而不是 RCC_AHB1PeriphResetCmd,因为显然后来访问的 RSTR(RCC 复位寄存器)而不是 ENR,因此时钟未启用(关于 Codo 是正确的)。
嗯,希望看到这个问题的小伙伴不要再犯这个尴尬的错误了;(