Search by Tags

Basic Usage of the External EIM Bus on Colibri iMX7

 

Article updated at 09 Mar 2018
Compare with Revision


This article wants to demonstrate the basic register setups to be able to access the external system bus (EIM) of the Colibri iMX7.

  • The EIM will be setup to operate in multiplexed, asynchronous mode
  • You will need to adjust timing parameters and other configurations, in order to match your requirements.
    Please refer to the iMX7 reference manual for details about the register settings.

/// @file         iMX7_EIM_Demo.c
/// @copyright    Copyright (c) 2017 Toradex AG
/// @brief        Basic demonstration how how to use the EIM bus of the
///               Colibri iMX7. \n
///               The Bus is configured as follows:
///               * Multiplexed Mode
///               * 8 combined Address / Data Signals
///               * use Chip select nCS0 (SODIMM 105)
///
/// @test         Tested on: Colibri iMX7D
///               Windows Embedded Compact 7 (V1.0)
///               Visual Studio 2008
///               Toradex CE Libraries V2.0
 
#include <windows.h>
#include "mapmem.h"
#include "clk_imx7.h"
#include "gpio_imx7.h"
 
 
// WEIM clock root and clock gate registers
#define CCM_BASE_ADDRESS    0x30380000
#define CCM_CCGR22          0x30384160
#define CCM_TARGET_ROOT83   0x3038A980
 
/* WEIM registers */
typedef struct
{
    UINT32 EIM_CS0GCR1;
    UINT32 EIM_CS0GCR2;
    UINT32 EIM_CS0RCR1;
    UINT32 EIM_CS0RCR2;
    UINT32 EIM_CS0WCR1;
    UINT32 EIM_CS0WCR2;
    UINT32 EIM_CS1GCR1;
    UINT32 EIM_CS1GCR2;
    UINT32 EIM_CS1RCR1;
    UINT32 EIM_CS1RCR2;
    UINT32 EIM_CS1WCR1;
    UINT32 EIM_CS1WCR2;
    UINT32 EIM_CS2GCR1;
    UINT32 EIM_CS2GCR2;
    UINT32 EIM_CS2RCR1;
    UINT32 EIM_CS2RCR2;
    UINT32 EIM_CS2WCR1;
    UINT32 EIM_CS2WCR2;
    UINT32 EIM_CS3GCR1;
    UINT32 EIM_CS3GCR2;
    UINT32 EIM_CS3RCR1;
    UINT32 EIM_CS3RCR2;
    UINT32 EIM_CS3WCR1;
    UINT32 EIM_CS3WCR2;
    UINT32 EIM_CS4GCR1;
    UINT32 EIM_CS4GCR2;
    UINT32 EIM_CS4RCR1;
    UINT32 EIM_CS4RCR2;
    UINT32 EIM_CS4WCR1;
    UINT32 EIM_CS4WCR2;
    UINT32 EIM_CS5GCR1;
    UINT32 EIM_CS5GCR2;
    UINT32 EIM_CS5RCR1;
    UINT32 EIM_CS5RCR2;
    UINT32 EIM_CS5WCR1;
    UINT32 EIM_CS5WCR2;
    UINT32 EIM_WCR;
    UINT32 EIM_DCR;
    UINT32 EIM_DSR;
    UINT32 EIM_WIAR;
    UINT32 EIM_EAR;
}tEIM_CSP_WEIM_REGS, *ptEIM_CSP_WEIM_REGS;
 
//-----------------------------------------------------------------------------
// Configure the IOs for the iMX7 EIM bus
/// @param[in] hGpio    handle received from Gpio_Init()
/// @retval     TRUE       Success
/// @retval     FALSE      Failure
BOOL Eim_ConfigureIos(HANDLE hGpio)
{
    int i;
    BOOL fSuccess = TRUE;
 
    const uIo eimIo[] =
    {
        COLIBRI_PIN( 89),   // RW
        COLIBRI_PIN( 91),   // OE
        COLIBRI_PIN(105),   // CS0_B
        COLIBRI_PIN(150),   // LBA_B
        COLIBRI_PIN(111),   // AD0
        COLIBRI_PIN(113),   // AD1
        COLIBRI_PIN(115),   // AD2
        COLIBRI_PIN(117),   // AD3
        COLIBRI_PIN(119),   // AD4
        COLIBRI_PIN(121),   // AD5
        COLIBRI_PIN(123),   // AD6
        COLIBRI_PIN(125)    // AD7
    };
 
    /// The EIM functionality is on Alternate Function 4 for all EIM pins.
    for (i = 0; i < _countof(eimIo); i++)
        fSuccess &= Imx7Gpio_SetConfigString(hGpio, eimIo[i], NULL, L"AltFn=4", StoreVolatile);
 
    return fSuccess;
}
 
