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

38 минут назад, Сергей Борщ сказал:

Тут что-то другое. Даже глядя на вот на эту табличку:

Я не утверждаю (кто его знает - что там внутри, если это не документировано?). Просто предполагаю, что тупо увеличить размер кеша (по сравнению с оригинальным STM32F103) - намного проще и дешевле, чем полностью зеркалировать весь флешь в 256КБ ОЗУ. Да и эффект от кеша падает с ростом его размера, а значит между например 32КБ и 256КБ кеша - скорей всего мало в каких прикладных задачах вообще будет заметна хоть какая-то разница в скорости выполнения кода. Хотя в скорости реакции на редкие прерывания разница, вероятно, будет.

Если у производителя есть возможность разместить на кристалле эти дополнительные 256КБ, то намного эффективнее отдать бОльшую его часть под пользовательское ОЗУ, и малую - под кеш.

Цитата

Это из GD32F1 - AN002 Programming flash memory manual. И выход из спячки Standby в 59.4 мс для устройств с памятью до 128К, и 118.8 мс для устройств с памятью больше 128 К неспроста.

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

Да и если предполагать, что там идёт копирование в ОЗУ при выходе из спячки, то почему тогда сектора >= 512КБ имеют ещё бОльшую латентность? Тем, что есть девайсы, в которых "теневое ОЗУ" = 512КБ и копирование из нижних 2-х секторов в это ОЗУ идёт последовательно?  :wink:

Ещё один момент - как раз для случая малопотребляющих устройств: чтение всего объёма флешь при выходе из спячки должно давать значительный бросок тока потребления. Т.е. - как-то очень неправильно.

 

PS: Может быть и реально там есть какое-то теневое ОЗУ. Тут можно только гадать. Но мне представляется такое решение производителя неэффективной тратой ценного ОЗУ.

 

PPS: Ещё одна фантастическая(?) версия: китайцы стырили технологию FRAM/MRAM и младший сектор сделали на ней. Но (так как технология стыреная), чтобы не палиться, пишут что это FLASH.  :biggrin:

 

PPPS: Ещё одна версия о происхождении разности времён выхода из спячки: ROM-код проверяет содержимое флеша. Отсюда и 2-кратная разница.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

статья с хабра https://habr.com/ru/company/ruvds/blog/525842/?ysclid=l2u2op1rco

Цитата

Хотя флеш-хранилище GD32 должно было бы работать очень медленно, так как это — SPI ROM, в микроконтроллере используется SRAM главного чипа в роли «кеша» для флеш-хранилища, что приводит к тому, что это хранилище быстрее того, которое входит в состав основного чипа. Оно не пребывает в состоянии ожидания даже при работе микроконтроллера на полной доступной ему тактовой частоте.

Минус использования SRAM в связке с флеш-памятью заключается в том, что это повышает энергопотребление устройства. Это, кроме того, вызывает задержку при загрузке (небольшую), вызванную тем, что содержимое SPI ROM копируется в SRAM до того, как сможет загрузиться прошивка.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот тут в комментариях тоже жалуются на подобную проблему (медленная работа). Приводится цитата из мануала
 

Quote

No waiting time within first 256K bytes when CPU executes instructions. A long delay when CPU fetches the instructions out of the range.

