RP2040の2つのコアを使い分ける
こんにちは、リゲル・インテリジェンスです。
RP2040へのUSBマスストレージクラス=FAT12ドライブの実装は目処が立ちましたので、PICマイコン用の「.hex」ファイルがドライブへ書き込まれたことを検出するために、Root directory entry=Block3への書込み発生をトリガにします。「.hex」ファイルの書込み先がルートディレクトリへ限定されますが、実用上の問題は無いでしょう。
まずは試しにRoot directory entryへ書込みがあったら、全ドライブ領域のデータダンプをUART上へ行うようにプログラムを組んでみました。
PANICで停止しました。最後のメッセージはTiny USBからで、end pointを掴みっぱなし、もしくは無反応のためと推測します。UARTへのデータダンプに時間がかかり、その間プロセッサがマスストレージ側の処理が出来なくなったためでしょう。PICマイコンへのプログラム書込みの際にも同様のことが発生する可能性があります。
問題回避のためにOSを導入してタスク管理をする方法もありますが(Tiny USBではfreeRTOSをサポートしているexampleもあります)、RP2040は折角Cortex M0+を2個持っていますので少々贅沢な気はしますが
- Core0:Tiny USB(マスストレージ)関連の処理=ホストPC処理
- Core1:PICマイコン書込み関連の処理
と分けて担当させればOS無しでもスムースに動くでしょう。core1_main.cを追加し、main.cとCMakeLists.txtを修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
//****************************************************************************** //* main_core1.c : test program for RP2040 core1 with using Tiny USB on core0. * //* * //* usage: * //* This program is running on CPU core-1 to avoid unexpected wait for USB. * //* * //* * //* history: * //* Sep16,2022 start coding. N.Mato * //* * //* Copyright(c)2022 Rigel Intelligence * //****************************************************************************** //*** includes ***************************************************************** #include <stdio.h> #include "pico/stdlib.h" #include "pico/types.h" #include "pico/multicore.h" //*** definitions ************************************************************** #define DISK_BLOCK_NUM 480 // 240KB #define DISK_BLOCK_SIZE 512 #define NEW_FILE_FOUND 100 //*** prototydes *************************************************************** static void dump_all_storage( void ); //*** constants/variables ****************************************************** extern uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE]; //****************************************************************************** //*** functions **************************************************************** //****************************************************************************** void core1_main( void ) { printf("\nCore-1 loaded.\n\n"); while(1) { const uint32_t msc_flag = multicore_fifo_pop_blocking(); printf("\nCore-1 called :%d\n\n", msc_flag); if( msc_flag == NEW_FILE_FOUND ) { dump_all_storage(); } } } // dump the all if storage data for debug purpose static void dump_all_storage( void ) { int i, j, k; for( i=0; i<DISK_BLOCK_NUM; i++ ) // reduce the number of sectors to reduce 'panic' of USB module { printf("[%d]\n", i); for( j=0; j<(DISK_BLOCK_SIZE/16); j++ ) { for( k=0; k<16; k++ ) { printf("%02X ", msc_disk[i][j*16 +k]); if( k== 7 ) printf(" "); } printf(" "); for( k=0; k<16; k++ ) { if( (msc_disk[i][j*16 +k] >= 0x20)&&(msc_disk[i][j*16 +k] <= 0x7E) ) printf("%c", msc_disk[i][j*16 +k]); else printf("."); if( k== 7 ) printf(" "); } printf("\n"); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ //****************************************************************************** //* customized for PIC writer USB * //* * //* history: * //* Sep16,2022 start coding, support multi-core. N.Mato * //* Sep19,2022 search_hexfile_task() added here. N.Mato * //* * //* Copyright(c)2022 Rigel Intelligence * //****************************************************************************** #include <stdlib.h> #include <stdio.h> #include <string.h> #include "bsp/board.h" #include "tusb.h" #include "pico/stdlib.h" #include "pico/multicore.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ /* Blink pattern * - 250 ms : device not mounted * - 1000 ms : device mounted * - 2500 ms : device is suspended */ enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, }; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; void led_blinking_task(void); void cdc_task(void); void search_hexfile_task(void); extern void core1_main( void ); extern volatile bool flag_rootdir_change; #define NEW_FILE_FOUND 100 /*------------- MAIN -------------*/ int main(void) { board_init(); tusb_init(); stdio_init_all(); // clear flag flag_rootdir_change = false; // start core-1 for PIC programming task multicore_reset_core1(); multicore_launch_core1( core1_main ); while (1) { tud_task(); // tinyusb device task led_blinking_task(); cdc_task(); search_hexfile_task(); // check availablity of 'HEX' file } return 0; } //--------------------------------------------------------------------+ // Device callbacks //--------------------------------------------------------------------+ // Invoked when device is mounted void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed void tud_resume_cb(void) { blink_interval_ms = BLINK_MOUNTED; } //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ void cdc_task(void) { // connected() check for DTR bit // Most but not all terminal client set this when making connection // if ( tud_cdc_connected() ) { // connected and there are data available if ( tud_cdc_available() ) { // read datas char buf[64]; uint32_t count = tud_cdc_read(buf, sizeof(buf)); (void) count; // Echo back // Note: Skip echo by commenting out write() and write_flush() // for throughput test e.g // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 tud_cdc_write(buf, count); tud_cdc_write_flush(); } } } // Invoked when cdc when line state changed e.g connected/disconnected void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { (void) itf; (void) rts; // TODO set some indicator if ( dtr ) { // Terminal connected }else { // Terminal disconnected } } // Invoked when CDC interface received data from host void tud_cdc_rx_cb(uint8_t itf) { (void) itf; } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); led_state = 1 - led_state; // toggle } //--------------------------------------------------------------------+ // 'HEX' FILE SEARCH TASK added by M.Mato //--------------------------------------------------------------------+ void search_hexfile_task(void) { if( flag_rootdir_change ) { // trigger to core-1 program multicore_fifo_push_blocking( NEW_FILE_FOUND ); // end of purse 'HEX' file flag_rootdir_change = false; } else { // no need to check the storage } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
cmake_minimum_required(VERSION 3.13) # Pull in SDK (must be before project) include(${CMAKE_CURRENT_LIST_DIR}/../pico_sdk_import.cmake) include(${PICO_SDK_PATH}/lib/tinyusb/hw/bsp/family_support.cmake) # project name (need to edit for each project) set(PROJECT "msc_test") project(${PROJECT} C CXX ASM) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) # SDK initialization family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) # executable name (need to edit for each project) add_executable(${PROJECT} src/main.c ) # source code target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/core1_main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) # include path target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) # Configure compilation flags and libraries ... # see the corresponding function in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${PROJECT}) # enable serial output pico_enable_stdio_usb(${PROJECT} 1) pico_enable_stdio_uart(${PROJECT} 1) # create map/bin/hex file etc. pico_add_extra_outputs(${PROJECT}) # pull in common dependencies target_link_libraries(${PROJECT} PUBLIC pico_multicore) |
ビルド後、msc_test.uf2をRP2040に書込みます。ダンプデータはCore1が出力します。テスト用にRoot directory entryへ書き込みがある度に480block全てをUARTへ書き出しますが、マスストレージ側の処理を妨げることは無いのでPANICは発生しません。
Core0、Core1、両方を使う方向で実装を進めていきます。
コメント