Lazarus

Programming => Embedded => Operating Systems => Embedded - ARM => Topic started by: diego bertotti on July 07, 2020, 07:10:37 pm

Title: stm32f103 dma problem [SOLVED]
Post by: diego bertotti on July 07, 2020, 07:10:37 pm
hi

im trying bluepill board

using  unit stm32f103fw
{ Converted from STM FWlib

 Contributors:
  Jeppe Johansen
  Bernd Mueller
  Valerio Turrini with really small adjustments.....
}

when i use dma channels system hangs

Code: Pascal  [Select][+][-]
  1.   DMA_InitTypeDef.DMA_BufferSize:= 64;
  2.   DMA_InitTypeDef.DMA_DIR:= DMA_DIR_PeripheralSRC;
  3.   DMA_InitTypeDef.DMA_M2M:= DMA_M2M_Disable;
  4.   DMA_InitTypeDef.DMA_MemoryBaseAddr:=  @RXbuffer1;
  5.   DMA_InitTypeDef.DMA_MemoryDataSize:= DMA_MemoryDataSize_Byte;
  6.   DMA_InitTypeDef.DMA_MemoryInc:= DMA_MemoryInc_Enable;
  7.   DMA_InitTypeDef.DMA_Mode:= DMA_Mode_Circular;
  8.   DMA_InitTypeDef.DMA_PeripheralBaseAddr:= @Usart1.DR;
  9.   DMA_InitTypeDef.DMA_PeripheralDataSize:= DMA_PeripheralDataSize_Byte;
  10.   DMA_InitTypeDef.DMA_PeripheralInc:= DMA_PeripheralInc_Disable;
  11.   DMA_InitTypeDef.DMA_Priority:= DMA_Priority_Medium;
  12.   DMA_Init(DMA1.Channel[5], DMA_InitTypeDef); //USART1_RX
  13.   DMA_CMD(DMA1.Channel[5], Enabled);
  14.  

or even hangs if i use only the dma_deinit function

if i comment out the last 2 lines, dont hang, but ovbiously, dont work the dma controller, but all the rest code work fine


in the stm32f10x_md file i found this ¿bug?
Code: Pascal  [Select][+][-]
  1.  TDMARegisters = record
  2.   ISR,
  3.   IFCR: longword;
  4.   //Channel: array[0..7] of TDMAChannel; //wrong!! 8 channels space but have only 7
  5.   Channel: array[0..6] of TDMAChannel;  //diego bertotti 7/7/2020
  6.  end;
  7.  


 thanks in advance for any help/suggestions

 
Title: Re: stm32f103 dma problem
Post by: MiR on July 07, 2020, 09:35:51 pm
Looking at the datasheet 0..6 is correct, but better values would have been 1..7 as the DMA channels are numbered 1-7 in the reference manual.

Not sure if you took the offset of one into account in your code, DMA1.Channel[5] actually means use Channel6

Michael
Title: Re: stm32f103 dma problem
Post by: MiR on July 07, 2020, 09:40:10 pm
Again, from the reference manual:

USART1.RX is attached to Channel5 which means you will have to take index '4'
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 07, 2020, 10:17:19 pm
thanks for replys

i try with index 4 (you are right). same problem.

remember, i have the same problem, using the DMA_deinit function. in this case is not important the index value, is just an initilization, and hangs too.

i fix index form 0 to 6 because this code

Code: Pascal  [Select][+][-]
  1. procedure DMA_DeInit(var DMAy_Channelx: TDMAChannel);
  2.  
  3. begin
  4.    DMAy_Channelx.CCR:= DMAy_Channelx.CCR and (not(CCR_ENABLE_SET));
  5.    DMAy_Channelx.CCR:=0;
  6.    DMAy_Channelx.CNDTR:=0;
  7.    DMAy_Channelx.CPAR:=0;
  8.    DMAy_Channelx.CMAR:=0;
  9.    if @DMAy_Channelx = @DMA1.Channel[0] then
  10.       DMA1.IFCR := DMA1.IFCR or DMA1_Channel1_IT_Mask
  11.    else if @DMAy_Channelx = @DMA1.Channel[1] then
  12.       DMA1.IFCR := DMA1.IFCR or DMA1_Channel2_IT_Mask
  13.    else if @DMAy_Channelx = @DMA1.Channel[2] then
  14.       DMA1.IFCR := DMA1.IFCR or DMA1_Channel3_IT_Mask
  15.    else if @DMAy_Channelx = @DMA1.Channel[3] then
  16.       DMA1.IFCR := DMA1.IFCR or DMA1_Channel4_IT_Mask
  17.    else if @DMAy_Channelx = @DMA1.Channel[4] then
  18.       DMA1.IFCR := DMA1.IFCR or DMA1_Channel5_IT_Mask
  19.    else if @DMAy_Channelx = @DMA1.Channel[5] then
  20.       DMA1.IFCR := DMA1.IFCR or DMA1_Channel6_IT_Mask
  21.    else if @DMAy_Channelx = @DMA1.Channel[6] then
  22.       DMA1.IFCR := DMA1.IFCR or DMA1_Channel7_IT_Mask
  23.    else if @DMAy_Channelx = @DMA2.Channel[0] then
  24.       DMA2.IFCR := DMA2.IFCR or DMA2_Channel1_IT_Mask
  25.    else if @DMAy_Channelx = @DMA2.Channel[1] then
  26.       DMA2.IFCR := DMA2.IFCR or DMA2_Channel2_IT_Mask
  27.    else if @DMAy_Channelx = @DMA2.Channel[2] then
  28.       DMA2.IFCR := DMA2.IFCR or DMA2_Channel3_IT_Mask
  29.    else if @DMAy_Channelx = @DMA2.Channel[3] then
  30.       DMA2.IFCR := DMA2.IFCR or DMA2_Channel4_IT_Mask
  31.    else if @DMAy_Channelx = @DMA2.Channel[4] then
  32.       DMA2.IFCR := DMA2.IFCR or DMA2_Channel5_IT_Mask
  33. end;    
  34.  

look for example channel 1 use index 0!
Title: Re: stm32f103 dma problem
Post by: MiR on July 07, 2020, 10:32:49 pm
Have you tried running your deinit code in a debugger?

When I compare your De-Init Code to the original code in the C-Library it looks like a 1:1 translation so there does not seem to be an issue with the code itself.

In the debugger you will see easily if some interrupt triggers or you get some other exception
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 07, 2020, 10:39:33 pm
sorry, dont have debugger
wich one?
Title: Re: stm32f103 dma problem
Post by: MiR on July 07, 2020, 10:53:46 pm
There's a moster long thread here in the forum on debugging.
You can use a 2nd bluepill flashed with either original stlink firmware (google is your friend) or use the very good Black Magic Probe which also fits on a bluepill.

Also found reset code in libopencm3 (which I use sometimes) looks pretty much the same...

Is the peripheral clock for DMA enabled?

void dma_channel_reset(uint32_t dma, uint8_t channel)
{
   /* Disable channel and reset config bits. */
   DMA_CCR(dma, channel) = 0;
   /* Reset data transfer number. */
   DMA_CNDTR(dma, channel) = 0;
   /* Reset peripheral address. */
   DMA_CPAR(dma, channel) = 0;
   /* Reset memory address. */
   DMA_CMAR(dma, channel) = 0;
   /* Reset interrupt flags. */
   DMA_IFCR(dma) |= DMA_IFCR_CIF(channel);
}
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 07, 2020, 11:24:18 pm
look this!!!!

Code: Pascal  [Select][+][-]
  1.  
  2.  
  3.   PDMARegisters : ^LongWord;
  4.  
  5.  
  6.   PDMARegisters := @DMA1 + $58;   //CCR5
  7.   PDMARegisters^:= %000000010100001;
  8.   PDMARegisters := @DMA1 + $5C;   //CNDTR5
  9.   PDMARegisters^:= 64;  
  10.   PDMARegisters := @DMA1 + $60;   //CPAR5
  11.   PDMARegisters^:= LongWord(@Usart1.DR);
  12.   PDMARegisters := @DMA1 + $64;   //CMAR5
  13.   PDMARegisters^:= LongWord(@RXBuffer1);
  14.  
  15.  

i still dont know if dma working, but now dont hangs

and dma clock is enabled


Code: Pascal  [Select][+][-]
  1.  RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1 or RCC_AHBPeriph_DMA2 or RCC_AHBPeriph_SRAM or RCC_AHBPeriph_FLITF, Enabled);
  2.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, Enabled);
  3.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, Enabled);
  4.  
  5.  
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 13, 2020, 02:47:24 pm
There's a moster long thread here in the forum on debugging.
You can use a 2nd bluepill flashed with either original stlink firmware (google is your friend) or use the very good Black Magic Probe which also fits on a bluepill.

ok. but what about debugging software. wich one?
Title: Re: stm32f103 dma problem
Post by: MiR on July 13, 2020, 03:52:25 pm
You can debug from Lazarus, works quite OK when things are not too complex. Instructions are in the Monster Thread on Debugging...

Good alternatives are:
https://www.gdbgui.com/

and if you have JLink use Ozone:
https://www.segger.com/products/development-tools/ozone-j-link-debugger/
To get a JLink buy a nucleo board for $10 and after a quick conversion you are ready to debug whole STM32 family:
https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/
Advantage of Ozone is that it works well with FreeRTOS

I also saw this, but did not try for myself:

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/jtag-debugging/using-debugger.html

seems you can use Eclipse as a standalone debugger, looks interesting, may be worth a try!
Title: Re: stm32f103 dma problem
Post by: avra on July 13, 2020, 06:22:54 pm
when i use dma channels system hangs
You should try some Arduino or STM32CubeIDE DMA code for stm32f103 to check if DMA works on your blue pill at all. If you have a cheap clone, there is some chance that you are facing a problem because of not 100% compatible cpu. Take a look at https://www.cnx-software.com/2020/03/22/how-to-detect-stm32-fakes/
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 15, 2020, 12:55:14 am
hi

now i have a working code, but in bare metal way

Code: Pascal  [Select][+][-]
  1.  
  2.   TXBuffer1[0]:= byte('h');  
  3.   TXBuffer1[1]:= byte('e');
  4.   TXBuffer1[2]:= byte('l');
  5.   TXBuffer1[3]:= byte('l');
  6.   TXBuffer1[4]:= byte('o');
  7.  
  8.  Usart1.CR1:= 0; //disable usart1
  9.  Usart1.CR1:= Usart1.CR1 or %00000000001100;
  10.  Usart1.CR2:= 0;
  11.  Usart1.CR2:= Usart1.CR2 or %000000000000000;
  12.  Usart1.CR3:= 0;
  13.  Usart1.CR3:= Usart1.CR3 or %00010000000;
  14.  Usart1.GTPR:= 0;
  15.  Usart1.BRR:= 5000 SHL 4;// 9600 @48mhz
  16.  Usart1.CR1:= Usart1.CR1 or $2000; //enable usart1
  17.  PDMARegisters := @DMA1 + $44;   //CCR4
  18.  PDMARegisters^:= %000000010110110;
  19.  PDMARegisters := @DMA1 + $48;   //CNDTR4
  20.  PDMARegisters^:= 5;
  21.  PDMARegisters := @DMA1 + $4C;   //CPAR4
  22.  PDMARegisters^:= LongWord(@Usart1.DR);
  23.  PDMARegisters := @DMA1 + $50;   //CMAR4
  24.  PDMARegisters^:= LongWord(@TXBuffer1);
  25.  Usart1.SR:= Usart1.SR and not %1000000;
  26.  PDMARegisters := @DMA1 + $44;   //CCR4
  27.  PDMARegisters^:= PDMARegisters^ or %1;   //enable
  28.  

Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 15, 2020, 03:24:49 pm
hi

problem seems are inside dma lib only

