nmaggioni commented on issue #16271:
URL: https://github.com/apache/nuttx/issues/16271#issuecomment-3263701404

   > @linguini1 Have a bootloader that puts the RP2040 into BOOTSEL when it 
detects something like 1200 baud on a UART line
   
   In my RP2040 board I have implemented this over USB CDC-ACM instead of UART. 
This comes at the cost of having a background demon that listens for 
LINE_CODING events (let me improperly call them "baud rate changes"), though.
   
   <details>
     <summary>Example code, ran as part of bringup</summary>
   
   Note: I have removed all error handling, comments, and mangled the control 
structure of this code for maximum brevity. Consider it pseudocode at this 
point :)
   The `BOARDIOC_RESET_BOOTSEL` ioctl does what the name suggests and is backed 
by a ROM lookup like in pico-sdk.
     
   ```c
   static sem_t g_board_bootsel_on_baudrate_change_daemon_sem;
   
   static void cdcacm_daemon_callback(enum cdcacm_event_e event) {
       if (event == CDCACM_EVENT_LINECODING) {
           sem_post(&g_board_bootsel_on_baudrate_change_daemon_sem);
       }
   }
   
   static int cdcacm_daemon(int argc, char *argv[]) {
       while (true) {
           sem_wait(&g_board_bootsel_on_baudrate_change_daemon_sem);
   
           int fd = open("/dev/ttyACM0", O_RDONLY);
           struct cdc_linecoding_s linecoding;
           int ret = ioctl(fd, CAIOC_GETLINECODING, &linecoding);
           unsigned long baud = (linecoding.baud[3] << 24 | linecoding.baud[2] 
<< 16 | linecoding.baud[1] << 8 | linecoding.baud[0]);
           close(fd);
   
           if (baud == 1200) {
               boardctl(BOARDIOC_RESET_BOOTSEL, (uintptr_t)NULL);
           }
       }
   }
   
   static int board_cdcacm_daemon_setup(int argc, char *argv[]) {
       uint8_t retry = 0;
       uint8_t retry_delay_lut[] = { 1, 2, 3, 5, 10, 15, 30, 60 };
   
       int fd;
       while (true) {
           fd = open("/dev/ttyACM0", O_RDONLY);
           if (fd >= 0) break;
           if (retry < ARRAY_SIZE(retry_delay_lut)) {
               uint8_t delay = retry_delay_lut[retry++];
               usleep(delay * USEC_PER_SEC);
           } else {
               return EXIT_FAILURE;
           }
       }
       ioctl(fd, CAIOC_REGISTERCB, &cdcacm_daemon_callback);
       close(fd);
   
       sem_init(&g_board_bootsel_on_baudrate_change_daemon_sem, 0, 0);
       sem_setprotocol(&g_board_bootsel_on_baudrate_change_daemon_sem, 
SEM_PRIO_NONE);
   
       task_create("cdcacm_daemon", sched_get_priority_min(SCHED_FIFO), 512, 
cdcacm_daemon, NULL);
       return EXIT_SUCCESS;
   }
   
   int board_app_finalinitialize(uintptr_t arg) {
       int pid = task_create("board_cdcacm_daemon_setup", 
sched_get_priority_min(SCHED_FIFO) + 1, 1024, board_cdcacm_daemon_setup, NULL);
       return EXIT_SUCCESS;
   }
   ```
     
   </details>
   
   ```plaintext
   nsh> ps
     PID GROUP PRI POLICY   TYPE    NPX STATE    EVENT       STACK    USED 
FILLED COMMAND
       0     0   0 FIFO     Kthread   - Ready              0001008 0000560  
55.5%  Idle_Task
       1     1 100 RR       Task      - Running            0003032 0001664  
54.8%  nsh_main
       3     3   1 RR       Task      - Waiting  Semaphore 0000472 0000408  
86.4%! cdcacm_daemon
   ```
   
   This way I can run `stty -F /dev/serial/by-id/usb-<your_device_id> 1200` on 
the host and have the board reboot to bootloader, and then it's just a matter 
of a few shell commands to wait for the USB drive to appear and copy the new 
UF2 file to it. I've wrapped all these actions in a couple of 
[Just](https://just.systems/man/en/) recipes for ease of use, so I can get away 
with things like `just build && just bootsel-flash` :)
   
   @cederom What do you think of this approach? Would it be interesting to 
upstream it or is it too niche? I typically use a debug probe while developing, 
but this alternative way of flashing still comes in handy at times.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to