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

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

У Lapis Semiconductor есть три линейки FRAM микросхем, которые обмениваются с ведущим устройством по I2C или SPI, либо по параллельному интерфейсу. Преимущества последовательных интерфейсов перед параллельным очевидны. Что же касается I2C и SPI, то скорость передачи данных по SPI в 4 раза выше чем по I2C, но и потребление в связи с этим выше практически в 16 раз.

Мне же выбирать не приходилось, в наличии была только MR45V256 c 32 Кб памяти и SPI интерфейсом. 32 Кб для моих нужд более чем достаточно, поэтому оставшуюся память я использовал для записи всевозможной технической информации и логирования команд полученных от оператора.

Работа с FRAM памятью очень простая. Любая операция начинается с перевода линии выбора ведомого устройства CS# в низкое состояние. Затем отправляется одна из команд операций, их всего 6:

— Чтение данных(READ)
— Запись данных(WRITE)
— Запись в регистр статуса FRAM(WRSR)
— Чтение из регистра статуса FRAM(RDSR)
— Установка защиты данных от перезаписи(WRDI)
— Снятие защиты данных от перезаписи(WREN)

Защиту от перезаписи можно установить либо на первую четверть памяти, либо на первую половину или же на всю память полностью. В случаях с командами чтения и записи, после них необходимо отправить еще и шестнадцатеричный адрес, с которого начнется чтение/запись. Команда и адрес отправляются единоразово, в последующем микросхема сама инкрементирует адрес и передает все последующие данные, до тех пор пока CS# не будет переведен в высокое состояние.

Перед тем как начать запись в память, необходимо всегда устанавливать бит разрешения записи(WREN) в регистре статуса MR45V256. И только после этого передавать команду записи(WRITE).

image

В качестве ведущего устройства использовал микроконтроллер Xmega. SPI микроконтроллеров Xmega практически ничем не отличается от SPI в других микроконтроллерах Atmel. Наиболее заметное отличие это возможность использования DMA, но объемы передаваемой информации в данном случае у меня не большие, поэтому от использования DMA я отказался. Xmega поддерживает все 4 режима работы SPI(Mode 0,1,2,3). Стоит заметить, что MR45V256 поддерживает только Mode 0 и Mode 3.

Модуль SPI в Xmega оснащен одноуровневой буферизацией в канале передачи и двухуровневой в канале приёма. То есть, байты для передачи, нельзя поместить в регистр данных SPI пока полностью не завершится цикл сдвигов. Во время приёма данных, принятую посылку необходимо считать прежде, чем завершится приём следующей посылки. В противном случае, первый байт данных будет потерян. Поэтому работать рекомендуется либо по прерываниям, либо при приёме и передаче контролировать регистр статуса SPI.

// Директивы для SPIE
#define	FRAMPORT	PORTE // FRAM PORT
#define	SPIRESET	0
#define	SPICS		4
#define	SPIMOSI		5
#define	SPIMISO		6
#define SPISCK		7

// Функция инициализации SPIE(FRAM)
void SPIE_init()
{
	FRAMPORT.DIRCLR = (1<<SPIMISO); // Выводы SPI на вход
	FRAMPORT.DIRSET = (1<<SPIMOSI) | (1<<SPISCK) | (1<<SPICS); // Выводы SPI на выход
	FRAMPORT.OUTSET = (1<<SPICS);
	// SPI включен, режим мастера, SPI Mode 0, деление частоты тактирования на 4
	SPIE.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_0_gc | SPI_PRESCALER_DIV4_gc;
}

