ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Понедельник
25 ноября
427357
VVB (25.07.2013 10:30 - 26.07.2013 11:49, просмотров: 6899)
Поделитесь примером инициализации SDRAM для LPC4357 (я использую Keil MCB4357) Третий день мучаю, не хочет работать. Инициализация проходит успешно (анализ по осциллографу), однако, при попытке чтения ячейки по адресу 0x28000004 ядро M4 блокируется и вываливается из отладки. И отладчик (JLink или CMSIS-DAP) более не могут остановить проц, соответственно, нельзя запрограммировать. Я так думаю, что контроллер шины блокирует ядро, ожидая завершения операции с SDRAM. Единственный выход из ситуации -- при сбросе перевести в ISP и снова запустить отладку (программатор). Данные (1 слово) по адресу 0x28000000 считываются, ядро не блокируется. Осциллограф показывает непонятный бред при попытке чтения по адресу 0x28000004. После выполнения команды загрузки из SDRAM имеет место быть команда ACTIVE и затем команда READ (как и положено). Однако, затем имеется опять команда READ (через 5 тактов) и опять команда READ (через 11 тактов от последней READ) и так это READ идут до бесконечности. Обращение по адресу 0x28000000 штатное, одна команда ACTIVE, одна READ. Затем после наступления цикла обновления идёт PRECHARGE, затем AUTOREFRESH. Тактовая процессора 100 МГц. Моя инициализация: /*---------------------------------------------------------------------------- Initialize the system *----------------------------------------------------------------------------*/ void SystemInit (void) { #if (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2) | /* set CP10 Full Access */ (3UL << 11*2) ); /* set CP11 Full Access */ #endif /* Disable SysTick timer */ SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk); /* Set vector table pointer */ SCB->VTOR = ((uint32_t)(&__Vectors)) & 0xFFF00000UL; LPC_CREG->FLASHCFGA = (LPC_CREG->FLASHCFGA & ~(0xF << 12)) | (0x9 << 12); LPC_CGU->BASE_OUT_CLK = 0x0D << 24; /* CLK_SEL = IDIVB */ // LPC_SCU->SFSCLK_1 = 1 | (1 << 5); /* pin function 1 for CLK1 = CLKOUT; enable high-speed mode */ /* Настройка ножки для вывода */ LPC_SCU->SFSP9_0 = 0; LPC_SCU->SFSP9_1 = 0; LPC_SCU->SFSP9_2 = 0; LPC_GPIO_PORT->DIR[4] = 0x00007000; /* Configure PLL0 and PLL1, connect CPU clock to selected clock source */ SetClock(); /* Configure External Memory Controller */ SystemInit_ExtMemCtl(); /* Update SystemCoreClock variable */ SystemCoreClockUpdate(); } Break! /*---------------------------------------------------------------------------- External Memory Controller Definitions *----------------------------------------------------------------------------*/ #define SDRAM_ADDR_BASE 0x28000000 /* SDRAM base address */ /* Write Mode register macro */ #define WR_MODE(x) (*((volatile uint32_t *)(SDRAM_ADDR_BASE | (x)))) /* Pin Settings: Glith filter DIS, Input buffer EN, Fast Slew Rate, No Pullup */ #define EMC_PIN_SET ((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4)) #define EMC_NANOSEC(ns, freq, div) (((uint64_t)(ns) * ((freq)/((div)+1)))/1000000000) #define EMC_CLK_DLY_TIM_2 (0x7777) /* 3.5 ns delay for the EMC clock out */ #define EMC_CLK_DLY_TIM_0 (0x0000) /* No delay for the EMC clock out */ /*---------------------------------------------------------------------------- Initialize external memory controller *----------------------------------------------------------------------------*/ void SystemInit_ExtMemCtl (void) { uint32_t emcdivby2_buf[emcdivby2_szw]; uint32_t div, n; const uint32_t sysclock = GetClockFreq ((LPC_CGU->BASE_M4_CLK >> 24) & 0x1F); /* Select and enable EMC branch clock */ LPC_CCU1->CLK_M4_EMC_CFG = (1 << 2) | (1 << 1) | 1; while (!(LPC_CCU1->CLK_M4_EMC_STAT & 1)); /* Set EMC clock output delay */ if (sysclock < 80000000UL) { LPC_SCU->EMCDELAYCLK = EMC_CLK_DLY_TIM_0; /* No EMC clock out delay */ } else { LPC_SCU->EMCDELAYCLK = EMC_CLK_DLY_TIM_2; /* 3.5 ns EMC clock out delay */ } /* Configure EMC port pins */ LPC_SCU->SFSP1_0 = EMC_PIN_SET | 2; /* P1_0: A5 */ LPC_SCU->SFSP1_1 = EMC_PIN_SET | 2; /* P1_1: A6 */ LPC_SCU->SFSP1_2 = EMC_PIN_SET | 2; /* P1_2: A7 */ LPC_SCU->SFSP1_6 = EMC_PIN_SET | 3; /* P1_6: WE */ LPC_SCU->SFSP1_7 = EMC_PIN_SET | 3; /* P1_7: D0 */ LPC_SCU->SFSP1_8 = EMC_PIN_SET | 3; /* P1_8: D1 */ LPC_SCU->SFSP1_9 = EMC_PIN_SET | 3; /* P1_9: D2 */ LPC_SCU->SFSP1_10 = EMC_PIN_SET | 3; /* P1_10: D3 */ LPC_SCU->SFSP1_11 = EMC_PIN_SET | 3; /* P1_11: D4 */ LPC_SCU->SFSP1_12 = EMC_PIN_SET | 3; /* P1_12: D5 */ LPC_SCU->SFSP1_13 = EMC_PIN_SET | 3; /* P1_13: D6 */ LPC_SCU->SFSP1_14 = EMC_PIN_SET | 3; /* P1_14: D7 */ LPC_SCU->SFSP2_0 = EMC_PIN_SET | 2; /* P2_0: A13 */ LPC_SCU->SFSP2_2 = EMC_PIN_SET | 2; /* P2_2: A11 */ LPC_SCU->SFSP2_6 = EMC_PIN_SET | 2; /* P2_6: A10 */ LPC_SCU->SFSP2_7 = EMC_PIN_SET | 3; /* P2_7: A9 */ LPC_SCU->SFSP2_8 = EMC_PIN_SET | 3; /* P2_8: A8 */ LPC_SCU->SFSP2_9 = EMC_PIN_SET | 3; /* P2_9: A0 */ LPC_SCU->SFSP2_10 = EMC_PIN_SET | 3; /* P2_10: A1 */ LPC_SCU->SFSP2_11 = EMC_PIN_SET | 3; /* P2_11: A2 */ LPC_SCU->SFSP2_12 = EMC_PIN_SET | 3; /* P2_12: A3 */ LPC_SCU->SFSP2_13 = EMC_PIN_SET | 3; /* P2_13: A4 */ LPC_SCU->SFSP5_0 = EMC_PIN_SET | 2; /* P5_0: D12 */ LPC_SCU->SFSP5_1 = EMC_PIN_SET | 2; /* P5_1: D13 */ LPC_SCU->SFSP5_2 = EMC_PIN_SET | 2; /* P5_2: D14 */ LPC_SCU->SFSP5_3 = EMC_PIN_SET | 2; /* P5_3: D15 */ LPC_SCU->SFSP5_4 = EMC_PIN_SET | 2; /* P5_4: D8 */ LPC_SCU->SFSP5_5 = EMC_PIN_SET | 2; /* P5_5: D9 */ LPC_SCU->SFSP5_6 = EMC_PIN_SET | 2; /* P5_6: D10 */ LPC_SCU->SFSP5_7 = EMC_PIN_SET | 2; /* P5_7: D11 */ LPC_SCU->SFSP6_4 = EMC_PIN_SET | 3; /* P6_4: CAS */ LPC_SCU->SFSP6_5 = EMC_PIN_SET | 3; /* P6_5: RAS */ LPC_SCU->SFSP6_8 = EMC_PIN_SET | 1; /* P6_8: A14 */ LPC_SCU->SFSP6_9 = EMC_PIN_SET | 3; /* P6_9: DYCS0 */ LPC_SCU->SFSP6_10 = EMC_PIN_SET | 3; /* P6_10: DQMOUT1 */ LPC_SCU->SFSP6_11 = EMC_PIN_SET | 3; /* P6_11: CKEOUT0 */ LPC_SCU->SFSP6_12 = EMC_PIN_SET | 3; /* P6_12: DQMOUT0 */ LPC_SCU->SFSPD_0 = EMC_PIN_SET | 2; /* PD_0: DQMOUT2 */ LPC_SCU->SFSPD_2 = EMC_PIN_SET | 2; /* PD_2: D16 */ LPC_SCU->SFSPD_3 = EMC_PIN_SET | 2; /* PD_3: D17 */ LPC_SCU->SFSPD_4 = EMC_PIN_SET | 2; /* PD_4: D18 */ LPC_SCU->SFSPD_5 = EMC_PIN_SET | 2; /* PD_5: D19 */ LPC_SCU->SFSPD_6 = EMC_PIN_SET | 2; /* PD_6: D20 */ LPC_SCU->SFSPD_7 = EMC_PIN_SET | 2; /* PD_7: D21 */ LPC_SCU->SFSPD_8 = EMC_PIN_SET | 2; /* PD_8: D22 */ LPC_SCU->SFSPD_9 = EMC_PIN_SET | 2; /* PD_9: D23 */ LPC_SCU->SFSPE_5 = EMC_PIN_SET | 3; /* PE_5: D24 */ LPC_SCU->SFSPE_6 = EMC_PIN_SET | 3; /* PE_6: D25 */ LPC_SCU->SFSPE_7 = EMC_PIN_SET | 3; /* PE_7: D26 */ LPC_SCU->SFSPE_8 = EMC_PIN_SET | 3; /* PE_8: D27 */ LPC_SCU->SFSPE_9 = EMC_PIN_SET | 3; /* PE_9: D28 */ LPC_SCU->SFSPE_10 = EMC_PIN_SET | 3; /* PE_10: D29 */ LPC_SCU->SFSPE_11 = EMC_PIN_SET | 3; /* PE_11: D30 */ LPC_SCU->SFSPE_12 = EMC_PIN_SET | 3; /* PE_12: D31 */ LPC_SCU->SFSPE_13 = EMC_PIN_SET | 3; /* PE_13: DQMOUT3 */ LPC_EMC->CONTROL = 0x00000001; /* EMC Enable */ LPC_EMC->CONFIG = 0x00000000; /* Little-endian, Clock Ratio 1:1 */ div = 0; if (sysclock > 120000000UL) { /* Use EMC clock divider and EMC clock output delay */ div = 1; LPC_CCU1->CLK_M4_EMCDIV_CFG = (1 << 5) | (1 << 2) | (1 << 1) | 1; LPC_CREG->CREG6 |= (1 << 16); // EMC_CLK_DIV divided by 2 } /* Configure EMC clock-out pins */ LPC_SCU->SFSCLK_0 = 1<<6; /* CLK0 */ LPC_SCU->SFSCLK_1 = 1<<6; LPC_SCU->SFSCLK_2 = 1<<6; LPC_SCU->SFSCLK_3 = 1<<6; /* Dynamic memory configuration (chip select 0) */ #if (USE_EXT_DYN_MEM_CS0) /* Set Address mapping: 128Mb(4Mx32), 4 banks, row len = 12, column len = 8 */ LPC_EMC->DYNAMICCONFIG0 = (1 << 14) | /* AM[14] = 1 */ (0 << 12) | /* AM[12] = 0 */ (2 << 9) | /* AM[11:9] = 2 */ (2 << 7) ; /* AM[8:7] = 2 */ LPC_EMC->DYNAMICRASCAS0 = 0x00000303; /* Latency: RAS 3, CAS 3 CCLK cyc.*/ LPC_EMC->DYNAMICREADCONFIG = 0x00000001; /* Command delayed by 1/2 CCLK */ LPC_EMC->DYNAMICRP = 2; //EMC_NANOSEC (18, sysclock, div); // tRP: precharge command period (18ns) LPC_EMC->DYNAMICRAS = 6; //EMC_NANOSEC (42, sysclock, div); // tRAS: active to precharge command period (42ns) LPC_EMC->DYNAMICSREX = 11; //EMC_NANOSEC (70, sysclock, div); // tXSR: self-refresh exit time (70ns) LPC_EMC->DYNAMICAPR = 2; //EMC_NANOSEC (18, sysclock, div); // tAPR: last-data-out to active command time // note: no tAPR value, using tRCD value (18ns) LPC_EMC->DYNAMICDAL = 5; // tDAL: data-in to active command time // for CL=3, tDAL = 5 tCK // for CL=2, tDAL = 4 tCK // for CL=1, tDAL = 3 tCK LPC_EMC->DYNAMICWR = 1;//2; // tWR: write recovery time is (12ns) UNLESS we are // using AUTO PRECHARGE, then it is (tCK+6ns) LPC_EMC->DYNAMICRC = 9;//EMC_NANOSEC (60, sysclock, div); // tRC: ACTIVE-to-ACTIVE command period (60ns) LPC_EMC->DYNAMICRFC = 9;//EMC_NANOSEC (60, sysclock, div); // tRFC: AUTO REFRESH period (60ns) LPC_EMC->DYNAMICXSR = 11;//EMC_NANOSEC (70, sysclock, div); // tXSR: Exit self refresh to ACTIVE command (70ns) LPC_EMC->DYNAMICRRD = 1;//EMC_NANOSEC (12, sysclock, div); // tRRD: active bank A to active bank B command // latency (12ns LPC_EMC->DYNAMICMRD = 1; // tMRD: LOAD MODE REGISTER command to ACTIVE or // REFRESH command time (2tCK) // SDRAM must be powered up and initialized in a predefined manner. Operational // procedures other than those specified may result in undefined operation. After power is // applied to VDD and VDDQ (simultaneously) and the clock is stable (stable clock is // defined as a signal cycling within timing constraints specified for the clock pin), the // SDRAM requires a 100us delay prior to issuing any command other than a COMMAND // INHIBIT or NOP. Starting at some point during this 100us period and continuing at least // through the end of this period, COMMAND INHIBIT or NOP commands must be // applied. // After the 100us delay has been satisfied with at least one COMMAND INHIBIT or NOP // command having been applied, a PRECHARGE command should be applied. All banks // must then be precharged, thereby placing the device in the all banks idle state. // The NO OPERATION (NOP) command is used to perform a NOP to the selected device // (CS# is LOW). This prevents unwanted commands from being registered during idle or // wait states. Operations already in progress are not affected. LPC_EMC->DYNAMICCONTROL = 0x00000183; /* Issue NOP command */ WaitUs(100); // The PRECHARGE command is used to deactivate the open row in a particular bank or // the open row in all banks. The bank(s) will be available for a subsequent row access a // specified time (tRP) after the PRECHARGE command is issued. Input A10 determines // whether one or all banks are to be precharged, and in the case where only one bank is // precharged, inputs BA0 and BA1 select the bank. Otherwise BA0 and BA1 are treated // as "Dont Care." After a bank has been precharged, it is in the idle state and must be // activated prior to any READ or WRITE commands are issued to that bank. // ------------------------------------------------------------------------------------------ // Send command: PRECHARGE-ALL and set the shortest possible refresh period // ------------------------------------------------------------------------------------------ LPC_EMC->DYNAMICCONTROL = 0x00000103; /* Issue PALL command */ LPC_EMC->DYNAMICREFRESH = 0x00000001; // 1 x 16 = 16 CCLKs between SDRAM refresh cycles // wait >128 clks // ------------------------------------------------------------------------------------------ for (n=128; n; n--); // The addressing is generated by the internal refresh controller. This makes the address // bits a "Dont Care" during an AUTO REFRESH command. Regardless of device width, // the 128Mb SDRAM requires 4096 AUTO REFRESH cycles every 64ms (commercial and // industrial) or 16ms (automotive). Providing a distributed AUTO REFRESH command // every 15.625us (commercial and industrial) or 3.906us (automotive) will meet the // refresh requirement and ensure that each row is refreshed. Alternatively, 4096 AUTO // REFRESH commands can be issued in a burst at the minimum cycle rate (tRFC), once // every 64ms (commercial and industrial) or 16ms (automotive). // so... Refresh period (4,096 rows) tREF 64ms // which gives a time of 15.625us per row, or 15625ns // ------------------------------------------------------------------------------------------ // Set correct refresh period // ------------------------------------------------------------------------------------------ LPC_EMC->DYNAMICREFRESH = EMC_NANOSEC(15625, sysclock, div) / 16 + 1; LPC_EMC->DYNAMICCONTROL = 0x00000083; /* Issue MODE command */ // Send the mode command, which tells the SDRAM what the burst length is, the type of burst, the latency, etc., as follows: // Set mode register in SDRAM // A0–A10 define the op-code written to the mode register // Bank select is A13-A14, address is A0-A12, data I/O mask is DQM0-DQM3... // ------------------------------------------------------------------------------------------ // Mode register table for Microns MT48LCxx (MT48LC2M32B2P ON FDI BOARD) // bit 9: Write Burst Mode: Programmed burst length(Innocent, Single Location Access(1) // bit 8~7: Operating Mode: Standard Operation(Innocent is the only thing defined // bit 6~4: CAS latency: 001(1), 010(2), 011(3) // bit 3: Type of Burst: Sequential(Innocent or Interleaved(1) // bit 2~0: Burst length: 000(1), 001(2), 010(4), 011(Cool, 111(Full Page) /* Mode register: Burst Length: 4, Burst Type: Sequential, CAS Latency: 3 */ WR_MODE(((3 << 4) | 2) << 12); LPC_EMC->DYNAMICCONTROL = 0x00000003; /* Issue NORMAL command */ LPC_EMC->DYNAMICCONFIG0 |= (1 << 19); /* Enable buffer */ #endif }