Флеш-память от ST Microelectronics

28 Декабря 2010 К комментариям

Собрался купить для очереного проекта память AT45DB161 в корпусе SO8-300, но не смог по причине отсутсвия у поставщиков :( хотя у одного поставщика нашел по цене в 600 рублей.

Решил глянуть что есть у ST Microelectronics, и как оказалось не зря :)

Есть у них серия микросхем в небольших корпусах, до двух мегабайт в SO-8, выше в SO16-300.

На пробу купил на два мегабайта M25P16, всего за 45 рублей.

Вся область разбита на сектора, сектора в свою очередь на страницы по 256 байт.

Не понравилось то что стереть можно либо всю флешку, либо сектор :( хотелось бы иметь возможность стирать страницу.

Для теста подключил к свободным ножкам МК и простым “ножко-дрыганьем” записал и считал пару страниц.

Команды:

enum M25P16_Command
{
	M25P16_WRITE_ENABLE = 0x06,
	M25P16_WRITE_DISABLE = 0x04,
	M25P16_READ_IDENTEFICATION = 0x9F,
	M25P16_READ_STATUS_REGISTER = 0x05,
	M25P16_WRITE_STATUS_REGISTER = 0x01,
	M25P16_READ = 0x03,
	M25P16_READ_FAST = 0x0B,
	M25P16_PAGE_PROGAM = 0x02,
	M25P16_SECTOR_ERASE = 0xD8,
	M25P16_BULK_ERASE = 0xC7,
	M25P16_DEEP_POWER_DOWN = 0xB9,
	M25P16_RELEASE_FROM_POWER_DOWN = 0xAB,
};

Тестовый кусочек кода:

void m25p16_test(void)
{
	for (i = 0; i < 256; i++)
		buffer[i] = i;

	// разрешаем запись
	m25p16_write_enable();
	// стираем
	m25p16_bulk_erase();
	// ожидаем
	while (m25p16_read_status() & 0x01)
	{

	}
	// разрешаем запись
	m25p16_write_enable();
	// пишем
	m25p16_page_write(0, &buffer[0]);
	// ожидаем
	while (m25p16_read_status() & 0x01)
	{

	}
	// разрешаем запись
	m25p16_write_enable();
	// пишем
	m25p16_page_write(1, &buffer[0]);
	// ожидаем
	while (m25p16_read_status() & 0x01)
	{

	}

	// читаем
	m25p16_page_read(0, &buffer[0]);
	for (i = 0; i < 256; i++)
		_DBH(buffer[i]);
	// читаем
	m25p16_page_read(1, &buffer[0]);
	for (i = 0; i < 256; i++)
		_DBH(buffer[i]);
}

Чтение регистра статуса:

uint8_t m25p16_read_status(void)
{
	uint8_t status;

	PIN_M25P16_CS_ON();

	m25p16_io_write(M25P16_READ_STATUS_REGISTER);

	status = m25p16_io_read();

	PIN_M25P16_CS_OFF();

	return status;
}

Перед стиранием или программированием необходимо разрешить запись:

void m25p16_write_enable(void)
{
	PIN_M25P16_CS_ON();

	m25p16_io_write(M25P16_WRITE_ENABLE);

	PIN_M25P16_CS_OFF();
}

и если передумали отменить:

void m25p16_write_disable(void)
{
	PIN_M25P16_CS_ON();

	m25p16_io_write(M25P16_WRITE_DISABLE);

	PIN_M25P16_CS_OFF();
}

Запись одной страницы:

void m25p16_page_write(uint16_t page_address, uint8_t * buffer)
{
	uint8_t byte_number;

	PIN_M25P16_CS_ON();

	m25p16_io_write(M25P16_PAGE_PROGAM);

	m25p16_io_write(page_address >> 8);
	m25p16_io_write(page_address >> 0);
	m25p16_io_write(0x00);

	for (byte_number = 0; byte_number++ < 255;)
	{
		m25p16_io_write(*buffer++);
	}

	m25p16_io_write(*buffer);

	PIN_M25P16_CS_OFF();
}

Чтение одной страницы:

void m25p16_page_read(uint16_t page_address, uint8_t * buffer)
{
	uint8_t byte_number;

	PIN_M25P16_CS_ON();

	m25p16_io_write(M25P16_READ);

	m25p16_io_write(page_address >> 8);
	m25p16_io_write(page_address >> 0);
	m25p16_io_write(0);

	for (byte_number = 0; byte_number++ < 255;)
	{
		*buffer++ = m25p16_io_read();
	}

	*buffer = m25p16_io_read();

	PIN_M25P16_CS_OFF();
}

Стереть всю флешку:

void m25p16_bulk_erase(void)
{
	PIN_M25P16_CS_ON();

	m25p16_io_write(M25P16_BULK_ERASE);

	PIN_M25P16_CS_OFF();
}

Стереть один сектор:

void m25p16_sector_erase(uint8_t sector_address)
{
	PIN_M25P16_CS_ON();

	m25p16_io_write(M25P16_SECTOR_ERASE);

	m25p16_io_write(sector_address);
	m25p16_io_write(0x00);
	m25p16_io_write(0x00);

	PIN_M25P16_CS_OFF();
}

Обмен данными:

void m25p16_io_write(uint8_t data)
{
	uint8_t bit_number;

	for (bit_number = 8; bit_number-- > 0;)
	{
		PIN_M25P16_CLK_OFF();

		if ((data & 0x80) == 0)
		{
			PIN_M25P16_DI_OFF();
		}
		else
		{
			PIN_M25P16_DI_ON();
		}

		PIN_M25P16_CLK_ON();

		data = data < < 1;
	}

	PIN_M25P16_CLK_OFF();
}


uint8_t m25p16_io_read(void)
{
	uint8_t bit_number;
	uint8_t data = 0;

	for (bit_number = 8; bit_number-- > 0;)
	{
		PIN_M25P16_CLK_OFF();

		data = data < < 1;

		PIN_M25P16_CLK_ON();

		if (PIN_M25P16_DO_SIGNAL())
			data |= 1;
	}

	PIN_M25P16_CLK_OFF();

	return data;
}


comments powered by Disqus