User Tools

Site Tools


en:pfw:usb_cdc_driver_for_rp2040

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:pfw:usb_cdc_driver_for_rp2040 [2025-12-27 13:33] – [Implementation example] willemen:pfw:usb_cdc_driver_for_rp2040 [2026-01-13 18:16] (current) – [The idea] willem
Line 18: Line 18:
 hex hex
 Function: DEVICE-DECRIPTOR \ 18 bytes Function: DEVICE-DECRIPTOR \ 18 bytes
-12 c, 01 c, 10 c, 01 c, ( 1.10 ) EF c, 02 c, 01 c, 40 c, 66 c, 66 c, ( 6666 ) +The USB CDC device descriptor
-10 c, 66 c, ( 6610 ) 00 c, 01 c, ( vsn 1.00 ) 00 c, 02 c, 00 c, 01 c,  align+
  
 Function: CONFIGURATION-DESCRIPTOR \ 9 or 75 bytes Function: CONFIGURATION-DESCRIPTOR \ 9 or 75 bytes
-9 c,  2 c,  4B c,  0 c,  2 c,  1 c,  0 c,  80 c,  FA c, \ Maximum power = 500mA +The complex USB CDC device descriptor
-8 c,  0B c,  0 c,  2 c,  2 c,  2 c,  1 c,  0 c,         \ Interface Association Descriptor - CDC +
-9 c,  4 c,  0 c,  0 c,  1 c,  2 c,  2 c,  1 c,  0 c,    \ Interface 1: Control - 1 - 0 - +
-5 c,  24 c,  0 c,  10 c,  1 c, ( CDC vsn 1.10 )         \ CDC Header functional +
-5 c,  24 c,  1 c,  0 c,  1 c,                           \ CDC Call management functional +
-4 c,  24 c,  2 c,  2 c,                                 \ CDC ACM functional ( two commands ) +
-5 c,  24 c,  6 c,  0 c,  1 c,                           \ CDC Union functional ( one interface ) +
-7 c,  5 c,  81 c,  3 c,  8 c,  0 c,  10 c,              \ Endpoint 1 IN descriptor +
-9 c,  4 c,  1 c,  0 c,  2 c,  0A c,  0 c,  0 c,  0 c,   \ Interface 2: DATA +
-7 c,  5 c,  82 c,  2 c,  40 c, 0 c,  0 c,               \ Endpoint 2 IN descriptor +
-7 c,  5 c,  3 c,  2 c,  40 c, 0 c,  0 c,  align         \ Endpoint 3 OUT descriptor+
  
-decimal +Function: USB-STATE    ( -- a ) 
-Function: USB-STATE  0 ,           Hold current USB state in first half word: 3 = ready +Hold current USB state in first half word: 3 = ready 
-                                   \ In second half word are memory for the 900/880 requests +In second half word are memory for the 900/880 requests 
-          4 c, 3 c, 9 c, 4 c,      \ English/US language ID +The English/US language ID string 
-          115200 ,  0 c,  0 c,  8 c,  align  \ Line data: 115k2, Stop bits, Parity, Data bits+CDC Line data: 115k2, Stop bits, Parity, Data bits
  
