-
Постов
10 921 -
Зарегистрирован
-
Посещение
-
Победитель дней
31
Сообщения, опубликованные Сергей Борщ
-
-
Если вылетает "сразу" - вполне возможно, что вы выбрали в среде разработки модель с бОльшим количеством памяти, чем есть в вашем контроллере. Поэтому компилятор разместил стек в несуществующей памяти и первая же инструкция записи на стек приводит к исключению. Самый простой и быстрый (на мой взгляд) способ проверить это - вставить в программу вот такой обработчик исключения HardFault:
void HardFault_Handler(void) { volatile int i = 0; while(!i) ; }
Попав в него вы переводите отладчик в режим исполнения ассемблерных команд (не помню, как это делается в Кейле - возможно, надо открыть и сделать активным окно дизассемблера), через отладчик заносите в i любое не равное 0 значение и двигаясь по ассемблерным командам выходите из обработчика. Попадаете на следующую инструкцию после той, которая вызвала исключение. Смотрите на нее, смотрите на содержимое использованных в ней регистров, думаете, почему там появились именно эти значения и какими они должны быть для правильной работы. Если же вы попадаете куда-то за пределы памяти программ - тогда все несколько сложнее, можно и книги Ю читать или тупо несколько раз выполнить программу с самого начала по ассемблерным командам найдя ту, на которой происходит падение.
-
11 часов назад, EUrry сказал:
с безопасностью от поражения тока
Току все равно, его поразить невозможно. Вероятно, вы имели ввиду "от поражения током"?
-
5 часов назад, MaximDV сказал:
Понял, принял, видимо не в ту ветку написал о помощи новичку.
-
1 час назад, Aries сказал:
Как влиять на это ???
Один и тот же результат операции может быть достигнут разными командами. Даже ассемблер пытается делать программу компактной и быстрой, а вы хотите делать ее большой и медленной (доля шутки). То есть заставить чистый ассемблер ставить неоптимальный код команды в одно конкретное место скорее всего будет невозможно. Единственное, что здесь может сработать - использовать связку ассемблер-компоновщик (линкер) и команду занесения в регистр неизвестной ассемблеру константы, подставляемой компоновщиком. Поскольку значение константы асссемблеру неизвестно - он будет вынужден поставить подходящий для произвольной константы более длинный и медленный код. И останется только надеяться, что компоновщик именно вашей версии IARа не умеет оптимизировать выходной код или эту оптимизацию можно принудительно отключить. Как это сделать конкретно в современном IAR я не знаю и присоединяюсь к совету jcxz почитать про раздельную компиляцию и работу компоновщика.
-
50 минут назад, djhall сказал:
но в этот раз появилось сообщение, что овальные отверстия не могут быть просверлены.
Откуда появилось сообщение?
Кикад пихает и овальные и круглые отверстия в один файл. JLCPCB делает по этим файлам платы с круглыми и овальными отверстиями без вопросов.
-
3 минуты назад, Arlleex сказал:
А std::aligned_storage это что-то наподобие __attribute__((aligned(x)))?
https://en.cppreference.com/w/cpp/types/aligned_storage
3 минуты назад, Arlleex сказал:Просто какой способ правильнее - атрибутами задать выравнивание и т.д., либо этим aligned_storage?
std:: как бы намекает, что это будет работать всегда с любым компилятором без шаманства.
-
48 минут назад, Arlleex сказал:
Объясните, пожалуйста, на пальцах, если не трудно.
std::aligned_storage резервирует память необходимого размера и с необходимым выравниванием с гарантией отсутствия неопределенного поведения.
placement new располагает в этой области необходимую вам структуру и возвращает указатель на нее. Дальше можно работать с этим указателем, мне больше нравится работать со ссылкой. Эта структура должна иметь конструктор, который не делает с этой структурой ничего (в данном случае это конструктор по умолчанию).
#include <type_traits> std::aligned_storage<sizeof(uint32_t), alignof(uint32_t)> Buffer[512 / sizeof(uint32_t)]; struct packet { uint32_t A; uint16_t B; uint8_t C; }; #include <new> void test() { auto const & Packet = *(new(Buffer) packet); uint32_t A = Packet.A; uint16_t B = Packet.B; uint8_t C = Packet.C; }
Фактически placement new() приводит переданный ему указатель к нужному типу и вызывает конструктор с этим указателем. Программист должен гарантировать, что переданный в placement new() указатель отвечает всем требованиям к выравниванию и прочему,
-
2
-
-
2 часа назад, Arlleex сказал:
приходят к примерно одному мнению - чтобы наложить структуру на буфер (я про подход, где гарантированно не будет проблем с активизацией членов union и strict aliasing), надо *боже дай мне сил не материться* скопировать этот буфер в объект такой структуры
Есть еще вариант с placement new().
-
13 часов назад, Arlleex сказал:
Идея ясна, спасибо.
Вот, придумался более простой вариант:
struct sendable {}; struct a : public sendable { }; struct b {}; inline void send_msg(sendable const & from, size_t size) { auto pSrc = static_cast<void const *>(&from); ............... } template<typename T> void send_msg(T const & data) { send_msg(data, sizeof(T)); } template<typename T, size_t items> void send_msg(T const (& data)[items]) // если вдруг потребуется передавать массив структур { send_msg(data[0], sizeof(T) * items); } void test() { a Good = {}; a Good2[2] = {{}, {}}; b Bad = {}; send_msg(Good); send_msg(Good2); send_msg(Bad); // error: no matching function for call to 'send_msg(const b&, unsigned int)' // <- note: no known conversion for argument 1 from 'const b' to 'const sendable&' }
-
1
-
-
42 минуты назад, Arlleex сказал:
Но, опять же, у Вас шаблонная функция, я бы хотел избежать этого
Эта шаблонная функция тупо передает другой (нешаблонной) указатель и размер структуры. Результат проверки известен на этапе компиляции. То есть код шаблонной функции занимает ровно ноль лишних байтов. Вам бы все равно пришлось передавать указатель и размер вручную (с шансом ошибиться). Да, я забыл сделать ее inline, но компилятор, скорее всего, догадается сам.
-
1 час назад, Arlleex сказал:
А функция отправки принимает любой из допустимых форматов, описанных в этой библиотеке. Соответственно, ее реализация одна, а принимает она некий общий тип.
Я бы делал примерно так:
struct sendable { enum class tag { OK }; static constexpt tag Tag = tag::OK; }; struct a : public sendable { .............. }; struct b { ............ }; void send_msg(void const * from, size_t size); template<typename T> void send_msg(T const & data) { if(data.Tag == sendable::tag::OK) send_msg(&data, sizeof(T)); } void test() { a Good = {}; send_msg(Good); b Bad = {}; send_msg(Bad); // <-- compile error Bad has no member 'Tag' }
-
1 час назад, MPetrovich сказал:
Tue Mar 14, 2023 11:43:42: Firmware version 0.0.0.0
Меня бы насторожили эти нули и я бы попробовал эту Firmware как-то обновить, чтобы цифры были более осмысленные. Но это чисто абстрактные рассуждения.
-
27 минут назад, Arlleex сказал:
А Flash сделать обычной.
Если ничего не путаю, GD изначально занималась флеш-памятью. То есть это не к готовому ядру прикрутили внешнюю флеш, а к готовой флешке прикрутили ядро.
-
3 часа назад, zheka сказал:
в ячейке 0x1FFFF7E0 содержится 00 00 00 00 CA 5C 5A 1A В правильном чипе 80 00 FF FF FF 58 4B 4A
Какая-то лютая отбраковка без флеша вообще? Согласно документации размер флеша 0 килобайт:
Бросьте каку 🤣
Следом за первыми двумя байтами идет 96-битный уникальный ID, который может быть любым.
3 часа назад, zheka сказал:Проверка показала, что Bits 26:24 SWJ_CFG[2:0]: Serial wire JTAG configuration - в принципе недоступны для записи
В чем дело то?
Надеюсь, вы перед обращением к этому регистру включаете его тактирование в RCC->APB2ENR.AFIO_EN?
-
25 минут назад, MrGalaxy сказал:
неиспользованные выводы портов целесообразнее оставить неподключёнными или соединить с GND/Vcc?
Оставить неподключенными и настроить на вывод.
-
1
-
-
1 час назад, MrGalaxy сказал:
или можно обращаться к отдельным элементам массива, не загружая его полностью?
Разумеется, должно быть можно. Ведь даже чтобы загрузить этот массив в ОЗУ нужно обращаться к его отдельным элементам в памяти программ.
Вот, из его документации:
ЦитатаШесть регистров из 32 могут использоваться как три 16-разрядных регистра косвенного адреса для эффективной адресации в пределах памяти данных. Один из этих указателей может также использоваться как указатель адреса для доступа к памяти программ.
-
1
-
-
12 часов назад, zheka сказал:
Не тот кристалл в не то корпус распаяли?
Да, похоже на то. Мне (не на Али) в разгар кризиса поставщик привез партию F100, половина которой оказалась перемаркированными F103. Ваши либо 101xC/D/E, либо 103xC/D/E. Точнее букву можно узнать по содержимому ячейки 0x1FFFF7E0. А вот отличить 103 от 101, наверное, только по регистрам RCC->AHBENR, RCC->APBxENR - для 101 там не должны устанавливаться в 1 биты несуществующих таймеров, USB, CAN, SDIO.
-
5 часов назад, Variant99 сказал:
Так это ж алгоритм DDS
Именно. Имеем предварительно рассчитанную таблицу одного (половины/четверти/одной восьмой) периода в постоянной памяти, из которой с нужным шагом выбираем значения (на каких-то частотах каждое n-е значение, на каких-то одно и то же значение k раз), умножаем на необходимую амплитуду в формате фиксированной точки и кладем в массив в ОЗУ, из которого ПДП (DMA) в нужные моменты времени забирает данные в таймер. Заполнение половин массива ОЗУ в прерываниях окончания передачи (TIF) и окончания половины передачи (HTIF). Одно умножение на отсчет. Для остальных фаз то же самое со сдвигом на 1/3 и 2/3 исходной таблицы. У меня по такому принципу ATmega88 на 16 МГц успевала без ПДП и ассемблера в исходниках выдавать шесть фаз синуса 400 Гц из таблицы на 1/8 периода синуса, а STM32F100 на 24 МГц с ПДП формировать два FFSK без разрыва фазы на 1200/2400 не особо напрягаясь.
У Л. И. Ридико прекрасная статья по реализации DDS.
-
5 часов назад, LAS9891 сказал:
У меня на самом деле GD32F103RB, и тут я не нашёл System configuration controller
Путаетесь в показаниях 🤨:
В 01.03.2023 в 15:19, LAS9891 сказал:Есть stm32
Сказали бы сразу про GD32 - я бы за вас его документацию почитал
-
-
Если одна кнопка на PA0, вторая - на PB0, то только одна из них может быть настроена на EXTI. То есть исходная задача не решается вообще никак - только одна из кнопок на Px0 может вызывать прерывание. Одну из кнопок надо уносить на PxY, где X - любой, а Y != 0.
-
1
-
-
44 минуты назад, Freibier сказал:
2.5 W * 2 Channel) / 5V = 1 A
Там же мостовое включение нагрузки, значит к нагрузке прикладывается удвоенное напряжение питания.
-
Потому что нагрузка включается в цепь стока. Понятий "перед транзистором" и "после транзистора" не существует.
-
1
-
1
-
-
Keil. Библиотеки
в Keil
Опубликовано · Пожаловаться
Насколько я понимаю - вы заставили принудительно все файлы (включая библиотеку SPL) компилироваться в режиме C++. Не думаю, что это правильное решение - языки отличаются и не всякий C-код будет собираться как код C++. А надо было просто разобраться, почему включаемые в ваш main.cpp объявления C-функций не имеют спецификатора extern "C".