RAM测试逐步完成,但在运行时失败

时间:2013-06-17 20:19:13

标签: c testing embedded ram pic

我正在研究的项目必须在程序运行之前测试dsPIC30F芯片的数据存储器。由于行业要求,我们无法使用C提供的任何预定义库。话虽这么说,这是我测试RAM的方法:

Step 1 - Write the word 0xAAAA to a specific location in memory (defined by a LoopIndex added to the START_OF_RAM address)

Step 2 - increment LoopIndex

Step 3 - Repeat Steps 1-2 until LoopIndex + START_OF_RAM >= END_OF_RAM

Step 4 - Reset LoopIndex = 0

Step 5 - Read memory at LoopIndex+START_OF_RAM

Step 6 - If memory = 0xAAAA, continue, else throw RAM_FAULT_HANDLER

Step 7 - increment LoopIndex

Step 8 - Repeat Step 5 - 7 until LoopIndex + START_OF_RAM >= END_OF_RAM

现在,奇怪的部分是我可以单步执行代码,没问题。只要我的小指按下F8,它就会慢慢地遍历每个内存地址,但是当我尝试在步骤4设置一个断点时,它会抛出一个随机的通用中断处理程序,没有明显的原因。我认为可能是因为我使用的for()可能超过END_OF_RAM,但我已经改变了条件的界限,但它仍然不喜欢运行。

任何见解都会有所帮助。

void PerformRAMTest()
{

    // Locals
    uint32_t LoopIndex = 0;
    uint16_t *AddressUnderTest;
    uint32_t RAMvar = 0;
    uint16_t i = 0;

    // Loop through RAM and write the first pattern (0xAA) - from the beginning to the first RESERVED block
    for(LoopIndex = 0x0000; LoopIndex < C_RAM_END_ADDRESS; LoopIndex+= 2)
    {

        AddressUnderTest = (uint32_t*)(C_RAM_START_ADDRESS + LoopIndex);

        *AddressUnderTest = 0xAAAA;


    }// end for

    for(LoopIndex = 0x0000; LoopIndex < C_RAM_END_ADDRESS; LoopIndex += 2)
    {
        AddressUnderTest = (uint32_t*)(C_RAM_START_ADDRESS + LoopIndex);

        if(*AddressUnderTest != 0xAAAA)
            {
                // If what was read does not equal what was written, log the
                // RAM fault in NVM and call the RAMFaultHandler()
                RAMFaultHandler();
            }// end if
    }

    // Loop through RAM and write then verify the second pattern (0x55)
    // - from the beginning to the first RESERVED block
//    for(LoopIndex = C_RAM_START_ADDRESS; LoopIndex < C_RAM_END_ADDRESS; LoopIndex++)
//    {
//        AddressUnderTest = (uint32_t*)(C_RAM_START_ADDRESS + LoopIndex);
//        *AddressUnderTest = 0x5555;
//        if(*AddressUnderTest != 0x5555)
//        {
//            // If what was read does not equal what was written, log the
//            // RAM fault in NVM and call the RAMFaultHandler()
//            RAMFaultHandler();
//        }
//    }

}// end PerformRAMTest

您可以看到测试的第二遍写0x55。这是给我的原始实现,但它从未起作用(至少就调试/运行而言;这种写入方法遇到了相同的随机中断,然后在继续之前立即读取相同的地址)

UPDATE :经过一些Clean&amp; Builds后,代码现在将运行直到它到达堆栈指针(WREG15),跳过,然后出错。以下是相关代码的新示例:

if(AddressUnderTest >= &SPLIMIT && AddressUnderTest <= SPLIMIT)
    {
        // if true, set the Loop Index to point to the end of the stack
        LoopIndex = (uint16_t)SPLIMIT;
    }
    else if(AddressUnderTest == &SPLIMIT) // checkint to see if AddressUnderTest points directly to the stack [This works while the previous >= &SPLIMIT does not. It will increment into the stack, update, THEN say "oops, I just hit the stack" and error out.]
    {
        LoopIndex = &SPLIMIT;
    }
    else
    {
        *AddressUnderTest = 0xAAAA;
    }

