FRAM

Чечако
Offline
Зарегистрирован: 15.06.2018

b707 пишет:

Чечако пишет:

Можно объяснить, в чем магия?

какая магия? у вас же в процедуразх записи и считывания используется указатель...

Я о том, почему операция с массивом корректно работает и без этого, а с байтом - заработала только с этим?

b707
Offline
Зарегистрирован: 26.05.2017

Чечако пишет:

Я о том, почему операция с массивом корректно работает и без этого, а с байтом - заработала только с этим?

вы троллите? имя массива является указателем на его первый элемент, а имя одинарной переменной - нет

Чечако
Offline
Зарегистрирован: 15.06.2018

b707 пишет:

вы троллите? имя массива является указателем на его первый элемент, а имя одинарной переменной - нет

Нет, я туплю. :) Да, тогда все логично.  

Чечако
Offline
Зарегистрирован: 15.06.2018

sadman41 пишет:

  
void FM_Write(const uint8_t addr, uint8_t* data, const uint8_t len) {
 ...
int16_t FM_Read(const uint8_t addr, uint8_t* data, const uint8_t len) {
 

Благодарю. :) А активное использование const с передаваемыми параметрами - это просто в качестве защиты от возможных собственных ошибок в коде, или имеет какой-то смысл скажем для компилятора?

Azathtot
Offline
Зарегистрирован: 17.03.2020

Вставлю свои 5 копеек. Гарантированно рабочий код
 

#define FRAM_ADDRESS 0xA0
#define FRAM_BLOCK_SIZE 128
#define FRAM_SIZE 2048

#define HIGHADDR(x)   ((((x)>>8) & 0xFF)<<1)
#define LOW(x) (x & 0xFF)

size_t fram_read(const uint32_t addr, uint8_t *data, const size_t size) {
	if(!twi_start(FRAM_ADDRESS+HIGHADDR(addr), OUT)) return 0;
	twi_writeB(LOW(addr));
	twi_stop();
	if(!twi_start(FRAM_ADDRESS+HIGHADDR(addr), IN)) return 0;
	size_t result = twi_read(data, size);
	twi_stop();
	return result;
}

size_t fram_write(const uint32_t addr, const uint8_t *data, const size_t size) {
	if(!twi_start(FRAM_ADDRESS+HIGHADDR(addr), OUT)) return 0;
	twi_writeB(LOW(addr));
	size_t result = twi_write(data, size);
	twi_stop();
	return result;
}

void fram_erase() {
	if(!twi_start(FRAM_ADDRESS+HIGHADDR(0), OUT)) return;
	twi_writeB(0);
	for(int i=0;i<FRAM_SIZE;i++)
		twi_writeB(0xFF);
	twi_stop();
}

Используется микруха FR24C16, подключение

 

b707
Offline
Зарегистрирован: 26.05.2017

Azathtot, если беретесь выкладывать списанный где-то код - неплохо бы понимать, что он делает.

Запишите этим кодом какое-то значение в ячейку на любой странице памяти далее первой, а потом прочитайте все ячейки подряд, начиная с нулевой. Вы убедитесь, что ваш код пишет совсем не по тому адресу, что вы планировали. так что простите, "гарантия работоспособности" тут не сработала...

Это главное. Ну и плюс к тому в коде полно странностей, показывающих, что его неумело адаптировали из какого-то другого кода - адрес ячейки размером uint32_t,, неиспользуемый дефайн FRAM_BLOCK_SIZE неверного размера и так далее

Azathtot
Offline
Зарегистрирован: 17.03.2020

b707 пишет:

Azathtot, если беретесь выкладывать списанный где-то код - неплохо бы понимать, что он делает.

Списанный, списанный. Из своего проекта.  Я копипастой не увлекаюсь.
По поводу адреса uint32_t кой вы считаете "неумело адаптированный".  У меня работа в проектах не только с  мелкими микрухами памяти. Поэтому размер адреса у меня всегда фиксированный и он uint32_t. Нравится мне так, вас устроит такое объяснение?

Ниже кусок из другого моего проекта, под XMega и W25xxx микрухи
[code]

size_t W25XX::write(const uint32_t address, const void *buffer, size_t size) {
 if(_id ==0) return 0;
 if(address+size > _size) size = _size - address;
 if(size == 0) return 0;
 const uint8_t *p = (const uint8_t *)buffer;
 enableWrite();
 nCS(true);
 *SPI << CMD_WRITE;
 *SPI << ((address >> 16) & 0xff);
 *SPI << ((address >> 8) & 0xff);
 *SPI << ((address & 0xff));
 for(size_t i =0;i<size;i++) {
    if(i > 0 && (address+i) % PAGE_SIZE == 0) {
       nCS(false);
       while((status() & STATUS_BUSY)) wdt_reset();
       return write(address+i,p,size-i);
     }
   *SPI << *p++;
 }
 nCS(false);
 while((status() & STATUS_BUSY)) wdt_reset();
 return size;
}
[/code]
И опять, адрес uint32_t, странно не правда ли? 
Дальше смотрим. 
Опять FRAM, проект под 128 мегу.
[code]
size_t FlashRAM::write(const uint32_t address, const void *data, size_t size) {
  if(_present) {
     if (address >= FRAM_SIZE)
       return 0;
     if (address + size > FRAM_SIZE)
        size = FRAM_SIZE - address;
     size_t len = size;;
     uint8_t *p = (uint8_t *)data;
     uint32_t a = address;
     while(len > 0) {
         size_t block = len > FRAM_BLOCK_SIZE ? FRAM_BLOCK_SIZE : len;
         if (TWIBus->begin(TWIBus::onboard, FRAM_ADDRESS, TWIBus::WRITE)) {
           *TWIBus << (a >> 8);
           *TWIBus << (a & 0xff);
            if(TWIBus->write(p, block)!=block) break;
            TWIBus->end();
            a += block;
            p += block;
           len -= block;
        }
      }
      return size - len;
  }
return 0;
}
[/code]
Опять, uint32_t, странно да?

 

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

b707
Offline
Зарегистрирован: 26.05.2017

Вместо кучи слов посмотрите - код, что вы выложили, рассчитан на размер страницы 128, а у Фрам она 256. Соотаетственно и адрес записи и считывания считается неверно.
Я вам сказал провести тест. Сделайте это вместо спора. Запишите данные своим кодом, а считайте кодом Садман41 из сообщения 50
Только адрес записи должен быть не на первой странице

AndyE
Offline
Зарегистрирован: 30.04.2015

А никто не оформил все эти изыскания в нормальную красивую библиотеку для работы с FRAM?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

я б написал, да у меня нету... :(

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

я б написал, да у меня нету... :(

у меня есть, но мне лень. Можешь написать "тиоритичски", я протестирую :)

sadman41
Offline
Зарегистрирован: 19.10.2016

А я тогда за вас двоих чаю попью - помогу, как могу!

5N62V
Offline
Зарегистрирован: 25.02.2016

под 25ую SPI фрамку писал в прошлом году - все работает с пол оборота , все согласно даташиту.  А кто-то QSPI пробовал с ней? 

Я почему пишу "согласно даташиту". Мне тут недавно поставили задачу Flash ключ интегрировать в сиситему, чтоб доступ имел только тот, кто правильный ключ вставит.  И по ошибке подсунули даташит от 25й флешки. По иронии судьбы коды чтения/записи/опроса статусного регистра совпали. И три дня я трахался пытаясь заставить ее работать. А потом выяснилось , что чутка даташиты перепутали , и адресация там не трехбайтовая , а двухбайтовая :)

 

AndyE
Offline
Зарегистрирован: 30.04.2015

А под I2C ничего нет? 24-я серия, которые.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

у меня есть, но мне лень.

А у тебя какая?  F24Cxx - что вместо xx? 

AndyE
Offline
Зарегистрирован: 30.04.2015

Кстати, а нельзя как-нибудь к i2c чипам прикрутить адресацию через EEMEM, как в либе avr/eeprom? Очень удобно использовать для адресации больших объемов данных.

AndyE
Offline
Зарегистрирован: 30.04.2015

DetSimen пишет:

b707 пишет:

у меня есть, но мне лень.

А у тебя какая?  F24Cxx - что вместо xx? 


У меня есть пара FM24C04

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

AndyE пишет:
А под I2C ничего нет? 24-я серия, которые.

У Кактуса есть.  И у меня, от AT24C32 до AT24C512

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

А у тебя какая?  F24Cxx - что вместо xx? 

04 у меня

AndyE
Offline
Зарегистрирован: 30.04.2015

О, у меня еще и FM24CL16 должны быть. Могу и на них погонять либу, если что.

b707
Offline
Зарегистрирован: 26.05.2017

AndyE пишет:
А под I2C ничего нет? 24-я серия, которые.

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

Там всего кода - строчек 20. Возьмите да напишите как вам надо, с EEMEM или без нее.

Мы когда тут в конфе эти микрухи тестировали - вообще без библиотеки обошлись, там буквально строчек 5 запись и столько же чтение

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

04 у меня

у неё страницы, как у AT24C04 адресом i2c выбираются, или нет?  У той на разных i2c адресах 0x50-0x57 разные страницы.

AndyE
Offline
Зарегистрирован: 30.04.2015

b707 пишет:

AndyE пишет:
А под I2C ничего нет? 24-я серия, которые.

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

Там всего кода - строчек 20. Возьмите да напишите как вам надо, с EEMEM или без нее.

Мы когда тут в конфе эти микрухи тестировали - вообще без библиотеки обошлись, там буквально строчек 5 запись и столько же чтение


Да я понимаю. Просто с моим уровнем я обязательно где-то накосячу и пока разберусь где - пройдёт вечность.
Либу видел, которая исходная. Там побайтовая запись если я правильно понял. Записать массив - уже требуется изврат. А мне, например, нужно хранить структуру из нескольких массивов в памяти.

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

у неё страницы, как у AT24C04 адресом i2c выбираются, или нет?  У той на разных i2c адресах 0x50-0x57 разные страницы.

да, до CL16 включительно страницы выбираются адресом, далее - передаются отдельным байтом при записи или чтении. То есть для флешек размера менее 16кбит и более - протокол немного разный

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

AndyE][quote=b707 пишет:

Там побайтовая запись если я правильно понял. Записать массив - уже требуется изврат. А мне, например, нужно хранить структуру из нескольких массивов в памяти.

Массив - тот же набор байтов. Записать массив - вызвать запись байта стока раз, скока размер массива, не забывая, естесс-но, сдвигать адрес записи. :)  И сё. 

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

