Jump to content

    

AVI-crak

Участник
  • Content Count

    251
  • Joined

  • Last visited

Everything posted by AVI-crak


  1. На случай аварий - системой уже предусмотрено несколько стандартных аппаратных прерываний разного уровня. От мягких программных, до жёстких системных. Собаку можно обработать программно, и успеть перевести внешнюю периферию в необходимое для выключение состояние. Например полностью блокировать внешний силовой драйвер мощных транзисторов, да и вообще отрубить всё питание. Чтение мимо адресного пространства BusFault - можно поймать отладчиком, вернуться в точку остановки кода, и найти сбойное место. Часто причиной сбоя является неисправность указателей, тогда приходится искать намного дольше. Модуль защиты MPU - на самом деле замечательная вещь, на M4-M7 без него никак. Дело в том что ядро обрабатывает программный код на конвейере, дополнительно - сам код собирается для внеочередного исполнения. GCC знает про MPU, и умеет использовать его настройки. Например для линейной области памяти управления почти всей периферией (0x40000000 - (0.5G)) - запрет кеша, сквозная запись, запрет обратной записи, запрет исполнения кода, ожидать выполнения физической записи. В этом случае состояние периферии будет меняться программой - как задумал пользователь, но не как удобно GCC. Дополнительно - конвейер команд будет сбрасываться при обнаружении обращения к области периферии - чтоб ни одна сволочь вперёд очереди не проскочила (типа я только спросить). Если при таких настройках выполнить переход на адреса периферии (исполнение программного кода) - то сработает прерывание MemManage_Handler. Оно является мягким, и его можно обработать возвратом в программный код с поиском ошибки. HardFault - являться жёстким отказом системы, его можно обработать ручным способом, и даже найти место сбоя - но невозможно исправить в реальном времени. Ну и всё скопом по порядку: Reset_Handler - стартовый адрес прошивки NMI_Handler - неизвестное прерывание Default_Handler, любое из неопределённых HardFault_Handler - отказы: шины, арбитра памяти, сбой чтения вектора прерываний. MemManage_Handler - ошибка доступа к памяти, срабатывание правил MPU BusFault_Handler - чтение/запись по недопустимому адресу UsageFault_Handler - прерывание специально для пользователя, можно оформить как критическую секцию часть прерываний от старших ARM процессоров вырезана тупым ржавым скальпелем, ещё не успело зарубцеваться SVC_Handler - крутое прерывание пользователя из разряда - пусть весь мир подождёт DebugMon_Handler - запуск кода отладчика на ядре мк в момент контрольной точки, остановка ядра после кода - для считывания данных отладчиком пусто PendSV_Handler - типа удобная функция для переключения контекста, я так не думаю SysTick_Handler - самый примитивный таймер во всей системе, он даже не полностью 32 бита. /* External Interrupts */ WWDG_IRQHandler - сторожевая собака, гавкает когда перестают ходить строем
  2. f7 h7 - имеют физику USB2.0 на кристалле чипа, внешняя физика не нужна. И кстати - достаточно шустро работает.
  3. Где именно вы умудряетесь нарушить алгоритм? 1 прочитать в ЛОКАЛЬНЫЕ переменные указатели кольцевого буфера 2 обработать данные (записать или прочитать), если таковые имеются 3 переписать ОДИН указатель по ЗАВЕРШЕНИЮ работы с данными. Прошу внимательно прочитать, и дать простой ответ под номером строки 1-2-3. При выходе из этого цикла данные записанные в буфер теряют актуальность. Не в том смысле что их можно портить, это больше похоже на лог, данные не актуальны в следующий момент времени. Например нельзя дописывать в буфер или прочитывать старое уже после выхода из полного цикла, данные теряют актуальность, и могут затереться другим процессом. Прервать алгоритм можно в любом месте, например прерыванием или переключением задач. Главное корректно его восстанавливать.
  4. Да это вообще не из этого мира. Часть инстала часов реального ремни. int rtc_initialize (void) { /* Enable PCLK to the RTC */ __set_PCONP(PCRTC); /* Start RTC with external XTAL */ RTC_CCR = 0x11; /* Stop PCLK to the RTC to reduce battery power consumption */ __clr_PCONP(PCRTC); return 1; } Я-ж говорил - всего один бит....
  5. Применимо к кортексу в целом - это запуск резервного домена питания. Домен связан с часами реального времени не только питанием, но и системной шиной. (или наоборот) В lpc это просто один бит, в stm больше движений - но и возможностей по более. Нужно смотреть документацию конкретно на этот узел от lpc, точнее под конкретный чип. Потому как BKPSRAM имеет питание 2,1в, и очень низкую частоту такта. Подать питание на память - это пол дела, транслятор уровня заметно кушает - и его не всегда держат в рабочем режиме. В данном случае транслятор уровня - это разрешение доступа к памяти. Нужен конкретный чип, без xxx.
  6. Да ёёёё. Кто-ж использует кольцевой буфер для физических устройств????? Для физики все (без исключения) применяют линейный буфер: одинарный или двойной - для одного!!! направления. Спокойно создаём сообщение, дожидаемся готовности физики, и пинаем дма. Всё, тайминги в порядке, процессорное время свободно, мозг никто не клюёт.
  7. Я не понимаю, как читающий может переписать чужой указатель??? Ну не успели выбрать все данные, или наоборот - положить всё что нужное в буфер. Конец света от этого не наступает, успеете сделать когда будет такая возможность. Не понимаю, зачем жопу рвать на британский флаг??? По поводу неуловимых глюков. Я уже писал насчёт проблемы использования внешних глобальных переменных с атрибутом volatile. Прямое использование в функции под GCC4,8 и выше - будет давать ошибку. Например в простом выражении где А - внешняя глобальная volatile переменная. А= (А+ В +С +Е)/2 переменная А будет физически переписана 4 раза!!! Потому что она volatile и внешняя. Чтобы избавиться от подобного - необходимо объявить локальную переменную в пределах функции, и работать уже с ней, и уже готовый результат переписать в внешнюю А. По этой причине большая часть кода написанного под GCC4.2 - глючит. Когда стало широко применяться внеочередное исполнение инструкций в коде ARM процессоров (GCC4.8) - вздрогнули все аурдинщики, без исключения. Это отдельная тема, но вы должны быть в курсе.
  8. Не плюй в колодец, пригодится. Сначала проверяем свободное место, потом пишем данные, потом переписываем указатель. Сначала проверяем наличие данных, потом их читаем, потом переписываем указатель. А для USART кольцевой буфер мало подходит, для него необходимо иметь два линейных!!! Переписывать данные в ручном режиме, дабы дма могло нормально работать. (я охреневаю от всплывающих подробностей :twak: )
  9. UM10211.pdf Искать 4.8.11 Power domains Искать 26.9 Battery RAM Это дока общая для LPC23XX, конкретная реализация зависит от полного названия чипа. Бегло, PVD механизма контроля питания в lpc - нет. В этом случае нужно использовать внешний аппаратный монитор питания. В навороченном варианте - это отдельный чип, в простом - резисторный делитель напряжения питания до стабилизатора чипа, например 5в. Подобрать номиналы до уверенного срабатывания лог уровня на ноге чипа, использовать внешнее прерывание с максимальным приоритетом.
  10. Конкретный пример кольцевого буфера на Си. Сначала проверяется возможность записи данных, и только потом пишется, и только после этого указатель переписывается. Сначала проверяется возможность чтения, потом читается, и только после этого - переписывается указатель. Кстати, лично у меня использование глобальных переменных в функции в прямом виде - приводит к их использованию в виде локальных переменных. В результате любое изменение сразу записывается в память (это грёбаное ускорение от GCC). Чтобы этого не происходило - нужно глобальные перемененные переписывать локальные принудительно, и уже с ними работать. Этот глюк появился в GCC с переходом от 4,2 до 4,8 версии. Кроме всего прочего, частое переписывание указателей (по чайной ложке) - это банальная нагрузка на память. Буфер всегда должен иметь хотя-бы один пустой элемент, это есть защита от глюка. Одинаковые указатели - признак пустого буфера.
  11. Подключить батарейку мало, нужно запустить стабилизатор питания, транслятор уровня, и монитор питания.
  12. Для этой памяти нужно отдельно запускать питание, монитор общего питания, и транслятор уровня. Потому как это очень медленная память, со своим личным стабилизатором, и с очень нежными ячейками памяти - которые мало кушают, и забиваются мусором от любого чиха на линии питания. Перед тем как проц теряет напряжение - нужно успеть отключить транслятор уровня. Иначе содержимое разрушится. Читайте доку.
  13. Может на Си показать кусок кода? #define buf_zize (127) uint8_t _std_out_buffer[buf_zize]; uint8_t _std_in_buffer[buf_zize]; uint8_t m_mk_buf[buf_zize + 1]; #pragma pack(push, 4) struct _stdout { const uint16_t length; const volatile uint16_t tail; volatile uint16_t head; uint16_t mode; volatile uint8_t *ptr; }_eb_monitor_stdout ={buf_zize,0,0,1,&_std_out_buffer[0]}; struct _stdin { const uint16_t length; volatile uint16_t tail; const volatile uint16_t head; uint16_t mode; const volatile uint8_t *ptr; }_eb_monitor_stdin ={buf_zize,0,0,1,&_std_in_buffer[0]}; #pragma pack(pop) void monitor_fining (void) { uint16_t tmp = 0; do { m_mk_buf[tmp++] = 0x20; }while (tmp != buf_zize); }; /// печать строки void monitor_print (uint8_t* text) { uint16_t temp_t = 0; if (text[temp_t] == '\0') return; uint16_t temp_h = _eb_monitor_stdout.head; uint16_t temp_l; do { temp_l = temp_h; temp_h++; if (temp_h == buf_zize) temp_h = 0; if (_eb_monitor_stdout.tail != temp_h ) _eb_monitor_stdout.ptr[temp_h] = text[temp_t++]; else { _eb_monitor_stdout.head = temp_l; while (_eb_monitor_stdout.tail != temp_l ) sTask_skip();// Delay(1000);// там занято _eb_monitor_stdout.ptr[temp_h] = text[temp_t++]; _eb_monitor_stdout.head = temp_h; } }while (text[temp_t] != '\0'); _eb_monitor_stdout.head = temp_h; __DSB(); }; uint8_t *monitor_scan (uint8_t *text) { uint16_t temp_h = _eb_monitor_stdin.head; uint16_t temp_l = _eb_monitor_stdin.tail; uint16_t temp_x = 0; if(temp_l == temp_h) { text[0] = 0; return text;}; while (temp_l != temp_h) { temp_l++; if (temp_l == buf_zize) temp_l = 0; text[temp_x++] = _eb_monitor_stdin.ptr[temp_l]; } _eb_monitor_stdin.tail = temp_l; text[temp_x] = 0; return text; } Это функции для печати в терминал через программатор. Глюков и зависаний не обнаружено, печатает отдельный процесс, в случае переполнения - остаётся в вечном ожидании, с последующим вытеснением. То-есть программа на мк не падает в случае автономного исполнения. Оба указателя читаются, и участвуют в управлении - но писать можно только один. Второй указатель переписывает отладчик. То самое в структуре под "const volatile" - меняется сторонним процессом. Инициализация один раз, при старте. Есть варианты с динамическим запуском в произвольном месте, но для терминала через программатор - получается слишком сложно для примера.
  14. Разве ерорная ситуация не должна обрабатываться системными вызовами? С закрытием потока и всех его хвостов... И кстати, получить сбой на кольцевом буфере - это очень сильно постараться нужно, прямо таки саботаж устроить.
  15. Он считает что на буфер указывает всего один указатель, и при этом не совсем верно понимает слово "кольцевой".
  16. Цель - сохранить стек без использования мази от геморроя. Запреты прерываний - вот настоящий геморрой. Насчёт кольцевого буфера (знатный срачь): На сам буфер натравлено два указателя, или лучше два смещения. Один для приёмника другой для передатчика. Всё что между приёмником и передатчиком - читает приёмник, как прочитает - переписывает приёмник. Всё что перед передатчиком и позади приёмника - пишет передатчик, когда записал корректно - переписал передатчик. Когда приёмник с передатчиком складывается - читать нечего. Когда передатчик догоняет приёмник на расстояние одного символа - место для записи заканчивается. Это тупо означает что записывать в буфер нельзя, процесс за это отвечающий - должен ожидать. Складывается ощущение, что не каждый понимает о чём тут разговор. Но читать приятно.
  17. Защищённый режим: стек для потоков psp, стек для прерываний msp. Поток не имеет прямого доступа к части системных регистров. Приоритет SVC - 0. Пользовательские прерывания 1~14. Системный таймер, и таймер реального времени =15. Любой поток и прерывание может вызвать SVC без разрушения стека. Системный таймер и таймер реального может прервать любое прерывание, все изменения при этом будут скидываться стек прерываний, и восстанавливаться до первоначального вида совершенно автоматически. Кукла для всех прерываний не требуется!!! Проблема половины бесплатных ос - в наследии от пиков да авр, где защищённый режим просто не существовал. Переписывать всю ось нет смысла - вот и продолжают пользоваться кактусом.
  18. Проверять нужно кодом на асме, чтобы gcc не наоптимизировал записи до нуля. Тестовую запись нужно сбрасывать в память принудительно, с ожиданием завершения физической записи. Неявная запись (PUSH) - является отложенным событием (как и любая запись кучи регистров), код выполняется параллельно, сбросить физику с подтверждением не получится, но можно немного подождать в пустом цикле или сбросить конвейер. И наверное главное, давайте указывать явно - какой чип в тесте на данный момент.
  19. Это результат проверки с отладчиком на реальном камне М3-7. В последнее время я чаще доверяю собственным экспериментам, чем расплывчатому переводу гугла. Кстати, чтобы убрать последствия действий самого отладчика - точки останова необходимо ставить за пределами тестовой функции, иначе будут увлекательные результаты. Находясь в прерывании нельзя запретить само прерывание, получите сбой. Однако можно сбросить те сработавшие прерывания - что имеют более низкий приоритет, те что находятся в ожидании. Но не те что уже сработали и были вытеснены. Иначе будет разрушение стека. Кстати, эти действия могут понадобится в случае просто огромного кода в теле прерывания. То-есть нужно сначала создать себе проблемы, и только потом героически их решать. Юзайте SVC, и будет вам счастье.
  20. Там всё просто, один единственный 32b регистр и схема сравнения на коммутаторе памяти, уже после арбитра и коммутатора нагрузки. Эти команды не выполняются целиком и полностью в ядре мк, они большей частью размазаны по всему кристаллу. Точно так-же как и команды DSB, ISB, ISB, WFE, и так далее.
  21. Проблема проявится при использовании сна. Например М0-М7 просыпаются мгновенно, М7 умудряется так-же мгновенно прочитать почти всю флешь. А держать питание на ddr - батарейки сдохнут.
  22. Здравствуйте, я слесарь и у меня есть гараж, могу паять ручным способом 0,4мм и ниже. Кстати, у этого проца используется внешняя spi флешка в качестве программной памяти, и бут с неё грузится. Но следов шифрования не видно, первоначальный BROM - 32к - одноразовый, штампуется на заводе. Внешняя флешка не имеет проекции на линейную память, после копирования в память - не используется. Подключение не в квадро режиме, то-есть медленное. И это огромное количество линий питания, с разным напряжением и током... Оно меня бесит. Однако в качестве игрушки - вполне годится. Сейчас у каждого второго есть лишние мониторы, а то и планшеты - подножный корм.
  23. Сброс тег монитора из потока в прерывание - это нормальное поведение LDREX/STREX, именно для этого они и задумывались. Нет широкого распространения по другой причине - память должна подключаться к ядру без цепочек ускорителей. То-есть команды LDREX/STREX гарантированно выполняются на всех arm чипах, но не на всей используемой памяти. Делить на можно/нельзя - слишком сложно, проще не использовать вовсе. Однако применение LDREX/STREX даёт очень ощутимое ускорение на операциях с атомарными флагами. Словом можно - если руки растут из нужного места. Весь смысл в том чтобы не испортить другие флаги.
  24. Начали за упокой, кончили за здравие. Как уже было сказано, LDREX выставляет атомарный флаг при использовании команды в потоке, конкретно на используемый адрес. Точнее конкретный адрес чтения выставляется на мониторе, и отслеживается аппаратными механизмами сразу на интерфейсе памяти. Атомарный флаг может сбросить любое прерывание, любое аппаратное чтение/запись по этому адресу (например DMA). Флаг не сбрасывается в момент применения команды LDREX в прерывании и перебивании его более высоким приоритетом. Отчего костыль для использования в прерывании содержит собственный сброс до и после. STREX выполняется, или не выполняется без использования программной проверки атомарного флага, этот механизм выполнен полностью аппаратно. STREX выдаёт флаг, видимый для программы - для проверки успешности операции. Выполнение STREX в потоке - автоматически сбрасывает атомарный флаг, не важно какой результат успеха. Использование в прерывании STREX не гарантирует сброс, но успешно и корректно выставляет программный флаг для проверки операции. Мойте перед и зад - это есть костыль. +Ещё один важный прикол - конвейер. Лучше перебздеть, и подтверждать полный сброс данных в память. +Ещё грабли - LDREX STREX могут применяться на той памяти, что имеет прямое подключение к ядру мк. Например в М7 часть памяти заведена через ускоритель, в результате применение LDREX STREX моментально вешает мк. ------------ SVC - безусловное прерывание. Отрабатывается без вытеснения из любой позиции. Перебить SVC - просто невозможно. SVC - это рыба для сервисов ОС, с небольшим количеством шаманства - превращается в очень удобную функцию. У меня на SVC полностью работает собственная ось.
  25. Можно менять размеры буферов от 128б до "сколько влезет", остальное завязано на плагин - который работает на большой машине. По ссылкам нет си исходников плагина для ID.