//*****************************************************************************
/// Main function
/// @param[in]  argc    number of command line arguments
/// @param[in]  argv    array containing command line arguments
/// @retval     1       Success
/// @retval     0       Failure
int wmain(int argc, _TCHAR* argv[])
{
    BOOL   fSuccess = TRUE;
    HANDLE hMap;
    HANDLE hGpio;
 
    volatile ptEIM_CSP_WEIM_REGS pEimReg;
    volatile DWORD *clkRegs;
    volatile DWORD  tmp;
    volatile BYTE *extBus;
    volatile DWORD *targetAddr;
    int i;
 
    // Enable EIM Clock, OSC_24MHz
    hMap = Map_Init();
    clkRegs  = Map_MapMemory(CCM_BASE_ADDRESS, 0x10000);
    targetAddr =  clkRegs + (CCM_CCGR22 - CCM_BASE_ADDRESS)/4;
    *targetAddr &= ~0xFFFFFFFF;
    targetAddr = clkRegs + (CCM_TARGET_ROOT83 - CCM_BASE_ADDRESS)/4;
    *targetAddr |= 0x10000000;
    targetAddr = clkRegs + (CCM_CCGR22 - CCM_BASE_ADDRESS)/4;
    *targetAddr |= 0x03;
 
    // configure EIM GPIOs
    hGpio = Imx7Gpio_Init(NULL);
    fSuccess &= Eim_ConfigureIos(hGpio);
    fSuccess &= Imx7Gpio_Deinit(hGpio);
 
    // Configure CS0 properties for multiplexed, asynchronous operation
    pEimReg = (ptEIM_CSP_WEIM_REGS)Map_MapMemory(0x30bc0000, 0x1000);
 
    // Some of the settings below are not relevant for multiplexed, asynchronous 
    // operation. For details, refer to the iMX7 Reference Manual...
    pEimReg->EIM_CS0GCR1 = 0x0064a089;      // Bit 31-28    8 words page size (for sync. read/write)
                                            // Bit 27       write allowed
                                            // Bit 26-24    Gap between chip selects = 0 (for async.)
                                            // Bit 23       Address shifted according to port size
                                            // Bit 22-20    CS pulse width >= 6 EIM clocks
                                            // Bit 19       User Mode access allowed
                                            // Bit 18-16    8 bit data port resides on DATA[7:0]
                                            // Bit 15-14    Burst Clock Start 0 delay
                                            // Bit 13-12    Burst Clock divisor = 1
                                            // Bit 10-8     Burst Length = 4
                                            // Bit 7-6      CRE signal disabled
                                            // Bit 5        READ monitors WAIT signal
                                            // Bit 4        WRITE monitors WAIT signal
                                            // Bit 3        Multiplexed mode
                                            // Bit 2        Async. mode for WRITE
                                            // Bit 1        Async. Mode for READ
                                            // Bit 0        CS enabled
 
    pEimReg->EIM_CS0GCR2 = 0x00001002;      // Bit 12       ignore GRANT signal
                                            // Bit  8       DTACK disable
                                            // Bit  1-0     Address Hold time = 2 cycles
 
    // further timings can be set in the following registers:
    //pEimReg->EIM_CS0RCR1 = 0x00002000;
    //pEimReg->EIM_CS0RCR2 = 0x00000000;
    //pEimReg->EIM_CS0WCR1 = 0x00000400;
    //pEimReg->EIM_CS0WCR2 = 0x00000000;
 
 
    // Access memory at CS0 address.
    // The address range for nCS0 is 0x28000000 to 0x28FFFFFF (128MB).
    // However, we map only 64kB here.
    extBus = Map_MapMemory(0x28000000, 0x10000);
 
    // When hitting a breakpoint anywhere below, the debugger will read a large block of data and
    // create a lot of toggling on all EIM pins.
    // 16 x Write
    for (i = 0; i <= 15; i++)
        *(extBus + i) = 0x00;   ///< write
 
    // 16 x Read
    for (i = 0; i <= 15; i++)
        tmp = *(extBus + i);    ///< read
 
    return 1;
}