myxiaonia 发表于 2015-9-22 15:10:01

lpc1788 如何在sdram调试程序

用stm32的时候,习惯在sram上调试程序,省去flash下载的麻烦

现在用lpc1788后,也打算在sdram上调试程序了,结果好几天了还是没有搞定如何在sdram调试程序

flash上运行时,sdram可以正常运行,但是现在用sdram调试,第一条指令初始化是正常的,但是运行就跑飞,出现错误:
**JLink Warning: T-bit of XPSR is 0 but should be 1. Changed to 1

我用的调试配置文件如下,是从程序上的时钟和sdram配置改的,也参考了网上的意见,但是网上也没有看到有人在sdram上调试成功的

lpc1788_debug_sdram.ini
/******************************************************************
* File: LPC43XX_E_SDRAM_KEIL_DEBUG.ini
*
* Date: October 2012           Author: NXP
*
* KEIL µVision INI file for initialisation of LPC43xx when debugging code
* running from external SDRAM @ 0x28000000. The SDRAM must be initialized
* before the debugger can load the image to it.
* This use case is just for debugging, in a real application the code
* which goes into SDRAM will come from an external flash and the startup
* code needs to initialize the SDRAM and relocate the image.
*
* This script initializes the SDRAM on the KEIL MCB4300 board.
*
******************************************************************/


FUNC void Setup (unsigned int region) {
region &= 0xFF000000;
//_WDWORD(0x40043100, 0);                                // Set the shadow pointer to zero (can't map SDRAM to 0)
SP = _RDWORD(region);                     // Setup Stack Pointer
PC = _RDWORD(region + 4);               // Setup Program Counter
_WDWORD(0xE000ED08, region);                                // Set the vector table offset
}

FUNC void Clock_Setup (void) {
        _WDWORD(0x400FC1A0, 0x00000021);                        // Enable the crystal oscillator
        while((_RDWORD(0x400FC1A0) & (1<<6)) == 0);        // delay wait for oscillator to start
        _WDWORD(0x400FC10C, 0x00000001);                        // select crystal oscillator
        _WDWORD(0x400FC084, 0x00000009);                        // Configure PLL0 to multiply x 10 for 120 MHz operation from 12 MHz crystal
        _WDWORD(0x400FC080, 0x00000001);                        // PLL0 Enable
        _WDWORD(0x400FC08C, 0x000000AA);                        //
        _WDWORD(0x400FC08C, 0x00000055);                        //
       
        while((_RDWORD(0x400FC088) & (1<<10)) == 0);        // Wait for PLOCK0
       
        _WDWORD(0x400FC104, 0x00000101);                        //PLL0 not divide as the cpuclock
        _WDWORD(0x400FC100, 0x00000001);                        //cpuclock / 2 as the emcclock
        _WDWORD(0x400FC0C4, 0x00000800);                        //emcclock enable

        _WDWORD(0x400FC1B0, 0x00000003);                        //120M support
}


