Jump to content

    

Сергей Борщ

Модераторы
  • Content Count

    9310
  • Joined

Everything posted by Сергей Борщ


  1. Странно. Уже много лет использую этот менеджер памяти в плюсовых проектах для ARM7 и Cortex, никаких проблем с его плюсовостью не испытываю. Правда, я не выделяю динамически память при инциализации глобальных переменных. Может все же стоит найти исходники от cstartup из mingw и разобраться до конца?
  2. Это действие будет выполняться каждый раз при входе в функцию. Чтобы этого не происходило, я предложил перенести его в конструктор manager, чтобы оно выполнялось только один раз, во время выполнения конструктора: template<size_t size_items> manager::manager(int (& pool)[size_items]) : start((mcb *)pool) , freemem((mcb *)pool) , Guard() { init(start, sizeof(pool)); extern manager * pManager; pManager = this; } Про это тоже было в ссылке от GenaSPB: https://wiki.osdev.org/C++#Local_Static_Variables_.28GCC_Only.29 А пройти его пошагово в отладчике или посмотреть исходник?
  3. Эти картинки мне ни о чем не говорят. Вот выдержка из домументации на F1: В документации на F0, F4 аналогичная информация. Остальные не смотрел.
  4. Если речь идет о gcc и принятом в нем startup-коде, то приходит в голову такая идея: зарезервировать память под HeapPool и Manager в виде массива байтов, в секции .init3 (или .init2) разместить код с вызовом placement new для Manager. Этот код вызовет конструктор Manager, а размещение в .init3 заставит выполниться до первых обращений к malloc(). Как это сделать для других компиляторов без переписывания startup я не знаю. Добавлено: такая идея: heap::manager * pManager; // в конструктор heap::manager добавить: // extern heap::manager * pManager; pManager = this; void * do_alloc(size_t size) { static heap::pool<4096> HeapPool; static heap::manager<heap_guard> heap::Manager(HeapPool); return pManager->malloc(size); } void do_free(void * p) { pManager->free(p); } и во всех переопределениях new(), malloc(), delete() и free() использовать do_alloc() и do_free()
  5. Это процесс сильно зависит от качества самого пинцета. Купил лет 15 назад в уже не помню в каком магазине пинцет TS-11, был им очень и очень доволен - он и в руке лежит удобно и губки тонкие и губки практически не разъезжались при сжатии. Потом несколько раз покупал тоже TS-11 и в других местах и у китайцев - у всех была проблема с разъезжанием губок. И вот только буквально на прошлой неделе приехал с али пинцет (NB07), который там продается как "пинцет для выщипывания бровей", но по качеству он даже лучше чем тот мой самый первый - у него не разъезжаются губки и их тяжело сместить относительно друг друга даже принудительно. Он достаточно жесткий в том смысле, что чтобы его сжать нужно приложить ощутимо большее усилие чем у тех пинцетов, у которых губки разъезжаются и которые слипаются от флюса. Губки заточены очень остро и на упаковке была указана даже закалка HRC40. По форме и размерам он копия TS-11. Это пинцет, про который я смело могу сказать: по моему мнению он идеален.
  6. ЦАП STM32 умеет сам подмешивать в выходной сигнал треугольник или шум. У вас, случайно, не включен этот режим?
  7. Если при использовании этой конкретной функции volatile ни на что не влияет - привести явно. Попробую объяснить: если вы передаете в, скажем, memcmp() массив volatile - переменных, и обращение к одним переменным не влияет на другие, т.е. допустимо обращение к элементам в любом порядке - то можно делать приведение типа. А вот если порядок влияет (скажем, вы передаете структуру какой-то периферии, где чтение регистра данных сбрасывает флаги и вам обязательно нужно прочитать сначала регистр флагов и только потом регистр данных) - то надо писать свою реализацию функции, приннимающую volatile-аргумент и обращающуюся к данным в нужном порядке. В любом случае забивать на предупреждения ни в коем случае нельзя - если ваша программа при каждой компиляции выдает предупреждения - вам просто надоест их читать и когда появится действительно важное предупреждение - вы его банально пропустите в этом шуме. Переключить компилятор в режим C++ и переопределить функцию для volatile-аргумента. Пусть это явное приведение типа будет спрятано внутри переопределенной функции, а компилятор сам подставит вызов той или другой в зависимости от типа аргумента: void Foo(char const *p); inline void Foo(char const volatile *p) { Foo(const_cast<char const *>(p));
  8. Гляньте этот. Самому интересно - давно его использую, но в моих задачах нет активной работы с кучей.
  9. Рискну предположить, что это библиотечная функция, используется для вывода отладочной информации через отладчик. Если это так - то она подключается специальными ключами компилятора при сборке отладочной версии программы. Попав на эту точку остановки отладчик вычитывает откуда надо отладочную информацию ,выводит в специальное окно и запускает программу на дальнейшее выполнение. Для вас это должно происходить незаметно. Если же вы видите остановку в этой точке - у вас не подключен какой-нибудь нужный для этого плугин отладчика, а если эта отладочная информация вам не нужна, вам надо отключить работу с ней какими-то ключами компилятора или галочками в оболочке. Но это мои чисто теоретические предположения, с Кейлом я не работал. Что-то подобное наблюдал в ИАРе, но тоже не использовал.
  10. Может вы не там искали? cmsis_gcc.h: /** \brief Breakpoint \details Causes the processor to enter Debug state. Debug tools can use this to investigate system state when the instruction at a particular address is reached. \param [in] value is ignored by the processor. If required, a debugger can use it to store additional information about the breakpoint. */ #define __BKPT(value) __ASM volatile ("bkpt "#value) Для остальных компиляторов должно быть что-то подобное.
  11. Как раз наоборот: в ассемблере считаются адреса команд, т.е. org 7 -это адрес седьмой команды, или 14 в байтах. А компилятор Сей считает адреса в байтах, поэтому если заголовочный файл - сишный, то адрес 14 там с точки зрения Сей указан правильно, а при использовании его в ассемблере нужно переводить адрес байтов в адрес слов, т.е. делить на два.
  12. В вашей программе присутствует команда останова. Кто виноват, что в ней появилась такая команда? Что делать: искать в .map, внутри находится этот адрес, искать эту функцию в исходнике, удалить из нее эту команду или пытаться понять - зачем ее туда поместили и как ее обойти.
  13. Может пока вы неспешно выполняли команду за командой успело произойти какое-то событие, без которого программа в функцию заходить не должна? Или, как тут правильно намекнули, вы ставите точку останова на выражение, которое компилятор соптимизировал настолько, что уже не в состоянии найти соответствующую его началу ассемблерную инструкцию (на адрес которой он должен поставить точку останова).
  14. Тогда я пас. Как известно, CV - компилятор с "языка, похожего на C". Если бы программа была написана на C, то без volatile компилятор, зная содержимое delay_ms() (т.е. зная, что A в ней не меняется), имел бы полное право выкинуть проверку (A!=1) из цикла, так как прямо перед циклом A = 0 и в цикле A не меняется.
  15. Какие еще у нее есть свойства? Присутствует ли в ее объявлении квалификатор volatile?
  16. Но компилятор-то об этом не знает. Для него есть четкое правило: signed int * signed int = signed int. Если же у вас результат в signed int не укладывается - вам нужно делать signed long * signed long = signed long. Для этого необходимо хотя бы один из сомножителей привести к signed long. Второй сомножитель будет приведен неявно согласно правилам неявных приведений целых типов (integer promotion rules). То есть ваше выражение должно выглядеть так: a = (unsigned long)(b-c) * 100 / d; или так: a = (b-c) * 100L / d; Если же и результат разности у вас может выходить за диапазон целого со знаком, то вам нужно привести к unsigned long уменьшаемое или вычитаемое (остальное будет приведено согласно правилам неявных приведений целых). Как вы это наблюдали?
  17. Он же Гога Molex 500873, только без крыльев дырочек. Ан нет, чуток другой. Вычеркиваю.
  18. Значит проблема где-то раньше, во входной массив уже попадают кривые данные. А почему вы не хотите посмотреть эти принятые данные внутрисхемным отладчиком?
  19. P.S. я бы писал это примерно так: #define NCHANNELS 2 #define NSAMPLES 4 #define NDUMMY 1 typedef int16_t sample; typedef sample input_sample[NCHANNELS]; typedef input_sample input_buffer[NSAMPLES + NDUMMY]; typedef sample output_channel[NSAMPLES]; typedef output_channel output_buffer[NCHANNELS]; input_buffer Input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; output_buffer Output; void shuffle(int channel) { for(int i = 0; i < NSAMPLES; ++i) Output[channel][i] = Input[i + NDUMMY][channel]; } https://onlinegdb.com/S1fShTnED
  20. В чем, по-вашему, она заключается? Криминала я не вижу. Конечно назвать переменные audioBuf и audioBuff - знатная грабля на будущее, но это каждый сам себе злобный сами знаете кто. А что мешает в целях отладки сделать #define NSAMPLES 4 //Must be order of 2 #define NDUMMY 1 //Dummy samples are needed to minimize influence of filter settling after invoking the SAI int16_t audioBuf[(NSAMPLES + NDUMMY) * 2] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; ... void DSP_Sample(void){ /* extern SAI_HandleTypeDef haudio_in_sai; HAL_StatusTypeDef res = HAL_SAI_Receive(&haudio_in_sai,(uint8_t*) audioBuf, (NSAMPLES + NDUMMY) * 2, HAL_MAX_DELAY); if (HAL_OK != res) { CRASH_(15,"HAL_SAI_Receive failed"); } */ DSP_Sample_send(0); //заполняем 512байт левый канал DSP_Sample_send(1);//заполняем 512байт правый канал /* HAL_SPI_Transmit(&hspi3, (uint8_t*) audioBuff, (NSAMPLES + NDUMMY) * 2, HAL_MAX_DELAY); */ } и прогнать это под отладчиком? Если нет отладчика - написать простейшую консольную программу для PC, которая прогонит на этом массиве тот же алгоритм и распечатает выходной массив на экран.
  21. Напишите для этого случая другую задержку на любом свободном таймере: запретите прерывание этого таймера в NVIC, но разрешите в самом таймере, отключите бит SLEEPDEEP, выполните _WFE() и ожидайте события от этого таймера в режиме Sleep.
  22. Два диода. Второй - на обратной стороне платы.
  23. Дошли руки побаловаться. Скачал у микрософта свежий образ виртуалки W10, проверил - действительно, ставит драйвера для vcp в композитном устройстве автоматически. Сравнил со своими дескрипторами - все совпадает кроме У меня тут стоит ноль. Раньше я тоже писал сюда единицу, но года два назад линух при втыкании такого устройства стал пытаться с криком "О! Модем подвезли" установить через него связь. Что в общем-то и логично. У ардуинщиков были сложности с этим по этой же причине - у них в дескрипторе этот же протокол указан. У вас упоминание тут AT commands имеет какое-то обоснование или тоже скопировано из примеров в интернете?
  24. Поднять CMUX, через один виртуальный канал работать с PPP, через второй получать URC о приходе СМС и вообще делать все, что угодно AT-командами не прерывая PPP.