• (转)CortexM3 (NXP LPC1788)之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<j;i++)
     65   pmp[i] = i;
     66 
     67  for (k =0; k  < 1; k++)
     68  {
     69   for(i=0;i<j;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<SDRAM_PERIOD)?0:(uint32_t)((float)Period/SDRAM_PERIOD))+1)
     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上面,那么希望本篇文章能给你些帮助。

  • 相关阅读:
    逻辑学的基本运算
    第一性原理:First principle thinking是什么?
    人类认识的基本技能
    编程的本质:简化+抽象+再现
    区块链
    信号、系统、传递、树
    MVVM
    数据驱动 状态驱动
    事件与状态机 事件驱动编程
    数据一致性举例:登录系统
  • 原文地址:https://www.cnblogs.com/tdyizhen1314/p/2704627.html
Copyright © 2020-2023  润新知