Forum > Embedded - ARM

stm32f103 dma problem [SOLVED]

<< < (8/8)

diego bertotti:

--- Quote from: MiR on July 17, 2020, 01:47:29 pm ---I forgot in my last post that when an interrupt is not configured in nvic it does not fire....

The problem was indeed the 16-bit alignment of the fields, the processor creates an exception when the CNDTR field is accessed as HalfWord (16 Bits).

@Jeppe: Do you think you can patch this in the unit code @Trunk?
While at it, how do you think about changing the array index for dma from [0..6] to [1..7], that creates perhaps less confusion

So I stripped down your code and created this working example:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program torque_vfd_comm; uses cortexm3, stm32f103fw;{$O-} const  Serial_buffer_size = 7;  DMA_CHANNEL4 = 3;  PERIPH_BASE   = $40000000;  AHBPERIPH_BASE= PERIPH_BASE + $00020000;  DMA1_Channel4_BASE= AHBPERIPH_BASE + $00000044; type  TDMA_Channel_Registers = record    CCR         : longword;    CNDTR       : longword;    CPAR        : longword;    CMAR        : longword;  end; var  TXBuffer1: Array [0..Serial_buffer_size-1] of byte;  Usart_ini: TUSART_InitTypeDef;  NVIC_Ini: TNVIC_InitTypeDef;  GPIO_InitStruct: TGPIO_InitTypeDef;  RCC_Clocks: TRCC_ClocksTypeDef;  DMA1_Channel4 : TDMA_Channel_Registers absolute DMA1_Channel4_BASE;  i : integer; procedure DMA1_Channel4_global_interrupt;  public name 'DMA4_Channel1_global_interrupt';  interrupt;Begin  dma1.ifcr:= $0FFFFFFF;end; procedure USART1_SendBytesViaDMA(var Data : array of byte; const count : integer = -1);begin  //Disable DMA, Transfer Complete IRQ Read from Memory No Circular Mode No Periph Inc Memory Inc 8bit periph 8bit mem prio0  DMA1_Channel4.CCR := %000000010010010;  if count=-1 then    DMA1_Channel4.CNDTR := High(Data)+1  else    DMA1_Channel4.CNDTR := Count;  DMA1_Channel4.CPAR :=  LongWord(@Usart1.DR);  DMA1_Channel4.CMAR := LongWord(@Data);  DMA1_Channel4.CCR := DMA1_Channel4.CCR or %1;   //enableend; begin  //************************************************  //**************** RCC  *************************  //FLASH_SetLatency(1);  RCC_HSICmd(Enabled);  RCC_DeInit;  RCC_HSICmd(Enabled);  //For simplicity run on 8MHz internal Clock  RCC_HCLKConfig(RCC_SYSCLK_Div1);  RCC_PCLK1Config(RCC_HCLK_Div2); //24MHz  RCC_PCLK2Config(RCC_HCLK_Div1); //48MHz  RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1 or RCC_AHBPeriph_SRAM or RCC_AHBPeriph_FLITF, Enabled);  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, Enabled);  RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, Enabled);  RCC_GetClocksFreq(RCC_Clocks);   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_9; //TX USART1  GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;  GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;  GPIO_Init(PortA, GPIO_InitStruct);   //************************************************  //**************** USART *************************   Usart_ini.USART_BaudRate:= 9600;  Usart_ini.USART_WordLength:= USART_WordLength_8b;  Usart_ini.USART_StopBits:= USART_StopBits_1;  Usart_ini.USART_Parity:= USART_Parity_No;  Usart_ini.USART_Mode:= USART_Mode_Tx;  Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_None;  Usart_ini.USART_Clock:= USART_Clock_Disable;  Usart_ini.USART_CPOL:= USART_CPOL_Low;  Usart_ini.USART_CPHA:= USART_CPHA_1Edge;  Usart_ini.USART_LastBit:= USART_LastBit_Disable;  USART_Init(USart1, Usart_ini);   USART_DMACmd(Usart1,USART_DMAReq_Tx,Enabled);   Usart_Cmd(Usart1, ENABLED);   //************************************************  //**************** NVIC **************************  NVIC_Ini.NVIC_IRQChannelPreemptionPriority:= 0;  NVIC_Ini.NVIC_IRQChannelSubPriority:= 0;  NVIC_Ini.NVIC_IRQChannel:= DMAChannel4_IRQChannel;  NVIC_Init(NVIC_Ini);  NVIC_Ini.NVIC_IRQChannelCmd := Enabled;   TXBuffer1[0] := byte('h');  TXBuffer1[1] := byte('e');  TXBuffer1[2] := byte('l');  TXBuffer1[3] := byte('l');  TXBuffer1[4] := byte('o');  TXBuffer1[5] := byte(#13);  TXBuffer1[6] := byte(#10);   while true do  begin    USART1_SendBytesViaDMA(TXBuffer1);    //Quick hack, wait for tramsfer done....    repeat    until DMA1_Channel4.CNDTR = 0;    //now waste some time so that we better see when transfer starts again    for i := 1 to 100000 do      ;   end;end. 
i will try your code, but modified to use usart3 and ill see what happens[/code]
--- End quote ---

