summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-08-05 21:18:05 +0200
committerSuren A. Chilingaryan <csa@suren.me>2015-08-05 21:18:05 +0200
commit3e4b1ebf881a61900c4bab96dc7a7f3963b6d891 (patch)
tree95fbb89669ebb961f97e2df9ef80d94afb24ecb6
parentff82489cba07d124ca76ac9ce78e70c73cad9317 (diff)
downloadipecamera-3e4b1ebf881a61900c4bab96dc7a7f3963b6d891.tar.gz
ipecamera-3e4b1ebf881a61900c4bab96dc7a7f3963b6d891.tar.bz2
ipecamera-3e4b1ebf881a61900c4bab96dc7a7f3963b6d891.tar.xz
ipecamera-3e4b1ebf881a61900c4bab96dc7a7f3963b6d891.zip
Serialize access to CMOSIS registers
-rw-r--r--cmosis.c75
-rw-r--r--cmosis.h2
-rw-r--r--model.c2
3 files changed, 71 insertions, 8 deletions
diff --git a/cmosis.c b/cmosis.c
index 4199148..b40e175 100644
--- a/cmosis.c
+++ b/cmosis.c
@@ -1,5 +1,7 @@
#define _BSD_SOURCE
#define _IPECAMERA_MODEL_C
+#include <stdio.h>
+#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <assert.h>
@@ -7,6 +9,8 @@
#include <pcilib.h>
#include <pcilib/tools.h>
#include <pcilib/error.h>
+#include <pcilib/locking.h>
+#include <pcilib/model.h>
#include "cmosis.h"
#include "private.h"
@@ -25,13 +29,51 @@
//#define IPECAMERA_RETRY_ERRORS
#define IPECAMERA_MULTIREAD
-int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value) {
+
+typedef struct ipecamera_cmosis_context_s ipecamera_cmosis_context_t;
+
+struct ipecamera_cmosis_context_s {
+ pcilib_register_bank_context_t bank_ctx; /**< the bank context associated with the software registers */
+ pcilib_lock_t *lock; /**< the lock to serialize access through GPIO */
+};
+
+void ipecamera_cmosis_close(pcilib_t *ctx, pcilib_register_bank_context_t *reg_bank_ctx) {
+ ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx;
+
+ if (bank_ctx->lock)
+ pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, bank_ctx->lock);
+ free(bank_ctx);
+}
+
+pcilib_register_bank_context_t* ipecamera_cmosis_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args) {
+ int err;
+ ipecamera_cmosis_context_t *bank_ctx;
+
+ bank_ctx = calloc(1, sizeof(ipecamera_cmosis_context_t));
+ if (!bank_ctx) {
+ pcilib_error("Memory allocation for bank context has failed");
+ return NULL;
+ }
+
+ bank_ctx->lock = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "cmosis");
+ if (!bank_ctx->lock) {
+ ipecamera_cmosis_close(ctx, (pcilib_register_bank_context_t*)bank_ctx);
+ pcilib_error("Failed to initialize a lock to protect CMOSIS register bank");
+ return NULL;
+ }
+
+ return (pcilib_register_bank_context_t*)bank_ctx;
+}
+
+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) {
+ int err;
uint32_t val, tmp[4];
char *wr, *rd;
struct timeval start;
int retries = RETRIES;
- const pcilib_register_bank_description_t *bank = bank_ctx->bank;
-
+ ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx;
+ const pcilib_register_bank_description_t *bank = reg_bank_ctx->bank;
+
assert(addr < 128);
wr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr);
@@ -42,6 +84,12 @@ int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ct
}
retry:
+ err = pcilib_lock(bank_ctx->lock);
+ if (err) {
+ pcilib_error("Error (%i) obtaining a lock to serialize access to CMOSIS registers ", err);
+ return err;
+ }
+
val = (addr << 8);
ipecamera_datacpy(wr, &val, bank);
@@ -71,15 +119,18 @@ retry:
}
#endif /* IPECAMERA_MULTIREAD */
+ pcilib_unlock(bank_ctx->lock);
+
if ((val & READ_READY_BIT) == 0) {
if (--retries > 0) {
pcilib_warning("Timeout reading register value (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES);
goto retry;
}
+
pcilib_error("Timeout reading register value (CMOSIS %lu, status: %lx)", addr, val);
return PCILIB_ERROR_TIMEOUT;
}
-
+
if (val & READ_ERROR_BIT) {
#ifdef IPECAMERA_RETRY_ERRORS
if (--retries > 0) {
@@ -109,12 +160,14 @@ retry:
return 0;
}
-int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value) {
+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) {
+ int err;
uint32_t val, tmp[4];
char *wr, *rd;
struct timeval start;
int retries = RETRIES;
- const pcilib_register_bank_description_t *bank = bank_ctx->bank;
+ ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx;
+ const pcilib_register_bank_description_t *bank = reg_bank_ctx->bank;
assert(addr < 128);
assert(value < 256);
@@ -127,6 +180,12 @@ int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_c
}
retry:
+ err = pcilib_lock(bank_ctx->lock);
+ if (err) {
+ pcilib_error("Error (%i) obtaining a lock to serialize access to CMOSIS registers ", err);
+ return err;
+ }
+
val = WRITE_BIT|(addr << 8)|(value&0xFF);
ipecamera_datacpy(wr, &val, bank);
@@ -154,6 +213,8 @@ retry:
}
#endif /* IPECAMERA_MULTIREAD */
+ pcilib_unlock(bank_ctx->lock);
+
if ((val & READ_READY_BIT) == 0) {
#ifdef IPECAMERA_RETRY_ERRORS
if (--retries > 0) {
@@ -186,7 +247,7 @@ retry:
pcilib_error("Address verification failed during register write (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val);
return PCILIB_ERROR_VERIFY;
}
-
+
if ((val&0xFF) != value) {
pcilib_error("Value verification failed during register read (CMOSIS %lu, value: %lu != %lu)", addr, val/*&ipecamera_bit_mask[bits]*/, value);
return PCILIB_ERROR_VERIFY;
diff --git a/cmosis.h b/cmosis.h
index 0d9c7a1..eb222d3 100644
--- a/cmosis.h
+++ b/cmosis.h
@@ -3,6 +3,8 @@
#include <pcilib/bank.h>
+void ipecamera_cmosis_close(pcilib_t *ctx, pcilib_register_bank_context_t *reg_bank_ctx);
+pcilib_register_bank_context_t* ipecamera_cmosis_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args);
int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value);
int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value);
diff --git a/model.c b/model.c
index df4124d..82cbe74 100644
--- a/model.c
+++ b/model.c
@@ -14,7 +14,7 @@ enum ipecamera_protocol_s {
static const pcilib_register_protocol_api_description_t ipecamera_cmosis_protocol_api =
- { IPECAMERA_VERSION, NULL, NULL, ipecamera_cmosis_read, ipecamera_cmosis_write };
+ { IPECAMERA_VERSION, ipecamera_cmosis_open, ipecamera_cmosis_close, ipecamera_cmosis_read, ipecamera_cmosis_write };
/*
static const pcilib_dma_description_t ipecamera_dma =