maxntf
Участник-
Постов
112 -
Зарегистрирован
-
Посещение
Весь контент maxntf
-
Этот пост я проглядел. то есть не совсем проглядел, а проглядывал его с телефона дома, и не особо придал значение коду с дефайнами. После продолжение ветки перешло на второй лист, и туда забыл посмотреть. Но зато комент, где было сказано что тачлиб юзает SysTick натолкнула на мысль, что нужно из нее удалить все упоминания SysTick чтоб она вообще забыла о его существовании. По этому автору esaulenka отдельное спасибо. Это все хорошо. Только мне не понятен один момент, откинув всю лирику о приоритетах задач, концепции FreeRTOS и т.д. Планировщик, очень сокращенно - это функция которая управляет регистром PC, то есть выбирает куда перекинуть ход выполнения программы. Он вызывается по прерыванию таймера на котором он работает - SysTick, или через API функции FreeRTOSа. У меня 3 задачи, не в одной нет никаких API функций, даже делай. 1-я вызывает функцию, которая отключает SysTick и по какой то причине он не включается. Каким образом моя программа оказывается во второй задачи и там висит, потому как SysTick отключен и планировщик больше не вызывается, а API функций в задачах нет, чтоб вызвать планировщик. P.S. Остается только один вариант - когда 1-я задача включает SysTick, срабатывает прерывание, мы попадаем в планировщик, он передает управление 2-й задаче, и тут по какой то причине SysTick отключается (уже в планировщике).
-
Нужные макросы чего? Просто эта библиотека TouchSensorLib была заточена под SysTick. Ее нужно перебирать. Только хрена было ее делать под хардтимер не понятно. Там и так хренова куча настроек, ну добавили бы еще одну по выбору и настройке таймера. Тем более что там нужно только мсек и сек считать и все! Заделал такое: #define enableInterrupts() {NVIC->ISER[TIM3_IRQn >> 0x05] = (uint32_t)0x01 << (TIM3_IRQn & (uint8_t)0x1F);} #define disableInterrupts() {NVIC->ICER[TIM3_IRQn >> 0x05] = (uint32_t)0x01 << (TIM3_IRQn & (uint8_t)0x1F);} Все вроде работает. Осталось проверить чтоб теперь TIM3 не вис. Если будет виснуть, тогда косяк где то в TouchSensorLib.
-
Нашел костыль. В функции обработка кнопок есть дефайн отключения а потом включения прерываний. Там осталось от оригинала управление SysTick: #define enableInterrupts() {SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;} #define disableInterrupts() {SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;} , а я кручу тайминг на TIM3. Только пока не могу понять как это приводит к полному отключению прерываний. Проверил все места где disableInterrupts применяется, всегда есть обратный на включение enableInterrupts, а пока SysTick отключен, планировщик ведь не может передать управление. Дело в том что функция в которой SysTick включается/отключается вызывается из задачи 1, а когда происходит баг, программа весит в задаче 2.
-
С памятью все ок! Ловушки хоть и примитивные - бесконечный цикл (для отладки сгодится) везде стоят: vApplicationStackOverflowHook, HardFault_Handler и т.д. Я не проект готовый делаю, а только разбираюсь. С STM и FreeRTOS, ранее не работал. Нужно было сделать захват сигнала с частотой 10мкс. Думал попробовать на таймере ОС, вот и поднял частоту. То оказалась глупая затея, а вот баг вылез. Вот и хочу разобраться, чтоб потом таких грабель не было.
-
Гуру Keil, подскажите возможно ли установить брекпоинт по записи в регистр конкретного значения? Отладка через SL_Link Debugger.
-
Я функцию TSL_tim_ProcessIT перенес в TIM3. Возможно у них где то в инициализации есть управление SysTick, буду искать. Спасибо за наводку.
-
Не понял что значит переносить под FreeRTOS? Какие могут быть коллизии, если FreeRTOS использует прерывания с самыми высокими приоритетами? Я же обработчик делаю на низкоприоритетных TIM3 приоритет 36, а SysTick приоритет 6; В общем из за малого опыта, тажело судить что происходит, но причина выявлена - 100% перестает работать SysTick, а соответственно и scheduler который крутится на этом таймере. Вот только что происходит с SysTick, понять не могу. Кто может, опишите регистры SysTick или ткните где посмотреть. PS: Судя по функции SysTick_Config там всего 3 бита, интуитивно по названиям дефайнов SysTick_CTRL_CLKSOURCE_Msk, SysTick_CTRL_TICKINT_Msk, SysTick_CTRL_ENABLE_Msk. один включает тактирование, второй инициализирует и третий запускает. Вот этот SysTick_CTRL_TICKINT_Msk и сбрасывается. Где не могу поймать. если бы в Кеил можно было установить брекпоинт на запись в бит. Кто знает можно такое?
-
В Кеил брекпоинт можно поставить только на весь регистр, вот если бы на изменение бита.:) Глючит из за библиотеки, там в прерывании таймера, у меня TIM3, вызывается некая функция обработчика этих кнопок. Вот тут то и происходит баг.
-
Да при тике 1кгц все работает. 2-я задача читает блоками аудио файл с флешь и DMA его пересылает в DAC. Она то и оставалась работать. Я ее отключил. 1-я задача обрабатывает сенсорные кнопки библиотекой touch-sensing library от ST. Собственно вызывает функцию, которая возвращает состояние кнопок. И если кнопка нажата, устанавливает глобальный флаг. 3-я задача проверяет этот флаг, когда он установился, запускает два таймера, один читает IR код с фотоприемника, а второй его передает. Сразу оговорюсь, с ARM только начал разбираться, так что некоторые мои рассуждения могут быть глупые, не судите строго :). Глючит именно пара задач 1 и 3. Причем если я блокирую одну из них, глюк пропадает. У меня пока один вариант: - библиотека touch-sensing library как то конфликтует с FreeRTOS. Сейчас просматриваю не использует ли она какие то аппаратные ресурсы что и ОС, например SysTickTimer. В планировщик больше вообще не попадаем после глюка. Надо проверить что там с прерываниями SysTickTimer, которые где то в FreeRTOS По ходу прерывания SysTick отключаются. Точнее я вижу что в структуре описания этого регистра меняется значение CTRL - при старте CTRL = 0х00000007 / 0х00010007, а после глюка 0х00010005, и больше в прерывание не попадаем. Сейчас поставил частоту 20000Нz и глюк начал проявляться практически сразу.
-
Всем привет. На FreeRTOS вертятся 3 задачи, больше ничего из инструментария ОС не пользую. Так вот когда configTICK_RATE_HZ установлен 1000Hz, все работает без проблем. Меняю это значение на 10000Hz, после ресета все задачи какое то время работают, а потом работает только одна - 2-я задача (скорее работает просто функция). Шедуллер перестает работать вовсе - vApplicationTickHook перестает вызываться и задачи не переключаются. МК STM32L152rc работает на 16MHz. В чем может быть дело? Как отследить где планировщик заткнулся и почему?
-
Помогите разобраться, не правильно работает функция SystemCoreClockUpdate() Когда запускаю тактирование без PLL от встроенного генератора HSI - 16Mhz, работает правильно. А когда включаю PLL, функция SystemCoreClockUpdate() возвращает все равно значение 16MHz, хотя реальная частота 32MHz. Работает только если самому прописать SystemCoreClock = 32000000 перед вызовом SysTick_Config. RCC_Init(); SystemCoreClockUpdate(); SysTick_Config(SystemCoreClock/1000);//TO=1ms void RCC_Init(void) { RCC_HSICmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET); FLASH->ACR=FLASH_ACR_ACC64; FLASH->ACR|=FLASH_ACR_LATENCY; FLASH->ACR|=FLASH_ACR_PRFTEN; RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_4, RCC_PLLDiv_2); RCC_PLLCmd(ENABLE);//Включаем PLL RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); RCC_HSEConfig(RCC_HSE_OFF); while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET); }
-
Проверка трансформатора
maxntf ответил maxntf тема в Силовая Преобразовательная Техника
Используем эти БП уже долгое время, особых проблем нет. Нужно кое что свое добавить и по быстрому сделать, а я в силовой электронике не особо. Вот и решили быстро передрать то что было. По тепловым характеристикам, шум и т.д. все идентично. Намотали нам 2 варианта по 5 шт. Сказали что в первом варианте при высоком входном напряжении заметили перенасыщение (как это проверить самому я не знаю). И сделали вариант 2 на один виток меньше. Вот мои замеры индуктивности. Оригинал (под рукой только 2 шт.): а) первичка 1103uH вторичка 11uH б) первичка 1082uH вторичка 10,9uH Вариант 1: а) первичка 1225uH вторичка 12,3uH б) первичка 1219uH вторичка 12,2uH в) первичка 1219uH вторичка 12,2uH г) первичка 1215uH вторичка 12,2uH д) первичка 1226uH вторичка 12,3uH Вариант 2: а) первичка 1017uH вторичка 10,3uH б) первичка 1036uH вторичка 10,4uH в) первичка 1031uH вторичка 10,4uH г) первичка 1029uH вторичка 10,4uH д) первичка 1020uH вторичка 10,3uH -
Проверка трансформатора
maxntf ответил maxntf тема в Силовая Преобразовательная Техника
Там был еще узел для резервного аккумулятора, я его убрал чтоб уменьшить размер схемы. Индуктивность обмоток я могу измерить есть RLC прибор. Меня интересует правильно ли там подобраны сердечник и провод. Такие моменты как перенасыщение сердечника и что там еще может быть? А все выше перечисленные параметры это само собой. -
Проверка трансформатора
maxntf ответил maxntf тема в Силовая Преобразовательная Техника
Просьба по сути. Я сам вижу что там на входе не хватает термистора, дросселя, кондера. Я привел схему изделия которое уже есть, о его недостатках речь не идет. Вопрос про трансформатор. -
Проверка трансформатора
maxntf опубликовал тема в Силовая Преобразовательная Техника
Сам не занимаюсь расчетами трансформаторов и всех тонкостей не знаю. Нужно собрать ИБП по образцу. У меня есть оригинальный БП, а так же трансформаторы которые я заказал намотать по образцу. Подскажите какие и как снять параметры чтоб определить что новые трансформаторы работают не хуже оригинала. Схему БП прилагаю, из подручных средств есть - осциллограф, мультиметр, ЛАТР. -
Да действительно коротит, а я уже думал может индуктивность меняется или еще какая хрень. Спасибо. Никогда не подумал бы, что эта эмаль такая...
-
Собрана схема DC-DC на LM2576T-ADJ. И всплыл такой баг, как только дроссель касается обмоткой к предохранительной колодке входного питания, напряжение на выходе стабилизатора сразу начинает расти. Обмотка дросселя изолирована лаком и КЗ соответственно нет. Кто может объяснить что происходит в этот момент?
-
Просто у меня в отладке, когда указатель стека попадает в секцию bss сразу происходит вылет в то самое прерывание. Поскольку с прерываниями я еще не успел толком разобраться, вот и предположил что есть такая заглушка. Ну раз это не так, значит на данном этапе моих познаний ARM все равно как расположить стек и кучу (главное понял как :rolleyes: ). А дальше посмотрим.
-
То есть не факт что программа обязательно вылетает в это прерывание?
-
Люди подскажите чем Вы готовите звук. Пробую сделать как в статье Воспроизведение звука на STM32-Discovery при помощи Speex. Звук что в примере у меня играет. Поставил кодек SpeexACM_1.0.1.1 пробую из разных конвертеров ауди сделать закодированный файл, никак не получается то что нужно. Если у кого есть, поделитесь кодеком и конвертером на котором у Вас получилось.
-
Когда он туда наезжает у меня программа вылетает в прерывание HardFault_Handler. Можно там фиксировать что переполнение стека. И потом менять его размер. А если наедет на кучу, как узнать?
-
Уважаемые AHTOXA и zltigo спасибо Вам за помощь! Мне почему то больше понравился вариант сначала стек потом куча. Тогда исключается вариант их пересечения. Чтоб размер этих секций не превысил ОЗУ, я размер стека буду задавать какой нужен, а размер кучи все что осталось. А для контроля минимального размера кучи и сделаю условие в линкере. _StackSize = 0x1000;/*устанавливаем*/ _StackTop = . + _StackSize; PROVIDE(_stack = _StackTop); _HeapSize = _eram - _StackTop; _HeapBegin = _eram - _HeapSize; _HeapLimit = _eram; _HeapMinimal = 0x2000;/*устанавливаем*/ ASSERT(_HeapSize > _HeapMinimal, "warning! small size of the heap")
-
Вух!!!, вроде все понял. Много вопросов отпало, когда собралась общая картинка. Просто начал я не с того боку и все из за того базового линк. Нужно было начинать с его ковыряния, а не кода Си. Вот линк: _eram = 0x20000000 + 0x00020000; SECTIONS { .text : { KEEP(*(.isr_vector)) ля-ля-ля } > rom .data : { ля-ля-ля } > ram .bss : { ля-ля-ля } > ram //Начало моей части где я настраиваю stack & heap //Стек _stack_size = 0x200;/*Размер - нужно только мне и для вычисления след. параметров*/ _StackTop = . + _stack_size;/*Вершина стека начало лок. данных + его размер*/ _StackLimit = .;/*Для наглядности - начало лок. данных*/ .stack :/*Это собственно секция стека*/ { . = . + _stack_size;/*установка размера этой секции*/ } > ram PROVIDE(_stack = _StackTop);/*значение _stack устанавливаем в _StackTop*/ /*_stack потом помещаем в начало вектора*/ //Куча _heap_size = 0x100;/*размер кучи*/ _heap_begin = _eram - _heap_size;/*адрес начала кучи*/ _heap_limit = _heap_begin + _heap_size;/*лимит кучи для проверки*/ .heap (_heap_begin):/*секцию под кучу располагаем адреса _heap_begin*/ { . = . + _heap_size;/*установка размера этой секции*/ } > ram } В startup файле устанавливаем только координаты начала стека, больше в нем нет ничего про стек и кучу! extern unsigned long _stack;//значение задано в линк. файле __attribute__ ((used,section(".isr_vector"))) void (* const g_pfnVectors[])(void) = { /*----------Core Exceptions------------------------------------------------ */ (void *)&_stack, /*!< The initial stack pointer */ Reset_Handler, /*!< Reset Handler */ NMI_Handler, /*!< NMI Handler */ Для проверки переполнения кучи в файле syscalls.c extern int _heap_begin; extern int _heap_limit; caddr_t _sbrk ( int incr ) { static unsigned char *heap = NULL; unsigned char *prev_heap; unsigned char *new_heap; if (heap == NULL) { heap = (unsigned char *)&_heap_begin; } prev_heap = heap; new_heap = heap + incr; if(new_heap > (unsigned char *)&_heap_limit) { return 0; } heap = new_heap; return (caddr_t) prev_heap; } По map файлу (просто для наглядности): В итоге мы получили стек размером 0x200 который идет с адреса 0x20000a88 к 0x20000888. Куча которая начинается с адреса 0x2001ff00 и идет до конца памяти с ограничением переполнения. COMMON 0x20000884 0x20000884 errno 0x20000888 . = ALIGN (0x4) 0x20000888 __bss_end__ = . 0x20000888 _ebss = __bss_end__ 0x00000200 _stack_size = 0x200 0x20000a88 _StackTop = (. + _stack_size) 0x20000888 _StackLimit = . .stack 0x20000888 0x200 load address 0x080014b4 0x20000a88 . = (. + _stack_size) *fill* 0x20000888 0x200 0x20000a88 PROVIDE (_stack, _StackTop) 0x00000100 _heap_size = 0x100 0x2001ff00 _heap_begin = (_eram - _heap_size) 0x20020000 _heap_limit = (_heap_begin + _heap_size) .heap 0x2001ff00 0x100 load address 0x08020b2c 0x2001ff00 _end = . 0x20020000 . = (. + _heap_size) *fill* 0x2001ff00 0x100 Остался один вопрос: Эти самые секции объявляются для того, чтоб в эти места памяти никто ничего левого не подсунул? Типа ка в линке MCC18 под ПИК когда нужна секция, в которую линкер ничего не суют? Или то-же только для наглядности? И здесь и так никто ничего не подсунет. Все глобальные переменные по порядочку по секциям data и bss (в PIC они были разбросаны по банкам памяти). Стек от А до В, куча от С до D. Все локальные переменные в стеке. Тогда может вообще лишнее объявлять эти секции? Сделать себе _stack_size = 0x200; _StackTop = . + _stack_size; PROVIDE(_stack = _StackTop); //Куча _heap_size = 0x100; _heap_begin = _eram - _heap_size; _heap_limit = _heap_begin + _heap_size; И Все?!
-
С этим вроде понял. Все дело в файле starup который coocox включает при выборе в репозитории компонента CMSIS BOOT. Не понятно зачем так? /*----------Stack Configuration-----------------------------------------------*/ #define STACK_SIZE 0x00002000 /*!< The Stack size suggest using even number */ __attribute__ ((section(".co_stack"))) unsigned long pulStack[STACK_SIZE]; __attribute__ ((used,section(".isr_vector"))) void (* const g_pfnVectors[])(void) = { /*----------Core Exceptions------------------------------------------------ */ (void *)&pulStack[STACK_SIZE], /*!< The initial stack pointer */ Reset_Handler, /*!< Reset Handler */ ля-ля-ля } В общем я поменял кусок, и теперь и стек начинается с __StackTop что в линкере указан, и проверка сохраняется ASSERT(__StackLimit >= __HeapLimit, "region ram overflowed with stack") /*----------Stack Configuration-----------------------------------------------*/ #define STACK_SIZE 0x00002000 /*!< The Stack size suggest using even number */ __attribute__ ((section(".co_stack"))) unsigned long pulStack[STACK_SIZE]; extern unsigned long __stack; __attribute__ ((used,section(".isr_vector"))) void (* const g_pfnVectors[])(void) = { /*----------Core Exceptions------------------------------------------------ */ (void *)&__stack, /*!< The initial stack pointer */ Reset_Handler, /*!< Reset Handler */ Вот теперь после изменения startup и понял. Вот что у меня в этой функции. extern int _end; /*This function is used for handle heap option*/ __attribute__ ((used)) caddr_t _sbrk ( int incr ) { static unsigned char *heap = NULL; unsigned char *prev_heap; if (heap == NULL) { heap = (unsigned char *)&_end; } prev_heap = heap; heap += incr; return (caddr_t) prev_heap; } На сколько я понял _end это та что в линкере .heap (COPY): { __end__ = .; _end = __end__; end = __end__; *(.heap*) __HeapLimit = .; } > ram Не пойму как устанавливается значение __HeapLimit? И что в _sbrk нужно добавить, чтоб запретить выделять память после этого HeapLimit? FreeRTOS. Глобальных переменных, области data и bss?
-
Тогда мне не понятно, зачем делать, чтоб куча шла на встречу стеку? Почему не выделить вначале кусок памяти под стек, а все что осталось под кучу? Но с таким-же успехом можно и в конце фиксированный под стек, а весь остаток под кучу. Главное. что ВЕСЬ а не какой-то опять-же фиксированный размер. Размер хипа следует указывать только минимальный, дабы уже линкер ругался, что совсем уж памяти не хватает. Возможно я здесь чего то не понял. RTOS использует собственный стек и кучу, или те же что и компилятор (у меня GCC)? В настройках RTOS есть 2 параметра: Получается что этими параметрами я задаю имеющуюся память в МК, потому что RTOS не имеет представления о том что у него на борту?