-
Постов
5 813 -
Зарегистрирован
-
Посещение
-
Победитель дней
14
Arlleex стал победителем дня 6 апреля
Arlleex имел наиболее популярный контент!
Репутация
131 Очень хорошийИнформация о Arlleex
-
Звание
Гуру
Контакты
-
ICQ
Array
Посетители профиля
-
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Нет, с точки зрения аппаратной реализации мне как раз понятно все. Я говорил об историческом наследии именно в программном обеспечении, реализующим всякие ширпотребные протоколы. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Можете наглядно показать, что Вы имели в виду? Ибо я читаю это как попытаться запихнуть структуру с FAM в другую структуру, и дописать за ней CRC. Но любые попытки сделать так тщетны, т.к. нельзя использовать FAM-структуры как член другой структуры. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Вы правы, косяк в этом есть. До какого-то момента писал так - вот и попал кусок сюда в том виде в каком есть. Но на самом деле сколько своего писал, сколько чужого лопатил - пока что ни разу не удалось нарваться на конфликт дефайнов)) Возможно, потому, что в моих исходниках мало подключений сторонних библиотек. А те, что подключаются, не пересекаются названиями. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Ды кто его теперь знает. Исторически в конец всегда запихивал. А сейчас понимаю, что с точки зрения языка программирования это очень выходит костыльно. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Из крайнего проекта (извернулся трюком с union, но это все равно громоздко и муторно): // это с компа надо отправить в железку, а та отправит в свой RS-485 len байт struct sTxMsgRS485SendCmd { sMsgHdr hdr; eMsgUID uid; u32 ifNum; u32 len; union { u8 byte[MAX_RS485_TX_SIZE + sizeof(u32)]; // - эта добавка sizeof() как раз для CRC-поля u32 crc[(MAX_RS485_TX_SIZE + sizeof(u32)) / sizeof(u32)]; // а это чтоб представить весь буфер как набор u32 crc[] }; }; ... void send() { sTxMsgRS485SendCmd tx; tx.hdr.srcAddr = HOST_ADDR; tx.hdr.dstAddr = MBC_ADDR; tx.uid = WORK_REQ_MBC_SEND_RS485; tx.ifNum = 0; u32 const len = /* считал с окошка программы */; u32 i = 0; while(i < len && i < MAX_RS485_TX_SIZE) tx.byte[i] = /* чтение с окошка ввода */()[i++]; tx.len = i; if(i > 0) { i = (i + 3) / 4; // ровняю по u32 u32 const size = sizeof(tx) - (MAX_RS485_TX_SIZE - i * 4); // началось в деревне лето... считаю общий размер кадра tx.crc[i] = crc_Calc(&tx, size / 4 - 1); // фокус с union <- вот он /* ethernet_send() */(&tx); } } Ну вот визуально - полная шляпа выходит)) А хотелось копеечка к копеечке - все заполнили и отправили, без хитрых представлений и закулисных допущений. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Вот я и хотел, чтобы визуально CRC присутствовала в структуре, чтобы и мне (спустя время) и другому человеку было понятно, что содержится в теле пакета. В чем текущее неудобство. Пример. К МК подцеплен езернет и CAN, и пусть это будет некий преобразователь интерфейсов. Езернет цепляется к компу. Комп периодически поллит входящую очередь CAN-а, для чего шлет пакет-запрос READ_CAN_FIFO. МК по этому запросу формирует ответ в виде структуры struct ReadCANAck { Header hdr; CANFrame frame[]; }; Вопрос - где эту структуру создать в памяти. Понимаем, что нижестоящие функции отправки в сеть требуют структуру "целиком", т.е. непрерывным массивом известной длины. Значит можно запихнуть эту структуру в union #define MAX_SEND_MESSAGE_SIZE MAX_ETH_UDP_PAYLOAD_SIZE union SendMessage { ReadCANAck readCANAck; ... ; // возможно, другие "форматки" для других команд u8 buffer[MAX_SEND_MESSAGE_SIZE]; }; Мы заранее не знаем, сколько там в CAN-е может храниться принятых кадров, поэтому после заполнения хедера ответа, мы читаем N кадров CAN-FIFO и заполняем свободное место пэйлоада езернет-фрейма, чуть ли не вот так static SendMessage Tx; void sendCANRxFIFO() { // не насилуем стек - готовим кадр в одном месте Tx.readCANAck.hdr.cmd = READ_CAN_FIFO; // сколько там в CAN фреймов пришло? u32 const frameCnt = CAN.getFrameCnt(); // запихиваем CAN-кадры из его FIFO, пока место в буфере отправки в езернет еще есть for(u32 i = 0; i < frameCnt; ++i) { if(/* места в езернет-фрейме еще хватает ? */) Tx.readCANAck.frame[i] = CAN.readFrame(); } } и вот теперь: беда. Мы договорились, что в протоколе обмена все кадры имеют CRC последним членом. Тут (примера ради) его не было показано. Но этот CRC подразумевался. В структуре ReadCANAck его нельзя после frame[] поставить. И это порождает 2 проблемы: 1) визуально нет поля CRC в пакете - т.е. или я, или сторонний разраб, которому я дам эту структуру, может "забыть", что там еще CRC считать надо и заполнять (а еще и место в памяти выделять!); 2) после заполнения основных указанных полей, в силу "отсутствия" явного описания CRC в структуре отправки - мы должны костыльными приведениями типов и адресацией залезть за последний записанный frame и вставить туда CRC. Это может (и будет!) выглядеть плохо! Так как сходу не будет понятно, с какого лешего мы пишем "за пределы структуры" какую-то там CRC: void sendCANRxFIFO() { ... u32 i; // запихиваем CAN-кадры из его FIFO, пока место в буфере отправки в езернет еще есть for(i = 0; i < frameCnt; ++i) { if(/* места в езернет-фрейме еще хватает ? */) Tx.readCANAck.frame[i] = CAN.readFrame(); } *(u32 *)&Tx.readCANAck.frame[i] = calcCRC32(&Tx, /* правильно посчитать len */); // <- через пару месяцев: WTFFFFFFFFFFFF??? } -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Разумное число - у всех разное, поэтому его либо заранее обговаривать в ТЗ, либо пытаться сделать так, чтобы программист вообще об этом не думал - т.е. технически победить ограничение. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Нет не так. Структурой я описываю все содержимое кадра - хедеры, данные и т.д., в том числе CRC. Обрамление кадра - совершенно другая процедура, ее структарми не опишешь. Да и незачем. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Я такие документики тоже делаю - только для такого рода девайсов, где потенциальный заказчик - любой с планеты Земля. А когда надо внутри отдела между парой-тройкой разрабов договориться - никакой писаниной заниматься времени нет. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Нет. Никаких CRC writeTxFIFO() не считает и не дописывает. Условно: void sendTemperature() { ExchDesc<Temperature> t; t.hdr.dst = HOST_PC; t.temp = getTemperature(); t.crc = CRC32(&t, sizeof(t) - 4); SLIP.send(&t, sizeof(t)); // вот внутри нее содержимое 't' обернется в кадр и вызовется writeTxFIFO() } -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Обычно в этом корень всех бед. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Да. Так делают, например, топовые гиганты типа интел/амд/нвидиа. И да, я не видел ни одной фирмы, где прям по серьезке садились бы считать байты ОЗУ, которые потребуются для задачи, ибо хотя бы найти челвоека, который это умеет и потом будет в случае чего отвечать - та еще задача. Обычно смотрят по верхушкам - устраивает ли МК/проц по интерфейсам и их скоростям, режимам и т.д. Можно ли его купить в обозримом будущем в тех же объемах, что он продается сейчас. У инженера обычно в комплекте где-то в районе пятой точки есть чуйка, которая подсказывает ему, хватит ли ему ресурсов или будет маловато. Чуйка обучается опытом а потом подтверждается расчетами. -
STM32F103 переход в default_handler
Arlleex ответил addi II тема в Программирование
... или стартап-файл не под свой контроллер налутал)) -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Есть, конечно)) Но эта ошибка из разряда "вернуть адрес локальной переменной из функции" - т.е. бывалым разработчиком не допустится🙂 Операции с DMA либо блокирующие (костыль, не делаю так никогда), либо функция отправки пишет в буфер, из которого DMA спокойно будет отправлять, а из той функции можно смело выходить. Я стремлюсь всегда разделять уровни кода, поэтому все очень просто становится читать и поддерживать. Вот так выглядит интерфейс чтения/записи в UART #ifndef _UART_HPP_ #define _UART_HPP_ #include "macros.h" namespace nsUART { void init(); u32 readRxFIFO (u8 dst[], u32 len); s32 writeTxFIFO(u8 src[], u32 len); } #endif И совершенно не важно, что передача и прием реализованы как кольцевой буфер с задействованным DMA как на прием, так и на передачу. Задача (или цикл) парсера вызывает readRxFIFO() и разгребает входящий поток байтов: если нащупала что-то осмысленное - вызывает функцию разбора пакетов. Если хотим отправить данные - вызываем соотв. функцию и передаем ей эти данные, она их кодирует, обрамляет как надо и вызывает writeTxFIFO(). -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Отключать то зачем? Скорее, просто следить за когерентностью данных и вовремя их флушить/инвалидировать. Я тоже могу представить контекст, в котором эти сентенции уместны. Но они точно не уместны при тезисном описании в википедиях и тем более не применимы в технических дискуссиях за свод нерушимых правил, преклоняясь перед авторитетом дяди в очках с задней обложки книжки. На всякий случай, повторюсь🙂 Я цифру 1024 написал от балды, это лишь для примера было. На самом деле у меня отправляемые пакеты создаются по мере необходимости к отправке, т.е. на стеке. А вот под принимаемые пакеты как раз статически выделяется буфер-агрегатор (в виде Си-шного union) под самый длинный возможный пакет. Т.е. если максимально возможный принимаемый пакет будет, например, 1000 байт - будет создан буфер на 1000 байт или чуть больше для локальных требований к выравниванию и т.д. В особых случаях, когда памяти почти нет (ОЗУ), а линия связи позволяет отправлять данные порционно - то можно так и делать. Например, тот же SLIP по UART-у можно не кодировать предварительно, а кодировать по мере отправки очередного символа. С тем же езернетом так не получится - внутри одного езернет-кадра будь добр подготовить все нужные данные сразу.