|
Кэширование записи в RAM в LPC2478? |
|
|
|
Oct 20 2015, 11:26
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 23-12-10
Пользователь №: 61 816

|
Собственно при отладке программы наблюдаю спецэффекты, из которых напрашивается вывод о наличии этого самого кэширования. Оно действительно есть? Если да, то где про него почитать? По ARM Architecture Reference Manual у меня создалось впечатление, что кэш присутствует у процессоров c MMU либо MPU, а разве LPC2478 к таким относится? В user manual'е на сам МК ни слова не нашел про это.
Сообщение отредактировал murug - Oct 20 2015, 11:30
|
|
|
|
|
Oct 20 2015, 12:34
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 23-12-10
Пользователь №: 61 816

|
Цитата(aaarrr @ Oct 20 2015, 14:52)  У ARM7TDMI нет ни кэша ни буфера записи. Ну я это подозревал. Тогда придется изложить, что же я наблюдаю. Код такой В *.h-файле: Код __no_init volatile unsigned long ForceReprogrammingSignature @ 0x40008000; В *.cpp-файле функция: Код void ForceReprogramming(bool Monopoly) { ForceReprogrammingSignature = 0x085D0B75; // asm("nop"); // маленькая задержка в пять ассемблерных команд - если раскомментировать, не помогает (возвращается старое значение) // asm("nop"); // asm("nop"); // asm("nop"); // asm("nop"); // volatile unsigned long x = ForceReprogrammingSignature; // чтение (в ассемблере две команды) - если раскомментировать, помогает (сохраняется записанное значение)
// vTaskDelay(10/portTICK_RATE_MS); // большая задержка в 10 мс - если раскомментировать, помогает (сохраняется записанное значение)
if (Monopoly) __disable_interrupt(); // при Monopoly == true запрещаем прерывания
PCLKSEL0_bit.PCLK_WDT = 1; // далее взводим WDT WDTC = CCLK / 4 * 5; // на 5 секунд WDMOD_bit.WDEN = 1; WDMOD_bit.WDRESET = 1; WDCLKSEL_bit.WDSEL = 1; WDFEED = 0xAA; WDFEED = 0x55;
if (Monopoly) // при Monopoly == true из функции не возвращаемся while (1); } Так вот, изначально в ForceReprogrammingSignature некое значение, назовем его "старым значением". Далее разные варианты: 1. Вызываем ForceReprogramming(false), она записывает в ForceReprogrammingSignature сигнатуру 0x085D0B75, назовем это "записанное значение", запускает WDT, возвращается, через 5 секунд программа перезапускается, видим в ForceReprogrammingSignature "записанное значение", все ок, вопросов нет. 2. Вызываем ForceReprogramming( true), она записывает в ForceReprogrammingSignature сигнатуру, без задержки запрещает прерывания (тем самым в частности останавливает планировщик FreeRTOS), запускает WDT, виснет в бесконечном цикле, через 5 секунд программа перезапускается, видим в ForceReprogrammingSignature "старое значение", офигеваем. 3. Вызываем ForceReprogramming(true) с раскомментированной задержкой на 10 мс, она записывает в ForceReprogrammingSignature сигнатуру, через 10 мс запрещает прерывания, запускает WDT, виснет в бесконечном цикле, через 5 секунд программа перезапускается, видим в ForceReprogrammingSignature "сохраненное значение". 4. Вызываем ForceReprogramming(true) с закомментированной задержкой на 10 мс, но с раскомментированным чтением, она записывает в ForceReprogrammingSignature сигнатуру, тут же считывает ее (две ассемблерные команды), запускает WDT, виснет в бесконечном цикле, через 5 секунд программа перезапускается, видим в ForceReprogrammingSignature "сохраненное значение". 5. Вызываем ForceReprogramming(true) с закомментированными задержкой на 10 мс и чтением, но с раскомментированной задержкой из пяти nop'ов, она записывает в ForceReprogrammingSignature сигнатуру, выполняет 5 пустых команд, запускает WDT, виснет в бесконечном цикле, через 5 секунд программа перезапускается, видим в ForceReprogrammingSignature "старое значение". Вот и создается такое впечатление, как будто оператор Код ForceReprogrammingSignature = 0x085D0B75; пишет физически в кэш, и если после этого сразу отключить прерывания, то значение из кэша не успевает сброситься в "настоящий" RAM, поэтому после перезагрузки по WDT снова читаем оттуда старое значение. Звучит бредово, поэтому ищу другую версию )
Сообщение отредактировал murug - Oct 20 2015, 12:56
|
|
|
|
|
Oct 20 2015, 12:58
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(murug @ Oct 20 2015, 15:34)  Вот и создается такое впечатление, как будто оператор Код ForceReprogrammingSignature = 0x085D0B75; пишет физически в кэш, и если после этого сразу отключить прерывания, то значение из кэша не успевает сброситься в "настоящий" RAM, поэтому после перезагрузки по WDT снова читаем оттуда старое значение. Звучит бредово, поэтому ищу другую версию ) А Вы проверяли в листинге наличие записи для ситуации, когда значение не меняется? Все это больше похоже на "потерянный" квалификатор volatile.
|
|
|
|
|
Oct 20 2015, 13:12
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 23-12-10
Пользователь №: 61 816

