Например TDA7294

Форум РадиоКот • Просмотр темы - Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Чт сен 18, 2025 20:06:06

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 291 ]     ... , , , , 15
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Вс янв 03, 2021 23:12:24 
Мудрый кот

Карма: 20
Рейтинг сообщений: 145
Зарегистрирован: Вс дек 25, 2016 08:34:54
Сообщений: 1849
Рейтинг сообщения: 0
Сравнивай
СпойлерИзображение Изображение


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Вс янв 03, 2021 23:21:05 
Собутыльник Кота
Аватар пользователя

Карма: 18
Рейтинг сообщений: 430
Зарегистрирован: Вт май 01, 2018 19:44:47
Сообщений: 2539
Рейтинг сообщения: 0
Я же всё показал. Сравнивай сам.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Пт янв 08, 2021 01:18:30 
Нашел транзистор. Понюхал.

Зарегистрирован: Вс сен 06, 2020 16:06:10
Сообщений: 156
Рейтинг сообщения: 0
Поигрался я с идеей iddqd, есть 2 варианта:
1 вариант, когда пины располагаются на одном порту, не важно в какой последовательности.
ОЗУ на один пин 4 байта, на 8 пинов 32 байта.
Технически на 1 пин - 1 бит на порцию, если -> ODR или 2 бита, если -> BSRR. В допущении port-wide доступа. Port-wide доступ имеет смысл например если там LCD с 8-bit bus развесили или например большая группа светодиодов, etc. В принципе с BSRR это битовая маска + latch, так что можно и меньше пинов за раз ворочать, с ухучшением КПД этой операции.

Цитата:
Если хранить картинку 256*256 точек, да в добавок в цветном изображении, параллельный порт 8 пинов, 256*256*3*32 = 6.291.456 байт.?
Любую идею можно довести до маразма. Слать можно отдельные регионы картинки/небольшие иконки/инициализацию дисплея/etc и размер может быть вменяемым. Кстати и ряд других коммуникаций недурно смотрится в виде make packet -> queue send, а пока оно там send можно чем-то еще заняться. И если там всякое сжатие, ну тогда после decompress и "prepare buffer" из вон того куска наверное ок? А какие еще варианты? Если контроллер шины есть то все просто, но он только в очень разлапистых камнях, они дорогие и роутить печатку заманаешься, в общем это сразу повышает планку. А без него вообще какие варианты? Софтом ногодрыгать? Так это вообще блокирующая операция, на ее время проц недееспособен толком (минус IRQ). А, ну еще RTOS можно, но я не знаю как там с таймингами шины будет, в такие дебри я лезть не собираюсь. Мне от MK нужен нижний уровень и предсказуемость, а не высокие абстракции.

Цитата:
Ну как так можно без кода обойтись? Ведь еще сжать картинку можно, без кода ни как.
Есть варианты когда можно совсем без кода. Типа quasi-hardware PWM, когда целый порт ворочается закольцованым DMA без вмешательства софта вообще. Это будет работать даже если процессорное ядро встрянет. Правда оно тогда не сможет параметры подкручивать, но если это не требовалось, то там целиком железки без участия процессора смогут все сделать.

Цитата:
Значит дма будем запускать только на один пин, а в прерывании выключать канал,
1 пин не эффективно по КПД операции. Оно может ВЕСЬ ПОРТ за транзакцию кантовать. Но да, это потребует определенных компромиссов. Оптимальнее всего выделить весь порт под такое развлечение. А почему бы хардвару не сделать хардвару и софту удобно и быстро?. И да, data -> ODR будет с КПД вплоть до 100%. В BSRR только до 50%, битов в 2 раза больше. Зато есть latch, можно только некоторые биты ворочать. Это даже может сосуществовать с некоторой периферией - AFIO в общем случае не очень интересует что там GPIO пытался вообще изобразить. А какое дело какому-нибудь uart input'у до его бита в ODR?

