Author Topic: DMA, memory to peripheral  (Read 7444 times)

0 Members and 1 Guest are viewing this topic.

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
DMA, memory to peripheral
« on: August 18, 2018, 04:43:46 am »
I'm starting to use DMA, and I'm porting an application from Kinetis MK66 to NXP RT1020, and from STM32 to RT1020.

As I still did not know how the DMA works, to copy memory data to GPIO ports, I routed a couple of boards without taking into account the order of the ports.

To read data by DMA using SPI, I see no problems. The problem, I think it comes when I'm going to use DMA memory to peripherals (seven GPIO ports).

From what I read, it seemed to me that I understand that the addresses of the ports to which I am going to copy from memory using the DMA, should have consecutive  addresses, could not use ports that do not have consecutive addresses.

Is this so, or can it be fixed by software, if I have not routed the ports with consecutives addresses ?

On one of the boards, I can fix it easily, soldering some cables, to the ports that I do not use, and for the other ports I would make a small board that reorders them, to connect them all to an IDC connector of 2x16, to which they connect to LED panels HUB75 of my application.

With the other board, I have it more complicated, because it is the evaluation board of the RT1020, and on this board there are very few accessible ports. Only the ports just for my application, but of all these, once discarded those using the SPI that I need also, I would not have any group of 7 consecutive ports. I would only have 5 consecutive ports, and the other 2 I would have to wire them, desoldering a pair of very small resistors (0402 or 0201), to weld there 2 wires.

Is any software solution possible, to be able to use 7 non-contiguous ports in their addresses, to use DMA memory to peripheral?

Greetings.

« Last Edit: August 18, 2018, 06:30:05 am by luiHS »
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: DMA, memory to peripheral
« Reply #1 on: August 18, 2018, 04:52:36 am »
Usually GPIO ports are not really compatible with DMA unless hardware has some additional magic to handle it.

DMA also needs a beat trigger, which in case of an SPI peripheral is a shift register empty flag. You can probably use a timer for that, but again it depends on the DMA controller and if it can do this. Otherwise DMA will just instantly go through all the values.

What sort of data you are planning to write?
« Last Edit: August 18, 2018, 05:08:17 am by ataradov »
Alex
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: DMA, memory to peripheral
« Reply #2 on: August 18, 2018, 06:23:45 am »
I implemented a parallel SPI tranceiver once on STM32 using a timer and a 16-bit GPIO port. There were two tricky parts: 1) getting the timer to stop after a certain number of frames, and 2) "transposing" the bits back into words (and vice versa). But it worked out well and was a nice way to read a bunch of outboard ADCs that shared the same clock.

I don't understand the OP's desire for "consecutive addresses" though. Most DMA controllers allow you to increment one of the two pointers by zero, so you keep transferring to or from the same address (which is typically a peripheral register). And even if the port peripherals are somehow "consecutive", the data registers almost certainly won't be.

If you had to DMA to/from locations that were arbitrarily scattered in memory, you could probably do it with linked DMA transfers (if the chip supports that).
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #3 on: August 18, 2018, 06:40:58 am »
Usually GPIO ports are not really compatible with DMA unless hardware has some additional magic to handle it.

DMA also needs a beat trigger, which in case of an SPI peripheral is a shift register empty flag. You can probably use a timer for that, but again it depends on the DMA controller and if it can do this. Otherwise DMA will just instantly go through all the values.

What sort of data you are planning to write?

Yes, there is no problem in that issue, I have always an external trigger signal to load buffer of DMA, for Memory to Peripheral and also an external trigger signal to Read by SPI using DMA.

My problem is with the DMA, from Memory to Peripherals (seven GPIO ports), if all those ports must be in consecutive directions for it to work. I already routed the board, and those seven ports were not in consecutive directions (I did not know at that time). I do not know if that can be fixed by software, or I must do it by hardware, rewiring the board for the tests, and routing again for the final product.

 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: DMA, memory to peripheral