using this code works too

Code: Pascal  [Select][+][-]
  1.  Usart_ini.USART_BaudRate:= 9600;
  2.  Usart_ini.USART_WordLength:= USART_WordLength_8b;
  3.  Usart_ini.USART_StopBits:= USART_StopBits_1;
  4.  Usart_ini.USART_Parity:= USART_Parity_No ;
  5.  Usart_ini.USART_Mode:= USART_Mode_Rx or USART_Mode_Tx;
  6.  Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_None;
  7.  Usart_ini.USART_Clock:= USART_Clock_Disable;
  8.  Usart_ini.USART_CPOL:= USART_CPOL_Low;
  9.  Usart_ini.USART_CPHA:= USART_CPHA_1Edge;
  10.  Usart_ini.USART_LastBit:= USART_LastBit_Disable;
  11.  USART_Init(USart1, Usart_ini);
  12.  USART_Init(USart3, Usart_ini);
  13.  Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_RTS;
  14.  USART_Init(USart2, Usart_ini);
  15.  
  16.  USART_DMACmd(Usart1,USART_DMAReq_Tx  or USART_DMAReq_Rx ,Enabled);
  17.  USART_ITConfig(Usart1, USART_IT_TC , enabled);
  18.  Usart_Cmd(Usart1, ENABLED);
  19.  PDMARegisters := @DMA1 + $44;   //CCR4
  20.  PDMARegisters^:= %000000010110110;
  21.  PDMARegisters := @DMA1 + $48;   //CNDTR4
  22.  PDMARegisters^:= 5;
  23.  PDMARegisters := @DMA1 + $4C;   //CPAR4
  24.  PDMARegisters^:= LongWord(@Usart1.DR);
  25.  PDMARegisters := @DMA1 + $50;   //CMAR4
  26.  PDMARegisters^:= LongWord(@TXBuffer1);
  27.  Usart1.SR:= Usart1.SR and not %1000000;
  28.  PDMARegisters := @DMA1 + $44;   //CCR4
  29.  PDMARegisters^:= PDMARegisters^ or %1;   //enable    
  30.  
Title: Re: stm32f103 dma problem
Post by: MiR on July 15, 2020, 05:14:27 pm
I compared the definition in the unit file with my own autogenerated units for stm32f103rb.

There are two differences, one is that in the official lib we have word access to some of the fields, this does matter on Cortex-M0 but on Cortex M3 it should not matter as the chip can handle word access to 32bit registers. But it is perhaps worth a try to redefine the fields to be longWord and by this to force proper 32bit access.

The other difference is that STM defines hard offsets for the DMA_Channels, you do the same in your code.

Can you check if address of DMA1.Channel[4].CCR is the same as @DMA1 + $58;

or

DMA1.Channel[3].CCR is the same as @DMA1 + $44; (From your last example, there you use DMA Channel 4)


If addresses are the same then the word/longword access sounds like a good cause for the problem.
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 15, 2020, 11:15:41 pm
@DMA1.Channel[2] = $4002 0030




using this code and a logic analizer in the out pin

Code: Pascal  [Select][+][-]
  1.  
  2.    tmpreg:= longWord(@DMA1.Channel[2]);
  3.    AUX_B:= Byte((tmpreg AND $000000FF));
  4.    TXBuffer1[5]:= AUX_B;
  5.    AUX_B:= Byte((tmpreg  AND $0000FF00) shr 8);
  6.    TXBuffer1[6]:= AUX_B;
  7.    AUX_B:= Byte((tmpreg  AND $00FF0000) shr 16);
  8.    TXBuffer1[7]:= AUX_B;
  9.    AUX_B:= Byte((tmpreg  AND $FF000000) shr 24);
  10.    TXBuffer1[8]:= AUX_B;
  11.  
  12.  

seems ok but shifted one.

i try deinit function with any index btw 0..6 and always hangs!!

i try modify record form word to lonword...and hangs!!!

now, if i comment out lines in library writing the ccr and cntdr, dont hang

Code: Pascal  [Select][+][-]
  1.  
  2. procedure DMA_DeInit(var DMAy_Channelx: TDMAChannel);
  3.  
  4. begin
  5.   // DMAy_Channelx.CCR:= DMAy_Channelx.CCR and (not(CCR_ENABLE_SET));
  6.   // DMAy_Channelx.CCR:=0;
  7.   // DMAy_Channelx.CNDTR:= 0;
  8.    DMAy_Channelx.CPAR:=0;
  9.    DMAy_Channelx.CMAR:=0;
  10.    if @DMAy_Channelx = @DMA1.Channel[0] then
  11.       DMA1.IFCR := DMA1.IFCR or DMA1_Channel1_IT_Mask  
  12.  
  13.  

but i try to modify declaration from word to longword, (and eliminating the res1 and res2 words) and still hangs

Code: Pascal  [Select][+][-]
  1.  
  2.  TDMAChannel = record
  3.   {CCR, res1,
  4.   CNDTR, res2: word;}
  5.   CCR,
  6.   CNDTR,
  7.   CPAR,
  8.   CMAR,
  9.   res: longword;
  10.  end;
  11.  
  12.  
Title: Re: stm32f103 dma problem
Post by: avra on July 16, 2020, 09:13:38 am
This is from one of the stm32f103*.h files at https://github.com/stm32duino/Arduino_Core_STM32:
Code: C  [Select][+][-]
  1. typedef struct
  2. {
  3.   __IO uint32_t CCR;
  4.   __IO uint32_t CNDTR;
  5.   __IO uint32_t CPAR;
  6.   __IO uint32_t CMAR;
  7. } DMA_Channel_TypeDef;
  8.  
  9. typedef struct
  10. {
  11.   __IO uint32_t ISR;
  12.   __IO uint32_t IFCR;
  13. } DMA_TypeDef;

Code: C  [Select][+][-]
  1. #define PERIPH_BASE           0x40000000UL /*!< Peripheral base address in the alias region */
  2.  
  3. #define APB1PERIPH_BASE       PERIPH_BASE
  4. #define APB2PERIPH_BASE       (PERIPH_BASE + 0x00010000UL)
  5. #define AHBPERIPH_BASE        (PERIPH_BASE + 0x00020000UL)
  6.  
  7. #define DMA1_BASE             (AHBPERIPH_BASE + 0x00000000UL)
  8. #define DMA1_Channel1_BASE    (AHBPERIPH_BASE + 0x00000008UL)
  9. #define DMA1_Channel2_BASE    (AHBPERIPH_BASE + 0x0000001CUL)
  10. #define DMA1_Channel3_BASE    (AHBPERIPH_BASE + 0x00000030UL)
  11. #define DMA1_Channel4_BASE    (AHBPERIPH_BASE + 0x00000044UL)
  12. #define DMA1_Channel5_BASE    (AHBPERIPH_BASE + 0x00000058UL)
  13. #define DMA1_Channel6_BASE    (AHBPERIPH_BASE + 0x0000006CUL)
  14. #define DMA1_Channel7_BASE    (AHBPERIPH_BASE + 0x00000080UL)

Code: C  [Select][+][-]
  1. #define DMA1                ((DMA_TypeDef *)DMA1_BASE)
  2. #define DMA1_Channel1       ((DMA_Channel_TypeDef *)DMA1_Channel1_BASE)
  3. #define DMA1_Channel2       ((DMA_Channel_TypeDef *)DMA1_Channel2_BASE)
  4. #define DMA1_Channel3       ((DMA_Channel_TypeDef *)DMA1_Channel3_BASE)
  5. #define DMA1_Channel4       ((DMA_Channel_TypeDef *)DMA1_Channel4_BASE)
  6. #define DMA1_Channel5       ((DMA_Channel_TypeDef *)DMA1_Channel5_BASE)
  7. #define DMA1_Channel6       ((DMA_Channel_TypeDef *)DMA1_Channel6_BASE)
  8. #define DMA1_Channel7       ((DMA_Channel_TypeDef *)DMA1_Channel7_BASE)

and here is relevant HAL driver code from stm32f1xx_ll_dma.c:
Code: C  [Select][+][-]
  1. /**
  2.   * @brief  De-initialize the DMA registers to their default reset values.
  3.   * @param  DMAx DMAx Instance
  4.   * @param  Channel This parameter can be one of the following values:
  5.   *         @arg @ref LL_DMA_CHANNEL_1
  6.   *         @arg @ref LL_DMA_CHANNEL_2
  7.   *         @arg @ref LL_DMA_CHANNEL_3
  8.   *         @arg @ref LL_DMA_CHANNEL_4
  9.   *         @arg @ref LL_DMA_CHANNEL_5
  10.   *         @arg @ref LL_DMA_CHANNEL_6
  11.   *         @arg @ref LL_DMA_CHANNEL_7
  12.   * @retval An ErrorStatus enumeration value:
  13.   *          - SUCCESS: DMA registers are de-initialized
  14.   *          - ERROR: DMA registers are not de-initialized
  15.   */
  16. uint32_t LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Channel)
  17. {
  18.   DMA_Channel_TypeDef *tmp = (DMA_Channel_TypeDef *)DMA1_Channel1;
  19.   ErrorStatus status = SUCCESS;
  20.  
  21.   /* Check the DMA Instance DMAx and Channel parameters*/
  22.   assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));
  23.  
  24.   tmp = (DMA_Channel_TypeDef *)(__LL_DMA_GET_CHANNEL_INSTANCE(DMAx, Channel));
  25.  
  26.   /* Disable the selected DMAx_Channely */
  27.   CLEAR_BIT(tmp->CCR, DMA_CCR_EN);
  28.  
  29.   /* Reset DMAx_Channely control register */
  30.   LL_DMA_WriteReg(tmp, CCR, 0U);
  31.  
  32.   /* Reset DMAx_Channely remaining bytes register */
  33.   LL_DMA_WriteReg(tmp, CNDTR, 0U);
  34.  
  35.   /* Reset DMAx_Channely peripheral address register */
  36.   LL_DMA_WriteReg(tmp, CPAR, 0U);
  37.  
  38.   /* Reset DMAx_Channely memory address register */
  39.   LL_DMA_WriteReg(tmp, CMAR, 0U);
  40.  
  41.   if (Channel == LL_DMA_CHANNEL_1)
  42.   {
  43.     /* Reset interrupt pending bits for DMAx Channel1 */
  44.     LL_DMA_ClearFlag_GI1(DMAx);
  45.   }
  46.   else if (Channel == LL_DMA_CHANNEL_2)
  47.   {
  48.     /* Reset interrupt pending bits for DMAx Channel2 */
  49.     LL_DMA_ClearFlag_GI2(DMAx);
  50.   }
  51.   else if (Channel == LL_DMA_CHANNEL_3)
  52.   {
  53.     /* Reset interrupt pending bits for DMAx Channel3 */
  54.     LL_DMA_ClearFlag_GI3(DMAx);
  55.   }
  56.   else if (Channel == LL_DMA_CHANNEL_4)
  57.   {
  58.     /* Reset interrupt pending bits for DMAx Channel4 */
  59.     LL_DMA_ClearFlag_GI4(DMAx);
  60.   }
  61.   else if (Channel == LL_DMA_CHANNEL_5)
  62.   {
  63.     /* Reset interrupt pending bits for DMAx Channel5 */
  64.     LL_DMA_ClearFlag_GI5(DMAx);
  65.   }
  66.  
  67.   else if (Channel == LL_DMA_CHANNEL_6)
  68.   {
  69.     /* Reset interrupt pending bits for DMAx Channel6 */
  70.     LL_DMA_ClearFlag_GI6(DMAx);
  71.   }
  72.   else if (Channel == LL_DMA_CHANNEL_7)
  73.   {
  74.     /* Reset interrupt pending bits for DMAx Channel7 */
  75.     LL_DMA_ClearFlag_GI7(DMAx);
  76.   }
  77.   else
  78.   {
  79.     status = ERROR;
  80.   }
  81.  
  82.   return status;
  83. }

