xwkm 发表于 2013-7-12 11:47:48

LGT 最小系统板测评

本帖最后由 xwkm 于 2013-7-12 22:47 编辑

在两天前我向LGT工作人员申请了样品和工具。现在依然在试用和编程中。
今天搞完了内置32MHz的R/C振荡器V-USB。顺带靠测量D-脉冲写了个R/C振荡器自动校准程序。
不过依然有bug。而且不是完美解决。

xwkm 发表于 2013-7-12 22:49:12

上板图




关于这个板子的各种开发我会陆续公布在这个帖子上。
明天争取解决振荡器校准的问题/

goodcode 发表于 2013-7-12 23:40:34

不知道楼主有时间能不能测一下vusb跑在32m的速度{:lol:}

附件里是个测试工程上位机有c的和delphi的

xwkm 发表于 2013-7-13 00:01:38

本帖最后由 xwkm 于 2013-7-13 00:04 编辑

goodcode 发表于 2013-7-12 23:40 static/image/common/back.gif
不知道楼主有时间能不能测一下vusb跑在32m的速度

附件里是个测试工程上位机有c的和delphi的 ...

暂时还没有自己移植个32M的打算。内部RC不算特别稳定。
现在在内振上跑的2分频。
LGT8F88A进中断的时序貌似发生了一些改变。所以12M的驱动估计得大改了。
当然我要试试移植个24M的V-USB。
不过目前最棘手的问题就是88A的OSCCAL自动校准问题。我得找个最好的解决方案来解决。
不过其实不解决也不是不可以。因为现在的8F88A都已经校准过。没啥大问题。
我写这个校准算法主要是想提高稳定性。并且想在8F08A上无外振V-USB……

xwkm 发表于 2013-7-13 00:03:06

本帖最后由 xwkm 于 2013-7-13 00:08 编辑

不过说实话等到最后的校准算法出来后估计USBasp会更省料了。晶振都可以省掉了。
另外就是以前的in + sbrs指令可以直接换成nop + sbis了。LGT8F88A没有了IO同步的问题。
关于Bootloader的制作我是想好好省下料。最好做到不用接任何器件。只要VCC D+ D- GND接了就可以连接电脑下载。
这样开发板成本可以大幅降低。毕竟现在LGT时钟准了不少。不好好利用下也不是咱作风啊。
PS:实验板是公版V-USB的设计.所以如果以后要给实验板开发V-USB程序可以不用改IO部分.

90999 发表于 2013-7-13 00:05:51

奇怪了,我十几年没撸了,怎么看东西还有重影啊?肯定是肾亏了。

xwkm 发表于 2013-7-13 00:07:32

楼上对不起。相机没有防抖功能.

danju 发表于 2013-7-13 00:11:07

LGT跟AVR那样皮实不?

lawdown 发表于 2013-7-13 00:16:50

90999 发表于 2013-7-13 00:05 static/image/common/back.gif
奇怪了,我十几年没撸了,怎么看东西还有重影啊?肯定是肾亏了。

你太幽默了{:lol:}

xwkm 发表于 2013-7-13 00:37:41

danju 发表于 2013-7-13 00:11 static/image/common/back.gif
LGT跟AVR那样皮实不?

目前我还没坏过一片……

HYLG 发表于 2013-7-13 01:02:00

顶楼主为大伙造福。

LGT 发表于 2013-7-13 10:08:55

楼主辛苦了!!

LGT 发表于 2013-7-13 10:11:59

danju 发表于 2013-7-13 00:11 static/image/common/back.gif
LGT跟AVR那样皮实不?

楼上可以整几片LGT8F88A测试下, 看是不是和AVR一样皮实!:)

goodcode 发表于 2013-7-13 11:57:00

/* Name: usbdrvasm12.inc
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2004-12-29
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id$
*/

/* Do not link this file! Link usbdrvasm.S instead, which includes the
* appropriate implementation!
*/

/*
General Description:
This file is the 12 MHz version of the asssembler part of the USB driver. It
requires a 12 MHz crystal (not a ceramic resonator and not a calibrated RC
oscillator).

See usbdrv.h for a description of the entire driver.

Since almost all of this code is timing critical, don't change unless you
really know what you are doing! Many parts require not only a maximum number
of CPU cycles, but even an exact number of cycles!


Timing constraints according to spec (in bit times):
timing subject                                    min max    CPUcycles
---------------------------------------------------------------------------
EOP of OUT/SETUP to sync pattern of DATA0 (both rx) 2   16   16-128
EOP of IN to sync pattern of DATA0 (rx, then tx)    2   7.5    16-60
DATAx (rx) to ACK/NAK/STALL (tx)                  2   7.5    16-60
*/

#if USB_CFG_CLOCK_KHZ == 12000
        #define nop8
#elif USB_CFG_CLOCK_KHZ == 24000
        #define nop8                rcall delay8
#else
        #error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
#endif

;Software-receiver engine. Strict timing! Don't change unless you can preserve timing!
;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled
;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable
;max stack usage: = 11 bytes
;Numbers in brackets are maximum cycles since SOF.
USB_INTR_VECTOR:
;order of registers pushed: YL, SREG , YH, shift, x1, x2, x3, cnt
    push    YL            ;2 push only what is necessary to sync with edge ASAP
    in      YL, SREG      ;1
    push    YL            ;2
        push         x5                                ; //新增加寄存器变量
;----------------------------------------------------------------------------
; Synchronize with sync pattern:
;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100
;sync up with J to K edge during sync pattern -- use fastest possible loops
;The first part waits at most 1 bit long since we must be in sync pattern.
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
;原始LGT 移植代码 此处可能会引起错误当开启USB_COUNT_SOF, USB_SOF_HOOK或者电平错误时将导致死循环或不执行代码
;通过增加新寄存器变量修正
waitForJ:
    inc   YL
    in                x5,         USBIN
    sbrs    x5,         USBMINUS
    brne    waitForJ      ; just make sure we have ANY timeout
