Jump to content

    

AVI-crak

Участник
  • Content Count

    234
  • Joined

  • Last visited

Everything posted by AVI-crak


  1. Stm32 remap pin function

    В чипах STM32F4 и выше - ремапа нет, в реальности нога процессора выбирает периферию. Однако можно получить вечный жёсткий отказ шины данных в случае двух ног мк на одной периферии в случае входа, выход успешно переваривается - но не имеет смысла.
  2. Почему может не работать malloc в Keil?

    А что произойдёт с адресом выделенной памяти после вторичного вызова функции?
  3. Цитата(Forger @ Aug 4 2017, 17:04) зы Ради спортивного интереса прям щас Дык это программный ресет, при аппаратном ресете отладчик не успевает подключиться, по крайней мере у меня.
  4. Цитата(jcxz @ Aug 4 2017, 12:59) Или что имелось в виду? Я говорю о том, что в момент аппаратного срабатывания триггера выбора загрузочного интерфейса - всё остальное отключается!!!!. Потому как сам механизм записи в память флеша - не имеет арбитра. Да и всего остального фарша - тоже.
  5. Цитата(LightElf @ Aug 3 2017, 20:06) Действительно, бессмысленно предполагать. Надо тупо залезть дизасмом в бут и посмотреть КАК? Каким образом смотреть содержимое ядра и адресного пространства мк в режиме явного срабатывания загрузчика по usart??? Вопрос на миллион баксов!!!
  6. Режим отладки в памяти. Программа в флеш выполняет две функции: запись адреса стека (аппаратная команда), меняет адрес массива векторов прерываний (аппаратный переход на ресет), повторный переход на новый ресет в памяти мк. При физическом нажатии ресета - память sram не искажается. Запуск кода из допустимых для данного мк областей памяти - память sram не искажается. Ресет не искажает память. Запуск бута в режиме программирования (после успешной синхронизации!!!) - всегда портит stam и стирает флеш при включённой защите (сразу!!!), стирает сам флеш по секторам при программировании (последовательно). Без успешной синхронизации - содержимое памяти не искажается при ресете. Бут является аппаратным механизмом, без использования ресурсов ядра и памяти. Но в момент полноценной работы - память stam используется в качестве буфера. Адреса массивов являются аппаратными, изменить их нельзя. Максимальный бардак в памяти получается при загрузке через usb. Вас не должно волновать содержимое памяти после срабатывания бута - к этому моменту у вас уже поменялась прошивка.
  7. Кодcase(OpenTCP):                        //Открытие TCP                 {                                //                     printf("\rOpen TCP Session\r");//                         GSM_State_Mashine = ConnMQTT;//Успешно                     GSM_Mashine_Errors = 0;        //                     if(GPRSConnect1(TCP, MQTT_BROKER_SERVER, PORT, DEFAULT_TIMEOUT*8, DEFAULT_INTERCHAR_TIMEOUT*5) == 0)                         //                         { // эта функция всегда возвращает аргумент в регистре R0, выделять новую переменную для этого не нужно.                             printf("\rError TCP Open... Try Again...\r");//                               //  int T =    GPRSClose();//  не вижу повторного использования Т                             GPRSClose();                             GSM_Mashine_Errors++;//                             break;                //                         }                        //                     GSM_State_Mashine = ConnMQTT;//Успешно                     GSM_Mashine_Errors = 0;        //                     printf("\rTCP Session Open\r");//                     break;
  8. Цитата(Forger @ Jul 13 2017, 23:14) Имхо, лучше лишний раз "передернуть" все железо, чем так нагло влезать в стек подобного девайса Чтобы не ресетить девайс - нужно изначально закладывать архитектуру здоровой OS, с отдельным стеком прерываний и куче стеков задач. В этом случае запуск/отключение и управление уровнем прерывания - осуществляется через активную задачу, которая вызывает системное прерывание с заведомо максимальным уровнем. Без блокировки!!! Править уровни прерываний и их очереди в теле пользовательских прерываний - это есть громадный костыль, означающий что программист накосячил в нескольких местах и не смог исправить. Если прерывание пользователя зависает в бесконечном цикле - то лучше сразу сменить род деятельности, пока более опытные товарищи вам ноги руки не по отрывали. Уход в глубокий сон выполняется по команде OS, после чего все активные задачи должны свернуть свою деятельность и уйти в зависимость, вот после этого можно сохранять на флеш - активную память задач и их стеки, с последующим отключением питания. Предусмотреть все ньюансы работы периферии - просто невозможно. Однако в самой активной задаче - вполне реально. Просто блок инициализации будет выполняться повторно при перезапуске в каждой задаче отдельно. Глубокий сон - весьма специфическое требование, его трудно выполнить качественно, всегда придётся идти на компромисс. Гораздо чаще делают более простой вариант - сохраняют только данные объявленные как статические - в энергонезависимой памяти. С копированием их в память при запуске и сохранением перед отключением.
  9. Цитата(jeka @ Jul 12 2017, 22:58) Собственно, зачем это нужно - в случае аварии вызывается определенный irq. На случай аварий - системой уже предусмотрено несколько стандартных аппаратных прерываний разного уровня. От мягких программных, до жёстких системных. Собаку можно обработать программно, и успеть перевести внешнюю периферию в необходимое для выключение состояние. Например полностью блокировать внешний силовой драйвер мощных транзисторов, да и вообще отрубить всё питание. Чтение мимо адресного пространства 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 - сторожевая собака, гавкает когда перестают ходить строем
  10. Цитата(dachny @ Jun 16 2017, 18:18) То есть получается фактически USB2.0 ваще нету... f7 h7 - имеют физику USB2.0 на кристалле чипа, внешняя физика не нужна. И кстати - достаточно шустро работает.
  11. __LDREX __STREX в STM32F407

    Цитата(Forger @ Jun 12 2017, 15:29) Именно так я и скажу Где именно вы умудряетесь нарушить алгоритм? 1 прочитать в ЛОКАЛЬНЫЕ переменные указатели кольцевого буфера 2 обработать данные (записать или прочитать), если таковые имеются 3 переписать ОДИН указатель по ЗАВЕРШЕНИЮ работы с данными. Прошу внимательно прочитать, и дать простой ответ под номером строки 1-2-3. При выходе из этого цикла данные записанные в буфер теряют актуальность. Не в том смысле что их можно портить, это больше похоже на лог, данные не актуальны в следующий момент времени. Например нельзя дописывать в буфер или прочитывать старое уже после выхода из полного цикла, данные теряют актуальность, и могут затереться другим процессом. Прервать алгоритм можно в любом месте, например прерыванием или переключением задач. Главное корректно его восстанавливать.
  12. LPC23XX backup Battery RAM

    Цитата(gte @ Jun 12 2017, 04:28) LPC23xx это не кортекс. Да это вообще не из этого мира. Часть инстала часов реального ремни. Код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; } Я-ж говорил - всего один бит....
  13. LPC23XX backup Battery RAM

    Цитата(gte @ Jun 11 2017, 18:00) И что, там написано про "запустить стабилизатор питания, транслятор уровня, и монитор питания"? Что такое транслятор уровня? Применимо к кортексу в целом - это запуск резервного домена питания. Домен связан с часами реального времени не только питанием, но и системной шиной. (или наоборот) В lpc это просто один бит, в stm больше движений - но и возможностей по более. Нужно смотреть документацию конкретно на этот узел от lpc, точнее под конкретный чип. Потому как BKPSRAM имеет питание 2,1в, и очень низкую частоту такта. Подать питание на память - это пол дела, транслятор уровня заметно кушает - и его не всегда держат в рабочем режиме. В данном случае транслятор уровня - это разрешение доступа к памяти. Нужен конкретный чип, без xxx.
  14. __LDREX __STREX в STM32F407

    Цитата(Forger @ Jun 11 2017, 18:19) Может перезаписать свой и исходя из этого изменить логику работы очереди, в мое случае - остановить передачу тогда, когда это делать рано. Сама очередь ничего не потеряла, но таймингки протокола на приемной стороне (внешнее устройство) были нарушены, что вызывало сбои в обмене. Да ёёёё. Кто-ж использует кольцевой буфер для физических устройств????? Для физики все (без исключения) применяют линейный буфер: одинарный или двойной - для одного!!! направления. Спокойно создаём сообщение, дожидаемся готовности физики, и пинаем дма. Всё, тайминги в порядке, процессорное время свободно, мозг никто не клюёт.
  15. __LDREX __STREX в STM32F407

    Цитата(Forger @ Jun 11 2017, 17:02) Я именно так и делаю, но прерывания временно запрещаю, т. к. между проверкой и изменением указателя проходит время, в которое может влезть прерывание, которое обращается к тем же указателям. Без эти временных запретов в одном из моих старых проектов вылезала редкая и потому очень трудноуловимая ошибка ((( Я не понимаю, как читающий может переписать чужой указатель??? Ну не успели выбрать все данные, или наоборот - положить всё что нужное в буфер. Конец света от этого не наступает, успеете сделать когда будет такая возможность. Не понимаю, зачем жопу рвать на британский флаг??? По поводу неуловимых глюков. Я уже писал насчёт проблемы использования внешних глобальных переменных с атрибутом volatile. Прямое использование в функции под GCC4,8 и выше - будет давать ошибку. Например в простом выражении где А - внешняя глобальная volatile переменная. А= (А+ В +С +Е)/2 переменная А будет физически переписана 4 раза!!! Потому что она volatile и внешняя. Чтобы избавиться от подобного - необходимо объявить локальную переменную в пределах функции, и работать уже с ней, и уже готовый результат переписать в внешнюю А. По этой причине большая часть кода написанного под GCC4.2 - глючит. Когда стало широко применяться внеочередное исполнение инструкций в коде ARM процессоров (GCC4.8) - вздрогнули все аурдинщики, без исключения. Это отдельная тема, но вы должны быть в курсе.
  16. __LDREX __STREX в STM32F407

    Цитата(Forger @ Jun 11 2017, 16:22) Я же пытаюсь донести, что не все тут так просто. Не плюй в колодец, пригодится. Сначала проверяем свободное место, потом пишем данные, потом переписываем указатель. Сначала проверяем наличие данных, потом их читаем, потом переписываем указатель. А для USART кольцевой буфер мало подходит, для него необходимо иметь два линейных!!! Переписывать данные в ручном режиме, дабы дма могло нормально работать. (я охреневаю от всплывающих подробностей )
  17. LPC23XX backup Battery RAM

    UM10211.pdf Искать 4.8.11 Power domains Искать 26.9 Battery RAM Это дока общая для LPC23XX, конкретная реализация зависит от полного названия чипа. Бегло, PVD механизма контроля питания в lpc - нет. В этом случае нужно использовать внешний аппаратный монитор питания. В навороченном варианте - это отдельный чип, в простом - резисторный делитель напряжения питания до стабилизатора чипа, например 5в. Подобрать номиналы до уверенного срабатывания лог уровня на ноге чипа, использовать внешнее прерывание с максимальным приоритетом.
  18. __LDREX __STREX в STM32F407

    Цитата(Forger @ Jun 11 2017, 14:04) Вот пример: Пусть put = 10, get = 9, т.е. в очереди остался всего один еще не отправленный элемент. Конкретный пример кольцевого буфера на Си. Сначала проверяется возможность записи данных, и только потом пишется, и только после этого указатель переписывается. Сначала проверяется возможность чтения, потом читается, и только после этого - переписывается указатель. Кстати, лично у меня использование глобальных переменных в функции в прямом виде - приводит к их использованию в виде локальных переменных. В результате любое изменение сразу записывается в память (это грёбаное ускорение от GCC). Чтобы этого не происходило - нужно глобальные перемененные переписывать локальные принудительно, и уже с ними работать. Этот глюк появился в GCC с переходом от 4,2 до 4,8 версии. Кроме всего прочего, частое переписывание указателей (по чайной ложке) - это банальная нагрузка на память. Буфер всегда должен иметь хотя-бы один пустой элемент, это есть защита от глюка. Одинаковые указатели - признак пустого буфера.
  19. LPC23XX backup Battery RAM

    Подключить батарейку мало, нужно запустить стабилизатор питания, транслятор уровня, и монитор питания.
  20. LPC23XX backup Battery RAM

    Для этой памяти нужно отдельно запускать питание, монитор общего питания, и транслятор уровня. Потому как это очень медленная память, со своим личным стабилизатором, и с очень нежными ячейками памяти - которые мало кушают, и забиваются мусором от любого чиха на линии питания. Перед тем как проц теряет напряжение - нужно успеть отключить транслятор уровня. Иначе содержимое разрушится. Читайте доку.
  21. __LDREX __STREX в STM32F407

    Может на Си показать кусок кода? CODE#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" - меняется сторонним процессом. Инициализация один раз, при старте. Есть варианты с динамическим запуском в произвольном месте, но для терминала через программатор - получается слишком сложно для примера.
  22. __LDREX __STREX в STM32F407

    Разве ерорная ситуация не должна обрабатываться системными вызовами? С закрытием потока и всех его хвостов... И кстати, получить сбой на кольцевом буфере - это очень сильно постараться нужно, прямо таки саботаж устроить.
  23. __LDREX __STREX в STM32F407

    Цитата(jcxz @ Jun 10 2017, 04:28) Может быть Вы укажете, где именно проблема в приведённом мной примере реализации кольцевого буфера? А то Forger видимо знает, но держит эту тайну при себе Он считает что на буфер указывает всего один указатель, и при этом не совсем верно понимает слово "кольцевой".
  24. __LDREX __STREX в STM32F407

    Цитата(Forger @ Jun 9 2017, 22:27) Поменять шило на мыло? По вашей логике получится, что пока этот приоритетный SVC не отработает, ни одно более важное аппаратное прерывание не пройдет. SVC с таким высоким приоритетом, вызываемые из других менее приоритетных прерываний по сути временно задирает их собственный приоритет, который был "ниже плинтуса", отбирая "право голоса" у более приоритетных прерываний. На лицо - инверсия приоритетов. С чем боролись на то и напоролись. Ни чем не лучше глобальной критической секции (запрет/разрешение всех прерываний). А должно быть совсем иначе - срочные и архиважные аппаратные прерывания должны отработаться предельно быстро, куда надо просемафорить и тут же освободить процессор. Цель - сохранить стек без использования мази от геморроя. Запреты прерываний - вот настоящий геморрой. Насчёт кольцевого буфера (знатный срачь): На сам буфер натравлено два указателя, или лучше два смещения. Один для приёмника другой для передатчика. Всё что между приёмником и передатчиком - читает приёмник, как прочитает - переписывает приёмник. Всё что перед передатчиком и позади приёмника - пишет передатчик, когда записал корректно - переписал передатчик. Когда приёмник с передатчиком складывается - читать нечего. Когда передатчик догоняет приёмник на расстояние одного символа - место для записи заканчивается. Это тупо означает что записывать в буфер нельзя, процесс за это отвечающий - должен ожидать. Складывается ощущение, что не каждый понимает о чём тут разговор. Но читать приятно.
  25. __LDREX __STREX в STM32F407

    Защищённый режим: стек для потоков psp, стек для прерываний msp. Поток не имеет прямого доступа к части системных регистров. Приоритет SVC - 0. Пользовательские прерывания 1~14. Системный таймер, и таймер реального времени =15. Любой поток и прерывание может вызвать SVC без разрушения стека. Системный таймер и таймер реального может прервать любое прерывание, все изменения при этом будут скидываться стек прерываний, и восстанавливаться до первоначального вида совершенно автоматически. Кукла для всех прерываний не требуется!!! Проблема половины бесплатных ос - в наследии от пиков да авр, где защищённый режим просто не существовал. Переписывать всю ось нет смысла - вот и продолжают пользоваться кактусом.