Code: C  [Select][+][-]
  1. /**
  2.   * @brief  Initialize the DMA registers according to the specified parameters in DMA_InitStruct.
  3.   * @note   To convert DMAx_Channely Instance to DMAx Instance and Channely, use helper macros :
  4.   *         @arg @ref __LL_DMA_GET_INSTANCE
  5.   *         @arg @ref __LL_DMA_GET_CHANNEL
  6.   * @param  DMAx DMAx Instance
  7.   * @param  Channel This parameter can be one of the following values:
  8.   *         @arg @ref LL_DMA_CHANNEL_1
  9.   *         @arg @ref LL_DMA_CHANNEL_2
  10.   *         @arg @ref LL_DMA_CHANNEL_3
  11.   *         @arg @ref LL_DMA_CHANNEL_4
  12.   *         @arg @ref LL_DMA_CHANNEL_5
  13.   *         @arg @ref LL_DMA_CHANNEL_6
  14.   *         @arg @ref LL_DMA_CHANNEL_7
  15.   * @param  DMA_InitStruct pointer to a @ref LL_DMA_InitTypeDef structure.
  16.   * @retval An ErrorStatus enumeration value:
  17.   *          - SUCCESS: DMA registers are initialized
  18.   *          - ERROR: Not applicable
  19.   */
  20. uint32_t LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitTypeDef *DMA_InitStruct)
  21. {
  22.   /* Check the DMA Instance DMAx and Channel parameters*/
  23.   assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));
  24.  
  25.   /* Check the DMA parameters from DMA_InitStruct */
  26.   assert_param(IS_LL_DMA_DIRECTION(DMA_InitStruct->Direction));
  27.   assert_param(IS_LL_DMA_MODE(DMA_InitStruct->Mode));
  28.   assert_param(IS_LL_DMA_PERIPHINCMODE(DMA_InitStruct->PeriphOrM2MSrcIncMode));
  29.   assert_param(IS_LL_DMA_MEMORYINCMODE(DMA_InitStruct->MemoryOrM2MDstIncMode));
  30.   assert_param(IS_LL_DMA_PERIPHDATASIZE(DMA_InitStruct->PeriphOrM2MSrcDataSize));
  31.   assert_param(IS_LL_DMA_MEMORYDATASIZE(DMA_InitStruct->MemoryOrM2MDstDataSize));
  32.   assert_param(IS_LL_DMA_NBDATA(DMA_InitStruct->NbData));
  33.   assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority));
  34.  
  35.   /*---------------------------- DMAx CCR Configuration ------------------------
  36.    * Configure DMAx_Channely: data transfer direction, data transfer mode,
  37.    *                          peripheral and memory increment mode,
  38.    *                          data size alignment and  priority level with parameters :
  39.    * - Direction:      DMA_CCR_DIR and DMA_CCR_MEM2MEM bits
  40.    * - Mode:           DMA_CCR_CIRC bit
  41.    * - PeriphOrM2MSrcIncMode:  DMA_CCR_PINC bit
  42.    * - MemoryOrM2MDstIncMode:  DMA_CCR_MINC bit
  43.    * - PeriphOrM2MSrcDataSize: DMA_CCR_PSIZE[1:0] bits
  44.    * - MemoryOrM2MDstDataSize: DMA_CCR_MSIZE[1:0] bits
  45.    * - Priority:               DMA_CCR_PL[1:0] bits
  46.    */
  47.   LL_DMA_ConfigTransfer(DMAx, Channel, DMA_InitStruct->Direction | \
  48.                         DMA_InitStruct->Mode                   | \
  49.                         DMA_InitStruct->PeriphOrM2MSrcIncMode  | \
  50.                         DMA_InitStruct->MemoryOrM2MDstIncMode  | \
  51.                         DMA_InitStruct->PeriphOrM2MSrcDataSize | \
  52.                         DMA_InitStruct->MemoryOrM2MDstDataSize | \
  53.                         DMA_InitStruct->Priority);
  54.  
  55.   /*-------------------------- DMAx CMAR Configuration -------------------------
  56.    * Configure the memory or destination base address with parameter :
  57.    * - MemoryOrM2MDstAddress: DMA_CMAR_MA[31:0] bits
  58.    */
  59.   LL_DMA_SetMemoryAddress(DMAx, Channel, DMA_InitStruct->MemoryOrM2MDstAddress);
  60.  
  61.   /*-------------------------- DMAx CPAR Configuration -------------------------
  62.    * Configure the peripheral or source base address with parameter :
  63.    * - PeriphOrM2MSrcAddress: DMA_CPAR_PA[31:0] bits
  64.    */
  65.   LL_DMA_SetPeriphAddress(DMAx, Channel, DMA_InitStruct->PeriphOrM2MSrcAddress);
  66.  
  67.   /*--------------------------- DMAx CNDTR Configuration -----------------------
  68.    * Configure the peripheral base address with parameter :
  69.    * - NbData: DMA_CNDTR_NDT[15:0] bits
  70.    */
  71.   LL_DMA_SetDataLength(DMAx, Channel, DMA_InitStruct->NbData);
  72.  
  73.   return SUCCESS;
  74. }
Title: Re: stm32f103 dma problem
Post by: MiR on July 16, 2020, 10:52:41 am
Can you please send complete code for the working example that sends Hello via DMA?

What I am missing (for example) is your ISR routine for DMA, you enable DMA Interrupts, so you also need to handle the interrupts.

As Addresses match perfectly and (as assumed) word/longword access is also not the root cause it must be somewhere else, and disabling the DMA by writing to CCR cannot be it. Also Errata Sheet for STM32F103 says nothing about DMA, so I guess we are save there.

When I have complete code for a simple example I am willing to run that code through the debugger, but it does not make sense when bits and peaces are missing. And please keep the code simple, include the minimum code needed to successfully do the job.
Title: Re: stm32f103 dma problem
Post by: kupferstecher on July 16, 2020, 12:05:29 pm
Code: Pascal  [Select][+][-]
  1.  Usart1.CR1:= 0; //disable usart1
  2.  Usart1.CR1:= Usart1.CR1 or %00000000001100;
  3.  Usart1.CR2:= 0;
  4.  Usart1.CR2:= Usart1.CR2 or %000000000000000;
  5.  Usart1.CR3:= 0;
  6.  Usart1.CR3:= Usart1.CR3 or %00010000000;
  7.  

Offtopic, but may be helpful: Once I translated the bit definitions to pascal, see attached file.
Title: Re: stm32f103 dma problem
Post by: Laksen on July 16, 2020, 01:05:45 pm
With the original code, when you say that it hangs how do you mean? Have you tried installing fault handlers?

Also what compiler version are you using? Trunk?
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 16, 2020, 02:59:06 pm
hi

thanks for replys

lazarus 2.1.0 fpc 3.3.1 on win10 64

this is the code

