|
Кэширование записи в 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) Никаких отладчиков для разборок с эффектом НЕ применять. Вот да, лучше отключить его вообще на это время.
|
|
|
|
|
Oct 21 2015, 08:03
|
Участник

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

|
Цитата(gerber @ Oct 21 2015, 10:45)  Классический механизм "posted write" ("отложенная запись"), всё правильно, процессор имеет право не исполнять физическую запись в устройство (в данном случае - это оперативная память) до следующей операции с ним, перед чтением вся очередь записей должна быть исполнена. Вот этому верю, чего-то подобного и ожидал. Встает вопрос, однако, где можно найти так сказать официальную инфу о наличии такой штуки в ARM7TDMI?
|
|
|
|
|
Oct 21 2015, 08:11
|

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

|
QUOTE (murug @ Oct 21 2015, 10:35)  Такие рекомендации исходя из предположения, что значение в ячейке все-таки какой-то программной инициализацией меняется, правильно я Вас понимаю? Да. Такие изменения делает какой-то конкретный кусок кода. Противное было-бы чисто чудом. Чудес в 21 веке не бывает. Я лично использую подобный подход - занесение массива данных и считывания его после перезапуска, достаточно широко. Например, в любом моем загрузчике используется область памяти для сохранения картины exception. Тоже пишется массив, записывается сигнатура наличия данных. При запуске основной программы распечатывается. Нималейших проблем, в том числе и на LPC2468. А чем вызвано фиксированное и причем в очень странном месте - середине памяти месторасположение этой сигнатуры? Нет, это как бы не криминал, но странно. Официально нельзя располагать подобное только в прследних 32 байтах памяти, которые используются заводским загрузчиком. QUOTE (murug @ Oct 21 2015, 11:03)  Встает вопрос, однако, где можно найти так сказать официальную инфу о наличии такой штуки в ARM7TDMI? Нет такой штуки у несчастного ARM7. Не говоря уже о том, что после этой записи контроллер по любому у Вас производит неоднократные записи при манипуляции с WD.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 21 2015, 08:15
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(murug @ Oct 21 2015, 11:03)  Встает вопрос, однако, где можно найти так сказать официальную инфу о наличии такой штуки в ARM7TDMI? В ядре ничего подобного нет. Буфер записи мог бы быть у контроллера встроенной SRAM, но: - Об этом нигде не говорится - Нет смысла в его наличии
|
|
|
|
|
Oct 21 2015, 08:48
|
Участник

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

|
Цитата(zltigo @ Oct 21 2015, 11:11)  Да. Такие изменения делает какой-то конкретный кусок кода. Противное было-бы чисто чудом. Я бы понял, если бы этот кусок какое-то фиксированное значение в ячейку заносил. Но он угадывает, что там было до последней записи... Что по-моему является еще бОльшим чудом ) Цитата(zltigo @ Oct 21 2015, 11:11)  Я лично использую подобный подход - занесение массива данных и считывания его после перезапуска, достаточно широко. А такая ситуация, что после последней записи и перед перезагрузкой нет обращений к on-chip static RAM, у Вас возникает? Цитата(zltigo @ Oct 21 2015, 11:11)  А чем вызвано фиксированное и причем в очень странном месте - середине памяти месторасположение этой сигнатуры? Нет, это как бы не криминал, но странно. Официально нельзя располагать подобное только в прследних 32 байтах памяти, которые используются заводским загрузчиком. Это уже в процессе экспериментов туда переместил, изначально как раз перед упомянутыми 32 байтами было. Цитата(zltigo @ Oct 21 2015, 11:11)  Нет такой штуки у несчастного ARM7. Не говоря уже о том, что после этой записи контроллер по любому у Вас производит неоднократные записи при манипуляции с WD. Эти записи в область AHB или APB peripherals, а не on-chip static RAM, видимо дело в этом. Вообще вроде удалось найти инфу (несколько зыбкую), что даже и кэш имеется: Вот здесь:Цитата Naming Conventions ... ARMx2z (e.g. ARM720T) indicates cache, MMU & Process ID support А что 2478 - это ARM720T - например вот здесь
|
|
|
|
|
Oct 21 2015, 09:13
|

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

