This article wants to demonstrate the basic register setups to be able to access the external system bus (EIM) of the Colibri iMX7.
/// @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; }