Code: Pascal  [Select][+][-]
  1.  
  2. program torque_vfd_comm;
  3.  
  4. uses cortexm3, stm32f103fw;
  5.  
  6. const
  7.   TIM_CR1_CEN : uInt16 = $0001;            // Counter enable
  8.   RCC_APB1ENR_TIM2EN : uInt32 = $00000001; // TIM2 clock enabled
  9.  
  10.   TIM_DIER_CC1IE : uInt16 = $0002;         // Capture / Compare 1 interrupt enable
  11.   TIM_SR_CC1IF : uInt16 = $0002;           // Capture / Compare 1 interrupt flag
  12.   TIM2_IRQn = 28;                          // TIM2 global interrupt
  13.  
  14.   systick_counter_enable = 1;
  15.   CTRL_TICKINT_Set = 2;
  16.   Systick_IRQn = -1;
  17.  
  18.   RCC_CR_PLLON = $01000000;
  19.   RCC_CR_CSSON = $00080000;
  20.   RCC_CR_HSEON = $00010000;
  21.   RCC_CR_HSION = $00000001;
  22.   RCC_CFGR_USBPRE = $00400000;
  23.   RCC_CFGR_PLLMULL6 = $00100000;
  24.   RCC_CFGR_PLLSRC = $00010000;
  25.   RCC_CFGR_ADCPRE_DIV4 = $00004000;
  26.   RCC_CFGR_HPRE_DIV2 = $0000008;
  27.   RCC_CFGR_SWS_PLL = $00000008;
  28.   RCC_CFGR_SW_PLL = $00000002;
  29.   RCC_CR_HSERDY = $00020000;
  30.   RCC_CR_HSIRDY = $00000002;
  31.   RCC_CR_PLLRDY = $02000000;
  32.   USART_RE =    $00000004;
  33.   USART_TE =    $00000008;
  34.   USART_IDLEIE = $00000010;
  35.   USART_RXNEIE = $00000020;
  36.   USART_TCIE =   $00000040;
  37.   USART_TXIE =   $00000080;
  38.   USART_PEIE =   $00000100;
  39.   USART_UE =     $00002000;
  40.   USART_DMAT =   $00000080;
  41.   USART_DMAR =   $00000040;
  42.  
  43.   Marcha_OUT =      $0001;
  44.   Para_OUT =        $0002;
  45.   Sentido_OUT =     $0004;
  46.   Marcha_local =    $0010;
  47.   Para_Local =      $0020;
  48.   Sentido_Local =   $0040;
  49.   Marcha_Remoto =   $0100;
  50.   Para_Remoto =     $0200;
  51.   Sentido_Remoto =  $0400;
  52.   Remoto_Local =    $8000; //1= remoto
  53.   Serial_buffer_size = 64;
  54.  
  55.  
  56.  
  57.  
  58.  
  59. {$O-}
  60.  
  61.  
  62. Type
  63.   TLed = bitpacked array[0..15] of boolean;
  64.  
  65.  
  66.  
  67. var                          
  68. PuertoA : TLed absolute PortA.ODR;
  69. PuertoB : TLed absolute PortB.ODR;
  70. PuertoC : TLed absolute PortC.ODR;
  71. PuertoD : TLed absolute PortD.ODR;
  72. LedC : TLed absolute PortC.ODR;
  73. contador: word;
  74. contador2,
  75. contador3: word;
  76. cuenta_max: word = 20;
  77. subiendo: boolean = true;
  78. PUsart: ^TUSARTRegisters;
  79. PDMARegisters : ^LongWord;
  80. RXBuffer1: Array [0..Serial_buffer_size-1] of byte;
  81. TXBuffer1: Array [0..Serial_buffer_size-1] of byte;
  82. RXBuffer2: Array [0..Serial_buffer_size-1] of byte;
  83. TXBuffer2: Array [0..Serial_buffer_size-1] of byte;
  84. RXBuffer3: Array [0..Serial_buffer_size-1] of byte;
  85. TXBuffer3: Array [0..Serial_buffer_size-1] of byte;
  86. ADC1Buffer: Array[0..4] of word;
  87. RPM : word;
  88. RPM_1,
  89. RPM_2,
  90. Presion_1,
  91. Presion_2,
  92. Temperatura_1,
  93. Temperatura_2,
  94. Caudal_1,
  95. Caudal_2,
  96. IO_Bits,
  97. Contador_tick_segundos: word;
  98. marca: Boolean;
  99. i: Longword;
  100. Usart_ini: TUSART_InitTypeDef;
  101. NVIC_Ini: TNVIC_InitTypeDef;
  102. ADC_Ini: TADC_InitTypeDef;
  103. I2C_Ini: TI2CRegisters;
  104. TIMER_Ini: TIM_TimeBaseInitTypeDef;
  105. Timer_OC_INI: TIM_OCInitTypeDef;
  106. Timer_IC_INI: TIM_ICInitTypeDef;
  107. GPIOx: TPortRegisters;
  108. GPIO_InitStruct: TGPIO_InitTypeDef;
  109. DMAChannel: TDMAChannel;
  110. DMA_InitTypeDef: TDMA_InitTypeDef;
  111. DMARegisters: TDMARegisters;
  112. tmpreg: longword;
  113. RCC_Clocks: TRCC_ClocksTypeDef;
  114. PByte: ^Byte;
  115. AUX_B: Byte;  
  116.  
  117. procedure SysTick_interrupt; public name 'SysTick_interrupt';  interrupt;
  118. begin       // 1 ms!!
  119. inc (contador3);
  120. If contador3 >= 100 then    //0.1 s
  121.   begin
  122.   marca:= true;
  123.   contador3:= 0;
  124.   end;
  125. end;
  126.  
  127. procedure Timer2_Interrupt; public name 'TIM2_global_interrupt';  interrupt;
  128.   begin
  129.     TIMER2.SR  := TIMER2.SR and not TIM_SR_CC1IF; // Clear CC1IF
  130.  
  131.   end;
  132.  
  133.  
  134. procedure DMA1_Channel1_global_interrupt; public name 'DMA1_Channel1_global_interrupt';  interrupt;
  135. Begin    
  136.     dmaregisters.ifcr:= $0FFFFFFF;
  137.  
  138. end;
  139.  
  140. procedure DMA1_Channel2_global_interrupt; public name 'DMA1_Channel2_global_interrupt';  interrupt;
  141. Begin
  142.       dmaregisters.ifcr:= $0FFFFFFF;
  143. end;
  144.  
  145. procedure DMA1_Channel3_global_interrupt; public name 'DMA3_Channel1_global_interrupt';  interrupt;
  146. Begin
  147.        dmaregisters.ifcr:= $0FFFFFFF;
  148. end;
  149.  
  150. procedure DMA1_Channel4_global_interrupt;  public name 'DMA4_Channel1_global_interrupt';  interrupt;
  151. Begin
  152.     dmaregisters.ifcr:= $0FFFFFFF;
  153. end;
  154.  
  155. procedure DMA1_Channel5_global_interrupt; public name 'DMA5_Channel1_global_interrupt';  interrupt;
  156. Begin
  157.     dmaregisters.ifcr:= $0FFFFFFF;
  158. end;
  159.  
  160. procedure DMA1_Channel6_global_interrupt; public name 'DMA6_Channel1_global_interrupt';  interrupt;
  161. Begin
  162.       dmaregisters.ifcr:= $0FFFFFFF;
  163. end;
  164.  
  165. procedure DMA1_Channel7_global_interrupt;  public name 'DMA7_Channel1_global_interrupt';  interrupt;
  166. Begin
  167.     dmaregisters.ifcr:= $0FFFFFFF;
  168. end;
  169.  
  170. procedure ADC1_and_ADC2_global_interrupt;  public name 'ADC1_and_ADC2_global_interrupt';  interrupt;
  171. Begin
  172.    dmaregisters.ifcr:= $0FFFFFFF;
  173. end;
  174.  
  175. begin
  176.  
  177.  //************************************************
  178.  //**************** RCC  *************************
  179.  //FLASH_SetLatency(1);
  180.  RCC_HSICmd(Enabled);
  181.  RCC_DeInit;
  182.  RCC_HSICmd(Enabled);
  183.  RCC_HSEConfig(RCC_HSE_On);
  184.  RCC_WaitForHSEStartUp;
  185.  RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6); //48MHz
  186.  RCC_PLLCmd(Enabled);
  187.    while rcc.cr and  RCC_CR_PLLRDY = 0 do
  188.     begin
  189.     //wait pll ready
  190.     end;
  191.  RCC_HCLKConfig(RCC_SYSCLK_Div1);
  192.  RCC_PCLK1Config(RCC_HCLK_Div2); //24MHz
  193.  RCC_PCLK2Config(RCC_HCLK_Div1); //48MHz
  194.  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
  195.  while RCC_GetSYSCLKSource <> %1000 do //(RCC_SYSCLKSource_PLLCLK shl 2)
  196.    begin
  197.    //wait pll source
  198.    end;
  199.  RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1 or RCC_AHBPeriph_DMA2 or RCC_AHBPeriph_SRAM or RCC_AHBPeriph_FLITF, Enabled);
  200.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, Enabled);
  201.  //RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, Disabled);
  202.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, Enabled);
  203.  //RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 or RCC_APB1Periph_I2C2 or RCC_APB1Periph_CAN, Disabled);
  204.  RCC_ADCCLKConfig(RCC_HCLK_Div2);  //12 MHz
  205.  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1); //48MHz
  206.  RCC_ClockSecuritySystemCmd(Enabled);
  207.  RCC_GetClocksFreq(RCC_Clocks);
  208.  
  209. //************************************************
  210. //**************** GPIO  *************************
  211.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_0;  //RPM TIM2_1 input1
  212.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  213.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  214.   GPIO_Init(PortA, GPIO_InitStruct);
  215.  
  216.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_1; //RTS USART2
  217.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  218.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  219.   GPIO_Init(PortA, GPIO_InitStruct);
  220.  
  221.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_2; //TX USART2
  222.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  223.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  224.   GPIO_Init(PortA, GPIO_InitStruct);
  225.  
  226.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_3; //RX USART2
  227.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  228.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  229.   GPIO_Init(PortA, GPIO_InitStruct);
  230.  
  231.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_4; //ADC
  232.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AIN;
  233.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  234.   GPIO_Init(PortA, GPIO_InitStruct);
  235.  
  236.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_5; //ADC
  237.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AIN;
  238.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  239.   GPIO_Init(PortA, GPIO_InitStruct);
  240.  
  241.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_6; //ADC
  242.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AIN;
  243.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  244.   GPIO_Init(PortA, GPIO_InitStruct);
  245.  
  246.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_7; //ADC
  247.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AIN;
  248.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  249.   GPIO_Init(PortA, GPIO_InitStruct);
  250.  
  251.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_8;//para_local_in
  252.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  253.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  254.   GPIO_Init(PortA, GPIO_InitStruct);
  255.  
  256.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_9; //TX USART1
  257.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  258.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  259.   GPIO_Init(PortA, GPIO_InitStruct);
  260.  
  261.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_10; //RX USART1
  262.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  263.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  264.   GPIO_Init(PortA, GPIO_InitStruct);
  265.  
  266.   //11 usb
  267.   //12 usb
  268.   //13 swdio
  269.   //14 swclk
  270.  
  271.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_15; //marcha_local_in
  272.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  273.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  274.   GPIO_Init(PortA, GPIO_InitStruct);
  275.  
  276.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_0; //ADC aux
  277.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AIN;
  278.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  279.   GPIO_Init(PortB, GPIO_InitStruct);
  280.  
  281.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_1; //rpm timer3_4
  282.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  283.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  284.   GPIO_Init(PortB, GPIO_InitStruct);
  285.  
  286.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_2;//BOOT1
  287.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  288.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  289.   GPIO_Init(PortB, GPIO_InitStruct);
  290.    
  291.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_3;//Sentido_local_in
  292.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  293.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  294.   GPIO_Init(PortB, GPIO_InitStruct);
  295.  
  296.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_4;//Marcha_OUT
  297.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_Out_PP;
  298.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  299.   GPIO_Init(PortB, GPIO_InitStruct);
  300.  
  301.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_5;//Para_OUT
  302.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_Out_PP;
  303.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  304.   GPIO_Init(PortB, GPIO_InitStruct);
  305.  
  306.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_6;//RPM TIMER4_1
  307.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  308.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  309.   GPIO_Init(PortB, GPIO_InitStruct);
  310.  
  311.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_7;//Sentido_OUT
  312.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_Out_PP;
  313.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  314.   GPIO_Init(PortB, GPIO_InitStruct);
  315.  
  316.   GPIO_PinRemapConfig(GPIO_Remap_I2C1, enabled);
  317.  
  318.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_8;//I2C1 SCL
  319.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_OD;
  320.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  321.   GPIO_Init(PortB, GPIO_InitStruct);
  322.  
  323.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_9;//I2C1 SDA
  324.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_OD;
  325.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  326.   GPIO_Init(PortB, GPIO_InitStruct);
  327.  
  328.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_10; //TX USART3
  329.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  330.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  331.   GPIO_Init(PortB, GPIO_InitStruct);
  332.  
  333.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_11; //RX USART3
  334.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_IPU;
  335.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  336.   GPIO_Init(PortB, GPIO_InitStruct);
  337.  
  338.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_12;//Aux_OUT
  339.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  340.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  341.   GPIO_Init(PortB, GPIO_InitStruct);
  342.  
  343.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_13; //PWM OUT 1
  344.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  345.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  346.   GPIO_Init(PortB, GPIO_InitStruct);
  347.  
  348.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_14; //PWM OUT 2
  349.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  350.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  351.   GPIO_Init(PortB, GPIO_InitStruct);
  352.  
  353.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_15; //PWM OUT 3
  354.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  355.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  356.   GPIO_Init(PortB, GPIO_InitStruct);
  357.  
  358.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_13; //led interno
  359.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_Out_PP;
  360.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  361.   GPIO_Init(PortC, GPIO_InitStruct);
  362.  
  363. //************************************************
  364. //**************** USART *************************
  365.  
  366.  Usart_ini.USART_BaudRate:= 9600;
  367.  Usart_ini.USART_WordLength:= USART_WordLength_8b;
  368.  Usart_ini.USART_StopBits:= USART_StopBits_1;
  369.  Usart_ini.USART_Parity:= USART_Parity_No ;
  370.  Usart_ini.USART_Mode:= USART_Mode_Rx or USART_Mode_Tx;
  371.  Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_None;
  372.  Usart_ini.USART_Clock:= USART_Clock_Disable;
  373.  Usart_ini.USART_CPOL:= USART_CPOL_Low;
  374.  Usart_ini.USART_CPHA:= USART_CPHA_1Edge;
  375.  Usart_ini.USART_LastBit:= USART_LastBit_Disable;
  376.  USART_Init(USart1, Usart_ini);
  377.  USART_Init(USart3, Usart_ini);
  378.  Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_RTS;
  379.  USART_Init(USart2, Usart_ini);
  380.  
  381.  USART_DMACmd(Usart1,USART_DMAReq_Tx  or USART_DMAReq_Rx ,Enabled);
  382.  USART_DMACmd(Usart2,USART_DMAReq_Tx  or USART_DMAReq_Rx ,Enabled);
  383.  USART_DMACmd(Usart3,USART_DMAReq_Tx  or USART_DMAReq_Rx ,Enabled);
  384.  USART_ITConfig(Usart1, USART_IT_TC , enabled);                      
  385.  USART_ITConfig(Usart2, USART_IT_TC , enabled);
  386.  USART_ITConfig(Usart3, USART_IT_TC , enabled);
  387.  Usart_Cmd(Usart1, ENABLED);
  388.  Usart_Cmd(Usart2, ENABLED);
  389.  Usart_Cmd(Usart3, ENABLED);  
  390.  
  391. //************************************************
  392.  //**************** NVIC **************************
  393.   NVIC_Ini.NVIC_IRQChannelPreemptionPriority:= 0;
  394.   NVIC_Ini.NVIC_IRQChannelSubPriority:= 0;
  395.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel1_IRQChannel;
  396.   NVIC_Init(NVIC_Ini);
  397.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel2_IRQChannel;
  398.   NVIC_Init(NVIC_Ini);
  399.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel3_IRQChannel;
  400.   NVIC_Init(NVIC_Ini);
  401.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel4_IRQChannel;
  402.   NVIC_Init(NVIC_Ini);
  403.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel5_IRQChannel;
  404.   NVIC_Init(NVIC_Ini);
  405.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel6_IRQChannel;
  406.   NVIC_Init(NVIC_Ini);
  407.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel7_IRQChannel;
  408.   NVIC_Init(NVIC_Ini);
  409.   NVIC_Ini.NVIC_IRQChannelCmd:= Enabled;  
  410.  
  411. //***************************************************
  412.   //******************** Systick **********************
  413.   Systick.LOAD:= 6000;   // 1ms main loop
  414.   SysTick.CTRL := SysTick.CTRL or CTRL_TICKINT_Set AND (not 4);// interrupt, AHB/8
  415.   SysTick.CTRL := SysTick.CTRL or systick_counter_enable ; //enabled
  416.  
  417.   contador:= cuenta_max - 2;
  418.  
  419.   TXBuffer1[0]:= byte('h');
  420.   TXBuffer1[1]:= byte('e');
  421.   TXBuffer1[2]:= byte('l');
  422.   TXBuffer1[3]:= byte('l');
  423.   TXBuffer1[4]:= byte('o');
  424.    
  425.  
  426.  tmpreg:= longWord(@DMA1.Channel[2].CCR);
  427.    AUX_B:= Byte((tmpreg AND $000000FF));
  428.    TXBuffer1[5]:= AUX_B;
  429.    AUX_B:= Byte((tmpreg  AND $0000FF00) shr 8);
  430.    TXBuffer1[6]:= AUX_B;
  431.    AUX_B:= Byte((tmpreg  AND $00FF0000) shr 16);
  432.    TXBuffer1[7]:= AUX_B;
  433.    AUX_B:= Byte((tmpreg  AND $FF000000) shr 24);
  434.    TXBuffer1[8]:= AUX_B;
  435.    tmpreg:= longWord(@DMA1.Channel[2].res1);
  436.    AUX_B:= Byte((tmpreg AND $000000FF));
  437.    TXBuffer1[9]:= AUX_B;
  438.    AUX_B:= Byte((tmpreg  AND $0000FF00) shr 8);
  439.    TXBuffer1[10]:= AUX_B;
  440.    AUX_B:= Byte((tmpreg  AND $00FF0000) shr 16);
  441.    TXBuffer1[11]:= AUX_B;
  442.    AUX_B:= Byte((tmpreg  AND $FF000000) shr 24);
  443.    TXBuffer1[12]:= AUX_B;
  444.    tmpreg:= longWord(@DMA1.Channel[2].CNDTR);
  445.    AUX_B:= Byte((tmpreg AND $000000FF));
  446.    TXBuffer1[13]:= AUX_B;
  447.    AUX_B:= Byte((tmpreg  AND $0000FF00) shr 8);
  448.    TXBuffer1[14]:= AUX_B;
  449.    AUX_B:= Byte((tmpreg  AND $00FF0000) shr 16);
  450.    TXBuffer1[15]:= AUX_B;
  451.    AUX_B:= Byte((tmpreg  AND $FF000000) shr 24);
  452.    TXBuffer1[16]:= AUX_B;
  453.    tmpreg:= longWord(@DMA1.Channel[2].res2);
  454.    AUX_B:= Byte((tmpreg AND $000000FF));
  455.    TXBuffer1[17]:= AUX_B;
  456.    AUX_B:= Byte((tmpreg  AND $0000FF00) shr 8);
  457.    TXBuffer1[18]:= AUX_B;
  458.    AUX_B:= Byte((tmpreg  AND $00FF0000) shr 16);
  459.    TXBuffer1[19]:= AUX_B;
  460.    AUX_B:= Byte((tmpreg  AND $FF000000) shr 24);
  461.    TXBuffer1[20]:= AUX_B;
  462.  
  463.  PDMARegisters := @DMA1 + $44;   //CCR4
  464.  PDMARegisters^:= %000000010110110;
  465.  PDMARegisters := @DMA1 + $48;   //CNDTR4
  466.  PDMARegisters^:= 22;
  467.  PDMARegisters := @DMA1 + $4C;   //CPAR4
  468.  PDMARegisters^:= LongWord(@Usart1.DR);
  469.  PDMARegisters := @DMA1 + $50;   //CMAR4
  470.  PDMARegisters^:= LongWord(@TXBuffer1);
  471.  Usart1.SR:= Usart1.SR and not %1000000;
  472.  PDMARegisters := @DMA1 + $44;   //CCR4
  473.  PDMARegisters^:= PDMARegisters^ or %1;   //enable
  474.  
  475.  PDMARegisters := @DMA1 + $80;   //CCR7
  476.  PDMARegisters^:= %000000010110110;
  477.  PDMARegisters := @DMA1 + $84;   //CNDTR7
  478.  PDMARegisters^:= 5;
  479.  PDMARegisters := @DMA1 + $88;   //CPAR7
  480.  PDMARegisters^:= LongWord(@Usart2.DR);
  481.  PDMARegisters := @DMA1 + $8c;   //CMAR7
  482.  PDMARegisters^:= LongWord(@TXBuffer2);
  483.  Usart2.SR:= Usart2.SR and not %1000000;
  484.  PDMARegisters := @DMA1 + $80;   //CCR7
  485.  PDMARegisters^:= PDMARegisters^ or %1;   //enable
  486.  
  487.  PDMARegisters := @DMA1 + $1C;   //CCR2
  488.  PDMARegisters^:= %000000010110110;
  489.  PDMARegisters := @DMA1 + $20;   //CNDTR2
  490.  PDMARegisters^:= 5;
  491.  PDMARegisters := @DMA1 + $24;   //CPAR2
  492.  PDMARegisters^:= LongWord(@Usart3.DR);
  493.  PDMARegisters := @DMA1 + $28;   //CMAR2
  494.  PDMARegisters^:= LongWord(@TXBuffer3);
  495.  Usart3.SR:= Usart3.SR and not %1000000;
  496.  PDMARegisters := @DMA1 + $1C;   //CCR2
  497.  PDMARegisters^:= PDMARegisters^ or %1;   //enable  
  498.  
  499.  while true do
  500.     begin
  501.   //RPM:= 60000 div Usart2.BRR;
  502.   If marca then
  503.     begin
  504.     marca:= False;
  505.     Inc(Contador);
  506.     Inc(Contador_tick_Segundos);
  507.     If Contador_tick_segundos >= 10 then
  508.         begin
  509.         Contador_tick_segundos:= 0;
  510.         PuertoB[4]:= Not PuertoB[4];
  511.         PuertoB[5]:= Not PuertoB[5];
  512.         PuertoB[7]:= Not PuertoB[7];
  513.         end;
  514.     //if contador and 01 = 0 then LedC[13] := not LedC[13] else LedC[13] := true;
  515.     if contador <= contador2 then LedC[13] := not LedC[13] else LedC[13] := true;
  516.     if contador >= cuenta_Max then
  517.       begin
  518.       contador := 0;
  519.       if subiendo then contador2 += 2 else contador2 -= 2;
  520.       if contador2 > Cuenta_max then subiendo:= false;
  521.       if contador2 = 0 then subiendo:= true;
  522.       end;
  523.     end;
  524.  
  525.  
  526.     end;
  527.  end.
  528.  
  529.  