Цитата:
А теперь вопрос в практическом применении, для чего и за чем? И где тут выигрыш в скорости?
Вы кажется не поняли. Суть идеи: в RAM или Flash заводится буфер. Он описывает sequencing группы пинов. Типа эволюции состояния порта во времени. И конечно же трансферов при этом должно быть уж точно не 1. Иначе нахрена б такое счастье с сетапом DMA. И да, поскольку DMA отпускает шину чтобы процу что-то дать, он рекорд скорости может и не поставит. Но есть одна killer feature. Мы можем "зарядить отправку пакета" или даже "закольцевать отправку буфера" - и заняться своими делами! DMA асинхронен относительно кода проца. Так что основной профит - в асинхронщине этого относительно процессора и подпертости железом. А отсутствие трафика кода по шинам для этой активности - приятный побочный эффект, DMA не процессор, ему для ворочания порции данных не надо инструкции по шине гонять. Если хочется именно 1 бит, именно DMA, ну, не знаю, SPI какой поюзайте, чтоли. Он видите ли десереализует то что в него вгрузили, так КПД операции сильно интереснее, а послать опять же можно "целый пакет" и даже, вероятно, закольцевать, если это за каким-то чертом надо.

Для того чтобы графику в жк индикатор писать - нужно дма вместе с таймером использовать.
И вас с новым годом. Я попробовал и с mem2mem. Вообще на светодиодах которым я сделал так подобие PWM это прокатило. Но выпадут ли из порта трансферы и прокатят ли уж какие получатся тайминги (дисплею это важно) если расписать "bus seqencing" и весь его пульнуть как mem2mem - вопрос открытый. Желающие могут позырить если у них скоростной многоканальный логический анализатор есть.

PWM в микроконтроллере это значительно больше, чем "ногодрыганье" с определенной частотой, и как только начнётся попытка реализовать его полноценную работу, и глянется на блок-схему, то на DMA останется минимум функционала.
Так реализуется только очень базовый вариант PWM, с рядом ограничений. Скажите, а вам никогда не хотелось PWM'нуть сразу МНОГО светодиодов, например? Можно и не PWM'нуть, а "sequence". При том вот так - число выходов "PWM" таки до 16 на порт - и таки в отличие от совсем софтварных эрзацев хорошо подперто железом, вплоть до того что будет долбить указанным (при формировании буфера) duty/последовательностью даже при кончине (или занятости) процессорного ядра. Да еще шину потоком команд не грузит, в отличие от софтэрзацев. А рассуждения о хардварных PWM - это прекрасно, но вот захочется пару десятков каналов "хоть какого-то PWM", для например группы светодиодов - и тогда чего? Хардварных каналов ограниченное количество, и вот для них можно и интереснее и требовательнее применения найти.

PWM до кучи придумался. Несколько интереснее ... скажем так, "штукам с разверткой". Когда куча светодиодов на энном порту имеет некий смысл. Вот там таймер ... может очень круто вписаться. Такой себе аппаратный blitter/display controller, если можно так сказать про такую штуку.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Пт янв 08, 2021 15:04:41 
Прорезались зубы
Аватар пользователя

Карма: 2
Рейтинг сообщений: 14
Зарегистрирован: Сб янв 09, 2016 15:51:17
Сообщений: 202
Рейтинг сообщения: 0
Но выпадут ли из порта трансферы и прокатят ли уж какие получатся тайминги (дисплею это важно)

Один канал таймера использовать как имитацию ноги WR, вторым каналом пинать дма. И да, дма уже загрузило данные для дальнейшей работы, если хочется - можно грузить целую пачку данных. Потери данных могут возникнуть только в одном случае: другой дма с более высоким приоритетом фигачет в режиме нонстоп.

_________________
sRtoS


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Пт сен 12, 2025 06:39:42 
Мучитель микросхем