2 个答案:

答案 0 :(得分:1)

我认为你实际上想要(C_RAM_START_ADDRESS + LoopIndex) < C_RAM_END_ADDRESS作为你的循环条件。目前,您正在从C_RAM_START_ADDRESS循环到C_RAM_START_ADDRESS + C_RAM_END_ADDRESS,我假设它正在写入RAM的末尾。

您还应该将重复的代码分解为一个单独的函数,该函数将测试模式作为参数(DRY)。

答案 1 :(得分:1)

好的,我们可以通过一些方法来更好地了解您的问题所在。我想指出一些事情 - 希望我们可以一起解决这个问题。我注意到的第一件事似乎有点不合适就是这个评论:

  

“......总RAM变为0x17FFE ...”

我查看了dsPIC30F6012A的数据表。您可以在图3-8(第33页)中看到,SRAM空间为8K,运行范围为0x0800至0x2800。还有,这是一个小小的问题:

  

“所有有效地址都是16位宽,指向数据空间中的字节”

因此,您可以为地址使用16位值。我也对你的更新感到有些困惑。 SPLIM是一个为 - 设置值的寄存器 - 该值限制了堆栈的大小。我不确定SPLIMIT的值是多少,但是W15是你的实际堆栈指针寄存器,而那里存储的值是堆栈顶部的地址:

  

“有一个堆栈指针限制寄存器(SPLIM)关联   使用堆栈指针。 SPLIM未初始化   重启。与堆栈指针的情况一样,SPLIM&lt; 0&gt;   被强制为'0',因为所有堆栈操作必须是   单词对齐。 每当有效地址(EA)为   使用W15作为源或目标生成   指针,将生成的地址与之比较   SPLIM中的值。如果是堆栈指针的内容   (W15)和SPLIM寄存器相等并且是推送   执行操作时,Stack Error Trap不会   发生。

最后,堆栈从最低可用SRAM地址值增加到SPLIM。所以我建议将SPLIM值设置为合理的值,假设为512字节(尽管最好是test how much room you need for your stack)。

由于这个特定的堆栈向上增长,我将从0x0800开始加上我们为堆栈限制添加的内容然后从那里进行测试(这将是0x1000)。这样您就不必担心堆栈区域了。

鉴于上述情况,我将采取以下措施。

void PerformRAMTest (void)
{
    #define SRAM_START_ADDRESS  0x0800

    /* Stack size = 512 bytes.  Assign STACK_LIMIT
       to SPLIM register during configuration. */
    #define STACK_SIZE          0x0200

    /* -2, see pg 35 of dsPIC30F6012A datasheet. */
    #define STACK_LIMIT             ((SRAM_START_ADDRESS + STACK_SIZE) - 2)
    #define SRAM_BEGIN_TEST_ADDRESS ((volatile uint16_t *)(STACK_LIMIT + 2))
    #define SRAM_END_TEST_ADDRESS   0x2800
    #define TEST_VALUE              0xAAAA

    /* No need for 32 bit address values on this platform */
    volatile uint16_t * AddressUnderTest = SRAM_BEGIN_TEST_ADDRESS

    /* Write to memory */
    while (AddressUnderTest < SRAM_END_TEST_ADDRESS)
    {
        *AddressUnderTest = TEST_VALUE;
        AddressUnderTest++;
    }

    AddressUnderTest = SRAM_BEGIN_TEST_ADDRESS;

    /* Read from memory */
    while (AddressUnderTest < SRAM_END_TEST_ADDRESS)
    {
        if (*AddressUnderTest != TEST_VALUE)
        {
            RAMFaultHandler();
            break;
        }
        else
        {
            AddressUnderTest++;
        }
    }
}

我的代码有点匆忙所以我确信可能存在一些错误(随意编辑),但希望这有助于您走上正确的轨道!