Доброго времени суток!
Добрался до девайса, который спроектировали 4 года назад

уже и чипы "not recommended for new design" LM3S9B92 ревизия C5, но партия железок спаяна, поэтому есть острая необходимость доделать.
Сделал RX по DMA, как отдельный процесс, работает довольно гладко.
А с TX беда. По статусам показывает что фрейм отправлен, но реально фрейм не уходит.
Привожу упрощенный кусочек кода (оттестированный).
Пакет на отправку однотипно подготавливается для случая с DMA и без DMA.
вот этот кусочек подготавливает данные к отправке:
Код
U32 buffer[2048 >> 2]; // 2KB to conver whole TX fifo
void nic_TxPacket(U8 *pPacket, U32 size)
{
U16 len;
U8 *pTxBuf = (U8 *)buffer;
len = size - (ETHERNET_HDR_LEN); // size - 14 (TX len should contain data payload len w/o eth hdr)
memcpy(&pTxBuf[0], &len, sizeof(len)); // put frame len first
memcpy(&pTxBuf[2], pPacket, size); // copy rest of the packet
Подготовленный фрейм лежит в pTxBuf.
Вот этот кусочек работает на ура (здесь проц напрямую пишет в TX fifo подготовленный фрейм):
Код
U32 *p = (U32 *)pTxBuf;
size += 2; // inc by "len" field
size = (size + 3) >> 2; // convert size into word count
while(size--)
MAC_DATA_R = *p++;
MAC_TR_R = MAC_TR_NEWTX;
while(MAC_TR_R & MAC_TR_NEWTX);
если пытаюсь то же самое отправить по DMA - получаю статус DMA - все ОК, статус MAC - Tx complete. Но фрейма на выходе с девайса не вижу..
Код
pdma_RunAutoTxfer32(EMAC_TX_DMA_CHANNEL,
(U32 *)EMAC_FIFO_ADDR, // ==0x40048010
(U32 *)&pTxBuf,
size + 2);
while(udma_Busy(EMAC_TX_DMA_CHANNEL));
MAC_TR_R = MAC_TR_NEWTX;
while(MAC_TR_R & MAC_TR_NEWTX);
код функции "pdma_RunAutoTxfer32():
Код
#define EMAC_RX_DMA_CHANNEL 6
#define EMAC_TX_DMA_CHANNEL 7
#define udma_Busy(Chan) (UDMA_ENASET_R & (1 << (Chan)))
typedef struct tagUDMA_TASK_DESCRIPTOR
{
V32 Src; // contains pointer to the end of the source buffer (inclusive)
V32 Dst; // contains pointer to the end of the dest buffer (inclusive)
V32 Ctrl;
V32 reserved;
} UDMA_TASK_DESC, *PUDMA_TASK_DESC;
void pdma_RunAutoTxfer32(U32 Chan, U32 *pDst, void *pSrc, U32 size)
{
U32 cnt = (size + 3) >> 2;
U32 ChanMask = (1 << Chan);
PUDMA_TASK_DESC pTask = udma_GetPrimaryEntry(Chan);
cnt -= 1;
pTask->Src = (U32)pSrc + (cnt << 2); // pointer to the last word inclusive
pTask->Dst = (U32)pDst; // for PDMA TX dest is peripheral data reg
pTask->Ctrl = 0
| UDMA_CHCTL_DSTINC_NONE
| UDMA_CHCTL_DSTSIZE_32
| UDMA_CHCTL_SRCINC_32
| UDMA_CHCTL_SRCSIZE_32
| UDMA_CHCTL_ARBSIZE_1
| (cnt << UDMA_CHCTL_XFERSIZE_S)
| UDMA_CHCTL_XFERMODE_AUTO
;
UDMA_ALTCLR_R |= ChanMask; // use primary entry (clear alternate)
UDMA_ENASET_R |= ChanMask; // enable channel
UDMA_SWREQ_R |= ChanMask; // generate soft request to push channel
}
Буду благодарен если меня ткнут носом, что я делаю не так!