bsps/mips/jmr3904: Raise tm27 with a software int

Cause_tm27_intr() reprogrammed timer 0 of the TX3904 to fire after 20
clicks.  That timer is the clock tick, so the macro left its compare
register at 20 instead of the clicks per tick, and Clear_tm27_intr() did
not restore it.  It also made the interrupt arrive 20 clicks later
rather than at once.

The validation tests which run code from an interrupt depend on the
arrival being immediate.  They hook the block operation of the scheduler
and submit the request from there, so the interrupt has to reach the
thread while it intends to block.  With the delay the thread was blocked
long before, and 245 test steps of ts-validation-no-clock-0 and one of
ts-validation-one-cpu-0 checked a state which had already passed.

The processor has two software interrupts and the BSP drives them
through rtems_interrupt_raise() already, so use one of them.  It is
pending from the write on, it needs no timer, and it leaves the clock
tick alone.  Both test suites report no failed step now.

The entry overhead which tm27 reports falls from 26 to 7, because the
measured path no longer contains the five register writes which armed
the timer.

Close #5688.

Assisted-by: Claude:claude-opus-5 claude-code
Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
This commit is contained in:
Sebastian Huber
2026-08-20 18:23:09 -05:00
committed by Joel Sherrill
parent a57578d817
commit 62c5b37a62
+36 -22
View File
@@ -22,33 +22,47 @@
*/
#include <bsp/irq.h>
#include <rtems/score/isr.h>
#define MUST_WAIT_FOR_INTERRUPT 1
#define Install_tm27_vector( handler ) \
rtems_interrupt_handler_install( \
TX3904_IRQ_TMR0, "benchmark", 0, \
handler, NULL );
#define TM27_INTERRUPT_VECTOR_DEFAULT TX3904_IRQ_SOFTWARE_1
#define Cause_tm27_intr() \
do { \
uint32_t _clicks = 20; \
TX3904_TIMER_WRITE( TX3904_TIMER0_BASE, TX3904_TIMER_CCDR, 0x3 ); \
TX3904_TIMER_WRITE( TX3904_TIMER0_BASE, TX3904_TIMER_CPRA, _clicks ); \
TX3904_TIMER_WRITE( TX3904_TIMER0_BASE, TX3904_TIMER_TISR, 0x00 ); \
TX3904_TIMER_WRITE( TX3904_TIMER0_BASE, TX3904_TIMER_ITMR, 0x8001 ); \
TX3904_TIMER_WRITE( TX3904_TIMER0_BASE, TX3904_TIMER_TCR, 0xC0 ); \
*((volatile uint32_t*) 0xFFFFC01C) = 0x00000700; \
} while(0)
static rtems_interrupt_entry jmr3904_tm27_interrupt_entry;
#define Clear_tm27_intr() \
do { \
TX3904_TIMER_WRITE( TX3904_TIMER0_BASE, TX3904_TIMER_ITMR, 0x0001 ); \
TX3904_TIMER_WRITE( TX3904_TIMER0_BASE, TX3904_TIMER_CCDR, 0x3 ); \
TX3904_TIMER_WRITE( TX3904_TIMER0_BASE, TX3904_TIMER_TISR, 0x00 ); \
} while(0)
static inline void Install_tm27_vector( rtems_interrupt_handler handler )
{
rtems_interrupt_entry_initialize(
&jmr3904_tm27_interrupt_entry,
handler,
NULL,
"tm27"
);
(void) rtems_interrupt_entry_install(
TM27_INTERRUPT_VECTOR_DEFAULT,
RTEMS_INTERRUPT_SHARED,
&jmr3904_tm27_interrupt_entry
);
}
#define Lower_tm27_intr() \
mips_enable_in_interrupt_mask( 0xff01 );
/*
* The software interrupt of the processor is a bit of the cause register, so
* it is pending from the write on and arrives as soon as the interrupts are
* enabled. It stays pending until it is cleared.
*/
static inline void Cause_tm27_intr( void )
{
(void) rtems_interrupt_raise( TM27_INTERRUPT_VECTOR_DEFAULT );
}
static inline void Clear_tm27_intr( void )
{
(void) rtems_interrupt_clear( TM27_INTERRUPT_VECTOR_DEFAULT );
}
static inline void Lower_tm27_intr( void )
{
_ISR_Set_level( 0 );
}
#endif