网上看到了一些关于1788 SDRAM的调试代码,基本上都一样,本人在调试1788 SDRAM过程中,遇到了一些大麻烦,本人使用的的SDRAM芯片为MT48LC16M162. 本人遇到的问题如下:
1:1788芯片硬件仿真初期,调试SDRAM寄存器配置错误,导致1788芯片无法进入仿真状态,只能用Flash Magic才能擦除。
2:1788芯片的SDRAM有一个很重要的寄存器,官方驱动为 LPC_SC->EMCDLYCTL 寄存器的设置,就算你和官方所使用芯片一样,只要电路板有差异,这个寄存器的设置将有可能导致SDRAM在使用过程中出现错误。
3:还有对于时序的设置,这一步相对来说就比较简单了。
下面例举出我的示例代码:
说明:
1:至于端口配置本人参考官方NXP网站,如果你的端口有充足情况下面,本人建议你不要修改。
2:本人的CPU主频为108M,不是120M,因为我的电路板的原因,在120M的时候,偶尔会有无法启动SDRAM的情况,所以为了安全本人使用了108M的主频。
1 #define SDRAM_REFRESH 7513
2 #define SDRAM_TRP 24
3 #define SDRAM_TRAS 40
4 #define SDRAM_TAPR 2
5 #define SDRAM_TDAL 2
6 #define SDRAM_TWR 18
7 #define SDRAM_TRC 70
8 #define SDRAM_TRFC 70
9 #define SDRAM_TXSR 78
10 #define SDRAM_TRRD 18
11 #define SDRAM_TMRD 2
12
13
14
15 void EMC_Init(void)
16 {
17 uint8_t i;
18
19
20 CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCEMC, ENABLE);
21 LPC_SC->EMCDLYCTL = (0x10 << 8) | (0 << 16) | (0 << 24) | 4;
22
23 LPC_EMC->Control = 0x00000001;
24 LPC_EMC->Config = 0x00000000;
25
26
27 PINSEL_ConfigPin(2,14,1);
28 PINSEL_ConfigPin(2,15,1);
29 PINSEL_ConfigPin(2,16,1);
30 PINSEL_ConfigPin(2,17,1);
31 PINSEL_ConfigPin(2,18,1);
32 PINSEL_ConfigPin(2,19,1);
33 PINSEL_ConfigPin(2,20,1);
34 PINSEL_ConfigPin(2,21,1);
35 PINSEL_ConfigPin(2,22,1);
36 PINSEL_ConfigPin(2,23,1);
37 PINSEL_ConfigPin(2,24,1);
38 PINSEL_ConfigPin(2,25,1);
39 PINSEL_ConfigPin(2,26,1);
40 PINSEL_ConfigPin(2,27,1);
41 PINSEL_ConfigPin(2,28,1);
42 PINSEL_ConfigPin(2,29,1);
43 PINSEL_ConfigPin(2,30,1);
44 PINSEL_ConfigPin(2,31,1);
45
46 for(i = 0; i < 32; i++)
47 {
48 PINSEL_ConfigPin(3,i,1);
49 PINSEL_ConfigPin(4,i,1);
50 }
51
52 }
53
54
55
56 int Sdram_Debug(void)
57 {
58 INT32U i=0,j,k;
59 volatile INT32U *pmp;
60
61
62 pmp = (volatile INT32U *)BASE_SDRAMADDR;
63 j = SDRAM_SIZE/sizeof(*pmp);
64 for(i=0;i 65 pmp[i] = i; 66 67 for (k =0; k < 1; k++) 68 { 69 for(i=0;i 70 { 71 if(pmp[i] != i) 72 { 73 while(1); 74 return FALSE; 75 } 76 } 77 } 78 return TRUE; 79 } 80 81 82 83 #define P2C(Period) (((Period 84 85 void SDRAMInit(void) 86 { 87 uint32_t i; 88 int dwtemp; 89 uint32_t uClk; 90 float SDRAM_PERIOD; 91 LPC_EMC->DynamicConfig0 = 0x00000680; 92 93 uClk = CLKPWR_GetCLK(CLKPWR_CLKTYPE_EMC); 94 uClk /= 1000000UL; 95 SDRAM_PERIOD = (float)1000/uClk; 96 97 LPC_EMC->DynamicRP = P2C(SDRAM_TRP); 98 LPC_EMC->DynamicRAS = P2C(SDRAM_TRAS); 99 LPC_EMC->DynamicSREX = P2C(SDRAM_TXSR); 100 LPC_EMC->DynamicAPR = SDRAM_TAPR; 101 LPC_EMC->DynamicDAL = SDRAM_TDAL+P2C(SDRAM_TRP); 102 LPC_EMC->DynamicWR = P2C(SDRAM_TWR); 103 LPC_EMC->DynamicRC = P2C(SDRAM_TRC); 104 LPC_EMC->DynamicRFC = P2C(SDRAM_TRFC); 105 LPC_EMC->DynamicXSR = P2C(SDRAM_TXSR); 106 LPC_EMC->DynamicRRD = P2C(SDRAM_TRRD); 107 LPC_EMC->DynamicMRD = SDRAM_TMRD; 108 109 LPC_EMC->DynamicConfig0 = 0x00000680; 110 LPC_EMC->DynamicRasCas0 = 0x00000303; 111 LPC_EMC->DynamicReadConfig = 0x00000001; 112 113 TIM_Waitms(100); 114 LPC_EMC->DynamicControl = 0x00000183; /* Issue NOP command */ 115 116 TIM_Waitms(200); 117 LPC_EMC->DynamicControl = 0x00000103; 118 LPC_EMC->DynamicRefresh = 0x00000002; 119 120 for(i = 0; i < 0x100; i++); 121 122 LPC_EMC->DynamicRefresh = P2C(SDRAM_REFRESH)>>4; 123 124 LPC_EMC->DynamicControl = 0x00000083; /* Issue MODE command */ 125 126 dwtemp = *((volatile int *)(SDRAM_BASE_ADDR | (0x33<<12))); 127 128 LPC_EMC->DynamicControl = 0x00000000; 129 130 LPC_EMC->DynamicConfig0 = 0x00080680; 131 for(i = 0; i < 20000; i++); 132 Sdram_Debug(); 133 } 上面的LPC_SC->EMCDLYCTL 是我自己调试出来的准确的值,所以固定了。当然Segger公司有一个更好的办法计算LPC_SC->EMCDLYCTL,以下为参考Segger公司的函数。 1 static int _TestSDRAM(void) { 2 volatile uint32_t * pWriteLong; 3 volatile uint16_t * pWriteShort; 4 uint32_t Data; 5 uint32_t i; 6 uint32_t j; 7 8 pWriteLong = (uint32_t*)SDRAM_BASE_ADDR; 9 pWriteShort = (uint16_t*)SDRAM_BASE_ADDR; 10 // 11 // Fill 16 bit wise 12 // 13 for (i = 0; i < (SDRAM_SIZE / 0x40000); i++) { 14 for (j = 0; j < 0x100; j++) { 15 *pWriteShort++ = (i + j); 16 *pWriteShort++ = (i + j) + 1; 17 } 18 } 19 // 20 // Verifying 21 // 22 pWriteLong = (uint32_t*)SDRAM_BASE_ADDR; 23 for (i = 0; i < (SDRAM_SIZE / 0x40000); i++) { 24 for (j = 0; j < 0x100; j++) { 25 Data = *pWriteLong++; 26 if (Data != (((((i + j) + 1) & 0xFFFF) << 16) | ((i + j) & 0xFFFF))) { 27 return 1; // Error 28 } 29 } 30 } 31 return 0; // O.K. 32 } 33 34 static void _FindDelay(int DelayType) { 35 uint32_t Delay; 36 uint32_t Min; 37 uint32_t Max; 38 uint32_t v; 39 Delay = 0x00; 40 Min = 0xFF; 41 Max = 0xFF; 42 // 43 // Test for DLY min./max. values 44 // 45 while (Delay < 32) { 46 // 47 // Setup new DLY value to test 48 // 49 if (DelayType == 0) { 50 v = LPC_SC->EMCDLYCTL & ~0x001Ful; 51 LPC_SC->EMCDLYCTL = v | Delay; 52 } else { 53 v = LPC_SC->EMCDLYCTL & ~0x1F00ul; 54 LPC_SC->EMCDLYCTL = v | (Delay << 8); 55 } 56 // 57 // Test configured DLY value and find out min./max. values that will work 58 // 59 if (_TestSDRAM() == 0) { 60 // 61 // Test passed, remember min. DLY value if not done yet 62 // 63 if (Min == 0xFF) { 64 Min = Delay; 65 } 66 } else { 67 // 68 // Test failed, if a min. value has been found before, remember the current value for max. 69 // 70 if (Min != 0xFF) { 71 Max = Delay; 72 } 73 } 74 Delay++; 75 } 76 // 77 // Calc DLY value 78 // 79 if (Max != 0xFF) { // If we found a min. and max. value we use the average of the min. and max. values to get an optimal DQSIN delay 80 Delay = (Min + Max) / 2; 81 } else if (Min != 0xFF) { // If we found only a min. value we use the average of the min. value and the longest DLY value to get an optimal DQSIN delay 82 Delay = (Min + 0x1F) / 2; 83 } else { // No working max. and/or min. values found 84 while (1); // Fatal error 85 } 86 // 87 // Setup DLY value to work with 88 // 89 if (DelayType == 0) { 90 v = LPC_SC->EMCDLYCTL & ~0x001Ful; 91 LPC_SC->EMCDLYCTL = v | Delay; 92 } else { 93 v = LPC_SC->EMCDLYCTL & ~0x1F00ul; 94 LPC_SC->EMCDLYCTL = v | (Delay << 8); 95 } 96 } 97 98 99 static uint32_t _CalibrateOsc(void) { 100 uint32_t Cnt; 101 uint32_t v; 102 uint32_t i; 103 104 // 105 // Init start values 106 // 107 Cnt = 0; 108 // 109 // Calibrate osc. 110 // 111 for (i = 0; i < 10; i++) { 112 LPC_SC->EMCCAL = (1 << 14); // Start calibration 113 v = LPC_SC->EMCCAL; 114 while ((v & (1 << 15)) == 0) { // Wait for calibration done 115 v = LPC_SC->EMCCAL; 116 } 117 Cnt += (v & 0xFF); 118 } 119 return (Cnt / 10); 120 } 121 122 static void _AdjustEMCTiming(uint32_t Delay) { 123 uint32_t v; 124 uint32_t CmdDly; 125 uint32_t FBDelay; 126 uint32_t FBClkDly; 127 128 FBDelay = _CalibrateOsc(); 129 130 v = LPC_SC->EMCDLYCTL; 131 CmdDly = ((v & 0x001Ful) * Delay / FBDelay) & 0x1F; 132 FBClkDly = ((v & 0x1F00ul) * Delay / FBDelay) & 0x1F00; 133 LPC_SC->EMCDLYCTL = (v & ~0x1F1Ful) | FBClkDly | CmdDly; 134 } 135 136 137 void SDRAMInit(void) 138 { 139 uint32_t i; 140 int dwtemp; 141 uint32_t uClk; 142 float SDRAM_PERIOD; 143 LPC_EMC->DynamicConfig0 = 0x00000680; 144 145 uClk = CLKPWR_GetCLK(CLKPWR_CLKTYPE_EMC); 146 uClk /= 1000000UL; 147 SDRAM_PERIOD = (float)1000/uClk; 148 LPC_EMC->DynamicRP = P2C(SDRAM_TRP); 149 LPC_EMC->DynamicRAS = P2C(SDRAM_TRAS); 150 LPC_EMC->DynamicSREX = P2C(SDRAM_TXSR); 151 LPC_EMC->DynamicAPR = SDRAM_TAPR; 152 LPC_EMC->DynamicDAL = SDRAM_TDAL+P2C(SDRAM_TRP); 153 LPC_EMC->DynamicWR = P2C(SDRAM_TWR); 154 LPC_EMC->DynamicRC = P2C(SDRAM_TRC); 155 LPC_EMC->DynamicRFC = P2C(SDRAM_TRFC); 156 LPC_EMC->DynamicXSR = P2C(SDRAM_TXSR); 157 LPC_EMC->DynamicRRD = P2C(SDRAM_TRRD); 158 LPC_EMC->DynamicMRD = SDRAM_TMRD; 159 160 LPC_EMC->DynamicConfig0 = 0x00000680; 161 LPC_EMC->DynamicRasCas0 = 0x00000303; 162 LPC_EMC->DynamicReadConfig = 0x00000001; 163 164 TIM_Waitms(100); 165 LPC_EMC->DynamicControl = 0x00000183; /* Issue NOP command */ 166 167 TIM_Waitms(200); 168 LPC_EMC->DynamicControl = 0x00000103; 169 LPC_EMC->DynamicRefresh = 0x00000002; 170 171 for(i = 0; i < 0x100; i++); 172 173 LPC_EMC->DynamicRefresh = P2C(SDRAM_REFRESH)>>4; 174 175 LPC_EMC->DynamicControl = 0x00000083; /* Issue MODE command */ 176 177 dwtemp = *((volatile int *)(SDRAM_BASE_ADDR | (0x33<<12))); 178 179 LPC_EMC->DynamicControl = 0x00000000; 180 181 LPC_EMC->DynamicConfig0 = 0x00080680; 182 i = _CalibrateOsc(); 183 _FindDelay(0); // EMCDLY 184 _FindDelay(1); // FBCLKDLY 185 186 _AdjustEMCTiming(i); 187 } 本人因为SDRAM的问题,折腾了进半个月的时间,移植UCOSIII,YAFFS2,UCGUI , LWIP中间,程序本来是没有问题,因为SDRAM的问题,曾经好几次让我想放弃这个芯片,翻过了不知道多少遍M3的手册,看了不知道多少遍数据手册,不过最后我还是很幸运的调试出来....如果你现在的问题也出在SDRAM上面,那么希望本篇文章能给你些帮助。
上一篇:stm32退出停止模式出现死机现象分析
下一篇:ARM 汇编中的 "B ." 语句意义.
推荐阅读最新更新时间:2024-03-16 15:47
设计资源 培训 开发板 精华推荐
- 柔灵科技陈涵:将小型、柔性的脑机接口睡眠设备,做到千家万户
- 微灵医疗李骁健:脑机接口技术正在开启意识与AI融合的新纪元
- USB Type-C® 和 USB Power Delivery:专为扩展功率范围和电池供电型系统而设计
- 景昱医疗耿东:脑机接口DBS治疗技术已实现国产替代
- 首都医科大学王长明:针对癫痫的数字疗法已进入使用阶段
- 非常见问题解答第223期:如何在没有软启动方程的情况下测量和确定软启动时序?
- 兆易创新GD25/55全系列车规级SPI NOR Flash荣获ISO 26262 ASIL D功能安全认证证书
- 新型IsoVu™ 隔离电流探头:为电流测量带来全新维度
- 英飞凌推出简化电机控制开发的ModusToolbox™电机套件
- 意法半导体IO-Link执行器电路板为工业监控和设备厂商带来一站式参考设计