📄 load_meas.cxgate
字号:
#include "per_XDx512_L15Y.h"
#include "load_meas.h"
#pragma MESSAGE DISABLE C2705
#pragma CODE_SEG XGATE_CODE
#pragma DATA_SEG __RPAGE_SEG XGATE_DATA
/* These routines are used to measure loading of XGATE by any software algorithms */
/* In the current implementation the max. period allowed for 1 measurement is 65535 bus cycles, i.e. 1.638ms @ 40MHz */
/* ECT overflow interrupt, ECT modulus down counter or the selected PIT interrupt vector table entry must be pointing to the lm_timekeeping routine */
/* lm_init must be linked to XGATE SW interrupt number LM_INIT_SWX */
/* Example of use:
1. Initialise measurement system using the CPU:
SetIntPrio(LM_XGATE_VECTOR, RQST|3);
SetIntPrio(0x39-LM_INIT_SWX, RQST|1);
LM_INIT();
2. Use LM_START and LM_STOP at the beginning and end of the XGATE routine to be evaluated:
LM_START(n);
...
...
LM_STOP(n);
Argument of the lm_start/lm_stop call is the measurement channel number: 0..(LM_NO_OF_CHANNELS-1)
3. Read loading in lm_load array. 0 corresponds to 0% load, 65536 corresponds to 100% load
Peak execution time is in bus cycles (i.e. 25ns increments @ 40MHz bus)
Remarks:
A) Longest measurement which can be done is 65535 bus cycles
B) The measurement has certain amount of natural inaccuracy due to the bus running slower than XGATE clock, typically under 0.1% (depending on the number of calls to lm_start/lm_stop per measurement period)
C) Execution of the load measurement routines creates additional overhead for XGATE:
C1) lm_timekeeping takes 11 bus cycles to execute when the average load calculation is not performed
This happens every 65536 bus cycles, i.e. 0.0168% load
C2) lm_timekeeping takes 17+LM_NO_OF_CHANNELS*30.5 bus cycles to execute when the average load calculation is performed
This happens every (2^LM_MEAS_PERIOD)*65536 bus cycles
C3) LM_START(n) takes 9 bus cycles to execute
C4) LM_STOP(n) takes 32 bus cycles when the peak execution time is not recorded and 33 bus cycles when it is recorded
For example if LM_MEAS_PERIOD=10, LM_NO_OF_CHANNELS=3 and a measurement is performed every 10ms @ 40MHz bus the additional load will be:
(1023*11+(17+30.5*3))/1024/65536 + (9+33)/(10ms*40MHz) = 0.027%
The interrupt latency of XGATE will be extended by 17+30.5*3 = 108.5 bus cycles = 2.71us
Version:
1.0 Original coding
1.1 Added lm_peak_runtime to record maximum execution time on a given channel
1.2 Made the initialisation more user friendly and added support for the PIT & the modulus down counter of ECT
*/
#if defined(LM_USE_ECT)
#define LM_INIT_TIMER() Timer.tscr1.byte|=TEN|TSFRZ; /* enable the ECT, freeze it while debugging */\
Timer.tscr2.byte|=TOI /* enable overflow interrupt */
#define LM_TIMER_VAL() Timer.tcnt.word /* current value of the ECT counter */
#define LM_TIMER_ICLR() Timer.tflg2.byte=TOF /* clear the interrupt flag */
#elif defined(LM_USE_PIT)
/* PIT microtimer register access */
#define LM_PIT_MT_W(n) PIT.pitmtld##n
#define LM_PIT_MT(n) LM_PIT_MT_W(n)
/* PIT mux bit access */
#define LM_PIT_M_W(n) PIT.pitmux.bit.pmux##n
#define LM_PIT_M(n) LM_PIT_M_W(n)
/* PIT interrupt enable bit access */
#define LM_PIT_I_W(n) PIT.pitinte.bit.pinte##n
#define LM_PIT_I(n) LM_PIT_I_W(n)
/* PIT load register access */
#define LM_PIT_L_W(n) PIT.pitld##n
#define LM_PIT_L(n) LM_PIT_L_W(n)
/* PIT counter register access */
#define LM_PIT_C_W(n) PIT.pitcnt##n
#define LM_PIT_C(n) LM_PIT_C_W(n)
/* PIT interrupt flag access */
#define LM_PIT_F_W(n) PTF##n
#define LM_PIT_F(n) LM_PIT_F_W(n)
/* PIT channel bit access */
#define LM_PIT_CH_W(n) PIT.pitce.bit.pce##n
#define LM_PIT_CH(n) LM_PIT_CH_W(n)
/* initialise the PIT */
#define LM_INIT_TIMER() PIT.pitcflmt.byte|=PITE|PITFRZ; /* enable PIT, stop it while debugging */\
LM_PIT_MT(LM_USE_PIT_MT).byte=0; /* microtimer divides by 1 */\
LM_PIT_M(LM_USE_PIT_T)=LM_USE_PIT_MT; /* select microtimer for the selected channel */\
LM_PIT_L(LM_USE_PIT_T).word=0xffff; /* count down from 0xffff */\
LM_PIT_CH(LM_USE_PIT_T) = 1; /* enable PIT channel */\
LM_PIT_I(LM_USE_PIT_T) = 1 /* enable interrupts */
#define LM_TIMER_VAL() LM_PIT_C(LM_USE_PIT_T).word /* current value of the PIT counter */
#define LM_TIMER_ICLR() PIT.pittf.byte = LM_PIT_F(LM_USE_PIT_T) /* clear the interrupt flag */
#elif defined(LM_USE_MDC)
/* initialise the MDC (part of ECT) */
#define LM_INIT_TIMER() Timer.mccnt.word = 0xffff; /* count down from 0xffff */\
Timer.tscr1.byte|=TSFRZ; /* freeze the timer while debugging */\
Timer.ptmcpsr.byte = 0; /* set prescaler to 1 (in case the user sets PRNT in TSCR1) */\
Timer.mcctl.byte = MCZI|MODMC|MCEN /* enable interrupts, enable MCD */
#define LM_TIMER_VAL() Timer.mccnt.word /* current value of the down counter */
#define LM_TIMER_ICLR() Timer.mcflg.byte = MCZF; /* clear the interrupt flag */
#endif
unsigned int lm_load[LM_NO_OF_CHANNELS]; /* 0=0%, 65536=100% */
unsigned int lm_peak_runtime[LM_NO_OF_CHANNELS]; /* peak execution time in bus cycles */
unsigned int lm_average_runtime[LM_NO_OF_CHANNELS]; /* average execution time in bus cycles */
unsigned int lm_execution_count_hold[LM_NO_OF_CHANNELS];
static unsigned int lm_execution_count[LM_NO_OF_CHANNELS];
static unsigned long int lm_load_accumulator[LM_NO_OF_CHANNELS];
static unsigned int lm_start_time[LM_NO_OF_CHANNELS];
static unsigned int lm_timebase;
static unsigned int lm_overhead;
/* initialise the measurement */
void interrupt lm_init(void) {
signed char i;
XGATE.xgswt.word = (1<<LM_INIT_SWX)<<8; /* clear SW interrupt flag */
lm_timebase=(1<<LM_MEAS_PERIOD);
LM_INIT_TIMER();
lm_overhead=0;
LM_START(0);
LM_STOP(0);
lm_overhead=lm_load_accumulator[0];
for (i=LM_NO_OF_CHANNELS-1;i>=0;i--) {
lm_load[i]=0;
lm_load_accumulator[i]=0;
lm_peak_runtime[i]=0;
lm_execution_count[i]=0;
lm_average_runtime[i]=0;
}
}
/* start measurement */
void lm_start(unsigned char channel) {
lm_start_time[channel]=LM_TIMER_VAL();
}
/* stop measurement */
void lm_stop(unsigned char channel) {
register unsigned int exec_time;
#if defined(LM_USE_ECT)
exec_time=(LM_TIMER_VAL()-lm_start_time[channel]-lm_overhead);
#elif (defined(LM_USE_PIT)||defined(LM_USE_MDC))
exec_time=(lm_start_time[channel]-LM_TIMER_VAL()-lm_overhead);
#endif
lm_load_accumulator[channel]+=exec_time;
if (lm_peak_runtime[channel]<exec_time) lm_peak_runtime[channel]=exec_time;
lm_execution_count[channel]++;
}
/* timebase for the calculation */
void interrupt lm_timekeeping(void) {
LM_TIMER_ICLR(); /* clear the interrupt flag */
lm_timebase--;
if (lm_timebase==0) {
/* time is up, calculate loads */
unsigned char i;
for (i=0;i<LM_NO_OF_CHANNELS;i++) {
lm_load[i]=lm_load_accumulator[i]>>LM_MEAS_PERIOD; /* calculate the load */
lm_average_runtime[i]=lm_load_accumulator[i]/lm_execution_count[i];
lm_load_accumulator[i]=0; /* clear the accumulator */
lm_execution_count_hold[i]=lm_execution_count[i];
lm_execution_count[i]=0;
}
/* reinitialise timebase */
lm_timebase=(1<<LM_MEAS_PERIOD);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -