Добрый день.

Пишу первый раз для аудитории, поэтому представлюсь. Зовут меня Артём, я разработчик приложения VestaXR для автомобилей LADA. Это приложение является бортовым компьютером для машин с магнитолами (ГУ) на базе Андроид, которое взаимодействует с машиной через электронную плату (канбас), и отправляет сигналы с каншины в ГУ и обратно, позволяя получать все данные и управлять некоторыми настройками автомобиля. Изначально канбас строился на базе STM32F405. Но настали времена, когда этот микроконтроллер стал дорогой и попал под санкции.

И вот волею судеб мне пришлось на время переквалифицироваться из программиста приложения для Андроид в программиста микроконтроллера (МК). Работать пришлось с МК, информации о котором очень мало, можно сказать даже что её толком нет. Всё что у меня было, это сайт производителя и один пример с led на github. Речь идёт о МК Artery AT32F403A.

По спецификации это очень навороченный МК

Опыт работы с STM32F405 у меня уже был, я правил уже готовую прошивку. Поэтому знаком с оболочкой Keil и принципами работы. Но я понимал, что здесь всё другое. Кроме конечно языка программирования.

Итак, две недели мозгового штурма, поиска информации и тупого копирования кода, принесли свои результаты. Я получил действующий канбас со всеми функциями, которые у него должны быть. работа с USB, CAN и USART. И я хочу с вами поделиться своим опытом, надеюсь кому-то это сэкономит время. Всё по порядку.

Моя первая статья будет о самом простом. Таймеры и LED. Так сказать "hello world"

Знакомимся с документами, выложенных на сайте производителя https://www.arterytek.com/en/product/AT32F403A.jsp

Для работы нам понадобится скачать следующие файлы (архив скачанных файлов в конце статьи):

  • AT32F403A_407_Firmware_Library_V2.1.4 - примеры и основные шаблоны

  • Keil5_AT32MCU_AddOn_V2.1.9 - файл данных для Keil и других средств разработки

  • AT_Link_20221221 - драйвера для программатора

Далее тестовая плата (у меня готовый канбас, с перепаянным МК. Стоял STM32F405, поставили AT32F403A. Разводку платы не пришлось менять. Жирный плюс!)

CanbusXR
CanbusXR

И наконец программатор AT-Link+

Итак, запускаем Keil. Нажимаем Pack installer. Далее Import Packs, находим расположение папки Keil5_AT32MCU_AddOn_V2.1.9. Выбираем наш МК и нажимаем "Открыть". итоге получаем такую картинку:

Когда справа у вас появится ваш МК, всё готово
Когда справа у вас появится ваш МК, всё готово

Открываем папку с примерами AT32F403A_407_Firmware_Library_V2.1.4\project\at_start_f403a\examples\tmr (это примеры таймеров). Находим папку timer_base. Как следует из названия, это базовый пример работы таймера. Открываем проект из папки mdk_v5. Всё стандартно и знакомо, не правда ли?

Надо сказать спасибо, все примеры лежат по полочкам. Но осторожно, эти примеры для тестовой доски от Artery. В моём случае у меня уже есть плата.

Только-только открыли проект
Только-только открыли проект

Что же у нас есть в файле main.c:

  • void clkout_config - функция настройки внешнего генератора частоты

  • void TMR1_OVF_TMR10_IRQHandler - функция обработки таймера

  • main - главное тело программы, которое состоит:

  1. system_clock_config() - настройка тактирования всей платы. Не трогаем! К этому мы вернемся ещё в следующих постах

  2. at32_board_init(); - настройка отладочной платы. Нам она не нужна, поэтому закомментируем

  3. /* get system clock */
    crm_clocks_freq_get(&crm_clocks_freq_struct); - как следует из комментариев, настройка системных часов

  4. /* turn led2/led3/led4 on */
    at32_led_on(LED2);
    at32_led_on(LED3);
    at32_led_on(LED4); - включение led на плате. У нас их нет, закомментируем всё

  5. /* enable tmr1 clock */
    crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);

    /* tmr1 configuration / / time base configuration / / systemclock/24000/10000 = 1hz */
    tmr_base_init(TMR1, 9999, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
    tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);

    /* overflow interrupt enable */
    tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);

    /* tmr1 overflow interrupt nvic init */
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
    nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 0, 0);

    /* enable tmr1 */
    tmr_counter_enable(TMR1, TRUE); - здесь собственно и объявляется работа таймера

  6. clkout_config() - настройка внешнего генератора частоты

Находим строчку tmr_base_init(TMR1, 9999, (crm_clocks_freq_struct.ahb_freq / 10000) - 1). Здесь мы задаём время работы таймера.

Формула такая: время_сек * 10000 - 1. То есть 9999 это 1 секунда, 999 это 100 мс, 29999 - 3 секунды.

Обращаем внимание на надпись TMR1. Нажимаем F7, проект компилируется и нам теперь доступны переходы по телу проекта. Переходим по TMR1 и видим, что у нас можно сделать 14 таймеров

Прекрасно, не правда ли?
Прекрасно, не правда ли?

Итак, добавляем в теле главной функции main строчки с TMR2.

  /* enable tmr1 tmr2 clock */
  crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE);

  /* tmr1 tmr2 configuration */
  /* time base configuration */
  /* systemclock/24000/10000 = 1hz */
  tmr_base_init(TMR1, 9999, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
  tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
  tmr_base_init(TMR2, 29999, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
  tmr_cnt_dir_set(TMR2, TMR_COUNT_UP);

  /* overflow interrupt enable */
  tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);
  tmr_interrupt_enable(TMR2, TMR_OVF_INT, TRUE);

  /* tmr1 overflow interrupt nvic init */
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 0, 0);

  /* enable tmr1 tmr2 */
  tmr_counter_enable(TMR1, TRUE);
  tmr_counter_enable(TMR2, TRUE);

Строчка 19 - это объявление главной функции работы с таймерами. Она не меняется. Ищем эту функцию и тоже исправляем для TMR2:

void TMR1_OVF_TMR10_IRQHandler(void)
{
  if(tmr_flag_get(TMR1, TMR_OVF_FLAG) != RESET)
  {
    /* add user code... */
    //at32_led_toggle(LED3);
    tmr_flag_clear(TMR1, TMR_OVF_FLAG);
  }
  if(tmr_flag_get(TMR2, TMR_OVF_FLAG) != RESET)
  {
    /* add user code... */
    //at32_led_toggle(LED3);
    tmr_flag_clear(TMR2, TMR_OVF_FLAG);
  }
}

У нас получается что при срабатывании таймера флаг переходит в !reset, с выполняется код в скобках для каждого таймера отдельно.

Теперь что касается внешнего генератора, а так же объявления в коде пинов МК.

У Artery объявление пинов обозначается gpio_init_struct.gpio_pins = GPIO_PINS_8, без указания A, B, C, D, F, E. (зависит от количество ножек МК). Они указываются в двух строчках:

/* enable gpio port clock */
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); // - это его регистр, А

  /* set default parameter */
  gpio_default_para_init(&gpio_init_struct);

  /* clkout gpio init */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_14; // - это пин МК
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOA, &gpio_init_struct); // - это его регистр, А

То есть у меня на плате внешний генератор подцеплен на PA14. Если у вас на другой ноге, то и меняете в трёх местах: GPIOA, GPIOB, GPIOC и так далее.

С кодом разобрались, теперь надо настроить программатор для режима Debug.

переходим в Options for Target, и выбираем CMSIS-DAP. Нажимаем далее Settings. Выбираем программатор.

Нажимаем F7, компилируем, и нажимаем меню Debug - start/stop debug session, и через 5 секунд снова нажимаем F5 для запуска.

