<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/106372/implementation-of-periodic-spi-operations-with-nrfx</link><description>Good evening, 
 I would like to execute an SPI operation every 20ms using an interruption. I saw that it was recommended utilizing nrfx timer and PPI to achieve this, ensuring that the SPI writing process does not encounter timeouts. But I have difficulties</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 02 Jan 2024 16:58:24 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/106372/implementation-of-periodic-spi-operations-with-nrfx" /><item><title>RE: Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/thread/462358?ContentTypeID=1</link><pubDate>Tue, 02 Jan 2024 16:58:24 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e644bbc3-5811-47ab-a904-185bd527a26c</guid><dc:creator>BENBF</dc:creator><description>&lt;p&gt;It seems that it works as intended when using &lt;span&gt;IRQ_CONNECT()&lt;/span&gt; instead of &lt;span&gt;IRQ_DIRECT_CONNECT().&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Thank you,&lt;br /&gt;Best regards&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/thread/462271?ContentTypeID=1</link><pubDate>Tue, 02 Jan 2024 12:13:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7da4271b-15af-44ec-be45-471d9ce17bda</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;The first I would try is whether the code you shared works as intended when using&amp;nbsp;&lt;span&gt;IRQ_CONNECT() instead of&amp;nbsp;IRQ_DIRECT_CONNECT().&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Kenneth&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/thread/462221?ContentTypeID=1</link><pubDate>Tue, 02 Jan 2024 09:36:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:47a25694-2783-45ad-a689-b09308ba4332</guid><dc:creator>BENBF</dc:creator><description>&lt;p&gt;Hello,&lt;br /&gt;Thank you for your answer.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m using IRQ_DIRECT_CONNECT() to declare my 50Hz timer.&lt;br /&gt;Unfortunately, as my SPI transactions are quite long, it triggers a timeout when I&amp;#39;m performing them directly from the timer handler function. This is why I tried to offload those transactions with another thread.&lt;/p&gt;
&lt;p&gt;The observed behaviour is that the SPI thread is not activated every time the timer IRQ is fired and I don&amp;#39;t understand why. The observed behaviour remains the same even if I lower the timer frequency.&lt;/p&gt;
&lt;p&gt;Do you know if there is a way to access thread scheduler information or to force it to update itself in order to be sure that my SPI thread is indeed the next one to be performed when the timer IRQ occurs ?&lt;/p&gt;
&lt;p&gt;Best regards&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/thread/462203?ContentTypeID=1</link><pubDate>Tue, 02 Jan 2024 08:35:36 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:69a7f38a-31cc-43ca-93a4-ae5eba7bd533</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;The only thing I can think of and I want to mention is that when you define the interrupts, you can choose between either IRQ_CONNECT() or IRQ_DIRECT_CONNECT(). Bascially the first allow you to use the zephyr api as-is from the interrupt handler, while the other you need to add some macros to the interrupt handler if you want to use the zephyr api from the interrupt handler. You can read more about it here:&lt;br /&gt;&lt;a href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/kernel/services/interrupts.html"&gt;https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/kernel/services/interrupts.html&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/thread/461754?ContentTypeID=1</link><pubDate>Wed, 27 Dec 2023 09:58:00 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1c3276df-1b05-4000-a9fe-756c540eb6ad</guid><dc:creator>ovrebekk</dc:creator><description>&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;We are severely understaffed this week because of the Christmas holidays, and Kenneth will have to get back to you on this next week. Sorry for the inconvenience.&lt;/p&gt;
&lt;p&gt;Best regards&lt;br /&gt;Torbjørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/thread/461458?ContentTypeID=1</link><pubDate>Thu, 21 Dec 2023 14:28:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c7869cad-7871-4708-a1fe-e9267f3c1cc1</guid><dc:creator>BENBF</dc:creator><description>&lt;p&gt;Hello, thank you for your answers.&lt;/p&gt;
&lt;p&gt;In the end it appear that I can&amp;#39;t use PPI for my application as I need to have fine control over SPI transactions...&lt;/p&gt;
&lt;p&gt;I tried to perform my SPI transactions in a dedicated thread that is triggered by a 50 Hz timer.&lt;br /&gt;Unfortunately, my SPI thread is not triggered every time that timer callback is called. Do you have nay idea of what be the cause of this issue ?&lt;br /&gt;&lt;br /&gt;I&amp;#39;ve tried to trigger the thread with either semaphore or thread management (with k_thread_resume()) but the observed behaviour is the same&lt;/p&gt;
&lt;p&gt;This is the test code I&amp;#39;m using:&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void t_test(void){
    while(1){
        //k_sem_take(&amp;amp;_sem, K_FOREVER);
        printk(&amp;quot;Second Thread\n&amp;quot;);
        k_thread_suspend(t_thread);
    }
}



