From 8f604211ada6888dc503ba7f3dbdb28723395db7 Mon Sep 17 00:00:00 2001 From: dzid26 Date: Wed, 17 Jul 2024 16:40:06 +0100 Subject: [PATCH] Measure ISR load, cleaned up timers, added tuned delay functions, add STMStudio setup and basic layout --- src/delay.h | 82 +++++++++++++++++++++ src/ebike_app.c | 3 + src/main.c | 50 +++++++++---- src/main.h | 6 +- src/timers.c | 18 ++--- src/timers.h | 5 +- tools/STMstudio.tsc | 159 ++++++++++++++++++++++++++++++++++++++++ tools/STMstudio_CPU.tsp | 10 +++ 8 files changed, 307 insertions(+), 26 deletions(-) create mode 100644 src/delay.h create mode 100644 tools/STMstudio.tsc create mode 100644 tools/STMstudio_CPU.tsp diff --git a/src/delay.h b/src/delay.h new file mode 100644 index 00000000..98006208 --- /dev/null +++ b/src/delay.h @@ -0,0 +1,82 @@ +/* + * delay utilite for STM8 family + * COSMIC and SDCC + * Terentiev Oleg + * t.oleg@ymail.com + */ + +#ifndef UTIL_DELAY_H_ +#define UTIL_DELAY_H_ 1 + +#ifndef F_CPU +#error F_CPU is not defined! +#endif + +// Amount of cycles was tuned to use desired amount time. +// Compiler settings may affect the delay time precision. +#if defined(__CSMC__) +static @inline void delay_cycl( unsigned short _ticks ) +#else +static inline void delay_cycl( unsigned short _ticks ) +#endif +{ +#if defined(__CSMC__) +/* COSMIC */ + #define T_COUNT_US(x) ((( (x) * (F_CPU / 1000000UL) )-3U)/3U) + // ldw X, ticks ; insert automaticaly + _asm("nop\n $N:\n decw X\n jrne $L\n nop\n ", ticks); +#elif defined(_SDCC_) + #define T_COUNT_US(x) ((( (x) * (F_CPU / 1000000UL) )-4U)*4/15U) + __asm__("nop\n nop\n"); + do { // ASM: lab$: decw X; tnzw X; jrne lab$ + _ticks--;// 1c; + 2c + ; 1/2c + 1/4 (mystery) = 3.75 = 15/4 + } while ( _ticks ); + __asm__("nop\n"); +#elif defined(__RCST7__) +/* RAISONANCE */ + #error ToDo for RAISONANCE +#elif defined(__ICCSTM8__) +/* IAR */ + #error ToDo for IAR +#else + #error Unsupported Compiler! /* Compiler defines not found */ +#endif +} + + +/** + * Delays for a specified number of microseconds. + * + * Blocking delay. + * + * @param _us the number of microseconds to delay, min = 4, max = 1000 + * + * @return void + * + * @throws None + */ +static inline void delay_us( unsigned short _us ) +{ + delay_cycl( (unsigned short)( T_COUNT_US(_us) )); +} + +/** + * Delays for a specified number of miliseconds. + * Blocking delay + * + * @param _us the number of microseconds to delay + * + * @return void + * + * @throws None + */ +static inline void delay_ms( unsigned short _ms ) +{ + while ( _ms-- ) + { + delay_us( 1000 ); + } +} + +#endif + diff --git a/src/ebike_app.c b/src/ebike_app.c index cf9156c8..099c25ef 100644 --- a/src/ebike_app.c +++ b/src/ebike_app.c @@ -3177,6 +3177,9 @@ static void uart_send_package(void) ui16_duty_cycle_percent = (uint16_t) ((ui8_g_duty_cycle * 100) / PWM_DUTY_CYCLE_MAX) - 1; ui16_display_data = (uint16_t) ui16_display_data_factor / (ui16_duty_cycle_percent * 10); break; + case 13: + ui16_display_data = (uint16_t) ui16_display_data_factor / (u8_isr_load_perc * (uint8_t)10U); + break; default: break; } diff --git a/src/main.c b/src/main.c index 2dfc20cf..1d9dea08 100644 --- a/src/main.c +++ b/src/main.c @@ -22,6 +22,8 @@ #include "torque_sensor.h" #include "eeprom.h" #include "lights.h" +#include "delay.h" +#include "stm8s_tim3.h" ///////////////////////////////////////////////////////////////////////////////////////////// //// Functions prototypes @@ -64,13 +66,28 @@ void HALL_SENSOR_C_PORT_IRQHandler(void) __interrupt(EXTI_HALL_C_IRQ); ///////////////////////////////////////////////////////////////////////////////////////////// #ifdef TIME_DEBUG -static uint8_t ui8_main_time; -uint8_t ui8_max_ebike_time = 0; +static uint16_t ebike_app_time; +static uint16_t ebike_app_time_max = 0; #endif -static uint8_t ui8_1ms_counter = 0; -static uint8_t ui8_ebike_app_controller_counter = 0; +volatile uint8_t u8_isr_load_perc = 100U; +static uint16_t isr_load_delta_tim; + +/** + * Calculates the ISR load percentage. + * The function intentionally wastes a known time amount of cpu cycles + * and compares with how long it actually took to execute. + */ +static void calc_isr_load(void){ + #define MEAS_WINDOW 184U // uS - divides nicely inside T_COUNT_US + uint16_t tim3_prev = TIM3_GetCounter(); + delay_us(MEAS_WINDOW); // precisly tuned delay - can be verified by comparing to isr_load_delta_tim with enableInterrupts() commented ouut + isr_load_delta_tim = (uint16_t)(TIM3_GetCounter() - tim3_prev) * (1000U / 256U); // uS + u8_isr_load_perc = 100U - (uint8_t)(100U * MEAS_WINDOW / isr_load_delta_tim); +} + + int main(void) { // set clock at the max 16 MHz @@ -94,26 +111,29 @@ int main(void) { enableInterrupts(); ebike_app_init(); - while (1) { - ui8_1ms_counter = ui8_tim4_counter; - // run every 25ms. Max measured ebike_app_controller() duration is 3,1 ms. - if ((uint8_t)(ui8_1ms_counter - ui8_ebike_app_controller_counter) >= 25U) { + + #define EBIKE_TASK_MS 25U + while (1) { + static uint8_t ui8_ebike_app_controller_counter = 0U; + + // run every 25ms. Measured duration ebike_app_controller() is 1ms average and 4ms peak. + if ((uint8_t)(ui8_1ms_counter - ui8_ebike_app_controller_counter) >= EBIKE_TASK_MS) { + ui8_ebike_app_controller_counter = ui8_1ms_counter; #ifdef TIME_DEBUG - // incremented every 50us by PWM interrupt function - ui8_main_time = 0; + uint16_t tim3_prev = TIM3_GetCounter(); // use TIM3 to measure exact duration of ebike_app_controller() #endif - ui8_ebike_app_controller_counter = ui8_1ms_counter; ebike_app_controller(); #ifdef TIME_DEBUG - ui8_main_time = ui8_tim4_counter - ui8_main_time - if (ui8_main_time > ui8_max_ebike_time) { - ui8_max_ebike_time = ui8_main_time; - } + uint16_t tim3_delta = (uint16_t)(TIM3_GetCounter() - tim3_prev); // this can wrap around correctly because tim3 period is full 16bit (0xffff) + ebike_app_time = tim3_delta * (uint8_t)(1000U/125U); // measure ebike_app_controller duration in uS, tim3 is 250khz + if (ebike_app_time > ebike_app_time_max) {ebike_app_time_max = ebike_app_time;} #endif } + + calc_isr_load(); } } diff --git a/src/main.h b/src/main.h index 03584520..fab9ce4f 100644 --- a/src/main.h +++ b/src/main.h @@ -15,6 +15,8 @@ //#define TIME_DEBUG //#define HALL_DEBUG +extern volatile uint8_t u8_isr_load_perc; + //#define FW_VERSION 15 // mspider65 /*--------------------------------------------------------- @@ -37,6 +39,8 @@ // ---------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------- +#define F_CPU (HSI_VALUE / 1U) //cpu frequency, based on HSI clock and 1x prescaler + //#define PWM_FREQ 18 // 18 Khz #define PWM_FREQ 19 // 19 Khz @@ -57,7 +61,7 @@ #define OEM_WHEEL_SPEED_DIVISOR 363 // at 18 KHz #endif -#define PWM_CYCLES_SECOND (16000000/(PWM_COUNTER_MAX*2)) // 55.5us (PWM period) 18 Khz +#define PWM_CYCLES_SECOND ((uint16_t)(F_CPU / (PWM_COUNTER_MAX*2))) // 55.5us (PWM period) 18 Khz /*--------------------------------------------------------- NOTE: regarding duty cycle (PWM) ramping diff --git a/src/timers.c b/src/timers.c index 166a5448..4281c8f2 100644 --- a/src/timers.c +++ b/src/timers.c @@ -9,7 +9,7 @@ #include "stm8s.h" #include "interrupts.h" -volatile uint8_t ui8_tim4_counter = 0; +volatile uint8_t ui8_1ms_counter = 0; #ifdef __CDT_PARSER__ #define __interrupt(x) @@ -25,13 +25,13 @@ void timers_init(void) { timer4_init(); } -// Timer2 is used to create the pulse signal for excitation of the torque sensor circuit +// 16bit Timer2 is used to create the pulse signal for excitation of the torque sensor circuit // Pulse signal: period of 20us, Ton = 2us, Toff = 18us void timer2_init(void) { uint16_t ui16_i; // Timer2 clock = 16MHz; target: 20us period --> 50khz - // counter period = (1 / (16000000 / prescaler)) * (159 + 1) = 20us + // counter period = 1/ (16000000 / 2 / (159 + 1)) = 20us TIM2_TimeBaseInit(TIM2_PRESCALER_2, 159); // pulse of 2us @@ -51,7 +51,7 @@ void timer2_init(void) { } } -// HALL sensor time counter (250 KHz, 4us period, 1deg resolution at max rotor speed of 660ERPS) +// HALL sensor 16bit time counter (250 KHz, 4us period, 1deg resolution at max rotor speed of 660ERPS) // Counter is used to measure the time between Hall sensors transitions. // Hall sensor GPIO IRQ is used to read counter reference value at every Hall sensor transition void timer3_init(void) { @@ -59,7 +59,7 @@ void timer3_init(void) { // TIM3 Peripheral Configuration TIM3_DeInit(); - TIM3_TimeBaseInit(TIM3_PRESCALER_64, 0xffff); // 16MHz/64=250KHz + TIM3_TimeBaseInit(TIM3_PRESCALER_64, 0xffff); // timer clock: 16MHz/64=250KHz TIM3_Cmd(ENABLE); // TIM3 counter enable // IMPORTANT: this software delay is needed so timer3 work after this @@ -68,25 +68,25 @@ void timer3_init(void) { } } -// TIM4 configuration used to generate a 1ms counter (Counter overflow every 1ms) +// 8bit TIM4 configuration used to generate a 1ms counter (Counter overflow every 1ms) void timer4_init(void) { uint16_t ui16_i; TIM4_DeInit(); - TIM4_TimeBaseInit(TIM4_PRESCALER_128, 0x7d); // Freq = 16MHz/128*125=1KHz (1ms) + TIM4_TimeBaseInit(TIM4_PRESCALER_128, 125U-1U); // timer clock = 16MHz/128 = 125khz ; timer period = 125khz/125=1KHz (1ms) ITC_SetSoftwarePriority(TIM4_OVF_IRQHANDLER, ITC_PRIORITYLEVEL_1); // 1 = lowest priority TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE); // Enable Update/Overflow Interrupt (see below TIM4_IRQHandler function) - TIM4_Cmd(ENABLE); // TIM4 counter enable // IMPORTANT: this software delay is needed so timer3 work after this for (ui16_i = 0; ui16_i < (65000); ui16_i++) { ; } + TIM4_Cmd(ENABLE); // TIM4 counter enable } // TIM4 Overflow Interrupt handler void TIM4_IRQHandler(void) __interrupt(TIM4_OVF_IRQHANDLER) { - ui8_tim4_counter++; + ui8_1ms_counter++; TIM4->SR1 = 0; // Reset interrupt flag } diff --git a/src/timers.h b/src/timers.h index 93404f92..cdbb4237 100644 --- a/src/timers.h +++ b/src/timers.h @@ -9,8 +9,11 @@ #ifndef _TIMERS_H_ #define _TIMERS_H_ +#include + void timers_init(void); -extern volatile uint8_t ui8_tim4_counter; +extern volatile uint8_t ui8_1ms_counter; + #endif /* _TIMERS_H_ */ diff --git a/tools/STMstudio.tsc b/tools/STMstudio.tsc new file mode 100644 index 00000000..0d12908c --- /dev/null +++ b/tools/STMstudio.tsc @@ -0,0 +1,159 @@ +#STM Touch Studio user settings - do not edit +#Tue Jul 16 03:08:47 BST 2024 +ExprVariable.Col0ModelIdx=0 +ExprVariable.Col0Width=15 +ExprVariable.Col1ModelIdx=1 +ExprVariable.Col1Width=129 +ExprVariable.Col2ModelIdx=2 +ExprVariable.Col2Width=131 +ExprVariable.Col3ModelIdx=3 +ExprVariable.Col3Width=130 +ExprVariable.Col4ModelIdx=4 +ExprVariable.Col4Width=40 +ExprVariable.Number=0 +GdbVar.ExecDate=1721095586473 +GdbVar.LastExecRelative=..\\Debug\\main.elf +GdbVar.Version=1 +GeneralPurpose.HorizontalSplit=465 +GeneralPurpose.ScrollAcq.Height=170 +GeneralPurpose.ScrollExpr.Height=60 +GeneralPurpose.ScrollPlugin.Height=124 +GeneralPurpose.ScrollStat.Height=0 +GeneralPurpose.Version=3 +GeneralPurpose.VerticalSplit1=60 +GeneralPurpose.VerticalSplit2=65 +GeneralPurpose.VerticalSplit3=171 +GeneralPurpose.VerticalSplit4=434 +Interface.LogPostProcessingEnable=true +Interface.RefreshRate=16 +Interface.Target=ST-Link SWIM +Interface.Version=2 +Log.AcqAllVariables=true +Log.AcqRate=-1 +Log.AcqVariablesVisible=false +Log.AppendMode=false +Log.CriticalLockAddr=0 +Log.DetectStm8LP=false +Log.DirectSynchronized=false +Log.EnableLog=true +Log.ExhaustiveDisplay=false +Log.FilenameRelative=..\\..\\..\\OneDrive\\Documents\\STMicroelectronics\\STMStudio\\log.txt +Log.GuiRate=false +Log.LittleEndian=false +Log.MaxConsecutiveCommErrors=10 +Log.MaxConsecutiveHalt=40 +Log.OnlyVariations=false +Log.RawFrame=false +Log.ReInitComm=true +Log.Replay=false +Log.SubSamplingSnapshot=1 +Log.TraceHeaderAddr=0 +Log.Trigger.AutoRestart=false +Log.Trigger.BySymbol=false +Log.Trigger.IgnoreTrig=false +Log.Trigger.NameBySymbol=Unknown +Log.Trigger.ParamStop=0 +Log.Trigger.RestartTimestamp=false +Log.Trigger.SnapshotMode=false +Log.Trigger.StartMode=0 +Log.Trigger.StopMode=0 +Log.Trigger.Threshold=0 +Log.Trigger.ThresholdBySymbol=0 +Log.Trigger.TrigToAllVar=false +Log.Trigger.VarAddr=0 +Log.Trigger.VarType=0 +Log.Trigger.nPreTrig=0 +Log.Version=13 +Main.Version=6 +StatVariable.Col0ModelIdx=0 +StatVariable.Col0Width=15 +StatVariable.Col1ModelIdx=1 +StatVariable.Col1Width=98 +StatVariable.Col2ModelIdx=2 +StatVariable.Col2Width=98 +StatVariable.Col3ModelIdx=3 +StatVariable.Col3Width=97 +StatVariable.Col4ModelIdx=4 +StatVariable.Col4Width=97 +StatVariable.Col5ModelIdx=5 +StatVariable.Col5Width=40 +StatVariable.Number=0 +TouchPointViewer.Name=Point Viewer +TouchPointViewer.Number=1 +TouchPointViewer.SecondScreen=false +TouchPointViewer.Version=3 +TouchPointViewer.Visible=false +TouchPointViewer.XRange.Low=-255 +TouchPointViewer.XRange.Up=255 +TouchPointViewer.YRange.Low=-255 +TouchPointViewer.YRange.Up=255 +VarViewer.DisplayAllMode=Curve +VarViewer.Number=3 +VarViewer.SelectedTab=3 +VarViewer.ShowIndex=false +VarViewer.Version=4 +VarViewer1.DisplayMode=Curve +VarViewer1.Hexa=false +VarViewer1.Name=CPU +VarViewer1.Range.Low=0.0 +VarViewer1.Range.Up=74.0 +VarViewer1.SecondScreen=false +VarViewer1.Var.Nb=1 +VarViewer1.Var0.Name=u8_isr_load_perc +VarViewer1.Visible=true +VarViewer2.DisplayMode=Curve +VarViewer2.Hexa=false +VarViewer2.Name=Times +VarViewer2.Range.Low=0.0 +VarViewer2.Range.Up=4400.0 +VarViewer2.SecondScreen=false +VarViewer2.Var.Nb=1 +VarViewer2.Var0.Name=ebike_app_time +VarViewer2.Visible=true +Variable.Col0ModelIdx=0 +Variable.Col0Width=15 +Variable.Col1ModelIdx=1 +Variable.Col1Width=183 +Variable.Col2ModelIdx=2 +Variable.Col2Width=104 +Variable.Col3ModelIdx=3 +Variable.Col3Width=103 +Variable.Col4ModelIdx=4 +Variable.Col4Width=40 +Variable.Number=3 +Variable.Version=5 +Variable0.AcqMode=false +Variable0.Address=1 +Variable0.Color=0xff6633 +Variable0.Name=ebike_app_time +Variable0.Type=unsigned 16-bit +Variable1.AcqMode=false +Variable1.Address=393 +Variable1.Color=0x006666 +Variable1.Name=ebike_app_time_max +Variable1.Type=unsigned 16-bit +Variable2.AcqMode=false +Variable2.Address=395 +Variable2.Color=0x6699ff +Variable2.Name=u8_isr_load_perc +Variable2.Type=unsigned 8-bit +Viewers.Synchronized=false +ViewersLayout.IntegratedLayout.Weight.0=0.49467455621301776 +ViewersLayout.IntegratedLayout.Weight.1=0.5017751479289941 +ViewersLayout.IntegratedLayout.Weight.Size=2 +ViewersLayout.Position.0=-1 +ViewersLayout.Position.1=0 +ViewersLayout.Position.2=1 +ViewersLayout.Position.Size=3 +ViewersLayout.Version=1 +WriteVariable.Col0ModelIdx=0 +WriteVariable.Col0Width=15 +WriteVariable.Col1ModelIdx=1 +WriteVariable.Col1Width=108 +WriteVariable.Col2ModelIdx=2 +WriteVariable.Col2Width=108 +WriteVariable.Col3ModelIdx=3 +WriteVariable.Col3Width=107 +WriteVariable.Col4ModelIdx=4 +WriteVariable.Col4Width=107 +WriteVariable.Number=0 diff --git a/tools/STMstudio_CPU.tsp b/tools/STMstudio_CPU.tsp new file mode 100644 index 00000000..d66a9a9e --- /dev/null +++ b/tools/STMstudio_CPU.tsp @@ -0,0 +1,10 @@ +#STM Studio project file - do not edit +#Tue Jul 16 03:08:47 BST 2024 +Main.Version=1 +Root.Child0.IsActive=true +Root.Child0.Name=STMstudio +Root.Child0.PathRelative=STMstudio.tsc +Root.Child0.Type=config +Root.ChildNb=1 +Root.Name=STMstudio_CPU +Root.Type=folder