Hi,
In the SDK for the co-processor (Cortex-M7) I don't find any example of SDMA usage with "custom scripts".
The objective is to mesure the duration of high/low levels of a signal with unknown frequency.
I need to trigger a DMA custom script when there is a falling or rising edge in a GPIO.
The script should do this:
1. Read the state of the GPIO
2. Read the CNT register of GPT peripheral
3. Store in a buffer at an offset X : gpio_state and cnt
4. Increase the offset X
5. If X >= 1024: Send the buffer to the user and set X = 0
I currently don't know where to start as currently there is no examples of SDMA with:
- custom script in cortex-m7 SDK.
- triggered by GPIO
Any help will be appreciated
Hi,
unfortunately you cannot "trigger" SDMA channels by the GPIO. You have to distinguish between "interrupts" which signal the (ARM) CPU and "dma requests" which signal the (S)DMA. Refer to the table "SDMA event mapping" in the reference manual where you can see that there are no SDMA events for GPIO.
Instead of an GPIO input you could use a GPT_CAPTURE input. The GPT inputs are able to capture on rising/falling/both edges. And the GPT can be combined with the SDMA (I have implemented measurement of fan rpm by monitoring the tacho line this way).
Please note that you cannot share the SDMA between the Cortex-A and Cortex-M. If you want to use the SDMA from the Cortex-M7, you cannot use it on the Cortex-A. Although some i.MX8 have more than one SDMA, this usually doesn't help as SDMA2+3 are only connected the SAI peripherals. So you have three options:
There are no "official" development tools available from NXP. Therefore I have ported GNU binutils (assembler/linker) for the SDMA. Additionally I have written a plugin for the Lauterbach Trace32 JTAG debugger. Please contact me via private message if you are interested in these.
regards,
Christian
Hi,
The GPT was one of the first option, but as we don't know the frequency (datarate) of the radio signal, (The frequency/datarate is unknown and can change) and we need to know the duration of high/low levels: We can't just configure the GPT to trigger or Rising or Faling edge.
We need to configure the trigger to BothRisingOrFalling edge.
But, If the GPT is triggered by both edges, then we are not able to know if the edge was rising or falling, so we don't know if the bit is 1 or 0 (reading the GPIO is not an option as seen with support)
The NXP support tell me that there is no options to know it with GPT if we trigger on both rising or falling edge.
-------------------
About GPIO:
The specs are really not clear, about what is "External DMA from pad through IOMUX" and if it is related with "SDMAx_EXT_EVENTn" and if we can trigger a DMA channel with it... But as I understand it's possible.
So if my understanding is correct, we can trigger a SDMA channel with GPIO.
But today there is no examples for cortex-m7 and I don't really know where to start
GPT:
What about connecting your signal to two GPT inputs in parallel and configuring one input for RisingEdge and the other for FallingEdge? In this case you should be able to distinguish the falling/rising edges.
GPIO:
It is definitely not possible to trigger the SDMA from the GPIO peripherals. But you may use the SDMAx_EXT_EVENTn lines (using them as SDMA peripheral input, not as GPIO). But you may run into the same problem that you may not be able to distinguish between rising/falling edge in this case (assuming that you can choose the active edge, maybe that's not possible for SDMA event intputs). This could eventually be fixed by reading the GPIO line state after the SDMA has been triggered, but this is a little bit racy.
With the current information I would definitely prefer the GPT solution is this one is more accurate. The SDMA channels are usually subject to "multi-tasking", so you may have varying context switch delays (similar as on an ordinary CPU). The GPT in turn will provide accurate time stamping, the only requirement is, that you read out the input capture registers before the next edge on your input appears.
regards,
Christian
Oh, and just to be clear about the freezing issue.
We have made a simple code:
#define RADIO_RX_1_GPIO (GPIO4)
#define RADIO_RX_1_PIN (28U)
#define RADIO_RX_1_ISR_FLAG (1U << RADIO_RX_1_PIN)
void GPIO4_Combined_16_31_IRQHandler(void) {
if (GPIO_GetPinsInterruptFlags(RADIO_RX_1_GPIO) & RADIO_RX_1_ISR_FLAG) {
GPIO_ClearPinsInterruptFlags(RADIO_RX_1_GPIO, RADIO_RX_1_ISR_FLAG);
}
SDK_ISR_EXIT_BARRIER;
}
void main(void) {
/* Init board hardware. */
/* M7 has its local cache and enabled by default,
* need to set smart subsystems (0x28000000 ~ 0x3FFFFFFF)
* non-cacheable before accessing this address region */
BOARD_InitMemory();
/* Board specific RDC settings */
BOARD_RdcInit();
BOARD_InitBootPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
gpio_pin_config_t pinConfig = {kGPIO_DigitalInput, 0, kGPIO_IntRisingOrFallingEdge};
GPIO_PinInit(RADIO_RX_1_GPIO, RADIO_RX_1_PIN, &pinConfig);
GPIO_EnableInterrupts(RADIO_RX_1_GPIO, RADIO_RX_1_ISR_FLAG);
EnableIRQ(GPIO4_Combined_16_31_IRQn);
// EnableIRQWithPriority(GPIO4_Combined_16_31_IRQn, 20);
while (1) {
__WFI();
}
}
The Linux side "freeze" when it receive a signal on the GPIO. It doesn't seems to be related to the frequency (Same results with 50Hz input or 50Khz at 50% duty cycle).
The freeze is not immediate, sometimes it's after 5 seconds, sometime 1 minute, the best record is 4 minutes.
Currently we don't know what is causing this freezing issue.
When the linux is frozen:
Also we measure that every call to a register like reading GPIO in the interrupts takes around 280nS, maybe this is due to IP Bus (?)
Note: Playing with interrupt priority has no effect on the freeze problem.
Note 2: Most of the times there are no logs, but yesterday I got interesting logs (linux side) before it freeze (attached)
We was also thinking about the first method.
----------------------------------------
With interrupts, it was possible to do what you say because we was able to trigger on level change (both)
But we want to do it with SDMA to prevent high interrupt usage in the cortex-m7, and also because interrupts are freezing the A53 (no logs to understand the problem) but the SDMA can only be triggered by "counter event" (instead of input capture):
----------------------------------------
Idealy if this is possible we are thinking:
1. Connecting a SDMAx_EXT_EVENTn to the radio signal, and another GPIO to the same radio signal
2. In the DMA process, if it can be triggered by both edges on SDMAx_EXT_EVENTn, then read the GPIO to know the "level"
----------------------------------------
About the second method, the specifications are really not clear. Did you know what are the possible triggers for DMA with a SDMAx_EXT_EVENTn pin ? Where is it explained in the reference manual ?
I don't find any mentions about what we can do with this, for exemple can we trigger on falling edge, rising edge, both ?
I understand that SDMAx_EXT_EVENTn is not GPIO, but where is it explained what it is ?
----------------------------------------
Now in any cases we need to use custom scripts to make it working with DMA, I'm looking for an example of SDMA custom script usage in cortex-m7.
----------------------------------------
Thanks for help
I use the GPT INPUT_CAPTURE events with the SDMA. The documentation may be not precise here.
I also haven't found any documentation about the polarity of the SDMA event lines (I also haven't used them yet). So it's likely that you can NOT use them for triggering on both edges.
Is it absolutely required to use the SDMA+Cortex-M, or could you use SDMA-Cortex-A instead.
regards,
Christian
g