Reading GPIO using DMA and PIT

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Reading GPIO using DMA and PIT

Jump to solution
447 Views
lukasz_iwaszkie
Contributor II

Dear community.

    I started experimenting with imxrt1011 (on EVK board) and can't get eDMA to read GPIO2 periodically. I verified that GPIO2->PSR returns the state of my pins (polling). Pin configuration is generated by MCUXpresso Config Tool BTW - 8 pins are set to GPIO2 inputs. I checked that my DMA example (modified ping-pong example) woks when I source data from memory buffer instead of GPIO2->PSR. PIT also seems to be working, because I checked on an oscilloscope that I can slow down DMA transfers using it. Yet, when I try to source data from GPIO2->PSR nothing happens, and even my callback (EDMA_Callback) doesn't get called.  My DMA configuration is as follows:

AT_NONCACHEABLE_SECTION_ALIGN_INIT (uint8_t destBuf[BUFFER_LENGTH], 32) = {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};

void init ()
{
        CLOCK_SetMux (kCLOCK_PerclkMux, 1U);
        CLOCK_SetDiv (kCLOCK_PerclkDiv, 0U);

        pit_config_t pitConfig{};
        PIT_GetDefaultConfig (&pitConfig);
        PIT_Init (PIT, &pitConfig);
        PIT_SetTimerPeriod (PIT, kPIT_Chnl_0, USEC_TO_COUNT (1000U, CLOCK_GetFreq (kCLOCK_OscClk)));
        PIT_StartTimer (PIT, kPIT_Chnl_0);

        edma_transfer_config_t transferConfig{};
        edma_config_t userConfig{};

        DMAMUX_Init (DMAMUX);
        DMAMUX_EnableChannel (DMAMUX, EDMA_CHANNEL_0);
        DMAMUX_EnableAlwaysOn (DMAMUX, EDMA_CHANNEL_0, true);
        DMAMUX_EnablePeriodTrigger (DMAMUX, EDMA_CHANNEL_0);

        EDMA_GetDefaultConfig (&userConfig);
        EDMA_Init (DMA0, &userConfig);
        EDMA_CreateHandle (&g_EDMA_Handle, DMA0, EDMA_CHANNEL_0);
        EDMA_SetCallback (&g_EDMA_Handle, EDMA_Callback, nullptr);
        EDMA_ResetChannel (g_EDMA_Handle.base, g_EDMA_Handle.channel);

        // Prepare descroptor 0
        EDMA_PrepareTransfer (&transferConfig,
                              (void *)&GPIO2->PSR,       // srcAddr eDMA transfer source address.
                              1,                         // srcWidth eDMA transfer source address width(bytes).
                              &destBuf[0],               // destAddr eDMA transfer destination address.
                              1,                         // destWidth eDMA transfer destination address width(bytes).
                              1,                         // bytesEachRequest (minor count B) eDMA transfer bytes per channel request.
                              HALF_BUFFER_LENGTH,        // transferBytes (major * minor count B) eDMA transfer total B.
                              kEDMA_PeripheralToMemory); // transferType eDMA transfer type.

        EDMA_TcdSetTransferConfig (&tcdMemoryPoolPtr[0], &transferConfig, &tcdMemoryPoolPtr[1]);

        // Prepare descroptor 1
        EDMA_PrepareTransfer (&transferConfig,
                              (void *)&GPIO2->PSR,          // srcAddr
                              1,                            // srcWidth
                              &destBuf[HALF_BUFFER_LENGTH], // destAddr
                              1,                            // destWidth
                              1,                            // bytesEachRequest
                              HALF_BUFFER_LENGTH,           // transferBytes
                              kEDMA_PeripheralToMemory);    // transferType

        EDMA_TcdSetTransferConfig (&tcdMemoryPoolPtr[1], &transferConfig, &tcdMemoryPoolPtr[0]);

        EDMA_TcdEnableInterrupts (&tcdMemoryPoolPtr[0], kEDMA_ErrorInterruptEnable | kEDMA_MajorInterruptEnable);
        EDMA_TcdEnableInterrupts (&tcdMemoryPoolPtr[1], kEDMA_ErrorInterruptEnable | kEDMA_MajorInterruptEnable);
        EDMA_InstallTCD (DMA0, EDMA_CHANNEL_0, tcdMemoryPoolPtr);
        EDMA_EnableAutoStopRequest (DMA0, EDMA_CHANNEL_0, false);
        EDMA_StartTransfer (&g_EDMA_Handle);
}

 