waitForK:
;The following code results in a sampling window of 1/4 bit which meets the spec.
    in                x5,         USBIN
    sbrs    x5,         USBMINUS
    rjmp    foundK
    in                x5,         USBIN
    sbrs    x5,         USBMINUS
    rjmp    foundK
    in                x5,         USBIN
    sbrs    x5, USBMINUS
    rjmp    foundK
    in                x5,         USBIN
    sbrs    x5,         USBMINUS
    rjmp    foundK
    in                x5,         USBIN
    sbrs    x5,         USBMINUS
    rjmp    foundK

#if USB_CFG_CLOCK_KHZ == 24000
    in                x5,         USBIN
    sbrs    x5, USBMINUS
    rjmp    foundK
    in                x5,         USBIN
    sbrs    x5,         USBMINUS
    rjmp    foundK
    in                x5,         USBIN
    sbrs    x5,         USBMINUS
    rjmp    foundK
#endif

#if USB_COUNT_SOF
    lds   YL, usbSofCount
    inc   YL
    sts   usbSofCount, YL
#endif/* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
    USB_SOF_HOOK
#endif
    rjmp    sofError
foundK:
;{3, 5} after falling D- edge, average delay: 4 cycles
;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
;are cycles from center of first sync (double K) bit after the instruction
    push    YH                          ;1
        nop
    lds   YL, usbInputBufOffset        ;2
    clr   YH                          ;1
    subi    YL, lo8(-(usbRxBuf))        ;1
    sbci    YH, hi8(-(usbRxBuf))        ;1

        in      x5,    USBIN                        ;1
        sbrs        x5,    USBMINUS                        ;1
    ;sbis    USBIN, USBMINUS ;1 we want two bits K
    rjmp    haveTwoBitsK                    ;1
    pop   YH                                     ;1 undo the push from before
    rjmp    waitForK                      ;1 this was not the end of sync, retry
haveTwoBitsK:
;----------------------------------------------------------------------------
; push more registers and initialize values while we sample the first bits:
;----------------------------------------------------------------------------
    push    shift                                  ;1 ;2
    push    x1                            ;1 ;2
    push    x2                                     ;1 ;2
    ;原始LGT 移植代码 此处引起关键错误 可能因为上面读寄存器引起的时序偏差导致读bit 0后移
        ;未使用逻辑分析仪跟踪分析 上面只是推测减少两个时钟的延迟就无错误数据出现 说明读取bit 0
        ;向后移了很多
        ;nop2                                                  ;2
    ;nop                                                          ;1
        ;新代码
        nop

    in      x1, USBIN       ;1 <-- sample bit 0
    ldi   shift, 0xff   ;1
    bst   x1, USBMINUS    ;1
    bld   shift, 0      ;1
    push    x3            ;1 ;2
    push    cnt             ;1 ;2
    nop2                  ;2
   
    in      x2, USBIN       ;1 <-- sample bit 1
    ser   x3            ;1
    eor   x1, x2          ;1
    bst   x1, USBMINUS    ;1
    bld   shift, 1      ;1
    ldi   cnt, USB_BUFSIZE;1
    nop                          ;1
    rjmp    rxbit2          ;1 ;2

;----------------------------------------------------------------------------
; Receiver loop (numbers in brackets are cycles within byte after instr)
;----------------------------------------------------------------------------

unstuff0:               ;1 (branch taken)
    andi    x3, ~0x01   ;1
    mov   x1, x2      ;1 x2 contains last sampled (stuffed) bit
    in      x2, USBIN   ;1 <-- sample bit 1 again
    ori   shift, 0x01 ;1
    nop                        ;1
    rjmp    didUnstuff0 ;1 ;2

unstuff1:               ;1 (branch taken)
    mov   x2, x1      ;1 x1 contains last sampled (stuffed) bit
    andi    x3, ~0x02   ;1
    ori   shift, 0x02 ;1
    nop               ;1
    in      x1, USBIN   ;1 <-- sample bit 2 again
    nop                        ;1
    rjmp    didUnstuff1 ;1 ;2

unstuff2:               ;1 (branch taken)
    andi    x3, ~0x04   ;1
    ori   shift, 0x04 ;1
    mov   x1, x2      ;1 x2 contains last sampled (stuffed) bit
    nop               ;1
    in      x2, USBIN   ;1 <-- sample bit 3
    nop                        ;1
    rjmp    didUnstuff2 ;1 ;2

unstuff3:               ;1 (branch taken)
    in      x2, USBIN   ;1 <-- sample stuffed bit 3
    andi    x3, ~0x08   ;1
    ori   shift, 0x08 ;1
    nop                        ;1
    rjmp    didUnstuff3 ;1 ;2

unstuff4:               ;1 (branch taken)
    andi    x3, ~0x10   ;1
    in      x1, USBIN   ;1 <-- sample stuffed bit 4
    ori   shift, 0x10 ;1
    nop                        ;1
    rjmp    didUnstuff4 ;1 ;2

unstuff5:               ;1 (branch taken)
    andi    x3, ~0x20   ;1
    in      x2, USBIN   ;1 <-- sample stuffed bit 5
    ori   shift, 0x20 ;1
    nop                        ;1
    rjmp    didUnstuff5 ;1 ;2

unstuff6:               ;1 (branch taken)
    andi    x3, ~0x40   ;1
    in      x1, USBIN   ;1 <-- sample stuffed bit 6
    ori   shift, 0x40 ;1
    nop                        ;1
    rjmp    didUnstuff6 ;1 ;2

; extra jobs done during bit interval:
; bit 0:    store, clear
; bit 1:    se0 check
; bit 2:    overflow check
; bit 3:    recovery from delay
; bit 4:    none
; bit 5:    none
; bit 6:    none
; bit 7:    jump, eor
rxLoop:
    eor   x3, shift   ;1 reconstruct: x3 is 0 at bit locations we changed, 1 at others
    in      x1, USBIN   ;1 <-- sample bit 0
    nop                        ;1
    st      y+, x3      ;1 ;2 store data
    ser   x3          ;1
    nop               ;1
    eor   x2, x1      ;1
    bst   x2, USBMINUS;1
    bld   shift, 0    ;1
    in      x2, USBIN   ;1 <-- sample bit 1 (or possibly bit 0 stuffed)
    andi    x2, USBMASK ;1
    breq    se0         ;1 SE0 check for bit 1
    andi    shift, 0xf9 ;1
