Сергей Борщ 134 28 мая, 2021 Опубликовано 28 мая, 2021 · Жалоба 20 часов назад, whale сказал: if(FLASH->SR & FLASH_SR_PROGERR )err= 3; if(FLASH->SR & FLASH_SR_SIZERR )err= 4; if(FLASH->SR & FLASH_SR_PGAERR )err= 5; if(FLASH->SR & FLASH_SR_WRPERR )err= 6; Просто на будущее: зачем заставлять компилятор 4 раза читать FLASH->SR? Этот регистр сбрасывается записью, а кое-где может сбрасываться чтением и три последних условия просто почти никогда не будут выполняться. Читайте во временную переменную и анализируйте флаги в ней. Хотя... 9 часов назад, whale сказал: все это лишняя суета Если стоит задача сделать максимально медленную программу - решение годное. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 29 мая, 2021 Опубликовано 29 мая, 2021 (изменено) · Жалоба Эти строки в программе были ровно 15 минут. Меня вот интересует вопрос, для записи 16 байт в память пришлось сделать 4 структуры по 4 байта, хотелось бы сделать для красоты одну структуру на 4*N байт но не знаю как ее записывать в память.... как то сдвигать ей адрес чтобы записывалось по 4 байта за раз последовательно в цикле. те вопрос как сделать указатель на структуру, чтобы он указывал на начало следующих 4 байт. Изменено 29 мая, 2021 пользователем whale Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 29 мая, 2021 Опубликовано 29 мая, 2021 (изменено) · Жалоба 5 часов назад, whale сказал: как сделать указатель на структуру, чтобы он указывал на начало следующих 4 байт. Указатель в каждый момент времени указывает на структуру. Эту структуру. А не на следующие 4 байта. Он не может одновременно указывать в два разных места. Просто объявите указатель на структуру из 4-х байт (а лучше на объединение 32-битного слова и массива из 4-х байт, как я вам предлагал сделать ранее). В цикле же инкрементируйте указатель. Или индексируйте его счётчиком цикла. Тогда ваш указатель будет сдвигаться на 4 байта вперёд за каждую итерацию цикла.. Изменено 29 мая, 2021 пользователем Darth Vader Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 29 мая, 2021 Опубликовано 29 мая, 2021 · Жалоба Как это выглядит в коде? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 51 29 мая, 2021 Опубликовано 29 мая, 2021 · Жалоба Почему не посмотреть рабочий пример за 10 минут ? Вместо двух страниц бессмысленных букв и четырёх потерянных дней ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 29 мая, 2021 Опубликовано 29 мая, 2021 · Жалоба 2 часа назад, whale сказал: Как это выглядит в коде? Скрытый текст #include <stdint.h> #define TARGET_ADDR 0x0801F800 #define NWORDS 20 // Сохранение 32-битного слова dst_val во флеше по указателю dst_p void SaveWordToFlash(uint32_t *dst_p, uint32_t dst_val); // Тип объединения 32-битного слова и массива из 4-х байт typedef union { uint32_t w; uint8_t b[4]; } WordUnion_t; // Где-то в коде // Объявляем и заполняем буфер-источник данных WordUnion_t src_buf[NWORDS]; // Заполнять можно побайтно: src_buf[0].b[0] = 1; src_buf[0].b[1] = 2; src_buf[0].b[2] = 3; src_buf[0].b[3] = 4; // или пословно: src_buf[0].w=0x4321 // заполняем все последующие элементы буфера требуемыми значениями // Сохранение NWORDS 32-битных слов из буфера src_buf[] во флеше с адреса TARGET_ADDR uint32_t *TargetP = (uint32_t*)TARGET_ADDR; for(uint32_t i = 0; i != NWORDS; ++i) { SaveWordToFlash(TargetP+i,src_buf[i].w); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 29 мая, 2021 Опубликовано 29 мая, 2021 (изменено) · Жалоба Спасибо, не совсем понял куда будет указывать src_buf[1] я правильно понимаю что можно сделать так struct tpSettings { int d1,d2, d3,d4, d5,d6, d7,d8;}; struct tpSettings Flash_data; uint32_t *source_data = (void *)&Flash_data; for(int i=0; i!=4, i+=2) { (*(__IO uint32_t*)FLASH_address) = *(source_data+i); (*(__IO uint32_t*)(FLASH_address+i*2+4)) = *(source_data+i+1); while(FLASH->SR & FLASH_SR_BSY1); } просто у меня все данные в int а структура чтобы было удобно обращаться к переменным по именам а не по цифрам. Изменено 29 мая, 2021 пользователем whale Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 30 мая, 2021 Опубликовано 30 мая, 2021 · Жалоба 21 час назад, whale сказал: не совсем понял куда будет указывать src_buf[1] На следующее 32-битное слово после src_buf[0]. 21 час назад, whale сказал: можно сделать так Чтобы это сказать, нужна постановка задачи. Что вы хотите сохранить во флеш? Сколько данных? Какого типа? 8 чисел типа int? Где они расположены? Тоже во флеше по какому-то известному адресу? Или в ОЗУ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 30 мая, 2021 Опубликовано 30 мая, 2021 · Жалоба 22 minutes ago, Darth Vader said: в ОЗУ В озу конечно, несколько int штук 20-30 по ситуации, в основном настройки программы которые меняются в процессе выполнения. 23 minutes ago, Darth Vader said: На следующее 32-битное слово те у вас автоматически генерируются несколько структур { двойное слов+ 4 байта } ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 31 мая, 2021 Опубликовано 31 мая, 2021 · Жалоба 19 часов назад, whale сказал: те у вас автоматически генерируются несколько структур { двойное слов+ 4 байта } ? Нет. Там я объявляю массив таких объединений: WordUnion_t src_buf[NWORDS]; Вот ещё вариант для сохранения объекта произвольного размера без требований к его выравниванию Скрытый текст #include <stdint.h> #include <string.h> // Сохраняем во флеш-память по указателю to_data_p объект *from_data_p произвольного размера data_size // возврашает фактически записанный объём флеш-памяти в байтах // указатель to_data_p должен быть выравнен по границе 8 байт size_t SaveToFlash(void* to_data_p, const void* from_data_p, size_t data_size) { // Объединение 64-битного двойного слова // c массивом из 2-х 32-битных слов union dword_u { uint64_t dword; uint32_t word[2]; } dword_buf; // Проверяем выравнивание адреса во флеше на 8 байт if(((size_t)to_data_p) & 3) { // Адрес не выровненный на 8 байт - выходим с нулевым объёмом записанных данных return 0; } // Вычисляем необходимое число двойных слов для хранения данных size_t n_dwords = data_size>>3; if(data_size&~3) { ++n_dwords; } // Заполняем флеш-память двойными словами for(size_t curr_dword = 0; curr_dword != n_dwords; ++curr_dword) { // Заполняем буфер текущим двойным словом memcpy(&dword_buf, (uint8_t*)from_data_p+(curr_dword<<3),8); // Сохраняем текущее двойное слово из буфера во флеш ((union dword_u *)to_data_p)[curr_dword].word[0] = dword_buf.word[0]; ((union dword_u *)to_data_p)[curr_dword].word[1] = dword_buf.word[1]; // Ждем окончания записи флеш-памяти while(FLASH->SR & FLASH_SR_BSY1); } // Возвращаем фактически записанный объем памяти в байтах return n_dwords<<3; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 31 мая, 2021 Опубликовано 31 мая, 2021 · Жалоба 2 hours ago, Darth Vader said: Вот ещё вариант для сохранения объекта Как то слишком запутано и не прозрачно для меня, попробую пока свой вариант ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 173 1 июня, 2021 Опубликовано 1 июня, 2021 · Жалоба 11 часов назад, Darth Vader сказал: Вот ещё вариант для сохранения объекта произвольного размера без требований к его выравниванию... У Вас, вроде, там ошибка. Корректно ли будет работать, если data_size будет равен, например, 1, 2 или, может быть, 3? // Вычисляем необходимое число двойных слов для хранения данных size_t n_dwords = data_size>>3; if(data_size&~3) { ++n_dwords; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 235 1 июня, 2021 Опубликовано 1 июня, 2021 · Жалоба 13 часов назад, Darth Vader сказал: // Проверяем выравнивание адреса во флеше на 8 байт if(((size_t)to_data_p) & 3) { // Адрес не выровненный на 8 байт - выходим с нулевым объёмом записанных данных return 0; } Это проверка выравнивания на 4 байта, а не на 8. Здесь: 13 часов назад, Darth Vader сказал: size_t n_dwords = data_size>>3; if(data_size&~3) { ++n_dwords; } вообще непонятно что вычисляется. Если data_size на входе в функцию будет ==8, то получим: n_dwords=2. Так и задумывалось? Два 64-битных слова? Или всё-таки нужно так?: size_t n_dwords = data_size + 7 >> 3; Так: 13 часов назад, Darth Vader сказал: while(FLASH->SR & FLASH_SR_BSY1); в корректно написанных программах лучше не делать. Разве что в каком-нить учебном коде (примерах) так сойдёт. Смысл копирования через промежуточный буфер dword_buf также неясен. Зачем?? Почему не сразу в to_data_p? У вас ядро < Cortex-M3? Так в этом случае достаточно использовать указатель на упакованные исходные данные и компилятор всё должен сам сделать. PS: Это-ж надо умудриться в таком коротком коде наделать столько ошибок...... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 1 июня, 2021 Опубликовано 1 июня, 2021 · Жалоба Человек хотел продемонстрировать принцип записи во флэш, на это принципе каждый уже может написать что ему удобно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 1 июня, 2021 Опубликовано 1 июня, 2021 · Жалоба 9 часов назад, Arlleex сказал: У Вас, вроде, там ошибка. 9 часов назад, jcxz сказал: Здесь: 21 час назад, Darth Vader сказал: size_t n_dwords = data_size>>3; if(data_size&~3) { ++n_dwords; } вообще непонятно что вычисляется. Если data_size на входе в функцию будет ==8, то получим: n_dwords=2. Так и задумывалось? Да, ошибка. Корректно будет так size_t n_dwords = data_size>>3; // делим на 8 if(data_size&7) { // Если при делении на 8 остаток не нулевой ++n_dwords; // увеличиваем частное на 1 } Что даст тот же результат, что и 9 часов назад, jcxz сказал: size_t n_dwords = data_size + 7 >> 3; 9 часов назад, jcxz сказал: Это проверка выравнивания на 4 байта, а не на 8. Да, тоже ошибка. Для проверки выравнивания на 8 байт должно быть ...&7 Прошу прощения. Код набрасывался на скорую руку и не тестировался. Отсюда ошибки. 9 часов назад, jcxz сказал: У вас ядро < Cortex-M3? Так в этом случае достаточно использовать указатель на упакованные исходные данные и компилятор всё должен сам сделать. Смысл был сделать универсальный код, чтобы корректно работал в том числе и на М0/М0+/М1, и не приводил к хардфолту от невыровненного доступа к данным. 9 часов назад, jcxz сказал: Смысл копирования через промежуточный буфер dword_buf также неясен. Зачем?? Сначала была идея напрямую копировать из ОЗУ во флеш двойными словами, но потом пришло понимание, что такое корректно работает только если данные в ОЗУ заранее выровнены по двойному слову. Если же это не так, то приходится копировать их через промежуточный буфер. А с ним, как оказалось, всё уже не так красиво получается, как видилось раньше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться