SPI 16 / 32 bits_per_word transfers fail

Discussion around products based on ARM Cortex-A5 core.

Moderator: nferre

mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

SPI 16 / 32 bits_per_word transfers fail

Wed Aug 13, 2014 1:34 pm

I am writing an SPI driver to access a TI ADS1281. The driver is reacting to a IRQ on GPIO on PB28, if the ADC generates a falling edge on DRDY (Data Ready).

Inside the IRQ handler i am starting a asynchronous SPI transfer to read out the 32Bit data word from ADC.

Code: Select all

/**
 * \brief
 * 
 * This is the completion handler for all async transfers that are started as
 * read access by the Data Ready IRQ handler. It will read the data from the 
 * rx buffer of the IRQ SPI transfer structure.
 * 
 * \author MWI
 * \date 2014-08-11
 */
static void adu_adb_spi_irq_completion_handler(void *arg)
{
  // declaration of variables
  int i_buff_index = atomic_read (&atom_irq_buff_num);
  
  if (atomic_read (&atom_irq_xfer_active) == 0)
  {
    printk(KERN_ALERT "[adu_adb_spi]: completian handler called, although no IRQ was handled!\n");
    printk(KERN_ALERT "[adu_adb_spi]: --> ignoring even !!!\n");
  }
  else
  {
    /*
    printk (KERN_ALERT "[adu-adb-spi] IRQ Completion Handler: %s ready on SPI%d.%d: data: 0x%2.2x%2.2x%2.2x%2.2x\n",
	    this_driver_name,
	    adu_adb_spi_dev.spi_device->master->bus_num,
	    adu_adb_spi_dev.spi_device->chip_select,
	    arc_irq_rx_buff[0], arc_irq_rx_buff[1], arc_irq_rx_buff[2], arc_irq_rx_buff[3]);
    */

    if (ui_irq_buff_sampl_count [i_buff_index] < C_IRQ_BUFF_SIZE)
    {
      // copy contents of receive buffer to local data buffer
      pi_irq_buff [i_buff_index] [ui_irq_buff_sampl_count [i_buff_index] + 0] = arc_irq_rx_buff [0];
      pi_irq_buff [i_buff_index] [ui_irq_buff_sampl_count [i_buff_index] + 1] = arc_irq_rx_buff [1];
      pi_irq_buff [i_buff_index] [ui_irq_buff_sampl_count [i_buff_index] + 2] = arc_irq_rx_buff [2];
      pi_irq_buff [i_buff_index] [ui_irq_buff_sampl_count [i_buff_index] + 3] = arc_irq_rx_buff [3];
      ui_irq_buff_sampl_count [i_buff_index] += 4;
    }
    else
    {
      printk(KERN_ALERT "[adu_adb_spi]: receive buffer full - data loss!\n");
    }    
    
    // free SPI interface for read / write access
    atomic_set (&atom_irq_xfer_active, 0);  
  }
}



/**
 * \brief
 * 
 * This IRQ handler reacts on DRDY (Data Ready) coming from the ADC and reads
 * the 32Bit data word from the ADC. It stores the data inside the driver internal
 * buffer that can be read by the drivers "read" function from user space.
 * 
 * @param[in] int irq = irq to handle (comes from linux system - not used, as only 1 IRQ is registered for this handler)
 * @param[in] void *dev_id = pointer to device id (not used)
 * @param[out] irqreturn_t = status IRQ (always IRQ_HANDLED)
 * 
 * \author MWI
 * \date 2014-08-11
 */
