/* * Copyright 2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ void Clock_Init(void) { unsigned int CCM_CCGR0; unsigned int CCM_CCGR1; unsigned int CCM_CCGR2; unsigned int CCM_CCGR3; unsigned int CCM_CCGR4; unsigned int CCM_CCGR5; unsigned int CCM_CCGR6; unsigned int CCM_ANALOG_PLL_SYS; unsigned int CCM_ANALOG_PFD_528; unsigned int CCM_CBCDR; CCM_CCGR0 = 0x400FC068; CCM_CCGR1 = 0x400FC06C; CCM_CCGR2 = 0x400FC070; CCM_CCGR3 = 0x400FC074; CCM_CCGR4 = 0x400FC078; CCM_CCGR5 = 0x400FC07C; CCM_CCGR6 = 0x400FC080; CCM_ANALOG_PLL_SYS = 0x400D8030; CCM_ANALOG_PFD_528 = 0x400D8100; CCM_CBCDR = 0x400FC014; /* Enable clocking for all peripherals */ MEM_WriteU32(CCM_CCGR0, 0xFFFFFFFF); MEM_WriteU32(CCM_CCGR1, 0xFFFFFFFF); MEM_WriteU32(CCM_CCGR2, 0xFFFFFFFF); MEM_WriteU32(CCM_CCGR3, 0xFFFFFFFF); MEM_WriteU32(CCM_CCGR4, 0xFFFFFFFF); MEM_WriteU32(CCM_CCGR5, 0xFFFFFFFF); MEM_WriteU32(CCM_CCGR6, 0xFFFFFFFF); /* Configure PLL_SYS: * 24MHz OSC as source; * output enabled; * Fout = Fref * 22 * Fout = 24MHz * 22 = 528MHz */ MEM_WriteU32(CCM_ANALOG_PLL_SYS, 0x00002001); /* Configure PFD_528: * set PFD2_FRAC = 29; * Fout = 528MHz * 18/29 = 327.724MHz */ MEM_WriteU32(CCM_ANALOG_PFD_528, 0x001D0000); /* Configure CCM Bus Clock Dividers: * set SEMC alternative clock as SEMC clock root; * set PLL2 PFD2 as alternative clock for SEMC root clock; * set IPG_PODF divider to 2; * set AHB_PODF divider to 4; * set SEMC_PODF divider to 2; * set peripheral main clock to pre_periph_clk_sel; * set PERIPH_CLK2_PODF divider to 1 */ MEM_WriteU32(CCM_CBCDR, 0x00010D40); JLINK_SYS_Report("Clocks initialized"); } void SDRAM_WaitIpCmdDone(void) { unsigned int SEMC_INTR; unsigned int reg_val; SEMC_INTR = 0x402F003C; do { reg_val = MEM_ReadU32(SEMC_INTR); } while ((reg_val & 0x00000003) == 0); MEM_WriteU32(SEMC_INTR, 0x00000003); // Clear IPCMDERR and IPCMDDONE bits } void SDRAM_IO_Init(void) { /* Configure SDRAM IOMUX */ MEM_WriteU32(0x401F8014, 0x00000000); // EMC_00 MEM_WriteU32(0x401F8018, 0x00000000); // EMC_01 MEM_WriteU32(0x401F801C, 0x00000000); // EMC_02 MEM_WriteU32(0x401F8020, 0x00000000); // EMC_03 MEM_WriteU32(0x401F8024, 0x00000000); // EMC_04 MEM_WriteU32(0x401F8028, 0x00000000); // EMC_05 MEM_WriteU32(0x401F802C, 0x00000000); // EMC_06 MEM_WriteU32(0x401F8030, 0x00000000); // EMC_07 MEM_WriteU32(0x401F8034, 0x00000000); // EMC_08 MEM_WriteU32(0x401F8038, 0x00000000); // EMC_09 MEM_WriteU32(0x401F803C, 0x00000000); // EMC_10 MEM_WriteU32(0x401F8040, 0x00000000); // EMC_11 MEM_WriteU32(0x401F8044, 0x00000000); // EMC_12 MEM_WriteU32(0x401F8048, 0x00000000); // EMC_13 MEM_WriteU32(0x401F804C, 0x00000000); // EMC_14 MEM_WriteU32(0x401F8050, 0x00000000); // EMC_15 MEM_WriteU32(0x401F8054, 0x00000000); // EMC_16 MEM_WriteU32(0x401F8058, 0x00000000); // EMC_17 MEM_WriteU32(0x401F805C, 0x00000000); // EMC_18 MEM_WriteU32(0x401F8060, 0x00000000); // EMC_19 MEM_WriteU32(0x401F8064, 0x00000000); // EMC_20 MEM_WriteU32(0x401F8068, 0x00000000); // EMC_21 MEM_WriteU32(0x401F806C, 0x00000000); // EMC_22 MEM_WriteU32(0x401F8070, 0x00000000); // EMC_23 MEM_WriteU32(0x401F8074, 0x00000000); // EMC_24 MEM_WriteU32(0x401F8078, 0x00000000); // EMC_25 MEM_WriteU32(0x401F807C, 0x00000000); // EMC_26 MEM_WriteU32(0x401F8080, 0x00000000); // EMC_27 MEM_WriteU32(0x401F8084, 0x00000000); // EMC_28 MEM_WriteU32(0x401F8088, 0x00000000); // EMC_29 MEM_WriteU32(0x401F808C, 0x00000000); // EMC_30 MEM_WriteU32(0x401F8090, 0x00000000); // EMC_31 MEM_WriteU32(0x401F8094, 0x00000000); // EMC_32 MEM_WriteU32(0x401F8098, 0x00000000); // EMC_33 MEM_WriteU32(0x401F809C, 0x00000000); // EMC_34 MEM_WriteU32(0x401F80A0, 0x00000000); // EMC_35 MEM_WriteU32(0x401F80A4, 0x00000000); // EMC_36 MEM_WriteU32(0x401F80A8, 0x00000000); // EMC_37 MEM_WriteU32(0x401F80AC, 0x00000000); // EMC_38 MEM_WriteU32(0x401F80B0, 0x00000010); // EMC_39 /* Configure SDRAM PAD. Drive strength = 0x7 * to increase drive strength, otherwise data7 * bit may fail. */ MEM_WriteU32(0x401F8204, 0x000110F9); // EMC_00 MEM_WriteU32(0x401F8208, 0x000110F9); // EMC_01 MEM_WriteU32(0x401F820C, 0x000110F9); // EMC_02 MEM_WriteU32(0x401F8210, 0x000110F9); // EMC_03 MEM_WriteU32(0x401F8214, 0x000110F9); // EMC_04 MEM_WriteU32(0x401F8218, 0x000110F9); // EMC_05 MEM_WriteU32(0x401F821C, 0x000110F9); // EMC_06 MEM_WriteU32(0x401F8220, 0x000110F9); // EMC_07 MEM_WriteU32(0x401F8224, 0x000110F9); // EMC_08 MEM_WriteU32(0x401F8228, 0x000110F9); // EMC_09 MEM_WriteU32(0x401F822C, 0x000110F9); // EMC_10 MEM_WriteU32(0x401F8230, 0x000110F9); // EMC_11 MEM_WriteU32(0x401F8234, 0x000110F9); // EMC_12 MEM_WriteU32(0x401F8238, 0x000110F9); // EMC_13 MEM_WriteU32(0x401F823C, 0x000110F9); // EMC_14 MEM_WriteU32(0x401F8240, 0x000110F9); // EMC_15 MEM_WriteU32(0x401F8244, 0x000110F9); // EMC_16 MEM_WriteU32(0x401F8248, 0x000110F9); // EMC_17 MEM_WriteU32(0x401F824C, 0x000110F9); // EMC_18 MEM_WriteU32(0x401F8250, 0x000110F9); // EMC_19 MEM_WriteU32(0x401F8254, 0x000110F9); // EMC_20 MEM_WriteU32(0x401F8258, 0x000110F9); // EMC_21 MEM_WriteU32(0x401F825C, 0x000110F9); // EMC_22 MEM_WriteU32(0x401F8260, 0x000110F9); // EMC_23 MEM_WriteU32(0x401F8264, 0x000110F9); // EMC_24 MEM_WriteU32(0x401F8268, 0x000110F9); // EMC_25 MEM_WriteU32(0x401F826C, 0x000110F9); // EMC_26 MEM_WriteU32(0x401F8270, 0x000110F9); // EMC_27 MEM_WriteU32(0x401F8274, 0x000110F9); // EMC_28 MEM_WriteU32(0x401F8278, 0x000110F9); // EMC_29 MEM_WriteU32(0x401F827C, 0x000110F9); // EMC_30 MEM_WriteU32(0x401F8280, 0x000110F9); // EMC_31 MEM_WriteU32(0x401F8284, 0x000110F9); // EMC_32 MEM_WriteU32(0x401F8288, 0x000110F9); // EMC_33 MEM_WriteU32(0x401F828C, 0x000110F9); // EMC_34 MEM_WriteU32(0x401F8290, 0x000110F9); // EMC_35 MEM_WriteU32(0x401F8294, 0x000110F9); // EMC_36 MEM_WriteU32(0x401F8298, 0x000110F9); // EMC_37 MEM_WriteU32(0x401F829C, 0x000110F9); // EMC_38 MEM_WriteU32(0x401F82A0, 0x000110F9); // EMC_39 } void SDRAM_SEMC_Init(void) { unsigned int SEMC_MCR; unsigned int SEMC_BMCR0; unsigned int SEMC_BMCR1; unsigned int SEMC_BR0; unsigned int SEMC_SDRAMCR0; unsigned int SEMC_SDRAMCR1; unsigned int SEMC_SDRAMCR2; unsigned int SEMC_SDRAMCR3; unsigned int SEMC_IPCR0; unsigned int SEMC_IPCR1; unsigned int SEMC_IPCR2; unsigned int SEMC_IPCMD; unsigned int SEMC_IPTXDAT; unsigned int SEMC_IPCMDMAGICKEY; unsigned int SEMC_IPCMDMODESET; unsigned int SEMC_IPCMDAUTOREFRESH; unsigned int SEMC_IPCMDPRECHARGEALL; unsigned int sdram_address; unsigned int reg_val; SEMC_MCR = 0x402F0000; SEMC_BMCR0 = 0x402F0008; SEMC_BMCR1 = 0x402F000C; SEMC_BR0 = 0x402F0010; SEMC_SDRAMCR0 = 0x402F0040; SEMC_SDRAMCR1 = 0x402F0044; SEMC_SDRAMCR2 = 0x402F0048; SEMC_SDRAMCR3 = 0x402F004C; SEMC_IPCR0 = 0x402F0090; SEMC_IPCR1 = 0x402F0094; SEMC_IPCR2 = 0x402F0098; SEMC_IPCMD = 0x402F009C; SEMC_IPTXDAT = 0x402F00A0; /* SDRAM address in MCU memory map */ sdram_address = 0x80000000; /* IP commands codes and magic key */ SEMC_IPCMDMAGICKEY = 0xA55A0000; SEMC_IPCMDMODESET = 0x0000000A; SEMC_IPCMDAUTOREFRESH = 0x0000000C; SEMC_IPCMDPRECHARGEALL = 0x0000000F; /* Disable SEMC module */ reg_val = MEM_ReadU32(SEMC_MCR); reg_val |= 0x00000002; MEM_WriteU32(SEMC_MCR, reg_val); /* Configure queues for AXI bus as suggested in https://community.nxp.com/t5/i-MX-RT/i-MXRT1060-SEMC-SDRAM-Data-Corruption/m-p/11696908: * Queue A: * WQOS = 1; * WAGE = 8; * WSH = 0; * WRWS = 0 */ MEM_WriteU32(SEMC_BMCR0, 0x00000081); /* Queue B: * WQOS = 1; * WAGE = 8; * WPH = 0; * WRWS = 0; * WBR = 0 */ MEM_WriteU32(SEMC_BMCR1, 0x00000081); /* Configure MCR: * set bus timeout cycles to 0x10; * set DQS mode to loopback from DQS pad for more accurate timings; * enable SEMC module. */ MEM_WriteU32(SEMC_MCR, 0x10000004); /* Configure BR0: * set SDRAM address; * set memory size to 16MB; * mark config as valid. */ MEM_WriteU32(SEMC_BR0, (sdram_address | 0x00000019)); /* Configure SDRAMCR0: * set port size to 16 bits; * set burst length to 1 (see IMXRT1050CE document, ERR050577, p.36); * set column address bit number to 9; * set CAS latency to 3 cycles. */ MEM_WriteU32(SEMC_SDRAMCR0, 0x00000F01); /* Configure SDRAMCR1-3: SDRAM timings. The values * were obtained by feeding SEMC_ConfigureSDRAM() with * proper data from Winbond W987D6HBGX6I datasheet. */ MEM_WriteU32(SEMC_SDRAMCR1, 0x00665222); MEM_WriteU32(SEMC_SDRAMCR2, 0x000A0C12); MEM_WriteU32(SEMC_SDRAMCR3, 0x10100A00); // Disable SDRAM self-refresh /* Prepare to send IP commands */ MEM_WriteU32(SEMC_IPCR0, sdram_address); // Set SDRAM address MEM_WriteU32(SEMC_IPCR1, 0x00000002); // Set 2-byte data size MEM_WriteU32(SEMC_IPCR2, 0x00000000); // Unmask all IPTXDAT command bytes /* Standard SDRAM init procedure - PRECHARGE followed by AUTO REFRESH twice */ MEM_WriteU32(SEMC_IPCMD, (SEMC_IPCMDMAGICKEY | SEMC_IPCMDPRECHARGEALL)); SDRAM_WaitIpCmdDone(); MEM_WriteU32(SEMC_IPCMD, (SEMC_IPCMDMAGICKEY | SEMC_IPCMDAUTOREFRESH)); SDRAM_WaitIpCmdDone(); MEM_WriteU32(SEMC_IPCMD, (SEMC_IPCMDMAGICKEY | SEMC_IPCMDAUTOREFRESH)); SDRAM_WaitIpCmdDone(); /* Set SDRAM mode: * set CAS latency to 3 cycles; * set burst length to 1. */ MEM_WriteU32(SEMC_IPTXDAT, 0x00000030); MEM_WriteU32(SEMC_IPCMD, (SEMC_IPCMDMAGICKEY | SEMC_IPCMDMODESET)); SDRAM_WaitIpCmdDone(); /* Re-enable SDRAM self-refresh */ reg_val = MEM_ReadU32(SEMC_SDRAMCR3); reg_val |= 0x00000001; MEM_WriteU32(SEMC_SDRAMCR3, reg_val); } void SDRAM_Init(void) { SDRAM_IO_Init(); SDRAM_SEMC_Init(); JLINK_SYS_Report("SDRAM initialized"); } void INTRAM_Init(void) { unsigned int IOMUXC_GPR_GPR14; unsigned int IOMUXC_GPR_GPR16; unsigned int IOMUXC_GPR_GPR17; unsigned int reg_val; IOMUXC_GPR_GPR14 = 0x400AC038; IOMUXC_GPR_GPR16 = 0x400AC040; IOMUXC_GPR_GPR17 = 0x400AC044; /* 448 KBytes of DTCM */ MEM_WriteU32(IOMUXC_GPR_GPR17, 0x5AAAAAAA); /* Turn off ITCM */ reg_val = MEM_ReadU32(IOMUXC_GPR_GPR16); reg_val &= ~0x00000001; MEM_WriteU32(IOMUXC_GPR_GPR16, reg_val); /* Configure DTCM/ITCM size */ reg_val = MEM_ReadU32(IOMUXC_GPR_GPR14); reg_val &= ~0x00FF0000; // Mask ITCM/DTCM size bits reg_val |= 0x00A00000; // Set DTCM size to 512KBytes MEM_WriteU32(IOMUXC_GPR_GPR14, reg_val); JLINK_SYS_Report("INTRAM initialized"); } void WDOG_Disable(void) { unsigned int MUX_CTL_PAD_GPIO_B1_13; MUX_CTL_PAD_GPIO_B1_13 = 0x401F81B0; /* Change pin mux from WDOG_B to GPIO to prevent resetting */ MEM_WriteU32(MUX_CTL_PAD_GPIO_B1_13, 0x00000005); JLINK_SYS_Report("Watchdog disabled"); } void SNVS_SSM_Init(void) { unsigned int SNVS_HPCOMR; unsigned int SNVS_HPCOMR_SW_SV_MASK; unsigned int reg_val; SNVS_HPCOMR = 0x400D4004; SNVS_HPCOMR_SW_SV_MASK = (1 << 8); /* Force enter non-secure state by setting software security violation bit */ reg_val = MEM_ReadU32(SNVS_HPCOMR); reg_val |= SNVS_HPCOMR_SW_SV_MASK; MEM_WriteU32(SNVS_HPCOMR, reg_val); JLINK_SYS_Report("SSM initialized"); } /* SetupTarget */ int AfterResetTarget(void) { WDOG_Disable(); Clock_Init(); SDRAM_Init(); INTRAM_Init(); SNVS_SSM_Init(); }