Наконец-то появилось время, начал писать свою библиотеку для AT45. За основу взял исходник at45db161.rar от GDI, кусок кода от mempfis_ и исправленную версию кода этого человека
http://balancer.ru/g/p1203759. Пока сделал процедуру очистки памяти, если с ней разберусь, то думаю в дальнейшем проблем не должно быть. Посмотрите пожалуйста все ли я так делаю?
CODE
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
#include <at45_defines.h>
#define DF_CHIP_SELECT 0x10 // DataFlash chip select port pin (PB 4)
//коды ошибок
enum {
DF_NO_ERROR=0,
DF_WAIT_FAIL,
DF_NOT_MATCH,
DF_UNKNOWN_DEVICE
};
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Активация микросхемы памяти
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void AT45_Check_ON(void)
{
PORTB &= ~DF_CHIP_SELECT; // {SPI_PORT &= ~( (1<<nSS_AT45DBXX)|(1<<SCK)|(1<<MOSI) );}
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Деактивация микросхемы памяти
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void AT45_Check_OFF(void)
{
PORTB |= DF_CHIP_SELECT;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Записываем байт
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void SPI_Write_Byte(unsigned char data)
{
//Start transmission
SPDR = data;
//ожидание завершения передачи
while (!(SPSR & (1<<SPIF))); // while((SPSR & (1<<SPIF)) == 0); while (!(SPSR & 0x80));
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Читаем байт
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
unsigned char SPI_Read_Byte(void)
{
//Start transmission
SPDR = 0x00;
//ожидание завершения передачи
while (!(SPSR & (1<<SPIF)));
return SPDR;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Ожидание готовности памяти
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
unsigned char AT45_Ready_Wait(void)
{
unsigned int i = 25000; //кол-во циклов проверки состояния готовности
unsigned char read_data;
AT45_Check_ON(); //активация микросхемы памяти
SPI_Write_Byte(AT45_OP_STATUS_REGISTER_READ); //инициализация опкода
while(i>0)
{
delay_us(25); //1 мсек = 1000мксек
read_data = SPI_Read_Byte(); //чтение регистра статуса
if( (read_data & 0x80 ) != 0 ) break;
i--;
}
AT45_Check_OFF(); //деактивация микросхемы памяти
if (i != 0) return DF_NO_ERROR; //обработка ошибок
else return DF_WAIT_FAIL;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Стирание блока
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void AT45_Block_Erase(int block_counter)
{
AT45_Check_ON(); //активация микросхемы памяти
SPI_Write_Byte(AT45_OP_BLOCK_ERASE);
SPI_Write_Byte((char)(block_counter>>3)); // 0x3F&(u8_t)(block>>6));
SPI_Write_Byte((char)(block_counter<<5));
SPI_Write_Byte(0x00);
AT45_Check_OFF(); //деактивация микросхемы памяти
if (AT45_Ready_Wait != 0) //по ДШ от 45 до 100 мсек
{
//если ошибка
}
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Полное стирание FLASH
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void AT45_Full_Erase(void)
{
unsigned int block_counter = 0;
while (block_counter<AT45_NUM_BLOCKS)
{
AT45_Block_Erase(block_counter);
block_counter++;
};
}
Теперь несколько глупых вопросов:
1.Возможно стоит использовать активацию и деактивацию памяти (AT45_Check_ON/OFF) только в AT45_Full_Erase перед и после while, а в AT45_Block_Erase и в AT45_Ready_Wait убрать их? Или тут принципиально?
2.Как найти оптимальную задержку delay_us в AT45_Ready_Wait? Или ее стоит убрать вообще как в at45db161.rar?
3.0x80 и 1<<SPIF одно и то же? Если да то сточку read_data & 0x80 можно так же записать read_data & (1<<SPIF) ?
4.В каком случае правильнее активируется память?
SPI_PORT &= ~(1<<DF_CHIP_SELECT);
SPI_PORT &= ~( (1<<DF_CHIP_SELECT)|(1<<SCK)|(1<<MOSI) );
5.В AT45_Block_Erase нашел отличия в исходниках в одной строчке (стоит коммент) 0x3F&(u8_t)(block>>6). Это правильно?
6.В файле at45_defines.h из архива at45db161.rar реализовано 2 варианта кодов, как воспользоваться этим SPI_MODE_0_3 ?