« Reply #4 on: August 18, 2018, 06:44:05 am »
I'm assuming you are talking about consecutive pins in a port? Even then, I don't see how DMA will do anything here. Typically GPIO pins are controlled by individual bits in a register, so DMA will not help.

Alex
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #5 on: August 18, 2018, 06:56:05 am »
I implemented a parallel SPI tranceiver once on STM32 using a timer and a 16-bit GPIO port. There were two tricky parts: 1) getting the timer to stop after a certain number of frames, and 2) "transposing" the bits back into words (and vice versa). But it worked out well and was a nice way to read a bunch of outboard ADCs that shared the same clock.

I don't understand the OP's desire for "consecutive addresses" though. Most DMA controllers allow you to increment one of the two pointers by zero, so you keep transferring to or from the same address (which is typically a peripheral register). And even if the port peripherals are somehow "consecutive", the data registers almost certainly won't be.

If you had to DMA to/from locations that were arbitrarily scattered in memory, you could probably do it with linked DMA transfers (if the chip supports that).


Maybe I did not explain myself well, or I still do not understand how the DMA works.

It is about reading seven GPIO ports and dumping the read into an array, so that with each reading, it is saved in seven elements of the array.

From what I have read, when configuring the DMA, we define the address of origin, destination address and width of the data to be transferred, also if we want to increase the address of origin or destination with each reading.

The entry addresses (GPIO ports) are always the same, only the destination varies, which will increase by seven with each reading.

If in the DMA, I configure the source address (I suppose the address of the first GPIO port), and the width of the data to be read (seven ports), I suppose that the addresses of the seven ports to be read must be consecutive, not I can take any group of seven ports, but these have to have their addresses one after the previous one.

For example, in the RT1020, those seven GPIO ports to read by DMA, I understand that these could be:

GPIO_AD_B1_01
GPIO_AD_B1_02
GPIO_AD_B1_03
GPIO_AD_B1_04
GPIO_AD_B1_05
GPIO_AD_B1_06
GPIO_AD_B1_07

but I could not use this port configuration, because their addresses are not contiguous:

GPIO_SD_B1_03
GPIO_AD_B0_01
GPIO_SD_B0_04
GPIO_AD_B1_01
GPIO_AD_B0_07
GPIO_SD_B1_02
GPIO_SD_B0_03
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: DMA, memory to peripheral
« Reply #6 on: August 18, 2018, 07:02:36 am »
What makes you think that DMA can do this with GPIO ports? There are no 7 ports, there are 7 bits in the same register.

You can read from GPIO pad status register (PSR) using DMA, but I don't see how this is helpful.

What is your actual goal here?
Alex
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #7 on: August 18, 2018, 07:03:18 am »
I'm assuming you are talking about consecutive pins in a port? Even then, I don't see how DMA will do anything here. Typically GPIO pins are controlled by individual bits in a register, so DMA will not help.

There is a trigger signal generated with a timer for the DMA to send the data, from memory to ports, with each pulse of that signal.

And when it comes to reading data, then there is an external trigger signal for the DMA to start capturing.

My problem is not that, but the configuration of the ports to send signals using DMA, from memory to peripherals. If those ports must have configuous addresses for it to work.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: DMA, memory to peripheral
« Reply #8 on: August 18, 2018, 07:07:49 am »
Not only they need to be sequential, they need to be 0-7 or 8-15 or 16-23, or 24-31. And you also need to check that GPIO handles byte writes correctly.

And you won't get 7 elements in the memory, you will get one byte per sample in which bits represent states of the corresponding pins.

GPIO is not designed to work with DMA.
Alex
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #9 on: August 18, 2018, 07:11:08 am »
What makes you think that DMA can do this with GPIO ports? There are no 7 ports, there are 7 bits in the same register.

You can read from GPIO pad status register (PSR) using DMA, but I don't see how this is helpful.

What is your actual goal here?