didUnstuff0:
    breq    unstuff0    ;1
    eor   x1, x2      ;1
    bst   x1, USBMINUS;1
    bld   shift, 1    ;1
rxbit2:
    in      x1, USBIN   ;1 <-- sample bit 2 (or possibly bit 1 stuffed)
    andi    shift, 0xf3 ;1
    breq    unstuff1    ;1 do remaining work for bit 1
didUnstuff1:
    subi    cnt, 1      ;1
    brcs    overflow    ;1 loop control
    eor   x2, x1      ;1
    bst   x2, USBMINUS;1
    bld   shift, 2    ;1
    in      x2, USBIN   ;1 <-- sample bit 3 (or possibly bit 2 stuffed)
    andi    shift, 0xe7 ;1
    breq    unstuff2    ;1
didUnstuff2:
    eor   x1, x2      ;1
    bst   x1, USBMINUS;1
    bld   shift, 3    ;1
didUnstuff3:
    andi    shift, 0xcf ;1
    breq    unstuff3    ;1
    in      x1, USBIN   ;1 <-- sample bit 4
    eor   x2, x1      ;1
    bst   x2, USBMINUS;1
    bld   shift, 4    ;1
didUnstuff4:
    andi    shift, 0x9f ;1
    breq    unstuff4    ;1
    nop2                ;2
    in      x2, USBIN   ;1 <-- sample bit 5
    eor   x1, x2      ;1
    bst   x1, USBMINUS;1
    bld   shift, 5    ;1
didUnstuff5:
    andi    shift, 0x3f ;1
    breq    unstuff5    ;1
    nop2                ;2
    in      x1, USBIN   ;1 <-- sample bit 6
    eor   x2, x1      ;1
    bst   x2, USBMINUS;1
    bld   shift, 6    ;1
didUnstuff6:
    cpi   shift, 0x02 ;1
    brlo    unstuff6    ;1
    nop2                ;2
    in      x2, USBIN   ;1 <-- sample bit 7
    eor   x1, x2      ;1
    bst   x1, USBMINUS;1
    bld   shift, 7    ;1
didUnstuff7:
    cpi   shift, 0x04 ;1
    brsh    rxLoop      ;2 loop control
unstuff7:
    andi    x3, ~0x80   ;1
    ori   shift, 0x80 ;1
    in      x2, USBIN   ;1 <-- sample stuffed bit 7
    nop2                ;2 ;1
    rjmp    didUnstuff7 ;1 ;2

macro POP_STANDARD ; 12 cycles
    pop   cnt
    pop   x3
    pop   x2
    pop   x1
    pop   shift
    pop   YH
    endm
macro POP_RETI   ; 5 cycles
        pop                x5
    pop   YL
    out   SREG, YL
    pop   YL
    endm

#include "asmcommon.inc"

;----------------------------------------------------------------------------
; Transmitting data
;----------------------------------------------------------------------------

txByteLoop:
txBitloop:
stuffN1Delay:                   ;   
    ror   shift               ;[-5]
    brcc    doExorN1            ;[-4]      
    subi    x4, 1               ;[-3]
    brne    commonN1            ;[-2]
    lsl   shift               ;[-1] compensate ror after rjmp stuffDelay
    nop                         ; stuffing consists of just waiting 8 cycles
        nop
    rjmp    stuffN1Delay      ; after ror, C bit is reliably clear

sendNakAndReti:               ;0 [-19] 19 cycles until SOP
    ldi   x3, USBPID_NAK      ;1 [-18]
    nop                                ;1 [-17]
    rjmp    usbSendX3         ;1;[-16];2 [-16]
sendAckAndReti:               ;0 [-19] 19 cycles until SOP
    ldi   x3, USBPID_ACK      ;1 [-18]
    nop                                ;1 [-17]
    rjmp    usbSendX3         ;1 [-16];2 [-16]
sendCntAndReti:               ;0 [-17] 17 cycles until SOP
    nop
        mov   x3, cnt             ;1 [-16]
usbSendX3:                      ;0 [-16]
    ldi   YL, 20            ;1 [-15] 'x3' is R20
    ldi   YH, 0               ;1 [-14]
    ldi   cnt, 2            ;1 [-13]
;   rjmp    usbSendAndReti      fallthrough

; USB spec says:
; idle = J
; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)

;usbSend:
;pointer to data in 'Y'
;number of bytes in 'cnt' -- including sync byte
;uses: x1...x2, x4, shift, cnt, Y
;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
usbSendAndReti:
    in      x2, USBDDR          ;[-12] 12 cycles until SOP
    ori   x2, USBMASK         ;[-11]
    sbi   USBOUT, USBMINUS    ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
    nop                                ;[-9]
    out   USBDDR, x2          ;[-8] <--- acquire bus
    in      x1, USBOUT          ;[-7] port mirror for tx loop
    ldi   shift, 0x40         ;[-6] sync byte is first byte sent (we enter loop after ror)
    ldi   x2, USBMASK         ;[-5]
    push    x4                  ;[-4]
    nop                                ;[-3]
doExorN1:
    eor   x1, x2            ;[-2]
    ldi   x4, 6               ;[-1]
commonN1:
stuffN2Delay:
    out   USBOUT, x1          ; <--- set bit
    ror   shift               ;
    brcc    doExorN2            ;
    subi    x4, 1               ;
    brne    commonN2            ;
    lsl   shift               ; compensate ror after rjmp stuffDelay
    nop                                ;
    rjmp    stuffN2Delay      ;; after ror, C bit is reliably clear
doExorN2:
    eor   x1, x2            ;
    ldi   x4, 6               ;
commonN2:
    nop                         ;
    subi    cnt, 171            ; trick: (3 * 171) & 0xff = 1
    out   USBOUT, x1          ; <--- set bit
    brcs    txBitloop         ;      

stuff6Delay:
    ror   shift               ;
    brcc    doExor6             ;
    subi    x4, 1               ;
    brne    common6             ;
    lsl   shift               ; compensate ror after rjmp stuffDelay
    nop2                        ; stuffing consists of just waiting 8 cycles
    rjmp    stuff6Delay         ; after ror, C bit is reliably clear
doExor6:
    eor   x1, x2            ;
    ldi   x4, 6               ;
common6:
stuff7Delay:
    ror   shift               ;
    out   USBOUT, x1          ; <--- set bit
    brcc    doExor7             ;
    subi    x4, 1               ;
    brne    common7             ;
    lsl   shift               ; compensate ror after rjmp stuffDelay
        nop
    rjmp    stuff7Delay         ; after ror, C bit is reliably clear
doExor7:
    eor   x1, x2            ;
    ldi   x4, 6               ;
common7:
    ld      shift, y+         ;
    nop                                                        ;
    tst   cnt               ;;
    out   USBOUT, x1          ;; <--- set bit
    ;brne   txByteLoop                        ;
    breq    makeSE0                                ;
    rjmp    txByteLoop          ;

makeSE0:
;make SE0:
    cbr   x1, USBMASK         ; prepare SE0
    lds   x2, usbNewDeviceAddr;
    lsl   x2                  ; we compare with left shifted address
    subi    YL, 2 + 20          ; Only assign address on data packets, not ACK/NAK in x3
    out   USBOUT, x1          ; <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
    sbci    YH, 0               ;
;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
;set address only after data packet was sent, not after handshake
    breq    skipAddrAssign      ;
    sts   usbDeviceAddr, x2   ; if not skipped: SE0 is one cycle longer
skipAddrAssign:
;end of usbDeviceAddress transfer
    ldi   x2, 1<<USB_INTR_PENDING_BIT; int0 occurred during TX -- clear pending flag
    USB_STORE_PENDING(x2)       ;
    ori   x1, USBIDLE         ;
    in      x2, USBDDR          ;
    cbr   x2, USBMASK         ; set both pins to input
    mov   x3, x1            ;
    cbr   x3, USBMASK         ; configure no pullup on both pins
    pop   x4                  ;
    nop2                        ;
    nop2                        ;
    out   USBOUT, x1          ; <-- out J (idle) -- end of SE0 (EOP signal)
    out   USBDDR, x2          ; <-- release bus now
    out   USBOUT, x3          ; <-- ensure no pull-up resistors are active
    rjmp    doReturn

;延时8个时钟周期从调用到返回
;rcall delay8                        ;
;xxx        ;
#if USB_CFG_CLOCK_KHZ == 24000
delay8:
        nop                                                ;
        nop                                                ;
        nop                                                ;
        nop                                                ;
        nop                                                ;
        ret                                                ;
#endif
只为测速度这个也许还能用
不过跑32m用这种代码有些浪费了, 最好从usbdrvasm18-crc.inc类似的文件移植
之前测试内部rc在常温下还是很稳定的 不过温度如果变化大些就会出问题

我的想法刚好相反用PL2303+LGT完成编程器, 波特率到5000kbps或1mbps 这个速度是vusb不能比的
目前用上面这种方案使用swim协议读stm8 8kflash只要500多ms swim还是跑在低速位格式{:lol:}

xwkm 发表于 2013-7-13 12:25:16

goodcode 发表于 2013-7-13 11:57 static/image/common/back.gif
只为测速度这个也许还能用
不过跑32m用这种代码有些浪费了, 最好从usbdrvasm18-crc.inc类似的文件移植
之前 ...

没错。确实V-USB速度快不了。不过PL-2303焊接有点难度。当然在linux下兼容性不错。win下就不知道了……
另外就是我没有移植32M的。用的16M分频而已。我尽量弄个原生32M CRC的。
LGT8F88A貌似进中断比标准AVR和08A慢一点。所以你的12M代码不能用。应该这个:/* Name: usbdrvasm12.inc
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2004-12-29
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id$
*/

/* Do not link this file! Link usbdrvasm.S instead, which includes the
* appropriate implementation!
*/

/*
General Description:
This file is the 12 MHz version of the asssembler part of the USB driver. It
requires a 12 MHz crystal (not a ceramic resonator and not a calibrated RC
oscillator).

See usbdrv.h for a description of the entire driver.

Since almost all of this code is timing critical, don't change unless you
really know what you are doing! Many parts require not only a maximum number
of CPU cycles, but even an exact number of cycles!


Timing constraints according to spec (in bit times):
timing subject                                    min max    CPUcycles
---------------------------------------------------------------------------
EOP of OUT/SETUP to sync pattern of DATA0 (both rx) 2   16   16-128
EOP of IN to sync pattern of DATA0 (rx, then tx)    2   7.5    16-60
DATAx (rx) to ACK/NAK/STALL (tx)                  2   7.5    16-60
*/

;Software-receiver engine. Strict timing! Don't change unless you can preserve timing!
;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled
;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable
;max stack usage: = 11 bytes
;Numbers in brackets are maximum cycles since SOF.
USB_INTR_VECTOR:
        nop
;order of registers pushed: YL, SREG , YH, shift, x1, x2, x3, cnt
    push    YL            ;2 push only what is necessary to sync with edge ASAP
    in      YL, SREG      ;1
    push    YL            ;2
;----------------------------------------------------------------------------
; Synchronize with sync pattern:
;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100
;sync up with J to K edge during sync pattern -- use fastest possible loops
;The first part waits at most 1 bit long since we must be in sync pattern.
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ:
    inc   YL
    //in                YL,         USBIN
    sbis    USBIN,         USBMINUS
    brne    waitForJ      ; just make sure we have ANY timeout
