8 zedboard Data Logging using SD Cards

使用SD卡进行数据记录
本文介绍在Zedboard上使用SD卡进行数据记录的方法,包括SD卡控制器、驱动及FatFs文件系统的应用,实现每次按下按钮时在SD卡上记录时间戳事件。

Data Logging using SD Cards

In this lab, All non-volatile memories available on the Zedboard are studied. The main focus is on the SD memory, its controller (SD/SDIO), and its driver. An application is developed to use the SD card to store a string of characters in the format “HH:MM:SS Event: Sensor X Triggered #” every time the lower push button on the Zedboard is pressed (the push button here emulates a sensor in a real life situation). HH:MM:SS represents the real time. The FatFs (File allocation table File system) APIs are used by the application to access the SD card.

Lab7 Design Flow

Lab7 Design Flow

Lab7 Block Diagram

Lab7 Block Diagram

Lab7 Board Interface

Lab7 Board Interface

Data logging in embedded systems is the activity of saving some data on a non-volatile memory. The data could be anything, to list few: sensors readings such as ambient temperature; figures relate to operation, for instance, energy consumption.
There are two non-volatile memories available on the Zedboard that can be used for the purpose of data logging. The first one is the QSPI (quad-SPI) serial NOR flash with a capacity of 256Mbit. The second is the SD card accessed through the SD card connector available on the back of the Zedboard (A 4GB SD card is already inserted in the connector).

Zedboard Block Diagram

Zedboard Block Diagram

Both of these memories could be used for initialization, or data storage. By initialization, we mean it can be used to initialize the PS subsystem as well as to configure the PL subsystem on boot up (Bitstream). QSPI memory is accessed through a quad-SPI flash controller, on the other hand, the SD card which is the focus of this lab requires a more sophisticated controller known as the SD/SDIO host controller. In this lab, we will use the SD card to store a string of characters in the format “HH:MM:SS Event: Sensor X Triggered #” every time the lower push button is pressed. HH:MM:SS represents the real time. The logging of events against time is called time stamping. It has a wide applications in weather stations, road traffic counting, and wildlife research. The strings will be stored in a log file called “RECORDS.txt” on the root of SD card. This file will preserve its content even if power is switched off on the board. The file could also be copied using an SD card reader to a host desktop or laptop.

records.txt created by the board and stored on the SD card

RECORDS.txt created by the Zedboard and stored on its SD card

The hardware setup of this lab is quite similar to the one of lab5(Hardware Timers), Except that the  SD0 controller  is enabled within the PS. On the PL-side, the AXI timer is used to keep track of the real time in a precise manner, the GPIO is used to provide an interface with the push buttons, the ZedboardOLED is there to display the real time (optional), while on the PS-side, the SDO controller is enabled to communicate with the SD card. The UART provides a debugging terminal when needed.

Background Information

     A-SD Cards

Secure Digital (SD) cards are flash-based memories used widely in embedded systems for nonvolatile storage. They come in three different dimensions: SD (used on the Zedboard), miniSD, microSD (both popular in smart phones and digital cameras). All SD cards have controllers inside it, as illustrated in the left figure below.

SD Card Block Diagram

SD Card Block Diagram

This controller inside SD card is responsible for low level details of interacting with memory cells, as well as error correction and wear leveling. A host controller(on the processing system side) is needed to interface with the controller of an SD card. For a host controller to be able to interact with an SD card, it has to comply with a protocol known as the SDIO Specification 2.0. The SDIO interface signals on SD card and SD card connector are outlined below.

SDIO Interface Signals

SDIO Interface Signals

There are two extra signals in the SDIO Specification 2.0, that are not part of SD card itself but part of SD card connector :

SD Connector Signals

SD Connector Signals

So to sum things up, the SDIO Specification 2.0 has the following signals:

1.Four signals for data transfer(D0-D3).
2.One signal for synchronizing clock (Clk).
3.One signal for command/response (CMD).
4.One signal to detect whether a card is present in the connector or not (CD).
5.One signal to read the write protect lock on the card(WP).
6.One signal for power.
7.Two signals for ground.

The figure bellow shown the wiring diagram of the SD card connector (J12) on the Zedboard(Obtained from Zedboard user manual). It is clear from the schematic that the data signals (D0-D3), and  control signals (CLK,CMD,CD,WP) are hardwired to the PS-side of the Zynq chip and namely to the MIO40-MIO47(Multiplexed IO). The part of the PS-side containing the MIO40-MIO47 pins is running on LVCMOS1.8 voltage standard (logic high is represented by 1.8 voltage level ) while the SD card used on the Zedboard is running on LVCMOC3.3 . This is why the manufacturer of Zedboard had placed a logic level converter IC (IC8) between the two.