diego bertotti:
ok now the results


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- program torque_vfd_comm; uses cortexm3, stm32f103fw;{$O-} const  Serial_buffer_size = 7;  DMA_CHANNEL4 = 3;  PERIPH_BASE   = $40000000;  AHBPERIPH_BASE= PERIPH_BASE + $00020000;  DMA1_Channel2_BASE= AHBPERIPH_BASE + $0000001C;  DMA1_Channel4_BASE= AHBPERIPH_BASE + $00000044; type  TDMA_Channel_Registers = record    CCR         : longword;    CNDTR       : longword;    CPAR        : longword;    CMAR        : longword;  end; var  TXBuffer1: Array [0..Serial_buffer_size-1] of byte;   TXBuffer3: Array [0..Serial_buffer_size-1] of byte;  Usart_ini: TUSART_InitTypeDef;  NVIC_Ini: TNVIC_InitTypeDef;  GPIO_InitStruct: TGPIO_InitTypeDef;  RCC_Clocks: TRCC_ClocksTypeDef;  DMA1_Channel4 : TDMA_Channel_Registers absolute DMA1_Channel4_BASE;    DMA1_Channel2 : TDMA_Channel_Registers absolute DMA1_Channel2_BASE;  i : integer; procedure DMA1_Channel2_global_interrupt;  public name 'DMA2_Channel1_global_interrupt';  interrupt;Begin  DMA1.IFCR:= DMA1_FLAG_GL2;end; procedure DMA1_Channel4_global_interrupt;  public name 'DMA4_Channel1_global_interrupt';  interrupt;Begin  DMA1.IFCR:= DMA1_FLAG_GL4;end; procedure USART1_SendBytesViaDMA(var Data : array of byte; const count : integer = -1);begin  //Disable DMA, Transfer Complete IRQ Read from Memory No Circular Mode No Periph Inc Memory Inc 8bit periph 8bit mem prio0  DMA1_Channel4.CCR := %000000010010010;  if count=-1 then    DMA1_Channel4.CNDTR := High(Data)+1  else    DMA1_Channel4.CNDTR := Count;  DMA1_Channel4.CPAR :=  LongWord(@Usart1.DR);  DMA1_Channel4.CMAR := LongWord(@Data);  DMA1_Channel4.CCR := DMA1_Channel4.CCR or %1;   //enableend; procedure USART3_SendBytesViaDMA(var Data : array of byte; const count : integer = -1);begin  //Disable DMA, Transfer Complete IRQ Read from Memory No Circular Mode No Periph Inc Memory Inc 8bit periph 8bit mem prio0  DMA1_Channel2.CCR := %000000010010010;  if count=-1 then    DMA1_Channel2.CNDTR := High(Data)+1  else    DMA1_Channel2.CNDTR := Count;  DMA1_Channel2.CPAR :=  LongWord(@Usart3.DR);  DMA1_Channel2.CMAR := LongWord(@Data);  DMA1_Channel2.CCR := DMA1_Channel2.CCR or %1;   //enableend; begin  //************************************************  //**************** RCC  *************************  //FLASH_SetLatency(1);  RCC_HSICmd(Enabled);  RCC_DeInit;  RCC_HSICmd(Enabled);  //For simplicity run on 8MHz internal Clock  RCC_HCLKConfig(RCC_SYSCLK_Div1);  RCC_PCLK1Config(RCC_HCLK_Div2); //24MHz  RCC_PCLK2Config(RCC_HCLK_Div1); //48MHz  RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1 or RCC_AHBPeriph_SRAM or RCC_AHBPeriph_FLITF, Enabled);  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, Enabled);  RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, Enabled);  RCC_GetClocksFreq(RCC_Clocks);     GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_9; //TX USART1    GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;    GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;    GPIO_Init(PortA, GPIO_InitStruct);   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_10; //TX USART3  GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;  GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;  GPIO_Init(PortB, GPIO_InitStruct);   //************************************************  //**************** USART *************************   Usart_ini.USART_BaudRate:= 9600;  Usart_ini.USART_WordLength:= USART_WordLength_8b;  Usart_ini.USART_StopBits:= USART_StopBits_1;  Usart_ini.USART_Parity:= USART_Parity_No;  Usart_ini.USART_Mode:= USART_Mode_Tx;  Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_None;  Usart_ini.USART_Clock:= USART_Clock_Disable;  Usart_ini.USART_CPOL:= USART_CPOL_Low;  Usart_ini.USART_CPHA:= USART_CPHA_1Edge;  Usart_ini.USART_LastBit:= USART_LastBit_Disable;   USART_Init(USart1, Usart_ini);  USART_Init(USart3, Usart_ini);   USART_DMACmd(Usart1,USART_DMAReq_Tx,Enabled);  USART_DMACmd(Usart3,USART_DMAReq_Tx,Enabled);   Usart_Cmd(Usart1, ENABLED);  Usart_Cmd(Usart3, ENABLED);   //************************************************  //**************** NVIC **************************  NVIC_Ini.NVIC_IRQChannelPreemptionPriority:= 0;  NVIC_Ini.NVIC_IRQChannelSubPriority:= 0;  NVIC_Ini.NVIC_IRQChannel:= DMAChannel2_IRQChannel;  NVIC_Init(NVIC_Ini);                                 NVIC_Ini.NVIC_IRQChannel:= DMAChannel4_IRQChannel;  NVIC_Init(NVIC_Ini);  NVIC_Ini.NVIC_IRQChannelCmd := Enabled;    TXBuffer1[0] := byte('h');  TXBuffer1[1] := byte('o');  TXBuffer1[2] := byte('l');  TXBuffer1[3] := byte('a');  TXBuffer1[4] := byte('1');  TXBuffer1[5] := byte(#13);  TXBuffer1[6] := byte(#10);   TXBuffer3[0] := byte('h');  TXBuffer3[1] := byte('o');  TXBuffer3[2] := byte('l');  TXBuffer3[3] := byte('a');  TXBuffer3[4] := byte('3');  TXBuffer3[5] := byte(#13);  TXBuffer3[6] := byte(#10);   while true do  begin    USART1_SendBytesViaDMA(TXBuffer1);    USART3_SendBytesViaDMA(TXBuffer3);    //Quick hack, wait for tramsfer done....    repeat    until (DMA1_Channel2.CNDTR = 0) AND (DMA1_Channel4.CNDTR = 0);    //now waste some time so that we better see when transfer starts again    for i := 1 to 100000 do      ;   end;end.  
USART1 run perfectly.