-hex +Function: START-USB     ( -- ) 
-Function: START-USB     ( -- )  Initialise the RP2040 USB hardware +Initialise the RP2040 USB hardware, restart the USB hardware, 
-    1000000  4000C000           \ Bit-24 mask Reset register +erase the USB DPRAM, enable USB controller, set USB address to zero. 
-    2dup **bis  2dup **bic      Restart USB +Setup used endpoints and used interrupts & enable full speed USB. 
-    begin  2dup 8 + bit** until Wait until USB is ready + 
-    2drop 50100000 1000 false fill Erase USB ram +Function: PAD           -- a ) 
-    00000009  50110074  !       USB_USB_MUXING    Softcon, to PHY +Reserve 64 bytes RAM as scratchpad area 
-    0000000C  50110078  !       USB_USB_PWR       VBUS overide & detect enable + 
-    00000001  50110040  !       USB_MAIN_CTRl     Enable controller +Function: EP0   ( -- a ) 
-    20000000  5011004C        \ USB_SIE_CONTROL   Enable End Point 0 interrupt +Function: EP1   ( -- a ) 
-    false     50110000  !       \ Respond to address 0 on initial setup +Function: EP2   ( -- a ) 
-    00011010  50110090  !       \ USB_INTE          Enable 3 interrupts +Function: EP3   ( -- a ) 
-    AC000180  50100008  !       \ init COMM endpoint in buffer 1 +Seven cells data structures to control endpoint-0, 1, 2 & 3 
-    A8000200  50100010  !       \ init SEND endpoint in buffer 2 +The first four cells a variable data 
-    A8000280  5010001C  !       \ init RECV endpoint out buffer 3 +The three cells thereafter contain USB pointers & register addresses 
-    00010000  5011204C  ! ;     \ USB_SIE_CONTROL   Enable pull up+ 
 +Function: @VAL   ( -- +n ) 
 +Read the wValue from any eight bytes setup packet 
 +Function: @LEN   ( -- +n ) 
 +Read the wLength from any eight bytes setup packet 
 + 
 +Function: >UNI   ( a1 u -- a2 ) 
 +Store the ASCII string to a unicode string tailored for USB 
 + 
 +Function: >CNT    Offset 00 
 +Function: >ORG    Offset 04 
 +Function: >PKT    Offset 08 
 +Function: >PID    \ Offset 12 
 +Function: >ICTRL  Offset 16 
 +Function: >OCTRL  Offset 20 
 +Function: >BUF    Offset 24 
 +Seven functions that calculate the address of each field in the  
 +endpoint data structures 
 + 
 +Function: EP-IN    ( ep -- org buf pkt ) 
 +Calculate data to send for 'ep'
 + 
 +Function: PREPARE  ( a u ep -- ) 
 +Prepare data packet from address 'a' with the length 'u' to send tp 'ep'
 + 
 +Function: >NEXT    ( ep -- pkt ) 
 +Get next packet size for 'ep' x, when 'pkt' is zero there is no more  
 +data to send 
 + 
 +Function: !PKT     ( pkt ep -- ictrl ) 
 +Store next packet to send for 'ep' x  
 + 
 +Function: PREP-RCV ( ep -- ) 
 +Enable endpoint 'ep' x  to receive a data packet 
 + 
 +Function: GONE?    ( ep -- f ) 
 +Leave true when the data in 'ep' x was sent 
 + 
 +Function: USB?     ( -- +n ) 
 +Leave three when the host & device are connected 
 + 
 +Function: USB-SEND ( ep -- ) 
 +Transmit the prepared data packet to 'ep'
 + 
 +Function: USB-RCV  ( pid ep -- ) 
 +Enable the receiving of a data packet on 'ep' x starting with the 'pid'  
 +from the stack 
 + 
 +Function: BUS=RESET ( -- ) 
 +Handle a USB bus reset, clearing the device address to zero, the USB  
 +state to zero, reinitialise the receiving & transmitting endpoints 
 + 
 +Function: SETUP>   ( a u -- ) 
 +Handle the answer data  packet 'a' 'u' for all setup packages 
 +When done wait for a ZLP from the host to signal a correct answer 
 + 
 +Function: XTABLE 
 +    Define an execution table entry for '+n' request actions 
 +    Define:  ( +n "name" -- ) 
 +        Create a table with "name" for '+n' actions 
 +    Action:  ( request -- ) 
 +        Execute the action for 'request' or generate a stall 
 +        when the 'request' is not available 
 +         
 +Function: ZLP>     ( -- ) 
 +Send a zero length package through endpoint zero. This is used  
 +to signal the handling of a request that sends no data back 
 + 
 +Define four action in front that leave their execution tokens on the stack 
 +0302 action xt 
 +0300 action xt 
 +0200 action xt 
 +0100 action xt 
 +Function: HANDLE-SETUP ( req0 .. req3 4 -- ) 
 + 
 +2221 action xt 
 +21A1 action xt 
 +2021 action xt 
 +0900 action xt 
 +0880 action xt 
 +0680 action xt 
 +0500 action xt 
 +Function: HANDLE-REQ)  ( req0 .. req6 7 -- ) 
 + 
 +Function: HANDLE-REQ   ( -- ) 
 +Reset setup request interrupt, read bmrequest type and do HANDLE-REQ) 
 + 
 +Function: #L           ( -- +n ) 
 +Ring buffer size, must be a power of two 
 +Function: #R           ( -- +n ) 
 +this is equal to #L - 
 + 
 +Function: #RX          ( -- +n ) 
 +Leave number of characters in receive buffer 
 +Function: #TX          ( -- +n ) 
 +Leave number of characters in transmit buffer 
 + 
 +Function: >RX          ( c -- ) 
 +Store character 'c' in RX ring buffer 
 +Function: >TX          ( c -- ) 
 +Store character 'c' in TX ring buffer 
 + 
 +Function: RX>          ( -- c ) 
 +Read character 'c' from RX ring buffer 
 +Function: TX>          ( -- c ) 
 +Read character 'c' from TX ring buffer 
 + 
 +Function: IFLAG    
 +Reserve one cell space for receive interrupt flag 
 + 
 +Function: ENDPOINTS    ( -- ) 
 +Handle EP1 & EP3 endpoints, save received data interrupt flag in IFLAG 
 +Release all interrupt flags 
 + 
 +Function: REQUESTS     ( -- ) 
 +Handle all USB interrupts, that are the USB bus reset, setup requests & endpoints 
 + 
 +Function: USB-HANDLER  ( -- ) 
 +Handle the receiving of the RX data using iFLAG and use the low level USB 
 +ACK/NAK handshake to move data from an endpoint to the RX ring buffer in a controlled way. 
 +Handle the transmitting of TX data, but only when a connection is made. Before filling 
 +the TX endpoint check if the previous data packet was sent too. 
 + 
 +Function: USB-KEY?     ( -- flag ) 
 +Leave true flag when there is data in the RX ring buffer, otherwise false 
 +Call the USB-HANDLER once too 
 + 
 +Function: USB-KEY      ( -- c ) 
 +Leave character 'c' when there is data in the RX ring buffer 
 +Call the USB-HANDLER waiting for space in the RX ring buffer 
 + 
 +Function: USB-EMIT     ( c -- ) 
 +Store character 'c' when there is space in the TX ring buffer 
 +Call the USB-HANDLER waiting for space in the TX ring buffer 
 + 
 +Function: USB-ON 
 +Initialise the USB DPRAM, call START-USB, clear USB-STATE & IFLAG 
 +finally initialse the KEY?, KEY and EMIT vectors of the used system.
  
 </code> </code>
  
-===== Implementation example =====+===== Generic Forth implementation example =====
  
 <code forth> <code forth>
Line 115: Line 241:
     00010000  5011204C  ! ;     \ USB_SIE_CONTROL   Enable pull up     00010000  5011204C  ! ;     \ USB_SIE_CONTROL   Enable pull up
  
 +\ Endpoint data structures, 4 variable cells & 3 constant cells
 \ Name:    CNT  ORG  PKT  PID   INBUF-CTRL  OUTBUF-CTRL   EPxBUF \ Name:    CNT  ORG  PKT  PID   INBUF-CTRL  OUTBUF-CTRL   EPxBUF
 \ Offsets: 00   04   08   0C       10            14         18 \ Offsets: 00   04   08   0C       10            14         18
Line 129: Line 256:
     ?do  c@+  pad i 2* + 2 + h!  loop  drop  pad ;     ?do  c@+  pad i 2* + 2 + h!  loop  drop  pad ;
  
- +\ Addresssing tools for the endpoint data structures
-\ Addresssing tools for endpoint administration+
 : >CNT      ; immediate     \ 00 - ep0 >cnt !   - Bytes left te send : >CNT      ; immediate     \ 00 - ep0 >cnt !   - Bytes left te send
 : >ORG      cell+ ;         \ 04 - ep1 >org @   - Address of next packet : >ORG      cell+ ;         \ 04 - ep1 >org @   - Address of next packet
Line 140: Line 266:
  
 \ Primitive endpoint functionality \ Primitive endpoint functionality
