AnsweredAssumed Answered

BF-537: MAC DMA TX interrupt called in infinite loop

Question asked by Pauli on Aug 1, 2012
Latest reply on Aug 3, 2012 by James.Kosin

I recently started working on a simple, very limited real-time driver for the Blackfin Ethernet MAC device (outgoing UDP packets only, reception of frames is still handled by the non real-time driver in bfin_mac.c). The custom board which I'm using is quite similar to the BF-537 STAMP.

 

The real-time driver uses a chained list of descriptor pairs (packet descriptor desc_a and status descriptor desc_b) for DMA TX as recommended in the BF537 hardware reference. While experimenting with the DMA TX interrupt assigned to DMA channel 2, I experienced some strange behaviour.

 

I'm using a descriptor-based interrupt setup by enabling the DI_EN flag in the config word of the second status descriptor desc_b (along with DMAEN for both descriptors in a packet scheduled for trasnmission and other settings for direction, fetching etc.)

 

I started by using the xenomai real-time driver development API (rtdm_irq_xxxx) to register and manage the interrupt, but this didn't work at all. The system hangs on transmission of the first packet via DMA.

 

I had more success by leaving the interrupt management to the Linux Kernel. The minimalist ISR looks like this:

 

static irqreturn_t bfin_mac_interrupt_tx(int irq, void *irq_handle)

{

    u16 irq_status;

 

    irq_status = bfin_read_DMA2_IRQ_STATUS();

    while (irq_status & (DMA_RUN | DFETCH)) {

        DBG_ISR_PRINTK(1, "tx relax DMA status: 0x%04x\n", irq_status);

        irq_status = bfin_read_DMA2_IRQ_STATUS();

    }

   

    bfin_write_DMA2_IRQ_STATUS(bfin_read_DMA2_IRQ_STATUS() | DMA_DONE | DMA_ERR);

    SSYNC();

 

    DBG_ISR_PRINTK(1, "** ISR TX: opmode = 0x%x, sysctl = 0x%x, irq status=0x%x (was: 0x%x), frame status=0x%x, dma_config=0x%x\n",

         bfin_read_EMAC_OPMODE(), bfin_read_EMAC_SYSCTL(), bfin_read_DMA2_IRQ_STATUS(), irq_status, bfin_read_EMAC_TX_STAT(), bfin_read_DMA2_CONFIG());

 

    return IRQ_HANDLED;

}

 

This ISR was called on transmission of the first packet as expected, but then executed endless in an infinite loop. I could see from the debug output that the irq status flag was cleared in the status register after the first call but nevertheless it was called infinitely regardless of any packet transmission.

 

First output on packet transmission:

** ISR TX: opmode = 0x15090821, sysctl = 0x1903, systat = 0x0, irq status=0x0 (was: 0x1), frame status=0x12c0083, dma_config=0x7608


That seems ok except the dma_config register which should have DI_EN and DMAEN being set but seems to be filled with the next desc_a config value (which corresponding packet is not scheduled for transmission).

 

Output after the second, third etc. call:

** ISR TX: opmode = 0x15090821, sysctl = 0x1903, systat = 0x0, irq status=0x0 (was: 0x0), frame status=0x12c0083, dma_config=0x7608

 

There's no DMA_DONE or DMA_ERR flag set in the irq status register, but nevertheless the ISR has been called.

 

Does anybody has an idea what's going wrong here?

 

Thanks,

Rainer

Outcomes