Read from an array (memory) and copy the data to seven GPIO ports (peripheral), using DMA. The trigger for DMA is generated by a timer.

Each pulse of the timer, the DMA must copy seven elements of the array to the seven GPIO ports, then increase the address of the array to copy the next seven elements of the array with the next pulse of the timer.

It is Memory to Peripheral transfer, using DMA, with increasing address of origin. It is working with STM32 and Kinetis MK66, now I need to port it to RT1020.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: DMA, memory to peripheral
« Reply #10 on: August 18, 2018, 07:15:45 am »
Read from an array (memory) and copy the data to seven GPIO ports (peripheral), using DMA. The trigger for DMA is generated by a timer.
There are no 7 GPIO ports. There are 7 bits in the port register. They are not the same thing.


It is working with STM32 and Kinetis MK66, now I need to port it to RT1020.
Can you show relevant code? I don't see how that is possible. What is the destination address set in the DMA?

It is probably possible using bit-banding, but it does not look like RT1020 has it.
Alex
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: DMA, memory to peripheral
« Reply #11 on: August 18, 2018, 09:26:49 am »
what is the purpose of that?
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #12 on: August 18, 2018, 09:55:18 am »
Read from an array (memory) and copy the data to seven GPIO ports (peripheral), using DMA. The trigger for DMA is generated by a timer.
There are no 7 GPIO ports. There are 7 bits in the port register. They are not the same thing.

Ok, I think I'm starting to understand. Then, when I configure DMA, I put in the source address the address of the first GPIO pin of the port to read and in the transfer source address width the number of bits to read, then when the DMA reads, each GPIO pin is a one bit of a byte.

But I must always configure the Source Address with the address of the first GPIO pin and how many bits to read, and all GPIOs must be contiguous in the same port starting from the indicated address. . This is so??.  I have check source code of one example and open the function to prepare the DMA, here I can see all the parameters to configure it.

In the SDK there are no examples of Memory to Peripheral or Peripheral to Memory. But I suppose that really a GPIO has an address assigned to it, and therefore it must be the same if in an example of Memory to Memory, I assigns to the address of origin or destination, the address of a GPIO port. I'm right ?.


* This function prepares the transfer configuration structure according to the user input.
 *
 * @param config The user configuration structure of type edma_transfer_t.
 * @param srcAddr eDMA transfer source address.
 * @param srcWidth eDMA transfer source address width (bytes).
 * @param destAddr eDMA transfer destination address.
 * @param destWidth eDMA transfer destination address width (bytes).
 * @param bytesEachRequest eDMA transfer bytes per channel request.
 * @param transferBytes eDMA transfer bytes to be transferred.
 * @param type eDMA transfer type.
 * @note The data address and the width data must be consistent. For example, if the SRC
 * is 4 bytes, the source address must be 4 bytes aligned, or it results in
 * source address error (SAE).
 * /
void EDMA_PrepareTransfer (edma_transfer_config_t * config,
                          void * srcAddr,
                          uint32_t srcWidth,
                          void * destAddr,
                          uint32_t destWidth,
                          uint32_t bytesEachRequest,
                          uint32_t transferBytes,
                          edma_transfer_type_t type);
« Last Edit: August 18, 2018, 10:10:31 am by luiHS »
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #13 on: August 18, 2018, 09:59:23 am »
what is the purpose of that?

Play animations in HUB75 LED panels.
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #14 on: August 18, 2018, 10:01:51 am »
It is working with STM32 and Kinetis MK66, now I need to port it to RT1020.
Quote
Can you show relevant code? I don't see how that is possible. What is the destination address set in the DMA?

It is probably possible using bit-banding, but it does not look like RT1020 has it.


