Cortex-M3 (NXP LPC1788)之SDRAM操作

发布者:TranquilWhisper最新更新时间:2017-12-01 来源: eefocus关键字:Cortex-M3  NXP  SDRAM操作 手机看文章 扫描二维码
随时随地手机看文章

网上看到了一些关于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上面,那么希望本篇文章能给你些帮助。


关键字:Cortex-M3  NXP  SDRAM操作 引用地址:Cortex-M3 (NXP LPC1788)之SDRAM操作

上一篇:stm32退出停止模式出现死机现象分析
下一篇:ARM 汇编中的 "B ." 语句意义.

推荐阅读最新更新时间:2024-03-16 15:47

恩智浦收购OmniPHY以加速发展自动驾驶和车载网络
  全球最大的汽车电子及人工智能物联网芯片公司 恩智浦 半导体(NASDAQ:NXPI)宣布收购汽车以太网子系统技术提供商 OmniPHY 。OmniPHY的专业技术包括汽车以太网,这种技术能够实现 自动驾驶 所需的快速数据传输。通过将OmniPHY的先进高速传输技术与恩智浦在车载网络领域的领先产品组合及丰富经验相结合,恩智浦将在为汽车制造商提供新一代数据传输解决方案方面处于独领先位。   受更高数据容量和速度需求的推动,汽车网络正在经历一场变革,旨在满足对自主驾驶程度日益提高的互联车辆的要求。全新的高级自动驾驶系统将需要千兆级以上的数据传输速度。对于下一代车辆来说,目前的计划需要8个以上摄像头、高清雷达、激光雷达和V2X功能,这
[嵌入式]
高通收购恩智浦遇阻 欧盟已启动反垄断调查
    eeworld电子网消息,据国外媒体报道,移动芯片巨头高通在2016年10月与恩智浦半导体(NXP)达成了收购协议,不过目前高通这一380亿美元的收购已遇到了阻力,欧盟已对这一交易启动反垄断调查。   当地时间周五,欧盟宣布对高通380亿美元收购恩智浦半导体的交易展开反垄断调查,欧盟担心这一交易完成后将导致价格上涨,削弱半导体行业的创新能力。   欧盟表示,经过前期的初步调查,他们已对这一收购交易产生了忧虑,他们担心这一收购将导致合并后的公司有足够的能力去打压基带芯片和近场通信芯片领域的竞争对手。   欧盟的担忧主要是高通可能将基带芯片与近场通信芯片捆绑销售,而高通在基带芯片方面的优势又非常明显,恩智浦在近场通信芯片方面
[半导体设计/制造]
15W无线充电方案,海外内厂商到底哪家强?
2018年,无线充电将引来爆发期,两个点将引爆市场:第一、无线充电体验的大幅度提升;第二无线充电领域,由智能手机向可穿戴设备、智能家居和汽车无线充电领域扩散。在智能手机领域,15W无线充电方案,比较iPhone8 7.5W无线充电,效率提升明显,已经成为多家厂商关注的焦点。笔者汇总两家厂商的产品,大家可以进行对比。 易冲无线 易冲无线的EC4016芯片支持多种无线充电标准,实现全兼容,可以自动识别发射端充电协议,支持无线充电功率最大可以达到15W,转化效率达到75%,实现了无线快充。目前市面上的无线充电产品充电功率过小,充电时间过长,大大影响了用户体验,使得用户使用无线充电的意愿并不强。前不久三星推出的S8,无线快充功率为
[电源管理]
恩智浦:汽车芯片行业将更多整合 并入高通获竞争优势
北京时间11月7日上午消息,恩智浦汽车业务主管预计,随着无人驾驶汽车的快速发展,汽车芯片行业将迎来更多整合。    汽车行业一直在整合,今后还将迫使芯片行业也出现整合。或许从更广阔的角度来看,一切都将接入互联网。 恩智浦汽车业务总经理科特 西沃斯(Kurt Sievers)说。   由于各大企业都希望在智能手机销量增速放缓的情况下夺取更大的市场份额,芯片行业一直在经历快速整合,很多都与联网设备和汽车有关。   与此同时,汽车和卡车制造商也在争相开发无人驾驶汽车,以便应对科技公司对其行业构成的威胁。   恩智浦上周同意高通的380亿美元收购要约,此时距离恩智浦通过收购飞思卡尔成为全球最大汽车芯片制造商还不到一年。   
[汽车电子]
联发科发出申请,美国ITC对NXP等10家企业启动337调查
据中国贸易救济信息网消息显示,7月21日,美国国际贸易委员会(ITC)投票决定对特定集成电路及其下游产品启动337调查。 据悉,6月21日,中国台湾联发科公司(MediaTek Inc. of Taiwan)、联发科美国公司(MediaTek USA Inc. of San Jose, California)向美国ITC提出337立案调查申请,指控10家企业对美出口、在美进口和在美销售的该产品侵犯了其专利权(美国注册专利号8,772,928、7,231,474、10,264,580、10,616,017、10,200,228),请求美国ITC发布有限排除令、禁止令。 这十家企业分别为:荷兰NXP Semiconductor
[半导体设计/制造]
NXP车规级深度学习工具包eIQ Auto将汽车应用性能提高30倍
旨在通过快速集成神经网络,最大化客户软件效率 提供包含软件、转换工具和车规级推断引擎的深度学习工具包 与恩智浦的S32V处理器系列紧密集成,以简化ADAS开发 全球最大的汽车半导体供应商恩智浦半导体NXP Semiconductors N.V.推出汽车车规级深度学习工具包eIQ Auto,扩展了公司eIQ机器学习产品系列。该工具包旨在帮助客户从开发环境快速地转向满足汽车行业严格标准的人工智能应用集成。eIQ Auto能够将基于深度学习的算法应用到视觉、自动驾驶、传感器融合、驾驶员监控和其他不断发展的汽车应用。 eIQ Auto工具包使客户能在PC端/云端/GPU环境下对汽车产品进行开发,并将其神经网络集成到S3
[汽车电子]
大联大世平集团推出基于NXP产品的多个智能手机用智能音频功放解决方案
近日,致力于亚太地区市场的领先半导体元器件分销商---大联大控股宣布,其旗下世平凭借恩智浦(NXP)产品在音响耐用性和EMC性能方面所具有的强大领先优势,推出多个基于NXP芯片的智能音频功放参考方案,力求帮助客户实现手机音质的提升,同时能够节省设计的空间。下面就随半导体小编一起来了解一下相关内容吧。 大联大世平此次推出的智能手机用智能音频功放解决方案包括: 一、基于NXP TFA9888的单声道智能音频方案 二、基于NXP TFA9911的单声道智能音频方案 三、基于NXP TFA9896的立体声智能音频方案 四、基于NXP TFA9890的立体声智能音频方案 一、基于NXP TFA9888的智能手机用单声道智能音频方案
[半导体设计/制造]
恩智浦携手SRS Labs为汽车引入真正的环绕声体验
汽车信息娱乐从此跨入真正数字音频处理时代 中国上海,2011年10月21日 ——全球排名首位的汽车娱乐系统供应商恩智浦半导体NXP Semiconductors N.V. (NASDAQ:NXPI) 今日宣布已与全球领先环绕立体声及音频技术供应商SRS 实验室达成合作协议,将SRS实验室针对汽车环境优化的环绕声技术CS Auto引入到中高端汽车中,为用户在路上提供更佳的汽车娱乐体验。恩智浦公司的DiRaNA2汽车收音机与音频解决方案可支持Circle Surround Automotive™ (简称CS Auto),这意味着未来在汽车中也可以体验到与家庭影院类似的环绕声音效,汽车信息娱乐从此将跨入真正的数字音频处理时代。 随着
[汽车电子]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved