Hi Yaduvir,
First of all, could you share the version (or hash) of the TF-M test repo you are using.
I believe it’s not the same tag 1.3.0 as the TF-M you are using.
For the reset, please see my in line comments.
Best Regards,
Kevin
From: Singh, Yaduvir <yaduvir.singh@intel.com>
Sent: Monday, October 25, 2021 11:18 AM
To: Kevin Peng <Kevin.Peng@arm.com>
Cc: tf-m@lists.trustedfirmware.org; nd <nd@arm.com>
Subject: RE: Enable GPIO IRQ in TFM 1.3 with zephry v2.7.0 on nrf5340DK
Hi Kevin,
Here are the answers to your questions:
[Yaduvir] Yes tfm_slih_test work on my nrf5340DK board. But not tfm_flih_test. “timer0_handler()” is called both in tfm_slih_test.c or our custom tfm service as long as “CONFIG_TFM_REGRESSION_NS=y”
in tfm_regression_test client sample. Further by experimenting, I found that slih timer interrupt is called if I remove all tests except below 2 tests, and I see that ‘register_testsuite_ns_core_positive’ just returns a ‘CORE_TEST_ERRNO_SUCCESS’, ‘register_testsuite_ns_qcbor’
runs some 20 something qcbr lib test and nothing is related timer interrupt. But if these 2 test are run then timer0 interrupt always work. Commenting any of these tests just disable the timer interrupt.
static struct test_suite_t test_suites[] = {
/* List test cases which are compliant with level 1 isolation */
#if defined(TFM_PARTITION_INITIAL_ATTESTATION) || defined(FORWARD_PROT_MSG)
/* Non-secure QCBOR library test cases */
{®ister_testsuite_ns_qcbor, 0, 0, 0},
#endif
/* Non-secure core test cases */
{®ister_testsuite_ns_core_positive, 0, 0, 0},
/* End of test suites */
{0, 0, 0, 0}
};
[Kevin] I think in the test codes you are using, the SLIH test is part of the NS core positive test suite (BTW, I introduced a dedicated IRQ test suites in later versions).
It should have nothing to do with the QCBOR tests.
[Yaduvir] 0 -128 (0x80)
[Kevin] So how many priorities. Configurable priorities should be discrete
I see that SLIH, timer0_handler is when TFM_TIMER0_IRQ_SIGNAL is received in psa_wait() and send by SPM. This is how SLIH is working in test suite and my own custom service as long as
“CONFIG_TFM_REGRESSION_NS=y” is enabled as discussed above.
[Kevin] That’s correct. The key point is if you can get the interrupt SIGNAL and you can handle it in your own way.
static void timer0_handler(void)
{
tfm_plat_test_secure_timer_stop();
psa_irq_disable(TFM_TIMER0_IRQ_SIGNAL);
}
static void slih_test_case_2(void) {
psa_irq_enable(TFM_TIMER0_IRQ_SIGNAL);
tfm_plat_test_secure_timer_start();
while (psa_wait(TFM_TIMER0_IRQ_SIGNAL, PSA_BLOCK) != TFM_TIMER0_IRQ_SIGNAL);
timer0_handler();
}
In tfm_plat_test.h, defines a macro which put the timer start function in Read only section of the partition.
TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_SP_SLIH_TEST", "APP-ROT")
tfm_plat_test_secure_timer_start, tfm_plat_test_secure_timer_stop
[Kevin] This is because:
now I need to know why timer0 interrupt is working only when “register_testsuite_ns_qcbor” and “register_testsuite_ns_core_positive” is run in tests. Any clue why FLIH timer interrupt not working.
Are there any sample to enable GPTIOE or any other peripheral interrupt sample in TFM test suite. Currently I see only Timer interrupt sample.
[Kevin] Unfortunately there are only the timer examples so far.
Thanks
Yaduvir
From: Kevin Peng <Kevin.Peng@arm.com>
Sent: Tuesday, October 19, 2021 10:13 PM
To: Singh, Yaduvir <yaduvir.singh@intel.com>
Cc: tf-m@lists.trustedfirmware.org; nd <nd@arm.com>
Subject: RE: Enable GPIO IRQ in TFM 1.3 with zephry v2.7.0 on nrf5340DK
Hi Singh,
Let me try to answer your questions.
Before that I have some general questions:
For your questions:
Q1) at least TIMER0 signal should be received after the timer start?
[Kevin]: I think yes. One thing I would suspect is about the priority. See my questions above.
If you could debug, I suggest to break point on either TFM_TIMER0_IRQ_Handler or tfm_set_irq_signal to see it these two could hit.
Q2)Are there any steps i missed to enable IRQ in TFM secure partition?
[Kevin]: I think you missed something in the Q4 question for GPIO.
Q3)Also, for GPIOTE i need to enable IRQ on the particular pin of port0 ex P0.8, How can i know the signal generated for the interrupt is for P0.8?
[Kevin]: I think that’s something specific to your GPIOTE. You might have some GPIOTE registers to read?
The signal asserted to your Secure Partition only indicates there is an asserted interrupt on the Interrupt Controller for that IRQ line - "source": "TFM_GPIOTE0_IRQ"
Q4)In tfm_secure_irq_handling.rst it mentions "it is important the macro name matches the platform's handler function for that IRQ source."
[Kevin]:
This is because the psa_wait(IRQ_SIGNAL) part it the Second-Level handling and there has be some First-Level handling which is done by the TF-M SPM and transparent to all IRQs.
The TFM_GPIOTE0_IRQ_Handler and the TFM_TIMER0_IRQ_Handler generated by TF-M build system are the First-Level handlings.
Best Regards,
Kevin
From: TF-M <tf-m-bounces@lists.trustedfirmware.org>
On Behalf Of Singh, Yaduvir via TF-M
Sent: Tuesday, October 19, 2021 11:50 PM
To: tf-m@lists.trustedfirmware.org
Subject: [TF-M] Enable GPIO IRQ in TFM 1.3 with zephry v2.7.0 on nrf5340DK
Hi All,
I want to enable GPIO IRQ in Trusted firmware-m 1.3 on nrf5340DK. I have TFM 1.3 which comes with zephyr v2.7.0 image flashed to board. followed the steps of https://www.trustedfirmware.org/docs/tech_forum_20210819BriefUpdatesInterruptHandling.pdf and tfm_slih_test_service
which has TIMER0 interrupt handler.
Steps1: Assigning the interrupt GPIOTE0 and TIMER0 in secure partition manifest file.
Steps2: Assigning the MMIO region of GPIOTE0 and TIMER0 in secure partition manifest file.
Step3: Enable(psa_irq_enable) for both GPIOTE0,TIMER0 and Start (tfm_plat_test_secure_timer_start) the TIMER0.
Step4: waiting for interrupt SIGNAL defined in secure partition manifest file for GPIOTE0 and TIMER0) using psa_wait(PSA_WAIT_ANY, PSA_BLOCK) in the secure partition source code.
But do not receive any signal for TIMER0 and GPIOTE0.
Q1) at least TIMER0 signal should be received after the timer start?
Q2)Are there any steps i missed to enable IRQ in TFM secure partition?
Q3)Also, for GPIOTE i need to enable IRQ on the particular pin of port0 ex P0.8, How can i know the signal generated for the interrupt is for P0.8?
Q4)In tfm_secure_irq_handling.rst it mentions "it is important the macro name matches the platform's handler function for that IRQ source."
- In case ``source`` is defined IRQ macro, the name of the handler becomes
``void <macro>_Handler(void)``.
I do not understand why we need to have a handler function name matching with IRQ source when we have to wait on psa_wait(PSA_WAIT_ANY,
PSA_BLOCK) for IRQ signal?
Step1,Step2
/*#####################################################################*/
modules\tee\tfm\trusted-firmware-m\platform\ext\target\nordic_nrf\common\nrf5340\tfm_peripherals_def.h
#ifndef __TFM_PERIPHERALS_DEF_H__
#define __TFM_PERIPHERALS_DEF_H__
#include <nrf.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TFM_TIMER0_IRQ (TIMER0_IRQn)
#define TFM_TIMER1_IRQ (TIMER1_IRQn)
#define TFM_GPIOTE0_IRQ (GPIOTE0_IRQn)
#define TFM_SPIM4_IRQ (SPIM4_IRQn)
struct platform_data_t;
extern struct platform_data_t tfm_peripheral_std_uart;
extern struct platform_data_t tfm_peripheral_timer0;
extern struct platform_data_t tfm_peripheral_std_gpiote0;
extern struct platform_data_t tfm_peripheral_std_spim4;
#define TFM_PERIPHERAL_STD_UART (&tfm_peripheral_std_uart)
#define TFM_PERIPHERAL_TIMER0 (&tfm_peripheral_timer0)
#define TFM_PERIPHERAL_GPIOTE0 (&tfm_peripheral_std_gpiote0)
#define TFM_PERIPHERAL_SPIM4 (&tfm_peripheral_std_spim4)
#define TFM_PERIPHERAL_FPGA_IO (0)
#ifdef __cplusplus
}
#endif
#endif /* __TFM_PERIPHERALS_DEF_H__ */
modules\tee\tfm\trusted-firmware-m\platform\ext\target\nordic_nrf\common\nrf5340\target_cfg.c
struct platform_data_t tfm_peripheral_timer0 = {
NRF_TIMER0_S_BASE,
NRF_TIMER0_S_BASE + (sizeof(NRF_TIMER_Type) - 1),
};
struct platform_data_t tfm_peripheral_std_uart = {
NRF_UARTE1_S_BASE,
NRF_UARTE1_S_BASE + (sizeof(NRF_UARTE_Type) - 1),
};
struct platform_data_t tfm_peripheral_std_gpiote0 = {
NRF_GPIOTE0_S_BASE,
NRF_GPIOTE0_S_BASE + (sizeof(NRF_GPIOTE_Type) - 1),
};
struct platform_data_t tfm_peripheral_std_spim4 = {
NRF_SPIM4_S_BASE,
NRF_SPIM4_S_BASE + (sizeof(NRF_SPIM_Type) - 1),
};
/*Secure partition manifest file change*/
samplepartition.yaml
{
"psa_framework_version": 1.1,
"name": "TFM_SP_sample",
# Possible options: "PSA-ROT | APPLICATION-ROT"
"type": "APPLICATION-ROT",
"priority": "NORMAL",
"model": "IPC",
"entry_point": "sample_partition_main",
"stack_size": "0x200",
"services": [
# Define the secure service here.
{
"name": "TFM_EXAMPLE_SERVICE",
# SIDs must be unique, ones that are currently in use are documented in
# tfm_secure_partition_addition.rst on line 184
"sid": "0x00001001",
"non_secure_clients": true,
"version": 1,
"version_policy": "STRICT"
},
],
# Define all the IRQs that the service wants to handle.
"mmio_regions": [
{
"name": "TFM_PERIPHERAL_GPIOTE0",
"permission": "READ-WRITE"
},
{
"name": "TFM_PERIPHERAL_SPIM4",
"permission": "READ-WRITE"
},
{
"name": "TFM_PERIPHERAL_TIMER0",
"permission": "READ-WRITE"
},
],
"irqs": [
{
"source": "TFM_GPIOTE0_IRQ",
"name": "TFM_GPIOTE0_IRQ",
"handling": "SLIH",
"tfm_irq_priority": 64,
},
{
"source": "TFM_SPIM4_IRQ",
"name": "TFM_SPIM4_IRQ",
"handling": "SLIH",
"tfm_irq_priority": 64,
},
{
"source": "TFM_TIMER0_IRQ",
"name": "TFM_TIMER0_IRQ",
"handling": "SLIH",
"tfm_irq_priority": 64,
}
],
"dependencies": [
"TFM_CRYPTO"
]
}
Step3, Step4
/*#####################################################################*/
/*Secure partition Code*/
sample_partition.c
#define TIMER_RELOAD_VALUE (1*1000*1000)
static void gpiote0_handler(void)
{
LOG_INFFMT("gpiote0_handler called!!\n");
psa_irq_disable(TFM_GPIOTE0_IRQ_SIGNAL);
psa_eoi(TFM_GPIOTE0_IRQ_SIGNAL);
}
static void spim4_handler(void)
{
LOG_INFFMT("spim4_handler called !\n");
psa_irq_disable(TFM_SPIM4_IRQ_SIGNAL);
psa_eoi(TFM_SPIM4_IRQ_SIGNAL);
}
static void timer0_handler(void)
{
LOG_INFFMT("timer0_handler called!\n");
psa_irq_disable(TFM_TIMER0_IRQ_SIGNAL);
psa_eoi(TFM_TIMER0_IRQ_SIGNAL);
}
static void timer_init(NRF_TIMER_Type * TIMER, uint32_t ticks)
{
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, ticks);
nrf_timer_one_shot_enable(TIMER, NRF_TIMER_CC_CHANNEL0);
}
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);
}
void tfm_plat_test_secure_timer_start(void)
{
timer_init(NRF_TIMER0, TIMER_RELOAD_VALUE);
timer_start(NRF_TIMER0);
}
void tfm_plat_test_secure_timer_stop(void)
{
timer_stop(NRF_TIMER0);
}
void sample_partition_main(void)
{
psa_signal_t signals;
psa_irq_enable(TFM_SPIM4_IRQ_SIGNAL);
psa_irq_enable(TFM_GPIOTE0_IRQ_SIGNAL);
/*Start timer interrupt*/
psa_irq_enable(TFM_TIMER0_IRQ_SIGNAL);
tfm_plat_test_secure_timer_start();
/* Continually wait for one or more of the partition's RoT Service or
* interrupt signals to be asserted and then handle the asserted signal(s).
*/
while (1) {
signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
if (signals & TFM_GPIOTE0_IRQ_SIGNAL) {
gpiote0_handler();
}else if (signals & TFM_SPIM4_IRQ_SIGNAL) {
spim4_handler();
}else if (signals & TFM_TIMER0_IRQ_SIGNAL) {
timer0_handler();
} else {
psa_panic();
}
}
}
/*#####################################################################*/
Thanks
Yaduvir