Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions examples/0timerint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,26 @@ Also, after a given number of invocations the ISR detaches itself.

#### Control

* `0`, `1`,`2` selects `ccompare0`, `ccompare1` or `ccompare2` for measurement.
* `0`, `1`,`2` selects `ccompare0`, `ccompare1` or `ccompare2` for measurement (default: 0).
* `[`,`]` for decrease/increase sampling length by `1`.
* `{`,`}` for decrease/increase sampling length by `10`.
* `,`,`.` for decrease/increase interrupt period by `1`.
* `<`,`>` for decrease/increase interrupt period by `10`.
* `s` starts the measurement.
* `r` prints the result of the last measurement.
* `C` prints some register and pointer information for debugging.
* `g` use general ISR (with xthal calls, slower, default).
* `G` use timer-specific ISR (with SRS()/WSR() calls).

#### Experience

* `TIMER.0` interrupt period gets stable around 264 ccompare increment (and above), (i.e., 1.65 µs, running at 160MHz).
* `TIMER.1` interrupt period gets stable around 230 ccompare increment (and above), (i.e., 1.44 µs, running at 160MHz).
* `TIMER.2` interrupt period gets stable around 484 ccompare increment (and above), (i.e., 3 µs, running at 160MHz).
* `TIMER.0` general interrupt period gets stable (no jitter) around 264 ccompare increment (and above), (i.e., 1.65 µs, running at 160MHz).
* `TIMER.1` general interrupt period gets stable around 230 ccompare increment (and above), (i.e., 1.44 µs, running at 160MHz).
* `TIMER.2` general interrupt period gets stable around 484 ccompare increment (and above), (i.e., 3 µs, running at 160MHz).
Note, however, `xt_highint5` is not implemented yet, i.e., we use the general ISR written in C.

Using hardwired RSR()/WSR() macros, at 184 ccompare increment the interrupt period is stable (meaning 1.15 µs).
Using the timer-specific ISRs with hardwired RSR()/WSR() macros,
the interrupt period gets stable at 220 (TIMER.0) and 178 (TIMER.1) ccompare increment (meaning 1.4 µs, 1.1 µs).

Note, the highest interrupt frequency we get with `TIMER.0` or `TIMER.1` is almost twice as high as the best frequency we get
using [TIMG ALARM interrupt](../0timgalarm)).
103 changes: 79 additions & 24 deletions examples/0timerint/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@

// ============= Local types ===============

typedef enum {
CTIMER0 = 0,
CTIMER1 = 1,
CTIMER2 = 2
} ECCompareIdx;

/// The results of the last measurement are stored in such structure.

