cmosis.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #define _DEFAULT_SOURCE
  2. #define _BSD_SOURCE
  3. #define _IPECAMERA_MODEL_C
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <sys/time.h>
  7. #include <unistd.h>
  8. #include <assert.h>
  9. #include <pcilib.h>
  10. #include <pcilib/tools.h>
  11. #include <pcilib/error.h>
  12. #include <pcilib/locking.h>
  13. #include <pcilib/model.h>
  14. #include <pcilib/datacpy.h>
  15. #include "cmosis.h"
  16. #include "private.h"
  17. #define ADDR_MASK 0x7F00
  18. #define WRITE_BIT 0x8000
  19. #define RETRIES 10
  20. //ToDo: check bot 1 and 2 bits for READY
  21. #define READ_READY_BIT 0x20000
  22. #define READ_ERROR_BIT 0x40000
  23. #define ipecamera_datacpy(dst, src, bank) pcilib_datacpy(dst, src, 4, 1, bank->raw_endianess)
  24. //#define IPECAMERA_SIMPLIFIED_READOUT
  25. #define IPECAMERA_RETRY_ERRORS
  26. #define IPECAMERA_MULTIREAD
  27. typedef struct ipecamera_cmosis_context_s ipecamera_cmosis_context_t;
  28. struct ipecamera_cmosis_context_s {
  29. pcilib_register_bank_context_t bank_ctx; /**< the bank context associated with the software registers */
  30. pcilib_lock_t *lock; /**< the lock to serialize access through GPIO */
  31. };
  32. void ipecamera_cmosis_close(pcilib_t *ctx, pcilib_register_bank_context_t *reg_bank_ctx) {
  33. ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx;
  34. if (bank_ctx->lock)
  35. pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, bank_ctx->lock);
  36. free(bank_ctx);
  37. }
  38. pcilib_register_bank_context_t* ipecamera_cmosis_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args) {
  39. ipecamera_cmosis_context_t *bank_ctx;
  40. bank_ctx = calloc(1, sizeof(ipecamera_cmosis_context_t));
  41. if (!bank_ctx) {
  42. pcilib_error("Memory allocation for bank context has failed");
  43. return NULL;
  44. }
  45. bank_ctx->lock = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "cmosis");
  46. if (!bank_ctx->lock) {
  47. ipecamera_cmosis_close(ctx, (pcilib_register_bank_context_t*)bank_ctx);
  48. pcilib_error("Failed to initialize a lock to protect CMOSIS register bank");
  49. return NULL;
  50. }
  51. return (pcilib_register_bank_context_t*)bank_ctx;
  52. }
  53. int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *reg_bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value) {
  54. int err;
  55. uint32_t val, tmp[4];
  56. char *wr, *rd;
  57. struct timeval start;
  58. int retries = RETRIES;
  59. ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx;
  60. const pcilib_register_bank_description_t *bank = reg_bank_ctx->bank;
  61. assert(addr < 128);
  62. wr = pcilib_resolve_bar_address(ctx, bank->bar, bank->write_addr);
  63. rd = pcilib_resolve_bar_address(ctx, bank->bar, bank->read_addr);
  64. if ((!rd)||(!wr)) {
  65. pcilib_error("Error resolving addresses of read & write registers");
  66. return PCILIB_ERROR_INVALID_ADDRESS;
  67. }
  68. retry:
  69. err = pcilib_lock(bank_ctx->lock);
  70. if (err) {
  71. pcilib_error("Error (%i) obtaining a lock to serialize access to CMOSIS registers ", err);
  72. return err;
  73. }
  74. val = (addr << 8);
  75. ipecamera_datacpy(wr, &val, bank);
  76. #ifdef IPECAMERA_SIMPLIFIED_READOUT
  77. usleep(IPECAMERA_SPI_REGISTER_DELAY);
  78. ipecamera_datacpy(wr, &val, bank);
  79. usleep(IPECAMERA_SPI_REGISTER_DELAY);
  80. ipecamera_datacpy(wr, &val, bank);
  81. usleep(IPECAMERA_SPI_REGISTER_DELAY);
  82. #endif /* IPECAMERA_SIMPLIFIED_READOUT */
  83. gettimeofday(&start, NULL);
  84. #ifdef IPECAMERA_MULTIREAD
  85. usleep(IPECAMERA_SPI_REGISTER_DELAY);
  86. pcilib_datacpy(tmp, rd, 4, 4, bank->raw_endianess);
  87. val = tmp[0];
  88. #else /* IPECAMERA_MULTIREAD */
  89. ipecamera_datacpy(&val, rd, bank);
  90. while ((val & READ_READY_BIT) == 0) {
  91. gettimeofday(&cur, NULL);
  92. if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > IPECAMERA_SPI_REGISTER_DELAY) break;
  93. ipecamera_datacpy(&val, rd, bank);
  94. }
  95. #endif /* IPECAMERA_MULTIREAD */
  96. pcilib_unlock(bank_ctx->lock);
  97. if ((val & READ_READY_BIT) == 0) {
  98. if (--retries > 0) {
  99. pcilib_warning("Timeout reading register value (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES);
  100. goto retry;
  101. }
  102. pcilib_error("Timeout reading register value (CMOSIS %lu, status: %lx)", addr, val);
  103. return PCILIB_ERROR_TIMEOUT;
  104. }
  105. if (val & READ_ERROR_BIT) {
  106. #ifdef IPECAMERA_RETRY_ERRORS
  107. if (--retries > 0) {
  108. pcilib_warning("Error reading register (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES);
  109. goto retry;
  110. }
  111. #endif /* IPECAMERA_RETRY_ERRORS */
  112. pcilib_error("Error reading register value (CMOSIS %lu, status: %lx)", addr, val);
  113. return PCILIB_ERROR_FAILED;
  114. }
  115. if (((val&ADDR_MASK) >> 8) != addr) {
  116. #ifdef IPECAMERA_RETRY_ERRORS
  117. if (--retries > 0) {
  118. pcilib_warning("Address verification failed during register read (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES);
  119. goto retry;
  120. }
  121. #endif /* IPECAMERA_RETRY_ERRORS */
  122. pcilib_error("Address verification failed during register read (CMOSIS %lu, status: %lx)", addr, val);
  123. return PCILIB_ERROR_VERIFY;
  124. }
  125. *value = val&0xFF;
  126. return 0;
  127. }
  128. int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *reg_bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value) {
  129. int err;
  130. uint32_t val, tmp[4];
  131. char *wr, *rd;
  132. struct timeval start;
  133. int retries = RETRIES;
  134. ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx;
  135. const pcilib_register_bank_description_t *bank = reg_bank_ctx->bank;
  136. assert(addr < 128);
  137. assert(value < 256);
  138. wr = pcilib_resolve_bar_address(ctx, bank->bar, bank->write_addr);
  139. rd = pcilib_resolve_bar_address(ctx, bank->bar, bank->read_addr);
  140. if ((!rd)||(!wr)) {
  141. pcilib_error("Error resolving addresses of read & write registers");
  142. return PCILIB_ERROR_INVALID_ADDRESS;
  143. }
  144. retry:
  145. err = pcilib_lock(bank_ctx->lock);
  146. if (err) {
  147. pcilib_error("Error (%i) obtaining a lock to serialize access to CMOSIS registers ", err);
  148. return err;
  149. }
  150. val = WRITE_BIT|(addr << 8)|(value&0xFF);
  151. ipecamera_datacpy(wr, &val, bank);
  152. #ifdef IPECAMERA_SIMPLIFIED_READOUT
  153. usleep(IPECAMERA_SPI_REGISTER_DELAY);
  154. ipecamera_datacpy(wr, &val, bank);
  155. usleep(IPECAMERA_SPI_REGISTER_DELAY);
  156. ipecamera_datacpy(wr, &val, bank);
  157. usleep(IPECAMERA_SPI_REGISTER_DELAY);
  158. #endif /* IPECAMERA_SIMPLIFIED_READOUT */
  159. gettimeofday(&start, NULL);
  160. #ifdef IPECAMERA_MULTIREAD
  161. usleep(IPECAMERA_SPI_REGISTER_DELAY);
  162. pcilib_datacpy(tmp, rd, 4, 4, bank->raw_endianess);
  163. val = tmp[0];
  164. #else /* IPECAMERA_MULTIREAD */
  165. ipecamera_datacpy(&val, rd, bank);
  166. while ((val & READ_READY_BIT) == 0) {
  167. gettimeofday(&cur, NULL);
  168. if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > IPECAMERA_SPI_REGISTER_DELAY) break;
  169. ipecamera_datacpy(&val, rd, bank);
  170. }
  171. #endif /* IPECAMERA_MULTIREAD */
  172. pcilib_unlock(bank_ctx->lock);
  173. if ((val & READ_READY_BIT) == 0) {
  174. #ifdef IPECAMERA_RETRY_ERRORS
  175. if (--retries > 0) {
  176. pcilib_warning("Timeout occured during register write (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES);
  177. goto retry;
  178. }
  179. #endif /* IPECAMERA_RETRY_ERRORS */
  180. pcilib_error("Timeout writting register value (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val);
  181. return PCILIB_ERROR_TIMEOUT;
  182. }
  183. if (val & READ_ERROR_BIT) {
  184. #ifdef IPECAMERA_RETRY_ERRORS
  185. if (--retries > 0) {
  186. pcilib_warning("Register write has failed (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES);
  187. goto retry;
  188. }
  189. #endif /* IPECAMERA_RETRY_ERRORS */
  190. pcilib_error("Error writting register value (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val);
  191. return PCILIB_ERROR_FAILED;
  192. }
  193. if (((val&ADDR_MASK) >> 8) != addr) {
  194. if (--retries > 0) {
  195. pcilib_warning("Address verification failed during register write (CMOSIS %lu, value: %lu, status: %lx), retrying (try %i of %i)...", addr, value, val, RETRIES - retries, RETRIES);
  196. goto retry;
  197. }
  198. pcilib_error("Address verification failed during register write (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val);
  199. return PCILIB_ERROR_VERIFY;
  200. }
  201. if ((val&0xFF) != value) {
  202. pcilib_error("Value verification failed during register read (CMOSIS %lu, value: %lu != %lu)", addr, val/*&ipecamera_bit_mask[bits]*/, value);
  203. return PCILIB_ERROR_VERIFY;
  204. }
  205. return 0;
  206. }