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.

TMS570LS3137: EMIF Asynchronous Timing unable to Write/Read device properly

Part Number: TMS570LS3137
Other Parts Discussed in Thread: HALCOGEN

I am having trouble interfacing with an external memory device over the EMIF Async 1 interface. This is my first time doing this sort of thing so sorry for any mistakes.

1. EMIF Clk is set to 36 MHz or ~27.8 ns / clk, EMIF device is set to 16 MHz or ~62.55 ns / clk

We are utilizing a 16-bit buffered, non zero wait approach with both external device select and strobe pins attached to the EMIF_nCS2

I believe my timing values i set are incorrect and therefore I am unable to configure the device or read from it correctly. Any help would be greatly appreciated.

My Current values are as follows:

void emif_ASYNC1Init(void)
{
    /* USER CODE BEGIN (4) */
    /* USER CODE END */
        emifREG->CE2CFG = 0x00000000U;
        emifREG->CE2CFG = (uint32_t)((uint32_t)0U << 31U)|
                          (uint32_t)((uint32_t)0U << 30U)|
                          (uint32_t)((uint32_t)6U << 26U)| // W_SETUP
                          (uint32_t)((uint32_t)7U << 20U)| // W_STROBE
                          (uint32_t)((uint32_t)1U << 17U)| // W_HOLD
                          (uint32_t)((uint32_t)6U << 13U)| // R_SETUP
                          (uint32_t)((uint32_t)16U << 7U)| // R_STROBE
                          (uint32_t)((uint32_t)1U << 4U)|  // R_HOLD
                          (uint32_t)((uint32_t)3U << 2U)|  // TURN AROUND
                          (uint32_t)((uint32_t)emif_16_bit_port);

        emifREG->AWCC   = (emifREG->AWCC & 0xC0FF0000U)|
                          (uint32_t)((uint32_t)emif_pin_high << 29U)|
                          (uint32_t)((uint32_t)emif_pin_low << 28U)|
                          (uint32_t)((uint32_t)emif_wait_pin0 << 16U)|
                          (uint32_t)((uint32_t)0U);

        emifREG->PMCR   = (emifREG->PMCR & 0xFFFFFF00U)|
                          (uint32_t)((uint32_t)0U << 2U)|
                          (uint32_t)((uint32_t)emif_4_words << 1U)|
                          (uint32_t)((uint32_t)0U);
    /* USER CODE BEGIN (5) */
    /* USER CODE END */
}

Below are the interface timing diagrams and timing sheets for writing to the device we are interfacing with (I can figure out reading after). If you need more information let me know.

Note: I have attached the datasheet instead as the images copied in did not work. Write timing diagram and timings are on pages 66-68

 

3010.67521ds.pdf

2. Another question, the device requires an input line to address memory vs registers which we currently have mapped to EMIF_ADDR[15], is this possible simply by setting the corresponding bit in the address when attempting to set the register or what would be the process otherwise?

