完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
嗨,我使用的PIC32 DA启动套件与PIC32 MZ2064 DAA28 8 MPU与128MB的外部DDR2内存。我在Hyg文件夹中查看ApvsExtRealDrWrdErdRead的DDR2项目,并编写了一些代码来初始化DDR内存。基本上,我删除它并用实际代码替换所有的PLIB函数,即PLIBY-DEVCONIONSythLoCK(DeViNeNIDID0)成为SysKEY=0x33 33 33。代码工作,除了一件事,它只会写入内存的32兆字节。我有一个测试例程,它编写值,然后读取它们。如果我试图写超过第一个32 MB,它会停止处理器。如果将测试限制为32 MB,它将成功。这个例子很好,除了我没有使用PLIB之外,我逐字地复制了它。我有一个{ PrimaMaMatg配置文件ExtDRStsix= DDRSIEZ1212MB来配置它为128MB,除此之外,我能看到的所有内容都与示例相同。请参阅内存测试部分中的代码底部的注释。有人知道这件事吗?谢谢,托尼。
以上来自于百度翻译 以下为原文 Hi, I'm using the PIC32 DA Starter Kit with the PIC32MZ2064DAA288 MPU with 128MB of external DDR2 memory. I looked at the appsexamplesperipheralddrwrite_read_ddr2 project in the HARMony folder as an example and wrote some code to initialize the DDR memory. Basically, I de-bloated it and replaced all the plib functions with actual code, i.e. PLIB_DEVCON_SystemLock(DEVCON_ID_0) became SYSKEY = 0x33333333. The code works, except for one thing - it'll only write to 32MB of the memory. I have a test routine that writes values, then read them back. If I try to write beyond the first 32MB, it halts the processor. If I limit the test to 32MB, it will succeed. The example works fine and I copied it verbatim except I didn't use plib. I have the #pragma config EXTDDRSIZE = DDR_SIZE_128MB to configure it for 128MB and everything else that I can see is the same as the example, except de-crapified. See the note towards the bottom of the code in the memory test section. Would anyone have a clue about this? Thanks in advance. Tony void DDR_Clock_Init(void) { /* Set up the Memory PLL (MPLL) */ asm volatile("di"); // Assembler interrupts disable. SYSKEY = 0x00000000; SYSKEY = 0xAA996655; // unlocking sequence. SYSKEY = 0x556699AA; CFGMPLLbits.MPLLVREGDIS = 0; // MPLL voltage regulator is enabled while (!CFGMPLLbits.MPLLVREGRDY); // wait until MPLL voltage regulator is ready for use CFGMPLLbits.INTVREFCON = 0; // use the external DDRVref circuit /* Memory PLL frequency = Posc / MPLLIDIV x MPLLMULT / MPLLODIV1 / MPLLODIV2 * Posc should be 24MHz */ CFGMPLLbits.MPLLIDIV = 3; // MPLL input clock is divided by 3 CFGMPLLbits.MPLLMULT = 50; // multiply by 50 CFGMPLLbits.MPLLODIV1 = 2; // divide by 2 CFGMPLLbits.MPLLODIV2 = 1; // divide by 1 CFGMPLLbits.MPLLDIS = 0; // enable the MPLL while (!CFGMPLLbits.MPLLRDY); // wait until MPLL clock is stable and is ready for use SYSKEY = 0x33333333; // locking sequence. asm volatile("ei"); // Assembler interrupts enable. } static void DDR_PMD_Init(void) { /* Power to DDR2 memory */ asm volatile("di"); // Assembler interrupts disable. SYSKEY = 0x00000000; SYSKEY = 0xAA996655; // unlocking sequence. SYSKEY = 0x556699AA; CFGCONbits.PMDLOCK = 0; // unlock Peripheral Module Disable (PMD) PMD7bits.DDR2CMD = 0; // enable the DDR2 module by setting the disable to 0 //CFGCONbits.PMDLOCK = 1; // lock Peripheral Module Disable (PMD) *** I guess it's good practice to lock it again, but Microchip's code doesn't... SYSKEY = 0x33333333; // locking sequence. asm volatile("ei"); // Assembler interrupts enable. } static void DDR_PHY_Init(void) { /* Physical Interface (PHY) initialization */ DDRPHYPADCONbits.ODTSEL = 1; // set On-Die Termination (ODT) to 150? - 0 = 75? DDRPHYPADCONbits.ODTEN = 1; // enable ODT DDRPHYPADCONbits.DATDRVSEL = 0; // set Data pads Drive Strength to 60% DDRPHYPADCONbits.ADDCDRVSEL = 0; // set Address and Control Pads Drive Strength to 60% DDRPHYPADCONbits.ODTPUCAL = 3; // On-Die Termination Pull-up impedance DDRPHYPADCONbits.ODTPDCAL = 2; // On-Die Termination Pull-down impedance DDRPHYPADCONbits.DRVSTRNFET = 14; // NFET Drive Strength DDRPHYPADCONbits.DRVSTRPFET = 14; // PFET Drive Strength DDRPHYPADCONbits.EOENCLKCYC = 0; // drive pad output is not enabled for an extra clock cycle after a write burst DDRPHYPADCONbits.NOEXTDLL = 1; // use internal digital DLL DDRPHYPADCONbits.RCVREN = 1; // pad receivers on bidirectional I/Os are turned on DDRPHYPADCONbits.PREAMBDLY = 2; // set Preamble Delay for writes to 1 cycle DDRPHYPADCONbits.HALFRATE = 1; // controller clock is running at half rate with respect to PHY DDRPHYPADCONbits.WRCMDDLY = 1; // set write command delay - write latency (WL) is an even number DDRPHYDLLRbits.RECALIBCNT = 16; // determines the period of recalibration of the digital DLL in units of (256 * PHY clock cycles) DDRPHYDLLRbits.DISRECALIB = 0; // recalibrate the digital DLL in accordance with the value of the RECALIBCNT DDRPHYDLLRbits.DLYSTVAL = 3; // the start value of the digital DLL master delay line - recommended value is 3 DDRSCLCFG0bits.BURST8 = 1; // DRAM is in Burst 8 mode while running a SCL test - this bit should always be set for devices operating in half-rate mode DDRSCLCFG0bits.DDR2 = 1; // DDR memory is connected DDRSCLCFG0bits.RCASLAT = 5; // DRAM read CAS latency in clock cycles DDRSCLCFG1bits.WCASLAT = 4; // DRAM write CAS latency in clock cycles DDRSCLCFG0bits.ODTCSW = 1; // ODT is turned on to the DRAM on CS0 during writes performed by the SCL DDRSCLCFG1bits.DBLREFDLY = 0; // the PHY will delay an SCL operation following an acknowledge by one interval DDRSCLLATbits.DDRCLKDLY = 4; // DDR Clock Delay bits DDRSCLLATbits.CAPCLKDLY = 3; // Capture Clock Delay bits } static void DDR_Init(void) { unsigned int tmp; unsigned int ba_field, ma_field; unsigned int w2rdly, w2rcsdly; /* Target Arbitration * TSEL selectes the target and must be set before a parameter is programmed. The value is set to the target number (0-4) multiplied by the field size of the parameter * MINLIMIT (size = 5) minimum number of DDR bursts (two cycles per burst) that a target must have uninterrupted access to without interference from another target * RQPER (size = 8) number of clocks (x4) until target's requests are treated with high priority if minimum number of DDR bursts are not met * MINCMD (size = 8) minimum number of DDR bursts to service target with */ /* Target 0 */ DDRTSELbits.TSEL = 0; // target x 5 DDRMINLIMbits.MINLIMIT = 0x1f; DDRTSELbits.TSEL = 0; // target x 8 DDRRQPERbits.RQPER = 0xff; DDRTSELbits.TSEL = 0; // target x 8 DDRMINCMDbits.MINCMD = 4; /* Target 1 */ DDRTSELbits.TSEL = 5; // target x 5 DDRMINLIMbits.MINLIMIT = 0x1f; DDRTSELbits.TSEL = 8; // target x 8 DDRRQPERbits.RQPER = 0xff; DDRTSELbits.TSEL = 8; // target x 8 DDRMINCMDbits.MINCMD = 0x10; /* Target 2 */ DDRTSELbits.TSEL = 10; // target x 5 DDRMINLIMbits.MINLIMIT = 0x1f; DDRTSELbits.TSEL = 16; // target x 8 DDRRQPERbits.RQPER = 0xff; DDRTSELbits.TSEL = 16; // target x 8 DDRMINCMDbits.MINCMD = 0x10; /* Target 3 */ DDRTSELbits.TSEL = 15; // target x 5 DDRMINLIMbits.MINLIMIT = 4; DDRTSELbits.TSEL = 24; // target x 8 DDRRQPERbits.RQPER = 0xff; DDRTSELbits.TSEL = 24; // target x 8 DDRMINCMDbits.MINCMD = 4; /* Target 4 */ DDRTSELbits.TSEL = 20; // target x 5 DDRMINLIMbits.MINLIMIT = 4; DDRTSELbits.TSEL = 32; // target x 8 DDRRQPERbits.RQPER = 0xff; DDRTSELbits.TSEL = 32; // target x 8 DDRMINCMDbits.MINCMD = 4; /* Addressing * Addressing is set up by Chip Selects, columns, rows and banks. These four fields can be organized in any sequence. * Depending on the selected sequence, they need to be shifted so as to be contiguous without colliding. */ DDRMEMCFG0bits.RWADDR = 13; // row address is offset by 13 DDRMEMCFG1bits.RWADDRMSK = 0x1fff; DDRMEMCFG0bits.CLHADDR = 0; // column address high is not offset because it is not used DDRMEMCFG3bits.CLADDRLMSK = 0x3ff; DDRMEMCFG2bits.CLADDRHMSK = 0; // column address low is not offset DDRMEMCFG0bits.BNKADDR = 10; // bank address offset by 10 DDRMEMCFG4bits.BNKADDRMSK = 7; DDRMEMCFG0bits.CSADDR = 0; DDRMEMCFG4bits.CSADDRMSK = 0; /* Table 55-3: SDRAM Timing Parameters * Note: All fractional results are rounded up to the nearest number of clocks. * Parameter Description Value Units * tRFC Auto-refresh Cycle Time 127500 nS * tWR Write Recovery Time nS * tRP Precharge-to-Active Command Delay Time nS * tRCD Active-to-Read/Write Command Delay Time nS * tRRD Row-to-Row (RAS to RAS) Command Delay Time nS * tWTR Write-to-Read Command Delay Time nS * tRTP Read-to-Precharge Command Delay Time nS * tDLLK DLL Lock Delay Time nClk * tRAS Active-to-Precharge Minimum Command Delay Time nS * tRC Row Cycle Time nS * tFAW Four Bank Activation Window nS * tMRD Mode Register Set Command Cycle Delay nClk * tXP Power-Down Exit Delay nClk * tCKE Power-Down Minimum Delay nClk * tCKESR Self-Refresh Minimum Delay nClk * RL/rLat CAS Latency nClk * tRFI Average Periodic Refresh Interval 7800000 nS * WL/wLat Write Latency nClk * BL/bLen Burst Length (in cycles) 2 nClk * * Table 55-4: DRAM Controller Timing * Delay Configuration Register Bits Description Formula Units * REFDLY (DDRREFCFG<23:16>) Minimum Refresh-to-Refresh Delay tRFC/CTL_CLK_PER - 1 nClk * W2PCHRGDLY<3:0> (DDRDLYCFG2<15:12>) Write Recovery Time (tWR/CTL_CLK_PER) + wLat + bLen nClk * W2PCHRGDLY<4> (DDRDLYCFG1<26>) * PCHRGALLDLY (DDRDLYCFG2<3:0>) Precharge-to-Active Command Delay Time tRP/CTL_CLK_PER nClk * PCHRG2RASDLY (DDRDLYCFG2<27:24>) Precharge-to-Active Command Delay Time (tRP/CTL_CLK_PER) - 1 nClk * RAS2CASDLY (DDRDLYCFG2<23:20>) Active-to-Read/Write Command Delay Time (tRCD/CTL_CLK_PER) - 1 nClk * RAS2RASDLY (DDRDLYCFG2<19:16>) Row-to-Row (RAS to RAS) Command Delay Time ((tRRD/CTL_CLK_PER) ? 1) nClk * W2RDLY<3:0> (DDRDLYCFG0<3:0>) Write-to-Read Command Delay Time (tWTR/CTL_CLK_PER) + wLat + bLen nClk * W2RDLY<4> (DDRDLYCFG1<27>) * W2RCSDLY<3:0> (DDRDLYCFG0<7:4>) Write-to-Read Chip Select Command Delay Time (W2RDLY - 1) or 3, whichever is greater nClk * W2RCSDLY<4> (DDRDLYCFG1<28>) * R2PCHRGDLY (DDRDLYCFG2<11:8>) Read-to-Precharge Command Delay Time (tRTP/CTL_CLK_PER) + bLen - 2 nClk * SLFREFEXDLY<7:0> (DDRDLYCFG1<15:8>) DLL Lock Delay Time tDLLK/2 - 2 nClk * SLFREFEXDLY<8> (DDRDLYCFG1<30>) * RAS2PCHRGDLY (DDRDLYCFG3<3:0>) Active-to-Precharge Minimum Command Delay Time (tRAS/CTL_CLK_PER) - 1 nClk * RAS2RASSBNKDLY (DDRDLYCFG3<13:8>) Row Cycle Time (tRC/CTL_CLK_PER) - 1 nClk * FAWTDLY (DDRDLYCFG3<21:16>) Four Bank Activation Window (tFAW/CTL_CLK_PER) - 1 nClk * DDRCMD2x<19:11> Mode Register Set Command Cycle Delay tMRD * CTL_CLK_PER nClk * PWRDNEXDLY (DDRDLYCFG1<25:20>) Power-Down Exit Delay tXP - 1 or tCKE - 1, whichever is greater nClk * SLFREFMINDLY (DDRDLYCFG1<7:0>) Self-Refresh Minimum Delay tCKE - 1 nClk * PWRDNMINDLY (DDRDLYCFG1<19:16>) Power-Down Minimum Delay (tCKE/CTL_CLK_PER) - 1 nClk * RMWDLY (DDRDLYCFG0<31:28>) Read-Modify-Write Delay rLat ? wLat + 3 nClk * REFCNT (DDRREFCFG<15:0>) Average Refresh Count (tRFI/CTL_CLK_PER) - 2 nClk * R2WDLY (DDRDLYCFG0<27:24>) Read-to-Write Delay bLen + 2 nClk * W2WCSDLY<3:0> (DDRDLYCFG0<23:20>) Write-to-Write Chip Select Delay bLen - 1 nClk * W2WDLY (DDRDLYCFG0<19:16>) Write-to-Write Delay bLen - 1 nClk * R2RCSDLY (DDRDLYCFG0<15:12>) Read-to-Read Chip Select Delay bLen nClk * R2RDLY (DDRDLYCFG0<11:8>) Read-to-Read Delay bLen - 1 nClk * RBENDDLY (DDRDLYCFG3<31:28>) Read Burst End Delay rLat + 3 nClk * NXTDATRQDLY (DDRXFERCFG<3:0) Next Data Request Delay wLat - 2 nClk * NXTDATAVDLY<3:0> (DDRXFERCFG<7:4>) Next Data Available Delay rLat + 4 nClk * NXTDATAVDLY<4> (DDRDLYCFG1<28>) * RDATENDLY<3:0> (DDRXFERCFG<19:16>) Read Data Enable Delay rLat - 2 nClk * Legend: CTL_CLK_PER = Controller Clock Period (DRAM clock period * 2); nClk = Number of Clocks * Note: All fractional results are rounded up to the nearest number of clocks. */ /* Refresh */ DDRREFCFGbits.REFCNT = (tRFI + CTL_CLK_PER - 1) / CTL_CLK_PER - 2; // Table 55-4 says (tRFI/CTRL_CLK_PER) - 2 DDRREFCFGbits.REFDLY = (tRFC + CTL_CLK_PER - 1) / CTL_CLK_PER - 2; // Table 55-4 says tRFC/CTRL_CLK_PER - 1 DDRREFCFGbits.MAXREFS = 7; // maximum number of refreshes that may be pending DDRPWRCFGbits.ASLFREFEN = 0; // do not allow automatic entry into Self-Refresh mode /* Power */ DDRPWRCFGbits.APWRDNEN = 0; // do not allow automatic entry into Power-Down mode DDRMEMCFG0bits.APCHRGEN = 0; // do not issue an auto-precharge command to accessed bank(s) after every user command DDRPWRCFGbits.PCHRGPWRDN = 0; // do not allow automatic entry into Precharge Power-Down mode /* Timing */ // read-to-write delay set DDRDLYCFG0bits.R2WDLY = bLen + 2u; // minimum number of clocks required between a Read command and Write command DDRDLYCFG0bits.RMWDLY = rLat - wLat + 3u; // minimum number of clocks required between the Read and Write command issued for a read-modify-write operation // write-to-read delay set w2rdly = round_up(tWTR, CTL_CLK_PER) + wLat + bLen; // fraction is rounded up DDRDLYCFG0bits.W2RDLY = w2rdly & 0x0fu; // minimum number of clocks required between a Write command and a Read command to the same Chip Select DDRDLYCFG1bits.W2RDLY4 = ((w2rdly & 0x10u) != 0) ? 1 : 0; // bit 4 of W2RDLY (W2RDLY is bits 0-3) w2rcsdly = ((w2rdly - 1u) > 3u) ? (w2rdly - 1u) : 3u; // (W2RDLY - 1) or 3, whichever is greater DDRDLYCFG0bits.W2RCSDLY = w2rcsdly & 0x0fu; // minimum number of clocks required between a Write command and a Read command to different Chip Selects DDRDLYCFG1bits.W2RCSDLY4 = ((w2rcsdly & 0x10u) != 0) ? 1 : 0; // bit 4 of W2RCSDLY (W2RCSDLY is bits 0-3) // read-read delay set DDRDLYCFG0bits.R2RDLY = bLen - 1u; // number of clocks required between two Read commands to the same Chip Select DDRDLYCFG0bits.R2RCSDLY = bLen; // minimum number of clocks required between two Read commands to different Chip Selects // write-write delay set DDRDLYCFG0bits.W2WDLY = bLen - 1u; // minimum number of clocks required between two Write command to the same Chip Selects DDRDLYCFG0bits.W2WCSDLY = bLen - 1u; // minimum number of clocks required between two Write command to different Chip Selects // self-refresh delay set DDRPWRCFGbits.SLFREFDLY = tCKESR; // minimum number of clock cycles of idle time the controller needs to wait before automatic entry into Self-Refresh mode * 1024 DDRDLYCFG1bits.SLFREFMINDLY = tCKE - 1u; // minimum number of clocks to stay in Self-Refresh mode DDRDLYCFG1bits.SLFREFEXDLY = (round_up(tDLLK, 2u) - 2u) & 0xffu; // minimum number of clocks required before normal operation after exiting Self-Refresh DDRDLYCFG1bits.SLFREFEXDLY8 = ((round_up(tDLLK, 2u) & 0x100u) != 0) ? 1u : 0; // bit 8 of SLFREFEXDLY (SLFREFEXDLY is bits 0-7) // power down delay set DDRPWRCFGbits.PWRDNDLY = 8; // minimum number of clock cycles of idle time the controller needs to wait before automatic entry into Power-Down * 4 DDRDLYCFG1bits.PWRDNMINDLY = tCKE - 1; // (tCKE/CTL_CLK_PER) - 1 // minimum number of clocks to stay in Power-Down mode after entering it DDRDLYCFG1bits.PWRDNEXDLY = (tCKE > tXP ? tCKE : tXP) - 1; // minimum number of clocks required before normal operation after exiting Power-Down // pre-charge all banks delay set DDRDLYCFG2bits.PCHRGALLDLY = round_up(tRP, CTL_CLK_PER); // minimum number of clocks required from a Pre-charge all banks command to an Activate/Refresh command // read to pre-charge delay set DDRDLYCFG2bits.R2PCHRGDLY = round_up(tRTP, CTL_CLK_PER) + bLen - 2; // minimum number of clocks required from a Read command to a Pre-charge command to the same bank // write to pre-charge delay set DDRDLYCFG2bits.W2PCHRGDLY = (round_up(tWR, CTL_CLK_PER) + wLat + bLen) & 0x0f; // minimum number of clocks required from a Write command to a Precharge command to the same bank as the write DDRDLYCFG1bits.W2PCHRGDLY4 = (((round_up(tWR, CTL_CLK_PER) + wLat + bLen) & 0x10u) != 0) ? 1 : 0; // bit 4 of W2PCHRGDLY (W2PCHRGDLY is bits 0-3) // pre-charge to RAS delay set DDRDLYCFG2bits.PCHRG2RASDLY = round_up(tRP, CTL_CLK_PER) - 1; // minimum number of clocks required from a Pre-charge command to a RAS command to the same bank // RAS to pre-charge delay set DDRDLYCFG3bits.RAS2PCHRGDLY = round_up(tRAS, CTL_CLK_PER) - 1; // minimum number of clocks required from a RAS command to a Pre-charge command to the same bank // RAS to RAS bank delay set DDRDLYCFG3bits.RAS2RASSBNKDLY = round_up(tRC, CTL_CLK_PER) - 1; // minimum number of clocks required between RAS commands to the same bank // RAS to RAS delay set DDRDLYCFG2bits.RAS2RASDLY = round_up(tRRD, CTL_CLK_PER) - 1; // minimum number of clocks required from a RAS command to a RAS command to a different bank on the same Chip Select // RAS to CAS delay set DDRDLYCFG2bits.RAS2CASDLY = round_up(tRCD, CTL_CLK_PER) - 1; // minimum number of clocks required from a RAS command to a CAS command to the same bank // data delay set DDRDLYCFG2bits.RBENDDLY = rLat + 3u; // minimum number of clocks required from issue of a Read command to the read data burst completion DDRXFERCFGbits.NXTDATRQDLY = wLat - 2u; // minimum number of clock cycles required between issuing a Write command and the write data transfer handshake signal ?next data request? // ***** This is how Table 55-4 of Section 55 DDR SDRAM Controller Reference Manual says to do it... doesn't seem to work! //DDRXFERCFGbits.NXTDATAVDLY = (rLat + 4u) & 0xf; // minimum number of clock cycles required between issuing a Read command and the read data being received //DDRDLYCFG1bits.NXTDATAVDLY4 = (((rLat + 4u) & 0x10) != 0) ? 1 : 0; // bit 4 of NXTDATAVDLY (NXTDATAVDLY is bits 0-3) //DDRXFERCFGbits.RDATENDLY = rLat - 2; // minimum number of clocks required between issuing a Read command to the PHY and when the ?read data enable? signal to the PHY is asserted // I guess this is how to do it, since the sample code actually works... DDRXFERCFGbits.NXTDATAVDLY = 4; // minimum number of clock cycles required between issuing a Read command and the read data being received DDRDLYCFG1bits.NXTDATAVDLY4 = (((rLat + 5u) & 0x10u) != 0) ? 1 : 0; // bit 4 of NXTDATAVDLY (NXTDATAVDLY is bits 0-3) DDRXFERCFGbits.RDATENDLY = 2; // minimum number of clocks required between issuing a Read command to the PHY and when the ?read data enable? signal to the PHY is asserted // four activate window time delay set DDRDLYCFG3bits.FAWTDLY = round_up(tFAW, CTL_CLK_PER) - 1; // minimum number of clocks within which only four banks may be opened /* On-Die Termination */ DDRODTCFGbits.ODTCSEN = 0; // number of Chip Selects multiplied by the Chip Select number to be programmed - always 0 since there's only one CS DDRODTENCFGbits.ODTREN = 0; // the Chip Select represented by the OTDCSEN has ODT disabled for data reads DDRODTCFGbits.ODTCSEN = 0; // number of Chip Selects multiplied by the Chip Select number to be programmed - always 0 since there's only one CS DDRODTENCFGbits.ODTWEN = 1; // the Chip Select represented by the OTDCSEN has ODT disabled for data writes DDRODTCFGbits.ODTWLEN = 3; // number of clocks ODT is turned on for writes DDRODTCFGbits.ODTWDLY = 1; // number of clocks after a Write command before turning on ODT to the DDR /* Controller Settings */ DDRXFERCFGbits.BIGENDIAN = 0; // data is little-endian format DDRMEMWIDTHbits.HALFRATE = 1; // PIC32 device always operates in Half-rate mode DDRXFERCFGbits.MAXBURST = 3; // maximum number of commands that can be written to the DDR Controller in Burst mode DDRCMDISSUEbits.NUMHOSTCMDS = 12; // number of host commands to be transmitted to the SDRAM /* DRAM Initialization Sequence */ /* bring CKE high after reset and wait 400 nS using a NOP or DESELECT command */ DDRCMD10 = DDR_IDLE_NOP; // set the CKE, CS, RAS, CAS, WE signals and Mode Address Low Command bits DDRCMD20 = (0x00 | (0x00 << 8) | (sys_mem_ddr_hc_clk_dly(400000) << 11)); // set the Mode Address High Command bits, Bank Address Command and Wait respectively /* issue pre-charge all command */ DDRCMD11 = DDR_PRECH_ALL_CMD; DDRCMD21 = (0x04 | (0x00 << 8) | (sys_mem_ddr_hc_clk_dly(12500 + 2500) << 11)); /* initialize EMR2 */ DDRCMD12 = DDR_LOAD_MODE_CMD; DDRCMD22 = (0x00 | (0x02 << 8) | (sys_mem_ddr_hc_clk_dly(2 * 2500) << 11)); /* initialize EMR3 */ DDRCMD13 = DDR_LOAD_MODE_CMD; DDRCMD23 = (0x00 | (0x03 << 8) | (sys_mem_ddr_hc_clk_dly(2 * 2500) << 11)); /* RDQS disable, DQSB enable, OCD exit, 150 ohm termination, AL=0, DLL enable */ DDRCMD14 = (DDR_LOAD_MODE_CMD | (0x40 << 24)); DDRCMD24 = (0x00 | (0x01 << 8) | (sys_mem_ddr_hc_clk_dly(2 * 2500) << 11)); tmp = ((sys_mem_ddr_round_up(15000, 2500) -1 ) << 1) | 1; ma_field = tmp & 0xff; ba_field = (tmp >> 8) & 0x03; /* PD fast exit, WR REC = tWR in clocks -1, DLL reset, CAS = RL, burst = 4 */ DDRCMD15 = (DDR_LOAD_MODE_CMD | (((5 << 4) | 2) << 24)); DDRCMD25 = (ma_field | (ba_field << 8) | (sys_mem_ddr_hc_clk_dly(2 * 2500) << 11)); /* issue pre-charge all command */ DDRCMD16 = DDR_PRECH_ALL_CMD; DDRCMD26 = (0x04 | (0x00 << 8) | (sys_mem_ddr_hc_clk_dly(12500 + 2500) << 11)); /* issue refresh command */ DDRCMD17 = DDR_REF_CMD; DDRCMD27 = (0x00 | (0x00 << 8) | (sys_mem_ddr_hc_clk_dly(tRFC) << 11)); /* issue refresh command */ DDRCMD18 = DDR_REF_CMD; DDRCMD28 = (0x00 | (0x00 << 8) | (sys_mem_ddr_hc_clk_dly(tRFC) << 11)); tmp = ((sys_mem_ddr_round_up(15000, 2500) -1 ) << 1); ma_field = tmp & 0xff; ba_field = (tmp >> 8) & 0x03; /* Mode register programming as before without DLL reset */ DDRCMD19 = (DDR_LOAD_MODE_CMD | (((5 << 4) | 3) << 24)); DDRCMD29 = (ma_field | (ba_field << 8) | (sys_mem_ddr_hc_clk_dly(2 * 2500) << 11)); /* extended mode register same as before with OCD default */ DDRCMD110 = (DDR_LOAD_MODE_CMD | (0xC0 << 24)); DDRCMD210 = (0x03 | (0x01 << 8) | (sys_mem_ddr_hc_clk_dly(2 * 2500) << 11)); /* extended mode register same as before with OCD exit */ DDRCMD111 = (DDR_LOAD_MODE_CMD | (0x40 << 24)); DDRCMD211 = (0x00 | (0x01 << 8) | (sys_mem_ddr_hc_clk_dly(140 * 2500) << 11)); /* Set number of host commands */ // TODO: find out if this is right, because there are 12 commands and there's another instruction up further that says 12 - should that one be deleted? DDRCMDISSUEbits.NUMHOSTCMDS = 0xc; // number of host commands to be transmitted to the SDRAM ***** was 1b DDRCMDISSUEbits.VALID = 1; // command register data is valid and should be transmitted to the SDRAM DDRMEMCONbits.STINIT = 1; // start memory initialization while (DDRCMDISSUEbits.VALID); // cleared by hardware when all data has been transmitted DDRMEMCONbits.INITDN = 1; // all commands have been issued and the controller is enabled for regular operation } static void DDR_PHY_Calib(void) { /* Physical Interface (PHY) Calibration */ DDRSCLSTARTbits.SCLEN = 1; // enable dynamic self-calibration logic DDRSCLSTARTbits.SCLSTART = 1; // start self-calibration while (!DDRSCLSTARTbits.SCLLBPASS || !DDRSCLSTARTbits.SCLUBPASS); // wait for both the upper and lower self-calibration logic to pass } void InitDDR(void) { volatile unsigned int i, imax, togled; volatile unsigned int *ptri; DDR_Clock_Init(); DDR_PMD_Init(); DDR_PHY_Init(); DDR_Init(); DDR_PHY_Calib(); // memory test /* since writes are 4 bytes, 128MB (0x8000000) is only 32M of uint_32, so imax should be 0x2000000, but if I go * even 1 beyond 0x800000 (8M uint_32 or 32MBytes), it will halt the MPU */ imax = 0x800000; ptri = (unsigned int*)(DDR_START); togled = imax / 16; for (i = 0; i < imax; i++) { *ptri = i; // memory write ptri += 4; if (!(--togled)) { LATHINV = 1; togled = imax / 16; } } ptri = (unsigned int*)(DDR_START); togled = imax / 16; for (i = 0; i < imax; i++) { if (*ptri == i) // memory read { ptri += 4; if (!(--togled)) { LATHINV = 2; togled = imax / 16; } } else { break; } } if (i < imax) // test whether the read succeeded { LATHSET = 1; // failure } else { LATHSET = 4; // success } } |
|
相关推荐
13个回答
|
|
嗨,你查过ValueV2.05例子了吗?在PIC32 MZ DA启动工具包上运行的一些图形示例可能会显示初始化代码。
以上来自于百度翻译 以下为原文 Hi, Have you checked the Harmony v2.05 examples ? Some of the graphics examples running on the PIC32MZ DA starter kit with external memory probably show initialization code. Regards |
|
|
|
您可能需要在TLB缓存中设置条目。Irc默认启动代码设置了一些映射,但我不认为它们覆盖了您的情况。至少对于MZ EC/EF设备,我认为默认是EBI区域的32 MB映射,而SQI区域则是另一个32 MB。
以上来自于百度翻译 以下为原文 You probably need to set up entries in the TLB cache. IIRC the default startup code sets up some mappings, but I don't think they cover your case. At least for MZ EC/EF devices, I believe the default was a 32MB mapping for the EBI area, and another 32MB for the SQI area. |
|
|
|
RISC,正如我在最初的帖子中所说的,我使用的是Orthic文件夹中的Orthic的DDR示例。我基本上逐字地复制它,用函数后面的实际代码替换PLIB函数,所以它应该工作完全一样。它是这样做的,除了我不能访问超过32兆字节的任何东西。
以上来自于百度翻译 以下为原文 RISC, as I stated in the initial post, I'm using Harmony's DDR example located within the Harmony folder. I basically copied it verbatim, replacing the plib functions with the actual code behind the function, so it SHOULD work exactly the same. It does, except that I can't access anything above 32MB. |
|
|
|
谢谢你的回应,安德斯。根据DS600 01361E(PIC32 DA家族参考)图4.1,关于访问所需的MMU/TLB的注释3仅适用于KSGE2和3(EBI & Sqi)。我认为我不需要为此设置MMU或TLB。示例代码中没有任何东西可以做到这一点。但是,如果我在下面的表4.1中查看,对于外部DDR,注释1是适用的,并且我需要设置128MB的EXDRDSIZE(我这样做)和“区域结束地址应该相应地缩放”。我不知道如何做到这一点,我在样本代码中没有看到这样做的任何东西。有人知道这意味着什么以及如何去做吗?
以上来自于百度翻译 以下为原文 Thanks for the response, andersm. According to DS60001361E (PIC32 DA Family Reference) Figure 4.1, note 3 about MMU/TLB needed to access only applies to KSEG2 and 3 (EBI & SQI). I don't think I need to set up the MMU or TLB for this. There's nothing in the sample code that does that. But if I look at Table 4.1 right below that, for external DDR, note 1 is applicable and states I need to set EXTDDRSIZE for 128MB (I did that) and "region end address should be scaled accordingly". I have no idea how to do that and I don't see anything in the sample code that does that. Does anyone know what that means and how to do it? |
|
|
|
如果您查看了在.lt;doc & gt文件夹中的编译器的Read .HTML文件,您将看到一个标题为“应用程序定义的内存区域”的章节。我认为“区域结束地址”可能与γ-语用区有关。只是猜测而已。
以上来自于百度翻译 以下为原文 If you take a look the compiler's readme.html file in the |
|
|
|
嘿,阿申,谢谢你的信息,但是我试过了,没有骰子。我认为这只是让你在其他区域分配变量的空间等。当我看CP0原因寄存器,它说0x000 800 01C,和0x7C & gt;& 2;7,这意味着“数据总线错误”,我猜。堆栈说它在for循环中停止了,但这可能是它执行的最后一条有效行吗?或者这意味着在for循环中有什么东西被搞砸了?
以上来自于百度翻译 以下为原文 Hey aschen, thanks for the info, but I tried it and no dice. I think that just lets you allocate space in other areas for variables, etc. When I look at the CP0 cause register, it says 0x0080001C, which & 0x7C >> 2 = 7, that means "data bus error", I guess. The stack says it stopped at the for loop, but maybe that's just the last valid line it executed? Or does that mean that something in the for loop is screwed up? // memory test imax = 0x800001; ptri = (unsigned int*)(DDR_START); togled = imax / 16; for (i = 0; i < imax; i++) // <----- stack says it stops here! { *ptri = i; // memory write ptri += 4; if (!(--togled)) { LATHINV = 1; togled = imax / 16; } } |
|
|
|
嗯,我是个白痴!我复制了和谐的例子:AppDATA.ADDR是一个未签名的int。我决定使用一个指针,ptri,这很好,除了这个:为什么我没有抓住它?代码使指针溢出到保留区域或某物中。现在,它工作得很好!!
以上来自于百度翻译 以下为原文 Well, I'm OFFICIALLY an idiot!! I copied the Harmony example: (*(volatile unsigned int *)(appData.addr)) = appData.addr; appData.addr += 4; appData.addr is an unsigned int. I decided to use a pointer, ptri, which is fine, EXCEPT for this: ptri += 4; /* NEEDS TO BE... */ ptri++; // since it's a pointer, an increment will add 4 to it since it's pointing to a 32-bit variable Why didn't I catch that? The code made the pointer spill over into reserved area or something. Now, it works GREAT!! |
|
|
|
是的,你说得对。张贴时我面前没有数据表,这总是一个错误。
以上来自于百度翻译 以下为原文 Yes, you're right. I didn't have the datasheet in front of me when posting, which is always a mistake. |
|
|
|
我的两个部分是整个微芯片DDR生态系统都不发达。例如,在DDR中,你真的不能做任何事情,因为启动代码将尝试在建立一个即时异常之前访问DDR地址。此外,在调试时不能看到DDR寄存器会变得很累人。我最终修改了DDR的UMMYMALOC。
以上来自于百度翻译 以下为原文 My two bits are that the whole microchip DDR ecosystem is under developed. For example, you really can't do anything with variables in ddr, because the startup code will try to access the ddr address before it is setup with an instant exception. Also, it becomes quickly tiring to not be able to see ddr registers while debugging. I ended up modifying umm_malloc for ddr. |
|
|
|
弗里森,你说得对,好像是被赶往市场去追赶。第55部分DDR手册中有很多矛盾,以及示例和和声所做的事情,DDR和SDHC。在加载变量之前,有一种初始化DDR的方法。在C:程序文件(x86)Microchip xC32 v1.44文档或在文档文件夹子文件夹用于XC32安装时,查找Read文件。钩子允许在初始化变量之前运行初始化代码。因此,结合新的“Apple Primar”区域,可以指定DDR区域中的加载,并在加载之前初始化它。
以上来自于百度翻译 以下为原文 friesen, you're right, it seems like it was rushed to market to play catch up. There are plenty of contradictions between the Section 55 DDR Manual and how the examples and Harmony do things, both DDR and SDHC. That being said, there IS a way to initialize the DDR BEFORE loading variables! Look up _on_reset in the readme.html file at C:Program Files (x86)Microchipxc32v1.44docs or wherever the docs sub-folder is for the XC32 install. The hook lets you run initialization code BEFORE it initializes variables. So, this, combined with the new #pragma region allows you to specify loading in the DDR area and initialize it before it's loaded. |
|
|
|
但如何融入和谐呢?你能让调试器部分工作吗?
以上来自于百度翻译 以下为原文 How would that integrate into harmony though? Have you been able to get the debugger part working? |
|
|
|
我认为它不会融入和谐。我尽量远离和谐。看看它们是如何运作的,但是它创建了“Buffice”,在那里,实际代码被埋藏在不必要的头文件堆的10个层次深处。对于我的项目,我可以初始化DDR内存,读取预加载的声音文件列表,加载所有的声音(.wav)文件,并在需要时播放它们。它会同时播放8个声音。这是我设计的弹球机代码的一部分。
以上来自于百度翻译 以下为原文 I don't think it would integrate into Harmony. I stay away from Harmony as much as I can. It was useful to see how they do things, but it creates "bloatware" where the actual code is buried 10 levels deep under mounds of unnecessary header files. I have gotten everything working. For my project, I can initialize the DDR memory, read a list of sound files to preload, load all the sound (.wav) files and play them when requested. It will play up to 8 sounds simultaneously. It's part of the code for a pinball machine I'm designing. |
|
|
|
在和谐的弱防御中,一个我可以看到价值的地方是整合RTOS的时候。有一个相当数量的工作已经进入使RTOS很容易集成,至少与MAL.相比。
以上来自于百度翻译 以下为原文 In weak defense of harmony, one place where I can see value is when integrating an RTOS. There is a fair amount of work that has gone into making an RTOS pretty easy to integrate, at least as compared to MAL. |
|
|
|
只有小组成员才能发言,加入小组>>
5181 浏览 9 评论
2004 浏览 8 评论
1931 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3177 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2228 浏览 5 评论
738浏览 1评论
622浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
509浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
636浏览 0评论
533浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 10:21 , Processed in 1.647794 second(s), Total 101, Slave 84 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号