|
Цитата(aaarrr @ Oct 20 2015, 15:58)  А Вы проверяли в листинге наличие записи для ситуации, когда значение не меняется? Все это больше похоже на "потерянный" квалификатор volatile. Согласен, похоже. Однако проверял - и код для записи присутствует, вот такой: Код MOV R1,#+1073741824 ORR R1,R1,#0x8000 LDR R2,??DataTable8_1;; 0x85d0b75 STR R2,[R1, #+0] во всех вариантах.
Сообщение отредактировал murug - Oct 20 2015, 13:13
|
|
|
|
|
Oct 20 2015, 14:30
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 23-12-10
Пользователь №: 61 816

|
Цитата(aaarrr @ Oct 20 2015, 16:25)  Можно все же увидеть листинг? Как-то уж очень чудесато это выглядит. Целиком функция, в первом случае работает корректно (это с заплаткой в виде чтения), во втором - нет. Код \ In section .text, align 4, keep-with-next 127 void ForceReprogramming(bool Monopoly) 128 { \ ForceReprogramming: \ 00000000 0xE24DD004 SUB SP,SP,#+4 129 ForceReprogrammingSignature = FORCE_REPROGRAMMING_SIGNATURE; \ 00000004 0xE3A01440 MOV R1,#+1073741824 \ 00000008 0xE3811C80 ORR R1,R1,#0x8000 \ 0000000C 0x........ LDR R2,??DataTable8_1 ;; 0x85d0b75 \ 00000010 0xE5812000 STR R2,[R1, #+0] 130 volatile unsigned long x = ForceReprogrammingSignature; // заплатка от непонятного бага с возвращением старого значения после сброса по WDT, см. http://electronix.ru/forum/index.php?showtopic=131171 \ 00000014 0xE5911000 LDR R1,[R1, #+0] \ 00000018 0xE58D1000 STR R1,[SP, #+0] 131 132 if (Monopoly) \ 0000001C 0xE3500000 CMP R0,#+0 \ 00000020 0x0A000002 BEQ ??ForceReprogramming_0 133 __disable_interrupt(); \ 00000024 0xE10F1000 MRS R1,CPSR \ 00000028 0xE38110C0 ORR R1,R1,#0xC0 \ 0000002C 0xE121F001 MSR CPSR_c,R1 134 135 PCLKSEL0_bit.PCLK_WDT = 1; \ ??ForceReprogramming_0: \ 00000030 0x........ LDR R1,??DataTable8_2 ;; 0xe01fc1a8 \ 00000034 0xE5912000 LDR R2,[R1, #+0] \ 00000038 0xE3C22003 BIC R2,R2,#0x3 \ 0000003C 0xE3822001 ORR R2,R2,#0x1 \ 00000040 0xE5812000 STR R2,[R1, #+0] 136 WDTC = CCLK / 4 * 5; // на 2 секунды \ 00000044 0xE3A014E0 MOV R1,#-536870912 \ 00000048 0x........ LDR R2,??DataTable8_3 ;; 0x55d4a80 \ 0000004C 0xE5812004 STR R2,[R1, #+4] 137 WDMOD_bit.WDEN = 1; \ 00000050 0xE5912000 LDR R2,[R1, #+0] \ 00000054 0xE3822001 ORR R2,R2,#0x1 \ 00000058 0xE5812000 STR R2,[R1, #+0] 138 WDMOD_bit.WDRESET = 1; \ 0000005C 0xE5912000 LDR R2,[R1, #+0] \ 00000060 0xE3822002 ORR R2,R2,#0x2 \ 00000064 0xE5812000 STR R2,[R1, #+0] 139 WDCLKSEL_bit.WDSEL = 1; \ 00000068 0xE5912010 LDR R2,[R1, #+16] \ 0000006C 0xE3C22003 BIC R2,R2,#0x3 \ 00000070 0xE3822001 ORR R2,R2,#0x1 \ 00000074 0xE5812010 STR R2,[R1, #+16] 140 WDFEED = 0xAA; \ 00000078 0xE3A020AA MOV R2,#+170 \ 0000007C 0xE5812008 STR R2,[R1, #+8] 141 WDFEED = 0x55; \ 00000080 0xE3A02055 MOV R2,#+85 \ 00000084 0xE5812008 STR R2,[R1, #+8] 142 143 if (Monopoly) \ 00000088 0xE3500000 CMP R0,#+0 \ 0000008C 0x0A000000 BEQ ??ForceReprogramming_1 144 while (1); \ ??ForceReprogramming_2: \ 00000090 0xEAFFFFFE B ??ForceReprogramming_2 145 } \ ??ForceReprogramming_1: \ 00000094 0xE28DD004 ADD SP,SP,#+4 ;; stack cleaning \ 00000098 0xE12FFF1E BX LR ;; return \ 0000009C REQUIRE ForceReprogrammingSignature \ 0000009C REQUIRE _A_PCLKSEL0 \ 0000009C REQUIRE WDTC \ 0000009C REQUIRE _A_WDMOD \ 0000009C REQUIRE _A_WDCLKSEL \ 0000009C REQUIRE _A_WDFEED Код \ In section .text, align 4, keep-with-next 127 void ForceReprogramming(bool Monopoly) 128 { 129 ForceReprogrammingSignature = FORCE_REPROGRAMMING_SIGNATURE; \ ForceReprogramming: \ 00000000 0xE3A01440 MOV R1,#+1073741824 \ 00000004 0xE3811C80 ORR R1,R1,#0x8000 \ 00000008 0x........ LDR R2,??DataTable8_1 ;; 0x85d0b75 \ 0000000C 0xE5812000 STR R2,[R1, #+0] 130 // volatile unsigned long x = ForceReprogrammingSignature; // заплатка от непонятного бага с возвращением старого значения после сброса по WDT, см. http://electronix.ru/forum/index.php?showtopic=131171 131 132 if (Monopoly) \ 00000010 0xE3500000 CMP R0,#+0 \ 00000014 0x0A000002 BEQ ??ForceReprogramming_0 133 __disable_interrupt(); \ 00000018 0xE10F1000 MRS R1,CPSR \ 0000001C 0xE38110C0 ORR R1,R1,#0xC0 \ 00000020 0xE121F001 MSR CPSR_c,R1 134 135 PCLKSEL0_bit.PCLK_WDT = 1; \ ??ForceReprogramming_0: \ 00000024 0x........ LDR R1,??DataTable8_2 ;; 0xe01fc1a8 \ 00000028 0xE5912000 LDR R2,[R1, #+0] \ 0000002C 0xE3C22003 BIC R2,R2,#0x3 \ 00000030 0xE3822001 ORR R2,R2,#0x1 \ 00000034 0xE5812000 STR R2,[R1, #+0] 136 WDTC = CCLK / 4 * 5; // на 2 секунды \ 00000038 0xE3A014E0 MOV R1,#-536870912 \ 0000003C 0x........ LDR R2,??DataTable8_3 ;; 0x55d4a80 \ 00000040 0xE5812004 STR R2,[R1, #+4] 137 WDMOD_bit.WDEN = 1; \ 00000044 0xE5912000 LDR R2,[R1, #+0] \ 00000048 0xE3822001 ORR R2,R2,#0x1 \ 0000004C 0xE5812000 STR R2,[R1, #+0] 138 WDMOD_bit.WDRESET = 1; \ 00000050 0xE5912000 LDR R2,[R1, #+0] \ 00000054 0xE3822002 ORR R2,R2,#0x2 \ 00000058 0xE5812000 STR R2,[R1, #+0] 139 WDCLKSEL_bit.WDSEL = 1; \ 0000005C 0xE5912010 LDR R2,[R1, #+16] \ 00000060 0xE3C22003 BIC R2,R2,#0x3 \ 00000064 0xE3822001 ORR R2,R2,#0x1 \ 00000068 0xE5812010 STR R2,[R1, #+16] 140 WDFEED = 0xAA; \ 0000006C 0xE3A020AA MOV R2,#+170 \ 00000070 0xE5812008 STR R2,[R1, #+8] 141 WDFEED = 0x55; \ 00000074 0xE3A02055 MOV R2,#+85 \ 00000078 0xE5812008 STR R2,[R1, #+8] 142 143 if (Monopoly) \ 0000007C 0xE3500000 CMP R0,#+0 \ 00000080 0x0A000000 BEQ ??ForceReprogramming_1 144 while (1); \ ??ForceReprogramming_2: \ 00000084 0xEAFFFFFE B ??ForceReprogramming_2 145 } \ ??ForceReprogramming_1: \ 00000088 0xE12FFF1E BX LR ;; return \ 0000008C REQUIRE ForceReprogrammingSignature \ 0000008C REQUIRE _A_PCLKSEL0 \ 0000008C REQUIRE WDTC \ 0000008C REQUIRE _A_WDMOD \ 0000008C REQUIRE _A_WDCLKSEL \ 0000008C REQUIRE _A_WDFEED
|
|
|
|
|
Oct 21 2015, 04:36
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(murug @ Oct 20 2015, 18:34)  2. Вызываем ForceReprogramming(true), она записывает в ForceReprogrammingSignature сигнатуру, без задержки запрещает прерывания (тем самым в частности останавливает планировщик FreeRTOS), запускает WDT, виснет в бесконечном цикле, через 5 секунд программа перезапускается, видим в ForceReprogrammingSignature "старое значение", офигеваем. И что? Очевидно, что startup инитит эту Вашу ForceReprogramming неким значением, либо эта область используется ROM-загрузчиком, либо используется самим startup на какие-то его нужды, ... Эксперимент проведён некорректно. Читайте юзермануал на предмет: какие области используются ROM-загрузчиком. И ставьте бряк не в функции main(), а сразу после вектора сброса. Чудес не бывает.
|
|
|
|
|
Oct 21 2015, 05:55
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 23-12-10
Пользователь №: 61 816

|
Цитата(jcxz @ Oct 21 2015, 07:36)  И что? Очевидно, что startup инитит эту Вашу ForceReprogramming неким значением, либо эта область используется ROM-загрузчиком, либо используется самим startup на какие-то его нужды, ... Эксперимент проведён некорректно. Читайте юзермануал на предмет: какие области используются ROM-загрузчиком. И ставьте бряк не в функции main(), а сразу после вектора сброса. Чудес не бывает. По-моему Вы невнимательно читали. В переменной ForceReprogrammingSignature восстанавливается значение, которое там было до вызова функции ForceReprogramming. Каким бы это значение не было. Ну и помимо того: 1. переменная помечена __no_init; 2. секция, в которую она помещена, указана для линкера do not initialize; 3. бряк ставил на первые выполняемые ассемблерные команды, уже там видел в отладчике "старое" значение в ForceReprogrammingSignature; 4. пробовал размещать переменную по двум разным адресам, результат один и тот же; 5. ну и в конце концов в случае описанных заплаток-то значение сохраняется. Цитата(aaarrr @ Oct 20 2015, 23:34)  Такое не работать просто не может, а в чудеса не очень верится. Что будет, если записать несколько чисел подряд? Попробую. Кстати, вспомнил - под отладчиком видел что внутри функции сигнатура 0x085D0B75 в переменную кладется. А вот после перезагрузки в самом начале cstartup.s - уже снова старое значение.
|
|
|
|
|
Oct 21 2015, 06:09
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 23-12-10
Пользователь №: 61 816

|
Цитата(zltigo @ Oct 21 2015, 09:00)  То есть весь этот вынос мозга Вы устраиваете по причине того, что сие оказывается "видит" отладчик?! Не совсем. То, что в ячейке "старое" значение, я вижу и без отладчика, но смотрю уже не на этапе выполнения cstartup.s, а после, когда все инициализации прошли и работает графический интерфейс у программы.
|
|
|
|
|
Oct 21 2015, 07:10
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (murug @ Oct 21 2015, 09:09)  Не совсем. То, что в ячейке "старое" значение, я вижу и без отладчика, но смотрю уже не на этапе выполнения cstartup.s, а после, когда все инициализации прошли и работает графический интерфейс у программы. Тем неменее 1) Никаких отладчиков для разборок с эффектом НЕ применять. 2) Никаких отображений далеко после старта через графический интерефейс - тоже. Тупо и просто в startup НИЧЕГО сложнее, чем изменить состояние какого-нибудь пина не предпринимать. Причем изменеие состояния пина обязательно контролировать по времени от снятия сброса с контроллера.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 21 2015, 07:35
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 23-12-10
Пользователь №: 61 816