FUNC void LPC1788_setupEmc (void)
{   
// Setup pins for external data/address bus
_WDWORD(0x4002C180, (1 << 9)|1);   // D0,P3.0   
_WDWORD(0x4002C184, (1 << 9)|1);   // D1,P3.1   
_WDWORD(0x4002C188, (1 << 9)|1);   // D2,P3.2   
_WDWORD(0x4002C18C, (1 << 9)|1);   // D3,P3.3   
_WDWORD(0x4002C190, (1 << 9)|1);   // D4,P3.4   
_WDWORD(0x4002C194, (1 << 9)|1);   // D5,P3.5   
_WDWORD(0x4002C198, (1 << 9)|1);   // D6,P3.6   
_WDWORD(0x4002C19C, (1 << 9)|1);   // D7,P3.7                                    
_WDWORD(0x4002C1A0, (1 << 9)|1);   // D8,P3.8                                    
_WDWORD(0x4002C1A4, (1 << 9)|1);   // D9,P3.9                                    
_WDWORD(0x4002C1A8, (1 << 9)|1);   // D10, P3.10                                    
_WDWORD(0x4002C1AC, (1 << 9)|1);   // D11, P3.11                                    
_WDWORD(0x4002C1B0, (1 << 9)|1);   // D12, P3.12                                    
_WDWORD(0x4002C1B4, (1 << 9)|1);   // D13, P3.13                                    
_WDWORD(0x4002C1B8, (1 << 9)|1);   // D14, P3.14                                    
_WDWORD(0x4002C1BC, (1 << 9)|1);   // D15, P3.15   

_WDWORD(0x4002C200, (1 << 9)|1);   // A0,P4.0
_WDWORD(0x4002C204, (1 << 9)|1);   // A1,P4.1
_WDWORD(0x4002C208, (1 << 9)|1);   // A2,P4.2   
_WDWORD(0x4002C20C, (1 << 9)|1);   // A3,P4.3   
_WDWORD(0x4002C210, (1 << 9)|1);   // A4,P4.4   
_WDWORD(0x4002C214, (1 << 9)|1);   // A5,P4.5   
_WDWORD(0x4002C218, (1 << 9)|1);   // A6,P4.6   
_WDWORD(0x4002C21C, (1 << 9)|1);   // A7,P4.7   
_WDWORD(0x4002C220, (1 << 9)|1);   // A8,P4.8   
_WDWORD(0x4002C224, (1 << 9)|1);   // A9,P4.9   
_WDWORD(0x4002C228, (1 << 9)|1);   // A10, P4.10   
_WDWORD(0x4002C22C, (1 << 9)|1);   // A11, P4.11   
_WDWORD(0x4002C230, (1 << 9)|1);   // A12, P4.12   
_WDWORD(0x4002C234, (1 << 9)|1);   // A13, P4.13   
_WDWORD(0x4002C238, (1 << 9)|1);   // A14, P4.14   

_WDWORD(0x4002C264, (1 << 9)|1);   // WEN, P4.25   

_WDWORD(0x4002C140, (1 << 9)|1);   // CAS, P2.16
_WDWORD(0x4002C144, (1 << 9)|1);   // RAS, P2.17
_WDWORD(0x4002C148, (1 << 9)|1);   // CLK, P2.18
_WDWORD(0x4002C150, (1 << 9)|1);   // DYCS,P2.20
_WDWORD(0x4002C160, (1 << 9)|1);   // CKE, P2.24
_WDWORD(0x4002C170, (1 << 9)|1);   // DMQ0,P2.28   
_WDWORD(0x4002C174, (1 << 9)|1);   // DMQ1,P2.29   

_WDWORD(0x400FC1DC, 0x00001010);   // (0x1010+1)* 250ps

// Initialize EMC
_WDWORD(0x2009C000, 0x00000001); // CONTROL=1 = Enable EMC
_WDWORD(0x2009C008, 0x00000000); // CONFIG=0
_WDWORD(0x2009C100, 0x00000680); // DYNAMICCONFIG0
_WDWORD(0x2009C104, 0x00000202); // DYNAMICRASCAS0

_WDWORD(0x2009C028, 0x00000001); // DYNAMICREADCONFIG

_WDWORD(0x2009C030, 0x00000001); // DYNAMICRP
_WDWORD(0x2009C034, 0x00000003); // DYNAMICRAS
_WDWORD(0x2009C038, 0x00000000); // DYNAMICREX
_WDWORD(0x2009C03C, 0x00000001); // DYNAMICAPR
_WDWORD(0x2009C040, 0x00000005); // DYNAMICDAL
_WDWORD(0x2009C044, 0x00000001); // DYNAMICWR
_WDWORD(0x2009C048, 0x00000004); // DYNAMICRC
_WDWORD(0x2009C04C, 0x00000004); // DYNAMICRFC
_WDWORD(0x2009C050, 0x00000005); // DYNAMICXSR
_WDWORD(0x2009C054, 0x00000001); // DYNAMICRRD
_WDWORD(0x2009C058, 0x00000001); // DYNAMICMRD

_WDWORD(0x2000C020, 0x00000183); // DYNAMICCONTROL - NOP
_WDWORD(0x2000C020, 0x00000103); // DYNAMICCONTROL - PRECHARGE_ALL

_WDWORD(0x2000C024, 0x0000001D); // DYNAMICREFRESH = 1D

_WDWORD(0x2009C020, 0x00000083); // DYNAMICCONTROL - MODE

_RDWORD(0xA0000000 | (0x23<<12));// Write 16-bit SDRAM Mode register burst 8- this is a read as requested by the SDRAM spec

_WDWORD(0x2009C020, 0x00000000); // DYNAMICCONTROL - NORMAL

_WDWORD(0x2009C100, 0x00080680); // DYNAMICCONFIG0

}

