USB driver for STM32F0x2 parts

The file UsbHwSTM32F0x2.fth provides a USB driver for STM32F0x2 devices. Some primitive code was taken from a public-domain source, and updated for correctness and interrupt operation.

https://github.com/jeelabs/embello/tree/master/explore/1608-forth/suf

Endpoint packet memory and control

: even          \ addr -- addr'
Force input address to be even.

: usb-pma       ( pos -- addr ) _USBSRAM + ;
Convert an offset/position in the packet RAM to an absolute address.

: usb-pma       ( pos -- addr ) _USBSRAM + ;
Convert an offset/position in the packet RAM to an absolute address. Compiler macro.

: ep-reg        \ ep n -- addr
Return the address in packet RAM of reg n (0..3) of ep (0..7)

Each endpoint has an 8 byte control area of four buffers for transmit and receive control.

0 equ EPR_ADDR_TX
1 equ EPR_COUNT_TX
2 equ EPR_ADDR_RX
3 equ EPR_COUNT_RX

: ep-addr       ( ep# -- addr )  $0F and  cells _USBdev usbEP0R + + ;
Return the address in the peripheral block of the peripheral register for endpoint ep.

\ endpoint status values, both TX and RX
0 equ epDISABLED
1 equ epSTALL
2 equ epNAK
3 equ epVALID

\ endpoint type, both TX and RX
0 equ epBULK
1 equ epCONTROL
2 equ epISO
3 equ epINTERRUPT

: rxstat!       \ ep u --
Set stat_rx without toggling/setting any other fields.

: txstat!       \ ep u --
Set stat_tx without toggling/setting any other fields.

: rxclear       \ ep --
Clear the endpoint receive CTR_RX bit.

: txclear       \ ep --
Clear the endpoint transmit CTR_TX bit.

: ep-reset-rx#  \ ep --
Clear the RX count register.

: ep-reset-tx#  \ ep --
Clear the TX count register.

Packet memory is used as shown below. Memory use is inefficient as two 64 byte buffers are reserved for each endpoint, whether needed or not.


000..03F   Endpoint Table
040..0BF   EP0 buffers, offset $00 for RX, $40 for TX
0C0..13F   EP1 ...
140..1BF   EP2 ...
1C0..23F   EP3 ...
240..2BF   EP4 ...
2C0..33F   EP5 ...
340..3BF   EP6 ...

: EPioBufRX     \ ep# -- pma
Return offset address of the receive packet memory buffer.

: EPioBufTX     \ ep# -- pma
Return offset address of the transmit packet memory buffer

: set-EPtab-n   \ ep# --
Set up EP buffer area in the packet memory.

Handling endpoints

This section contains an array of endpoint handlers and default actions for other operations which are hardware dependent.

: USBDirCtrlEP  \ dir -- ; 0=out
This word is a dummy for this hardware.

: USBResetEP    \ dir -- ; 0=out
This word is a dummy for this hardware.

: USBEnableEP   \ dir -- ; 0=out
This word is a dummy for this hardware.

create EPxts    \ -- addr
Holds the xts of the 16 endpoint handler words. The action of each handler must have the stack effect below:

  event --

: EPhandler     \ event u --
Run the endpoint handler associated with endpoint u, where endpoints are numbered 0..15. Each endpoint handler is passed an event type which allows it to determine what it has to do. The action of each handler must have the stack effect below.

  event --

: SetEPhandler  \ xt ep# --
Install the endpoint handler for endpoint ep#. Used during interpretation.

0 value UsbDevSt        \ -- x
USB device Status.

: USBsuspend    \ --
Suspend operations are performed by the hardware. This is a hook for installing actions such as toggling an LED.

: USBresume     \ --
Resume operations are performed by the hardware. This is a hook for installing actions such as toggling an LED.

: usbHWconnect  \ --
Connect pull up on USB DP line.

: usbHWdisconnect       \ --
Disconnect pull up on USB DP line.

: USBconnect    \ --
Connect to the USB bus.

: USBdisconnect \ --
Disconnect from the USB bus.

: USBWakeUp     \ --
Called automatically on USB Remote Wakeup.

: USBSetAddress \ addr --
Set the USB assigned address and enable the device. This should be done during a SOF (frame) interrupt. Note that USBSetAddress may not actually set the device address, but may just signal that an action must be taken, e.g. in the next frame interrupt

: USBConfigure  \ cfg -- ; 0=unconfigure
Set the SIE configuration state.

: cfg-EPnR      \ ep# x --
Configure the USB endpoint register,

: cfgIso        \ desc ep# -- desc
Configure an isochronous endpoint. UNTESTED.

: cfgBulk       \ desc ep# -- desc
Configure a bulk endpoint.

: cfgInt        \ desc ep# -- desc
Configure an interrupt endpoint.

: USBConfigEP   \ desc --
Configure USB Endpoint register according to Descriptor.

: USBConfig2EP  \ desc ep# -- desc
Configure USB Endpoint according to Descriptor and EndPoint.

: USBDisableEP  \ ep# -- ; bit7=dir, bits3:0=num
Disable the endpoint.

: USBSetStallEP \ ep# -- ; bit7=dir, bits3:0=num
Stall the endpoint. This word must clear the relevant bit in UsbEpHalt.

: epBulk?       \ ep# -- flag
Return true if the endpoint is BULK.

: USBClrStallEP \ ep# -- ; bit7=dir, bits3:0=num
Clear the endpoint stall. This word must clear the relevant bit in UsbEpHalt, and should ensure that bulk IN/OUT NAKs cause interrupts.

: .ep0/istr     \ --
Display the EP0 endpoint register and the ISTR

: .ep0-pma      \ --
Display the four EP0 packet memory registers

: set-EPnR      \ x ep --
Set the USB endpoint register

: USBswReset    \ --
The action performed for a software reset of the USB, either at reset or in response to a USB reset.

: ep-setup      \ ep# --
Trigger a SETUP packet handler.

: ep-out        \ ep# --
Trigger an OUT packet handler.

: ep-in         \ ep# --
Trigger an IN packet handler.

: usb-ctr       \ istr --
Given an interrupt status reading, process the packet.

: usb-poll      \ --
Main USB driver polling routine. Factored this way to allow EXITs from the branches.

: USBinterrupt  \ --
The USB interrupt handler. It calls usb-poll above to permit better factoring. LED1 is enabled around the handler to give the user or oscilloscope an idea of overheads.

' USBinterrupt USB_EXTI_18vec# EXC: USB_ISR     \ -- addr
The entry point for the USB interrupt.

: usbIntInit    \ --
Initialise USB hardware interrupt handler.

: InitUSB       \ --
Initialise the USB hardware.

: startUSB      \ --
Start the USB system. This word gives more control to devices that have VBUS control. If such devices are rebooted without power down, they may/will need to perform a USBdisconnect operation as part of the start up sequence. A disconnect, delay, connect sequence is part of startUSB.