找回密码
 立即注册
首页 业界区 安全 使用QSPI驱动PM004MNIA

使用QSPI驱动PM004MNIA

琴丁辰 21 小时前
概述

STT-MRAM PM004MNIA 是一种具有 随机存取(Random Access) 特性的非易失性存储器,无需擦除操作,可进行 任意地址的读写操作。它的核心基于 自旋转移扭矩(Spin Transfer Torque, STT) 技术,通过控制电流方向来改变磁性存储单元的状态,从而实现数据的存储与读取。支持写无延迟(Write No Delay) 的特性,显著提高了存储效率。 广泛应用于需要 高速读写、低功耗和长期数据保存 的场景,例如 IoT 设备、工业控制模块、可穿戴设备、传感器系统 等。
特性描述存储容量4Mbit存储技术自旋转移扭矩磁随机存取存储器(STT-MRAM)随机存取能力支持任意地址的读写操作,无需擦除,写入延迟低接口支持SPI 和 QPI(四线并行)最大 SPI 频率50MHz低功耗Sleep 模式下仅需 2μA数据保留时间可达 20 年(在 85°C 环境下)写入耐久性支持高达 10⁸ 次 P/E 周期写保护功能支持配置写保护区域,确保数据安全附录-使用STM32H750驱动程序

1、外设初始化文件


  • quadspi.c文件
  1. #include "quadspi.h"
  2. QSPI_HandleTypeDef hqspi;
  3. /**
  4. * @brief     quad spi 外设初始化函数
  5. * @param     无
  6. * @retval    无
  7. */
  8. void QUADSPI_Init(void)
  9. {
  10.         hqspi.Instance = QUADSPI;
  11.         hqspi.Init.ClockPrescaler = 5;                                                                        /* QSPI时钟预分频器(决定实际通信时钟频率) */
  12.         hqspi.Init.FifoThreshold = 32;                                                                        /* FIFO阈值(单位:字节),当FIFO中的数据量达到该值时触发中断/DMA请求 */
  13.         /* 采样移位模式:
  14.      * HALFCYCLE:在时钟半周期时采样(提高时序余量)
  15.      * NONE:不在半周期采样 */
  16.         hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
  17.         hqspi.Init.FlashSize = 23 - 1;                                                                        /* FLASH内存大小 = 2 ^ (FlashSize + 1) */
  18.        
  19.         /* 片选高电平时间:
  20.      * 表示两次传输之间CS保持高电平的最小时钟周期数 */
  21.         hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
  22.             /* 时钟模式:
  23.      * MODE_0:CLK空闲低电平,第1边沿(上升沿)采样
  24.      * MODE_3:CLK空闲高电平,第2边沿(下降沿)采样
  25.      * 需与Flash芯片规格书一致 */
  26.         hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
  27.         /* Flash芯片选择:
  28.      * ID_1:使用Bank1(对应BK1_IOx引脚)
  29.      * ID_2:使用Bank2(仅双Flash模式) */
  30.         hqspi.Init.FlashID = QSPI_FLASH_ID_1;
  31.         /* 双Flash模式:
  32.      * DISABLE:单Flash模式
  33.      * ENABLE:并联两个Flash(地址空间翻倍) */
  34.         hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
  35.         if (HAL_QSPI_Init(&hqspi) != HAL_OK)
  36.         {
  37.                 Error_Handler();
  38.         }
  39. }
  40. /**
  41. * @brief     quad spi 外设初始化回调函数
  42. * @param     qspiHandle:QSPI句柄
  43. * @retval    无
  44. */
  45. void HAL_QSPI_MspInit(QSPI_HandleTypeDef* qspiHandle)
  46. {
  47.         GPIO_InitTypeDef GPIO_InitStruct = {0};
  48.         RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  49.         if(qspiHandle->Instance==QUADSPI)
  50.         {
  51.         /** Initializes the peripherals clock
  52.          */
  53.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_QSPI;
  54.                 PeriphClkInitStruct.QspiClockSelection = RCC_QSPICLKSOURCE_D1HCLK;
  55.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  56.                 {
  57.                         Error_Handler();
  58.                 }
  59.                 /* QUADSPI clock enable */
  60.                 __HAL_RCC_QSPI_CLK_ENABLE();
  61.                 __HAL_RCC_GPIOB_CLK_ENABLE();
  62.                 __HAL_RCC_GPIOF_CLK_ENABLE();
  63.         
  64.                 /**QUADSPI GPIO Configuration
  65.                 PB6     ------> QUADSPI_BK1_NCS
  66.                 PF6     ------> QUADSPI_BK1_IO3
  67.                 PF7     ------> QUADSPI_BK1_IO2
  68.                 PF8     ------> QUADSPI_BK1_IO0
  69.                 PF10     ------> QUADSPI_CLK
  70.                 PF9     ------> QUADSPI_BK1_IO1
  71.                 */
  72.                 GPIO_InitStruct.Pin = GPIO_PIN_6;
  73.                 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  74.                 GPIO_InitStruct.Pull = GPIO_NOPULL;
  75.                 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  76.                 GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
  77.                 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  78.                 GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10;
  79.                 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  80.                 GPIO_InitStruct.Pull = GPIO_NOPULL;
  81.                 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  82.                 GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
  83.                 HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
  84.                 GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
  85.                 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  86.                 GPIO_InitStruct.Pull = GPIO_NOPULL;
  87.                 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  88.                 GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
  89.                 HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
  90.         }
  91. }
  92. /**
  93. * @brief     quad spi 外设重初始化回调函数
  94. * @param     qspiHandle:QSPI句柄
  95. * @retval    无
  96. */
  97. void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* qspiHandle)
  98. {
  99.         if(qspiHandle->Instance==QUADSPI)
  100.         {
  101.                 /* Peripheral clock disable */
  102.                 __HAL_RCC_QSPI_CLK_DISABLE();
  103.                 /**QUADSPI GPIO Configuration
  104.                 PB6     ------> QUADSPI_BK1_NCS
  105.                 PF6     ------> QUADSPI_BK1_IO3
  106.                 PF7     ------> QUADSPI_BK1_IO2
  107.                 PF8     ------> QUADSPI_BK1_IO0
  108.                 PF10     ------> QUADSPI_CLK
  109.                 PF9     ------> QUADSPI_BK1_IO1
  110.                 */
  111.                 HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6);
  112.                 HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_10
  113.                                                         |GPIO_PIN_9);
  114.         }
  115. }