|
QUOTE (murug @ Oct 21 2015, 11:48)  А такая ситуация, что после последней записи и перед перезагрузкой нет обращений к on-chip static RAM, у Вас возникает? Вообще-то сама "перезагрузка" это ВХОД В ЗАВОДСКОЙ загрузчик, где этих обращений явно хватает. Это раз. А то, что Ваши чудотворно действующие нопы это никак не обращение к памяти - это два. QUOTE А что 2478 - это ARM720T - например вот здесьА это ничего, что ПРОИЗВОДИТЕЛЬ конроллера пишет о своем изделии в Product data sheet - ARM7TDMI-S processor, running at up to 72 MHz
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 21 2015, 09:52
|

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

|
QUOTE (aaarrr @ Oct 21 2015, 12:24)  Ну, "перезагрузка" - это еще и сброс, который мог бы очистить буфер записи при его наличии. При наличии - да. Но его нет, а есть напротив куча команд - ну тот-же вечный цикл продолжающийся 5 секунд и команды в нем выпоняющиеся как-бы ничем не хуже несеольких нопов, которые типа "помогают". Вообще-то таинственные явления в NXP есть  - я не далее месяца тому назад в старом модернизируемом изделии на LPC2103 локализовал эффект, кода при работе SPI находящемся в режиме slave и тактирующимся софтовым мастером контроллер прерываний формировал нулевой вектор раз в несколько суток. Ничего из описанного в errata под этот эффект подогнать не удалось. Пришлось предпринимать близкие к шаманским действия  QUOTE (murug @ Oct 20 2015, 15:34)  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; А если к этому добавить: CODE WDFEED = 0xAA; WDFEED = 0x5A; то есть перезепуск без 5 секунд? И еще, инициализация WD и в случае Monopoly=FALSE должна производиться при запрещенном прерывании, ибо любое вкоинивание прерывания это мгновенный перезапуск.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 21 2015, 09:55
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zltigo @ Oct 21 2015, 15:45)  Вообще-то таинственные явления в NXP есть  - я не далее месяца тому назад в старом модернизируемом изделии на LPC2103 локализовал эффект, кода при работе SPI находящемся в режиме slave и тактирующимся софтовым мастером контроллер прерываний формировал нулевой вектор раз в несколько суток. Ничего из описанного в errata под этот эффект подогнать не удалось. Пришлось предпринимать боизкие к шаманским действия  Давно уже работал с LPC2378, но вроде смутно помнится, что был подобный баг в контроллере прерываний. И он был описан в еррата. И даже в соотв. порту uCOS было указано. Если это конечно он. Заключался он в том, что при чтении адреса вектора прерывания из VIC, мог считаться ноль - это ложное прерывание. Фрагмент моего ISR для IRQ где это проверяется: Код ISRirq: SUB LR, LR, #4 STMFD SP!, {R0-R3, R12, LR} MVN R1, #255 ;VICAddress LDR R0, [R1] CMP R0, #0 ;проверка на ложное IRQ STRNE R1, [R1] ;acknowlege IRQ MOVNE LR, PC BXNE R0 CMP R0, #0 LDMFDEQ SP!, {R0-R3, R12, PC}^;выйти если нет сис. вызовов ...
|
|
|
|
|
Oct 21 2015, 10:10
|
Участник

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

|
Цитата(zltigo @ Oct 21 2015, 12:13)  Вообще-то сама "перезагрузка" это ВХОД В ЗАВОДСКОЙ загрузчик, где этих обращений явно хватает. Это раз. А то, что Ваши чудотворно действующие нопы это никак не обращение к памяти - это два. Нет, я же написал, что нопы как раз не помогают. Цитата(zltigo @ Oct 21 2015, 12:13)  А это ничего, что ПРОИЗВОДИТЕЛЬ конроллера пишет о своем изделии в Product data sheet - ARM7TDMI-S processor, running at up to 72 MHz Полагал, что 720T и TDMI-S - понятия из разных классификаций, собственно из той же пдф, на которую давал ссылку - там указано, что 720T это частный случай ARM7TDMI-S. Ну я сразу написал, что инфа зыбкая. Цитата(zltigo @ Oct 21 2015, 12:52)  И еще, инициализация WD и в случае Monopoly=FALSE должна производиться при запрещенном прерывании, ибо любое вкоинивание прерывания это мгновенный перезапуск. О, действительно. Спасибо!
|
|
|
|
|
Oct 21 2015, 10:26
|
Знающий
   
Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088