This is with STM32, Memory to Peripheral. The memory is an array, Peripheral is 6 x GPIO in port D. The size of the data is one byte, although really it only copy to 6 x GPIO (I mean 6 bits), I still do not understand this detail. This prepares the DMA to transfer 256 bits of an Array to 6 x GPIO in port D, using a timer as trigger for DMA transfer.


   GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;

   GPIO_Init(GPIOD, &GPIO_InitStruct);

   // DMA init (DMA2, Channel6, Stream5)
   DMA_Cmd(DMA2_Stream5, DISABLE);
   DMA_DeInit(DMA2_Stream5);
   DMA_InitStructure.DMA_Channel = DMA_Channel_6;
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOD->ODR;
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;
   DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
   DMA_InitStructure.DMA_BufferSize = 256;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 8bit
   DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
   DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
   DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
   DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
   DMA_Init(DMA2_Stream5, &DMA_InitStructure);


« Last Edit: August 18, 2018, 10:20:54 am by luiHS »
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: DMA, memory to peripheral
« Reply #15 on: August 18, 2018, 10:52:59 am »
The memory is an array, Peripheral is 6 x GPIO in port D. The size of the data is one byte, although really it only copy to 6 x GPIO (I mean 6 bits), I still do not understand this detail.
Your example code initializes 7 pins of GPIOD. Anyway, on each DMA transfer cycle, one byte will be written into GPIOD->ODR. The effect is the same as if you had written the value to the register in code, all pins that have been configured as outputs will change state according to the written value. But a full byte will be written each transfer cycle.

Mike Harrison did a video on using GPIO DMA to bitbang SPI that may or may not be helpful:

Quote
This prepares the DMA to transfer 256 bits of an Array to 6 x GPIO in port D
Bytes. The array does contain 256 bits for each pin, but the transfer is done in bytes.

Quote
Code: [Select]
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;
This field should be initialized with the address of the source memory array.

Also, as a sidenote, not all STM32s have identical DMA controllers. It might be useful to say which specific chip the code you're trying to port was written for.
« Last Edit: August 18, 2018, 01:04:27 pm by andersm »
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #16 on: August 18, 2018, 11:44:31 am »
Thanks for your help andersm.

I have been looking in some sources of the RT1020 SDK, to see if I found out the difference between Memory to Memory and Memory to Periphal or Periphal to Memory, since I understand that a peripheral is also assigned a memory address.

This is what I have found, it seems that the only thing different is an offset (widht of source and destiny) that is applied to source and destiny when there is a Memory to Memory transfer. I still do not understand what this offset consists of.

    switch (type)
    {
        case kEDMA_MemoryToMemory:
            config->destOffset = destWidth;
            config->srcOffset = srcWidth;
            break;
        case kEDMA_MemoryToPeripheral:
            config->destOffset = 0U;
            config->srcOffset = srcWidth;
            break;
        case kEDMA_PeripheralToMemory:
            config->destOffset = destWidth;
            config->srcOffset = 0U;
            break;
        default:
            break;
    }
« Last Edit: August 18, 2018, 11:49:07 am by luiHS »
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: DMA, memory to peripheral
« Reply #17 on: August 18, 2018, 04:24:26 pm »
I put in the source address the address of the first GPIO pin of the port to read and in the transfer source address width the number of bits to read, then when the DMA reads, each GPIO pin is a one bit of a byte.
Correct, except the you specify the addres of a register containing all pins, not a specific pin. And size granularity is 8-bit.

But I must always configure the Source Address with the address of the first GPIO pin and how many bits to read, and all GPIOs must be contiguous in the same port starting from the indicated address. . This is so??
Yes, and not only contiguous, but in the ranges I specified.

In the SDK there are no examples of Memory to Peripheral or Peripheral to Memory. But I suppose that really a GPIO has an address assigned to it, and therefore it must be the same if in an example of Memory to Memory, I assigns to the address of origin or destination, the address of a GPIO port. I'm right ?.
Correct. In this case you need to specify the address of the GPIO data register (DR) of the corresponding port: "DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOD->DR;" (substitute GPIOD with whatever port you want).
Alex
 
