TLE9879 Timer3 is not starting after restart

Announcements

Webinar: Integrated solutions for smaller, simpler low-voltage motor control design.
Join the webinar to experience!

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Tim_AGL
Level 1
Level 1
First like given First reply posted First question asked

Hello Guys,

I´m currently working on the TLE9879 with my custom PCB. For some Delays in the Code i use the Timer3 with a ISR.

My current problem is that the Timer3 is not restarting after a power down. Debugging and flashing works fine until restart. After restart the program runs until the Timer is triggered then the MCU seems to be in a loop because my counter doesnt rise. 

Here are my Settings for Keil.

ASM.PNG

C_C++.PNG

Target.PNG

Unbenannt.PNG

    

Code:

The shown Code is only the part  which includes the Timer.

#include "tle_device.h"
#include "Emo.h"
#include "linmain.h"
#include "genLinConfig.h"
#include "lin_driver_api.h"
#include "math.h"
#include "stdlib.h"

 


static void Main_lStartMotor(void);
static void Main_lStopMotor(void);

int main(void)
{
sint16 speed;
/* Initialization of hardware modules based on Config Wizard configuration */
TLE_Init();
/* Initialize E-Motor application */
Emo_Init();
/* Initialize IHR LIN Low Level Driver */
LIN_LLD_Init();



TIMER3_Stop();

uint16 adc1_1_mV;
bool adc1_1_mV_valid;
uint8 temp;

uint8 permanent = 0;
uint8 anlernen = 0;
uint8 soll = 0;
uint8 sollPos = 0;
uint8 fadeAnteil = 0;

uint8 HALL_A_pred = 0;
uint8 HALL_B_pred = 0;
uint8 HALL_C_pred = 0;

uint8 HALL_A = 0;
uint8 HALL_B = 0;
uint8 HALL_C = 0;

uint32 streckeGesamt = 0;
uint32 istPos = 0;
bool senseflag1 = false;


bool rechts = false;
bool links = false;
bool angelernt = false;
uint16 pinchstrom = 2120;

for (;;)
{
/* Service watchdog */
(void)WDT1_Service();
LIN_LLD_Service();

if (l_flg_tst_RefSpeed() || (rechts || links)) //Aenderung an LIN-Eingangsdaten
{
speed = l_s16_rd_RefSpeed(); //Auslesen Soll-RPM
permanent = l_u8_rd_Permanent(); //Auslesen modus permanent drehen
anlernen = l_u8_rd_Anlernen(); //Auslesen medus anlernen
soll = l_u8_rd_Soll(); //Auslesen modus Position anfahren
sollPos = l_u8_rd_SollPos(); //Auslesen Soll-Position
fadeAnteil = l_u8_rd_Fade(); //fade (Strecke)
if(permanent == 0 && anlernen == 0 && soll == 0)
{
Main_lStopMotor();
Emo_Init();
l_flg_clr_RefSpeed();
}

if(permanent == 0 && anlernen == 1 && soll == 0) //Modus anlernen
{
streckeGesamt = 0;
Emo_SetRefSpeed(-speed); //rueckwaerts RPM setzen
adc1_1_mV_valid = ADC1_GetChResult_mV(&adc1_1_mV, ADC1_CH1);
while(adc1_1_mV < 2100) //zurueck drehen bis 0-Position (0 Prozent)
{
(void)WDT1_Service();
LIN_LLD_Service();
Main_lStartMotor();
adc1_1_mV_valid = ADC1_GetChResult_mV(&adc1_1_mV, ADC1_CH1); //ADC-Wert abrufen
}

Main_lStopMotor();
Emo_Init();

HALL_A_pred = PORT_P03_Get(); //pred = Vorgaenger, aktueller Hall-Wert zu 0-Position
HALL_B_pred = PORT_P04_Get();
HALL_C_pred = PORT_P12_Get();
timer3_cnt = 0;
TIMER3_Start();
while(timer3_cnt < 250) // 5000ms/20, 5 sek warten
{
;
}
TIMER3_Stop();
timer3_cnt = 0;
Emo_SetRefSpeed(speed); //vorwaerts RPM setzen

adc1_1_mV_valid = ADC1_GetChResult_mV(&adc1_1_mV, ADC1_CH1);
while(adc1_1_mV < 2100) //vorwaerts drehen bis maximale auslenkung (100 Prozent)
{
(void)WDT1_Service();
LIN_LLD_Service();
Main_lStartMotor();

HALL_A = PORT_P03_Get(); //Nachfolge-Hall-Wert ermitteln
HALL_B = PORT_P04_Get();
HALL_C = PORT_P12_Get();

if((HALL_A != HALL_A_pred) || (HALL_B != HALL_B_pred) || (HALL_C != HALL_C_pred))
{
streckeGesamt++; //Inkrement Gesamtstraeken-Zaehler bei Aenderung eines Hall-Wertes
HALL_A_pred = HALL_A;
HALL_B_pred = HALL_B;
HALL_C_pred = HALL_C;
}

adc1_1_mV_valid = ADC1_GetChResult_mV(&adc1_1_mV, ADC1_CH1);
}

Main_lStopMotor();
Emo_Init();
permanent = 0;
anlernen = 0;
soll = 0;
istPos = streckeGesamt; //Motor jetzt in maximaler Auslenkung (100 Prozent)
timer3_cnt = 0;
TIMER3_Start();
while(timer3_cnt < 100) // 5000ms/20, 5 sek warten
{
;
}
TIMER3_Stop();
timer3_cnt = 0;
l_flg_clr_RefSpeed();
angelernt = true;
}

void Main_HandleSysTick(void)
{
/* Callback function executed every ms for speed control */
Emo_CtrlSpeed();
}


static void Main_lStartMotor(void)
{
uint32 Error;
Error = EMO_ERROR_NONE;

if (Error == EMO_ERROR_NONE)
{
/* Start the motor with desired positive or negative speed in [rpm] */
Error = Emo_StartMotor();
}

if (Error == EMO_ERROR_NONE)
{
}
else /* Error */
{
}
}


static void Main_lStopMotor(void)
{
uint32 Error;
Error = Emo_StopMotor();

if (Error != EMO_ERROR_NONE)
{
}
}

void timer3_hb_callback(void)
{
timer3_cnt++;
}

0 Likes
1 Solution
Raj_C
Moderator
Moderator
Moderator
250 solutions authored 500 replies posted 50 likes received

Hi @Tim_AGL ,

We have analyzed your code and its implementation and we concluded that the issue is related to the WDT1 reset.

>> WDT1 requires to be served every 400ms typically.

In your application Timer3 is configured to generate an interrupt on overflow. As per your ConfigWizard settings, it will be generated at every 21845us (21.845ms). Depending on your entered cnt value, it will be beyond 400ms and trigger a WDT1 reset as the system cannot serve the WDT1.

This was working perfectly in Debug mode as WDT1 is disabled in the debug mode. When you test outside debug mode it will be in always reset.

Workaround:

>> Reduce the delay value. For inserting delay in code please use the following function:

/** \brief Delays the regular program execution by a given number of Microseconds
 * \brief the function returns if the given time has elapsed
 * \brief smaller Microsecond delay times are getting falsen by the execution time
 * \brief of the function itself
 *
 * \warning Handle this function with care, as WDT1/WDT will not be serviced during the delay time.
 * \warning The user has to take care of WDT1/WDT service by himself.
 *
 * \param delay_time_us Delay time in Microseconds
 *
 * \brief <b>Example</b><br>
 * \brief This example sets a delay of 100 us.
 * ~~~~~~~~~~~~~~~{.c}
 * void Example_Function(void)
 * {
 *     Delay_us(100);
 * }
 * ~~~~~~~~~~~~~~~
 * \ingroup wdt1_api
 */
void Delay_us(uint32 delay_time_us);

Please, let us know if you have further questions.

Thank you

Best Regards

Raj Chaudhari

View solution in original post

5 Replies
Raj_C
Moderator
Moderator
Moderator
250 solutions authored 500 replies posted 50 likes received

Hi @Tim_AGL,

Could you please attach the config Wizard settings or, if possible, attach the .zip file of the KEIL Project? It would help us to give faster resolution.

Thank you

Best Regards

Raj Chaudhari

0 Likes
lock attach
Attachments are accessible only for community members.
Tim_AGL
Level 1
Level 1
First like given First reply posted First question asked

Hi Raj_JC,

i added the config Wizard settings in the attached zip.

 

Best Regards

Tim Krause

0 Likes
ninad_w
Moderator
Moderator
Moderator
50 solutions authored 100 replies posted First like given

Hi @Tim_AGL ,

Could you please attach your entire Keil project in a zip file if it is possible? It will be easy for us to debug and solve this problem as early as possible.

Thank you!

Best Regards

Ninad

0 Likes
lock attach
Attachments are accessible only for community members.

Hi Ninad,

I attached the whole project for you.

Thanks for the Help!

Best Regards 

Tim

0 Likes
Raj_C
Moderator
Moderator
Moderator
250 solutions authored 500 replies posted 50 likes received

Hi @Tim_AGL ,

We have analyzed your code and its implementation and we concluded that the issue is related to the WDT1 reset.

>> WDT1 requires to be served every 400ms typically.

In your application Timer3 is configured to generate an interrupt on overflow. As per your ConfigWizard settings, it will be generated at every 21845us (21.845ms). Depending on your entered cnt value, it will be beyond 400ms and trigger a WDT1 reset as the system cannot serve the WDT1.

This was working perfectly in Debug mode as WDT1 is disabled in the debug mode. When you test outside debug mode it will be in always reset.

Workaround:

>> Reduce the delay value. For inserting delay in code please use the following function:

/** \brief Delays the regular program execution by a given number of Microseconds
 * \brief the function returns if the given time has elapsed
 * \brief smaller Microsecond delay times are getting falsen by the execution time
 * \brief of the function itself
 *
 * \warning Handle this function with care, as WDT1/WDT will not be serviced during the delay time.
 * \warning The user has to take care of WDT1/WDT service by himself.
 *
 * \param delay_time_us Delay time in Microseconds
 *
 * \brief <b>Example</b><br>
 * \brief This example sets a delay of 100 us.
 * ~~~~~~~~~~~~~~~{.c}
 * void Example_Function(void)
 * {
 *     Delay_us(100);
 * }
 * ~~~~~~~~~~~~~~~
 * \ingroup wdt1_api
 */
void Delay_us(uint32 delay_time_us);

Please, let us know if you have further questions.

Thank you

Best Regards

Raj Chaudhari