FUNC void mpu_region_setup(unsigned int a_addr,
                     unsigned int a_region,
                     unsigned int a_size,
                     unsigned int a_ap,
                     unsigned int a_mem_attrib,
                     unsigned int a_srd,
                     unsigned int a_XN,
                     unsigned int a_enable)
{
    // Setup procedure for each region
    unsigned int temp;
    temp = (a_addr & 0xFFFFFFE0) | (a_region & 0xF) | 0x10 ;
    _WDWORD(0xE000ED9C, temp); // RBAR
    temp = ((a_XN & 0x1)<<28) | ((a_ap & 0x7)<<24) | ((a_mem_attrib & 0x3F)<<16) | ((a_srd&0xFF)<<8) | ((a_size & 0x1F)<<1)| (a_enable & 0x1) ;
//    temp = ((a_ap & 0x7)<<24) | ((a_size & 0x1F)<<1)| (a_enable & 0x1) ;
    _WDWORD(0xE000EDA0, temp); // RASR
    _WDWORD(0xE000ED94, 1); // MPU enable
}

Clock_Setup();

//# Initialize the external memory interface. If booting in EMC mode,
//# the bootloader initializes the EMC, but enables only A.
LPC1788_setupEmc();

//# The LOAD command downloads the image to the memory region specified by the linker script as load region.
LOAD %L INCREMENTAL

//mpu_region_setup( 0xA0000000,
//                   7, // always reprogramming MPU region 7
//                   0x18,//32MB
//                   3, // full access
//                   0, // strongly ordered, shareable
//                   0, // subregion disabled
//                   0, // allow instruction execution
//                   1) ; // region enabled
mpu_region_setup( 0xA0000000,0,0x18,3,7,0,0,1);

//# Get ready to execute image in the given memory region
Setup(0xA0000000);

myxiaonia 发表于 2015-9-22 15:32:22

这个是分散加载的段设置

aozima 发表于 2015-9-22 16:00:26

方法是思路是对的。
1. 检查SDRAM是否可以正常读写
2. 检查MPU配置是允许SDRAM执行
3. 下载费不了几个时间,也就调些硬件驱动时用得多些,没必要折腾自己不熟悉的。

liurangzhou 发表于 2015-9-22 19:37:14

需要配置MPU

LQS1200 发表于 2015-9-22 20:44:33

myxiaonia 发表于 2015-9-22 15:32
这个是分散加载的段设置

记得论坛上有的,但是现在不怎么用1788了,忘记在哪了

myxiaonia 发表于 2015-9-22 21:19:59

LQS1200 发表于 2015-9-22 20:44
记得论坛上有的,但是现在不怎么用1788了,忘记在哪了

你有没有使用过调试程序啊,我找遍了各个角落,,,有人提出过相同的需求,却没有看到过完整确切的答案

LQS1200 发表于 2015-9-22 22:08:21

myxiaonia 发表于 2015-9-22 21:19
你有没有使用过调试程序啊,我找遍了各个角落,,,有人提出过相同的需求,却没有看到过完整确切的答案 ...

明天问下先,不知道还有没有

myxiaonia 发表于 2015-9-22 22:16:31

本帖最后由 myxiaonia 于 2015-9-22 22:38 编辑

在程序装载后,更新sp,pc等我发现xpsr的t位一直为0,而cm3必须为1(thumb模式),我强制设置为1还是为0

就是这个罪魁祸首,奇怪的是寄存器窗口xpsr显示值是0x81000000,这里t位是1,展开后t位却为0

贴两张截图


myxiaonia 发表于 2015-9-23 00:14:44

原来是vtor设置最多0-28位,并且29位还是code或者ram指示器 这样的话设置为0xa0000000效果成了0x20000000

LQS1200 发表于 2015-9-23 08:46:24

工程还没找到,参考下http://blog.csdn.net/waitig1992/article/details/38561867

