Observe shared TWI0 IRQ in nRF radio timing captures

This commit is contained in:
mikecarper committed 2026-10-23 04:08:05 -07:00
1 parent 1b97c089a7
commit aa480ae79e
5 files changed
+23 -12

No files matched your search

+3 -3
View File
@@ -103,7 +103,7 @@ class Nrf52HilIrqBindingTest(unittest.TestCase):
self.assertNotIn("__file__", scope)
self.assertEqual(len(env.middleware), expected)
def test_startup_changes_only_six_vectors_and_preserves_all_real_aliases(self):
def test_startup_changes_only_selected_vectors_and_preserves_all_real_aliases(self):
patched = PATCH.patched_startup(STARTUP.replace("\n", "\r\n"))
self.assertEqual(PATCH.patched_startup(patched), patched)
expected = STARTUP
@@ -185,13 +185,13 @@ class Nrf52HilIrqBindingTest(unittest.TestCase):
source = '#include <cassert>\n#include <cstdint>\n'
source += 'extern "C" const uint32_t test_vectors[];\n'
source += 'extern "C" void SVC_Handler() {}\nextern "C" void PendSV_Handler() {}\n'
source += "static unsigned real_calls[6], wrapped_calls[6];\n"
source += f"static unsigned real_calls[{len(PATCH.IRQ_HANDLERS)}], wrapped_calls[{len(PATCH.IRQ_HANDLERS)}];\n"
for index, symbol in enumerate(PATCH.IRQ_HANDLERS):
source += f'extern "C" void {symbol}() {{ ++real_calls[{index}]; }}\n'
source += f'extern "C" void __real_{symbol}();\n'
source += (f'extern "C" void __wrap_{symbol}() {{ ++wrapped_calls[{index}]; '
f'__real_{symbol}(); }}\n')
source += "int main() { for (unsigned i = 0; i < 6; ++i) { "
source += f"int main() {{ for (unsigned i = 0; i < {len(PATCH.IRQ_HANDLERS)}; ++i) {{ "
source += "reinterpret_cast<void(*)()>(uintptr_t(test_vectors[i+2]))(); "
source += "assert(real_calls[i] == 1); assert(wrapped_calls[i] == EXPECT_WRAPPED); } }\n"
(directory / "handlers.cpp").write_text(source)
+13 -5
View File
@@ -27,7 +27,7 @@ FIXTURE=r'''
#include <helpers/radiolib/ProfileSwitchTiming.h>
@TIMING_GLOBALS@
DwtMock dwt;
unsigned real_calls[7]{},durations[7]={640,128,192,256,320,384,448};
unsigned real_calls[8]{},durations[8]={640,128,192,256,320,384,448,512};
bool nested=false;
const char* selected_task_name="loop";
const char* pcTaskGetName(void* task) { assert(task==nullptr);return selected_task_name; }
@@ -38,6 +38,7 @@ extern "C" void __wrap_UARTE1_IRQHandler();
extern "C" void __wrap_POWER_CLOCK_IRQHandler();
extern "C" void __wrap_USBD_IRQHandler();
extern "C" void __wrap_vTaskSwitchContext();
extern "C" void __wrap_SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler();
extern "C" void __real_RTC1_IRQHandler() {
++real_calls[0];dwt.CYCCNT+=durations[0];
if(nested) __wrap_GPIOTE_IRQHandler();
@@ -49,15 +50,19 @@ REAL_HANDLER(UARTE1_IRQHandler,3)
REAL_HANDLER(POWER_CLOCK_IRQHandler,4)
REAL_HANDLER(USBD_IRQHandler,5)
REAL_HANDLER(vTaskSwitchContext,6)
REAL_HANDLER(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler,7)
int main() {
namespace obs=mesh::irqobserver;
namespace timing=mesh::profiletiming;
auto& capture=obs::mesh_hil_radio_irqs;
assert(capture.magic==0x4d434952 && capture.version==1 && capture.size_bytes==392 && capture.source_count==7);
assert(capture.magic==0x4d434952 && capture.version==2 && capture.size_bytes==424 && capture.source_count==8);
static_assert(obs::Scheduler==6 && obs::Twim0Spim0==7,"Original indices must remain stable");
static_assert(sizeof(obs::mesh_hil_irq_counters)==96,"IRQ counter bank size changed");
// Actual wrappers forward every source exactly once, with no active hop.
__wrap_UARTE0_UART0_IRQHandler();__wrap_UARTE1_IRQHandler();
__wrap_POWER_CLOCK_IRQHandler();__wrap_USBD_IRQHandler();__wrap_vTaskSwitchContext();
for(unsigned i=2;i<7;++i) assert(real_calls[i]==1);
__wrap_SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler();
for(unsigned i=2;i<8;++i) assert(real_calls[i]==1);
// Nested source time is explicitly inclusive in its parent; deltas remain
// per source and are attached to the same worst successful physical hop.
dwt.CYCCNT=100;durations[0]=640;durations[1]=128;nested=true;
@@ -94,9 +99,12 @@ int main() {
obs::mesh_hil_irq_counters[obs::Uart1].cycles=UINT32_MAX-10;
dwt.CYCCNT=UINT32_MAX-31;durations[3]=64;
timing::begin(1,0,timing::readClock());__wrap_UARTE1_IRQHandler();
__wrap_SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler();
timing::finish(timing::Success,timing::readEndpointClock());
assert(capture.direction[1].last_ticks==64 && capture.direction[1].last.calls[obs::Uart1]==1);
assert(capture.direction[1].last_ticks==576 && capture.direction[1].last.calls[obs::Uart1]==1);
assert(capture.direction[1].last.cycles[obs::Uart1]==64);
assert(capture.direction[1].last.calls[obs::Twim0Spim0]==1 && capture.direction[1].last.cycles[obs::Twim0Spim0]==512);
assert(capture.direction[1].worst.calls[obs::Twim0Spim0]==1 && capture.direction[1].worst.cycles[obs::Twim0Spim0]==512);
// A permanently odd writer sequence cannot hang the application or publish
// stale counter data as valid attribution. Timing itself remains available.
obs::mesh_hil_irq_counters[obs::Gpiote].sequence=1;
@@ -106,7 +114,7 @@ int main() {
dwt.CYCCNT+=128;
timing::finish(timing::Success,timing::readEndpointClock());
assert(capture.snapshot_failures==failures+1 && !capture.direction[1].last_valid);
for(unsigned i=0;i<7;++i) {
for(unsigned i=0;i<8;++i) {
assert(capture.direction[1].last.calls[i]==0 && capture.direction[1].last.cycles[i]==0);
}
assert(capture.sequence%2==0 && capture.snapshots==10 && capture.retries>=8);