Записать массив - вызвать запись байта стока раз, скока размер массива, не забывая, естесс-но, сдвигать адрес записи. :)  И сё. 

та не, дида, тут есть потоковая запись. Передаешь адрес начала масива, число элементов - и оно "само" все сливается в память...

AndyE
Offline
Зарегистрирован: 30.04.2015

Не, ну это понятно, просто до этого упаковывал эти структуры во встроенную EEPROM. Там вообще не приходится заморачиваться с циклами и адресацией. Вот моя ленивая задница и задумалась о том, что наверняка кто-то что-то подобное уже делал и изобретать велосипед нет смысла. :-)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

DetSimen пишет:

Записать массив - вызвать запись байта стока раз, скока размер массива, не забывая, естесс-но, сдвигать адрес записи. :)  И сё. 

та не, дида, тут есть потоковая запись. Передаешь адрес начала масива, число элементов - и оно "само" все сливается в память...

Ессли через Wire писать, то не более 30 байт так запишешь за раз

AndyE
Offline
Зарегистрирован: 30.04.2015

b707 пишет:

DetSimen пишет:

Записать массив - вызвать запись байта стока раз, скока размер массива, не забывая, естесс-но, сдвигать адрес записи. :)  И сё. 

та не, дида, тут есть потоковая запись. Передаешь адрес начала масива, число элементов - и оно "само" все сливается в память...


