2016-06-21 5 views
2

여기에 명백한 내용이 누락되어 있는지 확실하지 않지만 다른 어느 누구도 Cortex M0 + 또는 Cortex M 범위와 관련된 문제를 경험 한 경험이 없습니다. 슬립 모드에서 깨어 난 후 스레드 모드에서 다소 임의의 위치로 ISR합니다 (예 : WFI 명령어 아래 줄로 돌아 가지 않음). 그것은 for 루프의 중간이나 함수의 중간과 같이 코드의 중간에서 일어나는 것처럼 보입니다. 나는 ATSAMD218A 마이크로 컨트롤러를 사용하고 있는데 내가 문제를 분리하려고 시도했습니다 다음과 같은 발견했습니다 7 아트멜 Studio의 디버거를 사용하고 있습니다 :잠자기 중단 후 Cortex M0 +가 스레드 모드에서 잘못된 위치로 돌아갑니다.

장치가 잠들게 될 때에만 발생
  • 때 장치가 깨어있는 동안 장치가 인터럽트되면 ISR은 항상 올바른 위치로 되돌아갑니다.
  • ISR은 코드에서 해당 기능이나 코드 부분을 주석 처리하면 항상 잘못된 (잘못된) 위치로 되돌아갑니다.
  • 지연 및 NOP를 삽입하지 못했습니다. 그것은 타이밍 관련 또는 클럭 사이클 관련이 있지만 여전히 (잘못된) 위치로 항상 돌아갑니다
  • 나는 Arduino 인터럽트 라이브러리뿐만 아니라 직접 레지스터 액세스를 사용하여 인터럽트 구현을 시도했습니다.
  • ISR이가 'BX LR'명령어로 분기하도록되어있는라고, 종료 직전에, 디버깅하는 동안 조립 설명서 보면서 그것은 모두 유휴 대기 모드 (수면과 깊은 수면)
  • 발생 링크 레지스터. 링크 레지스터에는 반환 동작을 나타내는 EXC_RETURN이라는 값이 있는데,이 경우에는 0xFFFFFFF9 (스레드 모드로 돌아 가기)입니다. 그러나 어디서나 반환되는 실제 메모리 주소를 찾을 수는 없습니다. 메모리 주소가 코어 레지스터 R0-R15에 없습니다.

저는 Cortex M0 + 일반 사용자 가이드뿐만 아니라 ARMv6 아키텍처 참조 설명서도 읽었습니다. 무슨 일이 벌어지고 있는지, 그리고 어떤 디버깅 제안이 많이 들었을 지 확신 할 수 없습니다. 누구든지 Cortex M 시리즈의 예외 처리를 더 잘 이해하고 있으며 ISR 이후 스레드 모드가 반환하는 메모리 주소를 찾기 위해 올바른 방향으로 나를 안내 할 수 있습니다. 원하는 경우 코드를 제공 할 수 있지만 루프 만 계산하고 잠자기 한 다음 깨우면 문제가 발생하는 간단한 코드 조각도 제공 할 수 있습니다.

수정 아래 관련 코드를 추가했습니다. 여전히 문제를 일으키는 가장 많이 제거 된 버전입니다. RTC 코드 기능을 포함하지 않았습니다 (DS3231RTC 라이브러리 사용). 나는 효과가 없다고 확신합니다. 내가 더 많이 올려야한다고 생각하면 알려주세요.

void configInterrupt(void){ 
    NVIC_DisableIRQ(EIC_IRQn); 
    NVIC_ClearPendingIRQ(EIC_IRQn); 
    NVIC_SetPriority(EIC_IRQn, 0); 
    NVIC_EnableIRQ(EIC_IRQn); 

    // Enable GCLK for IEC (External Interrupt Controller) 
    GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC)); 

    EIC->WAKEUP.reg |= (1 << 0); 
    EIC->CONFIG[0].reg |= 0x2;     // falling edge 
    pinConfig(16,INPUT,UP);      // custom 'pinMode' function 
    PORT->Group[0].PINCFG[16].bit.PMUXEN = 1; // enable peripheral muxing 
    PORT->Group[0].PMUX[8].bit.PMUXE = 0x0;  // function A (EIC) = 0x0 
    EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << 0); 
    EIC->CTRL.bit.ENABLE = 1; 
} 

void EIC_Handler(void){ 
    RTC_FLAG = 1;   // my debug breakpoint is here, at this point the stack has already been pushed and I can see the PC value that will be popped off 
    int_count++; 
    EIC->INTFLAG.reg = 1 << 0; 
} 

void setup() { 
    configInterrupt();     
    configureRTC(); 
    RTC_FLAG = 1; 
} 

void loop() { 
    if (RTC_FLAG == 1) { 
    RTC_FLAG = 0; 
    setNextAlarm(); 
    } 

    for (int i = 0 ; i <= WINDOW-1 ; i++) { 
     String data = ""; 

     rawVal = 0;  // data gets read from sensor here (stripped) 
     data += String(rawVal); 
     data += ","; 

     distance = 0; // distance calculated from rawVal here (stripped) 
     data += String(distance); 
     data += ","; 

     mean = 0;  // mean calculated in a function here (stripped) 
     data += String(mean); 
     data += ","; 

     data += String(int_count); // ISR returns here 
     // Data gets written to file here (stripped) 
} 

    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 
    __DSB(); 
    __WFI(); 
} 
+0

사용중인 코드와 실패한 지점을 게시 할 수 있습니까? –

+1

_ "어디에서든지 반환되는 실제 메모리 주소를 찾을 수는 없습니다."- ARMv6-M ARM의 B1.5.6 "예외 항목 동작"을 참조하십시오. 그것은 스택에 있습니다. ISR 코드는 어떻게 생겼습니까? – Notlikethat

+0

나는이 장치가 아마도 칩 일일 가능성은 의심 스럽지만, 장치가 잠자기 될 때의 모든 것에 특별한 초점을 둔 장치 설명서를 읽을 필요가 있다고 생각합니다.어떻게, 어디서 어떻게 잠들 수있는 지에 대한 권장 사항이있는 경우 보존되지 않은 것은 무엇입니까? –

답변

0

Atmel ASF 프레임 워크를 사용하여 동일한 스 니펫을 구현하려고하면 API 세트와 레지스터 순서를 살펴보십시오. 그들은 또한 보통 에라타를 참조하고 해결안을 구현할 것입니다.

저전력 예제 프로젝트를로드하면 전원 모드가 전환되고 xplained board button press가 활성화됩니다. 보드에서 모드간에 전환이 가능하다면 그 부분이 아님을 알 수 있습니다. 웨이크 핀을 하드웨어에 맞게 움직여야 할 수도 있습니다.