复制代码

  • quadspi.h文件
  1. #ifndef __QUADSPI_H__
  2. #define __QUADSPI_H__
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #include "main.h"
  7. #include "string.h"
  8. extern QSPI_HandleTypeDef hqspi;
  9. void QUADSPI_Init(void);
  10. #ifdef __cplusplus
  11. }
  12. #endif
  13. #endif /* __QUADSPI_H__ */
复制代码
2、驱动文件


  • bsp_pm004mniatr.c文件
[code]#include "bsp_pm004mniatr.h"#include "quadspi.h"/** * @brief   读NOR Flash的状态寄存器 * @param   addr: 状态寄存器地址(寄存器1、2、3 对应地址为 0x00、0x01、0x02) * @retval  状态寄存器的值 */uint8_t pm004mniatr_read_sr(uint8_t addr){    uint8_t byte;    QSPI_CommandTypeDef qspi_command_struct = {0};    qspi_command_struct.InstructionMode = QSPI_INSTRUCTION_1_LINE;    qspi_command_struct.Instruction = PM004MNIATR_COMMAND_READ_MODE_REGISTER;    qspi_command_struct.AddressMode = QSPI_ADDRESS_1_LINE;        qspi_command_struct.AddressSize = QSPI_ADDRESS_24_BITS;        qspi_command_struct.Address = addr;    qspi_command_struct.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;    qspi_command_struct.DummyCycles = 2;    qspi_command_struct.DataMode = QSPI_DATA_1_LINE;    qspi_command_struct.NbData = 1;    qspi_command_struct.DdrMode = QSPI_DDR_MODE_DISABLE;    qspi_command_struct.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;    qspi_command_struct.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;    HAL_QSPI_Command(&hqspi, &qspi_command_struct, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);        HAL_QSPI_Receive(&hqspi, &byte, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);        return byte;}/** * @brief   写NOR Flash的状态寄存器 * @param   addr: 状态寄存器地址(寄存器1、2、3 对应地址为 0x00、0x01、0x02) * @param   byte:寄存器写入值 * @retval  无 */void pm004mniatr_write_sr(uint8_t addr, uint8_t byte){    QSPI_CommandTypeDef qspi_command_struct = {0};        qspi_command_struct.InstructionMode = QSPI_INSTRUCTION_1_LINE;    qspi_command_struct.Instruction = PM004MNIATR_COMMAND_WRITE_MODE_REGISTER;    qspi_command_struct.AddressMode = QSPI_ADDRESS_1_LINE;        qspi_command_struct.AddressSize = QSPI_ADDRESS_24_BITS;        qspi_command_struct.Address = addr;    qspi_command_struct.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;    qspi_command_struct.DummyCycles = 0;    qspi_command_struct.DataMode = QSPI_DATA_1_LINE;    qspi_command_struct.NbData = 1;    qspi_command_struct.DdrMode = QSPI_DDR_MODE_DISABLE;    qspi_command_struct.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;    qspi_command_struct.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;    HAL_QSPI_Command(&hqspi, &qspi_command_struct, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);        HAL_QSPI_Transmit(&hqspi, &byte, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);}/** * @brief   发送快速指令 * @param   无 * @retval  无 */void pm004mniatr_send_command(uint8_t command){        QSPI_CommandTypeDef qspi_command_struct = {0};                qspi_command_struct.InstructionMode = QSPI_INSTRUCTION_1_LINE;                  /* 设置指令模式:使用1线传输模式 */        qspi_command_struct.Instruction = command;                                      /* 设置指令代码 */        qspi_command_struct.AddressMode = QSPI_ADDRESS_NONE;                            /* 地址模式:不使用地址 */        qspi_command_struct.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;              /* 备用字节模式:不使用 */        qspi_command_struct.DummyCycles = 0;                                            /* 空周期数:0 */         qspi_command_struct.DataMode = QSPI_DATA_NONE;                                  /* 数据模式:不使用数据传输 */         qspi_command_struct.DdrMode = QSPI_DDR_MODE_DISABLE;                            /* DDR模式:禁用双倍数据率模式 */        qspi_command_struct.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;               /* DDR半周期保持:使用模拟延迟 */        qspi_command_struct.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;                        /* SIOO模式:每次发送指令 */            HAL_QSPI_Command(&hqspi, &qspi_command_struct, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);}/** * @brief   启用quad spi 操作模式 * @param   无 * @retval  无 */static inline void pm004mniatr_qspi_mode_enable(void){    pm004mniatr_send_command(PM004MNIATR_COMMAND_ENTER_QSPI);}/** * @brief   退出quad spi 操作模式 * @param   无 * @retval  无 */void inline pm004mniatr_qspi_mode_disable(void){    pm004mniatr_send_command(PM004MNIATR_COMMAND_EXIT_QSPI);}/** * @brief   写使能NOR Flash * @param   无 * @retval  无 */static inline void pm004mniatr_write_enable(void){    pm004mniatr_send_command(PM004MNIATR_COMMAND_WRITE_ENABLE);}/** * @brief   进入睡眠模式 * @param   无 * @retval  无 */static inline void pm004mniatr_sleep(void){    pm004mniatr_send_command(PM004MNIATR_COMMAND_ENTRY_SLEEP);}/** * @brief   唤醒PM004MNIA * @param   无 * @retval  无 */static inline void pm004mniatr_wake_up(void){    pm004mniatr_send_command(PM004MNIATR_COMMAND_EXIT_SLEEP);}/** * @brief   复位PM004MNIA * @param   无 * @retval  无 */static inline void pm004mniatr_reset(void){    pm004mniatr_send_command(PM004MNIATR_COMMAND_RESE_ENABLE);    pm004mniatr_send_command(PM004MNIATR_COMMAND_RESET);}/** * @brief   初始化 PM004MNIA * @param   无 * @retval  无 */void pm004mniatr_init(void){        /* 初始化quad spi外设 */    QUADSPI_Init();        /* ------------------安全启动 --------------------*/    delay_ms(20);    /* 复位PM004MNIA */    pm004mniatr_reset();    delay_ms(10);    /* 进入睡眠状态 */    pm004mniatr_sleep();    delay_ms(10);    /* 唤醒 */    pm004mniatr_wake_up();    delay_ms(10);    /* ----------------安全启动 END -----------------*/            /* 启动写使能 */        pm004mniatr_write_enable();        /* 进入qspi操作模式 */        pm004mniatr_qspi_mode_enable();}/** * @brief   读PM004MNIA芯片ID * @param   无 * @retval  PM004MNIA芯片ID */uint16_t pm004mniatr_read_id(void){    uint8_t id[16];    QSPI_CommandTypeDef qspi_command_struct = {0};        qspi_command_struct.InstructionMode = QSPI_INSTRUCTION_1_LINE;              /* 1线指令模式 */    qspi_command_struct.Instruction = PM004MNIATR_COMMAND_READ_ID;                /* 读取指令 */    qspi_command_struct.AddressMode = QSPI_ADDRESS_1_LINE;                      /* 无地址模式 */    qspi_command_struct.AddressSize = QSPI_ADDRESS_24_BITS;                     /* 24位地址 */    qspi_command_struct.Address = 0x000000;                                     /* 地址 */    qspi_command_struct.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;          /* 无交替字节 */    qspi_command_struct.DummyCycles = 0;                                        /* 空白周期个数 */    qspi_command_struct.DataMode = QSPI_DATA_1_LINE;                            /* 1线数据模式 */    qspi_command_struct.NbData = 2;    qspi_command_struct.DdrMode = QSPI_DDR_MODE_DISABLE;    qspi_command_struct.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;    qspi_command_struct.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;    HAL_QSPI_Command(&hqspi, &qspi_command_struct, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);        HAL_QSPI_Receive(&hqspi, id, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);        return (((uint16_t)id[0]

相关推荐

您需要登录后才可以回帖 登录 | 立即注册