The following users thanked this post: luiHS

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #18 on: August 19, 2018, 12:16:42 am »
 
Ok, thanks ataradov.

Little by little, I understand how the DMA works, and how it is configured, at first I found something quite complex and little documented (this last I still think).

Then to transfer from or to GPIO ports, I must indicate the port address, so the address is per port, not per pin. For example, a port D has an address, and by indicating the width of the transfer to 1byte or 2 bytes, the status of GPIOs 0 to 7, or 0 to 15, is transferred. Is this correct?
Then it could not be read or transferred by DMA, for example, port D, GPIO 3 to 10, it always has to be from 0 and in bytes?.

About the Memory to Peripheral or Peripheral to Memory, with respect to the Memory to Memory transfer; Besides that when a Peripheral is involved, only the width of the data is indicated in the Memory (origin or destination), and not in the Peripheral, is there any other difference?

    switch (type)
    {
        case kEDMA_MemoryToMemory:
            config->destOffset = destWidth;
            config->srcOffset = srcWidth;
            break;
        case kEDMA_MemoryToPeripheral:
            config->destOffset = 0U;
            config->srcOffset = srcWidth;
            break;
        case kEDMA_PeripheralToMemory:
            config->destOffset = destWidth;
            config->srcOffset = 0U;
            break;
        default:
            break;
    }


In this example of a source that I found, I do not understand why the address of the Memory (which is an array) in a Memory to Peripheral transfer is set to zero. Should not this address be the address of the array to be transmitted?

  // DMA init (DMA2, Channel6, Stream5)
   DMA_Cmd(DMA2_Stream5, DISABLE);
   DMA_DeInit(DMA2_Stream5);
   DMA_InitStructure.DMA_Channel = DMA_Channel_6;
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOD->ODR;
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;
   DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
   DMA_InitStructure.DMA_BufferSize = 256;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 8bit
   DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
   DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
   DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
   DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
   DMA_Init(DMA2_Stream5, &DMA_InitStructure);

« Last Edit: August 19, 2018, 12:25:36 am by luiHS »
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #19 on: August 19, 2018, 12:18:22 am »

Quote
Code: [Select]
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;
This field should be initialized with the address of the source memory array.

Also, as a sidenote, not all STM32s have identical DMA controllers. It might be useful to say which specific chip the code you're trying to port was written for.

And why in this example its set to zero ?. I do not understand it. Should not this address be the address of the array to be transmitted?.

This is the source code for STM32F405, STM32F407, and I want to port it to NXP RT1020. Although really, it is not about porting the original source of STM32 to RT1020, but understanding how it works to be able to write my own code for RT1020.

« Last Edit: August 19, 2018, 12:22:03 am by luiHS »
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: DMA, memory to peripheral
« Reply #20 on: August 19, 2018, 12:21:37 am »
Then to transfer from or to GPIO ports, you must indicate the port address, so the address is per port, not per pin. For example, a port D has an address, and by indicating the width of the transfer to 1byte or 2 bytes, the status of GPIOs 0 to 7, or 0 to 15, is transferred. Is this correct?
Correct.

Then it could not be read or transferred by DMA, for example, from port D, from ports GPIO 3 to 10, it always has to be from 0 and in bytes?.
Yep. And for writes it is not inherently  guaranteed that you can do byte-sized writes. That totally depends on specific hardware implementation. It is very much possible that entire words has to be written or results may be undefined. It does not look like this is explicitly documented anywhere though.

In this example of a source that I found, I do not understand why the address of the Memory (which is an array) in a Memory to Peripheral transfer is set to zero. Should not this address be the address of the array to be transmitted?
I don't know the specifics of that library and the device to answer this.
Alex
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #21 on: August 19, 2018, 12:37:17 am »
In this example of a source that I found, I do not understand why the address of the Memory (which is an array) in a Memory to Peripheral transfer is set to zero. Should not this address be the address of the array to be transmitted?
I don't know the specifics of that library and the device to answer this.