void main(void)
{
    //k_sem_init(&amp;amp;_sem, 0, 1);

    t_thread = k_thread_create(&amp;amp;t_k_thread, _stack, STACKSIZE, t_test, NULL, NULL, NULL, -2, 0, K_NO_WAIT);
    k_msleep(1000);
    printk(&amp;quot;Starting timer\n&amp;quot;);
    meas_timer_init();

    while (1) {
        printk(&amp;quot;Main thread: still alive\n&amp;quot;);
        k_msleep(1000);
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And this is the timer part :&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;ISR_DIRECT_DECLARE(meas_timer_handler)
{

    if (NRF_TIMER1-&amp;gt;EVENTS_COMPARE[0]) {
        NRF_TIMER1-&amp;gt;EVENTS_COMPARE[0] = 0;
        printk(&amp;quot;Timer\n&amp;quot;);
        //k_sem_give(&amp;amp;_sem);
        k_thread_resume(t_thread);
       
    }
    return 0;
}

void meas_timer_init(void)
{
    IRQ_DIRECT_CONNECT(TIMER1_IRQn, 4, meas_timer_handler, 0);
    NRF_TIMER1-&amp;gt;BITMODE = 32;
    NRF_TIMER1-&amp;gt;PRESCALER = 8;
    NRF_TIMER1-&amp;gt;MODE = TIMER_MODE_MODE_Timer;
    NRF_TIMER1-&amp;gt;CC[0] = 1250;
    NRF_TIMER1-&amp;gt;SHORTS = 0;
    NRF_TIMER1-&amp;gt;SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled &amp;lt;&amp;lt; TIMER_SHORTS_COMPARE0_CLEAR_Pos;
    NRF_TIMER1-&amp;gt;INTENSET = TIMER_INTENSET_COMPARE0_Enabled &amp;lt;&amp;lt; TIMER_INTENSET_COMPARE0_Pos;
    NRF_TIMER1-&amp;gt;TASKS_START = 1;
    irq_enable(TIMER1_IRQn);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Thank you,&lt;br /&gt;Best regards&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/thread/459201?ContentTypeID=1</link><pubDate>Wed, 06 Dec 2023 14:06:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8deb921d-a767-48c6-aa69-92a48191d8b9</guid><dc:creator>PabloL</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;1) Set a timer in timer mode:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;#define TIMER1_INST_IDX 0
#define TIMER_COMPARE_COUNT 320000  // 16000000 * 0.02s

// Timer instance
const nrfx_timer_t timer1_inst = NRFX_TIMER_INSTANCE(TIMER1_INST_IDX);

void timer_init(void)
{
    nrfx_err_t err;
    (void)err;
    
    // Configure Timer
    uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer1_inst.p_reg);
    nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency);
    config.bit_width = NRF_TIMER_BIT_WIDTH_32;
    config.mode = NRF_TIMER_MODE_TIMER;
    config.p_context = &amp;amp;timer1_inst;
    err = nrfx_timer_init(&amp;amp;timer1_inst, &amp;amp;config, NULL);
    NRFX_ASSERT(err == NRFX_SUCCESS);
    
    #if defined(__ZEPHYR__)
    IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(TIMER1_INST_IDX)), IRQ_PRIO_LOWEST,
    NRFX_TIMER_INST_HANDLER_GET(TIMER1_INST_IDX), 0);
    #endif
    
    /* Setting the timer (in timer mode) channel NRF_TIMER_CC_CHANNEL0 in the extended compare
     * mode to clear the timer and trigger an event if internal counter register is equal
     * to TIMER_COMPARE_COUNT.
     */
    nrfx_timer_extended_compare(&amp;amp;timer1_inst, NRF_TIMER_CC_CHANNEL0, TIMER_COMPARE_COUNT,
    NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;2) Set SPIM:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;// SPIM instance to be used
#define SPIM_INST_IDX 4

// SPI instance
nrfx_spim_t spim_inst = NRFX_SPIM_INSTANCE(SPIM_INST_IDX);