myxiaonia 发表于 2015-9-23 10:42:48

本帖最后由 myxiaonia 于 2015-9-23 10:46 编辑

LQS1200 发表于 2015-9-23 08:46
工程还没找到,参考下http://blog.csdn.net/waitig1992/article/details/38561867

这是你的博客吗我看过啊嘿嘿但是怎么忽略了在sdram调试成功的经验,估计是外部ram没有写明是sdram就晃眼了。。。回家测试下看看

我之前写外部字库到sst39v1602也是用的这个博客上的norflash配置ini,当时这个很快就搞成功了,用上这个配置文件立马ok

LQS1200 发表于 2015-9-23 11:54:35

myxiaonia 发表于 2015-9-23 10:42
这是你的博客吗我看过啊嘿嘿但是怎么忽略了在sdram调试成功的经验,估计是外部ram没有写明是sdram就 ...

不是,没那么高手

myxiaonia 发表于 2015-9-24 10:03:34

终于搞定了,贴出正确的配置文件,后来者不用再走弯路,感谢楼上兄弟贴出的博客地址,让我增强信心,因为之前在网上没有找到在sdram调试程序的先例,方向不明朗信心很受打击

基本配置过程就是那样,问题出在两处:emc操作寄存器,DYNAMICCONTROL 地址写错了,时钟配置寄存器里,没有使能外设时钟和gpio时钟,好低级的错误。。。。越是低级错误排错越是匪夷所思,血的教训。。。

/******************************************************************
* File: LPC43XX_E_SDRAM_KEIL_DEBUG.ini
*
* Date: October 2012           Author: NXP
*
* KEIL µVision INI file for initialisation of LPC43xx when debugging code
* running from external SDRAM @ 0x28000000. The SDRAM must be initialized
* before the debugger can load the image to it.
* This use case is just for debugging, in a real application the code
* which goes into SDRAM will come from an external flash and the startup
* code needs to initialize the SDRAM and relocate the image.
*
* This script initializes the SDRAM on the KEIL MCB4300 board.
*
******************************************************************/


FUNC void Setup (unsigned int region) {
    region &= 0xFF000000;
//    _WDWORD(0x40043100, 0);                                        // Set the shadow pointer to zero (can't map SDRAM to 0)
    SP = _RDWORD(region);                     // Setup Stack Pointer
    PC = _RDWORD(region + 4);                   // Setup Program Counter
    _WDWORD(0xE000ED08, region);                                // Set the vector table offset
}

FUNC void Clock_Setup (void) {
        _WDWORD(0x400FC1A0, 0x00000021);                        // Enable the crystal oscillator
//        while((_RDWORD(0x400FC1A0) & (1<<6)) == 0);        // delay wait for oscillator to start
    _sleep_ (100);                              // Wait for main oscillator to stabilize        _WDWORD(0x400FC10C, 0x00000001);                        // select crystal oscillator
        _WDWORD(0x400FC084, 0x00000009);                        // Configure PLL0 to multiply x 10 for 120 MHz operation from 12 MHz crystal
        _WDWORD(0x400FC080, 0x00000001);                        // PLL0 Enable
        _WDWORD(0x400FC08C, 0x000000AA);                        //
        _WDWORD(0x400FC08C, 0x00000055);                        //
       
//        while((_RDWORD(0x400FC088) & (1<<10)) == 0);        // Wait for PLOCK0
    _sleep_ (100);                              // Wait for PLOCK0
        _WDWORD(0x400FC104, 0x00000101);                        //PLL0 not divide as the cpuclock
        _WDWORD(0x400FC100, 0x00000001);                        //cpuclock / 2 as the emcclock
        _WDWORD(0x400FC18A, 0x00000002);                        //cpuclock / 2 as the pclock
        _WDWORD(0x400FC0C4, 0x00008800);                        //emcclock gpio enable

        _WDWORD(0x400FC1B0, 0x00000003);                        //120M support
}


