Skip to content

Commit

Permalink
Measure ISR load, cleaned up timers, added tuned delay functions, add…
Browse files Browse the repository at this point in the history
… STMStudio setup and basic layout
  • Loading branch information
dzid26 committed Jul 17, 2024
1 parent 90d69d2 commit 8f60421
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 26 deletions.
82 changes: 82 additions & 0 deletions src/delay.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* delay utilite for STM8 family
* COSMIC and SDCC
* Terentiev Oleg
* [email protected]
*/

#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

3 changes: 3 additions & 0 deletions src/ebike_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
50 changes: 35 additions & 15 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "torque_sensor.h"
#include "eeprom.h"
#include "lights.h"
#include "delay.h"
#include "stm8s_tim3.h"

/////////////////////////////////////////////////////////////////////////////////////////////
//// Functions prototypes
Expand Down Expand Up @@ -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
Expand All @@ -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();
}
}
6 changes: 5 additions & 1 deletion src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
//#define TIME_DEBUG
//#define HALL_DEBUG

extern volatile uint8_t u8_isr_load_perc;

//#define FW_VERSION 15 // mspider65

/*---------------------------------------------------------
Expand All @@ -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
Expand All @@ -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
Expand Down
18 changes: 9 additions & 9 deletions src/timers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -51,15 +51,15 @@ 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) {
uint16_t ui16_i;

// 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
Expand All @@ -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
}

5 changes: 4 additions & 1 deletion src/timers.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
#ifndef _TIMERS_H_
#define _TIMERS_H_

#include <stdint.h>

void timers_init(void);

extern volatile uint8_t ui8_tim4_counter;
extern volatile uint8_t ui8_1ms_counter;


#endif /* _TIMERS_H_ */
Loading

0 comments on commit 8f60421

Please sign in to comment.