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

stm32f1xx - внешняя флеш память по SPI

Пытаюсь общаться по SPI с внешней флеш памятью at45db081

Инициализация SPI:

void spi_init(void)
{
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

   port.GPIO_Mode = GPIO_Mode_AF_PP;
   port.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
   port.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &port);

   port.GPIO_Mode = GPIO_Mode_Out_PP;
   port.GPIO_Pin = GPIO_Pin_4;
   port.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &port);

   SPI_StructInit(&spi);
   spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
   spi.SPI_Mode = SPI_Mode_Master;
   spi.SPI_DataSize = SPI_DataSize_8b;
   spi.SPI_CPOL = SPI_CPOL_Low;
   spi.SPI_CPHA = SPI_CPHA_2Edge;
   spi.SPI_NSS = SPI_NSS_Soft;
   spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
   spi.SPI_FirstBit = SPI_FirstBit_MSB;
   spi.SPI_CRCPolynomial = 7;
   SPI_Init(SPI1, &spi);
   SPI_Cmd(SPI1, ENABLE);
   SPI_DataSizeConfig(SPI1, ENABLE);
}

 

отсылка и прием байта данных:

uint8_t sendByte(uint8_t byteToSend)
{
   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
   SPI_I2S_SendData(SPI1, byteToSend);
   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
   return (uint8_t)SPI_I2S_ReceiveData(SPI1);
}

 

В main пробую записать в начало памяти одну страницу данных (команда 0x85, три байта адреса и посылка), прочитать статусный регистр (команда 0xD7 - регистр читается, память не занята), а потом пробую читать с самого начала памяти (команда 0xE8, три байта адреса и 4 незначащих) - но принимаются одни и те же данные, независимого от того, что писал, т.е. это даже не прием данных:

int main(void)
{
SetSysClockTo72();
spi_init();
uint8_t data= 0;
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
data = sendByte(0x85);
data = sendByte(0x00);
data = sendByte(0x00);
data = sendByte(0x00);
for (int i = 0; i < 264; i++)
{
data = sendByte(0xEE);
}
GPIO_SetBits(GPIOA, GPIO_Pin_4);
for (int i = 0; i < 1000; i++);
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
sendByte(0xD7);
data = sendByte(DUMMY); // чтение статусного регистра
GPIO_SetBits(GPIOA, GPIO_Pin_4);
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
sendByte(0xE8);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
   while(1)
   {
   	data = sendByte(DUMMY);
   }
}

прием проверяю через debug в CooCox

гугление и поиск по форуму не помогли, не могу найти видимо какую то глупую ошибку

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


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

Я сам не применял, но вроде код ниже это для общения с подобной флешкой:

 

u8 SPI_Send(u8 data) 
{
WDG_func();

SPI_I2S_SendData(SPI2, data);  // отправили данные

while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){Circl_FUNC ();}; // ждём, пока данные не отправятся

while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){Circl_FUNC ();};  // ждём пока данные появятся

u8 received = SPI_I2S_ReceiveData(SPI2);

return received;
}

//Dataflash opcodes
#define FlashPageRead	   0x52  // Main memory page read
#define FlashToBuf1Transfer	   0x53  // Main memory page to buffer 1 transfer
#define Buf1Read		0x54  // Buffer 1 read
#define FlashToBuf2Transfer	   0x55  // Main memory page to buffer 2 transfer
#define Buf2Read		0x56  // Buffer 2 read
#define StatusReg	   0x57  // Status register
#define AutoPageReWrBuf1	  0x58  // Auto page rewrite through buffer 1
#define AutoPageReWrBuf2	  0x59  // Auto page rewrite through buffer 2
#define FlashToBuf1Compare				0x60  // Main memory page to buffer 1 compare
#define FlashToBuf2Compare		  0x61  // Main memory page to buffer 2 compare
#define ContArrayRead	   0x68  // Continuous Array Read (Note : Only A/B-parts supported)
#define FlashProgBuf1	   0x82  // Main memory page program through buffer 1
#define Buf1ToFlashWE		 0x83  // Buffer 1 to main memory page program with built-in erase
#define Buf1Write	   0x84  // Buffer 1 write
#define FlashProgBuf2	   0x85  // Main memory page program through buffer 2
#define Buf2ToFlashWE		 0x86  // Buffer 2 to main memory page program with built-in erase
#define Buf2Write	   0x87  // Buffer 2 write
#define Buf1ToFlash		   0x88  // Buffer 1 to main memory page program without built-in erase
#define Buf2ToFlash			 0x89  // Buffer 2 to main memory page program without built-in erase