FUNC void LPC1788_setupEmc (void)
{   
    // Setup pins for external data/address bus
    _WDWORD(0x4002C180, (1 << 9)|1);   // D0,P3.0   
    _WDWORD(0x4002C184, (1 << 9)|1);   // D1,P3.1   
    _WDWORD(0x4002C188, (1 << 9)|1);   // D2,P3.2   
    _WDWORD(0x4002C18C, (1 << 9)|1);   // D3,P3.3   
    _WDWORD(0x4002C190, (1 << 9)|1);   // D4,P3.4   
    _WDWORD(0x4002C194, (1 << 9)|1);   // D5,P3.5   
    _WDWORD(0x4002C198, (1 << 9)|1);   // D6,P3.6   
    _WDWORD(0x4002C19C, (1 << 9)|1);   // D7,P3.7                                    
    _WDWORD(0x4002C1A0, (1 << 9)|1);   // D8,P3.8                                    
    _WDWORD(0x4002C1A4, (1 << 9)|1);   // D9,P3.9                                    
    _WDWORD(0x4002C1A8, (1 << 9)|1);   // D10, P3.10                                    
    _WDWORD(0x4002C1AC, (1 << 9)|1);   // D11, P3.11                                    
    _WDWORD(0x4002C1B0, (1 << 9)|1);   // D12, P3.12                                    
    _WDWORD(0x4002C1B4, (1 << 9)|1);   // D13, P3.13                                    
    _WDWORD(0x4002C1B8, (1 << 9)|1);   // D14, P3.14                                    
    _WDWORD(0x4002C1BC, (1 << 9)|1);   // D15, P3.15   

    _WDWORD(0x4002C200, (1 << 9)|1);   // A0,P4.0
    _WDWORD(0x4002C204, (1 << 9)|1);   // A1,P4.1
    _WDWORD(0x4002C208, (1 << 9)|1);   // A2,P4.2   
    _WDWORD(0x4002C20C, (1 << 9)|1);   // A3,P4.3   
    _WDWORD(0x4002C210, (1 << 9)|1);   // A4,P4.4   
    _WDWORD(0x4002C214, (1 << 9)|1);   // A5,P4.5   
    _WDWORD(0x4002C218, (1 << 9)|1);   // A6,P4.6   
    _WDWORD(0x4002C21C, (1 << 9)|1);   // A7,P4.7   
    _WDWORD(0x4002C220, (1 << 9)|1);   // A8,P4.8   
    _WDWORD(0x4002C224, (1 << 9)|1);   // A9,P4.9   
    _WDWORD(0x4002C228, (1 << 9)|1);   // A10, P4.10   
    _WDWORD(0x4002C22C, (1 << 9)|1);   // A11, P4.11   
    _WDWORD(0x4002C230, (1 << 9)|1);   // A12, P4.12   
    _WDWORD(0x4002C234, (1 << 9)|1);   // A13, P4.13   
    _WDWORD(0x4002C238, (1 << 9)|1);   // A14, P4.14   

    _WDWORD(0x4002C264, (1 << 9)|1);   // WEN, P4.25   

    _WDWORD(0x4002C140, (1 << 9)|1);   // CAS, P2.16
    _WDWORD(0x4002C144, (1 << 9)|1);   // RAS, P2.17
    _WDWORD(0x4002C148, (1 << 9)|1);   // CLK, P2.18
    _WDWORD(0x4002C150, (1 << 9)|1);   // DYCS,P2.20
    _WDWORD(0x4002C160, (1 << 9)|1);   // CKE, P2.24
    _WDWORD(0x4002C170, (1 << 9)|1);   // DMQ0,P2.28   
    _WDWORD(0x4002C174, (1 << 9)|1);   // DMQ1,P2.29   

    _WDWORD(0x400FC1DC, 0x00001010);   // (0x1010+1)* 250ps

    // Initialize EMC
    _WDWORD(0x2009C000, 0x00000001);   // CONTROL=1 = Enable EMC
    _WDWORD(0x2009C008, 0x00000000);   // CONFIG=0
    _WDWORD(0x2009C100, 0x00000680);   // DYNAMICCONFIG0
    _WDWORD(0x2009C104, 0x00000202);   // DYNAMICRASCAS0
                                       
    _WDWORD(0x2009C028, 0x00000001);   // DYNAMICREADCONFIG
                                       
    _WDWORD(0x2009C030, 0x00000001);   // DYNAMICRP
    _WDWORD(0x2009C034, 0x00000003);   // DYNAMICRAS
    _WDWORD(0x2009C038, 0x00000000);   // DYNAMICREX
    _WDWORD(0x2009C03C, 0x00000001);   // DYNAMICAPR
    _WDWORD(0x2009C040, 0x00000005);   // DYNAMICDAL
    _WDWORD(0x2009C044, 0x00000001);   // DYNAMICWR
    _WDWORD(0x2009C048, 0x00000004);   // DYNAMICRC
    _WDWORD(0x2009C04C, 0x00000004);   // DYNAMICRFC
    _WDWORD(0x2009C050, 0x00000005);   // DYNAMICXSR
    _WDWORD(0x2009C054, 0x00000001);   // DYNAMICRRD
    _WDWORD(0x2009C058, 0x00000001);   // DYNAMICMRD
                                       
    _WDWORD(0x2009C020, 0x00000183);   // DYNAMICCONTROL - NOP
    _sleep_(100);
    _WDWORD(0x2009C020, 0x00000103);   // DYNAMICCONTROL - PRECHARGE_ALL
    _sleep_(100);                                    
    _WDWORD(0x2009C024, 0x0000001D);   // DYNAMICREFRESH = 1D
                                       
    _WDWORD(0x2009C020, 0x00000083);   // DYNAMICCONTROL - MODE
                                       
    _RDWORD(0xA0000000 | (0x23<<12));// Write 16-bit SDRAM Mode register burst 8- this is a read as requested by the SDRAM spec
                                       
    _WDWORD(0x2009C020, 0x00000003);   // DYNAMICCONTROL - NORMAL
                                       
    _WDWORD(0x2009C100, 0x00080680);   // DYNAMICCONFIG0
    _sleep_(100);                                    
}

