Jump to content

    
iva33

STM32L4 USB RXFIFO read RXFLVL flag not cleared

Recommended Posts

Доброй всем,

кто подскажет по какой то причине после загорания флажка RXFLVL при преёме setup паккета. после чтения флаг не тухнет. может я нетак четайо с fifo? в документах написано что должен сам тухнуть.

code:

;define
OTG_FS_H        equ 0x5000
OTG_FS_L        equ 0x0000

RX_FIFO_STR equ 0x1000

 

__usb_int    proc        
    push {LR}
    
    movw r9,#OTG_FS_L
    movt r9,#OTG_FS_H    
        
    ldr r0,[r9,#OTG_GINTSTS_B]
    tst r0,#USBRST
    beq jmp_usb_int_reset_skip
    bl _device_init
    b jmp_usb_int_end
    
jmp_usb_int_reset_skip    
    tst r0,#ENUMDNE
    beq  jmp_usb_int_enmflag_skip
    bl _device_enmflag
    b jmp_usb_int_end

jmp_usb_int_enmflag_skip    
    tst r0,#RXFLVL
    beq  jmp_usb_int_rx_skip

    ldr r0,[r9,#OTG_GRXSTSR_B]        ;
    and r1,r0,#EPNUM_MASK
    
    cmp r1,#ENPOINT0
    bne jmp_usb_int_rx_endpoint1
    bl _endpoint0_rx
    b jmp_usb_int_end
    
jmp_usb_int_rx_endpoint1    
    b jmp_usb_int_end
    
jmp_usb_int_rx_skip    
    tst r0,#IEPINT

jmp_usb_int_end
    pop {LR}    
    BX   LR
    endp    

 

_endpoint0_rx    proc    
    push {LR}
    ;acording to datasheet
    add r8,r9,#(RX_FIFO_STR)        ;point to rxfifo start
    
    and r1,r0,#PKTSTS_MASK
    cmp r1,#PKTSTS_SETUP_REC
    bne jmp_endpoint0_rx_setup_rec
    
    ;disable
    ldr r1,[r9,#OTG_GINTMSK_B]
    bic r1,#(RXFLVL)
    str r1,[r9,#OTG_GINTMSK_B]
    
    
    
    mov r1,#BCNT_MASK
    ands r1,r0                ;adviced to test BYT_COUNT before poping fifo to avoid undefined behavior!!!
    beq jmp_endpoint0_rx_end
    
    ;first 4byt are status data
    ldr r0,[r8]            
    mov r1,#BCNT_MASK
    and r1,r0
    lsr r1,#4            ;byte received
    and r2,r0,#FRMNUM_MASK
    lsr r2,#21
    
    ldr r3,[r8]            ;only 4byt read alowed
    ldr r4,[r8]    
    ;ldr r5,[r8],#4    
    
    mov32 r0,#(PKTCNT_CNT_OUT_MASK|STUPCNT_3PACK|0x40)            ;pack size max 64
    str r0,[r9,#OTG_DOEPTSIZ0_B]
    mov r0,#(CNAK)
    str r0,[r9,#OTG_DOEPCTL0_B]
    
    tst r3,#GET_BIT
    beq jmp_endpoint0_rx_setup_set
    
    and r1,r3,#GET_2BYT_MASK
    cmp r1,#GET_DESKRIPTOR
    bne jmp_endpoint0_rx_setup_get_next
    
    and r1,r3,#GET_4BYT_MASK
    cmp r1,#DEVICE_DESCRIPTOR
    bne jmp_endpoint0_rx_setup_get_next_descriptor
    
;    bl _send_device_descriptor
    b jmp_endpoint0_rx_setup_get_end
    
jmp_endpoint0_rx_setup_get_next_descriptor    
    b jmp_endpoint0_rx_end
    
    
;---------- setup get ----------------------------------------
jmp_endpoint0_rx_setup_get_next
jmp_endpoint0_rx_setup_get_end
    ldr r0,[r9,#OTG_GINTMSK_B]
    orr r0,#(RXFLVL)
    str r0,[r9,#OTG_GINTMSK_B]
    b jmp_endpoint0_rx_end
    
;*****SETUP set cmd    ***************************
jmp_endpoint0_rx_setup_set    
    
    ldr r0,[r9,#OTG_GINTMSK_B]
    mov r0,#(RXFLVL)
    str r0,[r9,#OTG_GINTMSK_B]
    b jmp_endpoint0_rx_end
    
    
jmp_endpoint0_rx_setup_rec
    cmp r1,#PKTSTS_SETUP_CMPL
    bne jmp_endpoint0_rx_out_cmpl

    mov32 r0,#(PKTCNT_CNT_OUT_MASK|STUPCNT_3PACK|0x40)            ;pack size max 64
    str r0,[r9,#OTG_DOEPTSIZ0_B]
    mov r0,#(CNAK)
    str r0,[r9,#OTG_DOEPCTL0_B]
    
    ;bl _send_device_descriptor
    
    b jmp_endpoint0_rx_end

jmp_endpoint0_rx_out_cmpl
    cmp r1,#PKTSTS_OUT_CMPL
    bne jmp_endpoint0_rx_next

    ldr r0,[r8]    
    
    b jmp_endpoint0_rx_end    
    
    
jmp_endpoint0_rx_next
    ldr r0,[r9,#OTG_GINTMSK_B]
    ;bic r0,#(RXFLVL)
    ;str r0,[r9,#OTG_GINTMSK_B]
    ;ldr r0,[r8]    
    ;mov r0,#0
    ;str r0,[r8]        

jmp_endpoint0_rx_end    
    pop {LR}
    BX   LR
    endp   

 

Share this post


Link to post
Share on other sites

Да, должен сам тухнуть. Вот функции чтения FIFO. Не забыть позаботиться о выравнивании буфера куда читаете. Иначе лучше через временную uint32_t переменную и из неё побайтно.

static inline void ReadSetupFIFO(uint8_t *adr)
{
  //Прочитать SETUP пакет из FIFO, он всегда 8 байт
  *(uint32_t *)adr = *otg_dfifo<0>();
  *((uint32_t *)adr+1) = *otg_dfifo<0>();
}

static inline void ReadFIFO(uint8_t *dest, uint16_t len)
{
  for ( uint32_t words2read = (len+3)>>2; words2read--; dest += 4 )
    *(uint32_t *)dest = *otg_dfifo<0>();
}

Ну и немножко отомщу за асм. :)

В файлах обработчик прерываний. Там для FS и HS сразу, поэтому немного раздуто, но работу с битами видно хорошо.

stm32_usb_otg.cpp

stm32_usb_otg.hpp

Share this post


Link to post
Share on other sites
1 час назад, VladislavS сказал:

В файлах обработчик прерываний.

Извиняюсь, что влезаю:

#ifndef USB_OTG_FS_MAX_IN_ENDPOINTS
#define USB_OTG_FS_MAX_IN_ENDPOINTS 4
#endif

#ifndef USB_OTG_FS_MAX_OUT_ENDPOINTS
#define USB_OTG_FS_MAX_OUT_ENDPOINTS 4
#endif

...
  
      static_assert((ep_num<4),"Wrong ep_num");

Просто бросилось в глаза.

Share this post


Link to post
Share on other sites
12 часов назад, iva33 сказал:

может я нетак четайо с fifo?

"Не так" у вас с кодом.....

12 часов назад, iva33 сказал:

__usb_int    proc        
    push {LR}
    
    movw r9,#OTG_FS_L
    movt r9,#OTG_FS_H    

...

_endpoint0_rx    proc    
    push {LR}
    ;acording to datasheet
    add r8,r9,#(RX_FIFO_STR)        ;point to rxfifo start
...    

Это что - содержимое ISR? :shok: А Вас не смущает, что портите содержимое R9, R8? Как у Вас после такого фоновая программа вообще работает???  :unknw:

Почитайте учебник про "Сохранение/восстановление контекста в Cortex-M при входе/выходе из прерывания".

 

12 часов назад, iva33 сказал:

bl _endpoint0_rx

И не смущает, что здесь вызываете функцию на стеке невыровненном на границу 64 бит?

Хотя, если и эта функция (и всё, что ниже неё по дереву вызовов) написана тоже на асме - то может быть это и позволительно.

 

12 часов назад, iva33 сказал:

pop {LR}
BX   LR

Здесь достаточно просто: POP PC

И в функции _endpoint0_rx сохранять LR не нужно, так как он в ней не портится и из неё нет вызовов других функций.

Share this post


Link to post
Share on other sites
6 hours ago, jcxz said:

"Не так" у вас с кодом.....

Это что - содержимое ISR? :shok: А Вас не смущает, что портите содержимое R9, R8? Как у Вас после такого фоновая программа вообще работает???  :unknw:

Почитайте учебник про "Сохранение/восстановление контекста в Cortex-M при входе/выходе из прерывания".

 

И не смущает, что здесь вызываете функцию на стеке невыровненном на границу 64 бит?

Хотя, если и эта функция (и всё, что ниже неё по дереву вызовов) написана тоже на асме - то может быть это и позволительно.

 

Здесь достаточно просто: POP PC

И в функции _endpoint0_rx сохранять LR не нужно, так как он в ней не портится и из неё нет вызовов других функций.

Всем спасибо за старания.
попробую объяснить что push и  pop LR нужен каждый раз перед использыванием Branch LR иначе его не восстановить и  не вазможна будет вернуться на исходную программу. весь код на асембли поэтому кручу регистерами как хочу r0-r12, регистры ISR r13 регистер ЛИНКА(LR) r14 и тд....

Share this post


Link to post
Share on other sites
4 минуты назад, iva33 сказал:

pop LR нужен каждый раз перед использыванием Branch LR

Подумайте - а что делает Branch LR? Что делает связка POP LR + BX LR? И что делает посоветованный вам POP PC.

7 минут назад, iva33 сказал:

иначе его не восстановить

А зачем восстанавливать, если его никто не испортил?

Share this post


Link to post
Share on other sites

с кодам всё хорошо и он не плохо работает (хотя многа надо доделать) . ошибка нашлась неправильно обеснили  в даташеет, не смотря что вобьеснениях написана что через адрес 0х5000 1000- 1ffc  можна четать фифо, но не стерает флаг. нужна четать через регистр OTG_GRXSTSP (0x5000 0020), хотя абетом не где асоба не написано а указан адрес  0х5000 1000 , тока в описаниях регистра написано што он для pop.

Share this post


Link to post
Share on other sites
54 minutes ago, Сергей Борщ said:

Подумайте - а что делает Branch LR? Что делает связка POP LR + BX LR? И что делает посоветованный вам POP PC.

А зачем восстанавливать, если его никто не испортил?

Регистр ЛИНКА предназначен для возвращения к исходной программе при пришке БЛ или при interupt (пре interupt туда сохроняетса спецальный код ). PC используется восновном компилире а вручную тока втаблицах, его не стоет особо трогать чтоб не застрять между кодам .

Share this post


Link to post
Share on other sites
21 минуту назад, iva33 сказал:

попробую объяснить что push и  pop LR нужен каждый раз перед использыванием Branch LR иначе его не восстановить и  не вазможна будет вернуться на исходную программу.

Ещё раз перечитайте внимательнее:

6 часов назад, jcxz сказал:

И в функции _endpoint0_rx сохранять LR не нужно, так как он в ней не портится и из неё нет вызовов других функций.

 

21 минуту назад, iva33 сказал:

весь код на асембли поэтому кручу регистерами как хочу r0-r12

А что - у вас кроме этого ISR никакого другого кода нет? Нет ни фонового процесса, ни других ISR?

Если так - то наверное можно. Но это какой-то странный случай.... :wacko2:

Share this post


Link to post
Share on other sites
49 minutes ago, jcxz said:

Ещё раз перечитайте внимательнее:

 

А что - у вас кроме этого ISR никакого другого кода нет? Нет ни фонового процесса, ни других ISR?

Если так - то наверное можно. Но это какой-то странный случай.... :wacko2:

endpoint0_rx    не надо (пока) но иногда пишу автоматом при открытии функции. пишу на проге КЕЙЛ тока АССЕМБЛИ. там есть C и ТП  но люблю всё контролиривать и не люблю искать функции и внекат что там на крутили (работаю напрямую с даташеет).
  

Share this post


Link to post
Share on other sites
1 минуту назад, iva33 сказал:

люблю всё контролиривать и не люблю искать функции и внекат что там на крутили (работаю напрямую с даташеет).  

Когда напишете другой ISR или фоновый процесс, в котором будут использоваться R8,R9; вот тогда эти грабли вам и съездят по лбу.  :unknw:

Share this post


Link to post
Share on other sites

xx proc    
    push {LR}

pop {LR}
    BX   LR
    endp   

всегда гарантирует хороший исход.

48 minutes ago, jcxz said:

Когда напишете другой ISR или фоновый процесс, в котором будут использоваться R8,R9; вот тогда эти грабли вам и съездят по лбу.  :unknw:

Все нормально у меня щас код на 80к и проблем нет с использыванием регистеров.

Edited by iva33

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.