当前位置:   article > 正文

ZYNQ7010的PS编程笔记_zynq.ps使用手册

zynq.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. */

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/830560
推荐阅读
相关标签
  

闽ICP备14008679号