cancel
Showing results for 
Search instead for 
Did you mean: 

uart4 DMA causing HardFault error

prasad2
Associate II
Posted on January 13, 2010 at 13:46

uart4 DMA causing HardFault error

5 REPLIES 5
prasad2
Associate II
Posted on May 17, 2011 at 13:37

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.

chikos33
Associate II
Posted on May 17, 2011 at 13:37

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 🙂

prasad2
Associate II
Posted on May 17, 2011 at 13:37

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,

Prasad

chikos33
Associate II
Posted on May 17, 2011 at 13:37

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!

chikos33
Associate II
Posted on May 17, 2011 at 13:37

Hi,

This may be an interesting topic for you:

http://www.st.com/mcu/forums-cat-7723-23.html

?