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
: 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.
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
EXIT
s 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
.