У меня именно так и происходит - когда размер флеш до 256к - все работает аналогично STM, но когда превышает - работает очень медленно.
Стало интересно, что же это за long delay. Создал в пустом проекте функцию, которая считает сумму байт в массиве. Функцию и массив расположил в регионе до 256к и аналогичную функцию и массив - в регионе выше 256к. Включил прерывание через 100мкс, в котором инкрементируется одна переменная (для измерения времени). Рабочая частота - 72М. Получил результат
code0 data0 t=1846 (1850)
code0 data1 t=2799 (2804)
code1 data0 t=1846 (1850)
code1 data1 t=2799 (2804)
code0 - это функция в регионе до 256к, data0 - массив в регионе до 256к. Время в мс. В скобках - время, если включено еще одно прерывание от другого таймера раз в 1мс.
Получилось, что нет разницы, где находится функция, а когда данные находятся по старшим адресам, то функция выполняется в два раза дольше. Но это не должно было бы нарушить нормальную работу. Так как исходный проект на STM может работать и на внутреннем генераторе 8МГц без каких-то намеков на сбои.Тогда я вставил эти функции в реальный проект с размером флеш 350к. Причем, никакой код, кроме этих функций не выполняется (до него не доходит), то есть, никак не должен влиять на результат. И вот что вышло
code0 data0 t=1846 (1859)
code0 data1 t=3633 (5917)
code1 data0 t=1846 (3156)
code1 data1 t=10133 (58691)
функция в старших адресах с данными в старших адресах выполняется уже в 5 раз дольше. А если включено хотя бы еще одно прерывание, то и вовсе получается плачевный результат (в скобках). При любом изменении основной программы эти цифры тоже меняются, чем больше занятая флеш память, тем выше эти цифры.
На STM при любых условиях цифры всегда одни и те же и не зависят от занятого размера флеш.
code0 data0 tc=3704 (3729)
code0 data1 tc=3704 (3729)
code1 data0 tc=2778 (2798)
code1 data1 tc=2778 (2798)
Не могу объяснить, с чем может быть связана такая странная работа GD.
 

Spoiler

#define SZ  0x4000

#pragma location="fastsect"
__root const uint8_t b1[SZ] = {2};

#pragma location="slowsect"
__root const uint8_t b2[SZ] = {2};

#pragma optimize=none
fastrom uint16_t crcx1 (const uint8_t *buf, uint32_t len) {
  uint16_t sum = 0;
  uint16_t b = 0;
  for(int j = 0; j < 1000; j++) {
    wdr();
    for(int i = 0; i < len; i++) {
      sum += buf[i];
    }
    b += (sum >> 8);
  }
  return(b);
}
//-----------------------

#pragma optimize=none
slowrom uint16_t crcx2 (const uint8_t *buf, uint32_t len) {
  uint16_t sum = 0;
  uint16_t b = 0;
  for(int j = 0; j < 1000; j++) {
    wdr();
    for(int i = 0; i < len; i++) {
      sum += buf[i];
    }
    b += (sum >> 8);
  }
  return(b);
}
//-----------------------

