Austin Schuh | 41baf20 | 2022-01-01 14:33:40 -0800 | [diff] [blame^] | 1 | *************** |
| 2 | Getting Started |
| 3 | *************** |
| 4 | |
| 5 | Add TinyUSB to your project |
| 6 | --------------------------- |
| 7 | |
| 8 | It is relatively simple to incorporate tinyusb to your (existing) project |
| 9 | |
| 10 | |
| 11 | * Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is *your_project/tinyusb* |
| 12 | * Add all the .c in the ``tinyusb/src`` folder to your project |
| 13 | * Add *your_project/tinyusb/src* to your include path. Also make sure your current include path also contains the configuration file tusb_config.h. |
| 14 | * Make sure all required macros are all defined properly in tusb_config.h (configure file in demo application is sufficient, but you need to add a few more such as CFG_TUSB_MCU, CFG_TUSB_OS since they are passed by IDE/compiler to maintain a unique configure for all boards). |
| 15 | * If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud descriptor** callbacks for the stack to work. |
| 16 | * Add tusb_init() call to your reset initialization code. |
| 17 | * Call ``tud_int_handler()`` (device) and/or ``tuh_int_handler()`` (host) in your USB IRQ Handler |
| 18 | * Implement all enabled classes's callbacks. |
| 19 | * If you don't use any RTOSes at all, you need to continuously and/or periodically call tud_task()/tuh_task() function. All of the callbacks and functionality are handled and invoked within the call of that task runner. |
| 20 | |
| 21 | .. code-block:: |
| 22 | |
| 23 | int main(void) |
| 24 | { |
| 25 | your_init_code(); |
| 26 | tusb_init(); // initialize tinyusb stack |
| 27 | |
| 28 | while(1) // the mainloop |
| 29 | { |
| 30 | your_application_code(); |
| 31 | |
| 32 | tud_task(); // device task |
| 33 | tuh_task(); // host task |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | Examples |
| 38 | -------- |
| 39 | |
| 40 | For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API() should be used. Most examples will work on most of `the supported Boards <boards.md>`_. Firstly we need to ``git clone`` if not already |
| 41 | |
| 42 | .. code-block:: |
| 43 | |
| 44 | $ git clone https://github.com/hathach/tinyusb tinyusb |
| 45 | $ cd tinyusb |
| 46 | |
| 47 | Some TinyUSB examples also requires external submodule libraries in ``/lib`` such as FreeRTOS, Lightweight IP to build. Run following command to fetch them |
| 48 | |
| 49 | .. code-block:: |
| 50 | |
| 51 | $ git submodule update --init lib |
| 52 | |
| 53 | In addition, MCU driver submodule is also needed to provide low-level MCU peripheral's driver. Luckily, it will be fetched if needed when you run the ``make`` to build your board. |
| 54 | |
| 55 | Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``/examples/device/99-tinyusb.rules`` file to /etc/udev/rules.d/ then run ``sudo udevadm control --reload-rules && sudo udevadm trigger`` is good enough. |
| 56 | |
| 57 | Build |
| 58 | ^^^^^ |
| 59 | |
| 60 | To build example, first change directory to an example folder. |
| 61 | |
| 62 | .. code-block:: |
| 63 | |
| 64 | $ cd examples/device/cdc_msc |
| 65 | |
| 66 | Then compile with ``make BOARD=[board_name] all``\ , for example |
| 67 | |
| 68 | .. code-block:: |
| 69 | |
| 70 | $ make BOARD=feather_nrf52840_express all |
| 71 | |
| 72 | Note: ``BOARD`` can be found as directory name in ``hw/bsp``\ , either in its family/boards or directly under bsp (no family). |
| 73 | |
| 74 | Port Selection |
| 75 | ~~~~~~~~~~~~~~ |
| 76 | |
| 77 | If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``PORT=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use: |
| 78 | |
| 79 | .. code-block:: |
| 80 | |
| 81 | $ make BOARD=stm32f746disco PORT=1 all |
| 82 | |
| 83 | Port Speed |
| 84 | ~~~~~~~~~~ |
| 85 | |
| 86 | A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``SPEED=full/high`` e.g To force F723 operate at full instead of default high speed |
| 87 | |
| 88 | .. code-block:: |
| 89 | |
| 90 | $ make BOARD=stm32f746disco SPEED=full all |
| 91 | |
| 92 | Size Analysis |
| 93 | ~~~~~~~~~~~~~ |
| 94 | |
| 95 | First install `linkermap tool <https://github.com/hathach/linkermap>`_ then ``linkermap`` target can be used to analyze code size. You may want to compile with ``NO_LTO=1`` since -flto merges code across .o files and make it difficult to analyze. |
| 96 | |
| 97 | .. code-block:: |
| 98 | |
| 99 | $ make BOARD=feather_nrf52840_express NO_LTO=1 all linkermap |
| 100 | |
| 101 | Debug |
| 102 | ^^^^^ |
| 103 | |
| 104 | To compile for debugging add ``DEBUG=1``\ , for example |
| 105 | |
| 106 | .. code-block:: |
| 107 | |
| 108 | $ make BOARD=feather_nrf52840_express DEBUG=1 all |
| 109 | |
| 110 | Log |
| 111 | ~~~ |
| 112 | |
| 113 | Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet. |
| 114 | |
| 115 | .. code-block:: |
| 116 | |
| 117 | $ make BOARD=feather_nrf52840_express LOG=2 all |
| 118 | |
| 119 | Logger |
| 120 | ~~~~~~ |
| 121 | |
| 122 | By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols: |
| 123 | |
| 124 | |
| 125 | * `LOGGER=rtt`: use `Segger RTT protocol <https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/>`_ |
| 126 | |
| 127 | * Cons: requires jlink as the debugger. |
| 128 | * Pros: work with most if not all MCUs |
| 129 | * Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package. |
| 130 | |
| 131 | * ``LOGGER=swo``\ : Use dedicated SWO pin of ARM Cortex SWD debug header. |
| 132 | |
| 133 | * Cons: only work with ARM Cortex MCUs minus M0 |
| 134 | * Pros: should be compatible with more debugger that support SWO. |
| 135 | * Software viewer should be provided along with your debugger driver. |
| 136 | |
| 137 | .. code-block:: |
| 138 | |
| 139 | $ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all |
| 140 | $ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all |
| 141 | |
| 142 | Flash |
| 143 | ^^^^^ |
| 144 | |
| 145 | ``flash`` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command |
| 146 | |
| 147 | .. code-block:: |
| 148 | |
| 149 | $ make BOARD=feather_nrf52840_express flash |
| 150 | $ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash |
| 151 | |
| 152 | Since jlink can be used with most of the boards, there is also ``flash-jlink`` target for your convenience. |
| 153 | |
| 154 | .. code-block:: |
| 155 | |
| 156 | $ make BOARD=feather_nrf52840_express flash-jlink |
| 157 | |
| 158 | Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with ``uf2`` target |
| 159 | |
| 160 | .. code-block:: |
| 161 | |
| 162 | $ make BOARD=feather_nrf52840_express all uf2 |
| 163 | |
| 164 | IAR Support |
| 165 | ^^^^^^^^^^^ |
| 166 | |
| 167 | IAR Project Connection files are provided to import TinyUSB stack into your project. |
| 168 | |
| 169 | * A buldable project of your MCU need to be created in advance. |
| 170 | |
| 171 | |
| 172 | * Take example of STM32F0: |
| 173 | |
| 174 | - You need `stm32l0xx.h`, `startup_stm32f0xx.s`, `system_stm32f0xx.c`. |
| 175 | |
| 176 | - `STM32L0xx_HAL_Driver` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs. |
| 177 | |
| 178 | * Open `Tools -> Configure Custom Argument Variables` (Switch to `Global` tab if you want to do it for all your projects) |
| 179 | Click `New Group ...`, name it to `TUSB`, Click `Add Variable ...`, name it to `TUSB_DIR`, change it's value to the path of your TinyUSB stack, |
| 180 | for example `C:\\tinyusb` |
| 181 | |
| 182 | Import stack only |
| 183 | ~~~~~~~~~~~~~~~~~ |
| 184 | |
| 185 | 1. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\tools\\iar_template.ipcf`. |
| 186 | |
| 187 | Run examples |
| 188 | ~~~~~~~~~~~~ |
| 189 | |
| 190 | 1. (Python3 is needed) Run `iar_gen.py` to generate .ipcf files of examples: |
| 191 | |
| 192 | .. code-block:: |
| 193 | |
| 194 | cd C:\tinyusb\tools |
| 195 | python iar_gen.py |
| 196 | |
| 197 | 2. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\examples\\(.ipcf of example)`. |
| 198 | For example `C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf` |