MIO40-MIO47 PS-Side Connections

MIO40-MIO47 PS-Side Connections

SD Connector Electrical Interface

SD Connector Electrical Interface

     B-SD host controller (SD0)

In the last few years SD cards started to become vital components in embedded systems, they present a flexible storage elements with reasonably adequate capacity for embedded usage. This is why the Zynq chip contains more than one SD host controllers. The one used here is the SD0 circled in red in the Zynq architecture diagram below:

Zynq Architecture- SDO circled in red

Zynq Architecture- SDO circled in red

The SD0 host controller is responsible for communicating with the SD card controller (inside the memory card), through the SDIO protocol. Data is transferred between the two controllers as data blocks in unit of 512 bytes. This is due to the fact that files are stored in SD cards in blocks of 512bytes(Default but could be changed). With that being said, you would expect a file of 10 bytes to occupy a full block with the rest of the block (502 bytes) unutilized. A one kilobyte file will occupy two blocks, and so on. The SD0 has its own DMA engine inside it. The figure below is a block diagram of the SD0 controller:

SD/SDIO Controller Block Diagram

SD/SDIO Controller Block Diagram

     C-SD host controller driver (XSdPs driver)

The SD host controller driver (XSdPs driver) can be used to initialize,and read from/write to the SD card by using the functions below:

XSdPs driver low-level functions

XSdPs driver low-level functions

Even though these functions are sufficient for the purpose of this lab ( we are dealing with only one file) , however ,trying to deal with multiple large files using these low level functions will be a very tedious, error-prone, and time consuming task. The reason is that we need to keep track of the starting address(es) of the block(s) of the files. This is illustrated by the following example:

We have only 3 files: FILE1.TXT of size 1536 bytes, FILE2.TXT also of size 1536 bytes, and FILE3.TXT of size 512 bytes. In order to work with these three files, we need to keep track of 7 addresses(see figure below). Now a question for you! How many addresses we need to keep track of, let’s say, for 10 files of size 100Mbyte!? NOTE: blocks of a certain file are not necessarily consecutive in order(check FILE2.TXT). This should highlight the challenges encountered when dealing with multiple large files and motivate the necessity to use a file system.

Keeping track of files block's addresses for three files

Keeping track of files block’s addresses (three files only)

     D-FatFs – File Allocation Table File System Library (Elm-Chan Library)

The file system library provides a high level, user friendly functions (aka API- Application Programming Interface). These APIs profoundly eliminate the complexity of dealing with low level addresses of the file(s)’ block(s). The figure below provides a list of the FatFs APIs:

FatFs APIs

FatFs APIs

Basically, FatFs library hides the complexity of dealing with the driver functions directly, however, it is worth noting that internally, the FatFs calls the SD host controller driver’s functions to implement its functionality(aka disk IOs). FatFs library could be used in both standalone systems or as part of an operating system. The way we are using it in this lab is in standalone system, where no OS support was included. The figure below illustrates the layers of lab7 software stack running on the Zynq ARM processor:

FatFs Zynq

Lab7 Software Stack

The above figure also shows how the application, library, driver, and hardware interact with each other. It is clear that the complexity of dealing with the hardware and driver directly has been abstracted and simplified through the use of the FatFs library. It is also evident that the application is effectively interacting with the hardware (SD card) using the user friendly APIs of the FatFs. The FatFs library is translating these APIs to function calls to the XSdPs driver, while the later will write to the memory-mapped region of the SD host controller to interact with the hardware, this is typically achieved through Xil_out32()Xil_in32() functions.
The FatFs supported by Xilinx SDK is compatible with all three FAT subtypes: FAT12, FAT16, and FAT32. These three subtypes have different features in terms of disk utilization, maximum partition size, and file names length. FAT32 is an extension of the FAT16, the original FAT12 (aka FAT) was first introduced way back in 1981 in the DOS system. The subtype used for this lab is the upgraded FAT (FAT32).

     E-FatFs APIs

To use the FatFs library, first you need to declare an instance of type file system (FATFS) to be associated with the SD card (s) present in the system.

FATFS Instance

 

 

Similarly, you need to create an instance of type file (FIL) for file(s) to be used in application.

FIL Instance

 