void x1 () {
  uint16_t a;

  clr_tc_100us();
  a = crcx1(b1, SZ);
  LOGk5("\r code0 data0 ={1}, tc={2} ", a, get_tc100us(), 0);

  clr_tc_100us();
  a = crcx1(b2, SZ);
  LOGk5("\r code0 data1 ={1}, tc={2} ", a, get_tc100us(), 0);

  clr_tc_100us();
  a = crcx2(b1, SZ);
  LOGk5("\r code1 data0 ={1}, tc={2} ", a, get_tc100us(), 0);

  clr_tc_100us();
  a = crcx2(b2, SZ);
  LOGk5("\r code1 data1 ={1}, tc={2} ", a, get_tc100us(), 0);
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, vit496 сказал:

Тогда я вставил эти функции в реальный проект с размером флеш 350к. Причем, никакой код, кроме этих функций не выполняется (до него не доходит), то есть, никак не должен влиять на результат. И вот что вышло

Ну подумайте сами - какая ядру разница, что там записано - 0xFFFFFFF или 0x1234567, если до исполнения этого кода дело все равно не доходит? У флеши ведь нет состояния "ничего не записано", что-то в каждой ячейке все равно хранится, либо ноль, либо единица.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, vit496 сказал:

На STM при любых условиях цифры всегда одни и те же и не зависят от занятого размера флеш.
code0 data0 tc=3704 (3729)
code0 data1 tc=3704 (3729)
code1 data0 tc=2778 (2798)
code1 data1 tc=2778 (2798)

Как же "одни", если сами же пишете разные цифры? Или что означают эти столбцы цифр? :wacko2:

Какие-то странные у Вас тесты. Да и сравнивать два разных си-исходника, не имея понятия во что они скомпилились (откуда уверенность, что скомпилились они одинаково? и что выравнивание кода одинаковое?) - это по меньшей мере - легкомысленно. Мягко говоря.

4 часа назад, vit496 сказал:

Тогда я вставил эти функции в реальный проект с размером флеш 350к. Причем, никакой код, кроме этих функций не выполняется (до него не доходит), то есть, никак не должен влиять на результат.

"Не выполняется"? Уверены? А кто тогда инициализирует периферию, систему тактирования, etc.? Да хотя-бы - тот же ваш источник прерываний/таймер?

 

PS: Какие "тесты" - такие и результаты. Чё сказать. :unknw:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 hours ago, Сергей Борщ said:

Ну подумайте сами - какая ядру разница, что там записано - 0xFFFFFFF или 0x1234567, если до исполнения этого кода дело все равно не доходит? У флеши ведь нет состояния "ничего не записано", что-то в каждой ячейке все равно хранится, либо ноль, либо единица.

Была дикая мысль, что если размер теневой RAM, например, 256к, то он закэширует туда только флеш без FFFFFFFF -).
В этом моем случае дело оказалось в том, что обработчики прерываний разместились по старшим адресам. После принудительного размещения их в первых 256к, тестируемые функции стали работать одинаково при любом размере флеша. Основная программа стала работать ощутимо шустрее, но в еще не работает как положено. Разбираюсь дальше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Один таймер, прерывания каждые 100мкс, высший приоритет. В прерывании инвертируется пин. Других прерываний нет.
Основной цикл - бесконечный вызов функции по подсчету суммы массива из флеш памяти. Прерывания нигде не запрещаются. Рабочая частота - 8МГц, внешний кварц. Пример сделан на основе библиотек от GD.
 

Spoiler

#define SZ0   200   // set size flash in kBytes
#define SZ1   0x400

const uint8_t buf[SZ0][SZ1] = { 0 };
uint8_t res[SZ0];

uint32_t crc ()  {
  uint32_t sz0, sz1;
  uint32_t sum = 0;

  for(sz0 = 0; sz0 < SZ0; sz0++) {
    res[sz0] = 0;
    sum = 0;
    for(sz1 = 0; sz1 < SZ1; sz1++) {
      sum += buf[sz0][sz1];
    }
    res[sz0] = sum & 0xff;
  }
  return(1);
}

int main(void) {
    nvic_priority_group_set(NVIC_PRIGROUP_PRE3_SUB1);
    gd_eval_led_init(LED2);
    timer_config();
    
    while(1) {
      crc();
    }
}

 

 

Меняем размер массива (SZ0), тем самым - размер занятой флеш памяти. До 256к все работает четко - импульсы каждые 100мкс. После 256к - провалы в работе. Примерно каждую миллисекунду какие-то задержки.
То есть, получается, что когда идет работа с флеш, которая находится выше 256к, МК начинает что-то делать, так что даже самые высокоприоритетные прерывания откладываются. И времени занимает это "что-то" не менее 250 мкс на частоте 8МГц. На частоте 72МГц - 17-25мкс.

 

Spoiler

100us_fail.thumb.jpg.e9410a88c0015e3174d3fe0f8d4d7fdf.jpg

 

Изменено пользователем vit496

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, vit496 сказал:

Меняем размер массива (SZ0), тем самым - размер занятой флеш памяти. До 256к все работает четко - импульсы каждые 100мкс. После 256к - провалы в работе. Примерно каждую миллисекунду какие-то задержки.
То есть, получается, что когда идет работа с флеш, которая находится выше 256к, МК начинает что-то делать, так что даже самые высокоприоритетные прерывания откладываются. И времени занимает это "что-то" не менее 250 мкс на частоте 8МГц. На частоте 72МГц - 17-25мкс.

Может быть - дочитывает флешь в кеш. Большими порциями.

