first submission
This commit is contained in:
@@ -0,0 +1,461 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : SPI_FLAH.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.1
|
||||
* Date : 2022/11/24
|
||||
* Description : SPI FLASHChip operation file
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/* Header Files */
|
||||
#include <SPI_FLASH.h>
|
||||
#include <SW_UDISK.h>
|
||||
#include "ch32v20x_spi.h"
|
||||
|
||||
/******************************************************************************/
|
||||
volatile uint8_t Flash_Type = 0x00; /* FLASH chip: 0: W25XXXseries */
|
||||
volatile uint32_t Flash_ID = 0x00; /* FLASH ID */
|
||||
volatile uint32_t Flash_Sector_Count = 0x00; /* FLASH sector number */
|
||||
volatile uint16_t Flash_Sector_Size = 0x00; /* FLASH sector size */
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_Port_Init
|
||||
* Description : FLASH chip operation related pins and hardware initialization
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_Port_Init( void )
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
||||
SPI_InitTypeDef SPI_InitStructure = {0};
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 , ENABLE);
|
||||
|
||||
/* CS# */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_2);
|
||||
|
||||
/* SCK */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* MISO */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* MOSI */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
|
||||
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
|
||||
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
|
||||
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
SPI_InitStructure.SPI_CRCPolynomial = 7;
|
||||
|
||||
SPI_Init(SPI1, &SPI_InitStructure);
|
||||
// SPI1->HSCR |= 0x01; // Enable High Speed Read
|
||||
SPI_Cmd(SPI1, ENABLE);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SPI1_ReadWriteByte
|
||||
*
|
||||
* @brief SPI1 read or write one byte.
|
||||
*
|
||||
* @param TxData - write one byte data.
|
||||
*
|
||||
* @return Read one byte data.
|
||||
*/
|
||||
uint8_t SPI1_ReadWriteByte(uint8_t TxData)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
|
||||
{
|
||||
i++;
|
||||
if(i > 200)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPI_I2S_SendData(SPI1, TxData);
|
||||
i = 0;
|
||||
|
||||
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
|
||||
{
|
||||
i++;
|
||||
if(i > 200)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SPI_I2S_ReceiveData(SPI1);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SPI_FLASH_SendByte
|
||||
* Description : SPI send a byte
|
||||
* Input : byte: byte to send
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
uint8_t SPI_FLASH_SendByte( uint8_t byte )
|
||||
{
|
||||
return SPI1_ReadWriteByte( byte );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SPI_FLASH_ReadByte
|
||||
* Description : SPI receive a byte
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : byte received
|
||||
*******************************************************************************/
|
||||
uint8_t SPI_FLASH_ReadByte( void )
|
||||
{
|
||||
return SPI1_ReadWriteByte( 0xFF );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ReadID
|
||||
* Description : Read FLASH ID
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : chip id
|
||||
*******************************************************************************/
|
||||
uint32_t FLASH_ReadID( void )
|
||||
{
|
||||
uint32_t dat;
|
||||
PIN_FLASH_CS_LOW( );
|
||||
SPI_FLASH_SendByte( CMD_FLASH_JEDEC_ID );
|
||||
dat = ( uint32_t )SPI_FLASH_SendByte( DEF_DUMMY_BYTE ) << 16;
|
||||
dat |= ( uint32_t )SPI_FLASH_SendByte( DEF_DUMMY_BYTE ) << 8;
|
||||
dat |= SPI_FLASH_SendByte( DEF_DUMMY_BYTE );
|
||||
PIN_FLASH_CS_HIGH( );
|
||||
return( dat );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_WriteEnable
|
||||
* Description : FLASH Write Enable
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_WriteEnable( void )
|
||||
{
|
||||
PIN_FLASH_CS_LOW( );
|
||||
SPI_FLASH_SendByte( CMD_FLASH_WREN );
|
||||
PIN_FLASH_CS_HIGH( );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_WriteDisable
|
||||
* Description : FLASH Write Disable
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_WriteDisable( void )
|
||||
{
|
||||
PIN_FLASH_CS_LOW( );
|
||||
SPI_FLASH_SendByte( CMD_FLASH_WRDI );
|
||||
PIN_FLASH_CS_HIGH( );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ReadStatusReg
|
||||
* Description : FLASH Read Status
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : status
|
||||
*******************************************************************************/
|
||||
uint8_t FLASH_ReadStatusReg( void )
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
PIN_FLASH_CS_LOW( );
|
||||
SPI_FLASH_SendByte( CMD_FLASH_RDSR );
|
||||
status = SPI_FLASH_ReadByte( );
|
||||
PIN_FLASH_CS_HIGH( );
|
||||
return( status );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_Erase_Sector
|
||||
* Description : FLASH Erase Sector
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_Erase_Sector( uint32_t address )
|
||||
{
|
||||
uint8_t temp;
|
||||
FLASH_WriteEnable( );
|
||||
PIN_FLASH_CS_LOW( );
|
||||
SPI_FLASH_SendByte( CMD_FLASH_SECTOR_ERASE );
|
||||
SPI_FLASH_SendByte( (uint8_t)( address >> 16 ) );
|
||||
SPI_FLASH_SendByte( (uint8_t)( address >> 8 ) );
|
||||
SPI_FLASH_SendByte( (uint8_t)address );
|
||||
PIN_FLASH_CS_HIGH( );
|
||||
do
|
||||
{
|
||||
temp = FLASH_ReadStatusReg( );
|
||||
}while( temp & 0x01 );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_RD_Block_Start
|
||||
* Description : FLASH start block read
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_RD_Block_Start( uint32_t address )
|
||||
{
|
||||
PIN_FLASH_CS_LOW( );
|
||||
SPI_FLASH_SendByte( CMD_FLASH_READ );
|
||||
SPI_FLASH_SendByte( (uint8_t)( address >> 16 ) );
|
||||
SPI_FLASH_SendByte( (uint8_t)( address >> 8 ) );
|
||||
SPI_FLASH_SendByte( (uint8_t)address );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_RD_Block
|
||||
* Description : FLASH read block
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_RD_Block( uint8_t *pbuf, uint32_t len )
|
||||
{
|
||||
while( len-- )
|
||||
{
|
||||
*pbuf++ = SPI_FLASH_ReadByte( );
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_RD_Block_End
|
||||
* Description : FLASH end block read
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_RD_Block_End( void )
|
||||
{
|
||||
PIN_FLASH_CS_HIGH( );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : W25XXX_WR_Page
|
||||
* Description : Flash page program
|
||||
* Input : address
|
||||
* len
|
||||
* *pbuf
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void W25XXX_WR_Page( uint8_t *pbuf, uint32_t address, uint32_t len )
|
||||
{
|
||||
uint8_t temp;
|
||||
FLASH_WriteEnable( );
|
||||
PIN_FLASH_CS_LOW( );
|
||||
SPI_FLASH_SendByte( CMD_FLASH_BYTE_PROG );
|
||||
SPI_FLASH_SendByte( (uint8_t)( address >> 16 ) );
|
||||
SPI_FLASH_SendByte( (uint8_t)( address >> 8 ) );
|
||||
SPI_FLASH_SendByte( (uint8_t)address );
|
||||
if( len > SPI_FLASH_PerWritePageSize )
|
||||
{
|
||||
len = SPI_FLASH_PerWritePageSize;
|
||||
}
|
||||
while( len-- )
|
||||
{
|
||||
SPI_FLASH_SendByte( *pbuf++ );
|
||||
}
|
||||
PIN_FLASH_CS_HIGH( );
|
||||
do
|
||||
{
|
||||
temp = FLASH_ReadStatusReg( );
|
||||
}while( temp & 0x01 );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : W25XXX_WR_Block
|
||||
* Description : W25XXX block write
|
||||
* Input : address
|
||||
* len
|
||||
* *pbuf
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void W25XXX_WR_Block( uint8_t *pbuf, uint32_t address, uint32_t len )
|
||||
{
|
||||
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
|
||||
|
||||
Addr = address % SPI_FLASH_PageSize;
|
||||
count = SPI_FLASH_PageSize - Addr;
|
||||
NumOfPage = len / SPI_FLASH_PageSize;
|
||||
NumOfSingle = len % SPI_FLASH_PageSize;
|
||||
|
||||
if( Addr == 0 )
|
||||
{
|
||||
if( NumOfPage == 0 )
|
||||
{
|
||||
W25XXX_WR_Page( pbuf, address, len );
|
||||
}
|
||||
else
|
||||
{
|
||||
while( NumOfPage-- )
|
||||
{
|
||||
W25XXX_WR_Page( pbuf, address, SPI_FLASH_PageSize );
|
||||
address += SPI_FLASH_PageSize;
|
||||
pbuf += SPI_FLASH_PageSize;
|
||||
}
|
||||
W25XXX_WR_Page( pbuf, address, NumOfSingle );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( NumOfPage == 0 )
|
||||
{
|
||||
if( NumOfSingle > count )
|
||||
{
|
||||
temp = NumOfSingle - count;
|
||||
W25XXX_WR_Page( pbuf, address, count );
|
||||
address += count;
|
||||
pbuf += count;
|
||||
W25XXX_WR_Page( pbuf, address, temp );
|
||||
}
|
||||
else
|
||||
{
|
||||
W25XXX_WR_Page( pbuf, address, len );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len -= count;
|
||||
NumOfPage = len / SPI_FLASH_PageSize;
|
||||
NumOfSingle = len % SPI_FLASH_PageSize;
|
||||
W25XXX_WR_Page( pbuf, address, count );
|
||||
address += count;
|
||||
pbuf += count;
|
||||
while( NumOfPage-- )
|
||||
{
|
||||
W25XXX_WR_Page( pbuf, address, SPI_FLASH_PageSize );
|
||||
address += SPI_FLASH_PageSize;
|
||||
pbuf += SPI_FLASH_PageSize;
|
||||
}
|
||||
if( NumOfSingle != 0 )
|
||||
{
|
||||
W25XXX_WR_Page( pbuf, address, NumOfSingle );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_IC_Check
|
||||
* Description : check flash type
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_IC_Check( void )
|
||||
{
|
||||
uint32_t count;
|
||||
|
||||
/* Read FLASH ID */
|
||||
Flash_ID = FLASH_ReadID( );
|
||||
printf("Flash_ID: %08x\n",(uint32_t)Flash_ID);
|
||||
|
||||
Flash_Type = 0x00;
|
||||
Flash_Sector_Count = 0x00;
|
||||
Flash_Sector_Size = 0x00;
|
||||
|
||||
switch( Flash_ID )
|
||||
{
|
||||
/* W25XXX */
|
||||
case W25X10_FLASH_ID: /* 0xEF3011-----1M bit */
|
||||
count = 1;
|
||||
break;
|
||||
|
||||
case W25X20_FLASH_ID: /* 0xEF3012-----2M bit */
|
||||
count = 2;
|
||||
break;
|
||||
|
||||
case W25X40_FLASH_ID: /* 0xEF3013-----4M bit */
|
||||
count = 4;
|
||||
break;
|
||||
|
||||
case W25X80_FLASH_ID: /* 0xEF4014-----8M bit */
|
||||
count = 8;
|
||||
break;
|
||||
|
||||
case W25Q16_FLASH_ID1: /* 0xEF3015-----16M bit */
|
||||
case W25Q16_FLASH_ID2: /* 0xEF4015-----16M bit */
|
||||
count = 16;
|
||||
break;
|
||||
|
||||
case W25Q32_FLASH_ID1: /* 0xEF4016-----32M bit */
|
||||
case W25Q32_FLASH_ID2: /* 0xEF6016-----32M bit */
|
||||
count = 32;
|
||||
break;
|
||||
|
||||
case W25Q64_FLASH_ID1: /* 0xEF4017-----64M bit */
|
||||
case W25Q64_FLASH_ID2: /* 0xEF6017-----64M bit */
|
||||
count = 64;
|
||||
break;
|
||||
|
||||
case W25Q128_FLASH_ID1: /* 0xEF4018-----128M bit */
|
||||
case W25Q128_FLASH_ID2: /* 0xEF6018-----128M bit */
|
||||
count = 128;
|
||||
break;
|
||||
|
||||
case W25Q256_FLASH_ID1: /* 0xEF4019-----256M bit */
|
||||
case W25Q256_FLASH_ID2: /* 0xEF6019-----256M bit */
|
||||
count = 256;
|
||||
break;
|
||||
default:
|
||||
if( ( Flash_ID != 0xFFFFFFFF ) && ( Flash_ID != 0x00000000 ) )
|
||||
{
|
||||
count = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 0x00;
|
||||
}
|
||||
break;
|
||||
}
|
||||
count = ( (uint32_t)count * 1024 ) * ( (uint32_t)1024 / 8 );
|
||||
|
||||
if( count )
|
||||
{
|
||||
Flash_Sector_Count = count / DEF_UDISK_SECTOR_SIZE;
|
||||
Flash_Sector_Size = DEF_UDISK_SECTOR_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("External Flash not connected\r\n");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user