Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

usbdrvasm16.inc 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /* Name: usbdrvasm16.inc
  2. * Project: AVR USB driver
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2007-06-15
  5. * Tabsize: 4
  6. * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
  7. * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
  8. * Revision: $Id$
  9. */
  10. /* Do not link this file! Link usbdrvasm.S instead, which includes the
  11. * appropriate implementation!
  12. */
  13. /*
  14. General Description:
  15. This file is the 16 MHz version of the asssembler part of the USB driver. It
  16. requires a 16 MHz crystal (not a ceramic resonator and not a calibrated RC
  17. oscillator).
  18. See usbdrv.h for a description of the entire driver.
  19. Since almost all of this code is timing critical, don't change unless you
  20. really know what you are doing! Many parts require not only a maximum number
  21. of CPU cycles, but even an exact number of cycles!
  22. */
  23. ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes
  24. ;nominal frequency: 16 MHz -> 10.6666666 cycles per bit, 85.333333333 cycles per byte
  25. ; Numbers in brackets are clocks counted from center of last sync bit
  26. ; when instruction starts
  27. USB_INTR_VECTOR:
  28. ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt
  29. push YL ;[-25] push only what is necessary to sync with edge ASAP
  30. in YL, SREG ;[-23]
  31. push YL ;[-22]
  32. push YH ;[-20]
  33. ;----------------------------------------------------------------------------
  34. ; Synchronize with sync pattern:
  35. ;----------------------------------------------------------------------------
  36. ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
  37. ;sync up with J to K edge during sync pattern -- use fastest possible loops
  38. ;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
  39. waitForJ:
  40. sbis USBIN, USBMINUS ;[-18] wait for D- == 1
  41. rjmp waitForJ
  42. waitForK:
  43. ;The following code results in a sampling window of < 1/4 bit which meets the spec.
  44. sbis USBIN, USBMINUS ;[-15]
  45. rjmp foundK ;[-14]
  46. sbis USBIN, USBMINUS
  47. rjmp foundK
  48. sbis USBIN, USBMINUS
  49. rjmp foundK
  50. sbis USBIN, USBMINUS
  51. rjmp foundK
  52. sbis USBIN, USBMINUS
  53. rjmp foundK
  54. sbis USBIN, USBMINUS
  55. rjmp foundK
  56. #if USB_COUNT_SOF
  57. lds YL, usbSofCount
  58. inc YL
  59. sts usbSofCount, YL
  60. #endif /* USB_COUNT_SOF */
  61. rjmp sofError
  62. foundK: ;[-12]
  63. ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]
  64. ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
  65. ;are cycles from center of first sync (double K) bit after the instruction
  66. push bitcnt ;[-12]
  67. ; [---] ;[-11]
  68. lds YL, usbInputBufOffset;[-10]
  69. ; [---] ;[-9]
  70. clr YH ;[-8]
  71. subi YL, lo8(-(usbRxBuf));[-7] [rx loop init]
  72. sbci YH, hi8(-(usbRxBuf));[-6] [rx loop init]
  73. push shift ;[-5]
  74. ; [---] ;[-4]
  75. ldi bitcnt, 0x55 ;[-3] [rx loop init]
  76. sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early)
  77. rjmp haveTwoBitsK ;[-1]
  78. pop shift ;[0] undo the push from before
  79. pop bitcnt ;[2] undo the push from before
  80. rjmp waitForK ;[4] this was not the end of sync, retry
  81. ; The entire loop from waitForK until rjmp waitForK above must not exceed two
  82. ; bit times (= 21 cycles).
  83. ;----------------------------------------------------------------------------
  84. ; push more registers and initialize values while we sample the first bits:
  85. ;----------------------------------------------------------------------------
  86. haveTwoBitsK:
  87. push x1 ;[1]
  88. push x2 ;[3]
  89. push x3 ;[5]
  90. ldi shift, 0 ;[7]
  91. ldi x3, 1<<4 ;[8] [rx loop init] first sample is inverse bit, compensate that
  92. push x4 ;[9] == leap
  93. in x1, USBIN ;[11] <-- sample bit 0
  94. andi x1, USBMASK ;[12]
  95. bst x1, USBMINUS ;[13]
  96. bld shift, 7 ;[14]
  97. push cnt ;[15]
  98. ldi leap, 0 ;[17] [rx loop init]
  99. ldi cnt, USB_BUFSIZE;[18] [rx loop init]
  100. rjmp rxbit1 ;[19] arrives at [21]
  101. ;----------------------------------------------------------------------------
  102. ; Receiver loop (numbers in brackets are cycles within byte after instr)
  103. ;----------------------------------------------------------------------------
  104. unstuff6:
  105. andi x2, USBMASK ;[03]
  106. ori x3, 1<<6 ;[04] will not be shifted any more
  107. andi shift, ~0x80;[05]
  108. mov x1, x2 ;[06] sampled bit 7 is actually re-sampled bit 6
  109. subi leap, 3 ;[07] since this is a short (10 cycle) bit, enforce leap bit
  110. rjmp didUnstuff6 ;[08]
  111. unstuff7:
  112. ori x3, 1<<7 ;[09] will not be shifted any more
  113. in x2, USBIN ;[00] [10] re-sample bit 7
  114. andi x2, USBMASK ;[01]
  115. andi shift, ~0x80;[02]
  116. subi leap, 3 ;[03] since this is a short (10 cycle) bit, enforce leap bit
  117. rjmp didUnstuff7 ;[04]
  118. unstuffEven:
  119. ori x3, 1<<6 ;[09] will be shifted right 6 times for bit 0
  120. in x1, USBIN ;[00] [10]
  121. andi shift, ~0x80;[01]
  122. andi x1, USBMASK ;[02]
  123. breq se0 ;[03]
  124. subi leap, 3 ;[04] since this is a short (10 cycle) bit, enforce leap bit
  125. nop ;[05]
  126. rjmp didUnstuffE ;[06]
  127. unstuffOdd:
  128. ori x3, 1<<5 ;[09] will be shifted right 4 times for bit 1
  129. in x2, USBIN ;[00] [10]
  130. andi shift, ~0x80;[01]
  131. andi x2, USBMASK ;[02]
  132. breq se0 ;[03]
  133. subi leap, 3 ;[04] since this is a short (10 cycle) bit, enforce leap bit
  134. nop ;[05]
  135. rjmp didUnstuffO ;[06]
  136. rxByteLoop:
  137. andi x1, USBMASK ;[03]
  138. eor x2, x1 ;[04]
  139. subi leap, 1 ;[05]
  140. brpl skipLeap ;[06]
  141. subi leap, -3 ;1 one leap cycle every 3rd byte -> 85 + 1/3 cycles per byte
  142. nop ;1
  143. skipLeap:
  144. subi x2, 1 ;[08]
  145. ror shift ;[09]
  146. didUnstuff6:
  147. cpi shift, 0xfc ;[10]
  148. in x2, USBIN ;[00] [11] <-- sample bit 7
  149. brcc unstuff6 ;[01]
  150. andi x2, USBMASK ;[02]
  151. eor x1, x2 ;[03]
  152. subi x1, 1 ;[04]
  153. ror shift ;[05]
  154. didUnstuff7:
  155. cpi shift, 0xfc ;[06]
  156. brcc unstuff7 ;[07]
  157. eor x3, shift ;[08] reconstruct: x3 is 1 at bit locations we changed, 0 at others
  158. st y+, x3 ;[09] store data
  159. rxBitLoop:
  160. in x1, USBIN ;[00] [11] <-- sample bit 0/2/4
  161. andi x1, USBMASK ;[01]
  162. eor x2, x1 ;[02]
  163. andi x3, 0x3f ;[03] topmost two bits reserved for 6 and 7
  164. subi x2, 1 ;[04]
  165. ror shift ;[05]
  166. cpi shift, 0xfc ;[06]
  167. brcc unstuffEven ;[07]
  168. didUnstuffE:
  169. lsr x3 ;[08]
  170. lsr x3 ;[09]
  171. rxbit1:
  172. in x2, USBIN ;[00] [10] <-- sample bit 1/3/5
  173. andi x2, USBMASK ;[01]
  174. breq se0 ;[02]
  175. eor x1, x2 ;[03]
  176. subi x1, 1 ;[04]
  177. ror shift ;[05]
  178. cpi shift, 0xfc ;[06]
  179. brcc unstuffOdd ;[07]
  180. didUnstuffO:
  181. subi bitcnt, 0xab;[08] == addi 0x55, 0x55 = 0x100/3
  182. brcs rxBitLoop ;[09]
  183. subi cnt, 1 ;[10]
  184. in x1, USBIN ;[00] [11] <-- sample bit 6
  185. brcc rxByteLoop ;[01]
  186. rjmp overflow
  187. macro POP_STANDARD ; 14 cycles
  188. pop cnt
  189. pop x4
  190. pop x3
  191. pop x2
  192. pop x1
  193. pop shift
  194. pop bitcnt
  195. endm
  196. macro POP_RETI ; 7 cycles
  197. pop YH
  198. pop YL
  199. out SREG, YL
  200. pop YL
  201. endm
  202. #include "asmcommon.inc"
  203. ; USB spec says:
  204. ; idle = J
  205. ; J = (D+ = 0), (D- = 1)
  206. ; K = (D+ = 1), (D- = 0)
  207. ; Spec allows 7.5 bit times from EOP to SOP for replies
  208. bitstuffN:
  209. eor x1, x4 ;[5]
  210. ldi x2, 0 ;[6]
  211. nop2 ;[7]
  212. nop ;[9]
  213. out USBOUT, x1 ;[10] <-- out
  214. rjmp didStuffN ;[0]
  215. bitstuff6:
  216. eor x1, x4 ;[5]
  217. ldi x2, 0 ;[6] Carry is zero due to brcc
  218. rol shift ;[7] compensate for ror shift at branch destination
  219. rjmp didStuff6 ;[8]
  220. bitstuff7:
  221. ldi x2, 0 ;[2] Carry is zero due to brcc
  222. rjmp didStuff7 ;[3]
  223. sendNakAndReti:
  224. ldi x3, USBPID_NAK ;[-18]
  225. rjmp sendX3AndReti ;[-17]
  226. sendAckAndReti:
  227. ldi cnt, USBPID_ACK ;[-17]
  228. sendCntAndReti:
  229. mov x3, cnt ;[-16]
  230. sendX3AndReti:
  231. ldi YL, 20 ;[-15] x3==r20 address is 20
  232. ldi YH, 0 ;[-14]
  233. ldi cnt, 2 ;[-13]
  234. ; rjmp usbSendAndReti fallthrough
  235. ;usbSend:
  236. ;pointer to data in 'Y'
  237. ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
  238. ;uses: x1...x4, btcnt, shift, cnt, Y
  239. ;Numbers in brackets are time since first bit of sync pattern is sent
  240. ;We don't match the transfer rate exactly (don't insert leap cycles every third
  241. ;byte) because the spec demands only 1.5% precision anyway.
  242. usbSendAndReti: ; 12 cycles until SOP
  243. in x2, USBDDR ;[-12]
  244. ori x2, USBMASK ;[-11]
  245. sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
  246. in x1, USBOUT ;[-8] port mirror for tx loop
  247. out USBDDR, x2 ;[-7] <- acquire bus
  248. ; need not init x2 (bitstuff history) because sync starts with 0
  249. ldi x4, USBMASK ;[-6] exor mask
  250. ldi shift, 0x80 ;[-5] sync byte is first byte sent
  251. txByteLoop:
  252. ldi bitcnt, 0x35 ;[-4] [6] binary 0011 0101
  253. txBitLoop:
  254. sbrs shift, 0 ;[-3] [7]
  255. eor x1, x4 ;[-2] [8]
  256. out USBOUT, x1 ;[-1] [9] <-- out N
  257. ror shift ;[0] [10]
  258. ror x2 ;[1]
  259. didStuffN:
  260. cpi x2, 0xfc ;[2]
  261. brcc bitstuffN ;[3]
  262. lsr bitcnt ;[4]
  263. brcc txBitLoop ;[5]
  264. brne txBitLoop ;[6]
  265. sbrs shift, 0 ;[7]
  266. eor x1, x4 ;[8]
  267. didStuff6:
  268. out USBOUT, x1 ;[-1] [9] <-- out 6
  269. ror shift ;[0] [10]
  270. ror x2 ;[1]
  271. cpi x2, 0xfc ;[2]
  272. brcc bitstuff6 ;[3]
  273. ror shift ;[4]
  274. didStuff7:
  275. ror x2 ;[5]
  276. sbrs x2, 7 ;[6]
  277. eor x1, x4 ;[7]
  278. nop ;[8]
  279. cpi x2, 0xfc ;[9]
  280. out USBOUT, x1 ;[-1][10] <-- out 7
  281. brcc bitstuff7 ;[0] [11]
  282. ld shift, y+ ;[1]
  283. dec cnt ;[3]
  284. brne txByteLoop ;[4]
  285. ;make SE0:
  286. cbr x1, USBMASK ;[5] prepare SE0 [spec says EOP may be 21 to 25 cycles]
  287. lds x2, usbNewDeviceAddr;[6]
  288. lsl x2 ;[8] we compare with left shifted address
  289. subi YL, 20 + 2 ;[9] Only assign address on data packets, not ACK/NAK in x3
  290. sbci YH, 0 ;[10]
  291. out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle
  292. ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
  293. ;set address only after data packet was sent, not after handshake
  294. breq skipAddrAssign ;[0]
  295. sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
  296. skipAddrAssign:
  297. ;end of usbDeviceAddress transfer
  298. ldi x2, 1<<USB_INTR_PENDING_BIT;[2] int0 occurred during TX -- clear pending flag
  299. USB_STORE_PENDING(x2) ;[3]
  300. ori x1, USBIDLE ;[4]
  301. in x2, USBDDR ;[5]
  302. cbr x2, USBMASK ;[6] set both pins to input
  303. mov x3, x1 ;[7]
  304. cbr x3, USBMASK ;[8] configure no pullup on both pins
  305. ldi x4, 4 ;[9]
  306. se0Delay:
  307. dec x4 ;[10] [13] [16] [19]
  308. brne se0Delay ;[11] [14] [17] [20]
  309. out USBOUT, x1 ;[21] <-- out J (idle) -- end of SE0 (EOP signal)
  310. out USBDDR, x2 ;[22] <-- release bus now
  311. out USBOUT, x3 ;[23] <-- ensure no pull-up resistors are active
  312. rjmp doReturn