Dear All,
it’s been two days now that I’m working on this and I don’t know how to solve the problems I’m facing.
I’m developing on the iMX7D colibri SoM and the Viola Plus carrier board.
The aim would be to leave the GPIO and timers modules to the M4, along with PWM, UART, SPI and i2c.
For this reason I’ve modified the device tree and it seems that linux, at least, is working as expected.
I’ve also played with the GPIO, that worked as expected too.
Now it was the time of the GPT. I’ve followed the blinking demo app, adapting it to my needs since I need a timer of at least 1us.
I’ve tried using both the ‘gptClockSourceOsc’ and the ‘gptClockSourcePeriph’.
In either cases, if I use a little or equal to 0 prescaler, Linux is not able to boot, it stucks at ‘Starting kernel…’.
If I use the oscillator with a prescaler of 1 (that is the clock is divided by 2) and then I use a fixed (for testing purpose) output compare value of 12, I obtain a delay of 10us, instead of 1us as expected.
24000000 / 2 = 12000000
12000000 / 12 = 1000000
That means that the period should be 1us, not 10us (measured with a xscope, since after the interval a pin is toggled).
Then I’ve tried to use the peripheral clock, using the ‘ccmRootmuxGptEnetPll40m’.
In this case, all I’ve obtained is the freeze of the linux counterpart at ‘starting kernel…’.
Here there is the hardware_init.c part related to the timer and clock init when I tried to use the enet clock:
void hardware_init(void)
{
/* Board specific RDC settings */
BOARD_RdcInit();
/* Board specific clock settings */
BOARD_ClockInit();
/* initialize debug uart */
dbg_uart_init();
RDC_SetPdapAccess(RDC, BOARD_GPTA_RDC_PDAP, 3 << (BOARD_DOMAIN_ID * 2), false, false);
CCM_ControlGate(CCM, ccmPllGateEnet, ccmClockNeededRunWait);
CCM_ControlGate(CCM, ccmPllGateEnet40m, ccmClockNeededRunWait);
//CCM_UpdateRoot(CCM, BOARD_GPTA_CCM_ROOT, ccmRootmuxGptOsc24m, 0, 0);
CCM_UpdateRoot(CCM, BOARD_GPTA_CCM_ROOT, ccmRootmuxGptEnetPll40m, 0, 0);
CCM_EnableRoot(CCM, BOARD_GPTA_CCM_ROOT);
CCM_ControlGate(CCM, BOARD_GPTA_CCM_CCGR, ccmClockNeededRunWait);
//CCM_ControlGate(CCM, ccmCcgrGateSema1, ccmClockNeededRun);
}
and here there is the gpt_timer.c, again with the enet clock:
static SemaphoreHandle_t xSemaphore;
void Hw_Timer_Init(void)
{
gpt_init_config_t config = {
.freeRun = false,
.waitEnable = true,
.stopEnable = true,
.dozeEnable = true,
.dbgEnable = false,
.enableMode = true
};
/* Initialize GPT module */
GPT_Init(BOARD_GPTA_BASEADDR, &config);
/* Set GPT clock source to 24M OSC */
//GPT_SetClockSource(BOARD_GPTA_BASEADDR, gptClockSourceOsc);
GPT_SetClockSource(BOARD_GPTA_BASEADDR, gptClockSourcePeriph);
/* Set GPT interrupt priority 3 */
NVIC_SetPriority(BOARD_GPTA_IRQ_NUM, 3);
/* Enable NVIC interrupt */
NVIC_EnableIRQ(BOARD_GPTA_IRQ_NUM);
xSemaphore = xSemaphoreCreateBinary();
}
void Hw_Timer_Delay(uint32_t us)
{
uint32_t ms_oc;
//GPT_SetOscPrescaler(BOARD_GPTA_BASEADDR, 1);
GPT_SetPrescaler(BOARD_GPTA_BASEADDR, 1);
GPT_SetOutputCompareValue(BOARD_GPTA_BASEADDR, gptOutputCompareChannel1, 19);
GPT_SetIntCmd(BOARD_GPTA_BASEADDR, gptStatusFlagOutputCompare1, true);
GPT_Enable(BOARD_GPTA_BASEADDR);
xSemaphoreTake(xSemaphore, portMAX_DELAY);
}
void BOARD_GPTA_HANDLER(void)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* When GPT time-out, we disable GPT to make sure this is a one-shot event. */
GPT_Disable(BOARD_GPTA_BASEADDR);
GPT_SetIntCmd(BOARD_GPTA_BASEADDR, gptStatusFlagOutputCompare1, false);
GPT_ClearStatusFlag(BOARD_GPTA_BASEADDR, gptStatusFlagOutputCompare1);
/* Unlock the task to process the event. */
xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
/* Perform a context switch to wake the higher priority task. */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
inside the main I have this, to test the timer:
while(1)
{
Hw_Timer_Delay(1);
if (currentPinsValue == gpioPinClear) currentPinsValue = gpioPinSet;
else currentPinsValue = gpioPinClear;
GPIO_WritePinOutput(config_array[0]->base, config_array[0]->pin, currentPinsValue);
}
The device tree file instead is:
&lcdif {
status = "disabled";
};
&pwm1 {
status = "disabled";
};
&pwm2 {
status = "disabled";
};
&pwm3 {
status = "disabled";
};
&pwm4 {
status = "disabled";
};
&bl {
status = "disabled";
};
&ecspi3 {
status = "disabled";
};
&i2c4 {
status = "disabled";
};
&sai1 {
status = "disabled";
};
&uart2 {
status = "disabled";
};
&uart3 {
status = "disabled";
};
&uart4 {
status = "disabled";
};
&uart5 {
status = "disabled";
};
&uart6 {
status = "disabled";
};
&uart7 {
status = "disabled";
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>;
assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
//uart-has-rtscts;
fsl,dte-mode;
};
&pinctrl_uart1 {
fsl,pins = <
MX7D_PAD_UART1_TX_DATA__UART1_DTE_RX 0x79
MX7D_PAD_UART1_RX_DATA__UART1_DTE_TX 0x79
>;
};
/ {
gpio-keys {
status = "disabled";
};
};
I don’t really know what I’m not understanding.
Any help will be appreciated, since I’m in an early stage of development of a new product and I would like to start on the right foot.
Thanks and regards,
Alessandro