Hi all,
I struggle the adjust the PIT timers
My workstation consist of MATLAB 2020a MBDT, MPC5775E-EVB board.
I try to implement custom code(as a descibed in here https://community.nxp.com/t5/NXP-Model-Based-Design-Tools/How-to-use-your-own-C-code-in-our-Toolbox-...)
for MC33937 driver.
CPOL:DSPI_ACTIVE_LOW
CPHA:DSPI_CLOCK_PHASE_2ND_EDGE
CS:Active Low
Setting deadtime for mc33937 ,
1) Send 0x81
2) 20 us CS High
3) 12 us CS Low
4) Send 0x03
Third step didn't works as i expected. I configured the 12 us, but it works aprroximatelly 43 us.
How can i set properly? @mariuslucianand
Relevant code pieces
/* Configure the SPI init structure. */
dspi_master_config_t spiConfig1 = {
/*.bitsPerSec = 328125U,*/
.bitsPerSec = 300000U, //300kHz for debug purpose(normally 3MHz)
.whichPCS = 3,
.pcsPolarity = DSPI_ACTIVE_LOW,
.continuousPCS = false,
.bitcount = 8U,
.clkPhase = DSPI_CLOCK_PHASE_2ND_EDGE,
.clkPolarity = DSPI_ACTIVE_LOW,
.lsbFirst = false,
/*.transferType = DSPI_USING_INTERRUPTS,
.callback = (spi_callback_t)spi_master_transfer_callback1,*/
};
//SPI configured as a pooling mode, TX,RX FIFOs disabled , just used PUSHR POPR for TX-RX
//! User channel configuration 0
pit_channel_config_t pit0_ChnConfig1= {
.hwChannel = 1U,
.periodUnit = PIT_PERIOD_UNITS_MICROSECONDS,
.period = 30, /*20 us*/
.enableChain = false,
.enableInterrupt = false
};
//! User channel configuration 2
pit_channel_config_t pit1_ChnConfig2= {
.hwChannel = 2U,
.periodUnit = PIT_PERIOD_UNITS_MICROSECONDS,
/*.period = ((750<<4)/1000)+ 9 - 4, /*12 us*/
.period = 25,
/*.period = 5,*/
.enableChain = false,
.enableInterrupt = false
};
// Initialize PIT for user
PIT_DRV_Init(0u, &pit0_InitConfig);
// Initialize channel 1 for user
PIT_DRV_InitChannel(0U, &pit0_ChnConfig1);
// for user
//INT_SYS_SetPriority(PIT_RTI1_IRQn, 9U);
// Initialize PIT for deadtime delay
PIT_DRV_Init(0u, &pit1_InitConfig);
// Initialize channel 1 for deadtime delay
PIT_DRV_InitChannel(0U, &pit1_ChnConfig2);
MC33937_Tx_Rx(1,send_buff,recv_buff); // send 0x81
DeadTime_Delay_us(0U, 1U); // 20 us delay
MC33937_CS_Low(1);
DeadTime_Delay_us(0U, 2U); // 12 us delay?
MC33937_CS_High(1);
MC33937_Tx_Rx(1,(0x03),recv_buff);
//functions
void DeadTime_Delay_us(const uint32_t instance, const uint8_t channel)
{
//uint32_t getStatusFlag = 0;
PIT_Type * const s_pitBase[] = PIT_BASE_PTRS;
PIT_Type * const base = s_pitBase[instance];
status_t clkErr;
// check if the timer is already running. If it is, we cannot use it.
DEV_ASSERT((base->TIMER[channel].TCTRL & PIT_TCTRL_TEN_MASK) == 0u);
//Start timer
base->TIMER[channel].TCTRL |= PIT_TCTRL_TEN_MASK;
//get status flag
//getStatusFlag = (base->TIMER[channel].TFLG & PIT_TFLG_TIF_MASK);
for(;;)
{
if((base->TIMER[channel].TFLG & PIT_TFLG_TIF_MASK)) //if counter reached a zero
{
base->TIMER[channel].TCTRL &= ~PIT_TCTRL_TEN_MASK;//stop channel
base->TIMER[channel].TFLG = PIT_TFLG_TIF_MASK; //clear status flag
break;
}
}
}
void MC33937_CS_Low(dspi_instance_t instance)
{
DSPI_Type * base = DSPI_Instances[instance];
uint32_t polarity;
uint32_t config_pcsPolarity = (uint32_t)DSPI_ACTIVE_HIGH;
/*
// Configure PCS polarity.
for (int i = 0; i < 8U; i++)
{
polarity |= config_pcsPolarity << i;
}
*/
polarity = 0;
DSPI_Set_MCR_PCSIS(base, polarity);
}
void MC33937_CS_High(dspi_instance_t instance)
{
DSPI_Type * base = DSPI_Instances[instance];
uint32_t polarity;
uint32_t config_pcsPolarity = (uint32_t)DSPI_ACTIVE_LOW;
/*
// Configure PCS polarity.
for (int i = 0; i < 8U; i++)
{
polarity |= config_pcsPolarity << i;
}
*/
polarity = 255;
DSPI_Set_MCR_PCSIS(base, polarity);
}
Hello @engineer_attila,
Below there are the suggestions I have for your approach in order to achieve the desired timing, as you may see in the screenshot below.
From the beginning, I shall tell that the PIT channel 0 is used to drive the main step interrupt, while the PIT channel 3 is used to calculate the timeout for the communications. So, instead of using 2 PIT channels, you could use only 1, and before waiting for the time to pass, you could set the period to wait for. But, the problem is that setting the new waiting value adds overtime, which of course can be calculated and can be considered constant. The SDK provides 2 functions PIT_DRV_SetTimerPeriodByUs and PIT_DRV_SetTimerPeriodByCount which lets you update the new PIT counter. The difference between them is that the first one accepts units of microseconds and computes the ticks based on clock frequency for PIT, while the second one just takes the ticks parameter and updates the PIT register. Because you want to wait for such a tiny amount of time, I suggest using the second one, because the clock frequency for the PIT is 100Mhz, so it's easy to compute ticks when writing the code and not let the MCU to compute it every step execution.
I have modified the DeadTime_Delay_us to just receive the ticks as parameters, set the timer period, star the timer, and wait until the timer expires, using a flag variable, which is reset in the deadtime_callback.
To link the deadtime_callback to the PIT1 in Simulink, I've been using a custom code example inserted in the PIT Channel 1 triggered Subsystem.
Now, the problem is the overhead execution for exiting the SPI transfer function, and the time passing from the moment when the DeadTime_Delay_us is called (setting the ticks value in registers) what you can see in my screenshot, segmented with A B C and D. Once you do the math, to reach 20us @ 100Mhz, you need to wait actually 2000 PIT ticks. But I've ended up calling the DeadTime_Delay_us with 399 ticks instead of 2000 because of what was mentioned above: the overhead of exiting the SPI transfer block function time A (this may vary on your side depending on how you call the SPI transfer) and the calling of DeadTime_Delay_us setting the ticks as well which takes around 5us time B, which can be seen on both delays. So it only remains to compute the C and D which in my case were 399 and 699. Of course, "A" may vary on your side.
I have attached the model and the code I've tested with, using the PTC29 SCK and PTD1 as PCS1. Please give it a try on your end, and let me know if you have further questions. Unfortunately, I cannot explain why it takes 43us on your side for the PIT 2.
Hope this helps,
Marius
Hello @engineer_attila ,
I am trying to provide you with a very fast response to make sure that you get the chance to test it today. My guess is that what you see might be related to the interrupts priorities of the SPI instance you are using. You can try to embed something similar as in the initialization custom code of the model I have attached.
Even if you are using the interrupts or blocking mode of the SPI transfer, behind, the SDK uses interrupts either if we talk about blocking or no blocking, so you will have to increase the priorities for the interrupts of the SPI instance you are using. I've used value 7 but has to be greater than the one of the PIT 0 interrupt (step time interrupt set in the config block), which drives the step trigger. Also, the PIT3 is used for the timeout of the blocking modes, so it has to be higher than the interrupts of the SPI.
In my attached archive there is also the elf file, so if you have access to the pins I';ve used you may fisrt try the same elf example I've provided on your setup. I've sued the X-MPC5775E-EVB, with the pins on DSPI_HDR.
Hope this helps,
Marius
Hello @mariuslucianand i flash your.elf and connect pins with logic analzer . I verified that CS pin works as i want. But i couldn't see decoded messages due to logic analzyer technical constraints.
i try to implement it my own project after 1 months (i'll send it from DM)
Regards
Attila