typedef struct {
Expand All @@ -57,8 +63,9 @@ typedef struct {

typedef struct {
bool bOngoing; ///< true: there is measurement process.going on.
bool bGeneral; ///< use gerenal ISR
ECCompareIdx eCcompare;
TimerId sTimer; ///< Reference clock to read out current time value
uint32_t u32CcompareIdx;
uint32_t u32cycPeriod;
uint32_t u32SampleLen; ///< Total number of samples to take.
uint32_t u32SampleIdx; ///< How many samples are still to take.
Expand All @@ -67,9 +74,11 @@ typedef struct {


// ================ Local function declarations =================
static void _ccompare_isr_attach();
static void _ccompare_stop();
static void _ccompare_isr(void *pvParam);
static void _timerx_isr_attach();
static void _timerx_stop();
static void _timerx_general_isr(void *pvParam);
static void _timer0_isr(void *pvParam);
static void _timer1_isr(void *pvParam);

static void _measurement_start(MeasurementState * psParam);
static void _print_resultline(uint32_t u32Idx, const Result *psResult);
Expand All @@ -91,8 +100,11 @@ DRAM_ATTR static Result gsResult = {
};
static bool gbAppCpuStarted = false;
DRAM_ATTR static MeasurementState gsMeasParam = {
.bOngoing = false,
.bGeneral = false,
.eCcompare = CTIMER0,
.sTimer =
{TIMG_0, TIMER0},
{TIMG_0, CTIMER0},
.u32cycPeriod = COMPAREINC_VAL_INIT,
.u32SampleLen = SAMPLE_INIT,
.u32SampleIdx = SAMPLE_INIT,
Expand All @@ -102,48 +114,83 @@ DRAM_ATTR static MeasurementState gsMeasParam = {
// ============== Implementation ==============
// -------------- Internal functions --------------

IRAM_ATTR static void _ccompare_isr(void *pvParam) {
IRAM_ATTR static void _timerx_general_isr(void *pvParam) {
MeasurementState *psParam = (MeasurementState*)pvParam;

uint32_t u32CurrCnt;
// note, the xthal_xxx() register access is slower than RSR/WSR access, nevertheless, it is more elastic.
// beeing #define macros, in case of RSR/WSR we have to explicitly set CCOMPAREn as first parameter.
u32CurrCnt = xthal_get_ccompare(psParam->u32CcompareIdx);
// RSR(CCOMPARE1, u32CurrCnt);
u32CurrCnt = xthal_get_ccompare(psParam->eCcompare);
u32CurrCnt += psParam->u32cycPeriod;
xthal_set_ccompare(psParam->eCcompare, u32CurrCnt);

// storing clock value
gsResult.au64tckSample[psParam->u32SampleIdx] = timg_ticks(psParam->sTimer);
++psParam->u32SampleIdx;

if (psParam->u32SampleIdx == psParam->u32SampleLen) {
_timerx_stop(pvParam);
}
}

IRAM_ATTR static void _timer0_isr(void *pvParam) {
MeasurementState *psParam = (MeasurementState*)pvParam;

uint32_t u32CurrCnt;
RSR(CCOMPARE0, u32CurrCnt);
u32CurrCnt += psParam->u32cycPeriod;
WSR(CCOMPARE0, u32CurrCnt);

// storing clock value
gsResult.au64tckSample[psParam->u32SampleIdx] = timg_ticks(psParam->sTimer);
++psParam->u32SampleIdx;

if (psParam->u32SampleIdx == psParam->u32SampleLen) {
_timerx_stop(pvParam);
}
}

IRAM_ATTR static void _timer1_isr(void *pvParam) {
MeasurementState *psParam = (MeasurementState*)pvParam;

uint32_t u32CurrCnt;
RSR(CCOMPARE1, u32CurrCnt);
u32CurrCnt += psParam->u32cycPeriod;
xthal_set_ccompare(psParam->u32CcompareIdx, u32CurrCnt);
// WSR(CCOMPARE1, u32CurrCnt);
WSR(CCOMPARE1, u32CurrCnt);

// storing clock value
gsResult.au64tckSample[psParam->u32SampleIdx] = timg_ticks(psParam->sTimer);
++psParam->u32SampleIdx;

if (psParam->u32SampleIdx == psParam->u32SampleLen) {
_ccompare_stop(pvParam);
_timerx_stop(pvParam);
}
}

IRAM_ATTR static void _ccompare_stop(void *pvParam) {
IRAM_ATTR static void _timerx_stop(void *pvParam) {
MeasurementState *psParam = (MeasurementState*)pvParam;

ets_isr_mask(1 << gau8TimerIntNum[psParam->u32CcompareIdx]);
_xtos_set_interrupt_handler(gau8TimerIntNum[psParam->u32CcompareIdx], NULL);
ets_isr_mask(1 << gau8TimerIntNum[psParam->eCcompare]);
_xtos_set_interrupt_handler(gau8TimerIntNum[psParam->eCcompare], NULL);

psParam->bOngoing = false;
uart_printf(&gsUART0, " Done.\r\n");
}

IRAM_ATTR static void _ccompare_isr_attach(void *pvParam) {
IRAM_ATTR static void _timerx_isr_attach(void *pvParam) {
MeasurementState *psParam = (MeasurementState*)pvParam;
Isr fIsr = psParam->bGeneral ? _timerx_general_isr :
psParam->eCcompare == CTIMER0 ? _timer0_isr :
psParam->eCcompare == CTIMER1 ? _timer1_isr :
_timerx_general_isr;
uint32_t u32Ccount;
u32Ccount = xthal_get_ccount();
// RSR(CCOUNT, u32Ccount);
uint32_t u32Ccompare = u32Ccount;
u32Ccompare += psParam->u32cycPeriod;
xthal_set_ccompare(psParam->u32CcompareIdx, u32Ccompare);
// WSR(CCOMPARE1, u32Ccompare);
_xtos_set_interrupt_handler_arg(gau8TimerIntNum[psParam->u32CcompareIdx], _ccompare_isr, (int)pvParam);
ets_isr_unmask(1 << gau8TimerIntNum[psParam->u32CcompareIdx]);
xthal_set_ccompare(psParam->eCcompare, u32Ccompare);

_xtos_set_interrupt_handler_arg(gau8TimerIntNum[psParam->eCcompare], fIsr, (int)pvParam);
ets_isr_unmask(1 << gau8TimerIntNum[psParam->eCcompare]);
}

static void _measurement_start(MeasurementState * psParam) {
Expand All @@ -153,7 +200,7 @@ static void _measurement_start(MeasurementState * psParam) {
psParam->psResult->u32cycPeriod = psParam->u32cycPeriod;
psParam->psResult->u32SampleLen = psParam->u32SampleLen;

_ccompare_isr_attach(psParam);
_timerx_isr_attach(psParam);

psParam->psResult->au64tckSample[0] = timg_ticks(psParam->sTimer);
}
Expand All @@ -178,7 +225,7 @@ static void _uart_cycle(uint64_t u64tckNow) {
case '1':
case '2': // TIMG_1 TIMER0
uart_printf(&gsUART0, "Using ccompare%c\r\n", cCtrl);
gsMeasParam.u32CcompareIdx = cCtrl - '0';
gsMeasParam.eCcompare = cCtrl - '0';
break;
case 'r': // print result
u32PrintNR = 0;
Expand All @@ -187,13 +234,21 @@ static void _uart_cycle(uint64_t u64tckNow) {
case 's': // start measurement
_measurement_start(&gsMeasParam);
break;
case 'g':
gsMeasParam.bGeneral = true;
uart_printf(&gsUART0, "Using general ISR\r\n");
break;
case 'G':
gsMeasParam.bGeneral = false;
uart_printf(&gsUART0, "Using CCOMPAREn-specific ISR\r\n");
break;
case 'c': // current Reg values
break;
case 'C':
uart_printf(&gsUART0, "ISR addr: %p, dat: %p %p\r\n", _ccompare_isr, &gsResult, &gsMeasParam);
uart_printf(&gsUART0, "ISR addr: %p, dat: %p %p, size: %u\r\n", _timerx_general_isr, &gsResult, &gsMeasParam, sizeof (MeasurementState));
break;
case 'i':
uart_printf(&gsUART0, "Ccompare%u\r\n", gsMeasParam.u32CcompareIdx);
uart_printf(&gsUART0, "Ccompare%u\r\n", gsMeasParam.eCcompare);
break;

// Alarm value modification
Expand Down
7 changes: 6 additions & 1 deletion src/romfunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ extern "C" {
#include <stdbool.h>
#include <stdint.h>

#ifdef __XTENSA__
#define RSR(reg, curval) __asm__ volatile ("rsr %0, " #reg : "=r" (curval));
#define WSR(reg, newval) __asm__ volatile ("wsr %0, " #reg : : "r" (newval));

#else
#define RSR(reg, curval) while(0){};
#define WSR(reg, curval) while(0){};
#endif

void ets_isr_mask(uint32_t mask);
void ets_isr_unmask(uint32_t mask);
void *_xtos_set_interrupt_handler(int irq_number, void* function);
Expand Down
Loading