This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EMACTxDMAPollDemand sends processor to fault isr

Other Parts Discussed in Thread: EK-TM4C123GXL

Hello,

I am new to the ethernet. I am fairly comfortable with Tiva, but this is my first venture into the ethernet realm. I am currently running on a tiva1294 launchpad.

I have a problem with the emac sending me to the fault isr after calling the EMACTxDMAPollDemand tiva command. I have ported most of my code from the enet_uip example project. I am at a loss as to where to look for clues. My standard NVIC_FAULT_ADDR register is reporting a location that isn't documented in the datasheet, 0xE000EDF8. 

When stepping through the code, as soon as I call EMACTxDMAPollDemand, the interrupt is triggered with a status of 0x00010040. I realize the 0x40 bit is the Int_Receive bit, but I do not know what the other one is for. 

I realize this is vague. Please let me know what other information would be helpful in diagnosing this. I'm stumped.

Thanks

  • I should probably add some of the standard information along with this post.
    Code Composer version 6.1.100022
    Arm compiler version 5.2.5
    Tivaware 2.1.2.111

    Using enet_uip.c as a design guide. My project is running FreeRTOS.

    Using the standard pinout() function call for init code.

    Ethernet descriptor init code:
    //
    // Get the MAC address from the user registers.
    //
    ROM_FlashUserGet(&ui32User0, &ui32User1);
    if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
    {
    rv = pdFAIL;
    }

    //
    // Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
    // address needed to program the hardware registers, then program the MAC
    // address into the Ethernet Controller registers.
    //
    pui8MAC[0] = ((ui32User0 >> 0) & 0xff);
    pui8MAC[1] = ((ui32User0 >> 8) & 0xff);
    pui8MAC[2] = ((ui32User0 >> 16) & 0xff);
    pui8MAC[3] = ((ui32User1 >> 0) & 0xff);
    pui8MAC[4] = ((ui32User1 >> 8) & 0xff);
    pui8MAC[5] = ((ui32User1 >> 16) & 0xff);

    // ASSERT((ui32IPMode == IPADDR_USE_STATIC) ||
    // (ui32IPMode == IPADDR_USE_DHCP) ||
    // (ui32IPMode == IPADDR_USE_AUTOIP));

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);

    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
    {
    }

    MAP_EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN |
    EMAC_PHY_AN_100B_T_FULL_DUPLEX);

    MAP_EMACReset(EMAC0_BASE);
    MAP_EMACInit(EMAC0_BASE, 120000000,
    EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4,
    0);

    MAP_EMACConfigSet(EMAC0_BASE, (EMAC_CONFIG_FULL_DUPLEX |
    EMAC_CONFIG_CHECKSUM_OFFLOAD |
    EMAC_CONFIG_7BYTE_PREAMBLE |
    EMAC_CONFIG_IF_GAP_96BITS |
    EMAC_CONFIG_USE_MACADDR0 |
    EMAC_CONFIG_SA_FROM_DESCRIPTOR |
    EMAC_CONFIG_BO_LIMIT_1024),
    (EMAC_MODE_RX_STORE_FORWARD |
    EMAC_MODE_TX_STORE_FORWARD |
    EMAC_MODE_TX_THRESHOLD_64_BYTES |
    EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);
    for(i = 0; i < NUM_TX_DESCRIPTORS; i++)
    {
    TxDescriptor[i].ui32Count =
    (DES1_TX_CTRL_SADDR_INSERT |
    (TX_BUFFER_SIZE << DES1_TX_CTRL_BUFF1_SIZE_S));
    TxDescriptor[i].pvBuffer1 = TxBuffer;
    TxDescriptor[i].DES3.pLink =
    (i == (NUM_TX_DESCRIPTORS - 1)) ?
    TxDescriptor : &TxDescriptor[i + 1];
    TxDescriptor[i].ui32CtrlStatus =
    (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG |
    DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_CHAINED |
    DES0_TX_CTRL_IP_ALL_CKHSUMS);
    }

    MAP_EMACRxDMADescriptorListSet(EMAC0_BASE, &RxDescriptor[0].TivaDescriptor);
    MAP_EMACTxDMADescriptorListSet(EMAC0_BASE, TxDescriptor);


    //
    // Program the hardware with its MAC address (for filtering).
    //
    MAP_EMACAddrSet(EMAC0_BASE, 0, (uint8_t *)pui8MAC);

    //wait for active link
    while((MAP_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
    EPHY_BMSR_LINKSTAT) == 0)
    {
    }


    MAP_EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_SADDR |
    EMAC_FRMFILTER_PASS_MULTICAST |
    EMAC_FRMFILTER_PASS_NO_CTRL));

    //
    // Clear any pending interrupts.
    //
    MAP_EMACIntClear(EMAC0_BASE, EMACIntStatus(EMAC0_BASE, false));
    //
    // Enable the Ethernet MAC transmitter and receiver.
    //
    MAP_EMACTxEnable(EMAC0_BASE);
    MAP_EMACRxEnable(EMAC0_BASE);

    //
    // Lower the priority of the Ethernet interrupt handler. This is required
    // so that the interrupt handler can safely call the interrupt-safe
    // FreeRTOS functions (specifically to send messages to the queue).
    //
    ROM_IntPrioritySet(INT_EMAC0, 0xC0);

    //
    // Enable the Ethernet interrupt.
    //
    MAP_IntEnable(INT_EMAC0);

    //
    // Enable the Ethernet RX Packet interrupt source.
    //
    MAP_EMACIntEnable(EMAC0_BASE, EMAC_INT_RECEIVE);


    ***************************
    And the transmit code


    *****************************
    while(TxDescriptor[currentTxDescriptor].ui32CtrlStatus &
    DES0_TX_CTRL_OWN)
    {
    //
    // Spin and waste time.
    //
    }

    currentTxDescriptor++;

    if(currentTxDescriptor >= NUMBER_TX_DESCRIPTORS){
    currentTxDescriptor = 0;
    }


    for(i=0;i<pxDescriptor->xDataLength;i++){
    TxBuffer[i] = *(pxDescriptor->pucEthernetBuffer + i);
    }

    //
    // Fill in the packet size and tell the transmitter to start work.
    //
    TxDescriptor[currentTxDescriptor].ui32Count = (uint32_t)pxDescriptor->xDataLength;

    TxDescriptor[currentTxDescriptor].pvBuffer1 = TxBuffer;

    TxDescriptor[currentTxDescriptor].ui32CtrlStatus =
    (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG |
    DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_IP_ALL_CKHSUMS |
    DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_OWN);

    //
    // Tell the DMA to reacquire the descriptor now that we've filled it in.
    //
    //MAP_EMACTxDMAPollDemand(EMAC0_BASE);
    EMACTxDMAPollDemand(EMAC0_BASE); //try non MAP_ call, no difference
    while(xSemaphoreTake(TX_InterruptSem, portMAX_DELAY))
    {

    } //spin until the interrupt has signaled transmission was good
  • On a quick glance the code looks ok. Can you attach your project here, so that I can take a closer look?

    In the future while posting code, please click on "Use rich formatting" and use Syntax Highlighter (with the icon Insert code using Syntaxhighlighter). This make it easy to review the code.

    Thanks,

    Sai

  • Hi Sai,

    Unfortunately I cannot attach my project. I can attach the relevant files as you see fit. I am running FreeRTOS and their tcp/ip stack. I can send you the couple files I needed to port in order to get it up and running. There are some other things within the project that I cannot post to the web. The problem is isolated to the ip/ethernet stacks.

    The problem must also be occurring prior to the EmacTxDemandPoll function call. I removed that completely and I still end up in the ISR. I have not been able to pinpoint it.

    Is there a way to gleam additional information from any the registers to figure out what exactly sent me to the fault ISR?

    I am always paranoid about stack overflows. Would that cause me to end up in the fault isr? I have allocated 32k of ram for the stack. Maybe overkill but I have plenty of space on this chip. The senshub_iot project called out 16k so I figured I'd at least top that.

    Back when I was originally working with the stellaris M4 chips, I remember a document that would help walk you through diagnosing a fault_isr condition. I can't seem to find that. Does that exist for the tiva stuff?

    Thanks!
  • Can you use the "freertos_demo" project in the folder "./examples/boards/dk-tm4c129x/freertos_demo" as the base, to remove any doubts about stack usage? This example serves a HTTP server using lwIP and FreeRTOS. You can remove the parts of the project that is not required and just add one component at a time to see what is causing the issue. Please note that this example has code that uses the LCD display on the DK-TM4C129X board, which might have to removed.

    If you continue to have issues, this approach will be easier for the members on this community to reproduce the issue and maybe help in debug.

    Also to confirm the TCP/IP stack being used is from FreeRTOS and not lwIP. Correct?

    The "Diagnosing Software Faults" document is relevant to both Cortex M3 and M4 devices. It can be found here: www.ti.com/.../spma043.pdf

    Thanks,
    Sai
  • Hello Sai,

    I will see if I can get the free_rtos demo running. That example is for the smaller tm4c123 series launchpad correct?

    Correct, I am using the FreeRTOS tcp/ip stack found here:
    www.freertos.org/.../index.html

    I followed the porting guide link found on that page to write the network interface layer and compiler setup headers.

    I require socket support, which I was told was not supported on the lwip implementation found in tivaware. Decided to give this freertos stack a try.

    Thanks for the document. That't the one I remember.
  • The "freertos_demo" that I mentioned is for the DK-TM4C129X board, that has a TM4C129 microcontroller. This application uses lwIP.

    There is another "freertos_demo" for the EK-TM4C123GXL board, which is aimed at introducing the FreeRTOS on TM4C MCUs.

    Currently, BSD sockets is not supported on lwIP, but we are looking onto the effort it takes to support it.

    Thanks,
    Sai
  • I officially have a palm to forehead moment.

    I wanted to move away from the lwip definitions of NUM_RX_DESCRIPTORS and NUM_TX_DESCRIPTORS. In my infinite wisdom I decided to name them NUMBER_TX_DESCRIPTORS and NUMBER_RX_DESCRIPTORS. Well, I missed two when renaming and I forgot to remove my include paths to lwip in my project settings. I had things pointing who knows where from referencing two different size of descriptor arrays. (That issue is in the code snippet above). Fixed that and I am not longer ending up in the fault isr.....