OK, I found this in the source code, it seems that the source address of the array is loaded later, every time the DMA transfer is triggered.  So it seems that it is an address that is different, in this case, each time a transfer is made.

         DMA2_Stream5->M0AR = (uint32_t)(rgbbuf + ((rgbrow * 256) + (rgbsubframe * targetSubframeSize)));
         DMA2->LIFCR = 0b111101;
         DMA2_Stream5->CR |= DMA_SxCR_EN;


I looked in the code "M0AR" and found this:

         typedef struct
         {
           __IO uint32_t CR;     /*!< DMA stream x configuration register      */
           __IO uint32_t NDTR;   /*!< DMA stream x number of data register     */
           __IO uint32_t PAR;    /*!< DMA stream x peripheral address register */
           __IO uint32_t M0AR;   /*!< DMA stream x memory 0 address register   */
           __IO uint32_t M1AR;   /*!< DMA stream x memory 1 address register   */
           __IO uint32_t FCR;    /*!< DMA stream x FIFO control register       */
         } DMA_Stream_TypeDef;

         typedef struct
         {
           __IO uint32_t LISR;   /*!< DMA low interrupt status register,      Address offset: 0x00 */
           __IO uint32_t HISR;   /*!< DMA high interrupt status register,     Address offset: 0x04 */
           __IO uint32_t LIFCR;  /*!< DMA low interrupt flag clear register,  Address offset: 0x08 */
           __IO uint32_t HIFCR;  /*!< DMA high interrupt flag clear register, Address offset: 0x0C */
         } DMA_TypeDef;
« Last Edit: August 19, 2018, 12:41:00 am by luiHS »
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #22 on: August 19, 2018, 05:20:06 am »
I checked the Memory Map in the Reference Manual and I'm confused.
There are four ports, GPIO1, GPIO2, GPIO3 and GPIO5 (there is no GPIO4). GPIO1 to GPIO3, each one with 32 IO pins, and GPIO5 only with 3 IO pins.

If I want to send data to 7 x IO ports per DMA, does this mean that I can only use the first seven IO pins of each GPIO1, GPIO2 or GPIO3 port?

For each GPIO, the pins are GPIOn_IO00 to GPIOn_IO31, where n is 1 to 3.

Therefore, it is not possible to send data, for example port GPIO1_I008 to GPIO1_I015.
Can I only send data to these ?, If I have understand correctly.

GPIO1_I000 to GPIO1_I007  ---> 1 byte
GPIO1_I000 to GPIO1_I015  ---> 2 bytes
GPIO1_I000 to GPIO1_I023  ---> 3 bytes
GPIO1_I000 to GPIO1_I031  ---> 4 bytes

The problem is that some of the ports are used in my circuit, so it is not possible to send data to more than 8 IO ports if I connect my 7 pins to the 2nd, 3rd or 4th byte of the corresponding GPIO.
« Last Edit: August 19, 2018, 05:34:12 am by luiHS »
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: DMA, memory to peripheral
« Reply #23 on: August 19, 2018, 05:25:29 am »
Therefore, it is not possible to send data, for example port GPIO1_I008 to GPIO1_I015.
Can I only send data to these ?, If I have understand correctly.
No, you can write a byte at address GPIO1 + 1.

In the code it will be something like this: "(uint8_t *)&GPIOD->ODR + 1"; Or just manually specify the address: 0x401b8001 for GPIO0 byte 1.

+1 can be +0, +1, +2 and +3 to get access to bits 0-7, 8-15, 16-23, and 24-31. Again, you will have to verify that GPIO peripheral handles byte writes at any offset  within a word correctly.
« Last Edit: August 19, 2018, 05:40:15 am by ataradov »
Alex
 

Offline luiHSTopic starter

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: es
Re: DMA, memory to peripheral
« Reply #24 on: August 19, 2018, 05:39:29 am »

OK thanks ataradov, I will check.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf