博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(转)Cortex-M3 (NXP LPC1788)之SDRAM操作
阅读量:4624 次
发布时间:2019-06-09

本文共 8949 字,大约阅读时间需要 29 分钟。

网上看到了一些关于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
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 values106   //107   Cnt = 0;108   //109   // Calibrate osc.110   //111   for (i = 0; i < 10; i++) {112     LPC_SC->EMCCAL = (1 << 14);     // Start calibration113     v = LPC_SC->EMCCAL;114     while ((v & (1 << 15)) == 0) {  // Wait for calibration done115       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);  // EMCDLY184  _FindDelay(1);  // FBCLKDLY185 186  _AdjustEMCTiming(i);187 }

 

本人因为SDRAM的问题,折腾了进半个月的时间,移植UCOSIII,YAFFS2,UCGUI , LWIP中间,程序本来是没有问题,因为SDRAM的问题,曾经好几次让我想放弃这个芯片,翻过了不知道多少遍M3的手册,看了不知道多少遍数据手册,不过最后我还是很幸运的调试出来....如果你现在的问题也出在SDRAM上面,那么希望本篇文章能给你些帮助。

转载于:https://www.cnblogs.com/tdyizhen1314/archive/2012/09/26/2704627.html

你可能感兴趣的文章
Centos7 中使用Supervisor守护进程
查看>>
第五周作业
查看>>
awk中关于BEGIN,END的使用问题
查看>>
[Vue warn]: Failed to mount component: template or render function not defined. 错误解决方法
查看>>
禁用root登录以及使用sudo分配权限
查看>>
mysql-The program could not be launched,Error Number 2解决办法
查看>>
字节缓冲流 BufferedOutputStream BufferedInputStream
查看>>
身份证正则表达式
查看>>
JS代码放在head和body中的区别分析
查看>>
C++string,char* 字符数组,int类型之间的转换
查看>>
sql 条件处理
查看>>
C语言 · 动态数组的使用
查看>>
win7提交代码到github
查看>>
flask上下文管理
查看>>
windows 上rails3.2 + ruby1.9环境搭建
查看>>
Eclipse如何修改dynamic web module version
查看>>
关于我学习Python语言后的感悟
查看>>
正太分布
查看>>
硬盘的转速是什么意思,有什么功能?
查看>>
version control
查看>>