На плате тишина. Давайте проверим что таймеры работают. Поставим breakpoint на строчку первого таймера

Как мы видим, выполнение остановилось, значит и таймеры работают. Отлично! Нажмите Breakpoint на TMR2 и увидите, что он сработает через 3 секунды
Как мы видим, выполнение остановилось, значит и таймеры работают. Отлично! Нажмите Breakpoint на TMR2 и увидите, что он сработает через 3 секунды

Выйдем из режима debug и добавим функцию инициализации led и впишем её запуск в main

void init_led(void) {
    gpio_init_type GPIO_Init;

    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); // - очень важно не пропустить

	GPIO_Init.gpio_mode = GPIO_MODE_OUTPUT;
    GPIO_Init.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    GPIO_Init.gpio_pull = GPIO_PULL_NONE;
    GPIO_Init.gpio_pins = GPIO_PINS_1;
    GPIO_Init.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOC, &GPIO_Init);

    GPIO_Init.gpio_mode = GPIO_MODE_OUTPUT;
    GPIO_Init.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    GPIO_Init.gpio_pull = GPIO_PULL_NONE;
    GPIO_Init.gpio_pins = GPIO_PINS_2;
    GPIO_Init.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOC, &GPIO_Init);
}

LED у меня подключены на PC1 и PC2.

Для их включения или выключения есть уже готовые функции

    at32_led_off(LED3);
    at32_led_on(LED2);

Нажимаем F12 на LED3 и переходим в код настройки обозначений

У меня 2 led, поэтому LED_NUM = 2
У меня 2 led, поэтому LED_NUM = 2

Нажимаем F12 на at32_led_off в теле main и переходим на эту функцию, прокручиваем код вверх и меняем (создаём) текcт объявления переменных LED, убираем лишнее

Пишем вызов функций включения led в теле main:

    at32_led_on(LED3);
    at32_led_on(LED2);

Нажимаем F7, далее Debug и у нас загораются оба led. УРА! Поздравляю.

Теперь модифицируем функцию обработки таймеров:

void TMR1_OVF_TMR10_IRQHandler(void) {
    if(tmr_flag_get(TMR1, TMR_OVF_FLAG) != RESET) {
        /* add user code... */
        at32_led_toggle(LED3);
        tmr_flag_clear(TMR1, TMR_OVF_FLAG);
    }
    if(tmr_flag_get(TMR2, TMR_OVF_FLAG) != RESET) {
        /* add user code... */
        at32_led_toggle(LED2);
        tmr_flag_clear(TMR2, TMR_OVF_FLAG);
    }
}

И снова запускаем. Теперь led у нас перемигиваются. Один с частотой 1 секунда, второй с частотой 3 секунды.

Полный код main.с выглядит так:

#include "at32f403a_407_board.h"
#include "at32f403a_407_clock.h"

/** @addtogroup AT32F403A_periph_examples
  * @{
  */

/** @addtogroup 403A_TMR_timer_base TMR_timer_base
  * @{
  */

crm_clocks_freq_type crm_clocks_freq_struct = {0};

void clkout_config(void) {
    gpio_init_type gpio_init_struct;

    /* enable gpio port clock */
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

    /* set default parameter */
    gpio_default_para_init(&gpio_init_struct);

    /* clkout gpio init */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_14;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);

    /* config clkout division */
    crm_clkout_div_set(CRM_CLKOUT_DIV_1);

    /* config clkout clock */
    crm_clock_out_set(CRM_CLKOUT_PLL_DIV_4);
}

/**
  * @brief  this function handles timer1 overflow handler.
  * @param  none
  * @retval none
  */
void TMR1_OVF_TMR10_IRQHandler(void) {
    if(tmr_flag_get(TMR1, TMR_OVF_FLAG) != RESET) {
        /* add user code... */
        at32_led_toggle(LED3);
        tmr_flag_clear(TMR1, TMR_OVF_FLAG);
    }
    if(tmr_flag_get(TMR2, TMR_OVF_FLAG) != RESET) {
        /* add user code... */
        at32_led_toggle(LED2);
        tmr_flag_clear(TMR2, TMR_OVF_FLAG);
    }
}

