usbdrvasm.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /* Name: usbdrvasm.S
  2. * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2007-06-13
  5. * Tabsize: 4
  6. * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
  7. * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
  8. */
  9. /*
  10. General Description:
  11. This module is the assembler part of the USB driver. This file contains
  12. general code (preprocessor acrobatics and CRC computation) and then includes
  13. the file appropriate for the given clock rate.
  14. */
  15. #define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
  16. #include "usbportability.h"
  17. #include "usbdrv.h" /* for common defs */
  18. /* register names */
  19. #define x1 r16
  20. #define x2 r17
  21. #define shift r18
  22. #define cnt r19
  23. #define x3 r20
  24. #define x4 r21
  25. #define x5 r22
  26. #define bitcnt x5
  27. #define phase x4
  28. #define leap x4
  29. /* Some assembler dependent definitions and declarations: */
  30. #ifdef __IAR_SYSTEMS_ASM__
  31. extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
  32. extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
  33. extern usbTxBuf, usbTxStatus1, usbTxStatus3
  34. # if USB_COUNT_SOF
  35. extern usbSofCount
  36. # endif
  37. public usbCrc16
  38. public usbCrc16Append
  39. COMMON INTVEC
  40. # ifndef USB_INTR_VECTOR
  41. ORG INT0_vect
  42. # else /* USB_INTR_VECTOR */
  43. ORG USB_INTR_VECTOR
  44. # undef USB_INTR_VECTOR
  45. # endif /* USB_INTR_VECTOR */
  46. # define USB_INTR_VECTOR usbInterruptHandler
  47. rjmp USB_INTR_VECTOR
  48. RSEG CODE
  49. #else /* __IAR_SYSTEMS_ASM__ */
  50. # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
  51. # ifdef INT0_vect
  52. # define USB_INTR_VECTOR INT0_vect // this is the "new" define for the vector
  53. # else
  54. # define USB_INTR_VECTOR SIG_INTERRUPT0 // this is the "old" vector
  55. # endif
  56. # endif
  57. .text
  58. .global USB_INTR_VECTOR
  59. .type USB_INTR_VECTOR, @function
  60. .global usbCrc16
  61. .global usbCrc16Append
  62. #endif /* __IAR_SYSTEMS_ASM__ */
  63. #if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */
  64. # define USB_LOAD_PENDING(reg) in reg, USB_INTR_PENDING
  65. # define USB_STORE_PENDING(reg) out USB_INTR_PENDING, reg
  66. #else /* It's a memory address, use lds and sts */
  67. # define USB_LOAD_PENDING(reg) lds reg, USB_INTR_PENDING
  68. # define USB_STORE_PENDING(reg) sts USB_INTR_PENDING, reg
  69. #endif
  70. #define usbTxLen1 usbTxStatus1
  71. #define usbTxBuf1 (usbTxStatus1 + 1)
  72. #define usbTxLen3 usbTxStatus3
  73. #define usbTxBuf3 (usbTxStatus3 + 1)
  74. ;----------------------------------------------------------------------------
  75. ; Utility functions
  76. ;----------------------------------------------------------------------------
  77. #ifdef __IAR_SYSTEMS_ASM__
  78. /* Register assignments for usbCrc16 on IAR cc */
  79. /* Calling conventions on IAR:
  80. * First parameter passed in r16/r17, second in r18/r19 and so on.
  81. * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
  82. * Result is passed in r16/r17
  83. * In case of the "tiny" memory model, pointers are only 8 bit with no
  84. * padding. We therefore pass argument 1 as "16 bit unsigned".
  85. */
  86. RTMODEL "__rt_version", "3"
  87. /* The line above will generate an error if cc calling conventions change.
  88. * The value "3" above is valid for IAR 4.10B/W32
  89. */
  90. # define argLen r18 /* argument 2 */
  91. # define argPtrL r16 /* argument 1 */
  92. # define argPtrH r17 /* argument 1 */
  93. # define resCrcL r16 /* result */
  94. # define resCrcH r17 /* result */
  95. # define ptrL ZL
  96. # define ptrH ZH
  97. # define ptr Z
  98. # define byte r22
  99. # define bitCnt r19
  100. # define polyL r20
  101. # define polyH r21
  102. # define scratch r23
  103. #else /* __IAR_SYSTEMS_ASM__ */
  104. /* Register assignments for usbCrc16 on gcc */
  105. /* Calling conventions on gcc:
  106. * First parameter passed in r24/r25, second in r22/23 and so on.
  107. * Callee must preserve r1-r17, r28/r29
  108. * Result is passed in r24/r25
  109. */
  110. # define argLen r22 /* argument 2 */
  111. # define argPtrL r24 /* argument 1 */
  112. # define argPtrH r25 /* argument 1 */
  113. # define resCrcL r24 /* result */
  114. # define resCrcH r25 /* result */
  115. # define ptrL XL
  116. # define ptrH XH
  117. # define ptr x
  118. # define byte r18
  119. # define bitCnt r19
  120. # define polyL r20
  121. # define polyH r21
  122. # define scratch r23
  123. #endif
  124. #if USB_USE_FAST_CRC
  125. ; This implementation is faster, but has bigger code size
  126. ; Thanks to Slawomir Fras (BoskiDialer) for this code!
  127. ; It implements the following C pseudo-code:
  128. ; unsigned table(unsigned char x)
  129. ; {
  130. ; unsigned value;
  131. ;
  132. ; value = (unsigned)x << 6;
  133. ; value ^= (unsigned)x << 7;
  134. ; if(parity(x))
  135. ; value ^= 0xc001;
  136. ; return value;
  137. ; }
  138. ; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
  139. ; {
  140. ; unsigned crc = 0xffff;
  141. ;
  142. ; while(argLen--)
  143. ; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
  144. ; return ~crc;
  145. ; }
  146. ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
  147. ; argPtr r24+25 / r16+r17
  148. ; argLen r22 / r18
  149. ; temp variables:
  150. ; byte r18 / r22
  151. ; scratch r23
  152. ; resCrc r24+r25 / r16+r17
  153. ; ptr X / Z
  154. usbCrc16:
  155. mov ptrL, argPtrL
  156. mov ptrH, argPtrH
  157. ldi resCrcL, 0xFF
  158. ldi resCrcH, 0xFF
  159. rjmp usbCrc16LoopTest
  160. usbCrc16ByteLoop:
  161. ld byte, ptr+
  162. eor resCrcL, byte ; resCrcL is now 'x' in table()
  163. mov byte, resCrcL ; compute parity of 'x'
  164. swap byte
  165. eor byte, resCrcL
  166. mov scratch, byte
  167. lsr byte
  168. lsr byte
  169. eor byte, scratch
  170. inc byte
  171. lsr byte
  172. andi byte, 1 ; byte is now parity(x)
  173. mov scratch, resCrcL
  174. mov resCrcL, resCrcH
  175. eor resCrcL, byte ; low byte of if(parity(x)) value ^= 0xc001;
  176. neg byte
  177. andi byte, 0xc0
  178. mov resCrcH, byte ; high byte of if(parity(x)) value ^= 0xc001;
  179. clr byte
  180. lsr scratch
  181. ror byte
  182. eor resCrcH, scratch
  183. eor resCrcL, byte
  184. lsr scratch
  185. ror byte
  186. eor resCrcH, scratch
  187. eor resCrcL, byte
  188. usbCrc16LoopTest:
  189. subi argLen, 1
  190. brsh usbCrc16ByteLoop
  191. com resCrcL
  192. com resCrcH
  193. ret
  194. #else /* USB_USE_FAST_CRC */
  195. ; This implementation is slower, but has less code size
  196. ;
  197. ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
  198. ; argPtr r24+25 / r16+r17
  199. ; argLen r22 / r18
  200. ; temp variables:
  201. ; byte r18 / r22
  202. ; bitCnt r19
  203. ; poly r20+r21
  204. ; scratch r23
  205. ; resCrc r24+r25 / r16+r17
  206. ; ptr X / Z
  207. usbCrc16:
  208. mov ptrL, argPtrL
  209. mov ptrH, argPtrH
  210. ldi resCrcL, 0
  211. ldi resCrcH, 0
  212. ldi polyL, lo8(0xa001)
  213. ldi polyH, hi8(0xa001)
  214. com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set
  215. ldi bitCnt, 0 ; loop counter with starnd condition = end condition
  216. rjmp usbCrcLoopEntry
  217. usbCrcByteLoop:
  218. ld byte, ptr+
  219. eor resCrcL, byte
  220. usbCrcBitLoop:
  221. ror resCrcH ; carry is always set here (see brcs jumps to here)
  222. ror resCrcL
  223. brcs usbCrcNoXor
  224. eor resCrcL, polyL
  225. eor resCrcH, polyH
  226. usbCrcNoXor:
  227. subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
  228. brcs usbCrcBitLoop
  229. usbCrcLoopEntry:
  230. subi argLen, -1
  231. brcs usbCrcByteLoop
  232. usbCrcReady:
  233. ret
  234. ; Thanks to Reimar Doeffinger for optimizing this CRC routine!
  235. #endif /* USB_USE_FAST_CRC */
  236. ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
  237. usbCrc16Append:
  238. rcall usbCrc16
  239. st ptr+, resCrcL
  240. st ptr+, resCrcH
  241. ret
  242. #undef argLen
  243. #undef argPtrL
  244. #undef argPtrH
  245. #undef resCrcL
  246. #undef resCrcH
  247. #undef ptrL
  248. #undef ptrH
  249. #undef ptr
  250. #undef byte
  251. #undef bitCnt
  252. #undef polyL
  253. #undef polyH
  254. #undef scratch
  255. #if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
  256. #ifdef __IAR_SYSTEMS_ASM__
  257. /* Register assignments for usbMeasureFrameLength on IAR cc */
  258. /* Calling conventions on IAR:
  259. * First parameter passed in r16/r17, second in r18/r19 and so on.
  260. * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
  261. * Result is passed in r16/r17
  262. * In case of the "tiny" memory model, pointers are only 8 bit with no
  263. * padding. We therefore pass argument 1 as "16 bit unsigned".
  264. */
  265. # define resL r16
  266. # define resH r17
  267. # define cnt16L r30
  268. # define cnt16H r31
  269. # define cntH r18
  270. #else /* __IAR_SYSTEMS_ASM__ */
  271. /* Register assignments for usbMeasureFrameLength on gcc */
  272. /* Calling conventions on gcc:
  273. * First parameter passed in r24/r25, second in r22/23 and so on.
  274. * Callee must preserve r1-r17, r28/r29
  275. * Result is passed in r24/r25
  276. */
  277. # define resL r24
  278. # define resH r25
  279. # define cnt16L r24
  280. # define cnt16H r25
  281. # define cntH r26
  282. #endif
  283. # define cnt16 cnt16L
  284. ; extern unsigned usbMeasurePacketLength(void);
  285. ; returns time between two idle strobes in multiples of 7 CPU clocks
  286. .global usbMeasureFrameLength
  287. usbMeasureFrameLength:
  288. ldi cntH, 6 ; wait ~ 10 ms for D- == 0
  289. clr cnt16L
  290. clr cnt16H
  291. usbMFTime16:
  292. dec cntH
  293. breq usbMFTimeout
  294. usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe)
  295. sbiw cnt16, 1 ;[0] [6]
  296. breq usbMFTime16 ;[2]
  297. sbic USBIN, USBMINUS ;[3]
  298. rjmp usbMFWaitStrobe ;[4]
  299. usbMFWaitIdle: ; then wait until idle again
  300. sbis USBIN, USBMINUS ;1 wait for D- == 1
  301. rjmp usbMFWaitIdle ;2
  302. ldi cnt16L, 1 ;1 represents cycles so far
  303. clr cnt16H ;1
  304. usbMFWaitLoop:
  305. in cntH, USBIN ;[0] [7]
  306. adiw cnt16, 1 ;[1]
  307. breq usbMFTimeout ;[3]
  308. andi cntH, USBMASK ;[4]
  309. brne usbMFWaitLoop ;[5]
  310. usbMFTimeout:
  311. #if resL != cnt16L
  312. mov resL, cnt16L
  313. mov resH, cnt16H
  314. #endif
  315. ret
  316. #undef resL
  317. #undef resH
  318. #undef cnt16
  319. #undef cnt16L
  320. #undef cnt16H
  321. #undef cntH
  322. #endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
  323. ;----------------------------------------------------------------------------
  324. ; Now include the clock rate specific code
  325. ;----------------------------------------------------------------------------
  326. #ifndef USB_CFG_CLOCK_KHZ
  327. # ifdef F_CPU
  328. # define USB_CFG_CLOCK_KHZ (F_CPU/1000)
  329. # else
  330. # error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!"
  331. # endif
  332. #endif
  333. #if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */
  334. # if USB_CFG_CLOCK_KHZ == 18000
  335. # include "usbdrvasm18-crc.inc"
  336. # else
  337. # error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!"
  338. # endif
  339. #else /* USB_CFG_CHECK_CRC */
  340. # if USB_CFG_CLOCK_KHZ == 12000
  341. # include "usbdrvasm12.inc"
  342. # elif USB_CFG_CLOCK_KHZ == 12800
  343. # include "usbdrvasm128.inc"
  344. # elif USB_CFG_CLOCK_KHZ == 15000
  345. # include "usbdrvasm15.inc"
  346. # elif USB_CFG_CLOCK_KHZ == 16000
  347. # include "usbdrvasm16.inc"
  348. # elif USB_CFG_CLOCK_KHZ == 16500
  349. # include "usbdrvasm165.inc"
  350. # elif USB_CFG_CLOCK_KHZ == 20000
  351. # include "usbdrvasm20.inc"
  352. # else
  353. # error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
  354. # endif
  355. #endif /* USB_CFG_CHECK_CRC */