FUNC void mpu_region_setup(unsigned int a_addr,
                     unsigned int a_region,
                     unsigned int a_size,
                     unsigned int a_ap,
                     unsigned int a_mem_attrib,
                     unsigned int a_srd,
                     unsigned int a_XN,
                     unsigned int a_enable)
{
    // Setup procedure for each region
    unsigned int temp;
    temp = (a_addr & 0xFFFFFFE0) | (a_region & 0xF) | 0x10 ;
    _WDWORD(0xE000ED9C, temp); // RBAR
    temp = ((a_XN & 0x1)<<28) | ((a_ap & 0x7)<<24) | ((a_mem_attrib & 0x3F)<<16) | ((a_srd&0xFF)<<8) | ((a_size & 0x1F)<<1)| (a_enable & 0x1) ;
    _WDWORD(0xE000EDA0, temp); // RASR
    _WDWORD(0xE000ED24, 1<<18); // usage fault enable
    _WDWORD(0xE000ED94, 5); // MPU enable
}

Clock_Setup();

LPC1788_setupEmc();

LOAD %L INCREMENTAL

mpu_region_setup( 0xA0000000,0,0x18,3,7,0,0,1);

Setup(0x10000000);

LQS1200 发表于 2015-9-24 13:46:54

搞定了就好,恭喜{:smile:}

R8C 发表于 2015-12-13 16:25:57

按你的方法还是调不出,SDRAM是好的,你看看对不对
LR_IROM1 0x10000000 0x00010000{    ; load region size_region
ER_IROM1 0x10000000 0x00010000{; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
}
RW_RAM1 0xA0010000 UNINIT 0x00010000{; RW data
   .ANY (+RW +ZI)
}
}

LR_ROM1 0xA0000000 0x00010000{
ER_ROM1 0xA0000000 0x00010000{; load address = execution address
   .ANY (+RO)
}
}

R8C 发表于 2015-12-14 21:29:22

已搞惦了

R8C 发表于 2015-12-18 22:58:51

楼主文件有错误

myxiaonia 发表于 2015-12-18 23:24:02

R8C 发表于 2015-12-18 22:58
楼主文件有错误

哦 请指出哪里有错误?

R8C 发表于 2015-12-19 08:58:43

错误地方:
_WDWORD(0x400FC18A, 0x00000002);                        //cpuclock / 2 as the pclock
正确应该是:
_WDWORD(0x400FC1A8, 0x00000002);                        //cpuclock / 2 as the pclock
页: [1]
查看完整版本: lpc1788 如何在sdram调试程序