|
Помимо ядра процессора с памятью может работать и периферия, посредством DMA, возможно, сразу несколько каналов. При отсутствии механизма "posted write" процессору после каждого запроса операции чтения/записи пришлось бы ожидать завершения транзакции, открытой каким-нибудь каналом DMA. С чтением ничего не поделаешь - придется ждать, т. к. продолжение программы без прочитанного значения бессмысленно. А запись на дальнейшее исполнение кода не влияет (до ближайшего чтения), поэтому глупо "стоять в очереди" и ждать, когда можно "записать и забыть". А не описан в руководстве на процессор он, видимо, потому, что имеет отношение скорее к внутренней шине типа AHB, APB, чем к самому ядру. Также как, например, механизм posted write на шине PCI - это фича PCI, а не процессора.
--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
|
|
|
|
|
Oct 27 2015, 12:22
|
Участник

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

|
Цитата(zltigo @ Oct 24 2015, 19:26)  Мда... есть в документации на 21xx, но нет (либо еще не найдено) на 24xx. Ну в любом случае вопрос можно считать закрытым. Спасибо всем, кстати )
|
|
|
|
|
Nov 16 2015, 02:53
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(aaarrr @ Oct 20 2015, 15:52)  У ARM7TDMI нет ни кэша ни буфера записи. У NXP есть - LPC288x. 8K кэша. Цитата(jcxz) Заключался он в том, что при чтении адреса вектора прерывания из VIC, мог считаться ноль - это ложное прерывание. Часто в векторе IRQ стоит что-то вроде LDR PC,[PC, #-xxx]. Оптимальнее будет ложный нулевой адрес "ловить" в ResetVector-е по значению младших пяти бит CPSR, равных режиму IRQ.
Сообщение отредактировал GetSmart - Nov 16 2015, 11:47
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Nov 16 2015, 12:13
|

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

|
QUOTE (jcxz @ Oct 21 2015, 11:55)  Давно уже работал с LPC2378, но вроде смутно помнится, что был подобный баг в контроллере прерываний. И он был описан в еррата. Посмотрел еще раз в свежайшие errata - увы, ничего подобного не описано. QUOTE И даже в соотв. порту uCOS было указано. Очень бы хотелось взглянуть на то, что в uCOS написано. Это было просто в исходниках откомментировано, или какой то документ? QUOTE Если это конечно он. Описанной ситуации соответствует. Явную заплатку не делал - стучал в бубен в месте опроса-сброса SPI прерывания. Но хотелось-бы явного понимания что надо делать. QUOTE (GetSmart @ Nov 16 2015, 04:53)  Часто в векторе IRQ стоит что-то вроде LDR PC,[PC, #-xxx]. Оптимальнее будет ложный нулевой адрес "ловить" в ResetVector-е по значению младших пяти бит CPSR, равных режиму IRQ. Делал подобное для локализации проблемы вылета, но просто возвратиться не подумал. Пожалуй это вариант.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Nov 16 2015, 13:30
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zltigo @ Nov 16 2015, 18:13)  Очень бы хотелось взглянуть на то, что в uCOS написано. Это было просто в исходниках откомментировано, или какой то документ? Я с LPC23xx последний раз работал уже неск. лет назад, а ещё раньше я переписал весь системный обработчик IRQ на свой собственный. Так что из оригинального там остались только комменты о проверке на ложное IRQ с соответствующим кодом. Надо старые архивы поднимать если там что-то сохранилось. Ну или скачать порт uCOS для ARM7 и посмотреть код стандартного обработчика IRQ. Документ, кстати, тоже был, находится гуглом по фразе "spurious interrupts": http://www.nxp.com/documents/application_note/AN10414.pdf
|
|
|
|
|
Nov 16 2015, 14:13
|

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

|
QUOTE (jcxz @ Nov 16 2015, 15:30)  Ну или скачать порт uCOS для ARM7 и посмотреть код стандартного обработчика IRQ. Хорошо. Посмотрю. Но если говорить об этом: QUOTE Документ, кстати, тоже был, находится гуглом по фразе "spurious interrupts": http://www.nxp.com/documents/application_note/AN10414.pdfТо это НЕ ТО о чем говорим. Заглушка на VIC Default Vector Address, естественно, стоит. То, что происходит, происходит по другому механизму - вектор считывается именно нулевой, хотя Default прописан. Вылетов по запрограммированному Default тоже можно добится, это я к тому, что эта ветка работает, но на ее фоне прилетает и нулевой вектор. Появилось при использовании SPI Slave.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Nov 17 2015, 04:56
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zltigo @ Nov 16 2015, 23:08)  Зашел на микриум. Скачал порт - для LPC23xx. Убийственный по объему обработчик, Ну что поделаешь - система прерываний ARM7 далеко не оптимальна для организации вытеснения задач и вложенных прерываний. Но ISR конечно там можно хорошо оптимизировать, что я и сделал. Цитата(zltigo @ Nov 16 2015, 23:08)  Кстати, действий при считывании нулевого вектора тоже никаких - даже ACK контроллеру не делают - просто вернулись и все. Ну и VICDefVectAddr они НЕ УСТАНАВЛИВАЮТ вообще, так что это объясняет впихивание во все их "макроме" еще и проверки вектора на NULL. Странно... Я по своему коду вижу, что ACK я даю на нулевой вектор также как на валидный, просто не вызываю никакой прикладной обработчик ISR. И проверка на NULL не в конце ISR, а в начале. Тем не менее множество наших счётчиков э-энергии на LPC2378 выпускаются уже несколько лет (уже наверное многие тысячи), работают в непрерывном круглосуточном режиме и проблем с прерываниями вроде не возникает. Сама проверка - ничего страшного - всего одна доп. команда CMP R0, #0.
|
|
|
|
|
Nov 17 2015, 07:55
|

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