Thanks for any information you can provide.

  • Hi David,

    1. Please make your pinmux is configured correctly.
    2. For memory interface, the EMIF address pin EMIF_A[0] always provides the least significant bit of a 32-bit word address. Therefore, when interfacing to a 16-bit asynchronous device, the EMIF_BA[1] pin provide the least-significant bits of the halfword. EMIF_BA[1] should be connected to Memory A[0] pin.
    3. Suggest to try maximum value for SETUP, STROBE, and HOLD fields in CE2FFG register first, make sure your setup work.
  • Deleting this reply as it was bad hardware. Will update with good hardware in a following reply.

    Thanks,

    David Cothran

  • May have a hardware issue, I will let you know when we get it resolved and if we have any more issues!

    I apologize for the inconvenience.

    Thanks,

    David Cothran

  • Hi David,

    Most likely, the problem is caused by the timing. Any special requirements for setup, strobe, and hold for the EMIF device? Can you lower the EMIF clock to 16MHz too?
  • QJ,

    We found out our oscillator was bad for our first chip and replaced it with another. We have verified the oscillator is working and we are seeing much better results! Also is there a way to lower the EMIF clock to 16 MHz? The closest I see are 18MHz,16.364MHz, 15Mhz. Though I believe our oscillator has since resolved many issues. See Below.

    The read seems to be working as far as we can tell (pic below), however we are having some issues on the write.

    Current Register Settings

        emifREG->CE2CFG = (uint32_t)((uint32_t)1U << 31U) | // Strobe Mode Enable
                          (uint32_t)((uint32_t)1U << 30U) | // Extended Wait Enable
                          (uint32_t)((uint32_t)6U << 26U) | // W_SETUP
                          (uint32_t)((uint32_t)8U << 20U)| // W_STROBE
                          (uint32_t)((uint32_t)1U << 17U) | // W_HOLD
                          (uint32_t)((uint32_t)6U << 13U) | // R_SETUP
                          (uint32_t)((uint32_t)17U << 7U) | // R_STROBE
                          (uint32_t)((uint32_t)1U << 4U)  | // R_HOLD
                          (uint32_t)((uint32_t)3U << 2U)  | // TURN AROUND
                          (uint32_t)((uint32_t)emif_16_bit_port);

    Test Code Section

        volatile uint32_t address;
        volatile uint16_t testval;
    
        /***************************** TEST READ ***************************/
        for(address = (uint32_t)STACK_A_ADDR; address < (uint32_t)RT_CMD_STACK_A_PTR; address++) // EDIT NOTE: THIS SHOULD BE address += 2 as it is 16-bit addressable
        {
            testval = *((volatile uint16_t *)address);
        }
    
        /***************************** TEST WRITE ***************************/
        testval = 10;
        for(address = (uint32_t)STACK_A_ADDR; address < (uint32_t)RT_CMD_STACK_A_PTR; address++) // EDIT NOTE: THIS SHOULD BE address += 2 as it is 16-bit addressable
        {
            gioPORTB->DOUT ^= 1 << 4U;  /* FLIP GIO Bit 4 */
            *((volatile uint16_t *)address) = ++testval;
            gioPORTB->DOUT ^= 1 << 4U;  /* FLIP GIO Bit 4 */
        }

    Read Example

    1. EMIF_ADDR[15] does not change even when attempting to OR bits 15 and 16 in the address itself (we attempted 16 because of the BA1 offset). Is this possible to manually operate as a memory/register pin or will we need to use something such as a GIO?

    2. During the write, in normal mode, it will attempt to write 3 addresses during one nCS2 [active low] cycle. During the write, in strobe mode, it will attempt to write 3 addresses (while overwriting a previous "good" write). Resulting in data being written correctly and then overwritten incorrectly. Is this an MPU 'device' issue?

    Picture below are some exampels of Writes in Strobe Mode, when only executing a single write command in code

    Example 2

    Thanks,

    David Cothran

  • QJ,

    Apologies for the chaos of this thread. The chip I was using is 16-bit addressable so the 8 bit addressing was not working for it and would also explain the overwriting of previous data (my bad). Another issue is possibly the emif_addr15/nREG line not moving (so the external chip thinks im only writing to registers).

    I found an MPU example in the halcogen examples for the TMS570LS31x and initialized the MPU in the start of main for JUST region 5 (0x60000000 + 64KB) and that fixed the multiple writes as far as i can tell.

    Now that everything looks relatively good, do you know how I can manually toggle the EMIF_ADDR[15] line? ORing bit 15 or 16 in the address (due to BA1 offset) to 1 or 0 seems to have no effect in the line.

    Thanks,

    David Cothran

  • Hello David,

    The EMIF clock is configurable. EMIF uses VCLK3. In HALCoGen GCM panel, increasing the VCLK3 divider will lower the EMIF clock frequency.

    You are right, to write data to EMIF async memory correctly, the memory has to be configured as device type or strongly-ordered type using MPU.

    TO toggle address[15] line, write data to EMIF memory address:

    0x6000_0000 + 0x8000 *4 = 0x6002_0000
  • QJ,

    This answered all my questions but now I have one more.

    1. Why is it 0x8000 *4 instead of *2? Should it not be left shift 1? Please explain.

    Thanks again for all the help,

    David Cothran

  • A[0] is the least significant bit of a 32-bit word address. BA1 provides the half-word address. DQM signals represent byte enable. This is why I left shift the bit by 17 --> 0x6002_0000
  • Thanks so much!!

    Regards,
    David Cothran