Hello,
I am trying to write an Application RoT for a research project I am a part of. I have run into an issue that I have been unable to solve independently.
My problem is the unexpected behavior of psa_wait() when using signal masks. I have two signals, TFM_TIMER1_IRQ_SIGNAL and TFM_SECURE_FUNCTION_SIGNAL. The TIMER1_IRQ signal is triggered by an FLIH interrupt handler that returns TFM_FLIH_SIGNAL. The interrupt is triggered every 1 second by TIMER1. The TFM_SECURE_FUNCTION_SIGNAL is triggered by a periodic function call from the NSPE (a Zephyr thread) and is called every 10 seconds.
Observed result: If PSA_WAIT_ANY is used as a signal mask, the TIMER0_IRQ_SIGNAL will only be received when TFM_SECURE_FUNCTION_SIGNAL is received, ergo, every 10 s. Thus any stage 2 handling of an interrupt would be missed.
If TFM_TIMER1_IRQ_SIGNAL is used as a signal mask, the signal will be received every 1 s as expected. The TFM_SECURE_FUNCTION_SIGNAL will never be received, as can be expected in the NSPEtoo.
I have tried a "hybrid approach" where I call psa_wait(TFM_TIMER1_IRQ_SIGNAL, PSA_BLOCK) /* handle signals .... */ and then psa_wait(TFM_SECURE_FUNCTION_SIGNAL, PSA_POLL). The stage 2 IRS is called, and the secure function is also called. But not with the regularity that I would like.
Am I missing something obvious? I have read the Secure Interrupt Integration Guide and carefully studied the SLIH and FLIH test services for the TF-M regression tests. Have I forgotten to reset a signal somewhere? Does the interrupt not preempt the NSPE?
I would be immensely grateful for any or all responses. If you need more information, please let me know.
Best wishes,
Martin Gunnarsson PhD Student RISE Research Institutes of Sweden & Lund University
Complete code of my Application RoT: #include <stdbool.h> #include <stdint.h> #include <stddef.h>
#include "tfm_api.h" #include "tfm_secure_api.h"
#include "psa/service.h" #include "tfm_sp_log.h"
#include "psa_manifest/pid.h" #include "psa_manifest/tfm_secure_partition.h"
#include <hal/nrf_gpio.h> #include <hal/nrf_timer.h> #include <helpers/nrfx_reset_reason.h> #include <nrf_board.h> #include <region_defs.h>
#define TIMER_RELOAD_VALUE (1*1024*1024) static volatile uint32_t interrupt_ctr = 0; static volatile uint32_t function_ctr = 0;
static void timer_init(NRF_TIMER_Type * TIMER) { nrf_timer_mode_set(TIMER, NRF_TIMER_MODE_TIMER); nrf_timer_bit_width_set(TIMER, NRF_TIMER_BIT_WIDTH_32); nrf_timer_frequency_set(TIMER, NRF_TIMER_FREQ_1MHz); nrf_timer_cc_set(TIMER, NRF_TIMER_CC_CHANNEL0, TIMER_RELOAD_VALUE); /* Clear the timer once event is generated. */ nrf_timer_shorts_enable(TIMER, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK); }
static void timer_stop(NRF_TIMER_Type * TIMER) { nrf_timer_task_trigger(TIMER, NRF_TIMER_TASK_STOP); nrf_timer_int_disable(TIMER, NRF_TIMER_INT_COMPARE0_MASK); nrf_timer_event_clear(TIMER, NRF_TIMER_EVENT_COMPARE0); }
static void timer_start(NRF_TIMER_Type * TIMER) { timer_stop(TIMER);
nrf_timer_task_trigger(TIMER, NRF_TIMER_TASK_CLEAR); nrf_timer_int_enable(TIMER, NRF_TIMER_INT_COMPARE0_MASK);
nrf_timer_task_trigger(TIMER, NRF_TIMER_TASK_START); }
static void timer_event_clear(NRF_TIMER_Type *TIMER) { nrf_timer_event_clear(TIMER, NRF_TIMER_EVENT_COMPARE0); }
void tfm_secure_controller_secure_timer_start(void) { timer_init(NRF_TIMER1); timer_start(NRF_TIMER1); }
void tfm_secure_controller_secure_timer_clear_intr(void) { timer_event_clear(NRF_TIMER1); }
psa_flih_result_t tfm_timer1_irq_flih(void) { tfm_secure_controller_secure_timer_clear_intr(); interrupt_ctr++; return PSA_FLIH_SIGNAL; }
static psa_status_t tfm_sp_secure_function_ipc(psa_msg_t *msg) { function_ctr++; LOG_INFFMT("Secure function called %u times, interrupt ctr: %u\n", function_ctr, interrupt_ctr ); return PSA_SUCCESS; }
void tfm_sp_secure_function(psa_msg_t *msg) { psa_status_t status; status = tfm_sp_secure_function_ipc(msg); psa_reply(msg->handle, status); }
void tfm_sp_entry(void) { LOG_INFFMT("Secure Partition: Init\n");
tfm_secure_controller_secure_timer_start(); psa_irq_enable(TFM_TIMER1_IRQ_SIGNAL); psa_signal_t signals = 0; uint32_t ctr = 0;
while (1) { signals = psa_wait(TFM_TIMER1_IRQ_SIGNAL, PSA_BLOCK); if ( (signals & TFM_TIMER1_IRQ_SIGNAL) == TFM_TIMER1_IRQ_SIGNAL) { ctr++; LOG_INFFMT("FLIH stage 2 %u\n", interrupt_ctr); psa_reset_signal(TFM_TIMER1_IRQ_SIGNAL); }
if ( ctr % 10 == 0 ) { signals = psa_wait(PSA_WAIT_ANY, PSA_POLL); if ( (signals & TFM_SECURE_FUNCTION_SIGNAL) == TFM_SECURE_FUNCTION_SIGNAL) { psa_msg_t msg; psa_get(signals, &msg); tfm_sp_secure_function(&msg);
} } } }