// Constants
//Look-up table for these sizes ->  512k, 1M, 2M, 4M, 8M, 16M, 32M, 64M
unsigned char DF_pagebits[]  ={  9,  9,  9,  9,  9,  10,  10,  11}; //index of internal page address bits

// Globals
unsigned char PageBits;

// Functions

/*****************************************************************************
*
* Function name : DF_SPI_init
*
* Returns :   None
*
* Parameters :  None
*
* Purpose :   Sets up the HW SPI in Master mode, Mode 3
*		 Note -> Uses the SS line to control the DF CS-line.
*
******************************************************************************/
//Set SS high
//Set SS, MOSI and SCK as outputs
//Enable SPI in Master mode, mode 3

/*****************************************************************************
*
* Function name : Read_DF_status
*
* Returns :   One status byte. Consult Dataflash datasheet for further
*	   decoding info
*
* Parameters :  None
*
* Purpose :   Status info concerning the Dataflash is busy or not.
*	   Status info concerning compare between buffer and flash page
*	   Status info concerning size of actual device
*
******************************************************************************/
unsigned char Read_DF_status (void)
{
 unsigned char result,index_copy;

 DF_CS_inactive();   //make sure to toggle CS signal in order
 DF_CS_active();		   //to reset dataflash command decoder
 result = SPI_Send(StatusReg);  //send status register read op-code
 result = SPI_Send(0x00);   //dummy write to get result

 index_copy = ((result & 0x38) >> 3);  //get the size info from status register
 PageBits   = DF_pagebits[index_copy]; //get number of internal page address bits from look-up table

 Transf("Read_DF_status:");
 sprintf(strng,"%x",result);
 Transf(strng);
 Transf("\r\n");

 Transf("PageBits:");
 sprintf(strng,"%x",PageBits);
 Transf(strng);
 Transf("\r\n");

 Transf("index_copy:");
 sprintf(strng,"%x",index_copy);
 Transf(strng);
 Transf("\r\n");

 return result;		//return the read status register value
}


/*****************************************************************************
*
* Function name : Page_To_Buffer
*
* Returns :   None
*
* Parameters :  BufferNo  ->  Decides usage of either buffer 1 or 2
*		 PageAdr   ->  Address of page to be transferred to buffer
*
* Purpose :   Transfers a page from flash to dataflash SRAM buffer
*
******************************************************************************/
void Page_To_Buffer (unsigned int PageAdr, unsigned char BufferNo)
{
 DF_CS_inactive();	   //make sure to toggle CS signal in order
 DF_CS_active();	   //to reset dataflash command decoder

 if (1 == BufferNo)	  //transfer flash page to buffer 1
 {
SPI_Send(FlashToBuf1Transfer); //transfer to buffer 1 op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)(PageAdr << (PageBits - 8)));  //lower part of page address
SPI_Send(0x00);			//don't cares
 }
 else
 if (2 == BufferNo)					  //transfer flash page to buffer 2
 {
SPI_Send(FlashToBuf2Transfer);		//transfer to buffer 2 op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)(PageAdr << (PageBits - 8)));  //lower part of page address
SPI_Send(0x00);			//don't cares
 }

 DF_CS_inactive();	   //initiate the transfer
 DF_CS_active();

 while(!(Read_DF_status() & 0x80));  //monitor the status register, wait until busy-flag is high
}



/*****************************************************************************
*
* Function name : Buffer_Read_Byte
*
* Returns :   One read byte (any value)
*
* Parameters :  BufferNo  ->  Decides usage of either buffer 1 or 2
*		 IntPageAdr  ->  Internal page address
*
* Purpose :   Reads one byte from one of the dataflash
*		 internal SRAM buffers
*
******************************************************************************/
unsigned char Buffer_Read_Byte (unsigned char BufferNo, unsigned int IntPageAdr)
{
 unsigned char data;

 DF_CS_inactive();	 //make sure to toggle CS signal in order
 DF_CS_active();	 //to reset dataflash command decoder

 if (1 == BufferNo)	//read byte from buffer 1
 {
SPI_Send(Buf1Read);		//buffer 1 read op-code
SPI_Send(0x00);			  //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));	//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(0x00);		//don't cares
data = SPI_Send(0x00);	 //read byte
 }
 else
 if (2 == BufferNo)  //read byte from buffer 2
 {
SPI_Send(Buf2Read);  //buffer 2 read op-code
SPI_Send(0x00);  //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(0x00);		//don't cares
data = SPI_Send(0x00);	 //read byte
 };

 return data;	//return the read data byte
}



