처음 몇 가지 배경. 어떤 이유로 든 펌웨어가 충돌 할 때 (예 : 스택 오버플로, 손상된 함수 포인터 ...) 어딘가로 점프하여 일부 코드 실행을 시작할 수 있습니다. 조만간 워치 독이 재설정 될 것입니다. MCU가 리셋되고 다시 정상적으로 돌아옵니다. 그렇지 않으면 ...우발적 인 펌웨어 덮어 쓰기 방지
플래시 (예 : 부트 로더)에 쓰는 코드는 어떻게됩니까? 이제 우연히 플래시 쓰기 코드로 직접 건너 뛰어 모든 검사를 건너 뛸 수 있습니다. 워치 독이 껍질을 벗기기 전에 손상된 펌웨어로 끝납니다. 이것은 정확히 나에게 일어난 일이다.
이제 어떤 사람들은 우리가 코드 작성에 뛰어 들었던 루트 버그를 수정한다고 말할 수 있습니다. 글쎄, 당신이 개발할 때 당신은 끊임없이 코드를 변경하고 있습니다. 현재 그곳에 그런 버그가 없다고해도 내일이있을 것입니다. 게다가, 어떤 코드도 버그가 없다 - 적어도 내 것이 아니다.
그래서 지금 나는 어떤 종류의 교차 검사를하고 있습니다. 나는 'wen'이라는 변수를 가지고 있는데 보통의 수표 (예 : 목적지가 유효한지 확인) 전에 0xa5로 설정합니다. 그런 다음 실제 지우기 또는 쓰기를 수행하기 전에 'wen'이 실제로 0xa5로 설정되어 있는지 확인합니다. 그렇지 않으면 우리가 실수로 글쓰기 코드로 뛰어 들었음을 의미합니다. 쓰기가 완료되면 'wen'이 지워집니다. C에서이 작업을 수행했으며 제대로 작동했습니다. 그러나 SPMCR 레지스터에 쓸 때까지 'wen'에 대한 최종 점검에서 나온 지침이 거의 없기 때문에 약간의 이론적 인 기회가 발생할 수 있습니다.
이제 SPMCR에 대한 쓰기와 SPM 명령어 사이에이 검사를 어셈블리에 넣음으로써이 기능을 향상시키고 싶습니다.
__asm__ __volatile__
(
"lds __zero_reg__, %0\n\t"
"out %1, %2\n\t"
"ldi r25, %3\n\t"
"add __zero_reg__, r25\n\t"
"brne spm_fail\n\t"
"spm\n\t"
"rjmp spm_done\n\t"
"spm_fail: clr __zero_reg__\n\t"
"call __assert\n\t"
"spm_done:"
:
: "i" ((uint16_t)(&wen)),
"I" (_SFR_IO_ADDR(__SPM_REG)),
"r" ((uint8_t)(__BOOT_PAGE_ERASE)),
"M" ((uint8_t)(-ACK)),
"z" ((uint16_t)(adr))
: "r25"
);
내일은 코드를 사용해 본적이 없습니다. 어떤 문제가 보이니? 어떻게 그런 문제를 해결할 수 있습니까?
예, 쓰기가 완료되면 wen이 지워집니다. 이 __assert를 호출하면 실제로는 워치 독 재설정이 트리거되고 (트리거 된 내용에 대한 정보가 기록됩니다). 사람들이 실제로 그런 접근법을 사용한다는 소식을 듣고 기쁜 마음입니다. – Stefan