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;
}
Solved! Go to Solution.
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;
}
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;
}