/*****************************************************************************
*
* Function name : Buffer_Read_Str
*
* Returns :   None
*
* Parameters :  BufferNo  ->  Decides usage of either buffer 1 or 2
*		 IntPageAdr  ->  Internal page address
*		 No_of_bytes ->  Number of bytes to be read
*		 *BufferPtr  ->  address of buffer to be used for read bytes
*
* Purpose :   Reads one or more bytes from one of the dataflash
*		 internal SRAM buffers, and puts read bytes into
*		 buffer pointed to by *BufferPtr
*
******************************************************************************/
void Buffer_Read_Str (unsigned char BufferNo, unsigned int IntPageAdr, unsigned int No_of_bytes, unsigned char *BufferPtr)
{
 unsigned int i;

 DF_CS_inactive();	 //make sure to toggle CS signal in order
 DF_CS_active();	 //to reset dataflash command decoder

 if (1 == BufferNo)	//read byte(s) from buffer 1
 {
SPI_Send(Buf1Read);	//buffer 1 read op-code
SPI_Send(0x00);	//don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(0x00);			//don't cares
for( i=0; i<No_of_bytes; i++)
{
  *(BufferPtr) = SPI_Send(0x00);   //read byte and put it in AVR buffer pointed to by *BufferPtr
  BufferPtr++;			//point to next element in AVR buffer
}
 }
 else
 if (2 == BufferNo)		  //read byte(s) from buffer 2
 {
SPI_Send(Buf2Read);		  //buffer 2 read op-code
SPI_Send(0x00);			//don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(0x00);			//don't cares
for( i=0; i<No_of_bytes; i++)
{
  *(BufferPtr) = SPI_Send(0x00);   //read byte and put it in AVR buffer pointed to by *BufferPtr
  BufferPtr++;		//point to next element in AVR buffer
}
 }
}
//NB : Sjekk at (IntAdr + No_of_bytes) < buffersize, hvis ikke blir det bare ball..



/*****************************************************************************
*
* Function name : Buffer_Write_Enable
*
* Returns :   None
*
* Parameters :  IntPageAdr  ->  Internal page address to start writing from
*		 BufferAdr ->  Decides usage of either buffer 1 or 2
*
* Purpose :   Enables continous write functionality to one of the dataflash buffers
*		 buffers. NOTE : User must ensure that CS goes high to terminate
*		 this mode before accessing other dataflash functionalities
*
******************************************************************************/
void Buffer_Write_Enable (unsigned char BufferNo, unsigned int IntPageAdr)
{
 DF_CS_inactive();	 //make sure to toggle CS signal in order
 DF_CS_active();	 //to reset dataflash command decoder

 if (1 == BufferNo)	//write enable to buffer 1
 {
SPI_Send(Buf1Write);   //buffer 1 write op-code
SPI_Send(0x00);	//don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
 }
 else
 if (2 == BufferNo)			//write enable to buffer 2
 {
SPI_Send(Buf2Write);		   //buffer 2 write op-code
SPI_Send(0x00);			//don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));  //upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr));	 //lower part of internal buffer address
 }
}



/*****************************************************************************
*
* Function name : Buffer_Write_Byte
*
* Returns :   None
*
* Parameters :  IntPageAdr  ->  Internal page address to write byte to
*		 BufferAdr ->  Decides usage of either buffer 1 or 2
*		 Data	->  Data byte to be written
*
* Purpose :   Writes one byte to one of the dataflash
*		 internal SRAM buffers
*
******************************************************************************/
void Buffer_Write_Byte (unsigned char BufferNo, unsigned int IntPageAdr, unsigned char Data)
{

 DF_CS_inactive();   //make sure to toggle CS signal in order
 DF_CS_active();   //to reset dataflash command decoder

 if (1 == BufferNo)  //write byte to buffer 1
 {
SPI_Send(Buf1Write);   //buffer 1 write op-code
SPI_Send(0x00);	//don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(Data);		//write data byte
 }
 else
 if (2 == BufferNo)		//write byte to buffer 2
 {
SPI_Send(Buf2Write);	   //buffer 2 write op-code
SPI_Send(0x00);		//don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(Data);		//write data byte
 }
}


