564 lines
10 KiB
C
564 lines
10 KiB
C
#include "main.h"
|
|
|
|
#define W25Q128_FLASH_SIZE 0x01000000
|
|
#define W25Q128_ADDR_BIT_NUM 24
|
|
|
|
#define NOR_FLASH_SIZE W25Q128_FLASH_SIZE
|
|
#define NOR_FLASH_ADDR_BIT_NUM W25Q128_ADDR_BIT_NUM
|
|
|
|
#define FLASH_WP_H() LL_GPIO_SetOutputPin(GPIOG,LL_GPIO_PIN_13)
|
|
#define FLASH_WP_L() LL_GPIO_ResetOutputPin(GPIOG,LL_GPIO_PIN_13)
|
|
#define FLASH_HOLD_H() LL_GPIO_SetOutputPin(GPIOE,LL_GPIO_PIN_2)
|
|
#define FLASH_HOLD_L() LL_GPIO_ResetOutputPin(GPIOE,LL_GPIO_PIN_2)
|
|
|
|
#define xSPI_CS_HI() LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_15)
|
|
#define xSPI_CS_LO() LL_GPIO_ResetOutputPin(GPIOA,LL_GPIO_PIN_15)
|
|
|
|
#define xSPI_CLK_HI() LL_GPIO_SetOutputPin(GPIOG,LL_GPIO_PIN_11)
|
|
#define xSPI_CLK_LO() LL_GPIO_ResetOutputPin(GPIOG,LL_GPIO_PIN_11)
|
|
|
|
#define xSPI_SET_MISO_INPUT() GPIOG->MODER&=~0x000C0000
|
|
#define xSPI_SET_MISO_OUTPUT() GPIOG->MODER|=0x00040000
|
|
|
|
#define xSPI_SET_MOSI_INPUT() GPIOD->MODER&=~0x0000C000
|
|
#define xSPI_SET_MOSI_OUTPUT() GPIOD->MODER|=0x00004000
|
|
|
|
#define xSPI_GET_MISO() LL_GPIO_IsInputPinSet(GPIOG,LL_GPIO_PIN_9)
|
|
#define xSPI_MOSI_HI() GPIOD->ODR|=(1<<7)
|
|
#define xSPI_MOSI_LO() GPIOD->ODR&=~(1<<7)
|
|
|
|
#define xSPI_SET_DATA_INPUT() (GPIOG->MODER&=~0x0C0C0000,GPIOE->MODER&=~0x00000030,GPIOD->MODER&=~0x0000C000)
|
|
#define xSPI_SET_DATA_OUTPUT() (GPIOG->MODER|=0x04040000,GPIOE->MODER|=0x00000010,GPIOD->MODER|=0x00004000)
|
|
|
|
#define xSPI_DIN() (((GPIOE->IDR&0x0004)<<1)|((GPIOG->IDR&0x2000)>>11)|((GPIOG->IDR&0x0200)>>8)|((GPIOD->IDR&0x0080)>>7))
|
|
|
|
#define xSPI_D0_HI() LL_GPIO_SetOutputPin(GPIOD,LL_GPIO_PIN_7)
|
|
#define xSPI_D0_LO() LL_GPIO_ResetOutputPin(GPIOD,LL_GPIO_PIN_7)
|
|
#define xSPI_D1_HI() LL_GPIO_SetOutputPin(GPIOG,LL_GPIO_PIN_9)
|
|
#define xSPI_D1_LO() LL_GPIO_ResetOutputPin(GPIOG,LL_GPIO_PIN_9)
|
|
#define xSPI_D2_HI() LL_GPIO_SetOutputPin(GPIOG,LL_GPIO_PIN_13)
|
|
#define xSPI_D2_LO() LL_GPIO_ResetOutputPin(GPIOG,LL_GPIO_PIN_13)
|
|
#define xSPI_D3_HI() LL_GPIO_SetOutputPin(GPIOE,LL_GPIO_PIN_2)
|
|
#define xSPI_D3_LO() LL_GPIO_ResetOutputPin(GPIOE,LL_GPIO_PIN_2)
|
|
|
|
static void flash_reset(void);
|
|
static void flash_write_enable(void);
|
|
static void flash_write_disable(void);
|
|
static void flash_quad_enable(void);
|
|
static void flash_quad_disable(void);
|
|
static uint8_t flash_read_sr1(void);
|
|
static uint8_t flash_read_sr2(void);
|
|
|
|
static void wait(void)
|
|
{
|
|
__nop();
|
|
__nop();
|
|
__nop();
|
|
__nop();
|
|
__nop();
|
|
__nop();
|
|
__nop();
|
|
__nop();
|
|
__nop();
|
|
__nop();
|
|
}
|
|
|
|
void w25q_IO_setup(void)
|
|
{
|
|
static uint8_t val = 0;
|
|
uint32_t i = 0;
|
|
/*
|
|
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOC);
|
|
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOD);
|
|
|
|
//PD6 PC10 12 13 14 15
|
|
GPIOC->MODER &=~0xFF300000;
|
|
GPIOD->MODER &=~0x00003000;
|
|
GPIOC->MODER |= 0x00100000;
|
|
GPIOD->MODER |= 0x00001000; //PD6,PC10 GPIO Output Mode
|
|
|
|
GPIOC->OTYPER &=~0x0000F400; //Output push-pull
|
|
GPIOD->OTYPER &=~0x00000040;
|
|
GPIOC->OSPEEDR |= 0xFF300000; //Very High speed
|
|
GPIOD->OSPEEDR |= 0x00003000;
|
|
*/
|
|
xSPI_CS_HI();
|
|
xSPI_CLK_LO();
|
|
|
|
xSPI_SET_DATA_OUTPUT();
|
|
FLASH_WP_H();
|
|
FLASH_HOLD_H();
|
|
for(i=0;i<10000;i++);
|
|
|
|
flash_write_enable();
|
|
xSPI_SET_DATA_INPUT();
|
|
|
|
flash_reset();
|
|
|
|
xSPI_SET_DATA_OUTPUT();
|
|
FLASH_WP_H();
|
|
FLASH_HOLD_H();
|
|
for(i=0;i<10000;i++);
|
|
flash_write_enable();
|
|
xSPI_SET_DATA_INPUT();
|
|
|
|
do
|
|
{
|
|
val = flash_read_sr1();
|
|
}while(val&0x01);
|
|
|
|
val = flash_read_sr2();
|
|
if(!(val&0x02))
|
|
{
|
|
do
|
|
{
|
|
flash_quad_enable();
|
|
val = flash_read_sr2();
|
|
}while(!(val&0x02));
|
|
}
|
|
}
|
|
|
|
uint8_t QSPI_D0123_read(void)
|
|
{
|
|
return(xSPI_DIN());
|
|
}
|
|
|
|
void QSPI_D0123_write(uint8_t x)
|
|
{
|
|
if(x&0x01)
|
|
{
|
|
xSPI_D0_HI();
|
|
}
|
|
else
|
|
{
|
|
xSPI_D0_LO();
|
|
}
|
|
|
|
if(x&0x02)
|
|
{
|
|
xSPI_D1_HI();
|
|
}
|
|
else
|
|
{
|
|
xSPI_D1_LO();
|
|
}
|
|
|
|
if(x&0x04)
|
|
{
|
|
xSPI_D2_HI();
|
|
}
|
|
else
|
|
{
|
|
xSPI_D2_LO();
|
|
}
|
|
|
|
if(x&0x08)
|
|
{
|
|
xSPI_D3_HI();
|
|
}
|
|
else
|
|
{
|
|
xSPI_D3_LO();
|
|
}
|
|
}
|
|
|
|
void xspi_write_byte(uint8_t data)
|
|
{
|
|
uint32_t i;
|
|
xSPI_SET_MOSI_OUTPUT();
|
|
for(i=0;i<8;i++)
|
|
{
|
|
if(data & 0x80)xSPI_MOSI_HI();
|
|
else xSPI_MOSI_LO();
|
|
|
|
xSPI_CLK_HI();
|
|
xSPI_CLK_LO();
|
|
data<<=1;
|
|
}
|
|
xSPI_MOSI_LO();
|
|
xSPI_SET_MOSI_INPUT();
|
|
}
|
|
|
|
uint8_t xspi_read_byte(void)
|
|
{
|
|
uint32_t i;
|
|
uint8_t data = 0;
|
|
for(i=0;i<8;i++)
|
|
{
|
|
wait();
|
|
data<<=1;
|
|
if(xSPI_GET_MISO())data |= 0x01;
|
|
xSPI_CLK_HI();
|
|
wait();
|
|
xSPI_CLK_LO();
|
|
}
|
|
return data;
|
|
}
|
|
|
|
void xspi_quad_write_byte(uint8_t data)
|
|
{
|
|
xSPI_SET_DATA_OUTPUT();
|
|
QSPI_D0123_write(data>>4);
|
|
xSPI_CLK_HI();
|
|
wait();
|
|
xSPI_CLK_LO();
|
|
QSPI_D0123_write(data);
|
|
xSPI_CLK_HI();
|
|
wait();
|
|
xSPI_CLK_LO();
|
|
xSPI_SET_DATA_INPUT();
|
|
wait();
|
|
}
|
|
|
|
uint8_t xspi_quad_read_byte(void)
|
|
{
|
|
uint8_t data;
|
|
|
|
data = QSPI_D0123_read();
|
|
xSPI_CLK_HI();
|
|
xSPI_CLK_LO();
|
|
data<<=4;
|
|
data |= QSPI_D0123_read();
|
|
xSPI_CLK_HI();
|
|
xSPI_CLK_LO();
|
|
return data;
|
|
}
|
|
|
|
static void flash_write_enable(void)
|
|
{
|
|
uint32_t i = 0;
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x06);
|
|
xSPI_CS_HI();
|
|
for(i=0;i<10000;i++);
|
|
}
|
|
|
|
static void flash_write_disable(void)
|
|
{
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x04);
|
|
xSPI_CS_HI();
|
|
}
|
|
|
|
static uint8_t flash_read_sr1(void)
|
|
{
|
|
uint8_t sr1;
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x05);
|
|
|
|
sr1 = xspi_read_byte();
|
|
wait();
|
|
xSPI_CS_HI();
|
|
return sr1;
|
|
}
|
|
|
|
static uint8_t flash_read_sr2(void)
|
|
{
|
|
uint8_t sr2;
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x35);
|
|
|
|
sr2 = xspi_read_byte();
|
|
wait();
|
|
xSPI_CS_HI();
|
|
return sr2;
|
|
}
|
|
|
|
void flash_write_sr(uint8_t sr1,uint8_t sr2)
|
|
{
|
|
flash_write_enable();
|
|
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x01);
|
|
xspi_write_byte(sr1);
|
|
xspi_write_byte(sr2);
|
|
wait();
|
|
xSPI_CS_HI();
|
|
|
|
flash_write_disable();
|
|
}
|
|
|
|
static void flash_quad_enable(void)
|
|
{
|
|
flash_write_enable();
|
|
flash_write_sr(0x00,0x02);
|
|
flash_write_disable();
|
|
}
|
|
|
|
static void flash_quad_disable(void)
|
|
{
|
|
flash_write_enable();
|
|
flash_write_sr(0x00,0x00);
|
|
flash_write_disable();
|
|
}
|
|
|
|
uint8_t get_flash_write_status(void)
|
|
{
|
|
return(flash_read_sr1() & 0x01);
|
|
}
|
|
|
|
unsigned int flash_quad_read_data(unsigned int addr, unsigned char * p_data,unsigned int len)//p_data >=256byte
|
|
{
|
|
unsigned int i = 0;
|
|
|
|
if((addr + len) > NOR_FLASH_SIZE)return 1;
|
|
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
xspi_write_byte(0x6b);
|
|
xspi_write_byte((addr>>16)&0xff);
|
|
xspi_write_byte((addr>>8)&0xff);
|
|
xspi_write_byte(addr&0xff);
|
|
xspi_write_byte(0);
|
|
|
|
for(i=0;i<len;i++)
|
|
{
|
|
p_data[i] = xspi_quad_read_byte();
|
|
}
|
|
xSPI_CS_HI();
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t* flash_quad_read_page(uint32_t addr)
|
|
{
|
|
uint32_t i = 0;
|
|
unsigned int addr_page = addr & 0xFFFFFF00;
|
|
static uint8_t p_data[288];
|
|
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
xspi_write_byte(0x6b);
|
|
xspi_write_byte((addr_page>>16)&0xff);
|
|
xspi_write_byte((addr_page>>8)&0xff);
|
|
xspi_write_byte(addr_page&0xff);
|
|
xspi_write_byte(0);
|
|
|
|
for(i=0;i<256;i++)
|
|
{
|
|
p_data[i] = xspi_quad_read_byte();
|
|
}
|
|
xSPI_CS_HI();
|
|
return &p_data[0];
|
|
}
|
|
|
|
void flash_quad_program_page(uint32_t addr,uint8_t* p_data)
|
|
{
|
|
uint32_t i = 0;
|
|
unsigned int addr_page = addr & 0xFFFFFF00;
|
|
//flash_quad_enable();
|
|
//do{
|
|
//i = flash_read_sr1();
|
|
//}while(i&0x01);
|
|
|
|
flash_write_enable();
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x32);
|
|
xspi_write_byte((addr_page>>16)&0xff);
|
|
xspi_write_byte((addr_page>>8)&0xff);
|
|
xspi_write_byte(addr_page&0xff);
|
|
|
|
for(i=0;i<256;i++)
|
|
{
|
|
xspi_quad_write_byte(*p_data);
|
|
p_data++;
|
|
}
|
|
xSPI_CS_HI();
|
|
flash_write_disable();
|
|
|
|
do{
|
|
LL_IWDG_ReloadCounter(IWDG1);
|
|
i = flash_read_sr1();
|
|
}while(i&0x01);
|
|
}
|
|
|
|
void flash_quad_program_page_no_wait(uint32_t addr,uint8_t* p_data)
|
|
{
|
|
uint32_t i = 0;
|
|
unsigned int addr_page = addr & 0xFFFFFF00;
|
|
|
|
flash_write_enable();
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x32);
|
|
xspi_write_byte((addr_page>>16)&0xff);
|
|
xspi_write_byte((addr_page>>8)&0xff);
|
|
xspi_write_byte(addr_page&0xff);
|
|
|
|
for(i=0;i<256;i++)
|
|
{
|
|
xspi_quad_write_byte(*p_data);
|
|
p_data++;
|
|
}
|
|
xSPI_CS_HI();
|
|
flash_write_disable();
|
|
}
|
|
|
|
unsigned int flash_quad_program_no_wait(uint32_t addr,uint8_t* p_data,unsigned int len)
|
|
{
|
|
uint32_t i = 0;
|
|
|
|
if(((addr&0xFF) + len) > 0x100)return 1;
|
|
|
|
flash_write_enable();
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x32);
|
|
xspi_write_byte((addr>>16)&0xff);
|
|
xspi_write_byte((addr>>8)&0xff);
|
|
xspi_write_byte(addr&0xff);
|
|
|
|
for(i=0;i<len;i++)
|
|
{
|
|
xspi_quad_write_byte(*p_data);
|
|
p_data++;
|
|
}
|
|
xSPI_CS_HI();
|
|
flash_write_disable();
|
|
return 0;
|
|
}
|
|
|
|
void flash_sector_erase(uint32_t addr)
|
|
{
|
|
unsigned char val = 1;
|
|
unsigned int i = 0;
|
|
unsigned int addr_sector = addr & 0xFFFFF000;
|
|
|
|
flash_write_enable();
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x20);
|
|
xspi_write_byte((addr_sector&0x00FF0000)>>16);
|
|
xspi_write_byte((addr_sector&0x0000FF00)>>8);
|
|
xspi_write_byte(addr_sector&0x000000FF);
|
|
xSPI_CS_HI();
|
|
flash_write_disable();
|
|
|
|
while(val)
|
|
{
|
|
LL_IWDG_ReloadCounter(IWDG1);
|
|
val = (flash_read_sr1() & 0x01);
|
|
}
|
|
|
|
for(i=0;i<10000;i++)__nop();
|
|
}
|
|
|
|
void flash_sector_erase_no_wait(uint32_t addr)
|
|
{
|
|
unsigned char val = 1;
|
|
unsigned int i = 0;
|
|
unsigned int addr_sector = addr & 0xFFFFF000;
|
|
|
|
flash_write_enable();
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x20);
|
|
xspi_write_byte((addr_sector&0x00FF0000)>>16);
|
|
xspi_write_byte((addr_sector&0x0000FF00)>>8);
|
|
xspi_write_byte(addr_sector&0x000000FF);
|
|
xSPI_CS_HI();
|
|
flash_write_disable();
|
|
wait();
|
|
}
|
|
|
|
void flash_full_chip_erase(void) // erase chip
|
|
{
|
|
uint8_t val = 1;
|
|
|
|
flash_write_enable();
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x60);
|
|
xSPI_CS_HI();
|
|
while(val)
|
|
{
|
|
LL_IWDG_ReloadCounter(IWDG1);
|
|
val = (flash_read_sr1() & 0x01);
|
|
}
|
|
}
|
|
|
|
void flash_full_chip_erase_no_wait(void) // erase chip
|
|
{
|
|
uint8_t val = 1;
|
|
|
|
flash_write_enable();
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x60);
|
|
xSPI_CS_HI();
|
|
wait();
|
|
}
|
|
|
|
static void flash_reset(void)
|
|
{
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x66);
|
|
xSPI_CS_HI();
|
|
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x99);
|
|
xSPI_CS_HI();
|
|
|
|
HAL_Delay(5);
|
|
}
|
|
|
|
void flash_read_id(uint8_t *p_ddata)
|
|
{
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
wait();
|
|
xspi_write_byte(0x90); // cmd
|
|
xspi_write_byte(0); // h
|
|
xspi_write_byte(0); // m
|
|
xspi_write_byte(0); // l
|
|
|
|
*p_ddata = xspi_read_byte();
|
|
p_ddata++;
|
|
*p_ddata = xspi_read_byte();
|
|
//wait();
|
|
xSPI_CS_HI();
|
|
}
|
|
|
|
void flash_quad_read_id(uint8_t *p_ddata)
|
|
{
|
|
xSPI_CLK_LO();
|
|
xSPI_CS_LO();
|
|
wait();
|
|
xspi_write_byte(0x94); // cmd
|
|
xspi_quad_write_byte(0); // h
|
|
xspi_quad_write_byte(0); // m
|
|
xspi_quad_write_byte(0); // l
|
|
xspi_quad_write_byte(0xff); // h
|
|
xspi_quad_write_byte(0); // m
|
|
xspi_quad_write_byte(0);
|
|
|
|
*p_ddata = xspi_quad_read_byte();
|
|
p_ddata++;
|
|
*p_ddata = xspi_quad_read_byte();
|
|
wait();
|
|
xSPI_CS_HI();
|
|
}
|