irqreturn_t adu_adb_spi_irq_handler(int irq, void *dev_id)
{
  // declaration of variables
  ssize_t s_status = 0;
  
  if (c_ignore_irq == 0)
  {
    //printk("[adu_adb_spi]: IRQ handler was called for IRQ %i\n", irq);
    
    if (atomic_read (&atom_irq_xfer_active) == 1)
    {
      /*
      printk(KERN_ALERT "[adu_adb_spi]: LAST IRQ WAS NOT HANDLED YET (callback missing) !!!\n");
      printk(KERN_ALERT "[adu_adb_spi]: IGNORING ACTUAL DRDY - POSSIBLE DATA LOSS !!!\n");
      */
    }
    else
    {
      // block SPI for data read access - is freed again in completion handler
      atomic_set (&atom_irq_xfer_active, 1);
      
      if (!adu_adb_spi_dev.spi_device)
      {
	strcpy(adu_adb_spi_dev.user_buff, "spi_device is NULL\n");
      }
      else if (!adu_adb_spi_dev.spi_device->master)
      {
	strcpy(adu_adb_spi_dev.user_buff, "spi_device->master is NULL\n");
      }
      else
      {
	// initialise the read of 4 bytes from SPI    
	memset(arc_irq_tx_buff, 0xFF, sizeof (arc_irq_tx_buff));
	memset(arc_irq_rx_buff, 0x00, sizeof (arc_irq_rx_buff));
	
	spi_irq_xfer.tx_buf = arc_irq_tx_buff;
	spi_irq_xfer.rx_buf = arc_irq_rx_buff;
	spi_irq_xfer.len    = 4;
	
	// initialise spi message
	spi_message_init (&spi_irq_msg);      
	spi_irq_msg.complete = adu_adb_spi_irq_completion_handler;
	spi_irq_msg.context  = NULL;      
	
	// add xfer to message
	spi_message_add_tail(&spi_irq_xfer, &spi_irq_msg);
	
	s_status = spi_async_locked (adu_adb_spi_dev.spi_device, &spi_irq_msg);
      }
    }
    
    //printk("[adu_adb_spi]: handled IRQ for GPIO %i\n", irq);
  }
  
  return IRQ_HANDLED;
}
The problem is, that the first 8 Bit transfer starts immediately after the IRQ was handled, but the following 3 8 bit transfers are delayed a arbitray time 10us to 20us. This is just incredibly long time, which reduces the maximum sampling rate (SPI bandwidth) dramatically. does anyone have an idea, why I see this huge gap between the 8 bit transfers?

As alternative I tried to do 1 single 32 bit or 2 16 bit transfer, but in both cases the SPI is not sending out any data, if setting the bits_per_word field to any such value (even 16 Bit does not work). It does not matter, if I modify the spi_device.bits_per_word or spi_transfer.bits_per_word fields here. In both cases I get no data on SPI at all.

I also tried to compile the kernel with full preemption support, but it did not make any difference.

Using SAMA5D33ek with SPI and mainline kernel 3.15.7, cross compiled using Pengutronix PTXDist.

Can anyone tell me, what I am doing wrong? Or if this is just the way it is I will need to get rid of Linux and do everything directly on the Processor ( :( ).
blue_z
Location: USA
Posts: 1690
Joined: Thu Apr 19, 2007 10:15 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Wed Aug 13, 2014 10:21 pm

mwi wrote:I am writing an SPI driver to access a TI ADS1281.
Apparently there is little/no Linux support for this device.
What driver structure are you following?
Are you utilizing the IIO subsystem (for trigger and ring buffer management)?
Have you studied any of the existing ADC drivers that use the IIO and SPI subsystems, e.g. drivers/iio/adc/ad7887.c?
Some documentation on that ADC driver and IIO is here.
AT91 use of IIO is documented here.

Regards
mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Thu Aug 14, 2014 3:22 pm

What driver structure are you following?
Originally started from the spike spi driver. Did not know about the IIO subsytem. Do you think that this will speed up my application?

I think the main problem is the big delays on SPI. On my Scope I see the falling edge on DRDY which triggers my IRQ handler, but the first data transfer on SPI is starting >= 40us later.

I do not understand this delay completely, as the spi_async_locked transfer is started directly inside the IRQ handler.

Another observation is that sometimes (not regularly) the first data transfer on SPI is delayed for deveal ms, which makes me skip some samples already at 250Hz (which is rather slow sampling rate).

Is this normal Linux behaviour, if not running a RT kernel?
mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Thu Aug 14, 2014 3:24 pm

One note: I set preemption to Low latency Desktop, but does not make any change.

Additional note: as far as i see the Analog Devices driver uses the SPI Subsystem, too. So if the SPI Subsystem causes the delays, they should be visible, too, if using IIO Subsystem.

Maybe Analog Devices implements the better SPI Master driver. I will check the Analog Devices SPI master driver and compare to spi-atmel.
mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Mon Aug 18, 2014 4:34 pm

Update:

SPI performance could be increased by:

1.) replacing the IRQ handler in spi-master driver with direct polling function that looks for TXEMPTY to be set in SR register.
-->this removes the "inter byte" delays