/*****************************************************************************
*
* Function name : Buffer_Write_Str
*
* Returns :   None
*
* Parameters :  BufferNo  ->  Decides usage of either buffer 1 or 2
*		 IntPageAdr  ->  Internal page address
*		 No_of_bytes ->  Number of bytes to be written
*		 *BufferPtr  ->  address of buffer to be used for copy of bytes
*				 from AVR buffer to dataflash buffer 1 (or 2)
*
* Purpose :   Copies one or more bytes to one of the dataflash
*		 internal SRAM buffers from AVR SRAM buffer
*		 pointed to by *BufferPtr
*
******************************************************************************/
void Buffer_Write_Str (unsigned char BufferNo, unsigned int IntPageAdr, unsigned int No_of_bytes, unsigned char *BufferPtr)
{
 unsigned int i;

 DF_CS_inactive(); //make sure to toggle CS signal in order
 DF_CS_active();   //to reset dataflash command decoder

 if (1 == BufferNo)	//write byte(s) to buffer 1
 {
SPI_Send(Buf1Write);   //buffer 1 write op-code
SPI_Send(0x00);	//don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));	 //upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
for( i=0; i<No_of_bytes; i++)
{
  SPI_Send(*(BufferPtr));  //write byte pointed at by *BufferPtr to dataflash buffer 1 location
  BufferPtr++;	//point to next element in AVR buffer
}
 }
 else
 if (2 == BufferNo)	//write byte(s) to buffer 2
 {
SPI_Send(Buf2Write);   //buffer 2 write op-code
SPI_Send(0x00);	//don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));	  //upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
for( i=0; i<No_of_bytes; i++)
{
  SPI_Send(*(BufferPtr));  //write byte pointed at by *BufferPtr to dataflash buffer 2 location
  BufferPtr++;	//point to next element in AVR buffer
}
 }
}
//NB : Monitorer busy-flag i status-reg.
//NB : Sjekk at (IntAdr + No_of_bytes) < buffersize, hvis ikke blir det bare ball..



/*****************************************************************************
*
* Function name : Buffer_To_Page
*
* Returns :   None
*
* Parameters :  BufferAdr ->  Decides usage of either buffer 1 or 2
*		 PageAdr   ->  Address of flash page to be programmed
*
* Purpose :   Transfers a page from dataflash SRAM buffer to flash
*
******************************************************************************/
void Buffer_To_Page (unsigned char BufferNo, unsigned int PageAdr)
{
 DF_CS_inactive();	   //make sure to toggle CS signal in order
 DF_CS_active();	   //to reset dataflash command decoder

 if (1 == BufferNo)	  //program flash page from buffer 1
 {
SPI_Send(Buf1ToFlashWE);   //buffer 1 to flash with erase op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)(PageAdr << (PageBits - 8)));  //lower part of page address
SPI_Send(0x00);			//don't cares
 }
 else
 if (2 == BufferNo)	  //program flash page from buffer 2
 {
SPI_Send(Buf2ToFlashWE);   //buffer 2 to flash with erase op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)(PageAdr << (PageBits - 8)));  //lower part of page address
SPI_Send(0x00);  //don't cares
 }

 DF_CS_inactive();	 //initiate flash page programming
 DF_CS_active();

 while(!(Read_DF_status() & 0x80));   //monitor the status register, wait until busy-flag is high
}


