DMA buffer to GPIO with NXP RT1064. - Page 1
Forum section: electronics / general

author: luiHS
author_rank: Frequent Contributor
timestamp: December 31, 2021, 01:38:20 pm
content: HelloI would like to use DMA to send data to multiple GPIO ports. I'm going to use an RT1064 microcontroller from NXP. I've been looking at the SDK sample sources, but all there are buffer to buffer and buffer to serial peripherals (SPI, I2C, CAN).Looking at one of the example sources, I find the call to the EDMA_PrepareTransfer function, in which the addresses of the origin and destination buffers are indicated among other data:Code:EDMA_PrepareTransfer (& transferConfig,srcAddr,sizeof (srcAddr ),destAddr, sizeof (destAddr ),sizeof (srcAddr ),sizeof (srcAddr),kEDMA_MemoryToMemory);The question is if I could replace the address of the destination buffer by the address of the first bit of a GPIO port, and indicating in the destination size parameter, the number of bits (pins) that will receive the data on the GPIO port.

author: TomS_
author_rank: Frequent Contributor
timestamp: December 31, 2021, 09:53:56 pm
content: If the GPIO pins are addressable at a memory location, I dont see any reason why you couldnt DMA to/from them.Typically there are multiple GPIOs per memory address though, so how you will handle the other bits you dont want to change is an interesting question.

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 31, 2021, 11:25:25 pm
content: Sure. You first need to study well how GPIOs work on this chip. Start with the IOMUX controller. Assign each required GPIO to the corresponding pin. Then set the direction.Then you'd use the GPIO_DR register as a destination for the DMA.Basically read chapters 10 to 12 of the ref. manual.Dunno what you want to achieve though. The problem with using the DMA to directly update GPIOs is that the rate of updates will likely not be fixed depending on what else is using the DMA controller and the memory. If you really need a fixed rate of change, you'd probably need to look at the FlexIO feature.

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 01, 2022, 01:30:51 pm
content: As far as I know, the i.MX RT1064 GPIO only supports 32 bit writes, so you're limited to either all outputs on a single bank, or a single pin in a single bank (using the bit slice memory aperture). You need to use FlexIO for better results. However, only FlexIO1 and FlexIO2 have full DMA support; FlexIO3 does not support DMA.For what it's worth, I –– as a complete bumbleduck hobbyist –– have been looking at creating a RT106x FlexIO board for controlling eg. display modules using 15/16/18-bit parallel IO with DMA, with a preprogrammed NXPMKL02 from PJRCto handle the bootup and flashing, to be used as a "smart" high-speed USB 2.0 framebuffer, for use with routers and other Linux-based SBCs. Non-commercial, just personal use. (With a small trick, using one UART RX/TX pair with 74LVC1T45 level shifters, so it can also be used as a serial (boot) terminal, and/or record the boot output; and to e.g. reboot the device if the serial output contains a trigger string (like a kernel oops or similar). And a few pins left over for additional buttons, encoders, and such. I'm targeting ILI9341 and similar controllers, because they're small and cheap even with IPS panels, and easy to control.)My problem at this point is that I'm a complete hobbyist, and even 0.8mm MAPBGA is way scary. I've only designed two-layer boards, and have never even soldered a BGA before; still practicing with SMD and hot air. Although I've done stuff with Teensy 4 (RT1062), it's been under Teensyduino (with the aforementioned MKL02 handling the bootup and flashing), not bare metal or NXP-provided SDK/HAL (CMSIS etc.).

