Перейти к содержанию
    

Сергей Борщ

Модератор
  • Постов

    10 908
  • Зарегистрирован

  • Посещение

  • Победитель дней

    31

Сообщения, опубликованные Сергей Борщ


  1. Микросхема U2 - память? Если да - есть ли с ней обмен при подаче питания на плату? Если обмен есть - прочитайте ее программатором, сохраните резервную копию и залейте содержимое такой же микросхемы с рабочей платы. Если не поможет - контролер устал, восстановление, вероятнее всего, нерентабельно. Если обмена с памятью нет и все питания на месте - проверять уровень сигнала на 14 ноге контроллера (должен быть высокий). Если и там все в порядке - значит контроллер устал.

  2. Можно сделать какую-нибудь тайную команду загрузчику - например, проверка свободной ноги на притяжку к земле и в этом случае в ответ на опять же недокументированную посылку по одному из выведенных наружу интерфейсу выдачу дампа всех задействованных областей флеша. Потом эти дампы залить в устройство без установленной защиты от чтения и уже в нем отладчиком найти причину окирпичивания.

  3. 10 минут назад, fpga_student сказал:

    Во-первых я конечно же смотрел и reset и boot0 и питание. На столе все идеально и откуда бы там что взялось ?

    Отсюда:

    image.png.bf2576a797130f3ed4c882615f5ed12d.png

    Ну раз там все чисто - значит как минимум постоянного циклического перезапуска не происходит и программа где-то "зависла".

  4. Посмотрите осциллографом на ногу RESET отказавшей платы. Если по какой-то причине идет постоянный перезапуск программы - на ноге RESET будут постоянные импульсы. Если они там есть - думать, почему происходит перезапуск. Можно доработать загрузчик, чтобы по определенному уровню на какой-то из ног он не передавал управление основной программе, а выдавал в какой-то отладочный канал контрольную сумму своей области и областей приложения. Если эта часть загрузчика в отказавшем приборе не будет работать - можно будет сделать вывод о порче загрузчика, если будет - поможет определить, это порча основной программы или какая-то непредусмотренная ее реакция на внешние условия (на какое-то состояние области настроек, например).

    У меня на STM32WL5 были похожие симптомы при невосстановимой порче корректирующего кода флеша - при попытке чтения сбойнувшей ячейки происходило исключение NMI. В вашем F42x такого механизма нет во флеше нет, но, возможно, есть другой, похожий. Что в вашей программе происходит при возникновении необработанного исключения?

  5. Сообщение говорит о том, что программатор не смог связаться с ядром по SWD. До определения типа дело не дошло. Либо проблема с подключением, либо в контроллере крутится программа, которая ушла в глубокий сон либо отключила ноги SWD -в последних двух случаях надо завести с программатора сигнал сброса и в его настройках указать "connect under Reset" или что-то подобное. Как это сделать - не подскажу, пользуюсь openicd, 

  6. 14 минут назад, Aries сказал:

    bit.w 0DD36h(PC), &24F4h в таком виде всё прекрасно компилируется.

    Сейчас компилируется и даже когда вы захотите потом изменить проект и dat слегка сместится оно тоже будет компилироваться, но работать уже не будет. И любой читающий этот плод вашей работы будет ломать голову над магическим числом 0DD36, посылая вам лучи поноса.

  7. Когда дописывал порт mspgcc под ядро 430Х, помнится, использовал свойство ядра при выходе за адресное пространство попадать в младшие адреса. На пальцах - если условно максимальный адрес 0x100, то 0xF0 + 0x20 попадает в 0x10. Если память не изменяет (почти 20 лет прошло), делал для этого отдельный ключ компоновщику. Посмотрите в документации, нет ли у компоновщика IARa подобного ключа. В названии может быть "address wrap" или что-то подобное.

  8. 1 час назад, aem сказал:

    Они не используют CMSIS и SPL? Или как-то иначе?

    А там, где вы нарабатывали свои заделы (подозреваю, что в виндовсе) вы системные функции ОС не вызывали? Или думаете, они на плюсах написаны? Там все то же самое - могучий extern "C" позволяет вызывать сишные и прочие ассемблерные функции из плюсов в любой среде.

    • Upvote 1
  9. 6 минут назад, Aries сказал:

    но как только я заменяю строку - линкер начинает ругаться.

    Как именно он начинает ругаться - нам предлагается угадать? К сожалению (на самом деле нет), на этом форуме викторины не проводятся.

  10. 4 часа назад, AzardCry сказал:

    нужно указать ключ -cpp в закладке C/C++

    Насколько я понимаю - вы заставили принудительно все файлы (включая библиотеку SPL) компилироваться в режиме C++. Не думаю, что это правильное решение - языки отличаются и не всякий C-код будет собираться как код C++. А надо было просто разобраться, почему включаемые в ваш main.cpp объявления C-функций не имеют спецификатора extern "C".

     

  11. Если вылетает "сразу" - вполне возможно, что вы выбрали в среде разработки модель с бОльшим количеством памяти, чем есть в вашем контроллере. Поэтому компилятор разместил стек в несуществующей памяти и первая же инструкция записи на стек приводит к исключению. Самый простой и быстрый (на мой взгляд) способ проверить это - вставить в программу вот такой обработчик исключения HardFault:

    void HardFault_Handler(void)
    {
        volatile int i = 0;
        while(!i)
            ;
    }

    Попав в него вы переводите отладчик в режим исполнения ассемблерных команд (не помню, как это делается в Кейле - возможно, надо открыть и сделать активным окно дизассемблера), через отладчик заносите в i любое не равное 0 значение и двигаясь по ассемблерным командам выходите из обработчика. Попадаете на следующую инструкцию после той, которая вызвала исключение. Смотрите на нее, смотрите на содержимое использованных в ней регистров, думаете, почему там появились именно эти значения и какими они должны быть для правильной работы. Если же вы попадаете куда-то за пределы памяти программ - тогда все несколько сложнее, можно и книги Ю читать или тупо несколько раз выполнить программу с самого начала по ассемблерным командам найдя ту, на которой происходит падение.

  12. 1 час назад, Aries сказал:

    Как влиять на это ???

    Один и тот же результат операции может быть достигнут разными командами. Даже ассемблер пытается делать программу компактной и быстрой, а вы хотите делать ее большой и медленной (доля шутки). То есть заставить чистый ассемблер ставить неоптимальный код команды в одно конкретное место скорее всего будет невозможно. Единственное, что здесь может сработать - использовать связку ассемблер-компоновщик (линкер) и команду занесения в регистр неизвестной ассемблеру константы, подставляемой компоновщиком. Поскольку значение константы асссемблеру неизвестно - он будет вынужден поставить подходящий для произвольной константы более длинный и медленный код. И останется только надеяться, что компоновщик именно вашей версии IARа не умеет оптимизировать выходной код или эту оптимизацию можно принудительно отключить. Как это сделать конкретно в современном IAR я не знаю и присоединяюсь к совету jcxz почитать про раздельную компиляцию и работу компоновщика.

  13. 50 минут назад, djhall сказал:

    но в этот раз появилось сообщение, что овальные отверстия не могут быть просверлены.

    Откуда появилось сообщение?

     

    Кикад пихает и овальные и круглые отверстия в один файл. JLCPCB делает по этим файлам платы с круглыми и овальными отверстиями без вопросов.

  14. 3 минуты назад, Arlleex сказал:

    А std::aligned_storage это что-то наподобие __attribute__((aligned(x)))?

    Слушать аудиосказку Вовка в тридевятом царстве (1965 г.)

    https://en.cppreference.com/w/cpp/types/aligned_storage

    3 минуты назад, Arlleex сказал:

    Просто какой способ правильнее - атрибутами задать выравнивание и т.д., либо этим aligned_storage?

    std:: как бы намекает, что это будет работать всегда с любым компилятором без шаманства.

  15. 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() указатель отвечает всем требованиям к выравниванию и прочему, 

    • Upvote 2
  16. 2 часа назад, Arlleex сказал:

    приходят к примерно одному мнению - чтобы наложить структуру на буфер (я про подход, где гарантированно не будет проблем с активизацией членов union и strict aliasing), надо *боже дай мне сил не материться* скопировать этот буфер в объект такой структуры

    Есть еще вариант с placement new().

  17. 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&'
    }

     

    • Upvote 1
  18. 42 минуты назад, Arlleex сказал:

    Но, опять же, у Вас шаблонная функция, я бы хотел избежать этого

    Эта шаблонная функция тупо передает другой (нешаблонной) указатель и размер структуры. Результат проверки известен на этапе компиляции. То есть код шаблонной функции занимает ровно ноль лишних байтов. Вам бы все равно пришлось передавать указатель и размер вручную (с шансом ошибиться). Да, я забыл сделать ее inline, но компилятор, скорее всего, догадается сам.

  19. 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'
    }

     

×
×
  • Создать...