/*****************************************************************************
*
* Function name : Cont_Flash_Read_Enable
*
* Returns :   None
*
* Parameters :  PageAdr   ->  Address of flash page where cont.read starts from
*		 IntPageAdr  ->  Internal page address where cont.read starts from
*
* Purpose :   Initiates a continuous read from a location in the DataFlash
*
******************************************************************************/
void Cont_Flash_Read_Enable (unsigned int PageAdr, unsigned int IntPageAdr)
{
 DF_CS_inactive();   //make sure to toggle CS signal in order
 DF_CS_active();	 //to reset dataflash command decoder

 SPI_Send(ContArrayRead);   //Continuous Array Read op-code
 SPI_Send((unsigned char)(PageAdr >> (16 - PageBits)));   //upper part of page address
 SPI_Send((unsigned char)((PageAdr << (PageBits - 8))+ (IntPageAdr>>8))); //lower part of page address and MSB of int.page adr.
 SPI_Send((unsigned char)(IntPageAdr)); //LSB byte of internal page address
 SPI_Send(0x00);		//perform 4 dummy writes
 SPI_Send(0x00);		//in order to intiate DataFlash
 SPI_Send(0x00);		//address pointers
 SPI_Send(0x00);
}

// *****************************[ End Of DATAFLASH.c]*************************

 

..хотя может я фигню вам написал, что-то команды не совпадают.

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


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

Пытаюсь общаться по SPI с внешней флеш памятью at45db081

 

В main пробую записать в начало памяти одну страницу данных (команда 0x85, три байта адреса и посылка), прочитать статусный регистр (команда 0xD7 - регистр читается, память не занята), а потом пробую читать с самого начала памяти (команда 0xE8, три байта адреса и 4 незначащих) - но принимаются одни и те же данные, независимого от того, что писал, т.е. это даже не прием данных:

 

прием проверяю через debug в CooCox

гугление и поиск по форуму не помогли, не могу найти видимо какую то глупую ошибку

 

Я писал страницы at45db321d командой 0x82, только предварительно их стерев 0x81 и между адресом и посылкой я снимал CS на 100мс

 

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


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

Вот из работающего проекта кусочек... посмотрите, что получится.

Работало с AT26DF081A

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

dataflash.c.txt

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

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


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

Давно работаю с этой флешкой - весч удобная и надежная.

Обратите внимание на следующее:

1. Запись в флеш (если страница заранее стерта и не используется команда "запись со встроенным стиранием")

1.1. записать данные в буфер (1 или 2) SRAM флеш. (ожидание завершение записи не требуется)

1.2. дать команду флеш на запись буфера (1 или 2) в флеш-массив. После записи флеш

будет занята этй операцией, кажется несколько миллисекунд 4-5 мс.

2. Чтение.

Есть чтение через буфер и чтение массива напрямую.

Операция выполняется без ожидания.

 

Так как цикл работы и проверки состоит из 2 фаз - чтение и запись -

Вам сильно помог бы программатор, который позволяет считать (или записать) флешку "гарантированным" способом.

Для отладки чтения (это проще всего проверяется) я заполнял на программаторе флеш паттерном с инкриментом (номер страницы+номер байта в странице)

До работы с флеш проверьте что SPI настроен и работает (закольцуйте MISO-MOSI)

 

ps

// Считать из флеш содержимое буфера
// 1-номер буфера (1 2)
// 2-адрес в BF-SRAM, с которого начать чтение
// 3-кол-во байт, которые требуется считать
// 4-указатель внешней памяти (dest, куда)
// 5-проверять-ждать готовность флеш
int AT45_ReadBuf( char n_buf, int a_addr, int n_size, char *to_ptr,  int test_ready)
{    
        char cmd_45 = C45_RD_BUFF_1;                // 054x 0x56 по умолчанию
    if( n_buf == AT45_BUFF_2 ) cmd_45 = C45_RD_BUFF_2;    // ошибки не обрабатываются
        if( n_size > 264 ) return( -2 );    // Err 2
    AT45_TEST_READY( test_ready );    
    // ----------------------        
    SET_CS0_AT45;
    SPI_TX( cmd_45 );    // 54/56 Read430<--Buf(1,2)
    SPI_TX(0);
    SPI_TX( A16_HI(a_addr) );    // старший байт адреса
    SPI_TX( A16_LO(a_addr) );    
    SPI_TX(0x00);            // Additional byte
    for( int i=0; i<n_size; i++) { *to_ptr = SPI_TX(0x00); to_ptr++; }
    CS_ALL_1;
    // ----------------------    
    
    return(1);

}//f

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

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


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

MOSI и MISO закольцовывал - все нормально, что отправляется, то и доходит

