<?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>Timing of SPI when sharing common lines on independent timers</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/108076/timing-of-spi-when-sharing-common-lines-on-independent-timers</link><description>We are using two SPI masters (SPIM0 and SPMI1) inside two independently running timers. SPIM0 and SPIM1 share MISO, MOSI, and SCK. Only the chip selects are different between the two. My question is as follows: 
 What will happen if the timers synchronize</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 08 Feb 2024 01:20:45 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/108076/timing-of-spi-when-sharing-common-lines-on-independent-timers" /><item><title>RE: Timing of SPI when sharing common lines on independent timers</title><link>https://devzone.nordicsemi.com/thread/467992?ContentTypeID=1</link><pubDate>Thu, 08 Feb 2024 01:20:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2a626482-2c23-48c4-b5a6-b68fc5f27267</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Since&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/members/nordicator_5f00_prim3"&gt;nordicator&lt;/a&gt; had some kind words, I wrote example code to allow multiple SPI peripherals to share the same pins. This is the basic functionality, the two SPI peripherals argue about who transmits but testing shows no corruption. Actual SPI devices are not required if loopback mode is used (Nordic documentation disapproves but it works fine):&amp;nbsp;&lt;em&gt;mInitSPI_Ports(true);&lt;/em&gt; the parameter enables (true) or disables (false) SPI loopback on a single pin.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// Two or more SPI peripherals can share SCK, MOSI and MISO pins, assuming two SPI peripherals are
// required by the application due to very different SPI settings or simple lack of spare io pins.
// &amp;quot;The PSEL.SCK, PSEL.MOSI, and PSEL.MISO registers and their configurations are only used as long as
// the SPI master/slave is enabled, and retained only as long as the device is in System ON mode&amp;quot;.
// TWIM is similar.
// So the pins can be shared provided each SPI is disabled before using the other. However, they
// cannot occupy the same timeslot; some form of software lock would be required to avoid being enabled
// simultaneously. To avoid this, the two SPI peripherals would only be enabled in an interrupt of equal
// priority, such that neither could interrupt the other, and the entire Enable-transfer-Disable
// sequence would have to take place in that single interrupt context. That can be done by using
// two SWI software interrupts of low and identical priority triggered from either a timer interrupt
// handler (software) or PPI event (hardware). The matching low interrupt priority for both SWIs is
// required to avoid distorting timers and stuff based on interrupts; stuff in main() will be blocked
// until SPI transfers complete, which may affect sleep/power calculations. All other actions via
// interrupts will safely interrupt both of these SWI handlers.

// Event Generator Unit (EGUn) - A, use (say) SWI/EGU number 3
static NRF_EGU_Type* pEGU_A = NRF_EGU3;
#define SWI_EGU_IRQn_A        SWI3_EGU3_IRQn
// Event Generator Unit (EGUn) - B, use (say) SWI/EGU number 4
static NRF_EGU_Type* pEGU_B = NRF_EGU4;
#define SWI_EGU_IRQn_B        SWI4_EGU4_IRQn
// Timer for this module, not all timers have 6 CC registers
static NRF_TIMER_Type *pTimer = NRF_TIMER3;
#define PWM_TIMER_IRQn          TIMER3_IRQn
static NRF_RTC_Type *pSpiRTC  = NRF_RTC2;
IRQn_Type SpiRTC_IRQn         = RTC2_IRQn;
volatile bool mRTC_Tick = true;

static volatile uint32_t mTriggerTimer         = 0;
static volatile uint32_t mSpiTransactionCountA = 0;
static volatile uint32_t mSpiTransactionCountB = 0;

#define EGU_COUNT_A 3   // Number of RTC ticks to trigger the SPI transfers
#define EGU_COUNT_B 5