Карма: 24
Рейтинг сообщений: 144
Зарегистрирован: Ср июн 08, 2011 20:25:20
Сообщений: 450
Рейтинг сообщения: 0
Продолжение от сюда viewtopic.php?f=59&t=67578&start=8840
По поводу тактов возник вопрос.
Команда LDR R0,[R1, #+0]; лежит уже в конвейере. До нее и после команд чтения и записи нет. За сколько тактов должна обработаться? За 2 или 3? процессор STM32G431.

Почему 2/3?
Вопрос и возник, что меньше 3 не могу получить, а в теории должно быть 2.
Раз не с кем спариваться, то в вашем случае на CM4 должно быть 2 такта.

Ниже тестовая прога для теста. Лежит в ССM, хотя из флешь также работает. Частота 16МГц.
Изменяя n вычисляем разницу счета таймера 4. Получаем такты за цикл. В меньшем случае 21=7+2+3*4. 7 это 1 тактовые команды, 2 такта переход, 4- количество LDR. 3 выходит такты выполнения команды LDR.

Спойлер
Код:
/*
#define  reg   (uint32_t) TIM4->CNT
#define  reg1  (uint32_t) TIM4->CNT
#define  reg2  (uint32_t) TIM4->CNT
#define  reg3  (uint32_t) TIM4->CNT
*/

#define  reg   (uint32_t) GPIOA->IDR
#define  reg1  (uint32_t) GPIOA->IDR
#define  reg2  (uint32_t) GPIOA->IDR
#define  reg3  (uint32_t) GPIOA->IDR

/*
#define  reg    bx[0]
#define  reg1   bx[1]
#define  reg2   bx[2]
#define  reg3   bx[3]
*/
__root uint32_t bx[]={1,2,3,4};
__root uint32_t res;

void test (void)@".ccmram"{
   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);
   LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_TIM4_STOP);
 
  LL_TIM_InitTypeDef TIM_InitStruct = {0};
  TIM_InitStruct.Autoreload        = 0xFFFFFFFFU;
  LL_TIM_Init(TIM4, &TIM_InitStruct);

  uint32_t n=6;
   uint32_t  w,w1;
  TIM4->CR1=1;
//---------- 
   do{
     w=reg;
     w1=w1+w;
     w= reg1;
     w1=w1+w;
     w= reg2;
     w1=w1+w;
     w= reg3;
     w1=w1+w;
    }
    while (n--!=0) ;
//----------
  res=w1;
  TIM4->CR1=0;
 
};


