PIC MICROCONTROLLER BASED USB STORAGE Darshil Arvindbhai Shah B.E., Gujarat University, India, 2007 PROJECT Submitted in partial satisfaction of the requirements for the degree of MASTER OF SCIENCE in ELECTRICAL AND ELECTRONIC ENGINEERING at CALIFORNIA STATE UNIVERSITY, SACRAMENTO SPRING 2011 PIC MICROCONTROLLER BASED USB STORAGE A Project by Darshil Arvindbhai Shah Approved by: _______________________________, Committee Chair Jing Pang, Ph.D. _______________________________, Second Reader Fethi Belkhouche, Ph.D. __________________________ Date ii Student: Darshil Arvindbhai Shah I certify that this student has met the requirements for format contained in the University format manual, and that this project is suitable for shelving in the Library and credit is to be awarded for the project _________________________, Graduate Coordinator Preetham Kumar, Ph.D. Department of Electrical and Electronic Engineering iii ________________ Date Abstract of PIC MICROCONTROLLER BASED USB STORAGE By Darshil Arvindbhai Shah USB (Universal Serial Bus) is most popular peripheral interface in the computer industry today. USB is plug and play communication. The user doesn’t have to initialize USB compliant device on the computer. Computer will detect the USB device. The older connection standards such as RS-232 or parallel port require external power supply. USB connector also supplies power to the connected devices, so the devices connected to it don’t require external power supply for operation. USB has become standard connection method for many computer peripherals such as mice, keyboards, digital cameras, printers, personal media players, flash drives. USB was designed for personal computers. But nowadays because of the features such as speed, no external power supply requirement, easy to implement have made USB common in smartphones, PDA and video game consoles. This project is an embedded system implementation that communicates with the personal computer using USB as an interface. This embedded system can be divided in two parts. First part is hardware design. The hardware part of the system is implemented iv using the PIC microcontroller. Second part is software implementation. The software implementation of the system is done using Visual C# language. ________________________________________________, Committee Chair Jing Pang, Ph.D. _________________________ Date v ACKNOWLEDGMENTS I would like to thank everybody who has helped me in this project .Specially, I would thank my advisor Dr. Jing Pang, and without her it was not possible to complete this project. It was her idea of doing this wonderful project. Dr. Pang has given encouragement and support throughout the project implementation. She has also given her valuable suggestion in writing the report. It was a great learning experience to work with her. I have learnt many practical aspects of research from her. In addition, I would like to thank Professor Dr. Fethi Belkhouche, the second reader of the project report, for his crucial guidance in writing this project report. I would like to thank Dr. Preetham Kumar for his advising throughout Master’s as Graduate Coordinator. I would also like to thank, Dr.Suresh Vadhva, Department Chair of the Electrical and Electronic Engineering Department, for his strong leadership and immense support throughout my masters. Also, I am thankful for all faculty members of the Electrical and Electronic Engineering Department for helping me finish my requirements for graduation at California State University, Sacramento. vi TABLE OF CONTENTS Page Acknowledgements ............................................................................................................ vi List of Tables ..................................................................................................................... ix List of Figures ......................................................................................................................x Chapter 1. INTRODUCTION ...........................................................................................................1 2. UNIVERSAL SERIAL BUS ...........................................................................................3 2.1 USB Protocol .....................................................................................................4 2.2 USB Connector ..................................................................................................6 2.3 USB Transfer Types ..........................................................................................7 2.4 USB Descriptors ................................................................................................9 3. HARDWARE OVERVIEW ..........................................................................................16 3.1 PIC Microcontroller .........................................................................................16 3.2 PIC18F4550 Microcontroller ...........................................................................16 3.3 Oscillator ..........................................................................................................18 3.4 PICKit 2 ...........................................................................................................20 4. DESIGN IMPLEMENTATION AND FINAL RESULTS ...........................................22 4.1 Block Diagram of the Design ..........................................................................22 4.2 Hardware Implementation ...............................................................................23 4.3 Software Implementation .................................................................................24 vii 4.4 Results ..............................................................................................................28 5. CONCLUSION AND FUTURE DEVELOPMENT .....................................................33 5.1 Future Development.........................................................................................33 Appendix ............................................................................................................................34 References ..........................................................................................................................51 viii LIST OF TABLES Page 1. Table 2.1.1.1 Token Packets Format……………………………………..........5 2. Table 2.1.2.1 Data Packets Format…………………………………...………. 5 3. Table 2.1.3.1 Handshake Packets Format………………………..........…........ 6 4. Table 2.2.1 USB Pin Description…………………..………………………..... 7 5. Table 2.4.1.1 Device Descriptor Fields………………………………….……. 11 6. Table 2.4.2.1 Configuration Descriptor Fields……………………………….. 12 7. Table 2.4.3.1 Interface Descriptor Fields………………...………….……....... 13 8. Table 2.4.4.1 Endpoint Descriptor Fields……………………..…………........ 14 9. Table 2.4.5.1 String Descriptor Fields…………………..……......................... 15 10. Table 3.2.1 PIC18F4550 Pin Description…………………….......................... 18 11. Table 3.3.1 Various Capacitor and Crystal Combination……...………........... 20 ix LIST OF FIGURES Page 1. Figure 2.1 Tier Star Topology...............................................................................3 2. Figure 2.2.1 USB Type A connector………………………………………........ 6 3. Figure 2.2.2 USB Type B connector……………………………….………….... 6 4. Figure 2.4.1 USB Descriptors…………………………......…….....…................ 10 5. Figure 3.2.1 PIC18F4550 ................................………………………..…........... 17 6. Figure 3.3.1 Oscillator Connection to the PIC18F4550………………………....19 7. Figure 3.4.1 PICKit 2……………………………….....………........................... 21 8. Figure 3.4.2 PICKit 2 Pin Description………………………………………...... 21 9. Figure 4.1.1 Block Diagram of the Design……………………………............... 22 10. Figure 4.3.1.1 Flowchart of Firmware Development............................................26 11. Figure 4.4.1.1 Final Hardware……………………..………………...……......... 28 12. Figure 4.4.2.1 GUI When USB Device Is not Connected…………………….... 29 13. Figure 4.4.2.2 GUI After USB Device Is Connected……………………...….....30 14. Figure 4.4.2.3 GUI After First 3 Tests Are Passed............................................... 31 15. Figure 4.4.2.4 GUI After All The Tests Are Done……………………............... 32 x 1 Chapter 1 INTRODUCTION The focus of this project is to implement USB protocol and read/ write different size packets in the Peripheral Interface Controller (PIC) microcontroller’s memory. Some test cases have been implemented, Single packet write to device Single packet read/write Single packet write, 128 packets read 128 packet write, single packet read Single packet write, timeout on read The project is combination of the software and hardware co-design. The software is implemented using Visual C#. The software part includes Graphical User Interface (GUI) implementation. It gives debugging capabilities. The hardware is implemented using the PIC microcontroller 18F4550, PIC Kit 2, Saronix 20MHz oscillator. The hardware is connected using the USB interface to the computer. Chapter 2 of the report discusses about USB protocol, types of packets in USB protocol. Different USB transfers types and USB descriptors fields are explained in this chapter. Chapter 3 explains different hardware components of the design and also discusses programming of PIC 18F4550 using PICKit 2. 2 Chapter 4 focuses on the hardware implementation of the design. This chapter shows block diagram of the design. It also discusses things need to be checked during hardware implementation. This chapter explains the software development process and PIC18F4550 firmware development. Chapter 5 discusses conclusion of the project and explores future improvements of the project. 3 Chapter 2 UNIVERSAL SERIAL BUS This Chapter discusses USB protocol, types of packets in USB protocol. There are 3 types of packets in the USB protocol. It also discusses different USB transfers types and USB descriptors fields. USB stands for Universal Serial Bus. USB has tiered star topology. This is similar to the 10BaseT Ethernet cable. The tier star topology is shown in Figure 2.1. USB has one central hub controller. This hub controller allows filtering of the different speeds transaction; therefore the low speed devices don’t receive the high or full speed transactions. Up to 127 devices can be connected to a USB bus. Figure 2.1 Tier Star Topology [1] The Universal Serial Bus (USB) has following excellent qualities. That makes it designers first choice. The USB is easy to use. There is no need to configuration and set up. It is fast. It doesn’t become communication bottleneck. The USB is reliable interface. 4 Errors are rare, with automatic retries when errors occur. It is versatile. Many different kinds of peripheral can use the USB.USB is inexpensive. The manufacturers and users don’t have to pay huge price. It is power conserving. Therefore it has been extensively used to save energy and extend battery life in portable computers and devices. USB is supported by both Windows and Mac operating systems. Therefore the developers don’t have to write low level drivers to communicate with the peripherals. 2.1 USB Protocol USB is a host centric bus. The host initiates all transactions. USB transaction is made up of several layers of protocol. USB has defined format for the data transfer. USB controller takes care of the lower level of protocol. The host generates token packet to describe type of transaction, the target device address and endpoint design. After token, host generates the data packet carrying payload. At last it generates the handshaking packet to report if the token and data was received completely. 2.1.1 Token Packets There are 3 types of token packet. In: This informs USB device that host has initiated read transaction. Out: Out informs USB device that host has initiated write transaction. Setup: Setup is used to begin control transfer. 5 Sync PID ADDR ENDP CRC5 EOP Table 2.1.1.1 Token Packets format 2.1.2 Data Packets There are 2 types of Data packets. Each data packet is capable of transferring up to 1024 bytes. 1. Data0 2. Data1 The maximum data payload for the low speed devices is 8 bytes, for full speed devices is 1023 bytes and for the high speed devices is 1024 bytes. Sync PID Data CRC16 EOP Table 2.1.2.1 Data Packets Format 2.1.3 Handshake Packets There are 3 types of handshake packets. The handshake packet contains only PID. ACK: The packet has been received successfully is acknowledged by ACK. NAK: NAK is used to let host that it cannot send or receive data. This situation can be because of the interrupt transactions. STALL: STALL informs host that device requires the host intervention. 6 Sync PID EOP Table 2.1.3.1 Handshake Packets Format 2.2 USB Connector There are two types of connectors, called Type A and Type B.USB connectors have four pins. USB connector pin description is shown in table 2.2.1. Figure 2.2.1 USB Type A connector Type A connector used for the upstream connection and they are usually mounted on the host devices like PC .Figure 2.2.1 shows USB Type A connector Figure 2.2.2 USB Type B connector Type B connector used for the downstream connection and they are usually mounted on the USB devices such as printers, faxes. In this project USB type B connector is used. 7 Pin number Function Color 1 Vbus Red 2 D- White 3 D+ Green 4 Ground Black Table 2.2.1 USB Pin Description 2.3 USB Transfer Types The USB specifies 4 different types of transfers. 2.3.1 Control Transfers The control transfers are used to set up a USB device. All enumeration functions are performed during control transfer. They are all burst transfers. The control transfer packets are initiated by the host. Packet size in of control transfer is 8 bytes for low speed devices, 8,16,32,64 bytes for the high speed devices and 64 bytes for the full speed devices. 2.3.2 Interrupt Transfers Interrupt transfers have guaranteed latency, unidirectional stream pipe and error detection capabilities. Interrupt transfers are non-periodic. The device queues its interrupt requests’ until the host polls for the data. The maximum data payload size is 8 bytes for the low speed devices. Full speed devices have the maximum data payload size of 64 8 bytes. And high speed devices have maximum data payload size of 1024 bytes. There are two types of interrupt transaction. IN: Each time the host polls device it will send IN tokens to device. OUT: Host sends data followed by the OUT token. 2.3.3 Isochronous Transfers Isochronous transfers contain time sensitive information such as video and audio streaming. These transfers occur periodically and continuously. Isochronous transfers have guaranteed bandwidth with bounded latency and error detection. These type of transfers are not supported for the low speed devices, they are only supported by the full and high speed devices. 2.3.4 Bulk Transfer Bulk transfers are used for time insensitive transaction like printing, scanning. The bulk transfers have no guaranteed latency. They provide error detection with 16 CRC field on data. Bulk transfers are schedule after the isochronous transfers and interrupt transfers in USB. They are usually done when the bus doesn’t have any other transfers left to do. The bulk transfers have been used in this project for transferring large amount of data. 2.3.5 Bus Bandwidth Management The bandwidth management on the bus is host’s responsibility. This is done during enumeration. When end point is configured as isochronous or interrupts host sets 9 bandwidth management function. The isochronous transfers and interrupt transfers are called periodic transfers. On the high speed , the periodic transfers get around 90% of bus time. The remaining 10 % time is used by for control transfer. The remaining time is allocated for the bulk transfer. On the full speed bus, the 80 % time is allocated for the periodic transfers. 2.4 USB Descriptors USB descriptors are very important in any USB compatible device. The USB descriptors describe the host information. The host information includes device’s version, how many USB device can be configured on the host, number of endpoints host supports and types of endpoint host supports. All the descriptors have common format. The first field specifies descriptor length, second field defines descriptor type. The host will ignore the descriptor, if the length field is smaller than what is required. If the descriptor length field is longer than what is required than host will remove extra bits. 10 bNumConfigurations bNumberInterfaces Interface Descriptor bNumEndpoints Endpoint Descriptor Configuration Descriptor Endpoint Descriptor bNumConfigurations Same as the other side bNumInterfaces bNumEndpoints bNumEndpoints Endpoint Descriptor Device Descriptor Interface Descriptor bNumEndpoints Endpoint Descriptor Figure 2.4.1 USB Descriptors [3] 2.4.1 Device Descriptors USB devices can have one device descriptor field per device. The device descriptor contains information about the USB version it compiles to, product ID and vendor ID and how many configuration devices can be connected to it. The product ID and vendor ID combination is used to load the appropriate drivers. Table 2.4.1.1 explains various device descriptor fields. 11 Field Offset Field Size Value Description Size of the descriptor in bytes (18 bytes) Device Descriptor(0x01) 0 bLength 1 Number 1 BDescriptortype 1 Constant 2 bcdUSB 2 BCD 4 bDeviceClass 1 Class 5 bDeviceSubClass 1 6 bDeviceProtocol 1 7 bMaxPacketSize 1 8 idVendor 2 10 idProduct 2 12 bcdDevice 2 SubClass Subclass Code (Assigned by USB Org) Protocol Protocol Code (Assigned by USB Org) Number Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64 ID Vendor ID( Assigned by the USB Org) ID Product ID( Assigned by the USB org) BCD Device Release Number 14 iManufacturer 1 Index 15 iProduct 1 Index 16 iSerialNumber 1 Index 17 bNumbConfigurations 1 Integer USB specification number which device complies. Class code Index of Manufacturer String Descriptor Index of Product String Descriptor Index of Serial Number String Descriptor Number of Possible Configurations Table 2.4.1.1 Device Descriptor Fields [3] 2.4.2 Configuration Descriptors The amount of power the particular configuration requires is specified using the configuration descriptor. The configuration field also specifies that device is self or bus powered. During the device enumeration process host read the device configuration 12 descriptor and decides on which configuration to enable. The host enables only one configuration at time for each device. Table 2.4.2.1 explains various configuration descriptor fields. Offset Field Size Value Description 0 bLength 1 Number Size of Descriptor in Bytes 1 bDescriptorType 1 Constant Configuration Descriptor(0x02) 2 wTotalLength 2 Number 4 bNumberInterfaces 1 Number 5 bConfigurationValue 1 Number 6 iConfiguration 1 Index 7 bmAttributes 1 Bitmap 9 bMaxPower 1 mA Total Length in bytes of data returned Number of Interfaces Value to use as an argument to select this configuration Index of String Descriptor describing this configuration D7 Reserved, set to 1. (USB 1.0 Bus Powered) D6 Self Powered D5 Remote Wakeup D4..0 Reserved, set to 0. Maximum Power Consumption in 2mA Units Table 2.4.2.1 Configuration Descriptor Fields [3] 2.4.3 Interface Descriptors The interface descriptors describe a functional group of endpoints that are related to single feature of the device. The device could have more than one interface descriptor enabled at a time, unlike the configuration descriptor where only one configuration descriptor could be enable at any time. For example a device like printer can perform printing, scanning, copying functions. It can give different interface descriptors to all this 13 functions and they all can be enabled at the same time. Table 2.4.3.1 explains various interface descriptor fields. Offset Field Size Value Description 0 bLength 1 Number Size of Description in Bytes (9 bytes) 1 bDescriptionType 1 Constant Interface Descriptor(0x04) 2 bInterfaceNumber 1 Number Number of Interface 3 bAlternateSetting 1 Number Value used to select alternative setting 4 bNumEndpoints 1 Number Number of endpoints used for this interface 5 bInterfaceClass 1 Class Class code ( Assigned by the USB org) 6 bInterfaceSubClass 1 SubClass Subclass Code (Assigned by USB org) 7 bInterfaceProtocol 1 Protocol Protocol Code(Assigned by USB org) 8 iInterface 1 Index Index of String Descriptor Describing this interface Table 2.4.3.1 Interface Descriptor Fields [3] 2.4.4 Endpoint Descriptors The type of transfer, direction, polling interval and the maximum packet size for the each end point is defined by the endpoint descriptor. Endpoint zero is by default for the control endpoint. The endpoint descriptor is configured before any descriptors are requested by the host. The host will use endpoint descriptor information to determine the bandwidth of the bus. Table 2.4.4.1 explains various endpoint descriptor fields. 14 Offset Field Size Value Description 0 bLength 1 Number Size of the Descriptor in Bytes(7 bytes) 1 bDescriptorType 1 Constant Endpoint Descriptor(0x05) 2 bEndpointAddress 1 3 bmAttributes 1 4 wMaxPacketSize 2 Number 6 bInterval 2 Number Endpoint Endpoint Address Bits 0..3b Endpoint Number. Bits 4..6b Reserved. Set to Zero Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints) Bitmap Bits 0..1 Transfer Type 00= Control 01= Isochronous 10 = Bulk 11 = Interrupt Bits 2..7 are reserved. If Isochronous endpoint, Bits 3..2 = Synchronization Type (Iso Mode) 00 = No Synchronization 01 = Asynchronous 10 = Adaptive 11 = Synchronous Bits 5..4 = Usage Type (Iso Mode) 00 = Data Endpoint 01 = Feedback Endpoint 10 = Explicit Feedback Data Endpoint 11 = Reserved Maximum Packet Size this endpoint is capable of sending or receiving Interval for polling endpoint data transfers. Value in frame counts. Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field may range from 1 to 255 for interrupt endpoints. Table 2.4.4.1 Endpoint Descriptor Fields [3] 15 2.4.5 String Descriptors These descriptors provide information to the user. The string descriptor is an optional field. Whenever it is not used it should be specified as 0.Table 2.4.5.1 explains various string descriptor fields Offset Field Size Value Description 0 bLength 1 Size of Descriptor in Bytes 1 bDescriptorType 1 Constant String Descriptor(0x03) 2 wLANGID[0] 2 Number 4 wLANGID[1] 2 Number N wLANGID[x] 2 Number Number Supported Language Code Zero (e.g. 0x0409 English - United States) Supported Language Code One (e.g. 0x0c09 English - Australian) Supported Language Code x (e.g. 0x0407 German - Standard) Table 2.4.5.1 String Descriptor Fields [3] 16 Chapter 3 HARDWARE OVERVIEW This chapter focuses on hardware components such as PIC microcontroller, PIC18F4550 Microcontroller, Saronix oscillator and also discusses programming of PIC 18F4550 using PICKit 2. 3.1 PIC Microcontroller PIC stands for the “Peripheral Interface Controller”. PIC is family of high performance, low cost microcontrollers developed by the Microchip Technology. They are based on the Harvard architecture for microcontrollers. Due to their low cost, wide availability, extensive collection of application notes, availability of free development tools and serial programming capability, they have become the first choice for the developers. PIC microcontroller’s architectures have many features such as small instruction set, RISC architecture, built in oscillator with selectable speeds, easy entry level in circuit programming and debugging kit. 3.2 PIC18F4550 Microcontroller PIC18F4550 is high performance microcontroller at economical price. It has enhanced flash memory as program memory. It is fully compliant to the USB communication module. It supports low speed and full speed USB transactions. It 17 supports control, interrupt, isochronous and bulk transfers. PIC18F4550 can be connected up to 16 bidirectional endpoints.PIC18F4550’s pin diagram is shown in figure 3.2.1. PIC18F4550 chip has 40 pins for connection. It has dual in package and has five input/output ports. Figure 3.2.1 show PIC18F4550 IC. Figure 3.2.1 PIC18F4550 [2] 18 Pin Name Pin Number MCLR/VPP/RE3 1 I/O Description I Master Clear or programming voltage RA0-RA5 2-7 I/O Bidirectional I/O port RE0-RE2 8-10 I/O Bidirectional I/O port. VDD 11,32 Power Positive supply for logic VSS 12,31 Power Ground reference for the logic OSC/CLK1 13 I Oscillator crystal or external clock input OSC2/CLK0 14 O Oscillator crystal or external clock output RC0-PC7 15-17, 23-26 18 I/O Bidirectional I/O port. O Internal USB 3.3 voltage regulator output RD0-RD7 19-22, 27-30 I/O Bidirectional I/O port or Streaming Parallel Port (SPP) RB0-RB7 33-40 I/O Bidirectional I/O port. PORT B can be software programmed for the internal weak pull ups on the inputs VUSB Table 3.2.1 PIC18F4550 Pin Description [2] 3.3 Oscillator The PIC18F4550 device can be operated in twelve different oscillator modes. In HS, HSPLL, XT and XTPLL oscillator modes, a crystal is connected to the OSC1 and OSC2 pins to establish oscillation. Table 3.3.1 provides various capacitor and crystal combinations for design. An internal postscaler allow users to select a clock frequency other than that of the crystal. The frequency division is determined by the CPUDIV 19 configuration bits. Users may select a clock frequency of the oscillator frequency or 1/2, 1/3 or 1/4 of the oscillator frequency. An external clock may be used when the microcontroller is in HS mode. In this case the OSC2 pin is left open. Figure 3.3.1 shows the crystal connection with the PIC microcontroller. Figure 3.3.1 Oscillator Connection to the PIC18F4550 [2] When the PIC18F4550 is used for the USB connectivity, it must have either 6 MHz or 48MHz clock for USB operation, depending on whether Low-speed or Full speed mode is being used. Because of the unique requirements of the USB module must be clocked using the primary clock source. The USB module, in either mode can run asynchronously with respect to the microcontroller core and other peripherals. This means that the USB module can runs on the primary oscillator and the other application can use different clock frequency at lower speed. If require to run entire application from only one clock source, full speed provides a greater selection of the microcontroller frequencies. 20 Crystal frequency Capacitor C1 Value Capacitor C2 Value 4 MHz 27 pF 27 pF 8 MHz 22 pF 22 pF 20 MHz 15 pF 15 pF Table 3.3.1 Various Capacitor and Crystal Combination [2] In our design we are using 20 MHz Saronix oscillator. The oscillator has 4 pins such as ground, output, Vcc and N/C. 3.4 PICKit 2 PICKit 2 is low cost PIC microcontroller programmer device. It is capable of programming most of Microchip’s flash microcontroller. The Status LEDs indicate the status. Power (green): Power is applied to the PICKit 2 microcontroller programmer via USB port. Target (yellow): The PICKIt2 microcontroller programmer is powering the target device. Busy (red): The PICKit 2 microcontroller programmer is busy with a function. The Push button is used for initiating a function that will be implemented in near future. 21 Figure 3.4.1 PICKit 2 [5] PICKit 2 has 6 pins. These pins connect programmer to the microcontroller device. The power to the programmer device is supplied using the USB port. The USB port connection is a USB `mini-B connector. Connect the PICKit 2 microcontroller programmer to the PC using the USB cable. Figure 3.4.2 shows pin description of the PICKit 2. Figure 3.4.2 PICKit 2 Pin Description [5] 22 Chapter 4 DESIGN IMPLEMENTATION AND FINAL RESULTS This chapter focuses on the hardware implementation of the design. This chapter explains block diagram of the design. It also discusses things need to be checked during hardware implementation, software development process and PIC18F4550 firmware development. 4.1 Block Diagram of the Design Figure 4.1.1 Block Diagram of the Design 23 4.2 Hardware Implementation To implement the PIC18F4550 based USB storage, the components such as breadboard, PIC18F4550 microcontroller IC, PICKit 2 programmer, Saronix 20 MHz oscillator, USB type B connector, 4 LEDs, registers, capacitors and wires are required. All these components are connected as per the block diagram in the Figure 4.1.1. The Microchip PIC18F4550 microcontroller is used in the design. It has in built circuit programmer (ICSP). The microcontroller is programmed using the PICKit 2 programmer. In the design Saronix 20 MHz crystal is used for the clocking the circuit. Two 20 pF capacitors are connected to stabilize output of the oscillator. Two 100 pF capacitors are connected to VSS and VCC. These capacitors are used as protection for the circuit against sudden power supply swings. The circuit is USB bus powered. It draws required voltage supply from the USB bus itself. Therefor it doesn’t require external power supply for operation. One 470pF capacitor is connected to the VBUS pin of the microcontroller. This capacitor regulates the voltage supplied by the USB bus. USB type B connector is used to connect the circuit to the computer. This connector has four pins, supply, ground, data in and data out. 4 LEDs are also used to check the status of the circuit. The first LED indicates the circuit is ready for the communication. The second LED blinks when the device is successfully enumerated on the host. The third LED indicates commands are correctly processed. The fourth LED indicates failure in communication. 24 After mounting all the components on the breadboard, the circuit is checked for connectivity using the buzzer to makes sure there is no loose connection between components. All pin connections of PIC18F4550 microcontroller are checked. The wrong pin connections can severely damage the circuit and lots of designer time could be wasted in debugging circuit. The oscillator connection is double checked because that is one of the most important parts of the circuit. The microcontroller won’t work without the clock. Connection for the USB type B connector also checked. Once all the connections are checked, device is connected to computer using the USB cable. 4.3 Software Implementation The software implementation part can be divided in PIC18F4550 firmware development and C# Graphical User Interface (GUI) development. 4.3.1 Firmware development The firmware is based on the Microchip USB stack. The main file (main.c) is shown in the appendix. All the transactions in the project are implemented as bulk data transfers. Figure 4.3.1.1 shows flowchart of the firmware development. In the firmware I have implemented various commands for the different test cases. These commands are implemented in the processIO function as shown Figure 4.3.1.1 Test-1: “The single packet write to device” has been implemented by command 0x80.This command receives a single command and data packet 25 from the host. It contains the command byte and then the number 1-63 in the remaining bytes. Test 2: “The single packet read/write” is implemented by command 0x81.The firmware generates return packet and passes it back to the host. Test 3: “The single packet write and 128 packet read” is implemented with the command 0x82. This command receives a command from the host following 128 64 byte packet containing data. In this the host is bulk transferring data to the USB device. Test 4: “The 128 packet write and single packet read” is implemented using the command 0x83.This command receives a command from the host followed by the 128 64 bytes packet containing data. In this command the device is bulk transferring data to the host. Test 5: “The single packet write and time out on read” is implemented using the 0x84 command. This commands implementation is different than the other command implementation. On the host side it simulates failure scenario when device doesn’t respond to command. This is useful for the testing the Visual C# GUI. 26 Include header files Configure the 18F4550 Fuse Success indicator Global Variable Failure indicator Global Variable Declare the Variable required for the keeping track a bulk receive command Declare the Variables required for the keeping track of a bulk send command Main Function Main() Process input and output ProcessIO() Intialize system InitializeSystem() Figure 4.3.1.1 Flowchart of Firmware Development 27 4.3.2 Graphic User Interface Development The GUI is developed using the Visual C#. It uses the C# class library to communicate with the PIC18F4550 firmware. It provides a simple five tests. It allows user to choose between the different test options. The application implements commands and data to send device. It also interprets the data and responses received from the device firmware as an acknowledgement. The Visual C# class library provides USB device ‘events’. It will let application know when the USB device is connected and disconnected from the host. The GUI window will show “device attached” when USB device is connected and “device detached” when the USB device is disconnected from. And also the C# USB device events disable the application buttons when no device is found on the host. The tests in GUI window correspond to the five commands implemented in the firmware. When you click a test button on the GUI, the command is sent to the firmware. Then both the host and firmware respond with the result of the command. If the command has passed through successfully than GUI will show “test passed" otherwise it will show “test failed”. The application is built on the C# USB generic Human Interface Device (HID) class library. This HID class library provides the base classes for the application building. The application defines a custom class for its own device. This class inherits all the functions from the base-class. Then it extends base-class to include its own custom 28 methods for communicating with the device. In this project, custom class has interface from the commands such as 0x80, 0x81, 0x82, 0x83, and 0x84. 4.4 Results This section discusses final hardware and software implementation results. 4.4.1 Hardware implementation Results Figure 4.4.1.1 shows picture of final hardware. It has been mounted on the breadboard. It is connected to the computer via USB. Figure 4.4.1.1 Final Hardware 29 4.4.2 Software Implementation Results This section shows GUI after different test cases has been applied. Figure 4.4.2.1 shows GUI when there is no device connected. At the bottom right corner, GUI shows “USB Device Status Unknown”. Figure 4.4.2.1 GUI When USB Device Is not Connected 30 Figure 4.4.2.2 shows GUI after, USB device is detected on the personal computer. At the bottom right corner, GUI shows “USB Device is attached”. Figure 4.4.2.2 GUI After USB Device Is Connected 31 Figure 4.4.2.3 shows GUI after, first three tests are successfully done. It also displays first 3 test as passed and rest as test not performed. Figure 4.4.2.3 GUI After First 3 Tests Are Passed 32 Figure 4.4.2.4 displays GUI after, the test 5 is done. Test 5 disconnects the USB on the PC. At bottom right corner, it shows “USB device is detached”. The buttons will be deactivated. Figure 4.4.2.4 GUI After All The Tests Are Done 33 Chapter 5 CONCLUSION AND FUTURE DEVELOPMENT The project has successfully achieved its goal of communicating with the computer and reading and writing bytes of data using USB interface. In the project five different test cases have been tested. Single packet write to device Single packet read/write Single packet write, 128 packets read 128 packet write, single packet read Single packet write, timeout on read The implantation of the USB device was very good learning experience for me. I have understood USB protocol, how to implement firmware for the PIC microcontroller and how to design GUI in Visual C#. 5.1 Future Development: USB is very popular serial bus. PIC microcontroller has USB 2.0 built in. That’s an advantage for the PIC18F4550 Microcontroller. Variety of different applications can be developed using wonderful features of the PIC18F4550. As during project we have developed a C# GUI, different graphic user interface can also be developed for those applications. 34 APPENDIX #ifndef MAIN_C #define MAIN_C //Global includes #include <htc.h> // Local includes #include "usb.h" #include "HardwareProfile.h" #include "usb_function_hid.h" #include "genericHID.h" #include "debug.h" // Ensure we have the correct target PIC device family #if !defined(__18F4550) #error "This firmware only supports either the PIC18F4550” #endif // PIC18F4550 fuse configuration // Config word 1 (Oscillator configuration) // 20Mhz crystal input scaled to 48Mhz and configured for USB operation __CONFIG(1, USBPLL & IESODIS & FCMDIS & HSPLL & CPUDIV1 & PLLDIV5); // Config word 2 __CONFIG(2, VREGEN & PWRTDIS & BOREN& BORV20 & WDTDIS & WDTPS32K); // Config word 3 35 __CONFIG(3, PBDIGITAL & LPT1DIS & MCLREN); // Config word 4 __CONFIG(4, XINSTDIS & STVREN & LVPDIS & ICPORTDIS & DEBUGDIS); // Config word 5, 6 and 7 (protection configuration) __CONFIG(5, UNPROTECT); __CONFIG(6, UNPROTECT); __CONFIG(7, UNPROTECT); // Globals // Success indication globals (used to keep the success LED on so you can see it) long intsuccessIndicatorCounter = 0; unsigned char successIndicatorFlag = FALSE; // Failure indication globals (used to keep the failure LED on so you can see it) long intfailureIndicatorCounter = 0; unsigned char failureIndicatorFlag = FALSE; // Variables required for keeping track of a bulk receive command unsigned char bulkReceiveFlag = FALSE; intbulkReceivePacketCounter = 0; intbulkReceiveExpectedPackets = 0; // Variables required for keeping track of a bulk send command unsigned char bulkSendFlag = FALSE; intbulkSendPacketCounter = 0; intbulkSendExpectedPackets = 0; 36 // Initialize system static void InitialiseSystem(void) { // PIC port set up -------------------------------------------------------- // Default all pins to digital ADCON1 = 0x0F; // Configure ports as inputs (1) or outputs(0) TRISA = 0b00000000; TRISB = 0b00000000; TRISC = 0b00000000; #if defined(__18F4550) TRISD = 0b00000000; TRISE = 0b00000000; #endif // Clear all ports PORTA = 0b00000000; PORTB = 0b00000000; PORTC = 0b00000000; #if defined(__18F4550) PORTD = 0b00000000; PORTE = 0b00000000; #endif 37 // USB set up ------------------------------------------------------------- // USB stack and parameter initialization #if defined(USE_SELF_POWER_SENSE_IO) tris_self_power = INPUT_PIN; #endif // Initialize the variable holding the handle for the last // transmission USBOutHandle = 0; USBInHandle = 0; // Call the stack initialisation functions USBDeviceInit(); } // Process input and output void ProcessIO(void) { // If we are not in the configured state just return if((USBDeviceState< CONFIGURED_STATE)||(USBSuspendControl==1)) { // We are not configured, set LED1 to off to show status LED1 = OFF; 38 return; } // We are configured, show state in LED1 LED1 = ON; // Check to see if the success indicator is on and update the delay counter if (successIndicatorFlag == TRUE) { LED2 = ON; successIndicatorCounter++; if (successIndicatorCounter == 20000) { LED2 = OFF; successIndicatorCounter = 0; successIndicatorFlag = FALSE; } } // Check to see if the failure indicator is on and update the delay counter if (failureIndicatorFlag == TRUE) { LED3 = ON; failureIndicatorCounter++; if (failureIndicatorCounter == 80000) { 39 LED3 = OFF; failureIndicatorCounter = 0; failureIndicatorFlag = FALSE; } } // Note: For all tests we expect to receive a 64 byte packet containing // the command in byte[0] and then the numbers 0-62 in bytes 1-63. unsigned charbufferPointer; unsigned char expectedData; unsigned char dataReceivedOk; unsigned char dataSentOk; // Check if data was received from the host. if(!HIDRxHandleBusy(USBOutHandle)) { // Test to see if we are in bulk send/receieve mode, or if we are waiting for a command if (bulkSendFlag == TRUE || bulkReceiveFlag == TRUE) { // We are either bulk sending or receieving // If we are bulk sending, check that we are not busy and send the next packet if (bulkSendFlag == TRUE && !HIDTxHandleBusy(USBInHandle)) { 40 // Send the next packet expectedData = bulkSendPacketCounter; for (bufferPointer = 0; bufferPointer< 64; bufferPointer++) { ToSendDataBuffer[bufferPointer] = expectedData; } // Transmit the response to the host USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64); // Add this following delay in if you want to simulate a slow transfer // from a busy PIC when testing bulk sends: // for (long int counter = 0; counter < 1000; counter++) __delay_us(100); bulkSendPacketCounter++; // Next packet // Are we done yet? if (bulkSendPacketCounter == bulkSendExpectedPackets) { // All done, indicate success and go back to command mode bulkSendFlag = FALSE; successIndicatorFlag = TRUE; } } 41 // If we are bulk receiving get the next packet if (bulkReceiveFlag == TRUE) { // The received data buffer is already filled by the USB stack // we just have to confirm the data integrity expectedData = bulkReceivePacketCounter; for (bufferPointer = 0; bufferPointer< 64; bufferPointer++) { // If the data isn't what we expected, turn on the failure light if (ReceivedDataBuffer[bufferPointer] != expectedData) failureIndicatorFlag = TRUE; } bulkReceivePacketCounter++; // Are we done yet? if (bulkReceivePacketCounter == bulkReceiveExpectedPackets) { // All done, indicate success and go back to command mode bulkReceiveFlag = FALSE; successIndicatorFlag = TRUE; } } } 42 else { // Command mode switch(ReceivedDataBuffer[0]) { // Debug information request from host case 0x10: // Copy any waiting debug text to the send data buffer copyDebugToSendBuffer(); // Transmit the response to the host if(!HIDTxHandleBusy(USBInHandle)) { USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64); } break; // Place application specific commands here: // Test 1 - Single packet write to device case 0x80: debugOut("Received command 0x80 from host"); // Test the receieved data expectedData = 0; dataReceivedOk = TRUE; 43 for (bufferPointer = 1; bufferPointer< 64; bufferPointer++) { if (ReceivedDataBuffer[bufferPointer] != expectedData) dataReceivedOk = FALSE; expectedData++; } // Display the test result if (dataReceivedOk == TRUE) { successIndicatorFlag = TRUE; debugOut("Successfully received 63 bytes of data from command 0x80"); } else { failureIndicatorFlag = TRUE; debugOut("Failed to receive 63 bytes of data from command 0x80"); } break; // Test 2 - Single packet read/write case 0x81: debugOut("Received command 0x81 from host"); // Test the receieved data 44 expectedData = 0; dataReceivedOk = TRUE; for (bufferPointer = 1; bufferPointer< 64; bufferPointer++) { if (ReceivedDataBuffer[bufferPointer] != expectedData) dataReceivedOk = FALSE; expectedData++; } // If we got the data correctly, send the response packet if (dataReceivedOk == TRUE) { debugOut("Successfully received 63 bytes of data from command 0x81"); expectedData = 0; dataSentOk = TRUE; for (bufferPointer = 0; bufferPointer< 64; bufferPointer++) { ToSendDataBuffer[bufferPointer] = expectedData; expectedData++; } // Transmit the response to the host if(!HIDTxHandleBusy(USBInHandle)) { 45 USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64); } debugOut("Sent 64 bytes of data to the host from command 0x81"); // Show our success successIndicatorFlag = TRUE; } else { failureIndicatorFlag = TRUE; debugOut("Failed to receive 63 bytes of data from command 0x81"); } break; // Test 3 - Single packet write, 128 packets read case 0x82: debugOut("Received command 0x82 from host"); // Test the receieved data expectedData = 0; dataReceivedOk = TRUE; for (bufferPointer = 1; bufferPointer< 64; bufferPointer++) { if (ReceivedDataBuffer[bufferPointer] != expectedData) 46 dataReceivedOk = FALSE; expectedData++; } // If the receive was ok, go into bulk sending mode if (dataReceivedOk == TRUE) { debugOut("Successfully received 63 bytes of data from command 0x82, now bulk sending"); // Go into bulk sending mode... bulkSendExpectedPackets = 128; bulkSendFlag = TRUE; bulkSendPacketCounter = 0; } else { failureIndicatorFlag = TRUE; debugOut("Failed to receive 63 bytes of data from command 0x82"); } break; // Test 4 - 128 packets write, single packet read case 0x83: 47 debugOut("Received command 0x83 from host"); // Test the receieved data expectedData = 0; dataReceivedOk = TRUE; for (bufferPointer = 1; bufferPointer< 64; bufferPointer++) { if (ReceivedDataBuffer[bufferPointer] != expectedData) dataReceivedOk = FALSE; expectedData++; } // If the receive was ok, go into bulk receiving mode if (dataReceivedOk == TRUE) { debugOut("Successfully received 63 bytes of data from command 0x83, now bulk sending"); // Go into bulk sending mode... bulkReceiveExpectedPackets = 127; bulkReceiveFlag = TRUE; bulkReceivePacketCounter = 0; } else failureIndicatorFlag = TRUE; 48 break; // Test 5 - Single Packet write, timeout on read case 0x84: debugOut("Received command 0x84 from host"); // Here we receive a command which expects a reply, but we // deliberately don't send one to test the timeout mechanisms // in the communication class // Test the receieved data expectedData = 0; dataReceivedOk = TRUE; for (bufferPointer = 1; bufferPointer< 64; bufferPointer++) { if (ReceivedDataBuffer[bufferPointer] != expectedData) dataReceivedOk = FALSE; expectedData++; } // Display the test result if (dataReceivedOk == TRUE) successIndicatorFlag = TRUE; else failureIndicatorFlag = TRUE; // Now we quit without replying break; default: // Unknown command received 49 break; } } // Only rearm the OUT endpoint if we are not bulk sending if (bulkSendFlag == FALSE) { // Re-arm the OUT endpoint for the next packet USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64); } } } // Main function void main(void) { // Initialise the microcontroller InitialiseSystem(); // Initialise the debug log functions debugInitialise(); // Show that we are up and running LED0 = 1; debugOut("USB Generic firmware started"); 50 debugOut("USB Device Initialised..."); while(1) { // Check bus status and service USB interrupts USBDeviceTasks(); // Application-specific tasks ProcessIO(); } } #endif 51 REFERENCES [1] Craig Peacock, “USB in a nutShell”, Release 4th edition, September 2010 [2] Microchip Techonology, “PIC18F2455/2550/4455/4550 Data Sheet”, Version C Document Number DS39632 [3] Don Anderson,”USB System Architecture”, MindShare, Inc, 1997 [4] Jan Axelson, “USB Mass Storage: Designing and Programming Device and Embedded Hosts”, Lakeview Research (September 1, 2006) [5] Microchip Technology “PICKit. 2 Programmer/Debugger User’s Guide”, Document Number DS51553E, 2008 [6] Technical Data, “Saronix Crystal Clock Oscillator”, Document Number DS-183. Revision C