#define CSPIN_A 10  // spi chip select A
#define CSPIN_B 11  // spi chip select B
#define SCKPIN  12  // spi clock
#define MOSIPIN 13  // spi mosi
#define MISOPIN 14  // spi miso
#define LIS2DH12_WHO_AM_I  0x0F  // Read back as 0x33
#define TYPICAL_INTERRUPT_PRIORITY  6

uint8_t spiTXBufA[]                  = {0x80|LIS2DH12_WHO_AM_I, 0xFF, 0xFF};
uint8_t spiRXBufA[sizeof(spiTXBufA)] = {0,0};
static const uint8_t mRxTxBufLengthA = sizeof(spiTXBufA);
static void mInitSPI_A(void);
static void mTransferSPI_A(void);

uint8_t spiTXBufB[]                  = {0x80|0x1F, 0xFF, 0xFF, 0xFF};
uint8_t spiRXBufB[sizeof(spiTXBufB)] = {0,0,0};
static const uint8_t mRxTxBufLengthB = sizeof(spiTXBufB);
static void mInitSPI_B(void);
static void mTransferSPI_B(void);

static void TestShareMultipleSPI(void)
{
   // Debug pin to observe wakeups, any spare unused pin
   nrf_gpio_cfg_output(X14_PIN);
   
   // Clear the A event ready to execute SPI transaction event A
   pEGU_A-&amp;gt;EVENTS_TRIGGERED[0] = 0;
   pEGU_A-&amp;gt;INTENSET = 1;
   // Set interrupt priority lower priority than timer and enable interrupt
   NVIC_SetPriority(SWI_EGU_IRQn_A, TYPICAL_INTERRUPT_PRIORITY+1);
   NVIC_ClearPendingIRQ(SWI_EGU_IRQn_A);
   NVIC_EnableIRQ(SWI_EGU_IRQn_A);

   // Clear the B event ready to execute SPI transaction event B
   pEGU_B-&amp;gt;EVENTS_TRIGGERED[0] = 0;
   pEGU_B-&amp;gt;INTENSET = 1;
   // Set interrupt priority lower priority than timer and enable interrupt
   NVIC_SetPriority(SWI_EGU_IRQn_B, TYPICAL_INTERRUPT_PRIORITY+1);
   NVIC_ClearPendingIRQ(SWI_EGU_IRQn_B);
   NVIC_EnableIRQ(SWI_EGU_IRQn_B);

   // Initialise the two SPI peripherals, using same pins other than /CS
   mInitSPI_A();
   mInitSPI_B();

   // Select 32kHz clock source, depends on whether external 32.768kHz crystal is fitted
   NRF_CLOCK-&amp;gt;LFCLKSRC = CLOCK_LFCLKSRC_SRC_Xtal &amp;lt;&amp;lt; CLOCK_LFCLKSRC_SRC_Pos;
   //NRF_CLOCK-&amp;gt;LFCLKSRC = CLOCK_LFCLKSRC_SRC_RC &amp;lt;&amp;lt; CLOCK_LFCLKSRC_SRC_Pos;
   //NRF_CLOCK-&amp;gt;LFCLKSRC = CLOCK_LFCLKSRC_SRC_Synth &amp;lt;&amp;lt; CLOCK_LFCLKSRC_SRC_Pos;
   // Start 32kHz clock
   NRF_CLOCK-&amp;gt;EVENTS_LFCLKSTARTED = 0;
   NRF_CLOCK-&amp;gt;TASKS_LFCLKSTART = 1;
   while (NRF_CLOCK-&amp;gt;EVENTS_LFCLKSTARTED == 0) ;
   // Clear started event otherwise won&amp;#39;t sleep
   NRF_CLOCK-&amp;gt;EVENTS_LFCLKSTARTED = 0;
   // Start RTC, enable TICK event
   // Select tick: 12 bit prescaler for COUNTER frequency (32768/(PRESCALER+1)). Must be written when RTC is stopped
   pSpiRTC-&amp;gt;PRESCALER = 7;
   pSpiRTC-&amp;gt;EVTENSET = RTC_EVTENSET_TICK_Msk;
   // Set interrupt priority higher than SWI/EGU priority and enable interrupt
   NVIC_SetPriority(SpiRTC_IRQn, TYPICAL_INTERRUPT_PRIORITY);
   NVIC_ClearPendingIRQ(SpiRTC_IRQn);
   NVIC_EnableIRQ(SpiRTC_IRQn);
   // Enable tick interrupt
   pSpiRTC-&amp;gt;INTENSET = 0x00001;
   pSpiRTC-&amp;gt;TASKS_START = 1;
   // Send a load of conflicting SPI transfers
   while(1)
   {
      nrf_gpio_pin_set(X14_PIN);
      mTriggerTimer++;
      // Stop after a while, meanwhile trigger lots of transfers
      if (mTriggerTimer &amp;gt; 100000-1)
      {
         pSpiRTC-&amp;gt;EVTENCLR    = 1;
         pSpiRTC-&amp;gt;TASKS_STOP  = 1;
         pSpiRTC-&amp;gt;TASKS_CLEAR = 1;
         // Clear any pending hardware register bus operations
         __DSB();
      }
      else
      {
         // Trigger the ready to execute SPI transaction event at arbitrary overlappng times
         if ((mTriggerTimer % EGU_COUNT_A) == 0) pEGU_A-&amp;gt;TASKS_TRIGGER[0] = 1;
         if ((mTriggerTimer % EGU_COUNT_B) == 0) pEGU_B-&amp;gt;TASKS_TRIGGER[0] = 1;
      }
      nrf_gpio_pin_clear(X14_PIN);
      // Go to sleep until next tick
      while(!mRTC_Tick)
      {
         // Clear the internal event register and wait for event - note an interrupt is required
         __WFE(); __SEV(); __WFE(); __NOP(); __NOP(); __NOP(); __NOP();
      }
      mRTC_Tick = false;
   }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;These are the SWI/EGU (software interrupt/Event Generator Unit) and RTC interrupt handlers:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void RTC2_IRQHandler(void)
{
    if (pSpiRTC-&amp;gt;EVENTS_TICK == 1)
    {
        pSpiRTC-&amp;gt;EVENTS_TICK = 0;
        mRTC_Tick = true;
    }
    // Clear any pending hardware register bus operations
    __DSB();
}

// Event Generator Unit (EGUn) A
void SWI3_EGU3_IRQHandler(void)
{
    // Handle the ready to execute SPI transaction event
    if (pEGU_A-&amp;gt;EVENTS_TRIGGERED[0])
    {
        // Clear the ready to execute SPI transaction event
        pEGU_A-&amp;gt;EVENTS_TRIGGERED[0] = 0;
        // Clear the Rx buffer so easier to verify transfer
        for (uint32_t i=0; i&amp;lt;sizeof(spiRXBufA); i++) spiRXBufA[i] = &amp;#39;?&amp;#39;;
        // Execute SPI transfer A, adjust the tx data a little
        spiTXBufA[1]++;
        mTransferSPI_A();
        mSpiTransactionCountA++;
    }
    // Clear any pending hardware register bus operations
    __DSB();
}

// Event Generator Unit (EGUn) B
void SWI4_EGU4_IRQHandler(void)
{
    // Handle the ready to execute SPI transaction event
    if (pEGU_B-&amp;gt;EVENTS_TRIGGERED[0])
    {
        // Clear the ready to execute SPI transaction event
        pEGU_B-&amp;gt;EVENTS_TRIGGERED[0] = 0;
        // Clear the Rx buffer so easier to verify transfer
        for (uint32_t i=0; i&amp;lt;sizeof(spiRXBufB); i++) spiRXBufB[i] = &amp;#39;?&amp;#39;;
        // Execute SPI transfer B, adjust the tx data a little
        spiTXBufB[2]++;
        mTransferSPI_B();
        mSpiTransactionCountB++;
    }
    // Clear any pending hardware register bus operations
    __DSB();
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;SPI interrupt handlers:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;volatile uint32_t mSpiInterruptCounterA = 0UL;
volatile uint32_t mSpiInterruptCounterB = 0UL;
volatile bool mSPI_TransactionComplete_A = false;
volatile bool mSPI_TransactionComplete_B = false;

volatile NRF_SPIM_Type *pSPIM1 = NRF_SPIM1;
volatile NRF_SPIM_Type *pSPIM2 = NRF_SPIM2;
#define SPI_IRQn_A  SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn
#define SPI_IRQn_B  SPIM2_SPIS2_SPI2_IRQn

void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void)
{
  if (pSPIM1-&amp;gt;EVENTS_END) pSPIM1-&amp;gt;EVENTS_END = 0;
  mSpiInterruptCounterA++;
  mSPI_TransactionComplete_A = true;
}

void SPIM2_SPIS2_SPI2_IRQHandler(void)
{
  if (pSPIM2-&amp;gt;EVENTS_END) pSPIM2-&amp;gt;EVENTS_END = 0;
  mSpiInterruptCounterB++;
  mSPI_TransactionComplete_B = true;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Initialisation of ports and SPI peripherals:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void mInitSPI_Ports(const bool LoopBackSPI);

static void mInitSPI_Ports(const bool LoopBackSPI)
{
   NRF_GPIO-&amp;gt;OUTSET  = 1 &amp;lt;&amp;lt; CSPIN_A;      // deactivate by setting chip select high
   NRF_GPIO-&amp;gt;OUTSET  = 1 &amp;lt;&amp;lt; CSPIN_B;
   NRF_GPIO-&amp;gt;OUTSET  = 1 &amp;lt;&amp;lt; SCKPIN;       // default outputs all high
   NRF_GPIO-&amp;gt;OUTSET  = 1 &amp;lt;&amp;lt; MOSIPIN;
   NRF_GPIO-&amp;gt;PIN_CNF[CSPIN_A] = 0x301;    // output, high drive high and low H0H1
   NRF_GPIO-&amp;gt;PIN_CNF[CSPIN_B] = 0x301;    // output, high drive high and low H0H1
   if (LoopBackSPI)
   {
      NRF_GPIO-&amp;gt;PIN_CNF[MOSIPIN] = 0x30D; // output, high drive high and low H0H1, input connected, pull-up
   }
   else
   {
      NRF_GPIO-&amp;gt;PIN_CNF[MOSIPIN] = 0x301; // output, high drive high and low H0H1, input connected
   }
   NRF_GPIO-&amp;gt;PIN_CNF[SCKPIN]  = 0x301;   // output, high drive high and low H0H1
   NRF_GPIO-&amp;gt;PIN_CNF[MISOPIN] = 0x00C;   // input pin, input buffer connected, pull-up, S0S1, sense disabled
}

static void mInitSPI_A(void)
{
   pSPIM1-&amp;gt;ENABLE = 0;                   // Disable SPIM
   mInitSPI_Ports(true);                // Initialise ports with loopback mode true or false
   NRF_GPIO-&amp;gt;OUTSET  = 1 &amp;lt;&amp;lt; CSPIN_A;     // deactivate by setting chip select high
   // Note SPI psel pins are lost when released, must be reset each transaction
   pSPIM1-&amp;gt;CONFIG    = 0;                // CPOL 0 -- clock polarity active high, CPHA 1 -- sample on trailing clock edge, send Msb first
   pSPIM1-&amp;gt;FREQUENCY = 0x80000000UL;     // 8 Mbps - LIS2DH12 works up to 10MHz on SPI
   pSPIM1-&amp;gt;ORC = 0;                      // Unused Tx bytes, set all low
   pSPIM1-&amp;gt;EVENTS_END   = 0;
   pSPIM1-&amp;gt;EVENTS_ENDTX = 0;
   pSPIM1-&amp;gt;EVENTS_ENDRX = 0;
   // Disable all interrupts
   pSPIM1-&amp;gt;INTENCLR = 0xFFFFFFFFUL;
   // Enable selected interrupts
   pSPIM1-&amp;gt;INTENSET = 0x040;            // END
   // Set interrupt priority and enable interrupt
   NVIC_SetPriority(SPI_IRQn_A, TYPICAL_INTERRUPT_PRIORITY);
   NVIC_ClearPendingIRQ(SPI_IRQn_A);
   NVIC_EnableIRQ(SPI_IRQn_A);
}

static void mInitSPI_B(void)
{
   pSPIM1-&amp;gt;ENABLE = 0;                   // Disable SPIM
   mInitSPI_Ports(true);                // Initialise ports with loopback mode true or false
   NRF_GPIO-&amp;gt;OUTSET  = 1 &amp;lt;&amp;lt; CSPIN_B;     // deactivate by setting chip select high
   // Note SPI psel pins are lost when released, must be reset each transaction
   pSPIM2-&amp;gt;CONFIG    = 0;                // CPOL 0 -- clock polarity active high, CPHA 1 -- sample on trailing clock edge, send Msb first
   pSPIM2-&amp;gt;FREQUENCY = 0x80000000UL;     // 8 Mbps
   pSPIM2-&amp;gt;ORC = 0;                      // Unused Tx bytes, set all low
   pSPIM2-&amp;gt;EVENTS_END   = 0;
   pSPIM2-&amp;gt;EVENTS_ENDTX = 0;
   pSPIM2-&amp;gt;EVENTS_ENDRX = 0;
   // Disable all interrupts
   pSPIM2-&amp;gt;INTENCLR = 0xFFFFFFFFUL;
   // Enable selected interrupts
   pSPIM2-&amp;gt;INTENSET = 0x040;            // END
   // Set interrupt priority and enable interrupt
   NVIC_SetPriority(SPI_IRQn_B, TYPICAL_INTERRUPT_PRIORITY);
   NVIC_ClearPendingIRQ(SPI_IRQn_B);
   NVIC_EnableIRQ(SPI_IRQn_B);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;SPI Transfer functions:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void mTransferSPI_A(void)
{
   // Note SPI psel pins are lost when released, must be reset each transaction
   pSPIM1-&amp;gt;PSEL.SCK  = SCKPIN;
   pSPIM1-&amp;gt;PSEL.MOSI = MOSIPIN;
   pSPIM1-&amp;gt;PSEL.MISO = MOSIPIN; //MISOPIN; // Loopback - setto MOSIPIN
   pSPIM1-&amp;gt;ENABLE = 7;                     // Enable SPIM
   pSPIM1-&amp;gt;TXD.PTR     = (uint32_t)spiTXBufA;
   pSPIM1-&amp;gt;TXD.MAXCNT  = mRxTxBufLengthA;
   pSPIM1-&amp;gt;RXD.PTR     = (uint32_t)spiRXBufA;
   pSPIM1-&amp;gt;RXD.MAXCNT  = mRxTxBufLengthA;
   NRF_GPIO-&amp;gt;OUTCLR    = 1 &amp;lt;&amp;lt; CSPIN_A;   // drive cs low to initiate spi comm
   pSPIM1-&amp;gt;TASKS_START = 1;
   while (!mSPI_TransactionComplete_A) ;
   mSPI_TransactionComplete_A = false;
   pSPIM1-&amp;gt;TASKS_STOP  = 1;
   // Clear pending hardware register bus operations
   __DSB();
   while(!pSPIM1-&amp;gt;EVENTS_STOPPED);
   NRF_GPIO-&amp;gt;OUTSET    = 1 &amp;lt;&amp;lt; CSPIN_A;
   __DSB();
   pSPIM1-&amp;gt;ENABLE      = 0;             // Disable SPIM
}

static void mTransferSPI_B(void)
{
   // Note SPI pins are lost when released, must be reset each transaction
   pSPIM2-&amp;gt;PSEL.SCK  = SCKPIN;
   pSPIM2-&amp;gt;PSEL.MOSI = MOSIPIN;
   pSPIM2-&amp;gt;PSEL.MISO = MOSIPIN; //MISOPIN; // Loopback - setto MOSIPIN
   pSPIM2-&amp;gt;ENABLE = 7;                     // Enable SPIM
   pSPIM2-&amp;gt;TXD.PTR     = (uint32_t)spiTXBufB;
   pSPIM2-&amp;gt;TXD.MAXCNT  = mRxTxBufLengthB;
   pSPIM2-&amp;gt;RXD.PTR     = (uint32_t)spiRXBufB;
   pSPIM2-&amp;gt;RXD.MAXCNT  = mRxTxBufLengthB;
   NRF_GPIO-&amp;gt;OUTCLR    = 1 &amp;lt;&amp;lt; CSPIN_B;   // drive cs low to initiate spi comm
   pSPIM2-&amp;gt;TASKS_START = 1;
   while (!mSPI_TransactionComplete_B) ;
   mSPI_TransactionComplete_B = false;
   pSPIM2-&amp;gt;TASKS_STOP  = 1;
   // Clear pending hardware register bus operations
   __DSB();
   while(!pSPIM2-&amp;gt;EVENTS_STOPPED);
   NRF_GPIO-&amp;gt;OUTSET    = 1 &amp;lt;&amp;lt; CSPIN_B;
   __DSB();
   pSPIM2-&amp;gt;ENABLE      = 0;             // Disable SPIM
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Paste all the above in order given to test; make sure SPI1, SPI2 and RTC2 are not enabled in any sdk_config.h file to avoid vector multiple definitions. Invoke in &lt;em&gt;SystemInit()&lt;/em&gt; before running the usual errata workarounds and before main() for a clean no-frills test.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Timing of SPI when sharing common lines on independent timers</title><link>https://devzone.nordicsemi.com/thread/467643?ContentTypeID=1</link><pubDate>Mon, 05 Feb 2024 17:24:28 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7b7adcc0-e42e-4e4f-9bb8-fee62444179d</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Conflict, everything will die including possibility of hardware output pin damage. The timer must be stopped from writing to both at once, see post above for some options.&lt;/p&gt;
&lt;p&gt;Edit: As a bare minimum, use the SPI ENABLE register as a hardware semaphore; do not enable a new SPI transaction to another chip until this register is 0 (released, disabled); remember to disable the SPI (ENABLE = 0) after a transaction.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Timing of SPI when sharing common lines on independent timers</title><link>https://devzone.nordicsemi.com/thread/467641?ContentTypeID=1</link><pubDate>Mon, 05 Feb 2024 17:14:58 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c59733d3-5a18-4fce-993c-313c54ac223b</guid><dc:creator>nordicator_prim3</dc:creator><description>&lt;p&gt;I didn&amp;#39;t consider that use case; good explanation! I learn a lot from reading your replies - I see you all over this forum.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Timing of SPI when sharing common lines on independent timers</title><link>https://devzone.nordicsemi.com/thread/467640?ContentTypeID=1</link><pubDate>Mon, 05 Feb 2024 17:14:12 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b06f7968-7ab2-4045-9d11-d2a0afadaaef</guid><dc:creator>SG1</dc:creator><description>&lt;p&gt;Thank you,&lt;/p&gt;
&lt;p&gt;I am not using Zephyr.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If I do configure it as above, what will happen if the timer tries to write to both chips at once? Will it be scheduled or will there be a conflict?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Timing of SPI when sharing common lines on independent timers</title><link>https://devzone.nordicsemi.com/thread/467636?ContentTypeID=1</link><pubDate>Mon, 05 Feb 2024 17:05:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ee6c55fa-ecb0-4d93-a3a0-99530d816088</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;I would suggest the two SPI peripherals can indeed share SCK, MOSI and MISO pins, assuming two SPI peripherals are required by the application due to very different SPI settings or simple lack of spare io pins.&lt;/p&gt;
&lt;p&gt;&amp;quot;&lt;em&gt;The PSEL.SCK, PSEL.MOSI, and PSEL.MISO registers and their configurations are only used as long as&lt;br /&gt;the SPI master/slave is enabled, and retained only as long as the device is in System ON mode&lt;/em&gt;&amp;quot;. TWIM is similar.&lt;/p&gt;
&lt;p&gt;So the pins can be shared provided each SPI is disabled before using the other. However, they cannot occupy the same timeslot, which I think was the original question; some form of software lock would be required to avoid being enabled simultaneously. There is no chip order or priority which can avoid this, unless the two SPI peripherals were only enabled in an interrupt of equal priority such that neither could interrupt the other and the entire &lt;em&gt;Enable-transfer-Disable&lt;/em&gt; sequence would have to take place in that single interrupt context. That can be done by using two SWI software interrupts of low and identical priority triggered from either a timer interrupt handler (software) or PPI (hardware). The matching low interrupt priority for both SWIs is required to avoid distorting timers and stuff based on interrupts; stuff in main() will be blocked until SPI transfers complete, which may affect sleep/power calculations. All other actions via interrupts will safely interrupt both of these SWI handlers.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Timing of SPI when sharing common lines on independent timers</title><link>https://devzone.nordicsemi.com/thread/467628?ContentTypeID=1</link><pubDate>Mon, 05 Feb 2024 16:31:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e65ed523-eddf-4cad-b3f8-b8dcf564f5b2</guid><dc:creator>nordicator_prim3</dc:creator><description>&lt;p&gt;SPIM0 and SPIM1 should not share any pins. It sounds like you want to access 2 different slave devices. Both devices can be under SPIM0 and use different chip selects. The chip select is not defined for SPIM0, it is only assigned for each slave device on that bus.&lt;/p&gt;
&lt;p&gt;I was assuming you&amp;#39;re using Zephyr but in hindsight that may not be the case.&lt;br /&gt;Example:&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;amp;spi2 {
	compatible = &amp;quot;nordic,nrf-spim&amp;quot;;
	status = &amp;quot;okay&amp;quot;;
	sck-pin = &amp;lt;0&amp;gt;;
	mosi-pin = &amp;lt;1&amp;gt;;
	miso-pin = &amp;lt;6&amp;gt;;
	cs-gpios = &amp;lt;&amp;amp;gpio0 24 GPIO_ACTIVE_LOW&amp;gt;, &amp;lt;&amp;amp;gpio0 13 GPIO_ACTIVE_LOW&amp;gt;;

	sdhc0: sdhc@0 {
		compatible = &amp;quot;zephyr,mmc-spi-slot&amp;quot;;
		reg = &amp;lt;0x0&amp;gt;;
		status = &amp;quot;okay&amp;quot;;
		spi-max-frequency = &amp;lt;8000000&amp;gt;;

		mmc {
			compatible = &amp;quot;zephyr,sdmmc-disk&amp;quot;;
			status = &amp;quot;okay&amp;quot;;
			label = &amp;quot;SDMMC_0&amp;quot;;
		};
	};

	// Wifi chip
	rs9116: rs9116@1 {
		status = &amp;quot;okay&amp;quot;;
		compatible = &amp;quot;silabs,rs9116&amp;quot;;
		reg = &amp;lt; 0x1 &amp;gt;;
		spi-max-frequency = &amp;lt;8000000&amp;gt;;
	};
};&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>