2010-01-13 04:46 AM
uart4 DMA causing HardFault error
2011-05-17 04:37 AM
UART4 & DMA init code:
/* Configure USARTx_Tx as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Configure USARTx_Rx as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOC, &GPIO_InitStructure); /* UART4 configured as follow: - BaudRate = 115200 baud - Word Length = 8 Bits - One Stop Bit - No parity - Hardware flow control disabled (RTS and CTS signals) - Receive and transmit enabled */ USART_InitStructure.USART_BaudRate = 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; /* Configure UART4 */ USART_Init(UART4, &USART_InitStructure); /* Enable the UART4 */ USART_Cmd(UART4, ENABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = UART4_DR_Base; DMA_InitStructure.DMA_MemoryBaseAddr = ((u32)pTxBuf); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 0xFF; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA2_Channel5, &DMA_InitStructure); /* Enable USART4 DMA TX request */ USART_DMACmd(UART4, USART_DMAReq_Tx, ENABLE); // restart DMA DMA_InitStructure.DMA_PeripheralBaseAddr = UART4_DR_Base; DMA_InitStructure.DMA_MemoryBaseAddr = (u32) pRxBuf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA2_Channel3, &DMA_InitStructure); /* Enable USART4 DMA TX request */ USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE); DMA_ITConfig(DMA2_Channel3, DMA_IT_TC, ENABLE); // enable interrupts DMA_ITConfig(DMA2_Channel3, DMA_IT_TC, ENABLE); //Rx DMA_ITConfig(DMA2_Channel5, DMA_IT_TC, ENABLE); //Tx DMA_ClearITPendingBit function is used to clear the interrupt flag. Problems: 1. Rx interrupt is not working. 2. Code in execution hits hardfault error but in debug mode works fine. Please give some suggestions.2011-05-17 04:37 AM
Hi,
I just have some remarks: - You should enable the Tx DMA request just after the DMA channel configuration (just like you did for Rx). And the USART_Cmd(Enable) should come at the end of the DMA configuration and Requests enable. (but I don't think this could really be the cause of the issue). - If you have hardfault in execution only and not in debug, it may be related to a timing issue (an event that can be delayed in debug mode), note that the DMA is not stopped when you are in debug mode, it is always running. - Could you check where exactly the hardfault is happening? And what kind of hardfault you have (by reading the CPU registers, if your tool allow it)? good luck :)2011-05-17 04:37 AM
Hi,
Thanks for the reply. I checked the exact location for the hardfault. In my program I need to reconfigure the DMA count and DMA transfer location for Tx & for Rx. By using following code I am using to change the DMA Tx counts. // clear pending interrupt request DMA_ClearFlag(DMA2_FLAG_TC5);// clear Tx interrupt request /* DMA2_Channel5 (triggered by UART4 Tx event) Config */ DMA_Cmd(DMA2_Channel5, DISABLE); DMA2_Channel5->CNDTR = TxCount; DMA2_Channel5->CMAR = (u32)pTxBuf; DMA_Cmd(DMA2_Channel5, ENABLE); Somewhere in DMA_Cmd I am facing the hardfault issue. If do the single stepping here then there is no hardfault. Regards, Prasad2011-05-17 04:37 AM
Hi,
I'm sorry, but I can't see anything wrong in your code. I just have a ''foolish'' idea: the DMA_Cmd contains |= and &= operators which means the operation is done through two instructions and maybe the interrupt is generated again while these operation are not still finished. So try to replace DMA_Cmd(DMA2_Channel5, ENABLE); and DMA_Cmd(DMA2_Channel5, DISABLE); by direct register access: DMA2_Channel5->CCR = xxxxxxx1h (replace with correct value for enable) DMA2_Channel5->CCR = xxxxxxx0h (replace with correct value for disable) Otherwise, Try to modify the optimization level or even the compiler. I hope someone else have better ideas than mine :-] . Good luck!2011-05-17 04:37 AM
Hi,
This may be an interesting topic for you: ?