Сейчас какая-то странная проблема - память как будто не стабильно работает, т.е. запускаю отладку один раз - все работает, пишется через 82h и читается через E8h, но иногда при запуске программа застревает в цикле проверки регистра статуса - память просто не выдает регистр, переменная равна 0. И работает память только при значении предделителя 8 (т.е. на 9 MHz), хотя при более низких частотах же тоже должна работать.

Может это быть проблемой настройки SPI или подключения? Уже который день пытаюсь настроить нормально работу, но все в одних и тех же ошибках.

Изменено пользователем Herz
Избыточное цитирование

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


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

какой SPI MODE - 0, 1, 2 или 3 выбрано?

spi.SPI_CPOL = SPI_CPOL_Low;

spi.SPI_CPHA = SPI_CPHA_2Edge;

какому оно соответствует? из четырех возможных допустимы только два (0 или 3, кажется).

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

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


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

но иногда при запуске программа застревает в цикле проверки регистра статуса - память просто не выдает регистр, переменная равна 0.

Поэтому я не проверял этот регистр, а ставил паузу. Может нужна пауза при проверке статуса...

 

И работает память только при значении предделителя 8 (т.е. на 9 MHz), хотя при более низких частотах же тоже должна работать.

 

Там ещё все ножки должны быть припаяны, даже брюхо и кондёр по питанию рядом. Ну и качество питания при включении платы.

Флешка не на проводах? На одной плате с контроллером?

 

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


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

. . . .

Может это быть проблемой настройки SPI или подключения? Уже который день пытаюсь настроить нормально работу, но все в одних и тех же ошибках.

Это цепочка из правильной настройки SPI, правильного обращения к AT45 и правильного алгоритма работы с состояниями AT45.

Для проверки сначала поработайте с буфером (первым или вторым) SRAM - без записи в массив флеш.

Буфер не требует ожидания готовности (так как это оперативная память). Соотв-но флешка "всегда готова".

Если все будет норм. - значит SPI и алгоритм обращения на AT45 правильный.

Если не читается регистр статуса - а он должен читаться ВСЕГДА - то чтото с SPI или Вашим алгоритмом.

Все блоки команд дожны отделятся "своим" CS.

Вам надо контролировать работу с "освобождением" сдвигового регистра, возможно еще не ушла

первая команда, а Вы шлете следующую.

//читаем статус
char AT45_StatusGet(void)
{
    SET_CS0_AT45;
    wrSPI( C45_RD_STATUS );
    wrSPI(0);
    CS_ALL_1;
    return( UCB0RXBUF );
}

char AT45_Ready(void)
{
  if( AT45_StatusGet() & 0x80 ) //
    return(1);    // Ready
  else
    return(0);    // ! Ready
}


// здесь следует добавить временную задержку delay(n) или Sleep(n)
// чтобы не лезть непрерывно на SPI и флеш
#define AT45_TEST_READY( t_rdy ) \
    if( t_rdy )     \
    {        int n_times = 0;    \
            while( ! AT45_Ready() )    \
            if( n_times > 10000 )    \
            return(-1);        \
            else            \
            n_times++;        \
    }                    \

 

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


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

. . . .
sendByte(0xD7);
data = sendByte(DUMMY);                
GPIO_SetBits(GPIOA, GPIO_Pin_4); --------------- (!)
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
sendByte(0xE8);
sendByte(0x00);
sendByte(0x00);

 

(!) - если это CS - то возможно обрубается обмен по SPI

(CS снимается раньше, чем выдвигается-вдвигается shift-регистр SPI)

Не знаю, как организован моудль SPI у STM (буферизация итд)

 

 

 

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


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

Не знаю, как организован моудль SPI у STM (буферизация итд)

да также, как у всех :)

нужно флаг контроллить

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


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

KamilSafin, вот тестовый проект в keil 4.7 (проверял на плате TE stm32f107, там стоит flash at45db321d), попробуйте, только перенастройте периферию под свой проект. SPI3.zip
Изменено пользователем ivan24190

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


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

KamilSafin, вот тестовый проект

ну о чем и говорилось:

//----------------------------------------------------------------------------------------------------
/* Обмен с Flash-памятью байтом */
uint8_t FlashByteExchg(uint8_t Byte)
{
    while(!(SPI3->SR & SPI_SR_TXE));
    SPI3->DR = Byte;
    while(!(SPI3->SR & SPI_SR_RXNE));
    return SPI3->DR;
}
;

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


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

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

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

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

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

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

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

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

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

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