void init_led(void) {
    gpio_init_type GPIO_Init;

    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);

	  GPIO_Init.gpio_mode = GPIO_MODE_OUTPUT;
    GPIO_Init.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    GPIO_Init.gpio_pull = GPIO_PULL_NONE;
    GPIO_Init.gpio_pins = GPIO_PINS_1;
    GPIO_Init.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOC, &GPIO_Init);

    GPIO_Init.gpio_mode = GPIO_MODE_OUTPUT;
    GPIO_Init.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    GPIO_Init.gpio_pull = GPIO_PULL_NONE;
    GPIO_Init.gpio_pins = GPIO_PINS_2;
    GPIO_Init.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOC, &GPIO_Init);
}

/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void) {
    system_clock_config();

    //at32_board_init();

    /* get system clock */
    crm_clocks_freq_get(&crm_clocks_freq_struct);

    /* turn led2/led3/led4 on */
    //at32_led_on(LED2);
    //at32_led_on(LED3);
    //at32_led_on(LED4);

    /* enable tmr1 tmr2 clock */
    crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE);

    /* tmr1 tmr2 configuration */
    /* time base configuration */
    /* systemclock/24000/10000 = 1hz */
    tmr_base_init(TMR1, 9999, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
    tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
    tmr_base_init(TMR2, 29999, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
    tmr_cnt_dir_set(TMR2, TMR_COUNT_UP);

    /* overflow interrupt enable */
    tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);
    tmr_interrupt_enable(TMR2, TMR_OVF_INT, TRUE);

    /* tmr1 overflow interrupt nvic init */
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
    nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 0, 0);

    /* enable tmr1 tmr2 */
    tmr_counter_enable(TMR1, TRUE);
    tmr_counter_enable(TMR2, TRUE);
    clkout_config();
    
	// enable led 
	init_led();
    at32_led_on(LED3);
    at32_led_on(LED2);


    while(1) {
    }
}

Ещё один плюс, это очень много комментариев по всем функциям, что облегчает задачу.

В принципе на этом первоначальное знакомство можно считать законченным.

Если вам понравилось, и полезно, дайте обратную связь. И я продолжу статьи про USB, CAN и USART.

Скачать архив с нужными файлами можно по ссылке.