waitForK:
;The following code results in a sampling window of 1/4 bit which meets the spec.
    //in                YL,         USBIN
    sbis    USBIN,         USBMINUS
    rjmp    foundK
    //in                YL,         USBIN
    sbis    USBIN,         USBMINUS
    rjmp    foundK
    //in                YL,         USBIN
    sbis    USBIN, USBMINUS
    rjmp    foundK
    //in                YL,         USBIN
    sbis    USBIN,         USBMINUS
    rjmp    foundK
    //in                YL,         USBIN
    sbis    USBIN,         USBMINUS
    rjmp    foundK
#if USB_COUNT_SOF
    lds   YL, usbSofCount
    inc   YL
    sts   usbSofCount, YL
#endif/* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
    USB_SOF_HOOK
#endif
    rjmp    sofError
foundK:
;{3, 5} after falling D- edge, average delay: 4 cycles
;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
;are cycles from center of first sync (double K) bit after the instruction
    push    YH                          ;1
        push        x1                                                ;1
    lds   YL, usbInputBufOffset        ;2
    clr   YH                          ;1
    subi    YL, lo8(-(usbRxBuf))        ;1
    sbci    YH, hi8(-(usbRxBuf))        ;1

        in      x1,    USBIN                        ;1
        sbrs        x1,    USBMINUS                        ;1
    ;sbis    USBIN, USBMINUS ;1 we want two bits K
    rjmp    haveTwoBitsK                    ;1
    pop   x1
    pop   YH                                     ;1 undo the push from before
    rjmp    waitForK                      ;1 this was not the end of sync, retry
haveTwoBitsK:
;----------------------------------------------------------------------------
; push more registers and initialize values while we sample the first bits:
;----------------------------------------------------------------------------
        pop                x1                                                ;1
    push    shift                                  ;1 ;2
    push    x1                            ;1 ;2
    push    x2                                     ;1 ;2
    nop                                                  ;2
    nop
    nop                                                          ;1

    in      x1, USBIN       ;1 <-- sample bit 0
    ldi   shift, 0xff   ;1
    bst   x1, USBMINUS    ;1
    bld   shift, 0      ;1
    push    x3            ;1 ;2
    push    cnt             ;1 ;2
    nop                  ;2
    nop
   
    in      x2, USBIN       ;1 <-- sample bit 1
    ser   x3            ;1
    eor   x1, x2          ;1
    bst   x1, USBMINUS    ;1
    bld   shift, 1      ;1
    ldi   cnt, USB_BUFSIZE;1
    nop                          ;1
    rjmp    rxbit2          ;1 ;2

;----------------------------------------------------------------------------
; Receiver loop (numbers in brackets are cycles within byte after instr)
;----------------------------------------------------------------------------

unstuff0:               ;1 (branch taken)
    andi    x3, ~0x01   ;1
    mov   x1, x2      ;1 x2 contains last sampled (stuffed) bit
    in      x2, USBIN   ;1 <-- sample bit 1 again
    ori   shift, 0x01 ;1
    nop                        ;1
    rjmp    didUnstuff0 ;1 ;2

unstuff1:               ;1 (branch taken)
    mov   x2, x1      ;1 x1 contains last sampled (stuffed) bit
    andi    x3, ~0x02   ;1
    ori   shift, 0x02 ;1
    nop               ;1
    in      x1, USBIN   ;1 <-- sample bit 2 again
    nop                        ;1
    rjmp    didUnstuff1 ;1 ;2

unstuff2:               ;1 (branch taken)
    andi    x3, ~0x04   ;1
    ori   shift, 0x04 ;1
    mov   x1, x2      ;1 x2 contains last sampled (stuffed) bit
    nop               ;1
    in      x2, USBIN   ;1 <-- sample bit 3
    nop                        ;1
    rjmp    didUnstuff2 ;1 ;2

unstuff3:               ;1 (branch taken)
    in      x2, USBIN   ;1 <-- sample stuffed bit 3
    andi    x3, ~0x08   ;1
    ori   shift, 0x08 ;1
    nop                        ;1
    rjmp    didUnstuff3 ;1 ;2

unstuff4:               ;1 (branch taken)
    andi    x3, ~0x10   ;1
    in      x1, USBIN   ;1 <-- sample stuffed bit 4
    ori   shift, 0x10 ;1
    nop                        ;1
    rjmp    didUnstuff4 ;1 ;2

unstuff5:               ;1 (branch taken)
    andi    x3, ~0x20   ;1
    in      x2, USBIN   ;1 <-- sample stuffed bit 5
    ori   shift, 0x20 ;1
    nop                        ;1
    rjmp    didUnstuff5 ;1 ;2

unstuff6:               ;1 (branch taken)
    andi    x3, ~0x40   ;1
    in      x1, USBIN   ;1 <-- sample stuffed bit 6
    ori   shift, 0x40 ;1
    nop                        ;1
    rjmp    didUnstuff6 ;1 ;2

; extra jobs done during bit interval:
; bit 0:    store, clear
; bit 1:    se0 check
; bit 2:    overflow check
; bit 3:    recovery from delay
; bit 4:    none
; bit 5:    none
; bit 6:    none
; bit 7:    jump, eor
rxLoop:
    eor   x3, shift   ;1 reconstruct: x3 is 0 at bit locations we changed, 1 at others
    in      x1, USBIN   ;1 <-- sample bit 0
    nop                        ;1
    st      y+, x3      ;1 ;2 store data
    ser   x3          ;1
    nop               ;1
    eor   x2, x1      ;1
    bst   x2, USBMINUS;1
    bld   shift, 0    ;1
    in      x2, USBIN   ;1 <-- sample bit 1 (or possibly bit 0 stuffed)
    andi    x2, USBMASK ;1
    breq    se0         ;1 SE0 check for bit 1
    andi    shift, 0xf9 ;1
didUnstuff0:
    breq    unstuff0    ;1
    eor   x1, x2      ;1
    bst   x1, USBMINUS;1
    bld   shift, 1    ;1