PS: А вообще - тест некорректный. Нормальный компилятор должен вообще весь внутренний for () выкинуть, так как заранее знает, что содержимое массива = 0. Изучите назначение ключевого слова volatile.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

тут все просто

 

And ST Different ,GD Of Flash There is the concept of partition , front 256K,CPU Execute instruction zero wait , call code District , Outside this scope is called dataZ District . There is no difference between the two in erasure operation , But there is a big difference in read operation time ,code The area code takes zero and waits ,data There is a large delay in executing code in the area , Code execution is more efficient than code The area is one order of magnitude slower , therefore data Areas usually do not recommend running code that requires high real-time performance , To solve this problem , The method of decentralized loading can be used , For example, put the initialization code , Picture code, etc data District .

 

https://chowdera.com/2022/04/202204091601119439.html

 

Кстати, в даташитах на старшие процы (450-470) уже явно в мануале сделано разделение флэша на Code Area и Data Area. Код из кода арии выполняется без задержек, код из дата с огромными задержками. Это происходит потому, что в реальности код из кодаарии выполняется из рамы, а код из даты из флэша, который по спи подключен

Изменено пользователем 0men

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 14.11.2021 в 18:41, KnightIgor сказал:

SCB->CPUID возвращает/содержит:

  • 0x411FC231 для STM32F103VET
  • 0x412FC231 для GD32F103VET
  • 0x410FC241 для GD32F303VET
  •  

Похоже, это слово не меняется от экземпляра к экземпляру одного типа, а идентифицирует тип.

Это информация о модели CPU

CPU_ID.thumb.png.a3b40a09b62a4a18d14545781c23d7a7.png

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот еще интересный документ. Выжимка по отличиям между GD и STM.

 

 

compatibility sumup between GD32 and STM32_V2.0.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не слушается RET6 в 64ногом корпусе.

Пытаюсь включить читалку энкодера на PB6 PB7

Использую обычную от стм инициализацию - в регистре счета ноль, ничего не считает.

На основе stdperiphlib :

//======================================================================================
void init_TIM4_ENA (void)
//======================================================================================
{
  GPIO_InitTypeDef         GPIO_InitStructure;
 // TIM4 ENA 
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
                         
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // PB6, PB7
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12,TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);
  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
  TIM_Cmd(TIM4, ENABLE);
}
 

У кого-нибудь получилось?

Прочитал рефмануал на ГД , отличий не увидел по модулю декодера вроде.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 24.10.2022 в 16:44, mitya1698 сказал:

Не слушается RET6 в 64ногом корпусе.

А где инициализация самого таймера?

Типа такой:

    timer_deinit(TIMER1);
    /* initialize TIMER init parameter struct */
    timer_struct_para_init(&timer_initpara);
    /* TIMER1 configuration */
    timer_initpara.prescaler         = 11999;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 9999;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_init(TIMER1, &timer_initpara);

    /* enable the TIMER interrupt */
    timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);
    timer_interrupt_enable(TIMER1, TIMER_INT_UP);
    
    timer_enable(TIMER1);

 

Для GD32E103 у меня инициализация энкодера простейшая:

void init_TIMER3(void)
{
  TIMER3->CTL0 = 0;
  TIMER3->CTL1 = 0;
  TIMER3->SMCFG = (3 << TIMER_SMCFG_SMC);
  TIMER3->PSC = 0;
  TIMER3->CAR = 0xFFFF;
  TIMER3->CTL0 = (1 << TIMER_CTL0_CEN);
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

В стм так работало прекрасно.

Обнаружил нестыковку, в СТМ на PB6 PB7 таймер 4

а вот у ГД на них таймер 3 :()

Переделал на 3, но не взлетело всеравно.

 

Попробую приведенную выше инициализацию, отпишусь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, mitya1698 said:

а сам таймер зачем инитить

Правильно, не надо инициализировать железо, а всегда нужно полагаться на то, что лежит в регистрах по-умолчанию, особенно в копиях чипа от других производителей, и уж подавно для их клонов... А то что-то мало "падает самолетов", нужно еще больше :dirol:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

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