Тут это где? В конде, в либе или еще где?

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen, на Амперке народ коллективно писал библиотеку под Фрам. я там тоже поучаствовал.

смотри ссылку в #39 сообщении этой ветки, номальный код там вроде с 4-й страницы начинается, но и обсуждение тоже полезное

b707
Offline
Зарегистрирован: 26.05.2017

AndyE пишет:
b707 пишет:

та не, дида, тут есть потоковая запись. Передаешь адрес начала масива, число элементов - и оно "само" все сливается в память...

Тут это где? В конде, в либе или еще где?

в даташите на память

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

Ессли через Wire писать, то не более 30 байт так запишешь за раз

А дальше по твоему совету :) - записал первые 30 байт, покурил, записал следующие :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

смотри ссылку в #39 сообщении этой ветки, номальный код там вроде с 4-й страницы начинается, но и обсуждение тоже полезное

OK, спс. Паматрю.

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

OK, спс. Паматрю.

хочешь, могу тебе пару CL04 выслать? у меня 5шт лежат полтора года, пока ни одну не использовал

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

чота совсем я ослеп. Нету в #39 

http://arduino.ru/forum/programmirovanie/fram#comment-525859

никуда ссылки. :( 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

хочешь, могу тебе пару CL04 выслать? у меня 5шт лежат полтора года, пока ни одну не использовал

Не, я от 4 Кбайт ставлю, AT24C32, не меньше. :)  

