AnsweredAssumed Answered

P1021 eTSEC not DMA'ing to Tx unless I write 1 to enable Transmitter

Question asked by Zachary Wilcox on Feb 5, 2019
Latest reply on Feb 5, 2019 by Zachary Wilcox

I'm trying to transmit on the TSEC.  I set up the TSEC DMA registers by enabling the TDSEN, TBDSEN, WWR, and WOP bits (0xC3)
I enable the transmitter by writing 1 to the maccfg1 bit during setup.

 

 

During transmission, I set up the BD flags, clear the tstat transmit halt bit. 

I've verified in the JTAG that the trasnmitter bit in the maccfg1 register is still enabled.

However, the DMA doesn't kick back off until I write another 1 to the maccfg1 bit.
Why do I have to write another 1 to the maccfg1 bit for the DMA to kick off?

 

void TSEC_init(eth_device_t *dev)
{
     tsec_t* regs = dev->regs;
     //clear any events in the tsec before starting
     regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
     //clear events (w1c)
     regs->ievent = 0xFFFFFFFF;
     //see 15.9.3.2 for reset and reconfiguration procedure
     //1. Set GRS/GTS bit in DMACTRL register
     regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);

     //2. Poll until GRSC and GTSC bits are high in the IEVEN register
     while( (regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)) != (IEVENT_GRSC | IEVENT_GTSC));

     //3. Set SOFT_RESET bit in maccfg1 register -- must be set for 3 tx clocks
     regs->maccfg1 |= MACCFG1_SOFT_RESET;
     //this will do the trick.
     __asm__ volatile
     (
          "isync\n"
          "msync\n"
          "isync\n"
     );

     //4. Clear SOFT_REST bit in MACCCFG1
     dev->regs->maccfg1 &= ~MACCFG1_SOFT_RESET;

     //5.  Load TBASE with new TxBD Pointer
     //setup_tx_buffer_bd(dev);  //This is done when we're ready to transmit
     //6.  Load RBASE with new RxBD Pointer
     setup_rx_buffer_bd(dev);

     //7. setup MAC registers (MACCFG2, MAXFRM, ETC)
     //7a. set up mac controller attributes
     setup_mac(dev);

     //7b. set MAC address
     set_mac_address(dev);

     //7c. set the receiver length register.
     //8. Setup group address hash table
     set_mac_rx_attribute(dev);

     //9. Set up receive frame filer table if filing to multiple RxBD rings is required
     //-- no applicable

     //10 Setup WWR, WOP, TOD bits in DMACTRL register -- TOD isn't applicable
        //NOTE: DMACTRL is now 0xC3
     dev->regs->dmactrl |= (DMACTRL_TDSEN | DMACTRL_TBDSEN |  DMACTRL_WWR | DMACTRL_WOP);

     //11. Enable tqueue, ensure that tx scheduling mode is set in TCTRL
     //dont need tqueue (for now - might need for doing tcpip stuff, ie tcpip offloading)
     //12. Enable rqueue
     //dont need rqueue (for now)

     //13. Clear THLT and TXF bits in TSTAT (w1c)
     regs->tstat = 0xFFFFFFFF;
     //14. Clear QHLT and RXF bits in RSTAT (w1c)
     regs->rstat = 0xFFFFFFFF;

     //15.  Clear GRS/GTS bits in dmactrl reg
     regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);


     //16.  Enable tx_en/rx_en in maccfg1
     dev->regs->maccfg1 |= MACCFG1_TX_EN;
//     dev->regs->maccfg1 |= (MACCFG1_LOOPBACK);  //here for testing

     dev->regs->tbase = (uint32_t)(&dev->txbd[0]);
     //clear events (w1c)
//     regs->ievent = 0xFFFFFFFF;
}


void TSEC_tx(eth_device_t *dev, uint8_t* data, uint16_t length)
{

//     dev->regs->maccfg1 &= ~MACCFG1_TX_EN;

     txbd_t* free_bd = &dev->txbd[dev->tx_idx];
     if( free_bd->flags & TXBD_READY )
     {
          printf("BD isn't ready \r\n");
          return;
     }


     free_bd->length = length;
     free_bd->bufptr = (uint32_t)(data);

     free_bd->flags  = TXBD_READY | TXBD_INTERRUPT | TXBD_LAST;

     dev->regs->tstat = 0x80000000;
        //Why do I have to Write another 1 to the maccfg1?
        //Note: I have verfied that it's still enabled here.
     dev->regs->maccfg1 |= MACCFG1_TX_EN;

     dev->tx_idx++;
     dev->tx_idx %= NUM_OF_BD_BUFFER;

}

Outcomes