You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

usbdrvasm.S 11KB

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