а FRAM она же еще в мелком корпусе, я такие не паяю, да и памяти 512 байт, куды ее применять-то. :) 

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

чота совсем я ослеп. Нету в #39

это местный движок ссылки съел. Смотри еще в #20 сообщении - ссылка на тот же тред. Если ее скопировать как текст и вставить в адресную строку - работает у меня

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

DetSimen пишет:

чота совсем я ослеп. Нету в #39

это местный движок ссылки съел. Смотри еще в #20 сообщении - ссылка на тот же тред. Если ее скопировать как текст и вставить в адресную строку - работает у меня

Да. Спс. 

AndyE
Offline
Зарегистрирован: 30.04.2015

DetSimen пишет:

b707 пишет:

хочешь, могу тебе пару CL04 выслать? у меня 5шт лежат полтора года, пока ни одну не использовал

Не, я от 4 Кбайт ставлю, AT24C32, не меньше. :)  

а FRAM она же еще в мелком корпусе, я такие не паяю, да и памяти 512 байт, куды ее применять-то. :) 

Мне в DIP корпусах попадались на Али, но, как говорят, можно нарваться на перемаркированный EEPROM.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

AndyE пишет:

можно нарваться на перемаркированный EEPROM.

если в DIP - это он и есть. 

В даташите есть только SOIC корпус. 

b707
Offline
Зарегистрирован: 26.05.2017

AndyE пишет:

можно нарваться на перемаркированный EEPROM.

мои (смд) выдержали тест на 70 миллионов перезаписей, так что наверно настоящие :)

AndyE
Offline
Зарегистрирован: 30.04.2015

b707 пишет:

мои (смд) выдержали тест на 70 миллионов перезаписей, так что наверно настоящие :)

Мне кажется там по времени записи должно быть понятно. Параметр различается в разы. И нет необходимости 70 миллионов циклов ячейку насиловать Ж-)

Чечако
Offline
Зарегистрирован: 15.06.2018

AndyE пишет:

Мне кажется там по времени записи должно быть понятно. Параметр различается в разы. И нет необходимости 70 миллионов циклов ячейку насиловать Ж-)

Тут лучше переесть, чем недоспать. В смысле, проверить. Я FRAM использую, и из трех закупок у одного поставщика на али одних и тех же FM24C04A у меня две партии нормальные, а третья ничего не запоминает. Я пока не разбирался что с ней именно не так и из чего она ремарк, просто убрал в сторону, времени нету. 

b707
Offline
Зарегистрирован: 26.05.2017

AndyE пишет:

Мне кажется там по времени записи должно быть понятно. Параметр различается в разы.

Энди, как вы предлагаете на практике измерять время записи?

AndyE
Offline
Зарегистрирован: 30.04.2015

b707 пишет:

[Энди, как вы предлагаете на практике измерять время записи?

Взять значение millis() в переменную 1, записать байт, взять значение millis() в переменную 2. Вычесть из переменной 2 переменную 1. Дельта должна примерно соответствовать времени записи.

sadman41
Offline
Зарегистрирован: 19.10.2016

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

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

AndyE
Offline
Зарегистрирован: 30.04.2015

andycat пишет:

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

Чисто теоретическое изыскание с целью проверки FRAM это или EEPROM перемаркированный.

AndyE
Offline
Зарегистрирован: 30.04.2015

Я правильно понимаю, что для FM24C04 у меня будет 2 страницы данных 0х50 и 0х51?

b707
Offline
Зарегистрирован: 26.05.2017

AndyE пишет:

Взять значение millis() в переменную 1, записать байт, взять значение millis() в переменную 2. Вычесть из переменной 2 переменную 1. Дельта должна примерно соответствовать времени записи.

так вы сможете померять только время отсылки байта вашим кодом, к времени записи этого байта микросхемой это не имеет ни малейшего отношения