but i think enabling, isr and all these are ok, because it work when i use bare metal code, then all the rest of code must be ok

look the attached image in previous post, was captured using logic analizer on usart1 output pin

again, thanks
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 16, 2020, 03:06:22 pm
With the original code, when you say that it hangs how do you mean? Have you tried installing fault handlers?

Also what compiler version are you using? Trunk?

my code make a blink in the internal led, but in a increasin and decreasing amount of blink fashion.

when i said it hangs, i mean led is allways on!!

Have you tried installing fault handlers? -> i thinking about it. not yet

Also what compiler version are you using? Trunk?-> 2.1.0 fpc 3.3.1 win10 64
Title: Re: stm32f103 dma problem
Post by: Laksen on July 16, 2020, 04:02:38 pm
Yeah it's probably stuck in a hardfault handler

Try adding:
Code: Pascal  [Select][+][-]
  1. SCB.SHCSR := SCB.SHCSR or (7 shl $10);

and

Code: Pascal  [Select][+][-]
  1. procedure hard_fault_handler_c(p: plongword; lr: longword);
  2. begin
  3.   writeln('Hardfault');
  4.   writeln(' R0:  ', hexstr(p[0], 8));
  5.   writeln(' R1:  ', hexstr(p[1], 8));
  6.   writeln(' R2:  ', hexstr(p[2], 8));
  7.   writeln(' R3:  ', hexstr(p[3], 8));
  8.  
  9.   writeln(' R12: ', hexstr(p[4], 8));
  10.   writeln(' LR:  ', hexstr(p[5], 8));
  11.   writeln(' PC:  ', hexstr(p[6], 8));
  12.   writeln(' PSR: ', hexstr(p[7], 8));
  13.  
  14.   writeln(' LR:  ', hexstr(lr, 8));
  15.   while true do;
  16. end;
  17.  
  18. procedure Hardfault_interrupt; assembler; nostackframe; [public, alias: 'Hardfault_interrupt'];
  19. asm
  20.   tst lr, #4
  21.   mov r1, lr
  22.   ite eq
  23.   mrseq r0, msp
  24.   mrsne r0, psp
  25.   b hard_fault_handler_c
  26. end;
  27.  
  28. procedure MemManage_interrupt_C(p: plongword; ALR: longword);
  29. begin
  30.   writeln('MemManage_interrupt');
  31.   writeln(' LR:  ', hexstr(p[5], 8));
  32.   writeln(' PC:  ', hexstr(p[6], 8));
  33.  
  34.   writeln(' MMFSR: ', hexstr(scb.CFSR and $FF, 8));
  35.   writeln(' MMFAR: ', hexstr(scb.MMFAR, 8));
  36.  
  37.   while true do;
  38. end;
  39.  
  40. procedure MemManage_interrupt; assembler; nostackframe; [public, alias: 'MemManage_interrupt'];
  41. asm
  42.   tst lr, #4
  43.   mov r1, lr
  44.   ite eq
  45.   mrseq r0, msp
  46.   mrsne r0, psp
  47.   b MemManage_interrupt_c
  48. end;
  49.  
  50. procedure BusFault_interrupt_C(p: plongword; ALR: longword);
  51. begin
  52.   writeln('BusFault');                  
  53.   writeln(' LR:  ', hexstr(p[5], 8));
  54.   writeln(' PC:  ', hexstr(p[6], 8));
  55.  
  56.   writeln(' BFAR: ', hexstr(scb.BFAR, 8));
  57.   while true do;
  58. end;
  59.  
  60. procedure BusFault_interrupt; assembler; nostackframe; [public, alias: 'BusFault_interrupt'];
  61. asm
  62.   tst lr, #4
  63.   mov r1, lr
  64.   ite eq
  65.   mrseq r0, msp
  66.   mrsne r0, psp
  67.   b BusFault_interrupt_C
  68. end;
  69.  
  70. procedure UsageFault_interrupt_C(p: plongword; ALR: longword);
  71. begin
  72.   writeln('UsageFault');
  73.   writeln(' LR:  ', hexstr(p[5], 8));
  74.   writeln(' PC:  ', hexstr(p[6], 8));
  75.   writeln(' UFSR: ', hexstr(SCB.CFSR shr 16, 4));
  76.   while true do;
  77. end;
  78.  
  79. procedure UsageFault_interrupt; assembler; nostackframe; [public, alias: 'UsageFault_interrupt'];
  80. asm
  81.   tst lr, #4
  82.   mov r1, lr
  83.   ite eq
  84.   mrseq r0, msp
  85.   mrsne r0, psp
  86.   b UsageFault_interrupt_C
  87. end;
  88.  

That should give you a good idea about what's going on.
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 16, 2020, 05:01:50 pm
Yeah it's probably stuck in a hardfault handler