|
Цитата(zltigo @ Oct 21 2015, 10:10)  Тем неменее 1) Никаких отладчиков для разборок с эффектом НЕ применять. 2) Никаких отображений далеко после старта через графический интерефейс - тоже. Тупо и просто в startup НИЧЕГО сложнее, чем изменить состояние какого-нибудь пина не предпринимать. Причем изменеие состояния пина обязательно контролировать по времени от снятия сброса с контроллера. Такие рекомендации исходя из предположения, что значение в ячейке все-таки какой-то программной инициализацией меняется, правильно я Вас понимаю? Цитата(aaarrr @ Oct 20 2015, 23:34)  Такое не работать просто не может, а в чудеса не очень верится. Что будет, если записать несколько чисел подряд? Попробовал писать подряд несколько разных значений. Получается, что после рестарта имеем в ячейке значение, которое записывалось предпоследней записью. Это если без последующего чтения, а если с ним - то сохраняется с последней записи. В ассемблерном листинге последняя запись безукоризненно присутствует наряду со всеми.
|
|
|
|
|
Oct 21 2015, 07:44
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(murug @ Oct 21 2015, 10:35)  Попробовал писать подряд несколько разных значений. Я имел в виду запись не нескольких значений в одну ячейку памяти, а запись нескольких слов в память последовательно. Цитата(zltigo @ Oct 21 2015, 10:10)  1) Никаких отладчиков для разборок с эффектом НЕ применять. Вот да, лучше отключить его вообще на это время.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|