rxbit2:
    in      x1, USBIN   ;1 <-- sample bit 2 (or possibly bit 1 stuffed)
    andi    shift, 0xf3 ;1
    breq    unstuff1    ;1 do remaining work for bit 1
didUnstuff1:
    subi    cnt, 1      ;1
    brcs    overflow    ;1 loop control
    eor   x2, x1      ;1
    bst   x2, USBMINUS;1
    bld   shift, 2    ;1
    in      x2, USBIN   ;1 <-- sample bit 3 (or possibly bit 2 stuffed)
    andi    shift, 0xe7 ;1
    breq    unstuff2    ;1
didUnstuff2:
    eor   x1, x2      ;1
    bst   x1, USBMINUS;1
    bld   shift, 3    ;1
didUnstuff3:
    andi    shift, 0xcf ;1
    breq    unstuff3    ;1
    in      x1, USBIN   ;1 <-- sample bit 4
    eor   x2, x1      ;1
    bst   x2, USBMINUS;1
    bld   shift, 4    ;1
didUnstuff4:
    andi    shift, 0x9f ;1
    breq    unstuff4    ;1
    nop                ;2
    nop
    in      x2, USBIN   ;1 <-- sample bit 5
    eor   x1, x2      ;1
    bst   x1, USBMINUS;1
    bld   shift, 5    ;1
didUnstuff5:
    andi    shift, 0x3f ;1
    breq    unstuff5    ;1
    nop                ;2
    nop
    in      x1, USBIN   ;1 <-- sample bit 6
    eor   x2, x1      ;1
    bst   x2, USBMINUS;1
    bld   shift, 6    ;1
didUnstuff6:
    cpi   shift, 0x02 ;1
    brlo    unstuff6    ;1
    nop                ;2
    nop
    in      x2, USBIN   ;1 <-- sample bit 7
    eor   x1, x2      ;1
    bst   x1, USBMINUS;1
    bld   shift, 7    ;1
didUnstuff7:
    cpi   shift, 0x04 ;1
    brsh    rxLoop      ;2 loop control
unstuff7:
    andi    x3, ~0x80   ;1
    ori   shift, 0x80 ;1
    in      x2, USBIN   ;1 <-- sample stuffed bit 7
    nop                ;2 ;1
    nop
    rjmp    didUnstuff7 ;1 ;2

macro POP_STANDARD ; 12 cycles
    pop   cnt
    pop   x3
    pop   x2
    pop   x1
    pop   shift
    pop   YH
    endm
macro POP_RETI   ; 5 cycles
    pop   YL
    out   SREG, YL
    pop   YL
    endm

#include "asmcommon.inc"

;----------------------------------------------------------------------------
; Transmitting data
;----------------------------------------------------------------------------

txByteLoop:
txBitloop:
stuffN1Delay:                   ;   
    ror   shift               ;[-5]
    brcc    doExorN1            ;[-4]      
    subi    x4, 1               ;[-3]
    brne    commonN1            ;[-2]
    lsl   shift               ;[-1] compensate ror after rjmp stuffDelay
    nop                         ; stuffing consists of just waiting 8 cycles
    rjmp    stuffN1Delay      ; after ror, C bit is reliably clear

sendNakAndReti:               ;0 [-19] 19 cycles until SOP
    ldi   x3, USBPID_NAK      ;1 [-18]
    nop                                ;1 [-17]
    rjmp    usbSendX3         ;1;[-16];2 [-16]
sendAckAndReti:               ;0 [-19] 19 cycles until SOP
    ldi   x3, USBPID_ACK      ;1 [-18]
    nop                                ;1 [-17]
    rjmp    usbSendX3         ;1 [-16];2 [-16]
sendCntAndReti:               ;0 [-17] 17 cycles until SOP
    mov   x3, cnt             ;1 [-16]
usbSendX3:                      ;0 [-16]
    ldi   YL, 20            ;1 [-15] 'x3' is R20
    ldi   YH, 0               ;1 [-14]
    ldi   cnt, 2            ;1 [-13]
;   rjmp    usbSendAndReti      fallthrough

; USB spec says:
; idle = J
; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)

;usbSend:
;pointer to data in 'Y'
;number of bytes in 'cnt' -- including sync byte
;uses: x1...x2, x4, shift, cnt, Y
;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
usbSendAndReti:
    in      x2, USBDDR          ;[-12] 12 cycles until SOP
    ori   x2, USBMASK         ;[-11]
    sbi   USBOUT, USBMINUS    ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
    nop                                ;[-9]
    out   USBDDR, x2          ;[-8] <--- acquire bus
    in      x1, USBOUT          ;[-7] port mirror for tx loop
    ldi   shift, 0x40         ;[-6] sync byte is first byte sent (we enter loop after ror)
    ldi   x2, USBMASK         ;[-5]
    push    x4                  ;[-4]
    nop                                ;[-3]
doExorN1:
    eor   x1, x2            ;[-2]
    ldi   x4, 6               ;[-1]
commonN1:
stuffN2Delay:
    out   USBOUT, x1          ; <--- set bit
    ror   shift               ;
    brcc    doExorN2            ;
    subi    x4, 1               ;
    brne    commonN2            ;
    lsl   shift               ; compensate ror after rjmp stuffDelay
    nop                                ;
    rjmp    stuffN2Delay      ;; after ror, C bit is reliably clear
doExorN2:
    eor   x1, x2            ;
    ldi   x4, 6               ;
commonN2:
    nop                         ;
    subi    cnt, 171            ; trick: (3 * 171) & 0xff = 1
    out   USBOUT, x1          ; <--- set bit
    brcs    txBitloop         ;      

stuff6Delay:
    ror   shift               ;
    brcc    doExor6             ;
    subi    x4, 1               ;
    brne    common6             ;
    lsl   shift               ; compensate ror after rjmp stuffDelay
    nop                        ; stuffing consists of just waiting 8 cycles
    nop
    rjmp    stuff6Delay         ; after ror, C bit is reliably clear
doExor6:
    eor   x1, x2            ;
    ldi   x4, 6               ;
common6:
stuff7Delay:
    ror   shift               ;
    out   USBOUT, x1          ; <--- set bit
    brcc    doExor7             ;
    subi    x4, 1               ;
    brne    common7             ;
    lsl   shift               ; compensate ror after rjmp stuffDelay
    rjmp    stuff7Delay         ; after ror, C bit is reliably clear
doExor7:
    eor   x1, x2            ;
    ldi   x4, 6               ;
common7:
    ld      shift, y+         ;
    nop                                                        ;
    tst   cnt               ;;
    out   USBOUT, x1          ;; <--- set bit
    ;brne   txByteLoop                        ;
    breq    makeSE0                                ;
    rjmp    txByteLoop          ;

makeSE0:
;make SE0:
    cbr   x1, USBMASK         ; prepare SE0
    lds   x2, usbNewDeviceAddr;
    lsl   x2                  ; we compare with left shifted address
    subi    YL, 2 + 20          ; Only assign address on data packets, not ACK/NAK in x3
    out   USBOUT, x1          ; <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
    sbci    YH, 0               ;
;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
;set address only after data packet was sent, not after handshake
    breq    skipAddrAssign      ;
    sts   usbDeviceAddr, x2   ; if not skipped: SE0 is one cycle longer
skipAddrAssign:
;end of usbDeviceAddress transfer
    ldi   x2, 1<<USB_INTR_PENDING_BIT; int0 occurred during TX -- clear pending flag
    USB_STORE_PENDING(x2)       ;
    ori   x1, USBIDLE         ;
    in      x2, USBDDR          ;
    cbr   x2, USBMASK         ; set both pins to input
    mov   x3, x1            ;
    cbr   x3, USBMASK         ; configure no pullup on both pins
    pop   x4                  ;
    nop                        ;
    nop
    nop                        ;
    nop
    out   USBOUT, x1          ; <-- out J (idle) -- end of SE0 (EOP signal)
    out   USBDDR, x2          ; <-- release bus now
    out   USBOUT, x3          ; <-- ensure no pull-up resistors are active
    rjmp    doReturn

xwkm 发表于 2013-7-13 12:25:34

本帖最后由 xwkm 于 2013-7-13 12:42 编辑

现在sbic/sbis指令可以正确使用了。
但是IRC能够成功起来custom的设备。作为HID或者传输大量数据就傻眼了。无法枚举成功。

LGT 发表于 2013-7-13 13:12:24

xwkm 发表于 2013-7-13 12:25 static/image/common/back.gif
现在sbic/sbis指令可以正确使用了。
但是IRC能够成功起来custom的设备。作为HID或者传输大量数据就傻眼了。 ...

1. 大量数据传输用外部晶振就OK了, 内部的话只有直接上32M RC测试下。

2. 与08A相比, 中断并没有什么变化, 主要是读PORT值和08A不同, 因为88A本身做了同步,可以直接用SBIC/SBIS,
    而用之前08A的先读到R里面,然后SBRC/SBRS, 每一个就要比08A慢1.5个周期了。 所以直接改成SBIC/SBIS就通过了。

xo37 发表于 2013-7-13 13:33:59

汇编啊…………………………

xwkm 发表于 2013-7-13 13:56:10

LGT 发表于 2013-7-13 13:12 static/image/common/back.gif
1. 大量数据传输用外部晶振就OK了, 内部的话只有直接上32M RC测试下。

2. 与08A相比, 中断并没有什么 ...

我还想用IRC做Bootloader呢。

goodcode 发表于 2013-7-13 14:59:08

xwkm 发表于 2013-7-13 12:25 static/image/common/back.gif
现在sbic/sbis指令可以正确使用了。
但是IRC能够成功起来custom的设备。作为HID或者传输大量数据就傻眼了。 ...

大量数据出错应该就是时序读取还是有问题的
usb转串口芯片好像就那个最便宜了 windows xp下用windows api进行操作还没问题 win7就不知道了
期待楼主和lgt官方的与08a芯片的区别 这样用88A的时候很快就能上手了

xwkm 发表于 2013-7-13 15:26:41

本帖最后由 xwkm 于 2013-7-13 15:27 编辑

goodcode 发表于 2013-7-13 14:59 static/image/common/back.gif
大量数据出错应该就是时序读取还是有问题的
usb转串口芯片好像就那个最便宜了 windows xp下用windows api ...

出错问题找到了:16M的文件少同步了一次。修复了。
区别有:
sbis/sbic指令可以用了。
进中断慢一个周期。
工程片5V触摸有点问题。
切换外振的时候注意操作时序,先使能PMCE后再去操作。保证周期限制。
现在正在用烙铁和冰块测IRC稳定性。就是烙铁靠近然后试USB传输稳定。
另外就是中断切换终于有了。现在做bootloader就要简单和稳定不少了,不过手册有一处描述错误。应该是对齐到512字节。
问过官方,他们说切换后偏移地址不会变。

goodcode 发表于 2013-7-13 16:21:43

xwkm 发表于 2013-7-13 15:26 static/image/common/back.gif
出错问题找到了:16M的文件少同步了一次。修复了。
区别有:
sbis/sbic指令可以用了。


进中断慢一个周期。 是不是中断向量表中rjmp编程jmp了
现在正在用烙铁和冰块测IRC稳定性。就是烙铁靠近然后试USB传输稳定。 我也用这种方式测试 太山寨了 哈哈
还没去细看手册 能切换中断向量表真是太方便了
谢谢楼主分享

xwkm 发表于 2013-7-13 17:09:51

goodcode 发表于 2013-7-13 16:21 static/image/common/back.gif
进中断慢一个周期。 是不是中断向量表中rjmp编程jmp了
现在正在用烙铁和冰块测IRC稳定性。就是烙铁靠近然 ...

不是。是中断处理哪里为了稳定多同步了一次。

danju 发表于 2013-7-13 17:32:45

xwkm 发表于 2013-7-13 00:37 static/image/common/back.gif
目前我还没坏过一片……

好消息,谢谢啊

danju 发表于 2013-7-13 17:36:09

LGT 发表于 2013-7-13 10:11 static/image/common/back.gif
楼上可以整几片LGT8F88A测试下, 看是不是和AVR一样皮实!:)

嗯,看来是要找个机会试一试

logicgreen 发表于 2013-7-13 19:50:50

楼主是正在读高一的高中生,这个就算是你的暑假作业了?

好好努力,没考上大学直接就来我们公司上班。

xwkm 发表于 2013-7-13 20:10:57

logicgreen 发表于 2013-7-13 19:50 static/image/common/back.gif
楼主是正在读高一的高中生,这个就算是你的暑假作业了?

好好努力,没考上大学直接就来我们公司上班。 ...

当然不是啦。我前十天一直在写作业。后面几天当然要好好休息下……

goodcode 发表于 2013-7-13 21:06:09

不知道现在的作业量多少, 我上学的时候十来天就糊弄完了{:lol:} 那玩意交了就行 根本没人看 呵呵
这个年龄,这样的主动性,如果环境好会是前途无量的{:lol:}

xwkm 发表于 2013-7-13 22:48:34

还是得写个32M的RC专门针对的汇编出来。自从被我烙铁处理后貌似频率调不准了。看来只能靠软件滑动补偿咯。

xwkm 发表于 2013-7-15 15:10:51

本帖最后由 xwkm 于 2013-7-15 15:12 编辑

goodcode 发表于 2013-7-13 21:06 static/image/common/back.gif
不知道现在的作业量多少, 我上学的时候十来天就糊弄完了 那玩意交了就行 根本没人看 呵呵
这个年龄, ...

to goodcode。如果你有LGT8F88A的话。这个程序帮我测试下。我发现内置rc usb误码率有点高。

现在我在做兼容usbasp的bootloader。

i55x 发表于 2013-7-15 15:18:03

90999 发表于 2013-7-13 00:05 static/image/common/back.gif
奇怪了,我十几年没撸了,怎么看东西还有重影啊?肯定是肾亏了。

不能同意的更多了。。。。

goodcode 发表于 2013-7-15 19:34:27

xwkm 发表于 2013-7-15 15:10 static/image/common/back.gif
to goodcode。如果你有LGT8F88A的话。这个程序帮我测试下。我发现内置rc usb误码率有点高。

现在我在做 ...

我还没申请这个芯片... 你试试串口加上奇偶效验在高高波特率下有没有问题.

xwkm 发表于 2013-7-15 23:10:13

goodcode 发表于 2013-7-15 19:34 static/image/common/back.gif
我还没申请这个芯片... 你试试串口加上奇偶效验在高高波特率下有没有问题. ...

串行口还好。出厂已经OSCCAL校准过了。现在的问题就是V-USB在内置rc下误码率比较高。
可能bootloader得换种方式实现。

goodcode 发表于 2013-7-16 00:10:11

串口室温下没问题证明内部rc还是稳定的

xwkm 发表于 2013-7-16 00:13:16

goodcode 发表于 2013-7-16 00:10 static/image/common/back.gif
串口室温下没问题证明内部rc还是稳定的

不过在循环里翻转IO口的话。会出现这种状况。4MHz偶尔出现几个3.7MHz或者4.2MHz的波形。
这个串行口要求又没usb那么高。如果写usb boot不依赖晶振的话。必须做校验处理。

LGT 发表于 2013-7-16 09:42:58

xwkm 发表于 2013-7-16 00:13 static/image/common/back.gif
不过在循环里翻转IO口的话。会出现这种状况。4MHz偶尔出现几个3.7MHz或者4.2MHz的波形。
这个串行口要求 ...

建议你用PWM测试内部RC的频率, 用I/O翻转要保证程序不会被中断。
校准过后的RC频率是非常稳定的, 我测试了一些芯片, 都是非常稳定的。

goodcode 发表于 2013-7-16 10:35:54

不过在循环里翻转IO口的话。会出现这种状况。4MHz偶尔出现几个3.7MHz或者4.2MHz的波形。{:sweat:} 不会这么不稳定吧
08a的工程样片也没这样啊 我一直用08a的内部rc测试vusb 因为工程样片的外部晶振有问题 调试麻烦{:lol:}

xwkm 发表于 2013-7-16 11:02:10

goodcode 发表于 2013-7-16 10:35 static/image/common/back.gif
不过在循环里翻转IO口的话。会出现这种状况。4MHz偶尔出现几个3.7MHz或者4.2MHz的波形。 不会这么 ...

08A的16M IRC还能带起来USB?我没一次成功过。
至于那个问题可能是线太长。寄生振荡了吧。

goodcode 发表于 2013-7-16 13:19:49

我手里用过的08a的芯片 OSCCAL = 0x08; 跑vusb就可以了 室温20~30多度都没问题

如果rc没问题, 可以在*.inc分块插一些没用的io翻转用逻辑分析仪辅助查看usb的时序和内部代码处理到什么地方是慢了还是快了
说起来简单 调试起来挺麻烦的一个活

xwkm 发表于 2013-7-16 23:18:06

goodcode 发表于 2013-7-16 13:19 static/image/common/back.gif
我手里用过的08a的芯片 OSCCAL = 0x08; 跑vusb就可以了 室温20~30多度都没问题

如果rc没问题, 可以在*.inc ...

08A的我自己写过用信标校准的程序。也用外振校准内部rc。但是死活V-USB就没起来过。

goodcode 发表于 2013-7-17 01:16:02

xwkm 发表于 2013-7-16 23:18 static/image/common/back.gif
08A的我自己写过用信标校准的程序。也用外振校准内部rc。但是死活V-USB就没起来过。 ...

我测的5,6片都ok{:sweat:}

xwkm 发表于 2013-7-17 10:35:06

RP不高。Bootloader custom协议完成。现在可以只接usb。外部一个 1.5k 电阻就能够通讯了。
页: [1]
查看完整版本: LGT 最小系统板测评