Try adding:
Code: Pascal  [Select][+][-]
  1. SCB.SHCSR := SCB.SHCSR or (7 shl $10);

and

Code: Pascal  [Select][+][-]
  1. procedure hard_fault_handler_c(p: plongword; lr: longword);
  2. begin
  3.   writeln('Hardfault');
  4.   writeln(' R0:  ', hexstr(p[0], 8));
  5.   writeln(' R1:  ', hexstr(p[1], 8));
  6.   writeln(' R2:  ', hexstr(p[2], 8));
  7.   writeln(' R3:  ', hexstr(p[3], 8));
  8.  
  9.   writeln(' R12: ', hexstr(p[4], 8));
  10.   writeln(' LR:  ', hexstr(p[5], 8));
  11.   writeln(' PC:  ', hexstr(p[6], 8));
  12.   writeln(' PSR: ', hexstr(p[7], 8));
  13.  
  14.   writeln(' LR:  ', hexstr(lr, 8));
  15.   while true do;
  16. end;
  17.  
  18. procedure Hardfault_interrupt; assembler; nostackframe; [public, alias: 'Hardfault_interrupt'];
  19. asm
  20.   tst lr, #4
  21.   mov r1, lr
  22.   ite eq
  23.   mrseq r0, msp
  24.   mrsne r0, psp
  25.   b hard_fault_handler_c
  26. end;
  27.  
  28. procedure MemManage_interrupt_C(p: plongword; ALR: longword);
  29. begin
  30.   writeln('MemManage_interrupt');
  31.   writeln(' LR:  ', hexstr(p[5], 8));
  32.   writeln(' PC:  ', hexstr(p[6], 8));
  33.  
  34.   writeln(' MMFSR: ', hexstr(scb.CFSR and $FF, 8));
  35.   writeln(' MMFAR: ', hexstr(scb.MMFAR, 8));
  36.  
  37.   while true do;
  38. end;
  39.  
  40. procedure MemManage_interrupt; assembler; nostackframe; [public, alias: 'MemManage_interrupt'];
  41. asm
  42.   tst lr, #4
  43.   mov r1, lr
  44.   ite eq
  45.   mrseq r0, msp
  46.   mrsne r0, psp
  47.   b MemManage_interrupt_c
  48. end;
  49.  
  50. procedure BusFault_interrupt_C(p: plongword; ALR: longword);
  51. begin
  52.   writeln('BusFault');                  
  53.   writeln(' LR:  ', hexstr(p[5], 8));
  54.   writeln(' PC:  ', hexstr(p[6], 8));
  55.  
  56.   writeln(' BFAR: ', hexstr(scb.BFAR, 8));
  57.   while true do;
  58. end;
  59.  
  60. procedure BusFault_interrupt; assembler; nostackframe; [public, alias: 'BusFault_interrupt'];
  61. asm
  62.   tst lr, #4
  63.   mov r1, lr
  64.   ite eq
  65.   mrseq r0, msp
  66.   mrsne r0, psp
  67.   b BusFault_interrupt_C
  68. end;
  69.  
  70. procedure UsageFault_interrupt_C(p: plongword; ALR: longword);
  71. begin
  72.   writeln('UsageFault');
  73.   writeln(' LR:  ', hexstr(p[5], 8));
  74.   writeln(' PC:  ', hexstr(p[6], 8));
  75.   writeln(' UFSR: ', hexstr(SCB.CFSR shr 16, 4));
  76.   while true do;
  77. end;
  78.  
  79. procedure UsageFault_interrupt; assembler; nostackframe; [public, alias: 'UsageFault_interrupt'];
  80. asm
  81.   tst lr, #4
  82.   mov r1, lr
  83.   ite eq
  84.   mrseq r0, msp
  85.   mrsne r0, psp
  86.   b UsageFault_interrupt_C
  87. end;
  88.  

That should give you a good idea about what's going on.

thank you! ill try

but i must assign writeln to the usart1  or stdout or something like that

again thanks for your time
Title: Re: stm32f103 dma problem
Post by: MiR on July 17, 2020, 09:55:15 am
I checked your code this morning, here's what I found:

You activate far more peripherals than you actually need which is bad for power consumption and can cause nice side effects when you experiment in different places. Tons of boilerplate code distract and you easily miss something important which I guess you did:

The thing that is wrong is that you have enabled transmission complete interrupts for uart and have no interrupt handlers for uart, this is the likely cause that your app crashes, has very little to do with DMA.

When using DMA then interrupts for serial should be turned off as the DMA controller takes over to handle the peripheral.

There is one exception which has to do with receiving in DMA Mode when you do not know how much data you actually will receive, please look at this very good article:

https://stm32f4-discovery.net/2017/07/stm32-tutorial-efficiently-receive-uart-data-using-dma/

What I absolutely not understand is why you put on the burden of using DMA at all for communication with a VFD at 9600 Baud.

Sending data via DMA is one thing, it is elegant and uses close to no CPU but receiving (unknown length) results via DMA is a real pain.

For Baudrates as low as 9600 using interrupts for Serial is a lot more straightforward and good enough to get the job done.