author: luiHS
author_rank: Frequent Contributor
timestamp: January 06, 2022, 02:01:49 am
content: Quote from: Nominal Animal on January 01, 2022, 01:30:51 pmThat is what they told me in the technical support of NXP, that the GPIOs go in groups of 32 bits, and then I understand that I could not control for example only 8 or 16 pins.The fact is that there is an application with Teensy 4, which is using 2 bytes to control several GPIOs by DMA, I do not know if with the RT1062 this is different and they can only be written on 8 or 16 pins instead of having to use 32 pins .

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 06, 2022, 02:23:27 am
content: Quote from: luiHS on January 06, 2022, 02:01:49 amNo, it is not different. The Teensy 4 stuff does not do DMA to GPIOs, it uses FlexIO.Teensy pins 6, 7, 8, 9, 10, 11, 12, 13, 32 are available for FlexIO2, and pins 2, 3, 4, 5, 33 for FlexIO1.Essentially, you can use GPIO_B0_00..GPIO_B0_15 and GPIO_B1_00..GPIO_B1_15 via FlexIO2 (up to 32 bits wide), and GPIO_EMC_00..GPIO_EMC_11, GPIO_EMC_26..GPIO_EMC_29 via FlexIO1 (up to 16 bits wide), using DMA. AFAIK, FlexIO3 does not support DMA.Technically, you can do DMA to GPIO by doing 32-bit DMA to the DR_TOGGLE register, but then the data must be the mask for the GPIOnbank bits that are to be changed; i.e.prev_state ^ curr_state. I use a similar trick with look-up tables to do non-DMA IO to a parallel bus on GPIO1/2/3/4 on the Teensy 4.

author: luiHS
author_rank: Frequent Contributor
timestamp: January 06, 2022, 02:32:32 am
content: Quote from: Nominal Animal on January 06, 2022, 02:23:27 amThanks, I will have to read about this Flexio, because I do not know. The problem is also that in the SDK sample sources I have not found anything about controlling GPIO ports using DMA.I also have another application with the RT1064 in which I need to have at least 5 SPI ports, I think this microcontroller only has 4 LPSPI ports, but I seemed to understand that using Flexio two other SPI ports could be emulated. Do you know if this is so, it could have up to 6 SPI ports between LPSPI and Flexio?

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 06, 2022, 05:06:17 am
content: There is an LPSPI module, with four separate SPI buses with FIFOs.LPSPI1: _SCK is GPIO_SD_B0_00 or GPIO_EMC_27, _SOUT is GPIO_SD_B0_02 or GPIO_EMC_28, and _SIN is GPIO_SD_B0_03 or GPIO_EMC_29.LPSPI2: _SCK is GPIO_SD_B1_07 or GPIO_EMC_00, _SOUT is GPIO_SD_B1_08 or GPIO_EMC_02, and _SIN is GPIO_SD_B1_09 or GPIO_EMC_03.LPSPI3: _SCK is GPIO_AD_B0_00 or GPIO_AD_B1_15, _SOUT is GPIO_AD_B0_01 or GPIO_AD_B1_14, and _SIN is GPIO_AD_B0_02 or GPIO_AD_B1_13.LPSPI4: _SCK is GPIO_B0_03 or GPIO_B1_07, _SOUT is GPIO_B0_02 or GPIO_B1_06, and _SIN is GPIO_B0_01 or GPIO_B1_05.There is a FlexSPI host controller, with two SPI channels (to up to 4 external devices).FlexSPI A/B uses either GPIO_SD_B1_00 through _11, or GPIO_AD_B1_09 through _15. Usually these are used for (boot) flash and psram.FlexSPI2 A uses GPIO_EMC_22 through _29, and B uses GPIO_EMC_09 through _16.You can use one of the FlexIOs to implement two SPI buses (or a SPI bus and an UART, or other configurations).FlexIO1 uses GPIO_EMC_00 through _11 and GPIO_EMC_26 through _29.FlexIO2 uses GPIO_B0_00 through _15 and GPIO_B1_00 through _15.FlexIO3 uses GPIO_AD_B1_00 through _15 and GPIO_B1_00 through _15, but does not support DMA. Note that upper 16 bits of FlexIO2 and FlexIO3 coincide.For a parallel bus, you'll want to use consecutive pins (and specific shifters). I would not want to try and split one FlexIO into two parallel buses, although a parallel bus and a SPI bus might work.JTAG pins are GPIO_AD_B0_06 through _11 and GPIO_EMC_01. (SWD is GPIO_AD_B0_06 and _07.)TPIU (for ARM trace) are GPIO_B0_04 through _07, _12, and _13.USDHC1 uses GPIO_SD_B0_00 through _05.USDHC2 uses GPIO_SD_B1_00 through _11, or GPIO_AD_04 through _09 and _12 through _15.First quad timer, TMR1, uses GPIO_B0_00 (TMR1_TIMER0), GPIO_B0_01 (TMR1_TIMER1), GPIO_B0_02 (TMR1_TIMER2), and GPIO_B1_08 (TMR1_TIMER3).Fourth quad timer, TMR4, uses GPIO_B0_09 (TMR4_TIMER0), GPIO_B0_10 (TMR4_TIMER1), GPIO_B0_11 (TMR4_TIMER2), and GPIO_B1_11 (TMR4_TIMER4).The LCD interface uses GPIO_B0_00 through _15 and GPIO_B1_00 through _11.There is not much options for remapping the pins, really; you will need to do compromises on what interfaces you expose.Chapter 10.1.1. Muxing Options and Table 10-1. Muxing Options in the i.MX RT1060 Processor Reference Manual will tell you what you need to know.I've been wondering if I should make a tool to explore the possible combinations in a visual way (as a standalone/local HTML+CSS+JS page); it is darned hard to wrap ones mind around the various options otherwise.

