2013-06-17 4 views
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 

지금, 이상한 부분은 내가 코드, 아무 문제를 단계별로 할 수 있다는 것입니다 : 말했다되는 것으로, 여기에 RAM을 테스트하기위한 나의 방법론이다. 내 작은 손가락이 F8 키를 누를 수있는 한 천천히 각 메모리 주소를 반복하지만 4 단계에서 중단 점을 설정하자마자 임의의 이유없이 범용 인터럽트 처리기가 무작위로 throw됩니다. 나는 이것이 내가 사용하는 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입니다. 이것은 나에게 주어진 원래의 구현 이었지만 결코 작동하지 않았다. (최소한 디버깅/실행과 같은 무작위 인터럽트는이 주소를 읽는이 방법으로 발생했다.)

업데이트 : 약간의 번복 후 & 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; 
    } 
+1

메모리에서 프로그램과 스택은 어디에 있습니까? –

+1

'(C_RAM_START_ADDRESS + LoopIndex)'를'(uint16_t *)'로 캐스팅해서는 안됩니까? –

+0

@LeeDanielCrocker - DATA 메모리는 이론적으로 0x0800에서 시작해야합니다. 프로그램 메모리가 시작됩니다. 잘 모르겠습니다. 우리는 W15 레지스터가 스택 포인터라는 것을 알고 있습니다. 그러나 SPIIMIT 변수를 가지고 있습니다 만, LoopIndex가 건너 뛰도록 설정했으나 작동하지 않습니다. – ThomSirveaux

답변

1

내가 당신이 실제로 루프 조건으로 (C_RAM_START_ADDRESS + LoopIndex) < C_RAM_END_ADDRESS를 원한다고 생각 : 여기에 문제가있는 코드의 새로운 샘플입니다. 현재, 당신은 C_RAM_START_ADDRESS에서 C_RAM_START_ADDRESS + C_RAM_END_ADDRESS으로 반복하고 있습니다. RAM 끝을 지나면 쓰고 있다고 가정합니다.

테스트 패턴을 매개 변수 (DRY)로 사용하는 별도의 함수로 반복 코드를 실제로 제외해야합니다.

+0

'LoopIndex ThomSirveaux

1

좋아, 문제가있는 위치를 더 잘 이해하기 위해 살펴볼 수있는 여러 가지 사항이 있습니다. 제가 지적하고자하는 몇 가지 것들이 있습니다 - 그리고 이것을 함께 이해할 수 있기를 바랍니다.

내가에 대한 데이터 시트를 보았다 "... ... 총 RAM이 0x17FFE 간다"

: 나는이 작은 장소에서 보인다 처음으로 느낀 것은이 댓글입니다 dsPIC30F6012A. 그림 3-8 (33 페이지)에서 SRAM 공간이 8K이고 0x0800에서 0x2800까지 실행된다는 것을 알 수 있습니다. 또한,이 작은 맛있는 가벼운 음식이있다 :

그래서, 당신이 당신의 주소를 16 비트 값을 사용할 수 있습니다 "모든 유효 주소는 데이터 공간 내에서 바이트 16 비트 폭과 점입니다." 나는 당신의 업데이트에도 약간 혼란 스럽다. SPLIM은 값을 설정하는 레지스터이며 그 값은 스택의 크기를 제한합니다.나는 당신의 SPLIMIT의 값이 무엇인지 모르겠지만, W15는 실제 스택 포인터 레지스터와 스택의 상단에 주소가 저장되어있는 값입니다

는 "스택이있다 스택 포인터의 경우 과 연관된 포인터 제한 레지스터 (SPLIM) SPLIM이 재설정에서 초기화되지 않음 모든 스택 작업이 워드로 정렬되어야하므로 스택 포인터의 경우와 마찬가지로 SPLIM <> 이 강제로 '0'으로 설정됩니다. W15를 소스 또는 목적지 포인터로 사용하여 유효 주소 (EA)가 일 때마다 생성 된 주소 ted는 과 SPLIM의 값을 비교합니다. 스택 포인터 (W15)과 SPLIM 레지스터의 내용이 같고 밀어 넣기 작업을 수행하면 스택 오류 트랩이 이되지 않습니다.는 "

마지막으로, 스택은 SPLIM까지 사용 가능한 가장 낮은 SRAM 주소 값에서 성장. 나는 합리적인 뭔가에 SPLIM 값을 설정 제안 할 것이다 그래서 (이 test how much room you need for your stack에 가장 좋은 것입니다 있지만)의 512 바이트를 가정 해 봅시다.

이 특정 스택은 위쪽으로 커지기 때문에 스택 제한에 대해 추가 한 내용과 0x1000이 될 테스트를 0x0800부터 시작합니다. 이렇게하면 스택 영역에 대해 걱정할 필요가 없습니다.

위의 내용을 감안할 때 여기 내가 어떻게 행동하겠습니까? 이거.

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

내 코드는 아마 약간의 오류 (편집 주시기)가 확신 그래서 돌진 조금이었다, 그러나 희망이 바른 길에 당신을 얻을 도움이됩니다!

+0

이것은 많은 도움을 주며 대부분 작동합니다.현재 오류가있는 곳을보기 위해 디버깅 중입니다.하지만 원래는 훨씬 간결한 코딩이 필요합니다. – ThomSirveaux

+0

그래서 좀 더 파고 들었고'SPLIMIT'은 사실 다른 IOMap 파일에서 수동으로 정의한'SPLIM'입니다. 코드에서 빼내고 여기에서 'SPLIM'을 사용하는 방법에 대해 알아 보겠습니다. – ThomSirveaux

+0

좋은 소리, 나는 이것이 정말로 당신을 위해 일하기를 바란다. –