• ZYNQ7010的PS编程笔记


    1.定时器中断

    api

    XScuTimer Timer;                                     //定时器驱动

    XScuTimer_Config *timer_cfg_ptr;         //定时器的配置

    XScuTimer_LookupConfig(XPAR_XSCUTIMER_0_DEVICE_ID);  //定时器查找表

     XScuTimer_CfgInitialize(timer_ptr, timer_cfg_ptr, timer_cfg_ptr->BaseAddr); //定时器初始化

     XScuTimer_LoadTimer(timer_ptr, TIMER_LOAD_VALUE); //加载计数周期,频率为CPU时钟频率(666MHz)一半大小
     XScuTimer_EnableAutoReload(timer_ptr); //设置自动装载模式,从而循环来产生定时器

    XScuTimer_EnableInterrupt(timer_ptr);  //使能定时器中断

     XScuTimer_Start(&Timer);  //启动定时器

     XScuTimer_ClearInterruptStatus(timer_ptr);  //清除定时器中断标志

    中断处理函数

    1. //初始化中断控制器
    2. XScuGic_Config *intc_cfg_ptr;
    3. intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID);
    4. XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr, intc_cfg_ptr->CpuBaseAddress);
    5. //设置并打开中断异常功能
    6. Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr);
    7. Xil_ExceptionEnable();
    8. //设置定时器中断,TIMER_IRPT_INTR是定时器中断ID
    9. XScuGic_Connect(intc_ptr, TIMER_IRPT_INTR, (Xil_ExceptionHandler)timer_intr_handler,(void*)timer_ptr);
    10. XScuGic_Enable(intc_ptr, TIMER_IRPT_INTR); //使能GIC中的定时器中断
    11. XScuTimer_EnableInterrupt(timer_ptr); //使能定时器中断

     下面是全部代码,实现了一个每200ms的PS的LED灯闪烁一次的效果。

    1. #include "xparameters.h"
    2. #include "xscutimer.h"
    3. #include "xscugic.h"
    4. #include "xgpiops.h"
    5. #include "xil_exception.h"
    6. #include "xil_printf.h"
    7. #define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID //定时器ID
    8. #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中断ID
    9. #define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR //定时器中断ID
    10. #define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID //宏定义GPIO_PS ID
    11. #define MIO_LED 0 //led连接到MIO0
    12. //私有定时器的时钟频率 = CPU时钟频率/2 = 333MHz
    13. // 0.2s闪烁一次,0.2/1000_000_00/(1000/333) - 1 = 3F83C3F
    14. #define TIMER_LOAD_VALUE 0x3F83C3F //定时器装载数值
    15. XScuGic Intc; //中断控制器驱动程序实例
    16. XScuTimer Timer; //定时器驱动程序实例
    17. XGpioPs Gpio; //GPIO设备的驱动程序实例
    18. //MIO引脚初始化
    19. int mio_init(XGpioPs *mio_ptr)
    20. {
    21. int status;
    22. XGpioPs_Config *mio_cfg_ptr;
    23. mio_cfg_ptr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    24. if (mio_cfg_ptr == NULL)
    25. return XST_FAILURE;
    26. status = XGpioPs_CfgInitialize(mio_ptr, mio_cfg_ptr, mio_cfg_ptr->BaseAddr);
    27. if (status != XST_SUCCESS)
    28. return XST_FAILURE;
    29. //设置指定引脚的方向 0是输入,1是输出
    30. XGpioPs_SetDirectionPin(&Gpio,MIO_LED, 1);
    31. //使能指定引脚输出,0 禁止输出使能 1使能输出
    32. XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED, 1);
    33. return XST_SUCCESS;
    34. }
    35. //定时器初始化程序
    36. int timer_init(XScuTimer *timer_ptr)
    37. {
    38. int status;
    39. //私有定时器初始化
    40. XScuTimer_Config *timer_cfg_ptr;
    41. timer_cfg_ptr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
    42. if (NULL == timer_cfg_ptr)
    43. {
    44. return XST_FAILURE;
    45. }
    46. status = XScuTimer_CfgInitialize(timer_ptr, timer_cfg_ptr, timer_cfg_ptr->BaseAddr);\
    47. if(status != XST_SUCCESS)
    48. return XST_FAILURE;
    49. XScuTimer_LoadTimer(timer_ptr, TIMER_LOAD_VALUE); //加载计数周期
    50. XScuTimer_EnableAutoReload(timer_ptr); //设置自动装载模式,从而循环来产生定时器
    51. return XST_SUCCESS;
    52. }
    53. //定时器中断处理函数
    54. void timer_intr_handler(void *CallBackRef)
    55. {
    56. //LED 状态,用于控制LED灯状态翻转
    57. static int led_state = 0;
    58. XScuTimer* timer_ptr = (XScuTimer *)CallBackRef;
    59. if(led_state == 0)
    60. led_state = 1;
    61. else
    62. led_state = 0;
    63. //向指定引脚写入数据:0 或者1
    64. XGpioPs_WritePin(&Gpio, MIO_LED, led_state);
    65. //清除定时器中断标志
    66. XScuTimer_ClearInterruptStatus(timer_ptr);
    67. }
    68. //定时器中断初始化
    69. void timer_intr_init(XScuGic *intc_ptr, XScuTimer * timer_ptr)
    70. {
    71. //初始化中断控制器
    72. XScuGic_Config *intc_cfg_ptr;
    73. intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID);
    74. XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr, intc_cfg_ptr->CpuBaseAddress);
    75. //设置并打开中断异常功能
    76. Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr);
    77. Xil_ExceptionEnable();
    78. //设置定时器中断,TIMER_IRPT_INTR是定时器中断ID
    79. XScuGic_Connect(intc_ptr, TIMER_IRPT_INTR, (Xil_ExceptionHandler)timer_intr_handler,(void*)timer_ptr);
    80. XScuGic_Enable(intc_ptr, TIMER_IRPT_INTR); //使能GIC中的定时器中断
    81. XScuTimer_EnableInterrupt(timer_ptr); //使能定时器中断
    82. }
    83. int main()
    84. {
    85. int status;
    86. xil_printf("SCU Timer Interrupt Test \r\n");
    87. mio_init(&Gpio); //MIO引脚初始化
    88. status = timer_init(&Timer); //定时器初始化
    89. if (status != XST_SUCCESS) {
    90. xil_printf("Timer Initial Failed \r\n");
    91. return XST_FAILURE;
    92. }
    93. timer_intr_init(&Intc, &Timer); //定时器中断初始化
    94. XScuTimer_Start(&Timer); //启动定时器
    95. while(1);
    96. return 0;
    97. }

    2.PS的XADC

    ps的xadc可以读取板子上的实时电压以及温度

    api

    XAdcPs xadc_inst;   //XADC实例以及初始化

    ConfigPtr = XAdcPs_LookupConfig(XPAR_XADCPS_0_DEVICE_ID);

    XAdcPs_CfgInitialize(&xadc_inst, ConfigPtr, ConfigPtr->BaseAddrss);

    XAdcPs_SetSequencerMode(&xadc_inst, XADCPS_SEQ_MODE_SAFE); //设置为安全模式

    u32 temp_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_TEMP); //读取原始数据

    XAdcPs_RawToVoltage()  XAdcPs_RawToTemperature()  //原始数据转换为电压(v)以及温度(摄氏度)

     下面是全部代码,实现了一个循环5s读取一次XADC上面的电压以及温度信号

    1. #include "xparameters.h"
    2. #include "xadcps.h"
    3. #include "stdio.h"
    4. #include "xil_printf.h"
    5. #include "sleep.h"
    6. #define XADC_DEVICE_ID XPAR_XADCPS_0_DEVICE_ID //PS的XADC器件
    7. static XAdcPs xadc_inst;
    8. int main(void)
    9. {
    10. XAdcPs_Config *ConfigPtr; //XADC配置指针
    11. //原始数据
    12. u32 temp_rawdata; //温度
    13. u32 vcc_pint_rawdata; //ps内核电压
    14. u32 vcc_paux_rawdata; //ps辅助电压
    15. u32 vcc_pddr_rawdata; //ps的ddr电压
    16. u32 vcc_int_rawdata; //pl内核电压
    17. u32 vcc_aux_rawdata; //pl辅助电压
    18. u32 vcc_bram_rawdata; //pl的bram电压
    19. float temp; //温度
    20. float vcc_pint; //ps内核电压
    21. float vcc_paux; //ps辅助电压
    22. float vcc_pddr; //ps的ddr电压
    23. float vcc_int; //pl内核电压
    24. float vcc_aux; //pl辅助电压
    25. float vcc_bram; //pl的bram电压
    26. //初始化xadc驱动
    27. ConfigPtr = XAdcPs_LookupConfig(XADC_DEVICE_ID);
    28. XAdcPs_CfgInitialize(&xadc_inst, ConfigPtr, ConfigPtr->BaseAddrss);
    29. // 设置xadc操作模式为 默认安全模式
    30. // XADC 会自动监测片上温度和电压传感器的数据,并将结果保存在状态寄存器中,此时 XADC
    31. // 的操作与其他任何控制寄存器的设置无关
    32. XAdcPs_SetSequencerMode(&xadc_inst, XADCPS_SEQ_MODE_SAFE);
    33. while(1) {
    34. //获取原始温度传感器数据
    35. temp_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_TEMP);
    36. //转换成温度信息
    37. temp = XAdcPs_RawToTemperature(temp_rawdata);
    38. //获取VCCPINT传感器数据
    39. vcc_pint_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCPINT);
    40. vcc_pint = XAdcPs_RawToVoltage(vcc_pint_rawdata);
    41. //获取VCCPAUX传感器数据
    42. vcc_paux_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCPAUX);
    43. vcc_paux = XAdcPs_RawToVoltage(vcc_paux_rawdata);
    44. //获取VCCPDRO传感器数据
    45. vcc_pddr_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCPDRO);
    46. vcc_pddr = XAdcPs_RawToVoltage(vcc_pddr_rawdata);
    47. //获取VCCINT传感器数据
    48. vcc_int_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCINT);
    49. vcc_int = XAdcPs_RawToVoltage(vcc_int_rawdata);
    50. //获取VCCPAUX传感器数据
    51. vcc_aux_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VCCAUX);
    52. vcc_aux = XAdcPs_RawToVoltage(vcc_aux_rawdata);
    53. //获取VCCPDRO传感器数据
    54. vcc_bram_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VBRAM);
    55. vcc_bram = XAdcPs_RawToVoltage(vcc_bram_rawdata);
    56. //打印温度、电压信息
    57. printf("Raw Temp %lu, Real Temp %fC \n", temp_rawdata, temp);
    58. printf("Raw VccPInt %lu, Real VccPInt %fV \n", vcc_pint_rawdata, vcc_pint);
    59. printf("Raw VccPAux %lu, Real VccPAux %fV \n", vcc_paux_rawdata, vcc_paux);
    60. printf("Raw VccPDDR %lu, Real VccPDDR %fV \n", vcc_pddr_rawdata, vcc_pddr);
    61. printf("Raw VccInt %lu, Real VccInt %fV \n", vcc_int_rawdata, vcc_int);
    62. printf("Raw VccAux %lu, Real VccAux %fV \n", vcc_aux_rawdata, vcc_aux);
    63. printf("Raw VccBram %lu, Real VccBram %fV \n\r", vcc_bram_rawdata, vcc_bram);
    64. //延时 5s
    65. sleep(5);
    66. }
    67. }

    下面实现了使用XADC读取外界输入的模拟信号转换成的数字信号

    1. // XADC 模块也集成了模数转换器,可以将外部输入的模拟电压转换成数字
    2. // 信号,实现通过 PS XADC 接口,读取外部模拟电压信号
    3. // XADC 内部的两块 ADC 分别为 ADC A 与 ADC B, ADC A 是可以接收左侧包括所有片上
    4. // 传感器(温度温度传感器信息、电源传感器信息)、 VP/VN 模拟电压信息以及 16 路辅助模拟输入的;而
    5. // ADC B 只能接收 VP/VN 模拟电压信息以及 16 路辅助模拟输入。 VP/VN 与 16 路辅助模拟输入的不同在于
    6. // VP/VN 是专用的支持差分输入的模拟通道输入引脚,而 16 路辅助模拟输入是模拟数字/数字复用引脚,其
    7. // 中某个引脚用作模拟输入,该引脚的数字 IO 功能就不可以再使用
    8. // VP/VN单端输入时候电压范围为0-1.0v, 如果是双端输入时电压范围则是-0.5v-0.5v的范围内
    9. #include "xparameters.h"
    10. #include "xadcps.h"
    11. #include "stdio.h"
    12. #include "xil_printf.h"
    13. #include "sleep.h"
    14. #define XADC_DEVICE_ID XPAR_XADCPS_0_DEVICE_ID //PS的XADC器件
    15. static XAdcPs xadc_inst;
    16. int main(void)
    17. {
    18. XAdcPs_Config *ConfigPtr; //XADC配置指针
    19. //原始数据
    20. u32 vcc_vpvn_rawdata; //VpVn原始数据
    21. float vcc_vpvn; //vpvn电压
    22. //初始化xadc驱动
    23. ConfigPtr = XAdcPs_LookupConfig(XADC_DEVICE_ID);
    24. XAdcPs_CfgInitialize(&xadc_inst, ConfigPtr, ConfigPtr->BaseAddress);
    25. // 设置xadc操作模式为 默认安全模式
    26. // XADC 会自动监测片上温度和电压传感器的数据,并将结果保存在状态寄存器中,此时 XADC
    27. // 的操作与其他任何控制寄存器的设置无关
    28. XAdcPs_SetSequencerMode(&xadc_inst, XADCPS_SEQ_MODE_SAFE);
    29. // 使能相应的通道
    30. XAdcPs_SetSeqChEnables(&xadc_inst, XADCPS_SEQ_CH_VPVN);
    31. //设置为循环模式
    32. XAdcPs_SetSequencerMode(&xadc_inst, XADCPS_SEQ_MODE_CONTINPASS);
    33. while(1) {
    34. //获取原始温度传感器数据
    35. vcc_vpvn_rawdata = XAdcPs_GetAdcData(&xadc_inst, XADCPS_CH_VPVN);
    36. //转换成温度信息
    37. vcc_vpvn = XAdcPs_RawToVoltage(vcc_vpvn_rawdata)/3;
    38. //打印温度、电压信息
    39. printf("Raw vpvn %lu, Real vpvn %fv \n", vcc_vpvn_rawdata, vcc_vpvn);
    40. //延时 1s
    41. sleep(1);
    42. }
    43. }

    3.PS的QSPI

    下面实现了QSPI的读写测试

    1. #include "xparameters.h"
    2. #include "xqspips.h"
    3. #include "xil_printf.h"
    4. /************************** Constant Definitions *****************************/
    5. /*
    6. * The following constants map to the XPAR parameters created in the
    7. * xparameters.h file. They are defined here such that a user can easily
    8. * change all the needed parameters in one place.
    9. */
    10. #define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
    11. /*
    12. * The following constants define the commands which may be sent to the FLASH
    13. * device.
    14. */
    15. #define WRITE_STATUS_CMD 0x01
    16. #define WRITE_CMD 0x02
    17. #define READ_CMD 0x03
    18. #define WRITE_DISABLE_CMD 0x04
    19. #define READ_STATUS_CMD 0x05
    20. #define WRITE_ENABLE_CMD 0x06
    21. #define FAST_READ_CMD 0x0B
    22. #define DUAL_READ_CMD 0x3B
    23. #define QUAD_READ_CMD 0x6B
    24. #define BULK_ERASE_CMD 0xC7
    25. #define SEC_ERASE_CMD 0xD8
    26. #define READ_ID 0x9F
    27. /*
    28. * The following constants define the offsets within a FlashBuffer data
    29. * type for each kind of data. Note that the read data offset is not the
    30. * same as the write data because the QSPI driver is designed to allow full
    31. * duplex transfers such that the number of bytes received is the number
    32. * sent and received.
    33. */
    34. #define COMMAND_OFFSET 0 /* FLASH instruction */
    35. #define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */
    36. #define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */
    37. #define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */
    38. #define DATA_OFFSET 4 /* Start of Data for Read/Write */
    39. #define DUMMY_OFFSET 4 /* Dummy byte offset for fast, dual and quad \
    40. * reads \
    41. */
    42. #define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and \
    43. * quad reads \
    44. */
    45. #define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */
    46. #define BULK_ERASE_SIZE 1 /* Bulk Erase command size */
    47. #define SEC_ERASE_SIZE 4 /* Sector Erase command + Sector address */
    48. /*
    49. * The following constants specify the extra bytes which are sent to the
    50. * FLASH on the QSPI interface, that are not data, but control information
    51. * which includes the command and address
    52. */
    53. #define OVERHEAD_SIZE 4
    54. /*
    55. * The following constants specify the page size, sector size, and number of
    56. * pages and sectors for the FLASH. The page size specifies a max number of
    57. * bytes that can be written to the FLASH with a single transfer.
    58. */
    59. #define SECTOR_SIZE 0x10000
    60. #define NUM_SECTORS 0x100
    61. #define NUM_PAGES 0x10000
    62. #define PAGE_SIZE 256
    63. /* Number of flash pages to be written.*/
    64. #define PAGE_COUNT 16
    65. /* Flash address to which data is ot be written.*/
    66. #define TEST_ADDRESS 0x00055000
    67. #define UNIQUE_VALUE 0x05
    68. /*
    69. * The following constants specify the max amount of data and the size of the
    70. * the buffer required to hold the data and overhead to transfer the data to
    71. * and from the FLASH.
    72. */
    73. #define MAX_DATA (PAGE_COUNT * PAGE_SIZE)
    74. /**************************** Type Definitions *******************************/
    75. /***************** Macros (Inline Functions) Definitions *********************/
    76. /************************** Function Prototypes ******************************/
    77. void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount);
    78. void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
    79. void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
    80. int FlashReadID(void);
    81. void FlashQuadEnable(XQspiPs *QspiPtr);
    82. int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId);
    83. /************************** Variable Definitions *****************************/
    84. /*
    85. * The instances to support the device drivers are global such that they
    86. * are initialized to zero each time the program runs. They could be local
    87. * but should at least be static so they are zeroed.
    88. */
    89. static XQspiPs QspiInstance;
    90. /*
    91. * The following variable allows a test value to be added to the values that
    92. * are written to the FLASH such that unique values can be generated to
    93. * guarantee the writes to the FLASH were successful
    94. */
    95. int Test = 5;
    96. /*
    97. * The following variables are used to read and write to the flash and they
    98. * are global to avoid having large buffers on the stack
    99. */
    100. u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
    101. u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
    102. /*****************************************************************************/
    103. /**
    104. *
    105. * Main function to call the QSPI Flash example.
    106. *
    107. * @param None
    108. *
    109. * @return XST_SUCCESS if successful, otherwise XST_FAILURE.
    110. *
    111. * @note None
    112. *
    113. ******************************************************************************/
    114. int main(void)
    115. {
    116. int Status;
    117. xil_printf("QSPI FLASH Polled Example Test \r\n");
    118. /* Run the Qspi Interrupt example.*/
    119. Status = QspiFlashPolledExample(&QspiInstance, QSPI_DEVICE_ID);
    120. if (Status != XST_SUCCESS)
    121. {
    122. xil_printf("QSPI FLASH Polled Example Test Failed\r\n");
    123. return XST_FAILURE;
    124. }
    125. xil_printf("Successfully ran QSPI FLASH Polled Example Test\r\n");
    126. return XST_SUCCESS;
    127. }
    128. /*****************************************************************************/
    129. /**
    130. *
    131. * The purpose of this function is to illustrate how to use the XQspiPs
    132. * device driver in polled mode. This function writes and reads data
    133. * from a serial FLASH.
    134. *
    135. * @param None.
    136. *
    137. * @return XST_SUCCESS if successful, else XST_FAILURE.
    138. *
    139. * @note None.
    140. *
    141. *****************************************************************************/
    142. int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId)
    143. {
    144. int Status;
    145. u8 *BufferPtr;
    146. u8 UniqueValue;
    147. int Count;
    148. int Page;
    149. XQspiPs_Config *QspiConfig;
    150. //初始化 QSPI 驱动
    151. QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
    152. XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig, QspiConfig->BaseAddress);
    153. //初始化读写 BUFFER
    154. for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
    155. Count++, UniqueValue++)
    156. {
    157. WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue + Test);
    158. /* WriteBuffer[4] = (5+5) = 10
    159. WriteBuffer[5] = (6+5) = 11
    160. WriteBuffer[6] = (7+5) = 12
    161. WriteBuffer[7] = (8+5) = 13
    162. ......
    163. WriteBuffer[259] = (260+5) = 265
    164. */
    165. }
    166. memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
    167. //设置手动启动和手动片选模式
    168. XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_MANUAL_START_OPTION |
    169. XQSPIPS_FORCE_SSELECT_OPTION |
    170. XQSPIPS_HOLD_B_DRIVE_OPTION);
    171. //设置 QSPI 时钟的分频系数
    172. XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);
    173. //片选信号置为有效
    174. XQspiPs_SetSlaveSelect(QspiInstancePtr);
    175. //读 Flash ID
    176. FlashReadID();
    177. //使能 Flash Quad 模式
    178. FlashQuadEnable(QspiInstancePtr);
    179. //擦除 Flash
    180. FlashErase(QspiInstancePtr, TEST_ADDRESS, MAX_DATA);
    181. //向 Flash 中写入数据
    182. for (Page = 0; Page < PAGE_COUNT; Page++)
    183. {
    184. FlashWrite(QspiInstancePtr, (Page * PAGE_SIZE) + TEST_ADDRESS,
    185. PAGE_SIZE, WRITE_CMD);
    186. }
    187. //使用 QUAD 模式从 Flash 中读出数据
    188. FlashRead(QspiInstancePtr, TEST_ADDRESS, MAX_DATA, QUAD_READ_CMD);
    189. //对比写入 Flash 与从 Flash 中读出的数据
    190. BufferPtr = &ReadBuffer[DATA_OFFSET + DUMMY_SIZE];
    191. for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
    192. Count++, UniqueValue++)
    193. {
    194. if (BufferPtr[Count] != (u8)(UniqueValue + Test))
    195. {
    196. return XST_FAILURE;
    197. }
    198. }
    199. return XST_SUCCESS;
    200. }
    201. /*****************************************************************************/
    202. /**
    203. *
    204. * This function writes to the serial FLASH connected to the QSPI interface.
    205. * All the data put into the buffer must be in the same page of the device with
    206. * page boundaries being on 256 byte boundaries.
    207. *
    208. * @param QspiPtr is a pointer to the QSPI driver component to use.
    209. * @param Address contains the address to write data to in the FLASH.
    210. * @param ByteCount contains the number of bytes to write.
    211. * @param Command is the command used to write data to the flash. QSPI
    212. * device supports only Page Program command to write data to the
    213. * flash.
    214. *
    215. * @return None.
    216. *
    217. * @note None.
    218. *
    219. ******************************************************************************/
    220. void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
    221. {
    222. u8 WriteEnableCmd = {WRITE_ENABLE_CMD};
    223. u8 ReadStatusCmd[] = {READ_STATUS_CMD, 0}; /* must send 2 bytes */
    224. u8 FlashStatus[2];
    225. /*
    226. * Send the write enable command to the FLASH so that it can be
    227. * written to, this needs to be sent as a separate transfer before
    228. * the write
    229. */
    230. XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
    231. sizeof(WriteEnableCmd));
    232. /*
    233. * Setup the write command with the specified address and data for the
    234. * FLASH
    235. */
    236. WriteBuffer[COMMAND_OFFSET] = Command;
    237. WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
    238. WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
    239. WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
    240. /*
    241. * Send the write command, address, and data to the FLASH to be
    242. * written, no receive buffer is specified since there is nothing to
    243. * receive
    244. */
    245. XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
    246. ByteCount + OVERHEAD_SIZE);
    247. /*
    248. * Wait for the write command to the FLASH to be completed, it takes
    249. * some time for the data to be written
    250. */
    251. while (1)
    252. {
    253. /*
    254. * Poll the status register of the FLASH to determine when it
    255. * completes, by sending a read status command and receiving the
    256. * status byte
    257. */
    258. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
    259. sizeof(ReadStatusCmd));
    260. /*
    261. * If the status indicates the write is done, then stop waiting,
    262. * if a value of 0xFF in the status byte is read from the
    263. * device and this loop never exits, the device slave select is
    264. * possibly incorrect such that the device status is not being
    265. * read
    266. */
    267. FlashStatus[1] |= FlashStatus[0];
    268. if ((FlashStatus[1] & 0x01) == 0)
    269. {
    270. break;
    271. }
    272. }
    273. }
    274. /*****************************************************************************/
    275. /**
    276. *
    277. * This function reads from the serial FLASH connected to the
    278. * QSPI interface.
    279. *
    280. * @param QspiPtr is a pointer to the QSPI driver component to use.
    281. * @param Address contains the address to read data from in the FLASH.
    282. * @param ByteCount contains the number of bytes to read.
    283. * @param Command is the command used to read data from the flash. QSPI
    284. * device supports one of the Read, Fast Read, Dual Read and Fast
    285. * Read commands to read data from the flash.
    286. *
    287. * @return None.
    288. *
    289. * @note None.
    290. *
    291. ******************************************************************************/
    292. void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
    293. {
    294. /*
    295. * Setup the write command with the specified address and data for the
    296. * FLASH
    297. */
    298. WriteBuffer[COMMAND_OFFSET] = Command;
    299. WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
    300. WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
    301. WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
    302. if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
    303. (Command == QUAD_READ_CMD))
    304. {
    305. ByteCount += DUMMY_SIZE;
    306. }
    307. /*
    308. * Send the read command to the FLASH to read the specified number
    309. * of bytes from the FLASH, send the read command and address and
    310. * receive the specified number of bytes of data in the data buffer
    311. */
    312. XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,
    313. ByteCount + OVERHEAD_SIZE);
    314. }
    315. /*****************************************************************************/
    316. /**
    317. *
    318. * This function erases the sectors in the serial FLASH connected to the
    319. * QSPI interface.
    320. *
    321. * @param QspiPtr is a pointer to the QSPI driver component to use.
    322. * @param Address contains the address of the first sector which needs to
    323. * be erased.
    324. * @param ByteCount contains the total size to be erased.
    325. *
    326. * @return None.
    327. *
    328. * @note None.
    329. *
    330. ******************************************************************************/
    331. void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
    332. {
    333. u8 WriteEnableCmd = {WRITE_ENABLE_CMD};
    334. u8 ReadStatusCmd[] = {READ_STATUS_CMD, 0}; /* must send 2 bytes */
    335. u8 FlashStatus[2];
    336. int Sector;
    337. /*
    338. * If erase size is same as the total size of the flash, use bulk erase
    339. * command
    340. */
    341. if (ByteCount == (NUM_SECTORS * SECTOR_SIZE))
    342. {
    343. /*
    344. * Send the write enable command to the FLASH so that it can be
    345. * written to, this needs to be sent as a separate transfer
    346. * before the erase
    347. */
    348. XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
    349. sizeof(WriteEnableCmd));
    350. /* Setup the bulk erase command*/
    351. WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
    352. /*
    353. * Send the bulk erase command; no receive buffer is specified
    354. * since there is nothing to receive
    355. */
    356. XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
    357. BULK_ERASE_SIZE);
    358. /* Wait for the erase command to the FLASH to be completed*/
    359. while (1)
    360. {
    361. /*
    362. * Poll the status register of the device to determine
    363. * when it completes, by sending a read status command
    364. * and receiving the status byte
    365. */
    366. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
    367. FlashStatus,
    368. sizeof(ReadStatusCmd));
    369. /*
    370. * If the status indicates the write is done, then stop
    371. * waiting; if a value of 0xFF in the status byte is
    372. * read from the device and this loop never exits, the
    373. * device slave select is possibly incorrect such that
    374. * the device status is not being read
    375. */
    376. FlashStatus[1] |= FlashStatus[0];
    377. if ((FlashStatus[1] & 0x01) == 0)
    378. {
    379. break;
    380. }
    381. }
    382. return;
    383. }
    384. /*
    385. * If the erase size is less than the total size of the flash, use
    386. * sector erase command
    387. */
    388. for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++)
    389. {
    390. /*
    391. * Send the write enable command to the SEEPOM so that it can be
    392. * written to, this needs to be sent as a separate transfer
    393. * before the write
    394. */
    395. XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
    396. sizeof(WriteEnableCmd));
    397. /*
    398. * Setup the write command with the specified address and data
    399. * for the FLASH
    400. */
    401. WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
    402. WriteBuffer[ADDRESS_1_OFFSET] = (u8)(Address >> 16);
    403. WriteBuffer[ADDRESS_2_OFFSET] = (u8)(Address >> 8);
    404. WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
    405. /*
    406. * Send the sector erase command and address; no receive buffer
    407. * is specified since there is nothing to receive
    408. */
    409. XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
    410. SEC_ERASE_SIZE);
    411. /*
    412. * Wait for the sector erse command to the
    413. * FLASH to be completed
    414. */
    415. while (1)
    416. {
    417. /*
    418. * Poll the status register of the device to determine
    419. * when it completes, by sending a read status command
    420. * and receiving the status byte
    421. */
    422. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
    423. FlashStatus,
    424. sizeof(ReadStatusCmd));
    425. /*
    426. * If the status indicates the write is done, then stop
    427. * waiting, if a value of 0xFF in the status byte is
    428. * read from the device and this loop never exits, the
    429. * device slave select is possibly incorrect such that
    430. * the device status is not being read
    431. */
    432. FlashStatus[1] |= FlashStatus[0];
    433. if ((FlashStatus[1] & 0x01) == 0)
    434. {
    435. break;
    436. }
    437. }
    438. Address += SECTOR_SIZE;
    439. }
    440. }
    441. /*****************************************************************************/
    442. /**
    443. *
    444. * This function reads serial FLASH ID connected to the SPI interface.
    445. *
    446. * @param None.
    447. *
    448. * @return XST_SUCCESS if read id, otherwise XST_FAILURE.
    449. *
    450. * @note None.
    451. *
    452. ******************************************************************************/
    453. int FlashReadID(void)
    454. {
    455. int Status;
    456. /* Read ID in Auto mode.*/
    457. WriteBuffer[COMMAND_OFFSET] = READ_ID;
    458. WriteBuffer[ADDRESS_1_OFFSET] = 0x23; /* 3 dummy bytes */
    459. WriteBuffer[ADDRESS_2_OFFSET] = 0x08;
    460. WriteBuffer[ADDRESS_3_OFFSET] = 0x09;
    461. Status = XQspiPs_PolledTransfer(&QspiInstance, WriteBuffer, ReadBuffer,
    462. RD_ID_SIZE);
    463. if (Status != XST_SUCCESS)
    464. {
    465. return XST_FAILURE;
    466. }
    467. xil_printf("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[1], ReadBuffer[2],
    468. ReadBuffer[3]);
    469. return XST_SUCCESS;
    470. }
    471. /*****************************************************************************/
    472. /**
    473. *
    474. * This function enables quad mode in the serial flash connected to the
    475. * SPI interface.
    476. *
    477. * @param QspiPtr is a pointer to the QSPI driver component to use.
    478. *
    479. * @return None.
    480. *
    481. * @note None.
    482. *
    483. ******************************************************************************/
    484. void FlashQuadEnable(XQspiPs *QspiPtr)
    485. {
    486. u8 WriteEnableCmd = {WRITE_ENABLE_CMD};
    487. u8 ReadStatusCmd[] = {READ_STATUS_CMD, 0};
    488. u8 QuadEnableCmd[] = {WRITE_STATUS_CMD, 0};
    489. u8 FlashStatus[2];
    490. if (ReadBuffer[1] == 0x9D)
    491. {
    492. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
    493. FlashStatus,
    494. sizeof(ReadStatusCmd));
    495. QuadEnableCmd[1] = FlashStatus[1] | 1 << 6;
    496. XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
    497. sizeof(WriteEnableCmd));
    498. XQspiPs_PolledTransfer(QspiPtr, QuadEnableCmd, NULL,
    499. sizeof(QuadEnableCmd));
    500. while (1)
    501. {
    502. /*
    503. * Poll the status register of the FLASH to determine when
    504. * Quad Mode is enabled and the device is ready, by sending
    505. * a read status command and receiving the status byte
    506. */
    507. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
    508. sizeof(ReadStatusCmd));
    509. /*
    510. * If 6th bit is set & 0th bit is reset, then Quad is Enabled
    511. * and device is ready.
    512. */
    513. if ((FlashStatus[0] == 0x40) && (FlashStatus[1] == 0x40))
    514. {
    515. break;
    516. }
    517. }
    518. }
    519. }
    520. /* 运行结果
    521. QSPI FLASH Polled Example Test
    522. FlashID=0xEF 0x40 0x19
    523. Successfully ran QSPI FLASH Polled Example Test
    524. */

  • 相关阅读:
    【PG】PostgreSQL字符集
    记一次线上websocket返回400问题排查
    vr航空博物馆综合展馆趣味VR科普体验
    Windows10 下 Neo4j1.5.8 安装教程
    Linux(openssl):解析证书
    # 从浅入深 学习 SpringCloud 微服务架构(四)Ribbon
    CV之ModelScope:基于ModelScope框架的人脸人像数据集利用DCT-Net算法实现人像卡通化图文教程之详细攻略
    MySQL text 能存多少个字符
    Redis
    .NET周报【10月第1期 2022-10-11】
  • 原文地址:https://blog.csdn.net/qq_38863842/article/details/126791744