/****************************************************************************************************************************************** * 文件名称: GD25Q21.c * 功能说明: GD25Q21 SPI Flash 驱动程序 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1 * 注意事项: * 版本日期: V1.0.0 2017年10月26日 * 升级记录: ******************************************************************************************************************************************* * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN- * -ECTION WITH THEIR PRODUCTS. * * COPYRIGHT 2012 Synwit Technology *******************************************************************************************************************************************/ #include "SWM221.h" #include "GD25Q21.h" /****************************************************************************************************************************************** * 函数名称: GD25Q21_Init() * 功能说明: 初始化GD25Q21使用的SPI接口,并读取芯片ID以判断其是否是GD25Q21芯片 * 输 入: 无 * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ void GD25Q21_Init(void) { uint16_t chip_id; uint8_t manufacture_id, device_id; SPI_InitStructure SPI_initStruct; GPIO_Init(GPIOB, PIN15, 1, 0, 0, 0); #define GD25Q21_Assert() GPIO_ClrBit(GPIOB, PIN15) #define GD25Q21_Deassert() GPIO_SetBit(GPIOB, PIN15) GD25Q21_Deassert(); PORT_Init(PORTB, PIN10, PORTB_PIN10_SPI0_SCLK, 0); PORT_Init(PORTB, PIN13, PORTB_PIN13_SPI0_MOSI, 0); PORT_Init(PORTB, PIN14, PORTB_PIN14_SPI0_MISO, 1); SPI_initStruct.clkDiv = SPI_CLKDIV_32; SPI_initStruct.FrameFormat = SPI_FORMAT_SPI; SPI_initStruct.SampleEdge = SPI_FIRST_EDGE; SPI_initStruct.IdleLevel = SPI_LOW_LEVEL; SPI_initStruct.WordSize = 8; SPI_initStruct.Master = 1; SPI_initStruct.RXThreshold = 0; SPI_initStruct.RXThresholdIEn = 0; SPI_initStruct.TXThreshold = 0; SPI_initStruct.TXThresholdIEn = 0; SPI_initStruct.TXCompleteIEn = 0; SPI_Init(SPI0, &SPI_initStruct); SPI_Open(SPI0); chip_id = GD25Q21_ReadChipID(); manufacture_id = chip_id >> 8; device_id = chip_id & 0xFF; if((manufacture_id == GD25Q21_MANUFACTOR_ID) && (device_id == GD25Q21_DEVICE_ID)) { printf("GD25Q21 found\r\n"); } else { printf("Manufactor ID: %02X, Device ID: %02X, fail to identify\r\n", manufacture_id, device_id); } } /****************************************************************************************************************************************** * 函数名称: GD25Q21_ReadChipID() * 功能说明: 读取芯片ID * 输 入: 无 * 输 出: uint16_t 芯片ID,共16位,高8位为厂商ID,低8位为Device ID * 注意事项: 无 ******************************************************************************************************************************************/ uint16_t GD25Q21_ReadChipID(void) { uint8_t manufacture_id, device_id; GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_READ_CHIP_ID); SPI_ReadWrite(SPI0, 0x00); SPI_ReadWrite(SPI0, 0x00); SPI_ReadWrite(SPI0, 0x00); manufacture_id = SPI_ReadWrite(SPI0, 0xFF); device_id = SPI_ReadWrite(SPI0, 0xFF); GD25Q21_Deassert(); return (manufacture_id << 8) | device_id; } /****************************************************************************************************************************************** * 函数名称: GD25Q21_ReadStatus() * 功能说明: 读取芯片状态寄存器 * 输 入: 无 * 输 出: uint16_t 芯片状态 * 注意事项: 无 ******************************************************************************************************************************************/ uint16_t GD25Q21_ReadStatus(void) { uint16_t status; GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_READ_STATUS_L); status = SPI_ReadWrite(SPI0, 0xFF); GD25Q21_Deassert(); GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_READ_STATUS_H); status |= SPI_ReadWrite(SPI0, 0xFF) << 8; GD25Q21_Deassert(); return status; } /****************************************************************************************************************************************** * 函数名称: GD25Q21_IsBusy() * 功能说明: 芯片忙检测,执行擦除、写入操作后需要执行忙检测以判断芯片是否已经完成操作 * 输 入: 无 * 输 出: uint32_t 1 芯片正在执行内部擦除、写入操作 0 芯片未在执行内部操作 * 注意事项: 无 ******************************************************************************************************************************************/ uint32_t GD25Q21_IsBusy(void) { return (GD25Q21_ReadStatus() & GD25Q21_STATUS_WIP_Msk) ? 1 : 0; } /****************************************************************************************************************************************** * 函数名称: GD25Q21_QuadSwitch() * 功能说明: 4线读开关 * 输 入: uint32_t 1 开启4线读写 0 关闭4线读写 * 输 出: uint16_t 芯片状态 * 注意事项: 无 ******************************************************************************************************************************************/ void GD25Q21_QuadSwitch(uint32_t on) { uint16_t status = GD25Q21_ReadStatus(); if(on) status |= (1 << GD25Q21_STATUS_QE_Pos); else status &= ~(1 << GD25Q21_STATUS_QE_Pos); GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_WRITE_ENABLE); GD25Q21_Deassert(); GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_WRITE_STATUS); SPI_ReadWrite(SPI0, (status >> 0) & 0xFF); SPI_ReadWrite(SPI0, (status >> 8) & 0xFF); GD25Q21_Deassert(); } /****************************************************************************************************************************************** * 函数名称: GD25Q21_EraseSector() * 功能说明: 扇区擦除 * 输 入: uint32_t addr 要擦除的扇区的地址,每扇区4K字节 * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ void GD25Q21_EraseSector(uint32_t addr) { GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_WRITE_ENABLE); GD25Q21_Deassert(); GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_ERASE_SECTOR); SPI_ReadWrite(SPI0, (addr >> 16) & 0xFF); SPI_ReadWrite(SPI0, (addr >> 8) & 0xFF); SPI_ReadWrite(SPI0, (addr >> 0) & 0xFF); GD25Q21_Deassert(); } /****************************************************************************************************************************************** * 函数名称: GD25Q21_ReadData() * 功能说明: 从GD25Q21指定地址读取指定个字节数据 * 输 入: uint32_t addr 要读取的数据在GD25Q21上的地址 * uint8_t buff[] 读取到的数据存储在buff中 * uint32_t cnt 要读取数据的字节个数 * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ void GD25Q21_ReadData(uint32_t addr, uint8_t buff[], uint32_t cnt) { uint32_t i; GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_READ_DATA); SPI_ReadWrite(SPI0, (addr >> 16) & 0xFF); SPI_ReadWrite(SPI0, (addr >> 8) & 0xFF); SPI_ReadWrite(SPI0, (addr >> 0) & 0xFF); for(i = 0; i < cnt; i++) { buff[i] = SPI_ReadWrite(SPI0, 0xFF); } GD25Q21_Deassert(); } /****************************************************************************************************************************************** * 函数名称: GD25Q21_WritePage() * 功能说明: 向GD25Q21指定地址处写入指定个字节数据 * 输 入: uint32_t addr 数据要写入到GD25Q21的位置 * uint8_t data[] 要写入的数据 * uint16_t cnt 要写入的数据个数,每页256字节,每次写入的数据必须在同一页的地址范围内 * 输 出: 无 * 注意事项: 无 ******************************************************************************************************************************************/ void GD25Q21_WritePage(uint32_t addr, uint8_t data[], uint16_t cnt) { uint32_t i; GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_WRITE_ENABLE); GD25Q21_Deassert(); GD25Q21_Assert(); SPI_ReadWrite(SPI0, GD25Q21_CMD_WRITE_PAGE); SPI_ReadWrite(SPI0, (addr >> 16) & 0xFF); SPI_ReadWrite(SPI0, (addr >> 8) & 0xFF); SPI_ReadWrite(SPI0, (addr >> 0) & 0xFF); for(i = 0; i < cnt; i++) { SPI_ReadWrite(SPI0, data[i]); } GD25Q21_Deassert(); }