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

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

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

Jump to solution
761 Views
zwilcox
Contributor IV

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;

}
Tags (4)
0 Kudos
1 Solution
650 Views
zwilcox
Contributor IV

Blah. Solved it.  The reference manual says that the tstat register needs to be set before enabling the transmitter.
The following has resolved the issue.

Thanks.

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
 dev->regs->tbase = (uint32_t)(&dev->txbd[0]);
 //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
 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;

 //clear events (w1c)
// regs->ievent = 0xFFFFFFFF;
}

View solution in original post

0 Kudos
1 Reply
651 Views
zwilcox
Contributor IV

Blah. Solved it.  The reference manual says that the tstat register needs to be set before enabling the transmitter.
The following has resolved the issue.

Thanks.

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
 dev->regs->tbase = (uint32_t)(&dev->txbd[0]);
 //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
 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;

 //clear events (w1c)
// regs->ievent = 0xFFFFFFFF;
}
0 Kudos