/* This file is the part of the Lightweight USB device Stack for STM32 microcontrollers * * Copyright ©2016 Dmitry Filimonchuk * * 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 #if defined(STM32F070x6) || defined(STM32F070xB) || \ defined(STM32F042x6) || defined(STM32F048xx) || \ defined(STM32F072xB) || defined(STM32F078xx) #define UID_OFFSET_0 0x00 #define UID_OFFSET_1 0x04 #define UID_OFFSET_2 0x08 #else #define UID_OFFSET_0 0x00 #define UID_OFFSET_1 0x04 #define UID_OFFSET_2 0x14 #endif #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 .section .rodata.usbd_devfs_asm .align 4 .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, UID_OFFSET_0] //UID0 bl .L_fnv1a ldr r2, [r5, UID_OFFSET_1] //UID1 bl .L_fnv1a ldr r2, [r5, UID_OFFSET_2] //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, #18 cmp r0, #0x80 blo .L_eis_check lsls r1, #8 .L_eis_check: lsrs r0, r1, #30 subs r0, #0x01 subs r1, r0, #0x01 sbcs r0, r0 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, const 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