In addition to that, declare a variable to hold the return value of the FatFs APIs. This variable should be of type (FRESULT). Examining the value returned in this variable can tell us whether an API succeeded or failed, and if failed we would know exactly what went wrong.

FRESULT variable

 

 

The FRESULT falls between 19 values, any value other than zero means a failure in execution. The interpretation of these values is as follows:

FATFS Return Values(FRESULT)

FatFs Return Values(FRESULT)

After defining these three variables, we can start using the APIs. The first API that should be present in all applications using FatFs library is the f_mount().

f_mount() FatFs Zynq

FatFs f_mount() format

f_mount() initializes an SD card and associates an instance of type FATFS with it.  f_mount()  takes three parameters: pointer to the FATFS instance, logical drive number (if there is only one SD card in the system its 0:/ ), and an option to have a delayed mount.

Note: this function can be also used to unmount an SD card by passing NULL in the first parameter.

The function returns FRESULT value similar to all FatFs APIs .

f_mount() Zynq

f_mount() with checked returned status

Path in the above example is a string pointer to the logical drive number:

Logical drive number SD0

It is a highly recommended practice to always check the value returned by any API, and if an error occurs it is typically safer to do the following:
1.Return to caller.
2.Notify user about the nature of the error.

After a successful call to f_mount(), a card is initialized and ready to be used. Similar to the way we handle files on our laptops and desktops, we will do similar steps here, in other words, in order to read/write a file, first we open it, then read/modify as needed, finally save and close it.

The f_open() function is used to create or to open a file. The function takes three parameters: a pointer to the file instance, name of the file including its path, and access mode.

f_open()

FatFs f_open() format

For the sake of simplicity, files are saved directly on the root of the SD card, however, directories are supported and can be created to organize files. The access mode determines whether we are creating a new file, or opening an existing file, and it also controls other parameters such as overwriting:

FATFS Access Mode

FatFs Access Mode

Example 1: Create a new file named “Record.txt” on the root directory of an SD card, if the file already exists it will be truncated and overwritten.

Example1

Example 1 solution

Example 2: Open a file named “temperature.txt” available on the root directory of an SD card, the file is to be read from and written to.

Example 2

Example 2 solution

Now we know how to open a file in FatFS, the next thing to master is how to read from it and write to it.

In order to read from a file, it should have already been opened using f_open()function in FA_READ mode. A buffer is declared to hold the data read from the file. The type of the buffer is dependent on the data stored in the file. As for the size of the buffer, it is application dependent,however, always take into consideration memory word alignment.

Example 3: Assume a file contains long strings of characters, and we want to read 9 characters at a time. The buffer to be declared in such scenario is :

char buffer

Example 3 solution

Note: you always need to declare a buffer with size+1, as the last location in the buffer is reserved for the NULL terminator.

It is also important to define an unsigned integer to keep track of how many bytes have been read from the file (counter). This is useful in many situations, like determining if end of the file(EOF) is reached.

Counter varibale to keep track of the data read from a file

 

Now, let’s talk about the function that actually do the reading  f_read(), it takes four parameters: a pointer to the file instance previously opened using f_open() in FA_READ mode, a buffer to store the read data, the number of bytes to be read,  and a pointer to the counter variable.

FatFs f_read() format

FatFs f_read() format

In the following example 4 bytes are read and saved in buffer “buff”. On a successful read operation, count should hold the value 4 .

f_read() reading 4 bytes from a file

f_read() reading 4 bytes from a file

If the opposite is needed, if data is to be written to a file,  then  f_write() function is called.

f_write() format

FatFs f_write() format

f_write() takes similar parameters to  f_read(), but this time the buffer would contain the data to be written.

Example 4: save 9 bytes of data held in “buff” in a file associated with file instance file3. On a successful write operation, count would hold the value 9.

Example 4

Example 4 solution

By using standard C functions, such as the sprintf(), you can format data in a write buffer the way you want.

It is recommended to close any file that is no longer needed to reserve resources. This is achieved by calling function f_close().

f_close() format

FatFs f_close() format

Example 5: closing file1 (no longer needed)

Example 5

Example 5 solution

Objectives
1.Introduce non-volatile memories available on the Zedboard.
2.Examine the general structure of an SD card, and how the SD card attached to the Zedboard is wired to the chip.
3.Understand the different hardware and software components needed to access SD cards efficiently.
4.Emphasize on the benefits of using libraries on top of drivers to hide complexities and enable broader usages of hardware.
5.Practice FatsFs Application Programming Interface (API).
6.Build a simple logging application.