Code: Select all

/**
 * \brief This function waits for the completion of the last transfer in polling mode.
 * 
 * It will poll the TXEMPTY flag inside the SPI_SR register to check, if the current transfer has finished.
 * Additionally it will check for overruns and read lasting data.
 * 
 * \author MWI (Metronix)
 * \date 2014-08-18
 */
static const int atmel_spi_mtx_pio_interrupt_poll (void *dev_id)
{
  struct spi_master	*master = dev_id;
  struct atmel_spi_mtx	*as 	= spi_master_get_devdata(master);
  u32			status, pending, imr, csr, mr;
  struct spi_transfer	*xfer;
  int			ret 	= 1;

  #ifdef C_MODULE_DBEUG
    unsigned long ul_jiffies = jiffies;
    printk ("[api-atmel-mtx] atmel_spi_mtx_pio_interrupt_poll was called ... %lu\n", ul_jiffies);
  #endif
    
  // wait, until all data has been transmitted
  do
  {
    status = spi_readl(as, SR);
  } while ((status & 0x00000200) == 0x00000000);  
  
  imr 	  = spi_readl(as, IMR);
  status  = spi_readl(as, SR);
  pending = status & imr;
  
  if (pending & SPI_BIT(OVRES))
  {

    //printk ("[api-atmel-mtx] atmel_spi_mtx_pio_interrupt_poll - 3\n");
    
    ret = -1;
    spi_writel(as, IDR, SPI_BIT(OVRES));
    dev_warn(master->dev.parent, "overrun\n");

    /*
     * When we get an overrun, we disregard the current
     * transfer. Data will not be copied back from any
     * bounce buffer and msg->actual_len will not be
     * updated with the last xfer.
     *
     * We will also not process any remaning transfers in
     * the message.
     */
    as->done_status = -EIO;
    smp_wmb();

    /* Clear any overrun happening while cleaning up */
    spi_readl(as, SR);
  }
  else if (pending & SPI_BIT(RDRF))
  {
    
    // no lock of mutex in polling mode
    //atmel_spi_mtx_lock(as);

    if (as->current_remaining_bytes)
    {
      xfer = as->current_transfer;
      atmel_spi_mtx_pump_pio_data(as, xfer);
      
      if (!as->current_remaining_bytes)
      {
	spi_writel(as, IDR, pending);
      }
    }

    // no lock of mutex in polling mode
    //atmel_spi_mtx_unlock(as);
  }
  else
  {
    WARN_ONCE(pending, "IRQ not handled, pending = %x\n", pending);
    ret = -1;
    spi_writel(as, IDR, pending);
  }

  return ret;  
}
2.) call spi_pump_messages (...) in spi.c directly after transferring new message to SPI bus in __spi_async (...)
-->removes the sometimes very long delays from point of time that spi_aysnc (...) is called until SPI is accessed by master driver.

Code: Select all

static int __spi_async(struct spi_device *spi, struct spi_message *message)
{
  int i_ret_value; 
  
	struct spi_master *master = spi->master;

	message->spi = spi;

	trace_spi_message_submit(message);
	
	i_ret_value = master->transfer(spi, message);
	
	// manually update censored now directly for master
	spi_pump_messages (&(master->pump_messages));

	return (i_ret_value);
}
The SPI on Atmel Sama5d33 can only do 16Bit transfers. This very likely is why bits_per_word = 32 fails. But still 16Bit transfer fail too. Did not go into this until now.

Using this modifications I can read data from the ADS1281 at 4kHz. I think that I could even do 8kHz (which is not supported by the ADS1281 anymore), but for faster transfers the delays inside the Linux are too big (e.g. from falling edge of DRDY to start of IRQ handler >= 6us - measured by setting GPIO in IRQ Handler).
mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Wed Aug 20, 2014 1:44 pm

I want to run the IRQ handler now in FIQ mode to avoid any latencies and try to read the SPI data manually inside the FIQ handler routine.

Question is now how to configure the IRQ as FIQ? I already do the following:

