1

我正在进行的项目必须在程序运行之前测试 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. 这是给我的原始实现,但它从未起作用(至少就调试/运行而言;这种写入方法遇到了相同的随机中断,然后在继续之前立即读取相同的地址)

更新:在几次 Clean&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;
    }
4

2 回答 2

1

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

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

于 2013-06-17T21:41:15.460 回答
1

Okay, so there are a number of things that we can look at to get a better understanding of where your problem may be. There are some things that I would like to point out - and hopefully we can figure this out together. The first thing that I noticed that seems a little out of place is this comment:

"...total RAM goes to 0x17FFE..."

I looked up the data sheet for the dsPIC30F6012A . You can see in Figure 3-8 (pg. 33), that the SRAM space is 8K and runs from 0x0800 to 0x2800. Also, there is this little tidbit:

"All effective addresses are 16 bits wide and point to bytes within the data space"

So, you can use 16 bit values for your addresses. I am a little confused by your update as well. SPLIM is a register that you set the value for - and that value limits the size of your stack. I'm not sure what the value for your SPLIMIT is, but W15 is your actual stack pointer register, and the value that is stored there is the address to the top of your stack:

"There is a Stack Pointer Limit register (SPLIM) associated with the Stack Pointer. SPLIM is uninitialized at Reset. As is the case for the Stack Pointer, SPLIM<0> is forced to ‘0’ because all stack operations must be word aligned. Whenever an Effective Address (EA) is generated using W15 as a source or destination pointer, the address thus generated is compared with the value in SPLIM. If the contents of the Stack Pointer (W15) and the SPLIM register are equal and a push operation is performed, a Stack Error Trap will not occur."

Finally, the stack grows from the lowest available SRAM address value up to SPLIM. So I would propose setting the SPLIM value to something reasonable, let's say 512 bytes (although it would be best to test how much room you need for your stack).

Since this particular stack grows upwards, I would start at 0x0800 plus what we added for the stack limit and then test from there (which would be 0x1000). This way you won't have to worry about your stack region.

Given the above, here is how I would go about doing this.

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++;
        }
    }
}

My code was a bit rushed so I am sure there are probably some errors (feel free to edit), but hopefully this will help get you on the right track!

于 2013-06-22T03:52:06.623 回答