Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC2138, memcpy и DataAbort
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
esaulenka
Наткнулся на непонятную проблему...

Исходные данные:
Keil, компилятор - древний кейловский CARM, оптимизаций нет.
процессор LPC2138


Есть такой код (вопросы по оптимальности использования LDRB/STRB, перебрасывания регистров туда-сюда - к авторам библиотек к CARM)
CODE

0x000388F4 E59FC000 LDR R12,[PC]
0x000388F8 E12FFF1C BX R12
0x000388FC 00038901 DD 0x00038901
strlen:
0x00038900 2100 MOV R1,#0x00
0x00038902 E000 B 0x00038906
0x00038904 3101 ADD R1,#0x01
0x00038906 1C02 ADD R2,R0,#0
0x00038908 3001 ADD R0,#0x01
0x0003890A 7812 LDRB R2,[R2,#0x00]
0x0003890C 2A00 CMP R2,#0x00
0x0003890E D1F9 BNE 0x00038904
0x00038910 1C08 ADD R0,R1,#0
0x00038912 4770 BX LR

0x00038914 E59FC000 LDR R12,[PC]
0x00038918 E12FFF1C BX R12
0x0003891C 00038921 DD 0x00038921
memcpy:
0x00038920 B430 PUSH {R4-R5}
0x00038922 1C03 ADD R3,R0,#0
0x00038924 1C18 ADD R0,R3,#0
0x00038926 E005 B 0x00038934
0x00038928 1C0C ADD R4,R1,#0
0x0003892A 7825 LDRB R5,[R4,#0x00]
0x0003892C 1C04 ADD R4,R0,#0
0x0003892E 7025 STRB R5,[R4,#0x00]
0x00038930 3101 ADD R1,#0x01
0x00038932 3001 ADD R0,#0x01
0x00038934 1C14 ADD R4,R2,#0
0x00038936 3A01 SUB R2,#0x01
0x00038938 2C00 CMP R4,#0x00
0x0003893A D1F5 BNE 0x00038928
0x0003893C 1C18 ADD R0,R3,#0
0x0003893E BC30 POP {R4-R5}
0x00038940 4770 BX LR



вызываем
memcpy (0x40002390, 0x00038910, 0x10)

... и попадаем в DataAbort.

Содержимое регистров:
R0 = 0x0000008A
R1 = 0x00038911
R2 = 0x0000000D
R3 = 0x40002390
R4 = 0x0000008A
R5 = 0x0000001C
R13 (SP) = 0x40002524
R14 (LR) = 0x00038936
R15 (PC) = 0x00000010
SPSR = 0x00000030


Какая-то мистика.
memcpy (0x40002390, 0x00038920, 0x10)
memcpy (0x40002390, 0x00038900, 0x10)
- всё проходит нормально.
Если выполнять этот код по шагам, всё также проходит нормально.
Запускаем в обычном режиме - получите переход на 0x10...

Экспериментально установлено, что если дошагать до
0x00038926 E005 B 0x00038934
дальше всё работает. Если запустить на выполнение до этой строки, получаем ошибку.


Сделал тестовую функцию - она тоже работает нормально!
Да, она действительно работает, оптимизатор до неё не добрался.
Адреса менял - пофигу...
CODE

void Test (void)
{
char buff[128];
int ptr = 0x038910; // этот адрес менял уже из-под отладчика

while (1)
{
memcpy (buff, ptr, 16);
}

}


Собственно, вопрос. Что это было?!

Нарисовал CopyMem, которая копирует по 4 байта за раз - она работает хорошо. Но хочется разобраться...
aaarrr
Можно сказать только, что кто-то у Вас портит R0, и это не memcpy. Прерывания выключать пробовали?
esaulenka
Угу, портится R0 и STRB вполне законно вылетает.

Только вот всё остальное-то работает!

В частности, в том же самом месте эта memcpy нормально вызывается 0x3890 раз (собственно, считываем прошивку целиком кусочками по 16 байт в один и тот же буфер). И дальше нормально выполняется, если указатель руками переставить...

Прерывания выключать не пробовал, т.к. всё развалится. Хотя вот Test() вызывал до разрешения прерываний, оно работает.

Освобожусь чуток, постараюсь разобраться...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.