Code: Select all

  // request FIQ for GPIO
  printk(KERN_ALERT "[adu-adb-spi] requesting FIQ for GPIO %i ... \n", C_GPIO_TO_HANDLE);
  error = claim_fiq (&s_adu_adb_spi_fiq_handler);
  if (error)
  {
    printk(KERN_ALERT "[adu-adb-spi] failed to claim FIQ: %i\n", error);
    return error;
  }
  
  // configure ASM function as FIQ handler (function pointer, length of function)
  set_fiq_handler(&adu_adb_spi_fiq_handler, &adu_adb_spi_fiq_handler_end - &adu_adb_spi_fiq_handler);

  // set FIQ registers to give parameters to FIQ handler - FIQ works on special registers
  // R8 .. R15, which cannot be accessed by any other resource then another FIQ, but FIQ calls
  // cannot be nested.
  regs.ARM_r8  = 0x00000000;
  regs.ARM_r9  = 0x00000001;
  regs.ARM_r10 = 0x00000002;
  set_fiq_regs(&regs);

  // configure the IRQ to be FIQ
  // NOTE: this function is implemented for IMX (Freescale) - does not work for Atmel SAMA5Dx i would guess
  mxc_set_irq_fiq(ui_irq, 1);

  // enable FIQ
  enable_fiq(ui_irq);   
I am missing the part to enable the "Force Fast Interrupt" inside the AIC. Mainly I do not know which value should be inserted into INTSEL inside AIC_SSR to configure the same IRQ (PIOB28) as FIQ, that I am now using as IRQ source.

The data sheet refers to the PID. Does this mean that I have to use the PID for PIOB (7)? In this case, would this mean that all interrupts coming in from PIOB would be executed as FIQ (maybe this is not what I want)?
mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Thu Aug 21, 2014 3:52 pm

After some more reading in data sheet now it is clear, that each PIO controller (A .. E) only fires one IRQ to the AIC for all 32 I/Os.

Happily on PIO B I am using my DRDY IRQ is the only one beeing active, so should be save to configure it as FIQ. In this case the INTSEL value is 7 (PID for PIO B).

I am activating the FIQ now in the following way:

Code: Select all

  // request FIQ for GPIO
  printk(KERN_ALERT "[adu-adb-spi] requesting FIQ for GPIO %i ... \n", C_GPIO_TO_HANDLE);
  error = claim_fiq (&s_adu_adb_spi_fiq_handler);
  if (error)
  {
    printk(KERN_ALERT "[adu-adb-spi] failed to claim FIQ: %i\n", error);
    return error;
  }
  
  // configure ASM function as FIQ handler (function pointer, length of function)
  set_fiq_handler(&adu_adb_spi_fiq_handler, &adu_adb_spi_fiq_handler_end - &adu_adb_spi_fiq_handler);

  // set FIQ registers to give parameters to FIQ handler - FIQ works on special registers
  // R8 .. R14, which cannot be accessed by any other resource then another FIQ, but FIQ calls
  // cannot be nested.
  
  // load r8 with base address of AIC
  regs.ARM_r8  = ioremap_nocache (C_SAMA5D3_AIC_BASE_ADDR, 0x000000FC);
  
  // load r9 with base address of PIO E controller
  regs.ARM_r9  = ioremap_nocache ((C_SAMA5D3_PIO_BASE_ADDR + (4 * C_SAMA5D3_PIO_BLOCK_OFFSET)), 0x00000114);
  
  // load r10 with bitmask of GPIO to toggle in PIO E controller
  u32_tmp      = (unsigned int) (C_GPIO_TOGGLE / 32); 
  u32_tmp      = C_GPIO_TOGGLE - (32 * u32_tmp);
  u32_tmp      = 0x00000001 << u32_tmp;
  regs.ARM_r10 = u32_tmp;
  set_fiq_regs(&regs);

  // configure the IRQ to be FIQ - must be done by direct access to AIC registers
  local_irq_disable ();
  
  u32_intsel = aic_readl (C_SAMA5D3_AIC_SSR);
  
  aic_writel (ui_irq_gpio_pio_pid, C_SAMA5D3_AIC_SSR);
  aic_writel (0x00000001,          C_SAMA5D3_AIC_FFER);
  
  u32_tmp = aic_readl (C_SAMA5D3_AIC_FFSR);
  if (u32_tmp != 0x00000001)
  {
    printk(KERN_ALERT "[adu-adb-spi] failed to activate Fast Forcing for PID: %i\n", ui_irq_gpio_pio_pid);
    aic_writel (u32_intsel, C_SAMA5D3_AIC_SSR);
    return error;
  }
  
  aic_writel (u32_intsel, C_SAMA5D3_AIC_SSR);

  // enable FIQ
  enable_fiq(ui_irq);   