Procedures

     A-Copy lab5 content into a new directory

Follow the same four steps in Procedures-A of Lab6. However, in Step1 name the new folder “lab7″.

     B-Enable SD0 Host Controller on PS

1.Double click on the zynq_interrupt_system_i block diagram file to open the block diagram.

Block Diagram File

Block Diagram File

2.In the diagram view, double click on Zynq Processing System to open the Re-customize IP window.
3.Click on MIO Configuration-> I/O Peripherals and enable SD0. Change bank 1 I/O Voltage to LVCMOS 1.8V. Then, do the required modifications so that it matches the figure below.

MIO Configration for SD0 / Zynq

MIO Configration for SD0

Make sure to disable the Pullup resisters for MIO 40-45 , and change its speed to fast. The Card detect signal “CD” and the write protect signal “WP” need to be enabled if you wish not to use JP6 jumper on the board.

Note: The above modifications were made to meet the electrical interface specifications of the SD card connector (obtained from Zedboard user manual). The Interface is shown below, MIO signals are wired to the SD connector through the TI TXS02612 SDIO level translator.

SD Card Interface Zynq

SD Card Interface

Click OK to close the the Re-customize IP window.

     C-Regenerate Bitstream to reflect the new modification

In the Program and Debug section of the Flow Navigator pane, click Generate Bitstream. A dialog box will appear to ask you to save the modification you made, click Save .

Generating Bitstream

Generating Bitstream

Generating the Bitstream may take a while to complete, depending on the performance of your machineAfter the Bitstream generation completes select View Reports in the dialog box, and click OK.

     D-Export hardware design to SDK

1.Click File > Export > Export Hardware, make sure you select Include bitstream.

Export Hardware to SDK

Export Hardware to SDK

2.Select File>Launch SDK. This will open up Launch SDK dialog, leave default options as as, and click OK. All the hardware files related to design have now been exported to SDK and we can work on the software.

We are now done with the hardware configuration of the system. You may close Vivado.

      E-Working with SDK

1.In SDK, select File > New > Application Project.
2.In the Application Project window, enter the parameters as provided in the snapshot below:

Data logger Zedboard

New Standalone C Project – data_logger

In the next window, select Empty Application from the available templates and click Finish. This will compile the BSP and the related drivers.

3.Expand data_logger project directory, right click on src directory, New->Source File.

New C Source File – lab7.c

New C Source File – lab7.c

4.In the next window that shows up type “lab7.c” in the source file and click Finish. This will create an empty C file in the src directory.

lab7.c empty source file created in SDK

lab7.c empty source file created in SDK

5.Right click on data_logger_bsp and select Board Support Package Settings. 
6.In Board Support Package Settings, click on the box next to xilffs to include FatFs File System Library into the BSP and be able to use its API. Click OK .

FatFs File System Library Zynq

Board Support Package Settings- Include FatFs File System Library

7.Paste the content of lab7.c ( Available on my Github page) in in the editor view of lab7.c of SDK , and click on Save Save Symbol or hit (Ctrl+S) , by doing so both lab7 application, and its BSP are compiled automatically and the executable .elf file is generated( the default settings of SDK triggers compilation with Save). This is the executable file that the ARM processor on the PS side of the Zynq will execute.

lab7.c is an extended version of lab5.c. The additions on top of lab5.c are enclosed by comments as show in the figures below. The additions include modified main() and modified push buttons ISR BTN_Intr_Handler() .

main() now includes the code for mounting an initializing the SD card, and also creating file RECORDS.txt ( Lines 287-296).

f_mount FatFs Zedboard

modified main() – Lab7

The code to write to the file is inside modified push buttons ISR  BTN_Intr_Handler() (Lines 130-169)

Writing to file inside pushbutton ISR everytime BTND is pressed

Writing to file inside pushbutton ISR everytime BTND is pressed

8.Select Xilinx Tools-> Program FPGA to download the Bitstream (this will take few seconds).

Downloading Bitstream to the PL

Downloading Bitstream to the PL

9.Select data_logger  project directory-> Run As-> Launch on Hardware (GDB) to run data_logger application on the ARM processor. After the download is complete, every time you press the lower push button. A string is saved in file RECORDS.txt on the Zedboard SD card. you can view the content of this file by using a card reader. The content should be identical to the below :

RECORDS.txt created by the board and stored on the SD card

RECORDS.txt created by the board and stored on its SD card