// SPI Configuration
void SPI_Init(void)
{
    nrfx_spim_config_t spim_config = NRFX_SPIM_DEFAULT_CONFIG(SCK_PIN,
                                                              MOSI_PIN,
                                                              MISO_PIN,
                                                              CS_PIN);

	spim_config.ss_pin = CS_PIN;
	spim_config.use_hw_ss = true;		// hardware SS (SPIM4 only)

    // Enable IRQ if necessary
	// IRQ_CONNECT(DT_IRQN(DT_NODELABEL(spi4)),
	// 			DT_IRQ(DT_NODELABEL(spi4), priority),
	// 			nrfx_isr, nrfx_spim4_irq_handler, 0);

    err = nrfx_spim_init(&amp;amp;spim_inst, &amp;amp;spim_config, NULL, NULL);
    NRFX_ASSERT(err != NRFX_SUCCESS);
}    &lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;3)&amp;nbsp;Configure DPPI:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;uint8_t ppi_channel1;

void ppi_init(void)
{
	nrfx_err_t err;

	/* Allocate a (D)PPI channel. */
	err = nrfx_gppi_channel_alloc(&amp;amp;ppi_channel1);
	if (err != NRFX_SUCCESS) {
		LOG_ERR(&amp;quot;nrfx_gppi_channel_alloc error: 0x%08X&amp;quot;, err);
		return;
	}
	
	/* Configure endpoints of the channel so that the TIMER1, CCCH0 event is
	 * connected with the SPIM task.
	 */
	nrfx_gppi_channel_endpoints_setup(ppi_channel1,
			nrfx_timer_compare_event_address_get(&amp;amp;timer1_inst, NRF_TIMER_CC_CHANNEL0),
			nrfx_spim_start_task_address_get(&amp;amp;spim_inst));
	
	// Enable the channel
	nrfx_gppi_channels_enable(BIT(ppi_channel1));
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;4) Configure xfer and start timer:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;    uint8_t tx_data[TX_DATA_SIZE]; // FILL with data to send
    uint8_t rx_data[RX_DATA_SIZE];
    
    // SPIM Descriptor
    nrfx_spim_xfer_desc_t spim_xfer_desc = NRFX_SPIM_XFER_TRX(tx_data, sizeof(tx_data), rx_data, sizeof(rx_data));

	// Configure SPIM transfer, hold for an event, increment rx pointer after transfer
	// Note: Should reset the pointer at some point
	err = nrfx_spim_xfer(&amp;amp;spim_inst, &amp;amp;spim_xfer_desc, NRFX_SPIM_FLAG_HOLD_XFER|NRFX_SPIM_FLAG_REPEATED_XFER|NRFX_SPIM_FLAG_RX_POSTINC|NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER);
    NRFX_ASSERT(err != NRFX_SUCCESS);

	
	nrfx_timer_clear(&amp;amp;timer1_inst);
    nrfx_timer_enable(&amp;amp;timer1_inst);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Implementation of Periodic SPI Operations with nrfx</title><link>https://devzone.nordicsemi.com/thread/459182?ContentTypeID=1</link><pubDate>Wed, 06 Dec 2023 13:01:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7363b0cd-dccf-442e-80f9-64847f7fd370</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;You may find the following two examples useful (I hope).&lt;/p&gt;
&lt;p&gt;How to setup timer to toggle a pin using ppi:&amp;nbsp;&lt;br /&gt;&lt;a href="https://github.com/zephyrproject-rtos/hal_nordic/tree/master/nrfx/samples/src/nrfx_gppi/one_to_one"&gt;https://github.com/zephyrproject-rtos/hal_nordic/tree/master/nrfx/samples/src/nrfx_gppi/one_to_one&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;But in your case you need to trigger a spi transfer instead, so here is an example on how to setup a spi transfer:&lt;br /&gt;&lt;a href="https://github.com/zephyrproject-rtos/hal_nordic/tree/master/nrfx/samples/src/nrfx_spim/non_blocking"&gt;https://github.com/zephyrproject-rtos/hal_nordic/tree/master/nrfx/samples/src/nrfx_spim/non_blocking&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;But in your case you should&amp;nbsp;setup the&amp;nbsp;nrfx_spim_xfer(..NRFX_SPIM_FLAG_HOLD_XFER). Then use the&amp;nbsp;nrfx_spim_start_task_address_get() to find the start task adress that should be used to connect the ppi channel from the timer (instead of&amp;nbsp;nrfx_gpiote_out_task_address_get).&lt;/p&gt;
&lt;p&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>