Комментарии (38)


  1. progchip666
    06.04.2023 13:38
    +3

    Полезно.

    Также работаю в последние лет 7 с STM, но сегодня с ними всё больше проблем. Дорого, сложно покупать в товарных количествах.Практически отрезали возможность работать с китайскими клонами да и нет гарантии что в один прекрасный момент отрежут доступ к CUBE-IDE вообще


  1. Dima_Sharihin
    06.04.2023 13:38

    Artery'шная Firmware library, это, конечно, намного лучше, чем STM32 HAL, но она абсолютно пустая. БОльшая часть кода - это синоним регистрового доступа. Я не сильно большой фанат таких библиотек (в самом деле, зачем вызывать функцию, если можно писать в периферию напрямую, все равно из TRM не вылезать)

    Про многое из AT32 думаю, что "лучше бы они у ST этого не копировали бы", в частности ADC, модуль GPIO и прочие радости.


  1. ancc
    06.04.2023 13:38
    +4

    А почему именно этот мк, а например, не Gigadevice? Мы вот в своих устройствах успешно переехали на них с F4, причем остались на STшных библиотеках, подпилив их где надо и где они вообще использовались.


    1. arty_morris Автор
      06.04.2023 13:38
      +2

      Это мне не ведомо. Сказали с Artery будем работать


    1. misha_ruchk0
      06.04.2023 13:38

      Юристы из ST, кажется, очень не советуют использовать STшный код на GD чипах. Хотя... в некоторых странах это, наверное, уже не злободневно.


      1. ancc
        06.04.2023 13:38
        +2

        А есть какая-то ссылка на это?


        1. misha_ruchk0
          06.04.2023 13:38

          Наверно стоит заглянуть в лицензию в файлах исходных текстов от ST. Обратить внимание на то, что програмные инструменты от ST не работают (или не должны работать) с чипами от других производителей. Наконец можно поискать в сетке людей уже наступивших на эти грабли: https://www.th3dstudio.com/2021/08/03/gd32-cpu-license-issues-attack-of-the-clones/

          Сам вынужден был перетаскивать систему с STM32 на GD32 в прошлом году. К счастю, весь код опирался на регистры - заменяем один файл заголовков, подправляем чуточку код и наслаждаемся мелкими несвометимостями и особенностями GD32.


          1. ancc
            06.04.2023 13:38

            Ради интереса прошелся по тем файлам, которые мы используем...(мы не используем HAL, может там что-то и появилось)...и там есть только что-то типа:

              * Redistribution and use in source and binary forms, with or without modification,
              * are permitted provided that the following conditions are met:
              *   1. Redistributions of source code must retain the above copyright notice,
              *      this list of conditions and the following disclaimer.
              *   2. Redistributions in binary form must reproduce the above copyright notice,
              *      this list of conditions and the following disclaimer in the documentation
              *      and/or other materials provided with the distribution.
              *   3. Neither the name of STMicroelectronics nor the names of its contributors
              *      may be used to endorse or promote products derived from this software
              *      without specific prior written permission.
              *
              * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
              * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
              * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
              * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
              * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
              * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
              * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
              * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
              * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
              * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
             

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


            1. misha_ruchk0
              06.04.2023 13:38

              Окончательную ясность вносит содержимое первого пункта FAQ, находящееся в папке Documentation пакета STM32CubeF4 (для примера):

              What is the license scheme for the STM32CubeF4 firmware?

              The HAL is distributed under a non-restrictive BSD (Berkeley Software Distribution) license.

              The middleware stacks made by ST (USB host and device libraries, STemWin, ST- TouchGFX) come with a licensing model allowing easy reuse, provided it runs on an ST device.

              The middleware based on the well-known open-source solutions (FreeRTOS, FatFS, LwIP, and mbedTLS) has user-friendly license terms. For more details, refer to the license agreement of each middleware.

              HAL пилить выходит можно. Ограничения начинаются на более сложных поделках от ST.


      1. DrGluck07
        06.04.2023 13:38
        +1

        Мы просто с нуля пишем под гигадевайсы.


        1. misha_ruchk0
          06.04.2023 13:38

          Конечно, но если с нуля. А если, как в моем случае, весь код написан, а микросхемки от ST возьми да пропади на неопределенный срок... Пришлось прогибаться. ;)


          1. DrGluck07
            06.04.2023 13:38

            Мы сразу пишем так, чтоб потом заменять только наш HAL, а всё что выше ничего об этом не знает. Да и у STM и Gigadevice библиотеки всё равно несовместимые, насколько я понимаю.


      1. Xadok
        06.04.2023 13:38

        У юристов тут в первую очередь будет другой вопрос, который на скриншотах аккуратно обошли :)


    1. VelocidadAbsurda
      06.04.2023 13:38

      Стоит попробовать поискать у ST прямой аналог этого Artery, эти не слишком оригинальничают. К примеру, у AT32F415 периферия содрана с STM32F10x, бинарник, собранный под ST (не использующий отсутствующий в АТ ADC2) работает и на том и на другом.


    1. DrGluck07
      06.04.2023 13:38

      Кстати, у гигадевайса библиотеки под некоторые серии просто не собираются. В смысле не собирается пустой проект с одним мейном. Причём под соседний контроллер их той же серии всё собирается нормально.


  1. lamerok
    06.04.2023 13:38
    +4

    Ещё один плюс, это очень много комментариев по всем функциям, что облегчает задачу.

    А зачем комментариями засорять код?

    Код итак уже есть документация на ПО. Зачем например вот это?

    /* enable tmr1 tmr2 */ tmr_counter_enable(TMR1, TRUE); tmr_counter_enable(TMR2, TRUE);

    // enable led

    init_led();

    at32_led_on(LED3);

    at32_led_on(LED2);

    Ну и все в таком духе.

    А ещё в прерывании, кроме флага ресет, хорошо бы ещё проверить, что само прерывание разрешено. А то может получиться так, что флаг ресет стоит, а прерывание пришло от другого источника и вы обработаете не существующее прерывание


    1. arty_morris Автор
      06.04.2023 13:38
      -2

      Чем вам комментарии мешают? Для себя же полезно, через год вернуться и не ломать голову. Это же вам всё понятно,а есть те, кому нужно подробно


      1. lamerok
        06.04.2023 13:38
        +2

        Тем что они замусоривают код и мешают пониманию кода. Если вы пишите комментарии, то, либо изначально код был плохой и непонятный, и его надо переделать, либо они не имеют смысла.

        В вашем случае, никакой смысловой нагрузки у комментариев нет. Итак понятно, что там делается по названию метода. Вы просто замусорили код и его трудно читать. Язык программирования, это такой же язык общения, ведь вы не поясняете //описываете более детально смысл слов и не пишите //комментируете все по два раза в русском языке.

        Комментарии должны пояснять, что не совсем может быть тривиально, например, сложный алгоритм, хотя лучше его описать отдельно в документе.

        Следует придерживаться эвристического правила: если ощущается необходимость что-то прокомментировать, нужно написать метод. Даже одну строку имеет смысл выделить в метод, если она нуждается в разъяснениях[7].

        https://ru.m.wikipedia.org/wiki/Код_с_запашком

        Комментарии

        Часто комментарии играют роль «дезодоранта» кода, который появляется в нём лишь потому, что код плохой. Почувствовав потребность написать комментарий, попробуйте изменить структуру кода так, чтобы любые комментарии стали излишними[17].

        Если для объяснения действий блока всё же требуется комментарий, попробуйте применить «Выделение метода» (Extract Method);

        Если метод уже выделен, но по-прежнему нужен комментарий для объяснения его действия, воспользуйтесь «Переименованием метода» (Rename Method);

        Если требуется изложить некоторые правила, касающиеся необходимого состояния системы, примените «Введение утверждения» (Introduce Assertion)[17


        1. arty_morris Автор
          06.04.2023 13:38
          -1

          Это лишь ваше мнение. И да, все комментарии из примеров, я их не писал. Вы можете у себя как угодно писать код. Я пишу как мне удобно, а не как кому-то хочется


          1. lamerok
            06.04.2023 13:38
            +1

            Это же вам всё понятно,а есть те, кому нужно подробно

            Я пишу как мне удобно, а не как кому-то хочется

            Странно, противорячащие друг другу высказывания.

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

            И, кстати, это не моё мнение, это как бы общепринятое правило хорошего кода, как здороваться при встрече.

            Можно же и не здороваться, но будет ли это способствовать эффективным коммуникациям, не думаю.


          1. aabzel
            06.04.2023 13:38
            -1

            Это лишь ваше мнение


            Это еще и моё мнение. @lamerok прав. В хорошем коде не нужны комментарии. Хороший код понятен и без комментариев за счет адекватных названий функций и переменных.


            https://habr.com/ru/articles/679256/


  1. Polzuchy_haos
    06.04.2023 13:38

    Кто нибудь разобрался как работает sram в artery? Я том плане что там у них написано 96 КБ + 128 КБ. И вот эти 128кБ они откуда берутся?


    1. man55
      06.04.2023 13:38
      +1

      Есть "обычная" часть ОЗУ и есть часть ОЗУ, которая может использоваться как ОЗУ, а может как теневое ОЗУ, в которое при старте копируется часть FLASH и получается исполнеие кода zero-wait-state даже на 240МГц. А еще для части FLASH такое теневое ОЗУ есть аппаратно по умолчанию и при старте проц несколько миллисекунд еще до передачи управления на стартовый вектор копирует FLASH туда. Жрет при этом около 30 мА, что ставит крест на применении Artery F4 в устройствах, которые не способны обеспечить 30 мА. Вот такое вот ОЗУ


      1. Polzuchy_haos
        06.04.2023 13:38

        Благодарю, а то я сначала вообще понял, что есть быстрая flash на 240 МГц, и вот мы из нее эмулируем дополнительную SRAM


      1. SuperTEHb
        06.04.2023 13:38

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


  1. alexhott
    06.04.2023 13:38

    А мне показалось странным...
    Задача : работа с КАН шиной на другом МК в серийном устройстве.
    Кто будет делать? Может те кто делал и разрабатывал устройства на МК?
    Нет! делать будет андроид разработчик!

    ЗЫ: здорово если будет в серийных ладах сразу и без косяков работать


    1. arty_morris Автор
      06.04.2023 13:38

      А вы знаете, работает. И неплохо. Думаете если человек разбирается в Java, он не сможет разобраться в программировании МК? Вы ошибаетесь, я разобрался


      1. alexhott
        06.04.2023 13:38

        Нисколько не сомневаюсь и тем более не хотел вас обидеть - такие люди как раз спасают ситуацию.

        Имел ввиду что "менеджеры" крупных предприятий доводят ситуацию иногда до абсурда.


        1. arty_morris Автор
          06.04.2023 13:38

          Ничего страшного. Я тут один )


          1. Serge78rus
            06.04.2023 13:38

            На самом деле — это ситуация довольно тревожная, причем как для Вас, так и для руководства. Сам в такой же ситуации, и лет 10 назад мне тоже казалось, что "Ничего страшного", а сейчас уже думаю по другому. Правда, и направлений не два, как у Вас (Java и эмбеддинг), а несколько больше. Все это со временем начинает очень выматывать, очень...


            1. arty_morris Автор
              06.04.2023 13:38

              Я сам себе руководство) А прошивка для канбаса пишется один раз. Так что не страшно. Тем более приложение и канбас это единое целое.
              Но я согласен, разрываться плохо


              1. Serge78rus
                06.04.2023 13:38

                А прошивка для канбаса пишется один раз.
                Ой, не зарекайтесь, тем более в текущей ситуации. Вот, например, завтра ARM нажмет на китайцев и перестанут они нам вообще поставлять МК на их ядрах. И придется все на RISC-V переделывать.


                1. arty_morris Автор
                  06.04.2023 13:38

                  Ничего страшного, переделаю. Лучше самому писать, и знать что программа не будет конфликтовать с канбасом, чем отдавать на сторону, ждать и объяснять, что же мне надо


  1. beefdeadbeef
    06.04.2023 13:38

    https://github.com/beefdeadbeef/libopencm3/tree/at32f4 -- форк libopencm3 для at32f40x, для любителей погорячее.


    1. UFO_01
      06.04.2023 13:38

      А не подскажете, нет информации, когда добавят поддержку at32f43x?


      1. arty_morris Автор
        06.04.2023 13:38

        Вроде есть же. Посмотрите pack с драйверами для keil


      1. beefdeadbeef
        06.04.2023 13:38

        у меня такой нужды пока не возникало, о сходных проектах мне неизвестно.


  1. ovn83
    06.04.2023 13:38

    Если в ВАЗ такие работают, то нафиг этот ТАЗ нужен. Уровень детского сада, поморгать светодиодом.

    В авиации делал CAN шину, свои протоколы и ARINC поверх наворачивал, stm32 серий с 1 по 4, сроки, месяц, до этого дел с stm и can не имел.