| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850 |
- /* This file is the part of the Lightweight USB device Stack for STM32 microcontrollers
- *
- * Copyright ©2016 Dmitry Filimonchuk <dmitrystu[at]gmail[dot]com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #if !defined (__ASSEMBLER__)
- #define __ASSEMBLER__
- #endif
- #include "usb.h"
- #if defined(USBD_STM32L052) || defined(USBD_STM32L433)
- #include "memmap.inc"
- #define EP_SETUP 0x0800
- #define EP_TYPE 0x0600
- #define EP_KIND 0x0100
- #define EP_ADDR 0x000F
- #define EP_RX_CTR 0x8000
- #define EP_RX_DTOG 0x4000
- #define EP_RX_STAT 0x3000
- #define EP_RX_SWBUF 0x0040
- #define EP_RX_DIS 0x0000
- #define EP_RX_STAL 0x1000
- #define EP_RX_NAK 0x2000
- #define EP_RX_VAL 0x3000
- #define EP_TX_CTR 0x0080
- #define EP_TX_DTOG 0x0040
- #define EP_TX_STAT 0x0030
- #define EP_TX_SWBUF 0x4000
- #define EP_TX_DIS 0x0000
- #define EP_TX_STAL 0x0010
- #define EP_TX_NAK 0x0020
- #define EP_TX_VAL 0x0030
- #define RXADDR0 0x00
- #define RXCOUNT0 0x02
- #define RXADDR1 0x04
- #define RXCOUNT1 0x06
- #define TXADDR0 0x00
- #define TXCOUNT0 0x02
- #define TXADDR1 0x04
- #define TXCOUNT1 0x06
- #define TXADDR 0x00
- #define TXCOUNT 0x02
- #define RXADDR 0x04
- #define RXCOUNT 0x06
- #define EP_NOTOG (EP_RX_CTR | EP_TX_CTR | EP_SETUP | EP_TYPE | EP_KIND | EP_ADDR)
- #define TGL_SET(mask, bits) ((EP_NOTOG | (mask))<<16 | (bits))
- #define TX_STALL TGL_SET(EP_TX_STAT, EP_TX_STAL)
- #define RX_STALL TGL_SET(EP_RX_STAT, EP_RX_STAL)
- #define TX_USTALL TGL_SET(EP_TX_STAT | EP_TX_DTOG, EP_TX_NAK)
- #define RX_USTALL TGL_SET(EP_RX_STAT | EP_RX_DTOG, EP_RX_VAL)
- #define DTX_USTALL TGL_SET(EP_TX_STAT | EP_TX_DTOG | EP_TX_SWBUF, EP_TX_VAL)
- #define DRX_USTALL TGL_SET(EP_RX_STAT | EP_RX_DTOG | EP_RX_SWBUF, EP_RX_VAL | EP_RX_SWBUF)
- .syntax unified
- .cpu cortex-m0plus
- .thumb
- .align 4
- .section .rodata.usbd_devfs_asm
- .globl usbd_devfs_asm
- usbd_devfs_asm:
- .long _getinfo
- .long _enable
- .long _connect
- .long _setaddr
- .long _ep_config
- .long _ep_deconfig
- .long _ep_read
- .long _ep_write
- .long _ep_setstall
- .long _ep_isstalled
- .long _evt_poll
- .long _get_frame
- .long _get_serial_desc
- .size usbd_devfs_asm, . - usbd_devfs_asm
- .text
- .align 2
- .thumb_func
- .type _get_serial_desc, %function
- /* uint16_t get_serial_desc (void *buffer)
- * R0 <- buffer for the string descriptor
- * descrpitor size -> R0
- */
- _get_serial_desc:
- push {r4, r5, lr}
- movs r1,18 //descriptor size 18 bytes
- strb r1,[r0]
- movs r1, #0x03 //DTYPE_STRING
- strb r1,[r0, #0x01]
- ldr r5, .L_uid_base //UID3 this is the serial number
- ldr r4, .L_fnv1a_offset //FNV1A offset
- ldr r2, [r5, 0x00] //UID0
- bl .L_fnv1a
- ldr r2, [r5, 0x04] //UID1
- bl .L_fnv1a
- ldr r2, [r5, 0x14] //UID2
- bl .L_fnv1a
- movs r3, #28
- .L_gsn_loop:
- movs r1, r4
- lsrs r1, r3
- lsls r1, #28
- lsrs r1, #28
- adds r1, #0x30 //'0'
- cmp r1, #0x3A
- blo .L_gsn_store
- adds r1, #0x07 //'A' - '0'
- .L_gsn_store:
- adds r0, #0x02
- strb r1, [r0]
- lsrs r1, #0x08
- strb r1, [r0, #0x01]
- subs r3, #0x04
- bpl .L_gsn_loop
- movs r0, #18
- pop {r4, r5, pc}
- .L_fnv1a:
- movs r3, #0x04
- .L_fnv1a_loop:
- uxtb r1, r2
- eors r4, r1
- ldr r1, .L_fnv1a_prime //FNV1A prime
- muls r4, r1
- lsrs r2, #0x08
- subs r3, #0x01
- bne .L_fnv1a_loop
- bx lr
- .align 2
- .L_fnv1a_prime: .long 16777619
- .L_fnv1a_offset: .long 2166136261
- .L_uid_base: .long UID_BASE
- .size _get_serial_desc, . - _get_serial_desc
- .thumb_func
- .type _connect, %function
- _connect:
- ldr r3, =#USB_REGBASE
- movs r1, #0x03 //BCDEN + DCDEN
- movs r2, #usbd_lane_dsc
- strh r1, [r3, #USB_BCDR]
- ldrh r1, [r3, #USB_BCDR]
- lsrs r1, #0x05 //DCDET->CF
- bcc .L_connect
- movs r1, #0x05 //BCDEN + PDEN
- movs r2, #usbd_lane_unk
- strh r1, [r3, #USB_BCDR]
- ldrh r1, [r3, #USB_BCDR]
- lsls r1, #25 //PS2DET->CF
- bcs .L_connect
- movs r2, #usbd_lane_sdp
- lsls r1, #2 //PDET->CF
- bcc .L_connect
- movs r1, #0x09 //BCDEN + SDET
- movs r2, #usbd_lane_cdp
- strh r1, [r3, #USB_BCDR]
- ldrh r1, [r3, #USB_BCDR]
- lsrs r1, #7 //SDET->CF
- bcc .L_connect
- movs r2, #usbd_lane_dcp
- .L_connect:
- subs r1, r0, #1
- sbcs r0, r1
- lsls r0, #15
- strh r0, [r3, #USB_BCDR]
- mov r0, r2
- bx lr
- .size _connect, . - _connect
- .thumb_func
- .type _setaddr, %function
- _setaddr:
- ldr r1, =USB_REGBASE
- adds r0, #0x80
- strh r0, [r1, #USB_DADDR] //USB->DADDR
- bx lr
- .size _setaddr, . - _setaddr
- .thumb_func
- .type _get_frame, %function
- _get_frame:
- ldr r0, =#USB_REGBASE
- ldrh r0, [r0, #USB_FNR] //FNR
- lsls r0, #21
- lsrs r0, #21
- bx lr
- .size _get_frame, . - _get_frame
- .thumb_func
- .type _enable, %function
- _enable:
- ldr r1, =#USB_REGBASE //USB->CNTR
- ldr r2, =#RCC_BASE //RCC
- movs r3, #0x01
- lsls r3, #RCC_USBEN //USBEN or USBRST
- tst r0, r0
- beq .L_disable
- .L_enable:
- ldr r0, [r2, #RCC_APB1ENR]
- orrs r0, r3
- str r0, [r2, #RCC_APB1ENR] //RCC->APB1ENR |= USBEN
- ldr r0, [r2, #RCC_APB1RSTR]
- orrs r0, r3
- str r0, [r2, #RCC_APB1RSTR] //RCC->APB1RSTR |= USBRST
- bics r0, r3
- str r0, [r2, #RCC_APB1RSTR] //RCC->APB1RSTR &= ~USBRST
- #if defined(USBD_PINS_REMAP) && (defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F070x6))
- ldr r0, [r2, #RCC_APB2ENR]
- movs r3, #0x01
- orrs r0, r3
- str r0, [r2, #RCC_APB2ENR] //RCC->APB2ENR |= RCC_APB2ENR_SYSCFGCOMPEN
- ldr r2, =#SYSCFG_BASE //SYSCFG->CFGR1
- ldr r0, [r2]
- lsls r3, #SYSCFG_USBREMAP
- orrs r0, r3
- str r0, [r2] //SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; // remap USB pins for small packages
- #endif
- #if !defined(USBD_SOF_DISABLED)
- movs r0, #0xBE // CTRM | ERRM | WKUPM | SUSPM | RESETM | SOFM
- #else
- movs r0, #0xBC // CTRM | ERRM | WKUPM | SUSPM | RESETM
- #endif
- lsls r0, #0x08
- strh r0, [r1] //set USB->CNTR
- bx lr
- .L_disable:
- ldr r0, [r2, #RCC_APB1ENR]
- tst r0, r3
- beq .L_enable_end // usb is disabled
- movs r0, #0x00
- strh r0, [r1, #USB_BCDR] //USB->BCDR disable USB I/O
- ldr r0, [r2, #RCC_APB1RSTR]
- orrs r0, r3
- str r0, [r2, #RCC_APB1RSTR] //RCC->APB1RSTR |= USBRST
- ldr r0, [r2, #RCC_APB1ENR]
- bics r0, r3
- str r0, [r2, #RCC_APB1ENR] //RCC->APB1ENR &= ~USBEN
- .L_enable_end:
- bx lr
- .size _enable, . - _enable
- .thumb_func
- .type _getinfo, %function
- _getinfo:
- movs r0, #USBD_HW_BC
- ldr r2, =#RCC_BASE
- ldr r1, [r2, #RCC_APB1ENR]
- lsrs r1, #24 //USBEN -> CF
- bcc .L_getinfo_end
- adds r0, #USBD_HW_ENABLED
- ldr r2, =#USB_REGBASE
- ldr r1, [r2, #USB_BCDR]
- lsrs r1, #15 //DPPU -> CF
- bcc .L_getinfo_end
- adds r0, #USBD_HW_SPEED_FS
- .L_getinfo_end:
- bx lr
- .size _getinfo, . - _getinfo
- .thumb_func
- .type _ep_setstall, %function
- /*void ep_settall(uint8_t ep, bool stall)
- * in R0 <- endpoint number
- * in R1 <- 0 if unstall, !0 if stall
- */
- _ep_setstall:
- push {r4, lr}
- lsls r2, r0, #28
- lsrs r2, #26
- ldr r3, =#USB_EPBASE
- adds r3, r2 // epr -> r3
- movs r2, 0x30 // TX_STAT_MASK -> r2
- ldrh r4, [r3]
- lsls r4, #21
- lsrs r4, #29 // EP_TYPE | EP_KIND -> R4 LSB
- cmp r4, #0x04 // ISO ?
- beq .L_eps_exit
- cmp r0, #0x80
- blo .L_eps_rx
- .L_eps_tx:
- ldr r0, =#TX_STALL //stall TX
- cmp r1, #0x00
- bne .L_eps_reg_set
- .L_eps_tx_unstall:
- ldr r0, =#DTX_USTALL //unstall dblbulk or iso TX (VALID and clr DTOG_TX & SWBUF_TX)
- cmp r4, #0x01 // if doublebuffered bulk endpoint
- beq .L_eps_reg_set
- ldr r0, =#TX_USTALL // unstall other TX (NAKED + clr DTOG_TX)
- b .L_eps_reg_set
- .L_eps_rx:
- lsls r2, #8 // RX_STAT_MASK -> R2
- ldr r0,=#RX_STALL //stall RX
- cmp r1, #0x00
- bne .L_eps_reg_set
- .L_eps_rx_unstall:
- ldr r0, =#DRX_USTALL //unstall dblbulk or iso (VALID. clr DTOG_RX set SWBUF_RX)
- cmp r4, #0x01 // if dblbulk
- beq .L_eps_reg_set
- ldr r0, =#RX_USTALL // unstall other RX (VALID + clr
- /* R0 - mask and toggle bits
- * R2 - mask for STAT bits
- * R3 - endpoint register pointer
- */
- .L_eps_reg_set:
- ldrh r1, [r3] // *epr -> r1
- ands r2, r1 // check if endpoint disabled
- beq .L_eps_exit // do nothing
- eors r1, r0
- lsrs r0, #16
- ands r1, r0
- strh r1, [r3]
- .L_eps_exit:
- pop {r4, pc}
- .size _ep_setstall, . - _ep_setstall
- .thumb_func
- .type _ep_isstalled, %function
- /* bool ep_isstalled(uint8t ep) */
- _ep_isstalled:
- ldr r1, =#USB_EPBASE
- lsls r2, r0, #28
- lsrs r2, #26
- ldr r1, [r1, r2]
- lsls r1, #17
- cmp r0, #0x80
- bhs .L_eis_check
- lsls r1, #8
- .L_eis_check:
- lsrs r1, r1, #28
- subs r1, #0x01
- subs r0, r1, #0x01
- sbcs r1, r1
- rsbs r0, r1, #0
- bx lr
- .size _ep_isstalled, . - _ep_isstalled
- .thumb_func
- .type _ep_read, %function
- /* int32_t _ep_read(uint8_t ep, void *buf, uint16_t blen)
- * in R0 <- endpoint
- * in R1 <- *buffer
- * in R2 <- length of the buffer
- * out length of the recieved data -> R0 or -1 on error
- */
- _ep_read:
- push {r4, r5, lr}
- ldr r3, =#USB_EPBASE
- ldr r4, =#USB_PMABASE
- lsls r0, #28
- lsrs r0, #26
- adds r3, r0 // *EPR -> R3
- lsls r0, #1
- adds r4, r0 // *EPT -> R4
- ldrh r5, [r3] // reading epr
- /* validating endpoint */
- movs r0, #0x37
- lsls r0, #0x08
- ands r0, r5
- lsrs r0, #0x08
- cmp r0, #0x34 // (OK) RX_VALID + ISO
- beq .L_epr_iso
- cmp r0, #0x31 // (OK) RX_VALID + DBLBULK
- beq .L_epr_dbl
- cmp r0, #0x20 // (OK) RX_NAKED + BULK
- beq .L_epr_sngl
- cmp r0, #0x22 // (OK) RX_NAKED + CTRL
- beq .L_epr_sngl
- cmp r0, #0x26 // (OK) RX_NAKED + INTR
- beq .L_epr_sngl
- movs r0, #0xFF // endpoint contains no valid data
- sxtb r0, r0
- b .L_epr_exit
- /* processing */
- .L_epr_dbl:
- lsrs r0, r5, #8
- eors r0, r5
- lsrs r0, #7 // SW_RX ^ DTOG_RX -> CF
- bcs .L_epr_notog // jmp if SW_RX != DTOG_RX (VALID)
- ldr r0, =#EP_NOTOG
- ands r5, r0
- adds r5, #EP_RX_SWBUF
- strh r5, [r3] // toggling SW_RX
- .L_epr_notog:
- ldrh r5, [r3]
- lsls r5, #8 // shift SW_RX to DTOG_RX
- .L_epr_iso:
- lsrs r5, #15 // DTOG_RX -> CF
- bcs .L_epr_sngl
- subs r4, #0x04 // set RXADDR0
- .L_epr_sngl:
- ldrh r0, [r4, #RXCOUNT]
- lsrs r5, r0, #0x0A
- lsls r5, #0x0A // r5 = r0 & ~0x03FF
- strh r5, [r4, #RXCOUNT]
- lsls r0, #22
- lsrs r0, #22 // r0 &= 0x3FF (RX count)
- ldrh r5, [r4, #RXADDR]
- ldr r4, =#USB_PMABASE
- adds r5, r4 // R5 now has a physical address
- cmp r2, r0
- blo .L_epr_read
- mov r2, r0 // if buffer is larger
- .L_epr_read:
- cmp r2, #1
- blo .L_epr_read_end
- ldrh r4, [r5]
- strb r4, [r1]
- beq .L_epr_read_end
- lsrs r4, #8
- strb r4, [r1, #1]
- adds r1, #2
- adds r5, #2
- subs r2, #2
- bhi .L_epr_read
- .L_epr_read_end:
- ldrh r5, [r3] // reload EPR
- lsls r1, r5, #21
- lsrs r1, #29
- cmp r1, #0x04
- beq .L_epr_exit // ep is iso. no needs to set it to valid
- cmp r1, #0x01
- beq .L_epr_exit // ep is dblbulk. no needs to set it to valid
- ldr r2, =#TGL_SET(EP_RX_STAT , EP_RX_VAL)
- eors r5, r2
- lsrs r2, #16
- ands r5, r2
- strh r5, [r3] // set ep to VALID state
- .L_epr_exit:
- pop {r4, r5, pc}
- .size _ep_read, . - _ep_read
- .thumb_func
- .type _ep_write, %function
- /* int32_t ep_write(uint8_t ep, void *buf, uint16_t blen)
- * R0 -> endpoint
- * R1 -> *buffer
- * R2 -> data length
- *
- */
- _ep_write:
- push {r4, r5, r6, lr}
- ldr r3, =#USB_EPBASE
- ldr r4, =#USB_PMABASE
- lsls r0, #28
- lsrs r0, #26
- adds r3, r0 // *EPR -> R3
- lsls r0, #1
- adds r4, r0 // TXADDR0 -> R4
- ldrh r5, [r3] // reading epr
- movs r0, #0x73
- lsls r0, #4
- ands r0, r5
- lsrs r0, #4
- cmp r0, #0x43 // (OK) TX_VALID + ISO
- beq .L_epw_iso
- cmp r0, #0x12 // (OK) TX_NAK + DBLBULK
- beq .L_epw_dbl
- cmp r0, #0x02 // (OK) TX_NAK + BULK
- beq .L_epw_sngl
- cmp r0, #0x22 // (OK) TX_NAK + CONTROL
- beq .L_epw_sngl
- cmp r0, #0x62 // (OK) TX_NAK + INTERRUPT
- beq .L_epw_sngl
- movs r0, #0xFF
- sxtb r0, r0
- b .L_epw_exit
- .L_epw_dbl:
- mvns r5, r5
- lsrs r5, #8 // ~SWBUF_TX -> DTOG_TX
- .L_epw_iso:
- lsrs r5, #7 // DTOG_TX -> CF
- bcs .L_epw_sngl
- adds r4, #4 // TXADDR1 -> R4
- .L_epw_sngl:
- strh r2, [r4, #TXCOUNT]
- mov r0, r2 // save count for return
- ldrh r5, [r4, #TXADDR]
- ldr r4, =#USB_PMABASE
- adds r5, r4 // PMA BUFFER -> R5
- .L_epw_write:
- cmp r2, #1
- blo .L_epw_write_end
- ldrb r4, [r1]
- beq .L_epw_store
- ldrb r6, [r1, #1]
- lsls r6, #8
- orrs r4, r6
- .L_epw_store:
- strh r4, [r5]
- adds r5, #2
- adds r1, #2
- subs r2, #2
- bhi .L_epw_write
- .L_epw_write_end:
- ldrh r5, [r3] // reload EPR
- lsls r1, r5, #21
- lsrs r1, #29
- cmp r1, #0x04
- beq .L_epw_exit // isochronous ep. do nothing
- ldr r2, =#TGL_SET(EP_TX_STAT, EP_TX_VAL)
- cmp r1, #0x01
- bne .L_epw_setstate // NOT a doublebuffered bulk
- ldr r2, =#TGL_SET(EP_TX_SWBUF, EP_TX_SWBUF)
- bics r5, r2 // clear TX_SWBUF
- .L_epw_setstate:
- eors r5, r2
- lsrs r2, #16
- ands r5, r2
- strh r5, [r3]
- .L_epw_exit:
- pop {r4, r5, r6, pc}
- .size _ep_write, .- _ep_write
- /* internal function */
- /* requester size passed in R2 */
- /* result returns in R0 CF=1 if OK*/
- _get_next_pma:
- push {r1, r3, r4, lr}
- movs r1, #0x3C
- movs r3, #1
- lsls r3, #10 //R3 MAX_PMA_SIZE
- ldr r0, =#USB_PMABASE
- .L_gnp_chkaddr:
- ldrh r4, [r0, r1]
- tst r4, r4
- beq .L_gnp_nxtaddr
- cmp r3, r4
- blo .L_gnp_nxtaddr
- mov r3, r4
- .L_gnp_nxtaddr:
- subs r1, #0x04
- bhs .L_gnp_chkaddr
- subs r0, r3, r2
- blo .L_gnp_exit
- cmp r0, #0x20 //check for the pma table overlap
- .L_gnp_exit:
- pop {r1, r3, r4, pc}
- .size _get_next_pma, . - _get_next_pma
- .thumb_func
- .type _ep_config, %function
- /* bool ep_config(uint8_t ep, uint8_t eptype, uint16_t epsize)
- * R0 <- ep
- * R1 <- eptype
- * R2 <- epsize
- * result -> R0
- */
- _ep_config:
- push {r4, r5, lr}
- movs r3, 0x01
- ands r3, r2
- adds r2, r3 //R2 -> halfword aligned epsize
- movs r3, #0x00 //BULK
- cmp r1, #0x02 // is eptype bulk ?
- beq .L_epc_settype
- movs r3, #0x01 //DBLBULK
- cmp r1, #0x06
- beq .L_epc_settype
- movs r3, #0x02 //CONTROL
- cmp r1, #0x00
- beq .L_epc_settype
- movs r3, #0x04 //ISO
- cmp r1, #0x01
- beq .L_epc_settype
- movs r3, #0x06 //INTERRUPT
- .L_epc_settype:
- lsls r3, #8
- lsls r4, r0, #28
- lsrs r4, #28
- orrs r3, r4
- lsls r4, #2
- ldr r5, =#USB_EPBASE
- strh r3, [r5, r4] //setup EPTYPE EPKIND EPADDR
- cmp r1, #0x00 // is a control ep ?
- beq .L_epc_setuptx
- cmp r0, #0x80
- blo .L_epc_setuprx
- .L_epc_setuptx:
- ldr r5, =#USB_PMABASE
- lsls r4, #1
- adds r5, r4
- /* setup buffer table */
- /* TX or TX0 */
- bl _get_next_pma
- bcc .L_epc_fail
- strh r0, [r5, #TXADDR] //store txaddr or txaddr0
- movs r0, #0x00
- strh r0, [r5, #TXCOUNT] //store txcnt
- cmp r1, #0x06 // is DBLBULK
- beq .L_epc_txdbl
- ldr r3, =#TX_USTALL //set state NAKED , clr DTOG_TX
- cmp r1, #0x01
- bne .L_epc_txsetstate //if single buffered
- .L_epc_txdbl:
- /* TX1 */
- ldr r3, =#DTX_USTALL //set state VALID clr DTOG_TX & SWBUF_TX
- bl _get_next_pma
- bcc .L_epc_fail
- strh r0, [r5, #TXADDR1] //store txaddr1
- movs r0, #0x00
- strh r0, [r5, #TXCOUNT1] //store txcnt
- .L_epc_txsetstate:
- ldr r5, =#USB_EPBASE
- lsrs r4, #1
- ldrh r0, [r5, r4]
- eors r0, r3
- lsrs r3, #16
- ands r0, r3
- strh r0, [r5, r4]
- cmp r1, #0x00 //is a control ep ?
- bne .L_epc_exit
- .L_epc_setuprx:
- /* calculating RX_COUNT field. result in R3*/
- movs r3, r2
- cmp r2, #62
- bls .L_epc_rxbb
- /* ep size must be 32-byte aligned if >= 64 */
- movs r3, #0x1F
- adds r2, r3
- bics r2, r3
- lsrs r3, r2, #4
- adds r3, #0x3E
- .L_epc_rxbb:
- lsls r3, #9
- ldr r5, =#USB_PMABASE
- lsls r4, #1
- adds r5, r4
- /* setup buffer table */
- bl _get_next_pma
- bcc .L_epc_fail
- /* set RX or RX1 */
- strh r0, [r5, #RXADDR]
- strh r3, [r5, #RXCOUNT]
- ldr r0, =#RX_USTALL
- /* check if doublebuffered */
- cmp r1, 0x06 //if dblbulk
- beq .L_epc_rxdbl
- cmp r1, 0x01 // iso
- bne .L_epc_rxsetstate
- .L_epc_rxdbl:
- bl _get_next_pma
- bcc .L_epc_fail
- strh r0, [r5, #RXADDR0] //store rxaddr0
- strh r3, [r5, #RXCOUNT0] //store rxcnt0
- ldr r0, =#DRX_USTALL
- .L_epc_rxsetstate:
- ldr r5, =#USB_EPBASE
- lsrs r4, #1
- ldrh r3, [r5, r4]
- eors r3, r0
- lsrs r0, #16
- ands r3, r0
- strh r3, [r5, r4]
- .L_epc_exit:
- movs r0, #0x01
- pop {r4, r5, pc}
- .L_epc_fail:
- movs r0, #0x00
- pop {r4, r5, pc}
- .size _ep_config, . - _ep_config
- .thumb_func
- .type _ep_deconfig, %function
- /* void ep_deconfig( uint8_t ep)
- * R0 <- ep
- */
- _ep_deconfig:
- lsls r1, r0, #28
- lsrs r1, #26
- ldr r2, =#USB_EPBASE
- ldr r3, =#USB_PMABASE
- adds r2, r1
- lsls r1, #1
- adds r3, r1
- /* clearing endpoint register */
- ldr r1, =#EP_NOTOG
- ldrh r0, [r2]
- bics r0, r1
- strh r0, [r2]
- /* clearing PMA data */
- movs r0, #0x00
- strh r0, [r3, #TXADDR]
- strh r0, [r3, #TXCOUNT]
- strh r0, [r3, #RXADDR]
- strh r0, [r3, #RXCOUNT]
- bx lr
- .size _ep_deconfig, . - _ep_config
- #define ISTRSHIFT 8
- #define ISTRBIT(bit) ((1 << bit) >> ISTRSHIFT)
- .thumb_func
- .type _evt_poll, %function
- /*void evt_poll(usbd_device *dev, usbd_evt_callback callback)*/
- _evt_poll:
- push {r0, r1, r4, r5}
- ldr r3, =#USB_REGBASE
- ldrh r0, [r3, #4] //USB->ISTR -> R2
- /* ep_index -> R2 */
- movs r2, 0x07
- ands r2, r0
- /* checking USB->ISTR for events */
- #if !defined(USBD_SOF_DISABLED)
- lsrs r1, r0, #10 //SOFM -> CF
- bcs .L_ep_sofm
- #endif
- lsrs r1, r0, #16 //CTRM -> CF
- bcs .L_ep_ctrm
- lsrs r1, r0, #14 //ERRM -> CF
- bcs .L_ep_errm
- lsrs r1, r0, #13 //WKUPM -> CF
- bcs .L_ep_wkupm
- lsrs r1, r0, #12 //SUSPM -> CF
- bcs .L_ep_suspm
- lsrs r1, r0, #11 //RESETM -> CF
- bcs .L_ep_resetm
- /* exit with no callback */
- pop {r0, r1, r4 , r5}
- bx lr
- .L_ep_ctrm:
- movs r5, #0x80 // CTR_TX mask to R5
- ldr r0,=#USB_EPBASE
- lsrs r0, #2
- adds r0, r2
- lsls r0, #2 // R0 ep register address
- ldrh r4, [r0] // R4 EPR valur
- lsrs r3, r4, #8 // CTR_TX -> CF
- bcc .L_ep_ctr_rx
- /* CTR_TX event */
- movs r1, #usbd_evt_eptx
- orrs r2, r5 // set endpoint tx
- b .L_ep_clr_ctr
- .L_ep_ctr_rx:
- /* CTR_RX RX or SETUP */
- lsls r5, #0x08 // set mask to CRT_RX
- movs r1, #usbd_evt_eprx
- lsls r3, r4, #21 //SETUP -> CF
- bcc .L_ep_clr_ctr
- movs r1, #usbd_evt_epsetup
- .L_ep_clr_ctr:
- bics r4, r5 //clear CTR flag
- ldr r5, =#EP_NOTOG
- ands r4, r5
- strh r4, [r0] // store
- b .L_ep_callback
- .L_ep_errm:
- movs r1, #usbd_evt_error
- movs r4, #ISTRBIT(13)
- b .L_ep_clristr
- #if !defined(USBD_SOF_DISABLED)
- .L_ep_sofm:
- movs r1, #usbd_evt_sof
- movs r4, #ISTRBIT(9)
- b .L_ep_clristr
- #endif
- .L_ep_wkupm:
- ldrh r1, [r3, #USB_CNTR] //R1 USB->CNTR
- movs r5, #0x08
- bics r1, r5 //clr FSUSP
- strh r1, [r3, #USB_CNTR] //USB->CNTR R2
- movs r1, #usbd_evt_wkup
- movs r4, #ISTRBIT(12)
- b .L_ep_clristr
- .L_ep_suspm:
- ldrh r1, [r3, #USB_CNTR] //R1 USB->CNTR
- movs r5, #0x08
- orrs r1, r5 //set FSUSP
- strh r1, [r3, #USB_CNTR] //USB->CNTR R2
- movs r1, #usbd_evt_susp
- movs r4, #ISTRBIT(11)
- b .L_ep_clristr
- /* do reset routine */
- .L_ep_resetm:
- movs r1, #7
- ldr r2, =#USB_EPBASE
- ldr r0, =#USB_PMABASE
- ldr r5, =#EP_NOTOG
- .L_ep_reset_loop:
- ldrh r4, [r2]
- bics r4, r5
- strh r4, [r2]
- movs r4, #0x00
- strh r4, [r0, #TXADDR]
- strh r4, [r0, #TXCOUNT]
- strh r4, [r0, #RXADDR]
- strh r4, [r0, #RXCOUNT]
- adds r2, #4
- adds r0, #8
- subs r1, #1
- bhs .L_ep_reset_loop
- strh r4, [r3, #USB_BTABLE]
- movs r1, #usbd_evt_reset
- movs r4, #ISTRBIT(10)
- .L_ep_clristr:
- lsls r4, #ISTRSHIFT
- ldrh r0, [r3, #4]
- bics r0, r4
- strh r0, [r3, #4]
- .L_ep_callback:
- pop {r0, r3, r4, r5 }
- bx r3
- .size _evt_poll, . - _evt_poll
- .pool
- .end
- #endif //USBD_STM32L052
|