Purpose:
After completing this lab, you will have an understanding of how to configure and add the Harmony Universal Serial Bus (USB) Library for Mass Storage Device (MSD) class using the MPLAB® Harmony Configurator (MHC).
Overview:
This lab extends audio_player_lab2 by adding SD (Secure Digital) card reader functionality. The audio_player_lab3 application shows how to edit contents of an SD card. The PIC32 Multimedia Expansion Board II is connected to a USB host, (typically a PC) and after a successful enumeration, the SD card is presented as a mass storage drive on the PC allowing you to add/delete contents.
You will add a new task to handle the USB device events for the SD card reader. Apart from registering a USB device layer events handler, the application need not intervene in the functionality of Mass Storage Device (MSD) Function driver since the MSD function driver does not provide any application callable functions.
You will also add a task to handle button (switch S1 on the MEB II Board) press events. Pressing switch S1 will allow you to switch between the SD card player mode and the SD card reader mode. By default, the SD card player mode is selected and the application will read and play the tone.txt file (if present) on the SD card. When switch S1 is pressed, the device will act as an SD card reader allowing you to connect to the PC and load files (tone.txt for this lab) to the SD card.
For Lab3, you will be able to play audio data saved in a tone.txt file by loading it through the USB interface.
For subsequent labs, you will be able to play WAV files by loading them to the SD card using the USB interface.
Lab Source Files and Solutions:
If you haven't already downloaded all source files for the SD card audio player labs:
Download the lab source files and solutions >
This project has been verified to work with the following versions of software tools:
MPLAB X IDE v3.26, MPLAB XC32 Compiler v1.40, MPLAB Harmony v1.08
As the tools are regularly updated, there may be occasional issues while using newer versions. If that is the case, we recommend using the same version as specified in the project.
The archived versions of our tools can be found below:
MPLAB Harmony
MPLAB X IDE and XC32 Compiler
Note that multiple versions of all these tools can co-exist on the same computer.
Procedure:
This lab builds off the work you performed in the previous lab. If you did not perform SD card Audio Player Lab2, please start Lab3 using the Lab2 solution project (found under the firmware folder). Verify it works as expected before continuing with this lab.
All steps must be completed before you will be ready to build, download, and run the application.
Lab Index
Step 1: Copy source files and rename project for Lab3
Create a new folder audio_player_lab3 under
apps/training/middleware/dev/audio_player.
At this point, we suggest you close any open projects from previous labs.
This will avoid confusion since you will be opening the project with the same name as the previous lab before renaming it for this lab.
Copy the firmware folder from
apps/training/middleware/dev/audio_player/audio_player_lab2
to the newly created folder (audio_player_lab3).
Rename the project from audio_player_lab2 to audio_player_lab3, because by the end of this session the lab will have audio_player_lab3 funcitonality. Open audio_player_lab2.
Under Projects, Right click on audio_player_lab2 and select Rename…
In the popup window rename the lab from audio_player_lab2 to audio_player_lab3.
The MPLAB X IDE renames the project. It closes the old project audio_player_lab2 and opens the renamed project audio_player_lab3.
Verify that the project builds properly after renaming. Click the
Clean and Build icon:
.
In the MPLAB X IDE Projects pane, right click on audio_player_lab3 and select Set as Main Project.
Open the MHC: In the MPLAB X IDE click on: Tools > Embedded > MPLAB Harmony Configurator.
Step 2: Configure the USB Library
Expand the Harmony Framework Configuration > USB Library selection tree.
Check the Use USB Stack? box.
Make sure the Interrupt Mode box is checked.
The MEB II Board will be acting as a USB device with the PC acting as the USB host. Expand Select Host or Device Stack and verify the USB Device box is checked.
Set the Number of Endpoints Used to 2. The MSD uses Bulk-Only Transport (BOT) protocol. This protocol uses one bulk endpoint for data from the host, one bulk endpoint for data going to the host and the control endpoint for other control-related transfers.
Make sure that the Endpoint 0 Buffer Size is set to 64. You will be using the USB in High-Speed mode which requires the endpoint buffer size to be set to 64.
Verify the USB Device Instance 0 box is checked and expand this option. Note: Since there is only one USB peripheral on the device, there is only one USB instance. This is selected by default.
Verify that the device speed is set to USB_SPEED_HIGH. PIC32MZ devices support full speed and high speed. Selecting high speed will allow the device to work at both full speed and high speed.
You will only need MSD functionality. Hence, the Number of Functions Registered to this Device Instance must be left at 1.
Check the Function 1 box and expand it.
The Device Class is set to MSD because you will be using the USB device as the interface to detect and access the SD card as a MSD on the PC.
Set the configuration value to which this function driver is tied. You will have only one configuration and hence retain the default Configuration Value of 1.
Retain the default Start Interface Number at 0.
The Speed member of the entry specifies the device speeds for which this function driver should be initialized. This can be set to either USB_SPEED_FULL, USB_SPEED_HIGH or a logical or a combination of both. The Device Layer will initialize the function if the device attaches speed matches the speed mentioned in the speed member of the entry. You will allow for both high speed and full speed operations and hence set it to USB_SPEED_HIGH|USB_SPEED_FULL.
Verify the Endpoint Number is set to 1. This is the endpoint number to use for bulk data in and bulk data out operations.
Change the Max number of sectors to buffer to 8.This will allow up to 8 sectors to be buffered before a read/write operation is performed.
Retain the Number of Logical Units to 1.
Check the LUN 0 box and expand it.
This application falls into the category of SD card reader. Set the Media Type to SDCARD.
Verify the Product ID Selection is set to msd_basic_sdcard_demo. Retain the default values for Enter Vendor ID, Enter Product ID, Manufacturer String, and Product String.
Make sure the Suspend in Sleep is unchecked. Retain the default priority settings for USB Interrupt Priority, USB Interrupt Sub-priority, USB DMA Interrupt Priority, and USB DMA Interrupt Sub-priority.
Keep the default value of SYS_MODULE_POWER_RUN_FULL for Power State.
The following other options must be left unchecked:
Enable SOF Events
Enable Set Descriptor Events
Enable Sync Frame Events
Use Remote Wakeup Feature
Enable BOS Descriptor Support
Enable advanced String Descriptor Table
You have finished configuring the USB library for your application. Save the configuration.
Since the USB MSD class will be using the SD card media, you must increment the number of clients for the SD card driver to 2. One client will be the file system and the other will be the USB MSD class.
Expand the Harmony Framework Configuration > Drivers > SD Card > Use SD Card Driver? selection tree.
Change the Number of SD Card Driver Clients to 2.
Save the MHC configuration by clicking the save button.
Step 3: Generate Harmony code
Click the Generate Code button as shown in the following figure. Make sure the Merging Strategy selected is Prompt Merge For All User Changes.
Resolve code generation merge conflicts.
When the Generate button is clicked, the MHC will modify and generate source files based on the options selected in the MHC. If the MHC generates code that will change a pre-existing file, it will show you the code it generated, and allow you to confirm if you want to add it to your source code. The following screenshots will guide you on which changes need to be merged (i.e., accepted).
Note: Retain the below definitions in the Current File
Let’s examine what was done after generating code:
The app folder contains files related to your specific application. In the following steps, you will add your application code to the existing app.c and app.h files. You will also add other application-specific source files to the project. As you can see, no new (with respect to the previous lab) files have been added to the app folder.
Also, note the Source Files/framework folder contains standard Harmony Framework files that have been added to your project by the MHC (based on your MHC selections). To be clear, unlike the framework files found under the app folder, these files have not been modified by the MHC. They are some of the standard Harmony Framework files included in the Harmony Framework download.
As you can see the usb folder has been added to this framework folder. Also another usb folder has been added under the Source Files/framework/driver folder.
Step 4: Include application-specific source files, add required code and build the project
Copy source files into your project's Source Files folder:
app_sdcard_reader_task.c
app_sdcard_reader_task.h
app_button_press_task.c
app_button_press_task.h
Copy them from this folder:
apps/training/middleware/audio_player/audio_player_lab3/dev_files
to this one:
apps/training/middleware/dev/audio_player/audio_player_lab3/firmware/src
Add the copied source files to your project.
- Add app_sdcard_reader_task.c and app_button_press_task.c to the Source Files/app folder (in the MPLAB X IDE Projects pane) by right clicking and selecting Add Existing Items…
- Add app_sdcard_reader_task.h and app_button_press_task.h to the Header Files/app folder by right clicking and selecting Add Existing Items…
The files under the project should look like this:
Open the app.c file and add the initialization routines for the SD card reader and button press tasks.
Modify the APP_Tasks function to add the two newly added tasks, under the APP_STATE_SERVICE_TASKS state.
Add two functions that will set and get the current mode of the application. This will execute either the player functionality implemented by the APP_TONE_TEXTFILE_SDCARD_Tasks, or the SD card reader functionality implemented by the APP_SDCARD_READER_Tasks.
Now, open the app.h file and add the following enumeration. This will be used to manage the application modes.
Next, modify the APP_DATA structure to include the application's mode related information.
Also, you need to expose the set and get mode functions to other tasks. Include the following declarations in the app.h file.
Finally, open app_tone_textfile_sdcard.c and add the following condition. This will ensure the APP_TONE_TEXTFILE_SDCARD_Tasks function runs only when the audio playback mode is selected.
Note: You must also add the closing bracket for the if condition.
Save all the files before closing.
Now, you are ready to build the code. Click the
Clean and Build icon and verify that the project builds successfully.
Step5: Review the Application code
Application File: app_tone_textfile_sdcard.c
This file remains the same as in audio_player_lab2, except for the condition added above which makes sure that APP_TONE_TEXTFILE_SDCARD_Tasks runs only when the application is in Audio Player mode.
Application File: app_tone_textfile_sdcard.h
This file remains same as in audio_player_lab2.
Application File: app_sdcard_reader_task.h
Open file app_sdcard_reader_task.h. This file defines application enums, data, and Application Programming Interfaces (APIs).
The below enumeration defines the states of the SD card reader task.
Only two states are needed as the entire functionality is handled by the USB MSD class driver.
The SD card reader data structure holds information on the USB device handle, current state of the task and whether the USB interface is detached or not.
Application File: app_sdcard_reader_task.c
Open file app_sdcard_reader_task.c. This file contains the SD card reader task initialization routine and the SD card task function.
The APP_SDCARD_READER_Initialize routine initializes the task to a known state.
The function APP_USBDeviceEventHandler notifies the application of USB MSD events.
The function APP_SDCARD_READER_Tasks opens the USB device and registers the USB device layer event handler. After this, the task enters the run state. From here on, the USB MSD driver handles all the events and there is really nothing that the application needs to handle for USB SD card read/write functionality.
The functions APP_SDCARD_READER_AttachDevice and APP_SDCARD_READER_DetachDevice attaches and detaches the USB device respectively.
Application File: app_button_press_task.h
Open the file app_button_press_task.h. This file defines the enums, data, and APIs related to the button press task.
The enum APP_BUTTON_PRESS_TASK_STATE helps maintain the states of the button task.
The APP_BUTTON_PRESS_TASK_DATA data structure holds the button task's state and button de-bounce related data.
Application File: app_button_press_task.c
Open the file app_button_press_task.c. This file initializes and runs the button press task.
The button Press Task uses the system timer service to implement de-bouncing. When the user presses the button, while the application is in Player mode, it suspends the audio streaming and un-mounts the file system. It then attaches the USB device and switches to the SD card reader mode. Similarly, when the user presses the button, while the application is in the SD card reader mode, the USB device is first detached, the tone text file SD card task is initialized and the application mode is switched back to SD card playback mode.
Step 6: Debug your Application
Congratulations! You’re done. You are ready to DEBUG
your third application.
Before you program and run the application, delete the tone.txt file on the micro SD card. You will load the tone.txt file using the newly added SD card reader functionality.
Make sure that the micro SD card is inserted into the micro SD card slot (J8) on the MEB II board.
Connect a USB cable from the micro USB connector (J4) on the PIC32MZEF Starter Kit Board to the PC.
Connect a headphone to the HP Out connector on the Multimedia Expansion Board II.
Before you start the debugger, you may want to set a breakpoint in the application file in app_button_press_task.c to verify that the application reads the button press and switches to the appropriate mode.
Debug your application! Click the
Debug Main Project icon.
The application boots in the SD Card Player mode. You will not be able to hear the tone as the tone.txt file was already deleted from the micro SD card.
Next, you will load the tone.txt file to the SD card from the PC. Press the switch S1 on the MEB II board. Verify that the breakpoint is hit and the Application mode is changed to SD card reader mode.
Remove all breakpoints, press Key F5 and allow the application to run.
Wait for the PC to enumerate the USB MSD. Verify that the device appears as a Removable Storage Device. On a Windows machine, do this by clicking on the My Computer (or Computer) icon. Click on the drive and copy the tone.txt file.
Once the tone.txt file is copied, press the S1 button to go back to the Player mode. Plugin your earphones and you should be able to listen to the tone!
Results
You should be able to view and edit the contents of the micro SD card by connecting the device to the USB host (PC). You will also be able to switch between the audio player functionality and the SD card reader functionality through the press of a button.
Analysis
In this lab, you added USB MSD support using the MHC. You also demonstrated how the MHC is capable of handling multiple clients that access the same SD card media. At the application layer, you added a new task (state machine) to handle a button press event to allow the users to switch between the audio player and SD card reader modes.
Conclusions
You added USB SD card reader support, thereby bringing your application one step closer to a full-fledged audio player. The lab demonstrates how easily you can add USB MSD class functionality to your applications. It also shows that there is little to no application overhead when it comes to handling MSD class events, as all these events are handled by the USB library. Going forward, you may want to add USB host functionality to the device to read a file (e.g., tone.txt or audio files) stored on a thumb-drive.