Michael
Title: Re: stm32f103 dma problem
Post by: 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  [Select][+][-]
  1. program torque_vfd_comm;
  2.  
  3. uses cortexm3, stm32f103fw;
  4. {$O-}
  5.  
  6. const
  7.   Serial_buffer_size = 7;
  8.   DMA_CHANNEL4 = 3;
  9.   PERIPH_BASE   = $40000000;
  10.   AHBPERIPH_BASE= PERIPH_BASE + $00020000;
  11.   DMA1_Channel4_BASE= AHBPERIPH_BASE + $00000044;
  12.  
  13. type
  14.   TDMA_Channel_Registers = record
  15.     CCR         : longword;
  16.     CNDTR       : longword;
  17.     CPAR        : longword;
  18.     CMAR        : longword;
  19.   end;
  20.  
  21. var
  22.   TXBuffer1: Array [0..Serial_buffer_size-1] of byte;
  23.   Usart_ini: TUSART_InitTypeDef;
  24.   NVIC_Ini: TNVIC_InitTypeDef;
  25.   GPIO_InitStruct: TGPIO_InitTypeDef;
  26.   RCC_Clocks: TRCC_ClocksTypeDef;
  27.   DMA1_Channel4 : TDMA_Channel_Registers absolute DMA1_Channel4_BASE;
  28.   i : integer;
  29.  
  30. procedure DMA1_Channel4_global_interrupt;  public name 'DMA4_Channel1_global_interrupt';  interrupt;
  31. Begin
  32.   dma1.ifcr:= $0FFFFFFF;
  33. end;
  34.  
  35. procedure USART1_SendBytesViaDMA(var Data : array of byte; const count : integer = -1);
  36. begin
  37.   //Disable DMA, Transfer Complete IRQ Read from Memory No Circular Mode No Periph Inc Memory Inc 8bit periph 8bit mem prio0
  38.   DMA1_Channel4.CCR := %000000010010010;
  39.   if count=-1 then
  40.     DMA1_Channel4.CNDTR := High(Data)+1
  41.   else
  42.     DMA1_Channel4.CNDTR := Count;
  43.   DMA1_Channel4.CPAR :=  LongWord(@Usart1.DR);
  44.   DMA1_Channel4.CMAR := LongWord(@Data);
  45.   DMA1_Channel4.CCR := DMA1_Channel4.CCR or %1;   //enable
  46. end;
  47.  
  48. begin
  49.   //************************************************
  50.   //**************** RCC  *************************
  51.   //FLASH_SetLatency(1);
  52.   RCC_HSICmd(Enabled);
  53.   RCC_DeInit;
  54.   RCC_HSICmd(Enabled);
  55.   //For simplicity run on 8MHz internal Clock
  56.   RCC_HCLKConfig(RCC_SYSCLK_Div1);
  57.   RCC_PCLK1Config(RCC_HCLK_Div2); //24MHz
  58.   RCC_PCLK2Config(RCC_HCLK_Div1); //48MHz
  59.   RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1 or RCC_AHBPeriph_SRAM or RCC_AHBPeriph_FLITF, Enabled);
  60.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, Enabled);
  61.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, Enabled);
  62.   RCC_GetClocksFreq(RCC_Clocks);
  63.  
  64.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_9; //TX USART1
  65.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  66.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  67.   GPIO_Init(PortA, GPIO_InitStruct);
  68.  
  69.   //************************************************
  70.   //**************** USART *************************
  71.  
  72.   Usart_ini.USART_BaudRate:= 9600;
  73.   Usart_ini.USART_WordLength:= USART_WordLength_8b;
  74.   Usart_ini.USART_StopBits:= USART_StopBits_1;
  75.   Usart_ini.USART_Parity:= USART_Parity_No;
  76.   Usart_ini.USART_Mode:= USART_Mode_Tx;
  77.   Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_None;
  78.   Usart_ini.USART_Clock:= USART_Clock_Disable;
  79.   Usart_ini.USART_CPOL:= USART_CPOL_Low;
  80.   Usart_ini.USART_CPHA:= USART_CPHA_1Edge;
  81.   Usart_ini.USART_LastBit:= USART_LastBit_Disable;
  82.   USART_Init(USart1, Usart_ini);
  83.  
  84.   USART_DMACmd(Usart1,USART_DMAReq_Tx,Enabled);
  85.  
  86.   Usart_Cmd(Usart1, ENABLED);
  87.  
  88.   //************************************************
  89.   //**************** NVIC **************************
  90.   NVIC_Ini.NVIC_IRQChannelPreemptionPriority:= 0;
  91.   NVIC_Ini.NVIC_IRQChannelSubPriority:= 0;
  92.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel4_IRQChannel;
  93.   NVIC_Init(NVIC_Ini);
  94.   NVIC_Ini.NVIC_IRQChannelCmd := Enabled;
  95.  
  96.   TXBuffer1[0] := byte('h');
  97.   TXBuffer1[1] := byte('e');
  98.   TXBuffer1[2] := byte('l');
  99.   TXBuffer1[3] := byte('l');
  100.   TXBuffer1[4] := byte('o');
  101.   TXBuffer1[5] := byte(#13);
  102.   TXBuffer1[6] := byte(#10);
  103.  
  104.   while true do
  105.   begin
  106.     USART1_SendBytesViaDMA(TXBuffer1);
  107.     //Quick hack, wait for tramsfer done....
  108.     repeat
  109.     until DMA1_Channel4.CNDTR = 0;
  110.     //now waste some time so that we better see when transfer starts again
  111.     for i := 1 to 100000 do
  112.       ;
  113.  
  114.   end;
  115. end.
  116.  
Title: Re: stm32f103 dma problem
Post by: Laksen on July 17, 2020, 02:00:28 pm
What's the difference in the generated assembly with longword vs word access? The reference manual explicitly states that all the registers can be accessed with either byte, halfword or word accesses.
Title: Re: stm32f103 dma problem
Post by: MiR on July 17, 2020, 02:08:20 pm
An STRH was created, after changing to 32bit an STR was created which then worked without creating an exception.

What I found strange was that the 16bit write to CCR actually worked with the original headers, only CNDTR had the issue.

By the way, for testing I used a Nucleo-F103RB Board, so my cpu is 100% geniue

Michael
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 17, 2020, 02:49:24 pm
I checked your code this morning, here's what I found:

You activate far more peripherals than you actually need which is bad for power consumption and can cause nice side effects when you experiment in different places. Tons of boilerplate code distract and you easily miss something important which I guess you did:

The thing that is wrong is that you have enabled transmission complete interrupts for uart and have no interrupt handlers for uart, this is the likely cause that your app crashes, has very little to do with DMA.

When using DMA then interrupts for serial should be turned off as the DMA controller takes over to handle the peripheral.

There is one exception which has to do with receiving in DMA Mode when you do not know how much data you actually will receive, please look at this very good article:

https://stm32f4-discovery.net/2017/07/stm32-tutorial-efficiently-receive-uart-data-using-dma/

What I absolutely not understand is why you put on the burden of using DMA at all for communication with a VFD at 9600 Baud.

Sending data via DMA is one thing, it is elegant and uses close to no CPU but receiving (unknown length) results via DMA is a real pain.

For Baudrates as low as 9600 using interrupts for Serial is a lot more straightforward and good enough to get the job done.

Michael

You activate far more peripherals than you actually need which is bad for power consumption and can cause nice side effects when you experiment in different places. Tons of boilerplate code distract and you easily miss something important which I guess you did: -> first i activate only needed peripheral, but after i see the problem, then i activate all, just in case....

What I absolutely not understand is why you put on the burden of using DMA at all for communication with a VFD at 9600 Baud.-> because is my first time with stm32 and just starting to know it. Really i need 3 usart and 1 i2c, at differents speeds and settings. Is just to learn.

now i'll try disabling transmission complete interrupts. but this must not be a problem in the deinit code...i guess,

again a lot of thanks!!!
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 17, 2020, 02:57:13 pm
hi

me again!!

thaks for the support

now i found another problem.

using the bare metal working code posted before, i see nothing on usart3 tx pin (PB10). Usart1 and USART2 works fine!!
Title: Re: stm32f103 dma problem
Post by: MiR on July 17, 2020, 03:07:09 pm
Sorry, cannot read your mind, which code are you talking about, yours or mine?

What I remember from your code is that you enabled Hardware Handshake, no Handshake->no transmit.

You have now a fairly stripped down example from me, when having issues, please create a minimalistic example that only does what needs to be done. Then I (and very likely also others) are happy to help.
Title: Re: stm32f103 dma problem
Post by: MiR on July 17, 2020, 03:22:03 pm
One more issue that I just saw is:
procedure DMA1_Channel3_global_interrupt; public name 'DMA3_Channel1_global_interrupt';  interrupt;
procedure DMA1_Channel4_global_interrupt;  public name 'DMA4_Channel1_global_interrupt';  interrupt;
procedure DMA1_Channel5_global_interrupt; public name 'DMA5_Channel1_global_interrupt';  interrupt;

look at the public names, they are wrong so there is actually no Interrupt Handler Handling anything for those Interrupts.
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 17, 2020, 04:36:07 pm
Sorry, cannot read your mind, which code are you talking about, yours or mine?

What I remember from your code is that you enabled Hardware Handshake, no Handshake->no transmit.

You have now a fairly stripped down example from me, when having issues, please create a minimalistic example that only does what needs to be done. Then I (and very likely also others) are happy to help.

Sorry, cannot read your mind, which code are you talking about, yours or mine?-> mine, sorry

What I remember from your code is that you enabled Hardware Handshake, no Handshake->no transmit.-> Usart1 and USART3 are without handshake. Only on usart2 and its working because i only use rts signal to use an rs485 half duplex line driver , then really don't stop usart work. but remember, only on usart2 and its working. must be another thing

again and again thank you very much
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 20, 2020, 03:49:55 pm
hi

i found the reason o f varios problem i have, even in bare metal way, but now these are solved with the folowing code.

Code: Pascal  [Select][+][-]
  1.  
  2. procedure DMA1_Channel4_global_interrupt;  public name 'DMA1_Channel4_global_interrupt';  interrupt;
  3. Begin
  4.     If DMA1.ISR and (Not DMA1_FLAG_TC4) > 0 then
  5.         begin
  6.         PDMARegisters := @DMA1 + $44;   //CCR4
  7.         PDMARegisters^:= PDMARegisters^ AND not %1;
  8.         end;
  9.     if contador <= contador2 then LedC[13] := not LedC[13] else LedC[13] := true;
  10.     DMA1.IFCR:= DMA1_FLAG_GL4;
  11. end;
  12.  
  13.  
  14.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_10; //TX USART3
  15.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  16.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  17.   GPIO_Init(PortB, GPIO_InitStruct);
  18.  
  19. TXBuffer3[0]:= byte('n');
  20.  TXBuffer3[1]:= byte('o');
  21.  TXBuffer3[2]:= byte(' ');
  22.  TXBuffer3[3]:= byte('s');
  23.  TXBuffer3[4]:= byte('e');
  24.  
  25.  
  26.  PDMARegisters := @DMA1 + $1C;   //CCR2
  27.  PDMARegisters^:= %000000010110110; //minc circ dir htie tcie
  28.  PDMARegisters := @DMA1 + $20;   //CNDTR2
  29.  PDMARegisters^:= 10;
  30.  PDMARegisters := @DMA1 + $24;   //CPAR2
  31.  PDMARegisters^:= LongWord(@Usart3.DR);
  32.  PDMARegisters := @DMA1 + $28;   //CMAR2
  33.  PDMARegisters^:= LongWord(@TXBuffer3);
  34.  
  35.  USART3.BRR:= 5000 shl 4; //9600bps
  36.  Usart3.CR1:= %10000001001000;  //usart enable, TCIE, TE
  37.  Usart3.CR2:=  0;
  38.  Usart3.CR3:= Usart3.CR3 or %10000000; //DMAT
  39.  
  40.  Usart3.SR:= Usart3.SR and (not Usart_flag_tc); //clear TC
  41.  PDMARegisters := @DMA1 + $1C;   //CCR2
  42.  PDMARegisters^:= PDMARegisters^ or %1;   //DMA channel enable
  43.  
  44.   //***************************************************
  45.   //******************** Systick **********************
  46.   Systick.LOAD:= 6000;   // 1ms main loop
  47.   SysTick.CTRL := SysTick.CTRL or CTRL_TICKINT_Set AND (not 4);// interrupt, AHB/8
  48.   SysTick.CTRL := SysTick.CTRL or systick_counter_enable ; //enabled  
  49.  
  50. while true do
  51.     begin
  52.   If marca then
  53.     begin
  54.     marca:= False;
  55.     Inc(Contador);
  56.     Inc(Contador_tick_Segundos);
  57.     If Contador_tick_segundos >= 10 then
  58.         begin
  59.         Contador_tick_segundos:= 0;
  60. //++++++++++++++++++ one second pulse routine +++++++++++
  61.         PDMARegisters := @DMA1 + $1c;   //CCR2
  62.         PDMARegisters^:= %000000010110110; //minc circ dir htie tcie
  63.         PDMARegisters := @DMA1 + $20;   //CNDTR2
  64.         PDMARegisters^:= 10;
  65.         PDMARegisters := @DMA1 + $24;   //CPAR2
  66.         PDMARegisters^:= LongWord(@Usart3.DR);
  67.         PDMARegisters := @DMA1 + $28;   //CMAR2
  68.         PDMARegisters^:= LongWord(@TXBuffer3);
  69.         Usart3.SR:= Usart3.SR and (not usart_flag_tc); //clear TC
  70.         PDMARegisters := @DMA1 + $1C;   //CCR2
  71.         PDMARegisters^:= PDMARegisters^ or %1;   //DMA channel enable
  72.         end;
  73.     //if contador and 01 = 0 then LedC[13] := not LedC[13] else LedC[13] := true;
  74.     //if contador <= contador2 then LedC[13] := not LedC[13] else LedC[13] := true;
  75.     if contador >= cuenta_Max then
  76.       begin
  77.       contador := 0;
  78.       if subiendo then contador2 += 2 else contador2 -= 2;
  79.       if contador2 > Cuenta_max then subiendo:= false;
  80.       if contador2 = 0 then subiendo:= true;
  81.       end;
  82.     end;
  83.  
  84.  
  85.     end;
  86.  
  87.  
  88.  

But still USART3 don't push out bits in the PB10 pin. I do a trick flasing internal led every time usart3 dma interrupt, and led flash!!!, but data isnt in the tx pin

with the same code, i can see a busrt of data outputing using usart1 and usart2
Title: Re: stm32f103 dma problem
Post by: MiR on July 20, 2020, 05:09:12 pm
What is your expectation now?

Would you like help with the problem?

If yes, please provide complete code that shows the problem in a minimalistic way so others can reproduce without guessing which other code to add to make your incomplete code snippet work.

MiR

Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 20, 2020, 08:15:46 pm
hello

my apologize. i'll not disturb you anymore.

I just want to share with all the solution of the problem i have before, and get some help with new one.

Code: Pascal  [Select][+][-]
  1.  
  2. procedure DMA1_Channel4_global_interrupt;  public name 'DMA1_Channel4_global_interrupt';  interrupt;
  3. Begin
  4.        your code here
  5.         ---->   DMA1.IFCR:= DMA1_FLAG_GL4; <---------
  6.        //dmaregisters.ifcr:= $0FFFFFFF; my previous mistake!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  7. end;
  8.  
  9.  

again thanks
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 20, 2020, 08:41:25 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  [Select][+][-]
  1. program torque_vfd_comm;
  2.  
  3. uses cortexm3, stm32f103fw;
  4. {$O-}
  5.  
  6. const
  7.   Serial_buffer_size = 7;
  8.   DMA_CHANNEL4 = 3;
  9.   PERIPH_BASE   = $40000000;
  10.   AHBPERIPH_BASE= PERIPH_BASE + $00020000;
  11.   DMA1_Channel4_BASE= AHBPERIPH_BASE + $00000044;
  12.  
  13. type
  14.   TDMA_Channel_Registers = record
  15.     CCR         : longword;
  16.     CNDTR       : longword;
  17.     CPAR        : longword;
  18.     CMAR        : longword;
  19.   end;
  20.  
  21. var
  22.   TXBuffer1: Array [0..Serial_buffer_size-1] of byte;
  23.   Usart_ini: TUSART_InitTypeDef;
  24.   NVIC_Ini: TNVIC_InitTypeDef;
  25.   GPIO_InitStruct: TGPIO_InitTypeDef;
  26.   RCC_Clocks: TRCC_ClocksTypeDef;
  27.   DMA1_Channel4 : TDMA_Channel_Registers absolute DMA1_Channel4_BASE;
  28.   i : integer;
  29.  
  30. procedure DMA1_Channel4_global_interrupt;  public name 'DMA4_Channel1_global_interrupt';  interrupt;
  31. Begin
  32.   dma1.ifcr:= $0FFFFFFF;
  33. end;
  34.  
  35. procedure USART1_SendBytesViaDMA(var Data : array of byte; const count : integer = -1);
  36. begin
  37.   //Disable DMA, Transfer Complete IRQ Read from Memory No Circular Mode No Periph Inc Memory Inc 8bit periph 8bit mem prio0
  38.   DMA1_Channel4.CCR := %000000010010010;
  39.   if count=-1 then
  40.     DMA1_Channel4.CNDTR := High(Data)+1
  41.   else
  42.     DMA1_Channel4.CNDTR := Count;
  43.   DMA1_Channel4.CPAR :=  LongWord(@Usart1.DR);
  44.   DMA1_Channel4.CMAR := LongWord(@Data);
  45.   DMA1_Channel4.CCR := DMA1_Channel4.CCR or %1;   //enable
  46. end;
  47.  
  48. begin
  49.   //************************************************
  50.   //**************** RCC  *************************
  51.   //FLASH_SetLatency(1);
  52.   RCC_HSICmd(Enabled);
  53.   RCC_DeInit;
  54.   RCC_HSICmd(Enabled);
  55.   //For simplicity run on 8MHz internal Clock
  56.   RCC_HCLKConfig(RCC_SYSCLK_Div1);
  57.   RCC_PCLK1Config(RCC_HCLK_Div2); //24MHz
  58.   RCC_PCLK2Config(RCC_HCLK_Div1); //48MHz
  59.   RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1 or RCC_AHBPeriph_SRAM or RCC_AHBPeriph_FLITF, Enabled);
  60.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, Enabled);
  61.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, Enabled);
  62.   RCC_GetClocksFreq(RCC_Clocks);
  63.  
  64.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_9; //TX USART1
  65.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  66.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  67.   GPIO_Init(PortA, GPIO_InitStruct);
  68.  
  69.   //************************************************
  70.   //**************** USART *************************
  71.  
  72.   Usart_ini.USART_BaudRate:= 9600;
  73.   Usart_ini.USART_WordLength:= USART_WordLength_8b;
  74.   Usart_ini.USART_StopBits:= USART_StopBits_1;
  75.   Usart_ini.USART_Parity:= USART_Parity_No;
  76.   Usart_ini.USART_Mode:= USART_Mode_Tx;
  77.   Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_None;
  78.   Usart_ini.USART_Clock:= USART_Clock_Disable;
  79.   Usart_ini.USART_CPOL:= USART_CPOL_Low;
  80.   Usart_ini.USART_CPHA:= USART_CPHA_1Edge;
  81.   Usart_ini.USART_LastBit:= USART_LastBit_Disable;
  82.   USART_Init(USart1, Usart_ini);
  83.  
  84.   USART_DMACmd(Usart1,USART_DMAReq_Tx,Enabled);
  85.  
  86.   Usart_Cmd(Usart1, ENABLED);
  87.  
  88.   //************************************************
  89.   //**************** NVIC **************************
  90.   NVIC_Ini.NVIC_IRQChannelPreemptionPriority:= 0;
  91.   NVIC_Ini.NVIC_IRQChannelSubPriority:= 0;
  92.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel4_IRQChannel;
  93.   NVIC_Init(NVIC_Ini);
  94.   NVIC_Ini.NVIC_IRQChannelCmd := Enabled;
  95.  
  96.   TXBuffer1[0] := byte('h');
  97.   TXBuffer1[1] := byte('e');
  98.   TXBuffer1[2] := byte('l');
  99.   TXBuffer1[3] := byte('l');
  100.   TXBuffer1[4] := byte('o');
  101.   TXBuffer1[5] := byte(#13);
  102.   TXBuffer1[6] := byte(#10);
  103.  
  104.   while true do
  105.   begin
  106.     USART1_SendBytesViaDMA(TXBuffer1);
  107.     //Quick hack, wait for tramsfer done....
  108.     repeat
  109.     until DMA1_Channel4.CNDTR = 0;
  110.     //now waste some time so that we better see when transfer starts again
  111.     for i := 1 to 100000 do
  112.       ;
  113.  
  114.   end;
  115. end.
  116.  

i will try your code, but modified to use usart3 and ill see what happens[/code]
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 20, 2020, 09:40:27 pm
ok now the results

Code: Pascal  [Select][+][-]
  1.  
  2. program torque_vfd_comm;
  3.  
  4. uses cortexm3, stm32f103fw;
  5. {$O-}
  6.  
  7. const
  8.   Serial_buffer_size = 7;
  9.   DMA_CHANNEL4 = 3;
  10.   PERIPH_BASE   = $40000000;
  11.   AHBPERIPH_BASE= PERIPH_BASE + $00020000;
  12.   DMA1_Channel2_BASE= AHBPERIPH_BASE + $0000001C;
  13.   DMA1_Channel4_BASE= AHBPERIPH_BASE + $00000044;
  14.  
  15. type
  16.   TDMA_Channel_Registers = record
  17.     CCR         : longword;
  18.     CNDTR       : longword;
  19.     CPAR        : longword;
  20.     CMAR        : longword;
  21.   end;
  22.  
  23. var
  24.   TXBuffer1: Array [0..Serial_buffer_size-1] of byte;
  25.   TXBuffer3: Array [0..Serial_buffer_size-1] of byte;
  26.   Usart_ini: TUSART_InitTypeDef;
  27.   NVIC_Ini: TNVIC_InitTypeDef;
  28.   GPIO_InitStruct: TGPIO_InitTypeDef;
  29.   RCC_Clocks: TRCC_ClocksTypeDef;
  30.   DMA1_Channel4 : TDMA_Channel_Registers absolute DMA1_Channel4_BASE;  
  31.   DMA1_Channel2 : TDMA_Channel_Registers absolute DMA1_Channel2_BASE;
  32.   i : integer;
  33.  
  34. procedure DMA1_Channel2_global_interrupt;  public name 'DMA2_Channel1_global_interrupt';  interrupt;
  35. Begin
  36.   DMA1.IFCR:= DMA1_FLAG_GL2;
  37. end;
  38.  
  39. procedure DMA1_Channel4_global_interrupt;  public name 'DMA4_Channel1_global_interrupt';  interrupt;
  40. Begin
  41.   DMA1.IFCR:= DMA1_FLAG_GL4;
  42. end;
  43.  
  44. procedure USART1_SendBytesViaDMA(var Data : array of byte; const count : integer = -1);
  45. begin
  46.   //Disable DMA, Transfer Complete IRQ Read from Memory No Circular Mode No Periph Inc Memory Inc 8bit periph 8bit mem prio0
  47.   DMA1_Channel4.CCR := %000000010010010;
  48.   if count=-1 then
  49.     DMA1_Channel4.CNDTR := High(Data)+1
  50.   else
  51.     DMA1_Channel4.CNDTR := Count;
  52.   DMA1_Channel4.CPAR :=  LongWord(@Usart1.DR);
  53.   DMA1_Channel4.CMAR := LongWord(@Data);
  54.   DMA1_Channel4.CCR := DMA1_Channel4.CCR or %1;   //enable
  55. end;
  56.  
  57. procedure USART3_SendBytesViaDMA(var Data : array of byte; const count : integer = -1);
  58. begin
  59.   //Disable DMA, Transfer Complete IRQ Read from Memory No Circular Mode No Periph Inc Memory Inc 8bit periph 8bit mem prio0
  60.   DMA1_Channel2.CCR := %000000010010010;
  61.   if count=-1 then
  62.     DMA1_Channel2.CNDTR := High(Data)+1
  63.   else
  64.     DMA1_Channel2.CNDTR := Count;
  65.   DMA1_Channel2.CPAR :=  LongWord(@Usart3.DR);
  66.   DMA1_Channel2.CMAR := LongWord(@Data);
  67.   DMA1_Channel2.CCR := DMA1_Channel2.CCR or %1;   //enable
  68. end;
  69.  
  70. begin
  71.   //************************************************
  72.   //**************** RCC  *************************
  73.   //FLASH_SetLatency(1);
  74.   RCC_HSICmd(Enabled);
  75.   RCC_DeInit;
  76.   RCC_HSICmd(Enabled);
  77.   //For simplicity run on 8MHz internal Clock
  78.   RCC_HCLKConfig(RCC_SYSCLK_Div1);
  79.   RCC_PCLK1Config(RCC_HCLK_Div2); //24MHz
  80.   RCC_PCLK2Config(RCC_HCLK_Div1); //48MHz
  81.   RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1 or RCC_AHBPeriph_SRAM or RCC_AHBPeriph_FLITF, Enabled);
  82.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, Enabled);
  83.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, Enabled);
  84.   RCC_GetClocksFreq(RCC_Clocks);
  85.  
  86.     GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_9; //TX USART1
  87.     GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  88.     GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  89.     GPIO_Init(PortA, GPIO_InitStruct);
  90.  
  91.   GPIO_InitStruct.GPIO_Pin:= GPIO_Pin_10; //TX USART3
  92.   GPIO_InitStruct.GPIO_Mode:= GPIO_Mode_AF_PP;
  93.   GPIO_InitStruct.GPIO_Speed:= GPIO_Speed_2MHz;
  94.   GPIO_Init(PortB, GPIO_InitStruct);
  95.  
  96.   //************************************************
  97.   //**************** USART *************************
  98.  
  99.   Usart_ini.USART_BaudRate:= 9600;
  100.   Usart_ini.USART_WordLength:= USART_WordLength_8b;
  101.   Usart_ini.USART_StopBits:= USART_StopBits_1;
  102.   Usart_ini.USART_Parity:= USART_Parity_No;
  103.   Usart_ini.USART_Mode:= USART_Mode_Tx;
  104.   Usart_ini.USART_HardwareFlowControl:= USART_HardwareFlowControl_None;
  105.   Usart_ini.USART_Clock:= USART_Clock_Disable;
  106.   Usart_ini.USART_CPOL:= USART_CPOL_Low;
  107.   Usart_ini.USART_CPHA:= USART_CPHA_1Edge;
  108.   Usart_ini.USART_LastBit:= USART_LastBit_Disable;
  109.   USART_Init(USart1, Usart_ini);
  110.   USART_Init(USart3, Usart_ini);
  111.  
  112.   USART_DMACmd(Usart1,USART_DMAReq_Tx,Enabled);
  113.   USART_DMACmd(Usart3,USART_DMAReq_Tx,Enabled);
  114.  
  115.   Usart_Cmd(Usart1, ENABLED);
  116.   Usart_Cmd(Usart3, ENABLED);
  117.  
  118.   //************************************************
  119.   //**************** NVIC **************************
  120.   NVIC_Ini.NVIC_IRQChannelPreemptionPriority:= 0;
  121.   NVIC_Ini.NVIC_IRQChannelSubPriority:= 0;
  122.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel2_IRQChannel;
  123.   NVIC_Init(NVIC_Ini);                              
  124.   NVIC_Ini.NVIC_IRQChannel:= DMAChannel4_IRQChannel;
  125.   NVIC_Init(NVIC_Ini);
  126.   NVIC_Ini.NVIC_IRQChannelCmd := Enabled;
  127.  
  128.  
  129.   TXBuffer1[0] := byte('h');
  130.   TXBuffer1[1] := byte('o');
  131.   TXBuffer1[2] := byte('l');
  132.   TXBuffer1[3] := byte('a');
  133.   TXBuffer1[4] := byte('1');
  134.   TXBuffer1[5] := byte(#13);
  135.   TXBuffer1[6] := byte(#10);
  136.  
  137.   TXBuffer3[0] := byte('h');
  138.   TXBuffer3[1] := byte('o');
  139.   TXBuffer3[2] := byte('l');
  140.   TXBuffer3[3] := byte('a');
  141.   TXBuffer3[4] := byte('3');
  142.   TXBuffer3[5] := byte(#13);
  143.   TXBuffer3[6] := byte(#10);
  144.  
  145.   while true do
  146.   begin
  147.     USART1_SendBytesViaDMA(TXBuffer1);
  148.     USART3_SendBytesViaDMA(TXBuffer3);
  149.     //Quick hack, wait for tramsfer done....
  150.     repeat
  151.     until (DMA1_Channel2.CNDTR = 0) AND (DMA1_Channel4.CNDTR = 0);
  152.     //now waste some time so that we better see when transfer starts again
  153.     for i := 1 to 100000 do
  154.       ;
  155.  
  156.   end;
  157. end.
  158.  
  159.  

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
Title: Re: stm32f103 dma problem
Post by: MiR on July 21, 2020, 11:23:04 am
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  [Select][+][-]
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA or RCC_APB2Periph_GPIOB or RCC_APB2Periph_USART1, Enabled);
  2. RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3+RCC_APB1Periph_PWR, Enabled);
  3.  

the example works for both USART1+3 (See Screenshot)
Title: Re: stm32f103 dma problem
Post by: diego bertotti on July 21, 2020, 01:17:53 pm
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
Title: Re: stm32f103 dma problem [SOLVED]
Post by: diego bertotti on July 21, 2020, 01:56:32 pm
hi

works!!!

i just uncomment this line
Code: Pascal  [Select][+][-]
  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 or RCC_APB1Periph_I2C2 or RCC_APB1Periph_CAN, Disabled);
  2.  

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
TinyPortal © 2005-2018