author: Scrts
author_rank: Frequent Contributor
timestamp: January 06, 2022, 06:37:35 pm
content: Do you utilize external RAM memory? If not - set your peripheral as external 8bit or 16bit RAM and use DMA this way.I once used Camera interface to interface 8bit data bus directly into the memory, even though it wasn't image data...

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 06, 2022, 06:52:15 pm
content: Quote from: luiHS on January 06, 2022, 02:01:49 amI have not dug into this a whole lot yet, but can't the GPIO registers be byte-accessed or half-word-accessed instead of a full word access?

author: luiHS
author_rank: Frequent Contributor
timestamp: January 06, 2022, 09:03:02 pm
content: I found some comments on the Smartmatrix source code for Teensy 4 that control HUB75 LED panels, it seems they use Flexio to drive 16 GPIO pins by DMA./ * Set up FlexIO peripheral for clocking out data to LED matrix panel.FlexIO enables parallel output to the panel's RGB data inputs and also generates the clock signal for the panel in hardware.For Teensy 3.x, SmartMatrix uses an 8-bit GPIO port to generate RGB and clock signals, but this is not possible or convenienton Teensy 4.0 / 4.1 because the GPIO ports only have 32-bit access.FlexIO provides four 32-bit buffered shift registers which can shift 1, 2, 4, 8, 16, or 32 bits in parallel, which can be assignedto a group of contiguous pins on one FlexIO peripheral. On Teensy 4.0 and 4.1, we need to use 16 bit shift width to obtaina group containing 6 external FlexIO pins. The clock signal can be assigned to a non-contiguous FlexIO pin.The process of shifting out display data works (without using the CPU) as follows:1. First, a burst of RGB data is transferred by DMA into the FlexIO shifter buffers.2. When the buffers receive data, this triggers FlexIO to load the buffers into the shift registers and start clocking out data.3. Once the shift registers are loaded from the buffers, this DMA triggers to transfer the next burst of data to the buffers.4. The DMA transfer occurs simultaneously as the FlexIO shifters clock out the data.5. Once the data is clocked out, FlexIO reloads the shifters and this process repeats seamlessly.6. When the DMA channel reaches the end of the RGB data for the current display row, it stops refreshing the shift buffers.7. The FlexIO shifters output the last RGB data and then the clock disables.8. After the clock stops, FlexIO outputs the address data from an extra shifter without a clock signal. This only occurswhen the buffers for the RGB data shifters are completely empty. These signals are not clocked into the LED panel but areinstead used to control the row address latches on the SmartLED shield. * /

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 06, 2022, 11:16:57 pm
content: Quote from: SiliconWizard on January 06, 2022, 06:52:15 pmNo, only 32-bit access is supported:Quote from: NXP i.MX RT1060 Professor Reference ManualI also found it odd.Quote from: luiHS on January 06, 2022, 09:03:02 pmYup. KurtE, a frequent contributor at the Teensy forums, has implemented a FlexIO library for Teensy 4.x,FlexIO_t4; I recommend you take a look at that.