// Функция записи во FRAM
void FRAM_WREN()
{
	SPIE_init();
	FRAMPORT.OUTCLR = (1<<SPICS); // Включаю ChipSelect
	SPIE.DATA = 0x06; // Установка бита разрешения записи
	while( !(SPIE_STATUS & SPI_IF_bm) ); // Жду отчета об отправке
	FRAMPORT.OUTSET = (1<<SPICS); // Выключаю ChipSelect

	PORTE.OUTCLR = (1<<SPICS); // Включаю ChipSelect
	SPIE.DATA = 0x02; // Отправляю команду на запись
	while( !(SPIE_STATUS & SPI_IF_bm) );
	SPIE.DATA = 0x00; // Старший байт адреса
	while( !(SPIE_STATUS & SPI_IF_bm) );
	SPIE.DATA = 0x10; // Младший байт адреса
	while( !(SPIE_STATUS & SPI_IF_bm) );
	
	SPIE.DATA = Data1; // Записываю данные
	while( !(SPIE_STATUS & SPI_IF_bm) );
	SPIE.DATA = Data2;
	while( !(SPIE_STATUS & SPI_IF_bm) );
	SPIE.DATA = Data3;
	while( !(SPIE_STATUS & SPI_IF_bm) );
	
	FRAMPORT.OUTSET = (1<<SPICS); // Выключаю ChipSelect
	SPIE.CTRL = 0x00;
	FRAMPORT.OUTCLR = (1<<SPIMOSI) | (1<<SPISCK);
	
}
// Функция чтения FRAM
void FRAM_RD()
{
	SPIE_init();
	FRAMPORT.OUTCLR = (1<<SPICS); // Включаю ChipSelect
	SPIE.DATA = 0x03;
	while( !(SPIE_STATUS & SPI_IF_bm) );
	SPIE.DATA = 0x00; // Старший байт адреса
	while( !(SPIE_STATUS & SPI_IF_bm) );
	SPIE.DATA = 0x10; // Младший байт адреса
	while( !(SPIE_STATUS & SPI_IF_bm) );
	
	SPIE.DATA = 0x00; // Считываю данные
	while( !(SPIE_STATUS & SPI_IF_bm) );
	Data1 = SPIE.DATA;
	SPIE.DATA = 0x00;
	while( !(SPIE_STATUS & SPI_IF_bm) );
	Data2 = SPIE.DATA;
	SPIE.DATA = 0x00;
	while( !(SPIE_STATUS & SPI_IF_bm) );
	Data3 = SPIE.DATA;
	
	FRAMPORT.OUTSET = (1<<SPICS); // Выключаем ChipSelect
	SPIE.CTRL = 0x00;
	FRAMPORT.OUTCLR = (1<<SPIMOSI) | (1<<SPISCK); // Порты SPI на выход
}

Команды для стирания во FRAM не предусмотрено, так как данные можно перезаписывать без предварительного стирания, как например в других видах памяти. Но всё же иногда возникает необходимость полного «стирания» всей FRAM:

void FramErase(void)
{
	SPIE_init();
	FRAMPORT.OUTCLR = (1<<SPICS); // Включаю ChipSelect
	SPIE.DATA = 0x06; // Отправляю команду WREN
	while( !(SPIE_STATUS & SPI_IF_bm) ); // Жду отчета об отправке
	FRAMPORT.OUTSET = (1<<SPICS); // Выключаю ChipSelect

	PORTE.OUTCLR = (1<<SPICS); // Включаю ChipSelect
	SPIE.DATA = 0x02; // Отправляю команду на запись
	while( !(SPIE_STATUS & SPI_IF_bm) );
	SPIE.DATA = 0x00; // Старший байт адреса
	while( !(SPIE_STATUS & SPI_IF_bm) );
	SPIE.DATA = 0x00; // Младший байт адреса
	while( !(SPIE_STATUS & SPI_IF_bm) );
	
	while(FramCounter <= 0x7FFF)
	{	
		SPIE.DATA = 0x00;
		while( !(SPIE_STATUS & SPI_IF_bm) );
		FramCounter++;
	}
	FRAMPORT.OUTSET = (1<<SPICS); // Выключаю ChipSelect
	FramCounter = 0;
	SPIE.CTRL = 0x00;
	// Порты SPI на выход
	FRAMPORT.OUTCLR = (1<<SPIMOSI) | (1<<SPISCK);	
}

