88#include <zephyr/ztest.h>
99#include <zephyr/drivers/spi.h>
1010#include <nrfx_spim.h>
11+ #include <nrfx_timer.h>
1112#include <zephyr/linker/devicetree_regions.h>
1213
13- #define SPI_MODE (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB)
14+ #include <zephyr/drivers/counter.h>
15+ #include <helpers/nrfx_gppi.h>
1416
15- #define TEST_BUFFER_SIZE 8
17+ /* SPI MODE 0 */
18+ #define SPI_MODE (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB)
19+ #define TEST_BUFFER_SIZE 64
1620
1721static struct spi_dt_spec spim_spec = SPI_DT_SPEC_GET (DT_NODELABEL (dut_spi_dt ), SPI_MODE , 0 );
1822NRF_SPIM_Type * spim_reg = (NRF_SPIM_Type * )DT_REG_ADDR (DT_NODELABEL (dut_spi ));
1923
24+ static nrfx_timer_t test_timer = NRFX_TIMER_INSTANCE (DT_REG_ADDR (DT_NODELABEL (tst_timer )));
25+
2026#define MEMORY_SECTION (node ) \
2127 COND_CODE_1(DT_NODE_HAS_PROP(node, memory_regions), \
2228 (__attribute__((__section__( \
@@ -39,15 +45,31 @@ static void set_buffers(void)
3945 memset (rx_buffer , 0xFF , TEST_BUFFER_SIZE );
4046}
4147
48+ static uint32_t configure_test_timer (nrfx_timer_t * timer )
49+ {
50+ uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET (timer -> p_reg );
51+ nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG (base_frequency );
52+
53+ timer_config .bit_width = NRF_TIMER_BIT_WIDTH_16 ;
54+ timer_config .mode = NRF_TIMER_MODE_COUNTER ;
55+
56+ TC_PRINT ("Timer base frequency: %d Hz\n" , base_frequency );
57+
58+ zassert_ok (nrfx_timer_init (timer , & timer_config , NULL ), "Timer init failed\n" );
59+ nrfx_timer_enable (timer );
60+
61+ return nrfx_timer_task_address_get (timer , NRF_TIMER_TASK_COUNT );
62+ }
63+
4264/*
4365 * Reference: MLTPAN-8
4466 * Requirements to trigger the PAN workaround
4567 * CPHA = 0 (configured in SPI_MODE)
46- * PRESCALER > 2 (16 for 1MHz )
68+ * PRESCALER > 2 (4 for 4MHz )
4769 * First transmitted bit is 1 (0x8B, MSB)
4870 */
4971
50- ZTEST (spim_pan , test_spim_pan_workaround )
72+ ZTEST (spim_pan , test_spim_mltpan_8_workaround )
5173{
5274 int err ;
5375
@@ -59,13 +81,65 @@ ZTEST(spim_pan, test_spim_pan_workaround)
5981
6082 set_buffers ();
6183
84+ err = spi_transceive_dt (& spim_spec , & tx_spi_buf_set , & rx_spi_buf_set );
6285 TC_PRINT ("SPIM prescaler: %u\n" , spim_reg -> PRESCALER );
6386 zassert_true (spim_reg -> PRESCALER > 2 , "SPIM prescaler is not greater than 2\n" );
64-
65- err = spi_transceive_dt (& spim_spec , & tx_spi_buf_set , & rx_spi_buf_set );
6687 zassert_ok (err , "SPI transceive failed: %d\n" , err );
6788
6889 zassert_mem_equal (tx_buffer , rx_buffer , TEST_BUFFER_SIZE , "TX buffer != RX buffer\n" );
6990}
7091
92+ /*
93+ * Reference: MLTPAN-55
94+ * Requirements to trigger the PAN workaround
95+ * MODE 0 or MODE 2 (CPHA = 0)
96+ * PRESCALER = 4 (4 MHz) for SPIM2x and SPIM3x
97+ * RX.MAXCNT lower than TX.MAXCNT
98+ */
99+
100+ ZTEST (spim_pan , test_spim_mltpan_55_workaround )
101+ {
102+ int err ;
103+
104+ uint8_t ppi_channel ;
105+
106+ uint32_t domain_id ;
107+ nrfx_gppi_handle_t gppi_handle ;
108+
109+ uint32_t timer_cc_before , timer_cc_after ;
110+
111+ uint32_t timer_task ;
112+ uint32_t spim_event ;
113+
114+ struct spi_buf tx_spi_buf = {.buf = tx_buffer , .len = TEST_BUFFER_SIZE };
115+ struct spi_buf_set tx_spi_buf_set = {.buffers = & tx_spi_buf , .count = 1 };
116+
117+ struct spi_buf rx_spi_buf = {.buf = rx_buffer , .len = TEST_BUFFER_SIZE - 1 };
118+ struct spi_buf_set rx_spi_buf_set = {.buffers = & rx_spi_buf , .count = 1 };
119+
120+ set_buffers ();
121+
122+ domain_id = nrfx_gppi_domain_id_get ((uint32_t )test_timer .p_reg );
123+ ppi_channel = nrfx_gppi_channel_alloc (domain_id );
124+ zassert_true (ppi_channel > 0 , "Failed to allocate GPPI channel" );
125+
126+ timer_task = configure_test_timer (& test_timer );
127+ spim_event = nrf_spim_event_address_get (spim_reg , NRF_SPIM_EVENT_END );
128+
129+ zassert_ok (nrfx_gppi_conn_alloc (spim_event , timer_task , & gppi_handle ),
130+ "Failed to allocate DPPI connection\n" );
131+ nrfx_gppi_conn_enable (gppi_handle );
132+
133+ timer_cc_before = nrfx_timer_capture (& test_timer , NRF_TIMER_CC_CHANNEL0 );
134+ err = spi_transceive_dt (& spim_spec , & tx_spi_buf_set , & rx_spi_buf_set );
135+ timer_cc_after = nrfx_timer_capture (& test_timer , NRF_TIMER_CC_CHANNEL0 );
136+
137+ TC_PRINT ("Timer count before: %u, timer count after: %u\n" , timer_cc_before ,
138+ timer_cc_after );
139+
140+ zassert_true ((timer_cc_after - timer_cc_before ) > 0 ,
141+ "NRF_SPIM_EVENT_END did not trigger\n" );
142+ zassert_mem_equal (tx_buffer , rx_buffer , TEST_BUFFER_SIZE - 1 , "TX buffer != RX buffer\n" );
143+ }
144+
71145ZTEST_SUITE (spim_pan , NULL , test_setup , NULL , NULL , NULL );
0 commit comments