My FIQ handler looks as follows:

Code: Select all

	.text
	.global adu_adb_spi_fiq_handler_end

ENTRY(adu_adb_spi_fiq_handler)
	/*
	 * The interrupt ACK needs to be put first in
	 * the handler to have time for the write to the
	 * interrupt controller to propagates on the bus.
	 * See http://forums.arm.com/index.php?/topic/13692-pipeline-issue-on-return-from-fiq/
	 */
	
	/*
	 * r8: 	ioremapped address of AIC controller base
	 * r9:	ioremapped address of PIO E base
	 * r10:	bitmask for GPIO to toggle in PIO E
	 */ 
       
	/* toggle PIO E30 pin */
	ldr	r11, [r9, +#0x0038]	/* get contents of PIO_ODSR for PIO E */
	
	ANDS	r13, r11, r10	
       
	CMP	r13, r10
	BEQ	deactivate_io
              
	/* activate I/O pin in output register */
	ORRS	r13, r11, r10
	str	r13, [r9, +#0x0038]
	b	out
       
      deactivate_io:
	mvn	r12, r10		/* mask PIO E30 I/O */
	
	ANDS	r13, r11, r12	
	str	r13, [r9, +#0x0038]
	
      out:
	/* Acknowledge the interrupt - write 0x00000001 to AIC_ICCR */
	movw	r11, #0x0001
	movt	r11, #0x0000
	
	str	r11, [r8, +#0x0048]	/* acknowkedge the FIQ by writing 1 to AIC_ICCR */

	/* return from FIQ */
	subs	pc, lr, #4
	
adu_adb_spi_fiq_handler_end:
It should toggle GPIO PIO E30 to check on scope, if the FIQ handler is working.

Unfortunately the System hangs up as soon as I give the first IRQ to the DRDY GPIO line. Before the FIQ occurs, system is running well. No messages occur on dmesg.

Is anyboday able to tell me what I am doing wrong. I thought that maybe the set_fiq_handler (...) function does not work well for sama5d3? Because I saw that the contents of AIC_SVR is 0x00000000 before AND after calling set_fiq_handler (...). I what think that the handler functions address should be inserted there for INTSEL = 0 after calling set_fiq_handler (...)?
mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Thu Sep 04, 2014 10:45 am

Now switched from PIO B28 to PIO C31, which is the direct FIQ line to the processor. This avoids the need to Fast Forcing. By implementing a endless loop I can see, that my FIQ handler is definitely executed (system stalls, where as without endless loop, system continous to work, after FIQ signal disappeared).

But if I try to access the GPIOs to toggle PIO E30 for checking, I do not see anything happen. Acces is done by io_remapped address I store in FIQ register R9. Therefore I think that:

1.) either the set_fiq_register (...) function fails and the addresses I get inside those registers are wrong.

2.) Or the addresses are different from the ones I get from io_remap (...) inside the ASM FIQ handler in FIQ context.

Hard to find out. Anny ideas? I asked Atmel support for help, but it seems that they never used FIQs so far for the SAMA5d3x (neither on Linux, nor in Bare Metal).
mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Tue Sep 09, 2014 9:15 am

Using the FIQ line directly now works pretty nice. The following needs to be done inside the drivers init function to activate the FIQ:

Code: Select all

 // ======================================================== //
  // configure FIQ - start                                    //
  // ======================================================== //
  local_irq_disable ();

  // save INTSEL
  u32_intsel = aic_readl (C_SAMA5D3_AIC_SSR);
  
  // request FIQ for GPIO
  printk(KERN_ALERT "[adu-adb-spi] requesting FIQ for GPIO %i ... \n", C_GPIO_TO_HANDLE);
  error = claim_fiq (&s_adu_adb_spi_fiq_handler);
  if (error)
  {
    printk(KERN_ALERT "[adu-adb-spi] failed to claim FIQ: %i\n", error);
    return error;
  }
  
  // configure ASM function as FIQ handler (function pointer, length of function)
  // does not seem to work on atmel sama5d3x
  set_fiq_handler(&adu_adb_spi_fiq_handler, &adu_adb_spi_fiq_handler_end - &adu_adb_spi_fiq_handler);

  // set FIQ registers to give parameters to FIQ handler - FIQ works on special registers
  // R8 .. R14, which cannot be accessed by any other resource then another FIQ, but FIQ calls
  // cannot be nested.
  // Note that R13 contains the SP and R14 the LR.

  // SPI-1
  regs.ARM_r8  = ioremap_nocache (0xF8008000, 0x000000EC);
  
  // AIC
  regs.ARM_r9  = ioremap_nocache (0xFFFFF000, 0x000000EC);
  
  // PIO E
  regs.ARM_r10 = ioremap_nocache (0xFFFFFA00, 0x00000104);
  
  set_fiq_regs(&regs);

  // enable Fast Interrupt
  aic_writel (0x00000000, C_SAMA5D3_AIC_SSR);
  aic_writel (0x00000001, C_SAMA5D3_AIC_IECR);
  
  /* set trigger level for FIQ */
  u32_tmp = C_SAMA5D3_AIC_SMR_SRCTYPE_LEVEL_LOW;
  aic_writel (u32_tmp, C_SAMA5D3_AIC_SMR);
  
  // enable FIQ
  enable_fiq(ui_irq_gpio_pio_pid);    

  local_irq_enable ();

  // ======================================================== //
  // configure FIQ - end                                      //
  // ======================================================== //
My FIQ handler looks as follows (doing nothing till now that toggling a GPIO):

Code: Select all

  
#include <linux/linkage.h>
#include <asm/assembler.h>


	.text
	.global adu_adb_spi_fiq_handler_end

ENTRY(adu_adb_spi_fiq_handler)
	/*
	 * The interrupt ACK needs to be put first in
	 * the handler to have time for the write to the
	 * interrupt controller to propagates on the bus.
	 * See http://forums.arm.com/index.php?/topic/13692-pipeline-issue-on-return-from-fiq/
	 */
	
	/*
	 * r8: 	ioremapped address of AIC controller base
	 * r9:	ioremapped address of PIO E base
	 * r10:	bitmask for GPIO to toggle in PIO E
	 * r14: contains value of PC before branch to FIQ handler - DO NOT OVERWRITE!
	 */ 

	/* set IO low */
	movw	r12, #0x0000
	movt	r12, #0x4000
	str	r12, [r10, #0X0030]
	str	r12, [r10, #0x0034]
	
	/* Acknowledge the interrupt (and disable) the FIQ */
	ldr	r12, [r9, #0x0000]
	
	movw	r11, #0x0000
	movt	r11, #0x0000
	str	r11, [r9, #0x0000]
	
	movw	r11, #0x0001
	movt	r11, #0x0000
	str	r11, [r9, #0x0048]

	str	r12, [r9, #0x0000]
	
	/* set IO low */
	movw	r12, #0x0000
	movt	r12, #0x4000
	str	r12, [r10, #0x0034]
	str	r12, [r10, #0X0030]
	
	/* return from FIQ */
	subs	pc, lr, #4
	
adu_adb_spi_fiq_handler_end:
Most important is to directly ack the FIQ after the handler has been called as otherwise it will be called over and over again.

Latency is pretty short and stable (as far as I can see on scope). Latency from falling edge of DRDY to Toggle of GPIO inside handler is < 1us (in most cases arround 660ns).

This is much better than normal IRQ calls inside Linux with latency > 6us (and jitter of sometimes > 1ms, which would skip samples already at very low sample frequencies).

Take care to keep the FIQ handler short as long delays will cause trouble inside the Linux system (e.g. high res timer will fail, ...).
mwi
Posts: 25
Joined: Wed Jul 30, 2014 9:17 pm

Re: SPI 16 / 32 bits_per_word transfers fail

Mon Sep 29, 2014 9:31 am

After some searching in the web I found that it seems the AIC of the Sama5D3x is not fully supported yet in actual kernel versions. There seems to be a patch series for full AIC hardware support available, but not yet integrated into the Linux kernel.

I hope, that the jitter of the FIQ (~660ns) will disappear once the AIC is fully supported by hardware.

Return to “SAMA5D Cortex-A5 MPU”

Who is online

Users browsing this forum: No registered users and 1 guest