Если говорить о преимуществах использования FRAM, то в первую очередь это надёжность. Количество циклов записи 10 в 12 степени. Производитель обещает до 10 лет хранения информации без её потери. По сравнению с той же FLASH память FRAM обладает большим быстродействием и куда меньшим потреблением. Из минусов можно отметить если только не большой объём памяти, но с учетом тех задач для которых обычно используют FRAM, большие объемы не так важны.
Поделиться с друзьями
-->

Комментарии (13)


  1. jok40
    26.01.2017 12:03

    Читал лет эдак 15-20 назад про FRAM — показалась интересной технологией. Тогда её представляли как убийцу памяти, которая заменит собой и RAM и FLASH. Однако виделось мне всё это довольно фантастическим и трудно реализуемым — не верилось, что когда-либо увижу её в реальном железе. А тут, после Вашей статьи, обрадовался — наконец-то и до FRAM дожили! Однако, полазив по интернету, понял, что счастливое будущее всё ещё не наступило. Микроскопические объёмы и высокая цена слишком ограничивают сферу применения. Ну а Вам за информацию — спасибо!


    1. mpa4b
      27.01.2017 06:46

      Вообще-то я лично лет 15 (а может и больше) назад, где-то на рубеже 90х-2000х, держал в руках и использовал fram-чипы, fm24c01 от ramtron. Рассылались в виде семплов всем подряд. Так что fram — довольно-таки старая технология.


    1. RomanStrlcpy
      27.01.2017 06:46

      С FRAM познакомился наверное лет 10 назад, отличная вещь в сфере автоматики построенной на основе микроконтроллеров. Много места на плате не занимает, быстра, не нужно парить мозг и думать что вот блин как же всё так заоптимизировать, чтобы не съесть циклы EEPROM.

      Вопрос к автору: А что за девайс на XMEGA?


      1. Reason89
        27.01.2017 06:50

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


    1. Reason89
      27.01.2017 06:56
      +1

      Вчера только читал второй выпуск «Зарубежная электронная техника» от 26.01.2017. Там есть небольшая статья про технологию MRAM памяти, которой тоже пророчат светлое будущее, возможно Вам и это будет интересно почитать.


      1. jok40
        27.01.2017 16:43

        Спасибо за наводку. Правда статью из журнала в интернете я так и не нашёл, но зато другие статьи про MRAM почитал. Вроде интересная технология, но как-то не шибко быстро развиваемая. Почему-то не наблюдается её активного проталкивания крупными компаниями на рынок.


        1. Reason89
          27.01.2017 16:55
          +1

          Я постоянно отсюда беру: ЦНИИ «Электроника»


          1. jok40
            27.01.2017 17:37

            Благодарствую! Весьма познавательная статья.


  1. GarryC
    26.01.2017 16:03
    +2

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


  1. vchs
    27.01.2017 06:47

    M24256-XX: EEPROM от ST, 256 Kbit, 0.2$, I2C до 1MHz и более 4 миллионов циклов записи.


  1. Sajan-san
    27.01.2017 06:47

    У Texas Instruments есть семейство контроллеров MSP430FRxx, где Flash-память для кода (и у некоторых чипов для пользовательских данных) полностью заменена на FRAM. Т.е. вместо привычного сочетания Flash ROM + RAM в этих контроллерах FRAM + RAM.


    1. GarryC
      27.01.2017 12:26
      +1

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


  1. Ivanii
    28.01.2017 14:16

    А как сейчас обстоит дело с SRAM памятью, с I2C под нужды хранения конфига?
    В лохматые годы в контроллере накопителя на гибких магнитных дисках для БК-0010 было 16 КБ SRAM и программа в этом SRAM без батареи переживала без разрушения отключения питания на несколько секунд.