-: EP-IN     ( ep -- org buf pkt )   >r  r@ >org @   r@ >buf @   r> >pkt @ ;     \ Calculate data to send for EPx +: EP-IN     ( ep -- org buf pkt )     \ Calculate data to send for EPx 
-: PREPARE   ( a u ep -- )           >r  dup r@ >cnt !  40 min r@ >pkt !  r> >org ! ; \ Prepare data to send for EPx +    >r  r@ >org @   r@ >buf @   r> >pkt @ ; 
-: >NEXT     ( ep -- pkt )           >r  r@ >pkt @   r@ >org @  +  r@ >org !     \ Get next packet size for EPx +     
-                                    r@ >pkt @  r@ @  over -  dup r@ !  40 min r> >pkt ! ; +: PREPARE   ( a u ep -- )             \ Prepare data to send for EPx 
-: !PKT      ( pkt ep -- ictrl )     >r  r@ >pid @ or  8000 or   \ pid + pkt + mask - Store next packet to send for EPx +    >r  dup r@ >cnt !  40 min r@ >pkt !  r> >org ! ; 
-                                    r> >ictrl @  tuck ! ; +     
-: PREP-RCV  ( ep -- )               >r r@ >octrl @   r@ >pid @  40 or  over !   \ Prepare to receive a packet on EPx +: >NEXT     ( ep -- pkt )             \ Get next packet size for EPx 
-                                    2000 r> >pid **bix  400 swap **bis ; +    >r  r@ >pkt @   r@ >org @  +  r@ >org ! 
-: GONE?     ( ep -- f )             >ictrl @ @ 400 and 0= ;     \ Leave true when Epx packet was sent +    r@ >pkt @  r@ @  over -  dup r@ !  40 min r> >pkt ! ; 
-: USB?      ( -- +n )               usb-state h@ 3 = ;          \ True when host & device are connected +     
 +: !PKT      ( pkt ep -- ictrl )       \ pid + pkt + mask - Store next packet to send for EPx 
 +     >r  r@ >pid @ or  8000 or  r> >ictrl @  tuck ! ; 
 +      
 +: PREP-RCV  ( ep -- )                 \ Prepare to receive a packet on EPx 
 +    >r r@ >octrl @   r@ >pid @  40 or  over ! 
 +    2000 r> >pid **bix  400 swap **bis ; 
 +     
 +: GONE?     ( ep -- f )     >ictrl @ @ 400 and 0= ; \ Leave true when Epx packet was sent 
 +: USB?      ( -- +n )       usb-state h@ 3 = ;      \ True when host & device are connected
  
 \ Basic receive & transmit packet handlers \ Basic receive & transmit packet handlers
Line 162: Line 296:
  
 : SETUP>        ( a u -- )      \ Handle the answer for all setup packages : SETUP>        ( a u -- )      \ Handle the answer for all setup packages
-    2000 ep0 >pid !  ep0 prepare                \ Start with DATA1, setup packet data+    2000 ep0 >pid !  ep0 prepare           \ Start with DATA1, setup packet data
     begin     begin
-        ep0 ep-in move  ep0 usb-send            \ Store & send packet +        ep0 ep-in move  ep0 usb-send       \ Store & send packet 
-        1 50110058                              \ Packet gone?+        1 50110058                         \ Packet gone?
         begin  2dup bit** until  **bis         begin  2dup bit** until  **bis
-    ep0 @ 0= until  2000 ep0 usb-rcv ;          \ Handle ZLP+    ep0 @ 0= until  2000 ep0 usb-rcv ;     \ Handle ZLP
  
 : XTABLE    ( +n "name" -- )    \ Define custom execution table : XTABLE    ( +n "name" -- )    \ Define custom execution table
Line 209: Line 343:
 \ 2   = Out pointer (OUT) \ 2   = Out pointer (OUT)
 \ 3   = Start of ring buffer \ 3   = Start of ring buffer
- 
 100     constant #L     \ Buffer size 100     constant #L     \ Buffer size
 #L 1-   constant #R     \ Buffer mask #L 1-   constant #R     \ Buffer mask
Line 282: Line 415:
     50100300  [ #L 2* 6 cells + ] literal  false fill \ Init. buffer space to zero     50100300  [ #L 2* 6 cells + ] literal  false fill \ Init. buffer space to zero
     start-usb  false usb-state !  false to iflag     start-usb  false usb-state !  false to iflag
-    ['] usb-key? to 'key?           \ Install USB CDC char. I/O vectors+    ['] usb-key? to 'key?           \ Install USB CDC char. I/O vectors (noForth specific!)
     ['] usb-key  to 'key     ['] usb-key  to 'key
     ['] usb-emit to 'emit ;     ['] usb-emit to 'emit ;
Line 289: Line 422:
 </code> </code>
  
 +===== Implementations =====
 +
 +[[https://github.com/WillemOuwerkerk/noForth-T-hardware-examples-RP2040/tree/main/USB-CDC|Different noForth implementations for the USB-CDC driver]]
en/pfw/usb_cdc_driver_for_rp2040.1766838788.txt.gz · Last modified: 2025-12-27 13:33 by willem