jcxz 241 5 мая, 2022 Опубликовано 5 мая, 2022 · Жалоба 38 минут назад, Сергей Борщ сказал: Тут что-то другое. Даже глядя на вот на эту табличку: Я не утверждаю (кто его знает - что там внутри, если это не документировано?). Просто предполагаю, что тупо увеличить размер кеша (по сравнению с оригинальным STM32F103) - намного проще и дешевле, чем полностью зеркалировать весь флешь в 256КБ ОЗУ. Да и эффект от кеша падает с ростом его размера, а значит между например 32КБ и 256КБ кеша - скорей всего мало в каких прикладных задачах вообще будет заметна хоть какая-то разница в скорости выполнения кода. Хотя в скорости реакции на редкие прерывания разница, вероятно, будет. Если у производителя есть возможность разместить на кристалле эти дополнительные 256КБ, то намного эффективнее отдать бОльшую его часть под пользовательское ОЗУ, и малую - под кеш. Цитата Это из GD32F1 - AN002 Programming flash memory manual. И выход из спячки Standby в 59.4 мс для устройств с памятью до 128К, и 118.8 мс для устройств с памятью больше 128 К неспроста. Из данных этих таблиц можно предположить, что возможно младший сектор имеет отдельную выделенную шину к ядру. А другие сектора - через матрицу шин. И плюс - разрядность шин к этим секторам может быть разной. А разница во времени выхода из спячки возможно объясняется просто тем, что эти сектора выводятся из спячки последовательно, а не параллельно. Например. Да и если предполагать, что там идёт копирование в ОЗУ при выходе из спячки, то почему тогда сектора >= 512КБ имеют ещё бОльшую латентность? Тем, что есть девайсы, в которых "теневое ОЗУ" = 512КБ и копирование из нижних 2-х секторов в это ОЗУ идёт последовательно? Ещё один момент - как раз для случая малопотребляющих устройств: чтение всего объёма флешь при выходе из спячки должно давать значительный бросок тока потребления. Т.е. - как-то очень неправильно. PS: Может быть и реально там есть какое-то теневое ОЗУ. Тут можно только гадать. Но мне представляется такое решение производителя неэффективной тратой ценного ОЗУ. PPS: Ещё одна фантастическая(?) версия: китайцы стырили технологию FRAM/MRAM и младший сектор сделали на ней. Но (так как технология стыреная), чтобы не палиться, пишут что это FLASH. PPPS: Ещё одна версия о происхождении разности времён выхода из спячки: ROM-код проверяет содержимое флеша. Отсюда и 2-кратная разница. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 6 мая, 2022 Опубликовано 6 мая, 2022 · Жалоба статья с хабра https://habr.com/ru/company/ruvds/blog/525842/?ysclid=l2u2op1rco Цитата Хотя флеш-хранилище GD32 должно было бы работать очень медленно, так как это — SPI ROM, в микроконтроллере используется SRAM главного чипа в роли «кеша» для флеш-хранилища, что приводит к тому, что это хранилище быстрее того, которое входит в состав основного чипа. Оно не пребывает в состоянии ожидания даже при работе микроконтроллера на полной доступной ему тактовой частоте. Минус использования SRAM в связке с флеш-памятью заключается в том, что это повышает энергопотребление устройства. Это, кроме того, вызывает задержку при загрузке (небольшую), вызванную тем, что содержимое SPI ROM копируется в SRAM до того, как сможет загрузиться прошивка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vit496 0 10 мая, 2022 Опубликовано 10 мая, 2022 · Жалоба Вот тут в комментариях тоже жалуются на подобную проблему (медленная работа). Приводится цитата из мануала 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); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 10 мая, 2022 Опубликовано 10 мая, 2022 · Жалоба 4 часа назад, vit496 сказал: Тогда я вставил эти функции в реальный проект с размером флеш 350к. Причем, никакой код, кроме этих функций не выполняется (до него не доходит), то есть, никак не должен влиять на результат. И вот что вышло Ну подумайте сами - какая ядру разница, что там записано - 0xFFFFFFF или 0x1234567, если до исполнения этого кода дело все равно не доходит? У флеши ведь нет состояния "ничего не записано", что-то в каждой ячейке все равно хранится, либо ноль, либо единица. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 10 мая, 2022 Опубликовано 10 мая, 2022 · Жалоба 4 часа назад, vit496 сказал: На STM при любых условиях цифры всегда одни и те же и не зависят от занятого размера флеш. code0 data0 tc=3704 (3729) code0 data1 tc=3704 (3729) code1 data0 tc=2778 (2798) code1 data1 tc=2778 (2798) Как же "одни", если сами же пишете разные цифры? Или что означают эти столбцы цифр? Какие-то странные у Вас тесты. Да и сравнивать два разных си-исходника, не имея понятия во что они скомпилились (откуда уверенность, что скомпилились они одинаково? и что выравнивание кода одинаковое?) - это по меньшей мере - легкомысленно. Мягко говоря. 4 часа назад, vit496 сказал: Тогда я вставил эти функции в реальный проект с размером флеш 350к. Причем, никакой код, кроме этих функций не выполняется (до него не доходит), то есть, никак не должен влиять на результат. "Не выполняется"? Уверены? А кто тогда инициализирует периферию, систему тактирования, etc.? Да хотя-бы - тот же ваш источник прерываний/таймер? PS: Какие "тесты" - такие и результаты. Чё сказать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vit496 0 11 мая, 2022 Опубликовано 11 мая, 2022 · Жалоба 18 hours ago, Сергей Борщ said: Ну подумайте сами - какая ядру разница, что там записано - 0xFFFFFFF или 0x1234567, если до исполнения этого кода дело все равно не доходит? У флеши ведь нет состояния "ничего не записано", что-то в каждой ячейке все равно хранится, либо ноль, либо единица. Была дикая мысль, что если размер теневой RAM, например, 256к, то он закэширует туда только флеш без FFFFFFFF -). В этом моем случае дело оказалось в том, что обработчики прерываний разместились по старшим адресам. После принудительного размещения их в первых 256к, тестируемые функции стали работать одинаково при любом размере флеша. Основная программа стала работать ощутимо шустрее, но в еще не работает как положено. Разбираюсь дальше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vit496 0 31 мая, 2022 Опубликовано 31 мая, 2022 (изменено) · Жалоба Один таймер, прерывания каждые 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 Изменено 31 мая, 2022 пользователем vit496 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 31 мая, 2022 Опубликовано 31 мая, 2022 · Жалоба 2 часа назад, vit496 сказал: Меняем размер массива (SZ0), тем самым - размер занятой флеш памяти. До 256к все работает четко - импульсы каждые 100мкс. После 256к - провалы в работе. Примерно каждую миллисекунду какие-то задержки. То есть, получается, что когда идет работа с флеш, которая находится выше 256к, МК начинает что-то делать, так что даже самые высокоприоритетные прерывания откладываются. И времени занимает это "что-то" не менее 250 мкс на частоте 8МГц. На частоте 72МГц - 17-25мкс. Может быть - дочитывает флешь в кеш. Большими порциями. PS: А вообще - тест некорректный. Нормальный компилятор должен вообще весь внутренний for () выкинуть, так как заранее знает, что содержимое массива = 0. Изучите назначение ключевого слова volatile. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
0men 2 4 июля, 2022 Опубликовано 4 июля, 2022 (изменено) · Жалоба тут все просто 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. Код из кода арии выполняется без задержек, код из дата с огромными задержками. Это происходит потому, что в реальности код из кодаарии выполняется из рамы, а код из даты из флэша, который по спи подключен Изменено 4 июля, 2022 пользователем 0men Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 6 июля, 2022 Опубликовано 6 июля, 2022 · Жалоба В 14.11.2021 в 18:41, KnightIgor сказал: SCB->CPUID возвращает/содержит: 0x411FC231 для STM32F103VET 0x412FC231 для GD32F103VET 0x410FC241 для GD32F303VET Похоже, это слово не меняется от экземпляра к экземпляру одного типа, а идентифицирует тип. Это информация о модели CPU В описании на ядро наверное тоже есть расшировка, но этот документ под рукой был. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 12 июля, 2022 Опубликовано 12 июля, 2022 · Жалоба Вот еще интересный документ. Выжимка по отличиям между GD и STM. compatibility sumup between GD32 and STM32_V2.0.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mitya1698 18 24 октября, 2022 Опубликовано 24 октября, 2022 · Жалоба Не слушается 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); } У кого-нибудь получилось? Прочитал рефмануал на ГД , отличий не увидел по модулю декодера вроде. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 24 октября, 2022 Опубликовано 24 октября, 2022 · Жалоба В 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); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mitya1698 18 24 октября, 2022 Опубликовано 24 октября, 2022 · Жалоба а сам таймер зачем инитить, он же в слейв, прескалер вроде как без нужды, регистр перезагрузки FFFF по умолчанию. В стм так работало прекрасно. Обнаружил нестыковку, в СТМ на PB6 PB7 таймер 4 а вот у ГД на них таймер 3 :() Переделал на 3, но не взлетело всеравно. Попробую приведенную выше инициализацию, отпишусь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 24 октября, 2022 Опубликовано 24 октября, 2022 · Жалоба 1 hour ago, mitya1698 said: а сам таймер зачем инитить Правильно, не надо инициализировать железо, а всегда нужно полагаться на то, что лежит в регистрах по-умолчанию, особенно в копиях чипа от других производителей, и уж подавно для их клонов... А то что-то мало "падает самолетов", нужно еще больше Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться