Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

Невыровненный доступ

Тема в разделе "ESP32 SDK", создана пользователем sharikov, 13 сен 2019.

  1. sharikov

    sharikov Авторитетный участник сообщества

    Сообщения:
    596
    Симпатии:
    52
    Поддерживается ли в ESP32 работа с невыровенными адресами или будет исключение ?
    Например если 32-х битную переменную расположить по адресу не кратному 4.
    Такой же вопрос про ESP8266.
    Про замедление и плохой стиль я знаю. Вопрос именно про исключения.
     
  2. enjoynering

    enjoynering Авторитетный участник сообщества

    Сообщения:
    562
    Симпатии:
    54
    я экспериментировал с ESP8266 и Arduino framework. разницы размера скеча от в unt8_t, uint16_t и uint32_t не заметил. похоже, какой тип не выбрать, всегда тупо занимается 4 бита

    вот тут чел спрашивает почему sizeof возвращает 1+1+4=6 байт
    Код (Text):
    1. typedef struct packet_t{
    2.   uint8_t a;     // sizeof(uint8_t) returns 1
    3.   uint8_t b;     // sizeof(uint8_t) returns 1
    4.   float c;         // sizeof(float) returns 4
    5. };
    а размер пакета получается 8
    Код (Text):
    1. sizeof(packet_t) //returns 8
    чтоб этого не происходило надо так
    Код (Text):
    1. typedef struct __attribute((__packed__)) packet_t{
    2.   uint8_t a;
    3.   uint8_t b;
    4.   float c;
    5. };
     
  3. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    9.004
    Симпатии:
    1.302
    Будет исключение.

    В IRAM, (кеш) Flash, registers - всегда должно быть выровнено и желательно чтение/запись по 32 бита.
     
  4. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    9.004
    Симпатии:
    1.302
    Думаю, что нет.
    На версиях NodeMCU LUA ESP8266 по exception читаются байтовые (string/char) переменные из Flash.
    Один exception = один char :) Метода такая чтобы не исправлять printf() и прочие процедуры библиотек создана процедура на векторе exception выуживающая байтики из IRAM (кеш) Flash...
    За последние годы в некоторых вариантах Aduino такое тоже наблюдалось - вставляли обработку exception по нарушению align(4)... - сотни тактов на байт для Arduino ерунда. Всё равно игрушка...
     
  5. sharikov

    sharikov Авторитетный участник сообщества

    Сообщения:
    596
    Симпатии:
    52
    На ESP32 исключения не возникает.
    Тест:
    Код (C):
    1. void unaligned_access_test(void) {
    2.    static char buffer[61];
    3.    unsigned int index, data;
    4.    volatile char *ptr1;
    5.  
    6.    // fill buffer
    7.    for (index=0; index < sizeof(buffer); index++)
    8.        buffer[index]=index;
    9.    // check buffer alignment
    10.    ptr1=&buffer[0];
    11.    printf("&buffer[0]=0x%x\n", (unsigned int)ptr1);
    12.    if (((unsigned int)ptr1 & 3) !=0) {
    13.        printf("unaligned!\n");
    14.        data = (unsigned int)ptr1;
    15.        data|=3;
    16.        data+=1;  // 4-byte aligned address
    17.        ptr1=(volatile char *)data;
    18.        printf("new: 0x%x\n", (unsigned int)ptr1);
    19.    }
    20.    // unaligned access test
    21.    for (index=0; index<4; index++) {
    22.        printf("[0x%x] : 0x%04x\n", (unsigned int)ptr1, *(unsigned int*)ptr1);
    23.        ptr1++;
    24.    }
    25. }
    Результат:
    Код (Text):
    1. &buffer[0]=0x3ffb2eb4
    2. [0x3ffb2eb4] : 0x3020100
    3. [0x3ffb2eb5] : 0x4030201
    4. [0x3ffb2eb6] : 0x5040302
    5. [0x3ffb2eb7] : 0x6050403
     
  6. sharikov

    sharikov Авторитетный участник сообщества

    Сообщения:
    596
    Симпатии:
    52
    Добавил измерение времени:
    Код (C):
    1. extern unsigned int g_ticks_per_us_pro;
    2. void unaligned_access_test(void) {
    3.     static char buffer[61];
    4.     unsigned int index, data, ccount_now, ccount_prv;
    5.     volatile char *ptr1;
    6.  
    7.     printf("ticks per us = %u\n", g_ticks_per_us_pro);
    8.     // fill buffer
    9.     for (index=0; index < sizeof(buffer); index++)
    10.         buffer[index]=index;
    11.     // check buffer alignment
    12.     ptr1=&buffer[0];
    13.     printf("&buffer[0]=0x%x\n", (unsigned int)ptr1);
    14.     if (((unsigned int)ptr1 & 3) !=0) {
    15.         printf("unaligned!\n");
    16.         data = (unsigned int)ptr1;
    17.         data|=3;
    18.         data+=1;  // 4-byte aligned address
    19.         ptr1=(volatile char *)data;
    20.         printf("new: 0x%x\n", (unsigned int)ptr1);
    21.     }
    22.  
    23.     // unaligned access test
    24.     for (index=0; index<4; index++) {
    25.         //ccount_prv = xthal_get_ccount();
    26.         __asm__ __volatile__("rsr %0,ccount":"=a" (ccount_prv));
    27.         data=*(volatile unsigned int*)ptr1;
    28.         //ccount_now = xthal_get_ccount();
    29.         __asm__ __volatile__("rsr %0,ccount":"=a" (ccount_now));
    30.  
    31.         printf("[0x%x] : 0x%04x  cycles : %d\n",
    32.                 (unsigned int)ptr1, data,
    33.                 (ccount_now < ccount_prv)? ccount_prv-ccount_now : ccount_now- ccount_prv);
    34.         ptr1++;
    35.     }
    36. }
    Результаты:
    Код (Text):
    1. ticks per us = 240
    2. &buffer[0]=0x3ffb2eb4
    3. [0x3ffb2eb4] : 0x3020100  cycles : 3
    4. [0x3ffb2eb5] : 0x4030201  cycles : 10
    5. [0x3ffb2eb6] : 0x5040302  cycles : 10
    6. [0x3ffb2eb7] : 0x6050403  cycles : 10
    По моему 10 тактов для обработчика исключения недостаточно. А вот на два обращения по шине данных и простой конвейера похоже. Результаты на 240MHz и на 160MHz не отличаются.
     
  7. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    9.004
    Симпатии:
    1.302
    То в простой SRAM. А в других областях "В IRAM, (кеш) Flash, registers"?
     
  8. sharikov

    sharikov Авторитетный участник сообщества

    Сообщения:
    596
    Симпатии:
    52
    При невыровненном чтении данных из области Instruction External Flash (0x400C2000-0x40BFFFFF) возникает исключение LoadStoreAlignment и далее ребут. Выровненное чтение из этой области работает.

    Обращение к области Data External Flash (0x3F400000-0x3F7FFFFF) исключение не выдается. Результаты двух тестов:
    Код (Text):
    1. ticks per us = 240
    2. &buffer[0]=0x3f402e9e
    3. unaligned!
    4. new: 0x3f402ea0
    5. [0x3f402ea0] : 0x5040302  cycles : 287
    6. [0x3f402ea1] : 0x6050403  cycles : 12
    7. [0x3f402ea2] : 0x7060504  cycles : 12
    8. [0x3f402ea3] : 0x8070605  cycles : 12
    9. ticks per us = 240
    10. &buffer[0]=0x3f402e9e
    11. unaligned!
    12. new: 0x3f402ea0
    13. [0x3f402ea0] : 0x5040302  cycles : 4
    14. [0x3f402ea1] : 0x6050403  cycles : 12
    15. [0x3f402ea2] : 0x7060504  cycles : 12
    16. [0x3f402ea3] : 0x8070605  cycles : 12
    287 циклов - подгрузка кэш. Из кэша данные читаются на 1 или 2 такта медленнее чем из SRAM.
     
  9. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    9.004
    Симпатии:
    1.302
    Это на одно считывание?
    Какая длина блока чтения у "кеш" из SPI-Flash? 16-ть байт или ?
    240MHz/287 = 830 кГц 2хCPU :) Супер производительность ESP32 :) :)
    У меня, по расчетам, получилось среднее к 10 миллионам операций CPU в секунду (на оба ядра) в процессах типа кодеков и прочего кода (типа рассчет ключей,SSL и подобное), когда он не вмещается в убогий "кеш" ESP32 (а он и не вместится никогда).
     
  10. sharikov

    sharikov Авторитетный участник сообщества

    Сообщения:
    596
    Симпатии:
    52
    В мануале не нашел. На форуме пишут "Cache lines are 32 bytes".
    В теории должно быть
    40MHz / (32+5) = 1.08 МHz или 0.925us на промах кэш.

    Жаль что кэш на 1 такт медленнее SRAM
     
  11. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    9.004
    Симпатии:
    1.302
    32 байта QSPI -> 64 такта SPI шины + заголовок с адресом (5 байт = 10 тактов + до пары тактов на старте).
    Получаем 80MHz/80 = 1 блок в 32 байта -> 1MHz * 32, т.е. QSPI читается в "кеш" со скоростью 32 мегабайта в сек.
    А средняя длина команды у ESP - 2 с чем-то байта, к трем ... и учтем работу "кеш" блоками на чтение указателей (лишние чтение вместо 4-х байт 32-х)...
    32/3 = 10M команд CPU в сек, если код длиннее "кеш" и идет в линейку или рандом.
    STM32 или какой современный PIC, не говоря уже о mips и прочих с большой SRAM, уделывает ESP32 в 10..100 раз.
     
  12. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    9.004
    Симпатии:
    1.302
    И при такой производительности (в 10МГц) ESP32 жрет так-же, даже немного более из-за постоянной SPI-Flash работы всех контроллеров с тактированием на 240x2МГц ядер. Т.е. и энерго-эффективность так-же падает по сравнению с другими на порядки !
    На ESP8266 уже эта бяда, а тут ещё 2 ядра на ту-же шину QSPI повесили... :eek:
     
  13. sharikov

    sharikov Авторитетный участник сообщества

    Сообщения:
    596
    Симпатии:
    52
    Интересно что происходит с работой второго ядра во время загрузки кэша ?
    Скажем второе ядро исполняет критичный по времени код только из IRAM и в это время первое ядро подгружает кэш.
    Шина как я понимаю одна и как пишут на форуме блоков предвыборки в процессорах нет
     
  14. pvvx

    pvvx Активный участник сообщества

    Сообщения:
    9.004
    Симпатии:
    1.302
    Если оно работает из SRAM (IRAM) - то работает как и работало.
    "предвыборки" нет и док-во в лишней команде "memw" и "extw".
     

Поделиться этой страницей