nothing on PB10. it means TX pin of USART3.

work like open drain never activated, means floating pin, or high impedance state

anybody knows why?

thanks

MiR:
The solution is to only enable Peripherals that are needed. (plus disable synchronous mode on UART when not needed)

From the Errata Sheet of stm32f1xx:

2.9.6 I2C2 with SPI2 and USART3 Conditions

I2C2 and SPI2 are clocked together or I2C2 and USART3 are clocked together
....
USART3 must not be used in synchronous mode when I2C2 is being used.

So having I2C2 enabled kills USART3 function in your case.

When you change the two initialization lines in your last example to:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA or RCC_APB2Periph_GPIOB or RCC_APB2Periph_USART1, Enabled);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3+RCC_APB1Periph_PWR, Enabled); 
the example works for both USART1+3 (See Screenshot)

diego bertotti:
hello

thank you very much!!

i saw the same last night and wanna test it today, but you do it before than me

again thank you

diego bertotti:
hi

works!!!

i just uncomment this line

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 or RCC_APB1Periph_I2C2 or RCC_APB1Periph_CAN, Disabled); 
in the original code and start to transmit on PB10 pin 

look at the attachment the 3 tx signals of 3 usart

from now rx test and them timers input capture, pwm out, and a/d inputs...and i2c1! lot of work of test and after that the code for the project.

a lot of thanks for support me and for your time

Navigation

[0] Message Index

[*] Previous page

Go to full version