• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » Stellaris® ARM® Microcontrollers » Stellaris® ARM® LM3S Microcontrollers Forum » LM3S9B96: EPI write stall in FIFO mode after non-blocking reads are cancelled.
Share
Stellaris® ARM® Microcontrollers
  • Forum
Options
  • Subscribe via RSS
Helpful Stellaris® LM4F Series Links
  • LM4F Series
  • Stellaris PinMux Utility
  • Stellaris® LM4F120 LaunchPad
  • LM4F MCU Applications
  • LM4F MCU Video
  • ARM Cortex-M4F Whitepaper
  • Stellaris MCU Brochure
  • LM4F232 Eval Kit
  • Forums

    LM3S9B96: EPI write stall in FIFO mode after non-blocking reads are cancelled.

    This question is not answered
    Ralph Lang
    Posted by Ralph Lang
    on Apr 25 2012 13:47 PM
    Prodigy40 points
    EPI Register Snapshot.png

    Hello,

    I am unable to figure out why EPI writes are being permanently stalled after I cancel non-blocking reads.   The condition that creates this situation is as follows:

    1. The EPI is configured for HB8-FIFO mode of operation.

    2. Non-blocking reads are used to receive bytes (only on channel #0).  This works fine.

    3. Some time later in the application the non-blocking reads are cancelled by this code:

    HWREG(EPI0_BASE + EPI_O_RPSTD0) = 0;
    while ((HWREG(EPI0_BASE + EPI_O_STAT) & 0x11) == 0x10);

    4.  That code is followed by three writes to the EPI as follows:

    volatile char * epi;
    epi = (char *) 0xA0000000;
    *epi = 'O';
    *epi = 'K';
    *epi = 13;

    5.  At this point the application goes off doing some other stuff (non EPI related), but no write strobes are ever detected on EPI bus.  When the program is halted I read the following from the EPI registers:

    EPI_STAT:  0x0000 00A0        [external FIFO is not full (bit 8 clear) and a write is in progress (bit 5 set)]

    EPI_WFIFOCNT:  0x0000 0001    [1 slot left in write FIFO - because three bytes were written to it]

    Unfortunately the above register values never change.  It seems the external writes are permanently stalled I and am unable to figure out why.

    The attached file show the contents of all the EPI registers when the program was halted.

    I am probably missing something obvious but it escapes me.  Thanks for any assistance you can offer.

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • Bobby Bradford
      Posted by Bobby Bradford
      on Apr 26 2012 10:37 AM
      Genius9030 points

      One thing that was observed about your code segment in section 3) above.  After waiting for the status to clear, you are not draining the fifo.  That is the last step in the data sheet for terminating the non-blocking read mode.

      If adding that doesn't address the problem, we will try to reproduce the error here.  We will need more details about your hardware setup and also more details on the code that you are using to setup and access the EPI.

      --Bobby

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Ralph Lang
      Posted by Ralph Lang
      on Apr 26 2012 14:14 PM
      Prodigy40 points
      ccs5 - EPI write stalling.zip

      Hi Bobby,

      Thanks for your reply.  I added the code to clear out the RX FIFO but the problem persists.   To simplify things I created a new CCSv5 project that attempts to duplicate the exact conditions without all my project's other code (RTOS, LwIP, ect).  This CCSv5 project is attached (as a .zip archive).  

      First some hardware details.  The board I have is a custom one, not a dev kit.  The MCU clock source is an external 16 MHz crystal.  The EPI is connected to a FIFO composed of 12 signals in total.  8 data lines, one read strobe (active low), one write strobe (active low), one FIFO full (active high), and one FIFO empty (active high).

      The board also uses many other peripherals (UART, I2C, I2S, Ethernet, ect) but for the attached CCS project only the EPI is used.  I also have 4 hardware debug pins connected to a scope that allows me to trace program flow.

      Inside the attached CCS project zip are two pictures captured from a scope.  One picture show the EPI writes occurring as desired, while the other does not show any EPI writes.  In both pictures the same 8 signals are traced.  They are my debug 1 to 4 GPIO outputs, EPI FIFO full, EPI write strobe, EPI FIFO empty, and EPI read strobe. (note, the pictures are also shown below).

      The only code difference between the two pictures is the line (in main.c):

      ROM_EPINonBlockingReadStart(EPI0_BASE, 0, 512);

      If the above function call is made the EPI writes stall out and never occur.  However once I comment out the above line the EPI writes happen as expected.

      Here is the entire main.c file:

      /* EPI <-> FIFO Test Program:
       *
       *
       *
       * main.c
       */
      
      #include <stdint.h>
      
      #include "inc/hw_memmap.h"
      #include "inc/hw_types.h"
      #include "inc/hw_ints.h"
      #include "inc/hw_sysctl.h"
      #include "inc/hw_gpio.h"
      #include "inc/hw_epi.h"
      #include "driverlib/sysctl.h"
      #include "driverlib/gpio.h"
      #include "driverlib/epi.h"
      #include "driverlib/rom.h"
      
      // Define the hardware debug pins that can be monitored on a scope.
      #define DEBUG0_SET  		HWREG(GPIO_PORTJ_BASE + (GPIO_PIN_3 << 2)) = GPIO_PIN_3
      #define DEBUG0_CLR			HWREG(GPIO_PORTJ_BASE + (GPIO_PIN_3 << 2)) = 0
      
      #define DEBUG1_SET  		HWREG(GPIO_PORTH_BASE + (GPIO_PIN_5 << 2)) = GPIO_PIN_5
      #define DEBUG1_CLR			HWREG(GPIO_PORTH_BASE + (GPIO_PIN_5 << 2)) = 0
      
      #define DEBUG2_SET  		HWREG(GPIO_PORTE_BASE + (GPIO_PIN_0 << 2)) = GPIO_PIN_0
      #define DEBUG2_CLR			HWREG(GPIO_PORTE_BASE + (GPIO_PIN_0 << 2)) = 0
      
      #define DEBUG3_SET  		HWREG(GPIO_PORTE_BASE + (GPIO_PIN_1 << 2)) = GPIO_PIN_1
      #define DEBUG3_CLR			HWREG(GPIO_PORTE_BASE + (GPIO_PIN_1 << 2)) = 0
      
      //=================================================================
      void main(void) {
      
      	// Use external 16 MHz Xtal.
          // Set the clocking to run at 50 MHz from the PLL.
          ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
      
      	//	Enable and then reset the GPIO Peripherals (all banks).
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
          ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
      
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOA);
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOB);
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOC);
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOD);
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOE);
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOF);
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOG);
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOH);
          ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOJ);
      
      	// Enable and then reset the external bus peripheral.
      	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0);
      	ROM_SysCtlDelay(1);
      	ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_EPI0);
      	ROM_SysCtlDelay(1);
      
      	// 	------------------------
      	// 	Configure GPIO - DEBUG OUTPUT PINS
      
      	//	Port 'E':	pin 0 is DEBUG2
      	//				pin 1 is DEBUG3
      	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1);
      
      	//	Port 'H':	pin 5 is DEBUG1
      	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_5);
      
      	//	Port 'J':	pin 3 is DEBUG0
      	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_3);
      
      	// Configure the GPIO pins for EPI operation.
          ROM_GPIOPinConfigure(GPIO_PH3_EPI0S0);
          ROM_GPIOPinConfigure(GPIO_PH2_EPI0S1);
          ROM_GPIOPinConfigure(GPIO_PC4_EPI0S2);
          ROM_GPIOPinConfigure(GPIO_PC5_EPI0S3);
          ROM_GPIOPinConfigure(GPIO_PC6_EPI0S4);
          ROM_GPIOPinConfigure(GPIO_PC7_EPI0S5);
          ROM_GPIOPinConfigure(GPIO_PH0_EPI0S6);
          ROM_GPIOPinConfigure(GPIO_PH1_EPI0S7);
      
          ROM_GPIOPinConfigure(GPIO_PH6_EPI0S26);
          ROM_GPIOPinConfigure(GPIO_PH7_EPI0S27);
          ROM_GPIOPinConfigure(GPIO_PJ4_EPI0S28);
          ROM_GPIOPinConfigure(GPIO_PJ5_EPI0S29);
      
      	// D2, D3, D4, D5
      	ROM_GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5
      									  | GPIO_PIN_6 | GPIO_PIN_7);
      	// D0, D1, D6, D7, xEMPTY, xFULL
      	ROM_GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1
      									  | GPIO_PIN_2 | GPIO_PIN_3
      									  | GPIO_PIN_6 | GPIO_PIN_7);
      	// nRD, nWR
      	ROM_GPIOPinTypeEPI(GPIO_PORTJ_BASE, GPIO_PIN_4 | GPIO_PIN_5);
      
      
      	DEBUG0_SET;
      
      	// Set the EPI clock divider and operating mode.
      	ROM_EPIDividerSet(EPI0_BASE, 5);
      	ROM_EPIModeSet(EPI0_BASE, EPI_MODE_HB8);
      
      	// Configure the host-bus 8-bit operating mode for FIFO.
      	ROM_EPIConfigHB8Set(EPI0_BASE, EPI_HB8_MODE_FIFO
      								 | EPI_HB8_USE_TXEMPTY
      								 | EPI_HB8_USE_RXFULL
      								 | EPI_HB8_WRWAIT_2
      								 | EPI_HB8_RDWAIT_2
      								 | EPI_HB8_CSCFG_CS, 0);
      
      	// Set address map for a peripheral size of 256 bytes mapped at 0xA000 0000;
          ROM_EPIAddressMapSet(EPI0_BASE, EPI_ADDR_RAM_SIZE_256B | EPI_ADDR_PER_BASE_A);
      
      	// Configure the read and write FIFO levels.
      	ROM_EPIFIFOConfig(EPI0_BASE, EPI_FIFO_CONFIG_TX_EMPTY
      							   | EPI_FIFO_CONFIG_RX_1_8);
      
      	// Configure non-blocking reads on channel #0.  Note, channel #1 is not used at all.
      	ROM_EPINonBlockingReadConfigure(EPI0_BASE, 0, EPI_NBCONFIG_SIZE_8, 0);
      
      	DEBUG0_SET;
      
      	// At this point the EPI should be properly configured.
      
      	// Kill some time (~10 us).
      	ROM_SysCtlDelay(166);
      
      	DEBUG1_SET;
      
      	// Start EPI reading (channel 0) from the USB chip (up to 512 bytes).
          ROM_EPINonBlockingReadStart(EPI0_BASE, 0, 512);
      
      	// Kill some time (~10 us).
      	ROM_SysCtlDelay(166);
      
      	// Stop EPI non-blocking reads.
      	HWREG(EPI0_BASE + EPI_O_RPSTD0) = 0;
      	while ((HWREG(EPI0_BASE + EPI_O_STAT) & 0x11) == 0x10);
      
      	uint32_t ReadData = 0;
      	while (HWREG(EPI0_BASE + EPI_O_RFIFOCNT) != 0) {
      		ReadData += HWREG(EPI0_BASE + EPI_O_READFIFO);
      	}
      
      	DEBUG1_CLR;
      
      	// Kill some time (~10 us).
      	ROM_SysCtlDelay(166);
      
      	DEBUG0_CLR;
      
      	// Write three bytes.
      	volatile char * epi;
      	epi = (char *) 0xA0000000;
      	*epi = 'O';
      	*epi = 'K';
      	*epi = 13;
      
      	// Test complete.
      	while (1) {
      		DEBUG3_SET;
      		DEBUG3_CLR;
      	}
      
      }
      
      
      

      Here is the picture where EPI writes worked: (non-blocking reads were never started)

      And here is the picture where writes stalled out (non-blocking EPI reads were initiated for a short time then cancelled):

      The debug0 signal goes high after configuring the GPIO but before configuring the EPI.

      The debug1 signal goes high during the time non-blocking reads are active.

      The debug2 signal is not used.

      The debug3 signal marks the infinite loop at the end of main().

      No data was ever made available for reading by the EPI. This is why FIFO EMPTY is always high.

      Also...

      During this test I noticed that my debug0 signal was not behaving properly after the EPI is configured. This signal is connected to pin J3 on the MCU. J3 can be used as EPI0S19, but I am not using it in that manner. Just as a simply GP output. Any ideas why the EPI seems to take control over this pin?

      One other thing. Are the EPI read and write strobe glitches to be expected when configuring the peripheral?

      I hope this information helps. Please let me know if you need any additional information.

      Best regards,

      Ralph

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Bobby Bradford
      Posted by Bobby Bradford
      on Apr 27 2012 15:44 PM
      Genius9030 points

      Ralph,

      I've been able to download/build your project, and reproduce the results that you have seen/reported locally on a DK-LM3S9B96.  I am still trying to work through all of the code to understand all of the possible EPI configuration options to see if there is some configuration setting missing for this mode of operation.  It will likely be Monday or Tuesday next week before I am able to provide a better answer for what is happening.  But I did want to let you know the current status.

      --Bobby

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Ralph Lang
      Posted by Ralph Lang
      on May 03 2012 18:47 PM
      Prodigy40 points

      Hi Bobby,

      Well, I guess on the plus side the condition is reproducible.   Have you discovered any setting or configuration that I missed which is causing the writes to stall out?  From looking at the EPI peripheral register contents I am unable to see any obvious causes.

      Best regards,

      Ralph

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Bobby Bradford
      Posted by Bobby Bradford
      on May 04 2012 12:41 PM
      Genius9030 points

      Ralph,

      My apologies for the delay.  I am still coordinating with the IC and Apps team to determine exactly what is happening.  However, I do have a tentative work-around.  It involves setting the max delay to a non-zero value prior to terminating the non-blocking read operation.  This has the potential of resulting in invalid data in the nbr fifo (since a timeout could occur before the nbr is terminated).  So I would recommend draining the fifo of any valid data first, then implementing this modified piece of code to terminate the nbr.

       // Stop EPI non-blocking reads.
       uint32_t ReadData = 0;
       ReadData = HWREG(EPI0_BASE + EPI_O_HB8CFG);
       ReadData &= ~EPI_HB8CFG_MAXWAIT_M;
       ReadData |= (1 << EPI_HB8CFG_MAXWAIT_S);
       HWREG(EPI0_BASE + EPI_O_HB8CFG) = ReadData;
       HWREG(EPI0_BASE + EPI_O_RPSTD0) = 0;
       while ((HWREG(EPI0_BASE + EPI_O_STAT) & 0x11) == 0x10);

       ReadData = 0;
       while (HWREG(EPI0_BASE + EPI_O_RFIFOCNT) != 0) {
        DEBUG2_SET;
        ReadData += HWREG(EPI0_BASE + EPI_O_READFIFO);
        DEBUG2_CLR;
       }
       ReadData = HWREG(EPI0_BASE + EPI_O_HB8CFG);
       ReadData &= ~EPI_HB8CFG_MAXWAIT_M;
       HWREG(EPI0_BASE + EPI_O_HB8CFG) = ReadData;

       --Bobby

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Ralph Lang
      Posted by Ralph Lang
      on May 08 2012 14:11 PM
      Prodigy40 points

      Hi Bobby,

      Thanks for the update.  I used your code above to stop the non-blocking reads and it does the trick.   The writes are no longer stalled.  Here is a picture of the writes occurring (signal 'nWrite' is the write stobe).

      Note, the signal 'Debug1' goes low when the non-block reads are stopped.

      I then modified the code slightly such that it waits for some data to be received from the non-blocking reads before cancelling it.  This is the code added just before your new code to cancel the reads.

      	// Wait for a <CR> character to come in.
      	uint32_t EpiReadCount = 0;
      	while (1) {
      		if (HWREG(EPI0_BASE + EPI_O_RFIFOCNT) != 0) {
      			EpiReadCount++;
      			uint32_t EpiData;
      			EpiData = HWREG(EPI0_BASE + EPI_O_READFIFO);
      			if (EpiData == 13) {
      				// Got it, so exit the loop
      				break;
      			}
      		}
      	}
      

      I setup my hardware so two bytes are present in the external FIFO for reading by the EPI.  The byte values are 0x41 and 0x0D.  Sadly I encounter the same write stall condition as before.  Here is a picture:

      The two read strobes (nRead) indicates that the EPI is reading the external FIFO.  After the 2nd strobe the signal  'Debug1' goes low marking the code position where the non-blocking reads are cancelled.  Unfortunately the writes never occur after this.

      Somehow it seems like the EPI read strobes prevents the cancelling of the non-blocking reads.

      Best regards,

      Ralph

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use