By this you have completed Lab7-Data Logging using SD Cards. You can find the complete solution of this lab in here.

<think>好的,我现在需要帮用户解决如何在MATLAB脚本中为信号线启用数据记录的问题。用户提到他们之前询问过类似的问题,但这次特别强调使用脚本而不是Simulink界面操作。所以首先,我需要确保自己了解MATLAB中数据记录的相关功能,尤其是通过脚本控制的方法。 首先,回忆一下,Simulink中的数据记录通常可以通过模型配置参数或者右键点击信号线选择记录选项。但用户希望用脚本实现,这意味着需要使用MATLAB的命令行或脚本函数来设置信号属性。可能需要用到set_param函数,这是Simulink中常用的参数设置函数。 接下来,我需要确认如何通过脚本指定特定信号线进行数据记录。查阅资料时,记得每个信号线在模型中都有唯一的标识,可能是通过块路径和端口号来定位。例如,模型中的某个模块的输出端口,可以通过模块路径和端口号来找到对应的信号线。 然后,可能需要设置信号的DataLogging属性为'on'。例如,使用set_param函数,参数可能是信号线的句柄或者标识符,设置DataLoggingName来指定记录时的变量名,以及DataLoggingDecimateData控制是否降频,DataLoggingDecimation设置降频因子。 另外,还要考虑数据记录后的存储位置。通常,仿真运行后,数据会保存在Simulink.SimulationOutput对象中,可以通过logsout数据集访问记录的数据。需要确保用户知道如何从脚本中提取这些数据,比如使用get_param检查设置是否生效,或者在仿真后处理logsout。 同时,要检查是否有遗漏的步骤,比如确保模型在设置后正确保存配置,或者在仿真前应用这些参数设置。可能还需要提醒用户,如果信号线所在的子系统没有启用信号记录,可能需要先启用该子系统的信号记录功能。 最后,生成相关问题,帮助用户深入理解。例如,如何批量设置多个信号,如何处理记录的数据,或者如何通过脚本配置其他记录选项,如数据存储格式等。还要确保引用相关文档或工具箱,如Signal Processing Toolbox,但根据用户问题,这次重点在Simulink的数据记录,可能引用Simulink的官方文档更合适。 总结步骤:找到信号线标识,设置DataLogging相关属性,运行仿真,提取数据。示例代码需要具体,比如模块路径和端口号的正确使用方法。同时提醒用户注意模型保存和可能的错误排查。</think>在MATLAB中通过脚本为信号线启用数据记录,需使用`set_param`函数配置信号属性。以下是分步实现方法: ### 1. **定位信号线** 通过模块路径和输出端口号确定信号线,例如: ```matlab blockPath = 'modelName/Subsystem/BlockName'; % 替换为实际模块路径 portIndex = 1; % 输出端口编号(从1开始) ``` ### 2. **启用数据记录** 设置信号线的`DataLogging`属性: ```matlab signalObj = get_param([blockPath '/' int2str(portIndex)], 'SignalObject'); set_param(signalObj, 'DataLogging', 'on'); ``` 或直接通过端口句柄设置[^2]: ```matlab ph = get_param(blockPath, 'PortHandles'); set_param(ph.Outport(portIndex), 'DataLogging', 'on',... 'DataLoggingNameMode', 'Custom',... 'DataLoggingName', 'LoggedSignal'); ``` ### 3. **配置记录参数(可选)** - **降采样**:减少数据量 ```matlab set_param(ph.Outport(portIndex), 'DataLoggingDecimateData', 'on',... 'DataLoggingDecimation', '10'); ``` - **存储格式**:指定变量名 ```matlab set_param(ph.Outport(portIndex), 'DataLoggingName', 'MySignalData'); ``` ### 4. **运行仿真并提取数据** ```matlab simOut = sim('modelName', 'SaveOutput', 'on'); loggedData = simOut.get('logsout').get('MySignalData').Values.Data; ``` ### 完整示例脚本 ```matlab % 打开模型 open_system('modelName'); % 配置信号记录 blockPath = 'modelName/Subsystem/Integrator'; ph = get_param(blockPath, 'PortHandles'); set_param(ph.Outport(1), 'DataLogging','on',... 'DataLoggingName','Velocity',... 'DataLoggingDecimation','5'); % 运行仿真 simOut = sim('modelName'); % 获取记录数据 velocityData = simOut.logsout.get('Velocity').Values; plot(velocityData.Time, velocityData.Data); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值