|
QUOTE (jcxz @ Nov 17 2015, 06:56)  Ну что поделаешь - система прерываний ARM7 далеко не оптимальна для организации вытеснения задач и вложенных прерываний. Прямо противоположное мнение  . Просто вытеснение задач именно uCOS сделано конкретно через анус, ну а массовые вложеные вообще не нужны при операционке, тем более есть FIQ. То, как сделано у ARM7 так-же сделано у старших "A" кортексов явно заточеных под операционки, ну а для мелких "M" кортесов в которых справедливо предположили, что народ пойдет писать после всяких восьмибитовиков и в силе восьмибитовиков, сделали "удобный" NVIC. QUOTE Сама проверка - ничего страшного - всего одна доп. команда CMP R0, #0. На фоне ужасно огромого обработчика перывания, как у uCOS - несомненно да.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 6 2016, 09:51
|

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

|
Дошли руки. Заплатку на NULL вектор вставил по варианту GetSmart на вектор сброса: CODE __start_entry: push { r0 } mrs r0, cpsr and r0, r0, #MODE_MASK cmp r0, #IRQ_MODE bneq __start pop { r0 } b zero_vector_handler __start: Пытался всеми силами сэмулировать такой вылет, но как и ранее не удалось. Удается послать по этому пути только если явно для какого либо прерывания нагло прописать NULL вектор. При прописывании NULL вектора при возниконовении прерывания на официально документированный механизм заплатки через VICDefVectAddr не выходит. Так что смысл и в такой заплатке просмаривается не смотря на то, что ARM с NXP бьют себя пяткой в грудь и обещают, что установка VICDefVectAddr яко-бы решает проблемы неведомых прерываний. Теперь остается понаблюдать за устройством в реальных условиях, как оно будет себя более мягко себя вести.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 2 2016, 23:39
|
self made
   
Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795

|
Цитата(zltigo @ Feb 2 2016, 18:19)  К чему это было? Разговор не о EMC. Разговор был о кэшировании записи а.... ок. это on-chip memory... да, тогда мимо
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|