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

Подскажите по записи флэш

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 сказал:

все это лишняя суета

Если стоит задача сделать максимально медленную программу - решение годное.

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


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

Эти строки в программе были ровно 15 минут.

Меня вот интересует вопрос, для записи 16 байт в память пришлось сделать 4 структуры по 4 байта, хотелось бы сделать для красоты

 одну структуру на 4*N байт но не знаю как ее записывать  в память.... как то сдвигать ей адрес чтобы записывалось по 4 байта за раз последовательно в цикле. 

те вопрос как сделать указатель на структуру, чтобы он указывал на начало следующих 4 байт.

 

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

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


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

5 часов назад, whale сказал:

как сделать указатель на структуру, чтобы он указывал на начало следующих 4 байт.

Указатель в каждый момент времени указывает на структуру. Эту структуру. А не на следующие 4 байта. Он не может одновременно указывать в два разных места.

Просто объявите указатель на структуру из 4-х байт (а лучше на объединение 32-битного слова и массива из 4-х байт, как я вам предлагал сделать ранее). В цикле же инкрементируйте указатель. Или индексируйте его счётчиком цикла. Тогда ваш указатель будет сдвигаться на 4 байта вперёд за каждую итерацию цикла..

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

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


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

Почему не посмотреть рабочий пример за 10 минут ?

Вместо двух страниц бессмысленных букв и четырёх потерянных дней ?

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


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

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);	
}

 

 

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


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

Спасибо, не совсем понял куда будет указывать 

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 а структура чтобы было удобно обращаться к переменным по именам а не по цифрам.

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

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


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

21 час назад, whale сказал:

не совсем понял куда будет указывать 


src_buf[1]

На следующее 32-битное слово после src_buf[0].

21 час назад, whale сказал:

можно сделать так 

Чтобы это сказать, нужна постановка задачи. Что вы хотите сохранить во флеш? Сколько данных? Какого типа? 8 чисел типа int? Где они расположены? Тоже во флеше по какому-то известному адресу? Или в ОЗУ?

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


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

22 minutes ago, Darth Vader said:

в ОЗУ

В озу конечно, несколько int штук 20-30 по ситуации,  в основном настройки программы которые меняются в процессе выполнения.

 

23 minutes ago, Darth Vader said:

На следующее 32-битное слово

те у вас автоматически генерируются  несколько структур { двойное слов+ 4 байта } ?

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


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

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;
}

 

 

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


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

2 hours ago, Darth Vader said:

Вот ещё вариант для сохранения объекта

Как то слишком запутано и не прозрачно для меня, попробую пока свой вариант )

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


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

11 часов назад, Darth Vader сказал:

Вот ещё вариант для сохранения объекта произвольного размера без требований к его выравниванию...

У Вас, вроде, там ошибка. Корректно ли будет работать, если data_size будет равен, например, 1, 2 или, может быть, 3?

// Вычисляем необходимое число двойных слов для хранения данных
size_t n_dwords = data_size>>3;
if(data_size&~3) {
  ++n_dwords;
}

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


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

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; }

вообще непонятно что вычисляется. :wacko2:

Если data_size на входе в функцию будет ==8, то получим: n_dwords=2.

Так и задумывалось? Два 64-битных слова? :wacko2: Или всё-таки нужно так?:

size_t n_dwords = data_size + 7 >> 3;

 

Так:

13 часов назад, Darth Vader сказал:

while(FLASH->SR & FLASH_SR_BSY1);

в корректно написанных программах лучше не делать. Разве что в каком-нить учебном коде (примерах) так сойдёт.

 

Смысл копирования через промежуточный буфер dword_buf также неясен. Зачем?? :wacko2: Почему не сразу в to_data_p?

У вас ядро < Cortex-M3? Так в этом случае достаточно использовать указатель на упакованные исходные данные и компилятор всё должен сам сделать.

 

PS: Это-ж надо умудриться в таком коротком коде наделать столько ошибок...... :biggrin:

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


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

Человек хотел продемонстрировать принцип записи во флэш, на это принципе каждый уже может написать что ему удобно.

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


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

9 часов назад, Arlleex сказал:

У Вас, вроде, там ошибка.

 

9 часов назад, jcxz сказал:

Здесь:

21 час назад, Darth Vader сказал:

size_t n_dwords = data_size>>3; if(data_size&~3) { ++n_dwords; }

вообще непонятно что вычисляется. :wacko2:

Если 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 также неясен. Зачем??

Сначала была идея напрямую копировать из ОЗУ во флеш двойными словами, но потом пришло понимание, что такое корректно работает только если данные в ОЗУ заранее выровнены по двойному слову. Если же это не так, то приходится копировать их через промежуточный буфер. А с ним, как оказалось, всё уже не так красиво получается, как видилось раньше.

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


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

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

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

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

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

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

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

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

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

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