The reference firmware is used to:
initialize the USB FX2 microcontroller register, memory, etc..;
enter in infinite loop (aka super-loop) that manage incoming USB setup data packet and conect the TE USB FX2 module (both FX2 microcontroller and FPGA's MicroBlaze) with host computer's software though USB;
In the following table is described the tasks executed by the reference firmware (Trenz Electronic v3.02).
step | pseudocode function | description |
---|---|---|
1 | interrupt_disable(); //EA=0 | Disable interrupts |
2 | setup_autovectors (); | Setup interrupt table |
3 | usb_install_handlers (); | Setup/install handlers (aka functions) called to manage the interrupt set in interrupt table |
4 | interrupt_enable(); //EA=1 | Enable interrupts |
5 | fx2_renumerate(); | Simulates disconnection and then reconnection of TE USB FX2 module USB cable with host computer |
6 | task0(); //system_init(); | Initialization phase. The reference firmware is used to:
Step 1,2,3,4,5 can be called pre_task0() or pre_system_init(). |
7 | while(1) { | Enter the superloop |
8 | task1(); | Manage incoming USB setup data packet. See here. It is used in connection and disconnection (of TE USB FX2 module) phases from . |
9 | task2(); | Manage incoming USB data packet conforming to TE (FW) API It is used:
from host computer's software though USB. The previous activities are realized by
|
10 | task3(); | Manage interrupt request (INT0 pin) incoming from FPGA chip (normally, FPGA's MicroBlaze soft-processor): used with (some) MB Command |
11 | } | While running the FX2 microcontroller should never exit from the superloop and repeat (until a reset) step 8,9 and 10 |
In this super loop ("while(1)") reference firmware is used to:
Task 1 is realized by
if(usb_setup_packet_avail()) usb_handle_setup_packet();
Task 2 is realized by
void ep1_pool(void)
Task 3 is realized by
void int_pin_pool(void)
Task 2 and task 3 are grouped in a single function called activity() running in the superloop of fw.c;
void activity(void){ ep1_pool(); int_pin_pool(); }
Handles the setup package and the basic device requests like reading descriptors, get/set configuration etc. It is used in phase of connection/disconnection of the TE USB FX2 module from host computer's USB port. It is also used by CyControl, CyConsole (and other similar programs) to retrieve information about the configuration of the USB device (TE USB FX2 module view as USB device).
See this link for further explanations.
At this moment (Trenz Electronic v3.02), this part of code does not calls the app_class_cmd or app_vendor_cmd functions when needed, because CLASS command and VENDOR commands are not supported.
This process is realized by function ep1_pool().
This function pull 64 bytes from EP1OUTBUF FIFO; in this FIFO are stored possible host computer's SW sent by through USB connection.
EP1OUTBUF[0] and EP1OUTBUF[1:63] are written by host computer's software
or or libusb(x) C libusb_bulk_transfer(usbDeviceHandle, LIBUSB_ENDPOINT_OUT | 1, command, x, &actual_length, 1000) used with command[0] =ep1_pool() function uses a switch construct (EP1OUTBUF[0] decoded as
) to select the proper code (calling other functions,if any) to execute the task requested by the decoded .
Test data for internal test; if (in the EP1 OUT FIFO exist at least one USB command packet not yet readed) { Increment command count; Fill output buffer EP1INBUF with 0xFF value; switch(EPOUTBUF[0]) //Decode USB FX2 API Command correponding to received EPOUTBUF[0] default: // EPOUTBUF[0] different from any USB FX2 API encoded value Code to execute if EPOUTBUF[0] does not equal the value of any of the cases break; Â ... case USB_FX2_API_0xYZ: // EPOUTBUF[0] = USB_FX2_API_0xYZ , USB_FX2_API encoded value hexadecimal YZ Run the correspoding code snippet/function with auxiliary functions (if any) Write the reply (if any) in EP1INBUF Set a flag_new_data to indicate that a USB reply packet could be delivered to host computer's USB break; ... Free input buffer; if (flag_new_data = 1) //Check the flag to know if a USB reply packet should be delivered to host computer's USB { if(it is possible to send the USB reply packet using EP1) { Send the USB reply packet using EP1 Reset the flag flag_new_data to indicate that a USB reply packet has been delivered to host computer's USB //the buffer is free for use } } }
If
the FX2 microcontroller pull (using I2C in int_pin_pool()) x (x defined by EP1OUTBUF[2]) number of bytes from y I2C address (y defined by EP1OUTBUF[1]).
The host computer's SW should use a polling procedure to retrieve the I2C bytes read (and stored) by FX2 microcontroller (the pull response to host computer's pull is realized by task2: ep1_pool())
If
the FX2 microcontroller firmware reads (using I2C) a maximum of 32 byte (in the firmware a maximum of 12 is preconfigured but it could be overwritten by a host software FX2_API_Command SET_INTERRUPT => CMD_SET_AUTORESPONSE => iar_adress = EP1OUTBUF[1]; iar_count = EP1OUTBUF[2];) from an I2C address.
The I2C bytes data are copied in the byte array auto_response_data by the int_pin_pool() firmware function.
This byte array coul be pulled out by host computer'SW using SET_INTERRUPT ( => CMD_GET_AUTORESPONSE => for(i = 0; i < 32; i++) EP1INBUF[i+1] = auto_response_data[i];).
It is usually used with XPS_I2C_SLAVE custom IP block (LINK) for command, settings and status communication. When MicroBlaze write data to MB2FX2_REG0, the interrupt pin INT0 (aka FPGA_INT0 in firmware files) is rised. This pin is connected to PA0/INT0 pin of FX2 microcontroller. When the FX2 microcontroller's firmware read the rise of pin INT0 (=1 because MicroBlaze writes data to MB2FX2_REG0) it set the firmware variable FPGA_INT0 to 1.
If
the FX2 microcontroller firmware reads (using I2C) all MB2FX2 registers (12 bytes).
The registers value are copied in the byte array auto_response_data by the int_pin_pool() firmware function.
This byte array could be pulled out by host computer's SW using SET_INTERRUPT ( => CMD_GET_AUTORESPONSE => for(i = 0; i < 32; i++) EP1INBUF[i+1] = auto_response_data[i];).