执行程序前,需要将SPIM进行初始化,代码如下:
/*************************************************************************************************************
* 文件名 : m48x_spim.c
* 功能 : m48X SPIM驱动
* 作者 : cp1300@139.com
* 创建时间 : 2021-09-24
* 最后修改时间 : 2021-09-24
* 详细 : 只支持W25Q系列flash,并且需要falsh支持4线模式,并且均不支持4字节地址模式,地址24bit
SS设置必须与官方例程一样,否则会导致直接内存映射模式下无法读取flash
*************************************************************************************************************/
#include "m48x_map.h"
#include "system.h"
#include "m48x_spim.h"
//SPIM IO口选择
#define SPIM_IO_PA0_5 0 //使用PA0.5
#define SPIM_IO_PC0_5 1 //使用PC0.5
#define SPIM_IO_PE2_7 2 //使用PE2.7
#define SPIM_IO_PG9_14 3 //使用PG9.14
#define SPIM_IO_SELECT SPIM_IO_PC0_5
/* Flash opcodes. */
#define OPCODE_WREN 0x06U /* Write enable */
#define OPCODE_RDSR 0x05U /* Read status register #1*/
#define OPCODE_WRSR 0x01U /* Write status register #1 */
#define OPCODE_RDSR2 0x35U /* Read status register #2*/
#define OPCODE_WRSR2 0x31U /* Write status register #2 */
#define OPCODE_RDSR3 0x15U /* Read status register #3*/
#define OPCODE_WRSR3 0x11U /* Write status register #3 */
#define OPCODE_PP 0x02U /* Page program (up to 256 bytes) */
#define OPCODE_SE_4K 0x20U /* Erase 4KB sector */
#define OPCODE_BE_32K 0x52U /* Erase 32KB block */
#define OPCODE_CHIP_ERASE 0xc7U /* Erase whole flash chip */
#define OPCODE_BE_64K 0xd8U /* Erase 64KB block */
#define OPCODE_READ_ID 0x90U /* Read ID */
#define OPCODE_RDID 0x9fU /* Read JEDEC ID */
#define OPCODE_BRRD 0x16U /* SPANSION flash - Bank Register Read command */
#define OPCODE_BRWR 0x17U /* SPANSION flash - Bank Register write command */
#define OPCODE_NORM_READ 0x03U /* Read data bytes */
#define OPCODE_FAST_READ 0x0bU /* Read data bytes */
#define OPCODE_FAST_DUAL_READ 0x3bU /* Read data bytes */
#define OPCODE_FAST_QUAD_READ 0x6bU /* Read data bytes */
/* Used for SST flashes only. */
#define OPCODE_BP 0x02U /* Byte program */
#define OPCODE_WRDI 0x04U /* Write disable */
#define OPCODE_AAI_WP 0xadU /* Auto u32Address increment word program */
/* Used for Macronix flashes only. */
#define OPCODE_EN4B 0xb7U /* Enter 4-byte mode */
#define OPCODE_EX4B 0xe9U /* Exit 4-byte mode */
#define OPCODE_RDSCUR 0x2bU
#define OPCODE_WRSCUR 0x2fU
#define OPCODE_RSTEN 0x66U
#define OPCODE_RST 0x99U
#define OPCODE_ENQPI 0x38U
#define OPCODE_EXQPI 0xFFU
/* Status Register bits. */
#define SR_WIP 0x1U /* Write in progress */
#define SR_WEL 0x2U /* Write enable latch */
#define SR_QE 0x40U /* Quad Enable for MXIC */
/* Status Register #2 bits. */
#define SR2_QE 0x2U /* Quad Enable for Winbond */
/* meaning of other SR_* bits may differ between vendors */
#define SR_BP0 0x4U /* Block protect 0 */
#define SR_BP1 0x8U /* Block protect 1 */
#define SR_BP2 0x10U /* Block protect 2 */
#define SR_SRWD 0x80U /* SR write protect */
#define SR3_ADR 0x01U /* 4-byte u32Address mode */
#define SCUR_4BYTE 0x04U /* 4-byte u32Address mode */
//是否使能4字节地址模式
#define SPIM_SET_4BYTE_ADDR_EN(x) \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~(1<<5))) | (((x) ? 1UL : 0UL) << 5); \
} while (0)
//设置命令模式
#define SPIM_SET_SPIM_MODE(x) \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~(0xFF << 24))) | ((x&0xff) << 24); \
} while (0)
//设置空闲时间间隔
#define SPIM_SET_IDL_INTVL(x) \
do { \
SPIM->CTL1 = (SPIM->CTL1 & (~(0xF<<8))) | ((x&0XF) << 8); \
} while (0)
static void SPIM_IO_Init(void)
{
#if(SPIM_IO_SELECT == SPIM_IO_PA0_5)
SYS_GPIOx_SetAF(GPIO_PA0_SPIM_MOSI);
SYS_GPIOx_SetAF(GPIO_PA1_SPIM_MISO);
SYS_GPIOx_SetAF(GPIO_PA2_SPIM_CLK);
SYS_GPIOx_SetAF(GPIO_PA3_SPIM_SS);
SYS_GPIOx_SetAF(GPIO_PA4_SPIM_D3);
SYS_GPIOx_SetAF(GPIO_PA5_SPIM_D2);
#elif(SPIM_IO_SELECT==SPIM_IO_PC0_5)
SYS_GPIOx_SetAF(GPIO_PC0_SPIM_MOSI);
SYS_GPIOx_SetAF(GPIO_PC1_SPIM_MISO);
SYS_GPIOx_SetAF(GPIO_PC2_SPIM_CLK);
SYS_GPIOx_SetAF(GPIO_PC3_SPIM_SS);
SYS_GPIOx_SetAF(GPIO_PC4_SPIM_D3);
SYS_GPIOx_SetAF(GPIO_PC5_SPIM_D2);
#elif(SPIM_IO_SELECT==SPIM_IO_PE2_7)
SYS_GPIOx_SetAF(GPIO_PE2_SPIM_MOSI);
SYS_GPIOx_SetAF(GPIO_PE3_SPIM_MISO);
SYS_GPIOx_SetAF(GPIO_PE4_SPIM_CLK);
SYS_GPIOx_SetAF(GPIO_PE5_SPIM_SS);
SYS_GPIOx_SetAF(GPIO_PE6_SPIM_D3);
SYS_GPIOx_SetAF(GPIO_PE7_SPIM_D2);
#elif(SPIM_IO_SELECT==SPIM_IO_PG9_14)
SYS_GPIOx_SetAF(GPIO_PG9_SPIM_D2);
SYS_GPIOx_SetAF(GPIO_PG10_SPIM_D3);
SYS_GPIOx_SetAF(GPIO_PG11_SPIM_SS);
SYS_GPIOx_SetAF(GPIO_PG12_SPIM_CLK);
SYS_GPIOx_SetAF(GPIO_PG13_SPIM_MISO);
SYS_GPIOx_SetAF(GPIO_PG14_SPIM_MOSI);
#endif //SPIM_IO_SELECT
}
/* Used for Macronix flashes only. */
#define SPIM_OPCODE_EN4B 0xb7U /* Enter 4-byte mode */
#define SPIM_OPCODE_EX4B 0xe9U /* Exit 4-byte mode */
#define SPIM_OPCODE_RDSCUR 0x2bU
#define SPIM_OPCODE_WRSCUR 0x2fU
#define SPIM_OPCODE_RSTEN 0x66U
#define SPIM_OPCODE_RST 0x99U
#define SPIM_OPCODE_ENQPI 0x38U
#define SPIM_OPCODE_EXQPI 0xFFU
void SPIM_SET_SS(u8 level) {(!level)?(SPIM->CTL1&=~BIT4):(SPIM->CTL1|=BIT4);} //SS状态设置,低电平有效
void SPIM_OUT_EN(bool isOut) {isOut?(SPIM->CTL0 |= BIT15): (SPIM->CTL0 &= ~BIT15);} //输出使能,否则为输入
|