Labels (1)
0 Kudos
Reply
1 Solution
408 Views
lukasz_iwaszkie
Contributor II

I changed GPIO2 to GPIO1 for a test and it worked immediately. And according to this it seems like HS GPIO is not supported by eDMA (unfortunately). And on RT1011 GPIO2 is HSGPIO, while GPIO1 is regular GPIO...

View solution in original post

0 Kudos
Reply
6 Replies
429 Views
mayliu1
NXP Employee
NXP Employee

Hi @lukasz_iwaszkie ,

Thank you for your interest in the NXP MIMXRT product, I would  like to provide service for you.

I think there's a bit of a problem with the code you wrote(EDMA_PrepareTransfer), Please check it.

mayliu1_0-1728301564772.png

In SDK library, fsl_edma.c describe  EDMA_PrepareTransfer as follows. 

The data address and the data width 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).

mayliu1_2-1728301692908.png

Please modify the EDMA_PrepareTransfer function param, and then try to test the project again.

 

Wish it helps you.
If you still have question about it, please kindly let me know.

 

Best Regards

mayliu

 

 

0 Kudos
Reply
425 Views
lukasz_iwaszkie
Contributor II

Thanks for a quick reply.

  I set srcWidth to 1 hoping for reading 8 least significant bits from GPIO2->PSR. Is that possible? Do you mean that since GPIO2->PSR is 32bit I should always read 4B from it? Because otherwise if I do only 1B reads, then, according to what you pasted my corresponding addresses should be 1B aligned, which is always the case isn't it? All things aside, I tried with srcWidth == 4, destWidth == 4 and bytesEachRequest == 4 and nothing changed

0 Kudos
Reply
386 Views
mayliu1
NXP Employee
NXP Employee

Hi @lukasz_iwaszkie ,

 

Thank you for your updated information.

I import a SDK demo, and modify it, I can use DMA to transfer GPIO status to Buffer.

I use MIMXRT1170-EVKB board, and circle read GPIO13_00Pin(SW7)

mayliu1_3-1728455420108.png

Please pay attention to the following points:

1:The target cache type should be 4 bytes

mayliu1_5-1728455476649.png

 

 

2:you can use GPIOXX->DR to read GPIO status. 

mayliu1_4-1728455455890.png

 

3:I use while(1) and delay to circle start DMA transfer, you can change it, using PIT timer to trigger  DMA transfer.

Wish it helps you.
If you still have question about it, please kindly let me know.

 

Best Regards

mayliu

0 Kudos
Reply
368 Views
lukasz_iwaszkie
Contributor II

Thank you. Yes, this is very valuable piece of info as well you posted : GPIO registers have to be read as a whole by the eDMA, and in general (that is 32bits). 1010 RM on page 462, chapter 12.5 says: "12.5 GPIO Register Descriptions: There are eight 32-bit GPIO registers. All registers are accessible from the IP interface. Only 32-bit access is supported."

0 Kudos
Reply
409 Views
lukasz_iwaszkie
Contributor II

I changed GPIO2 to GPIO1 for a test and it worked immediately. And according to this it seems like HS GPIO is not supported by eDMA (unfortunately). And on RT1011 GPIO2 is HSGPIO, while GPIO1 is regular GPIO...

0 Kudos
Reply
357 Views
mayliu1
NXP Employee
NXP Employee

Hi @lukasz_iwaszkie ,

 

Thank you for your updated information.

I'm glad that you can read the GPIO state with DMA right now, Thanks for the answer that  "DMA does not have access to HS GPIO".

 

Have a nice day

 

Best Regards

mayliu

0 Kudos
Reply