Ниже листинг цикла. Для правильного получения нужно поиграться оптимизацией для разных reg.
Спойлер
Код:
// 1102 //---------- 
// 1103    do{
// 1104      w=reg;
??test_1:
        LDR      R0,[R3, #+0]
// 1105      w1=w1+w;
        ADDS     R2,R0,R2
// 1106      w= reg1;
        LDR      R0,[R3, #+0]
// 1107      w1=w1+w;
        ADDS     R2,R0,R2
// 1108      w= reg2;
        LDR      R0,[R3, #+0]
// 1109      w1=w1+w;
        ADDS     R2,R0,R2
// 1110      w= reg3;
        LDR      R0,[R3, #+0]
// 1111      w1=w1+w;
        ADDS     R2,R0,R2
// 1112     }
// 1113     while (n--!=0) ;
        MOV      R0,R1
        SUBS     R1,R0,#+1
        CMP      R0,#+0
        BNE.N    ??test_1
// 1114 //----------


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Пт сен 12, 2025 12:53:30 
Говорящий с текстолитом

Карма: -7
Рейтинг сообщений: 181
Зарегистрирован: Вт авг 15, 2017 10:51:13
Сообщений: 1569
Рейтинг сообщения: 0
Команда LDR R0,[R1, #+0]; лежит уже в конвейере.
Почему такой вывод?
Какова ширина шины CPU, читающей поток команд из данной памяти? Есть ли другие bus-masters, работающие в это время?

Ниже тестовая прога для теста. Лежит в ССM, хотя из флешь также работает. Частота 16МГц.
Изменяя n вычисляем разницу счета таймера 4. Получаем такты за цикл. В меньшем случае 21=7+2+3*4. 7 это 1 тактовые команды, 2 такта переход, 4- количество LDR. 3 выходит такты выполнения команды LDR.

А куда указывает R3? Откуда идёт чтение?
И как именно производите замер времени выполнения цикла?

Имхо: тестовый код - некорректный. Длительность выполнения LDR следует измерять не так.
Также необходимо прояснить целевой адрес R3. Вангую, что R3 указывает в тот же регион памяти, где находится код. Отсюда и лишний такт.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Пт сен 12, 2025 14:25:33 
Мучитель микросхем

Карма: 24
Рейтинг сообщений: 144
Зарегистрирован: Ср июн 08, 2011 20:25:20
Сообщений: 450
Рейтинг сообщения: 0
Почему такой вывод?
Это не вывод, а убрать вопросы про время загрузки команды в конвейер. Про кеш, ускоритель...
Какова ширина шины CPU, читающей поток команд из данной памяти?
64.
Есть ли другие bus-masters, работающие в это время?
Нет. Тестовая функция практически в начале main.
Код:
int main(void){
  SCB->VTOR = CCMSRAM_BASE;
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
  LL_RCC_ForceBackupDomainReset();
  LL_RCC_ReleaseBackupDomainReset();
  LL_PWR_EnableBkUpAccess();
  LL_PWR_DisableDeadBatteryPD();
  test();

А куда указывает R3? Откуда идёт чтение?
В тестовой функции экспериментировал чтение с TIM4->CNT , GPIOA->IDR и SRAM. Наверху кода выбирается в #define reg*.
И как именно производите замер времени выполнения цикла?
Изменяя n. К примеру выбираю n=6. Таймер 4 считает время выполнения кода. Увеличиваю n=7. Опять таймер считает. Разница счетов и дает время выполнения цикла. Увеличивая n на 1, то счет Tаймера 4 растет на одну и туже величину.
Длительность выполнения LDR следует измерять не так.
Готов посмотреть и ваш код.
Вангую, что R3 указывает в тот же регион памяти, где находится код.
В примере код в ССМ. Код был и во флеши (при enable ICEN bit ). Результат одинаковый. Чтение кода и памяти (куда указывает R3) идет по разным шинам.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Пт сен 12, 2025 20:20:10 
Говорящий с текстолитом

Карма: -7
Рейтинг сообщений: 181
Зарегистрирован: Вт авг 15, 2017 10:51:13
Сообщений: 1569
Рейтинг сообщения: 0
Какова ширина шины CPU, читающей поток команд из данной памяти?
64.
В моём текущем XMC4500 - столько же. Точнее - это ширина шины, читающей из кеша в буфер предвыборки. Ширина шин к памяти - разная, в зависимости от типа памяти. Up to 256 бит.

Изменяя n. К примеру выбираю n=6. Таймер 4 считает время выполнения кода. Увеличиваю n=7. Опять таймер считает. Разница счетов и дает время выполнения цикла. Увеличивая n на 1, то счет Tаймера 4 растет на одну и туже величину.
Некорректный метод. Не учитывает возможного времени перезагрузки буфера предвыборки при переходе. Также не учитывается невыровненность целевого адреса перехода. И не вижу запрета прерываний на время теста.

Готов посмотреть и ваш код.
Код (IAR):
Код:
               SECTION  .text:CODE:NOROOT(2)
               PUBLIC   TestLdr
               THUMB
;extern "C" void TestLdr(u32 const *);
TestLdr:       MRS      R12, PRIMASK
               CPSID    I
               MOVS     R2, #5
               alignrom 2, 0xBF00
TestLdr_01:    MOVS     R3, #1
               LDR      R1, [R0]
               MOVS     R3, #1
               SUBS     R2, R2, #1
               BNE      TestLdr_01
               MSR      PRIMASK, R12
               BX       LR
Вызов из си++:
Код:
extern "C" void TestLdr(u32 const *);
TestLdr((u32 const *)0x20000000);
Таймеры для измерения тоже не нужны - IAR (у вас же вроде IAR?) сам умеет измерять по отладочному таймеру DWT.CYCCNT. Ставим бряки как на картинке ниже:
Изображение
потом делаем один шаг "step into" чтобы соскочить с бряка (так как на некоторых МК в некоторых памятях это добавляет лишние такты (при soft-бряках)):
Изображение
потом жмём "go". Останавливается на 2-м бряке, смотрим поле "CCSTEP":
Изображение
Делаем рестарт МК, после "step into" вводим в R2 вручную 4, "go", результат:
Изображение
Как видно - у меня разница составила 34-27=7 тактов. Следовательно - длительность LDR = 2 такта. Как и ожидалось.
И нет влияния времени перезагрузки буфера предвыборки при переходе по BNE.

Можно ещё улучшить тест. Исключив возможное влияние перезагрузки буфера предвыборки. После первой пары LDR/MOVS добавляем 2-ю такую же пару:
Изображение
Делаем тест (с тем же числом проходов). У меня получилось == 49 тактов:
Изображение
Считаем (49-34)/5 = 3 такта добавилось. Тоже - как и ожидалось.

В моих тестах 0x20000000 - адрес начала одного из регионов ОЗУ. Код выполняется из другого региона ОЗУ (0x10000000).

Добавлено after 7 minutes 19 seconds:
PS:
Код:
// 1113     while (n--!=0) ;
        MOV      R0,R1
        SUBS     R1,R0,#+1
        CMP      R0,#+0
        BNE.N    ??test_1
Если цель - писать оптимально, то это плохая организация цикла. Используя постфиксную операцию декремента, вы не даёте компилятору использовать флаги результата команды SUBS, заставляя его добавлять ненужную CMP.
Лучше использовать префиксный декремент:
Код:
int n = N; do { ... } while (--n);
или
Код:
int n = N - 1; do { ... } while (--n >= 0);
в этих случаях будет одна команда SUBS за которой сразу BNE.
Хотя для целей измерения времени выполнения команды тут конечно всё равно.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Вс сен 14, 2025 08:29:20 
Мучитель микросхем

Карма: 24
Рейтинг сообщений: 144
Зарегистрирован: Ср июн 08, 2011 20:25:20
Сообщений: 450
Рейтинг сообщения: 0
Разобрался частично. Вывод: кеш инструкций включен, инструкции должны загружаться по I-bus, данные по D-bus. Загрузка по S-bus добавляет 1 такт в лучшем случае и получается, что с периферии данные считываются за 3 такта.
з.ы. Вопросы по расположению кода (цикла) еще остались. Потом еще поэкспериментирую.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Вс сен 14, 2025 15:13:27 
Говорящий с текстолитом

Карма: -7
Рейтинг сообщений: 181
Зарегистрирован: Вт авг 15, 2017 10:51:13
Сообщений: 1569
Рейтинг сообщения: 0
с периферии данные считываются за 3 такта.
Ранее вы писали, что читаете из памяти:
Чтение кода и памяти (куда указывает R3)
Почему сразу и спрашивал вас "откуда читаете?" При чтении из периферии есть много влияющих на чтение факторов: какая именно периферия? на какой шине (AHB, APB1, APB2 - для STM32)? какова частота шины?
Даже у разной периферии, находящейся на одной шине, длительность чтения может быть разной. К скорости выполнения LDR это не имеет отношения. Периферия может долго не ставить ready-сигнал, замораживая CPU.

PS: Иногда (на некоторых МК) помогает работа через bit-band область (если она есть в МК). На моих STM32 (STM32F4xx, STM32F1xx) работа с GPIO-потами через bit-band - заметно быстрее, чем через их регистры. Если подходит - можно попробовать переписать работу на bit-band и проверить.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
СообщениеДобавлено: Вс сен 14, 2025 18:47:33 
Мучитель микросхем

Карма: 24
Рейтинг сообщений: 144
Зарегистрирован: Ср июн 08, 2011 20:25:20
Сообщений: 450
Рейтинг сообщения: 0
Почему сразу и спрашивал вас "откуда читаете?"
Меня интересовала не конкретная задача, а общий случай. Пробовал и код в ссм и читал ram с адреса 0x20000000. Это было в декабре. Код тогда сделал "3 тактах". Просто пришлось больше стыковать друг другу команд чтения и записи. Тогда и возник вопрос про чтение по 2-м тактам. Сейчас созрел задать его :))
какая именно периферия?
ADC-результат. AHB2, делителя нет. Частота 32МГц такая же как у ядра SYSCLK. ADC тактируется без деления.
bit-band
Возьму на заметку. Нужно было чтение всего слова.
можно попробовать переписать работу на и проверить.
Сейчас завал.
К скорости выполнения LDR это не имеет отношения
Если так, то еще попробую поиграться, но позже.....
з.ы. Спасибо за идеи. Результат "2 такта" получил.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 291 ]     ... , , , , 15

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y