mirror of
https://github.com/xtacocorex/CHIP_IO
synced 2025-07-19 12:23:22 +00:00
Reworked a lot of error handling.
This commit is contained in:
@ -131,7 +131,7 @@ pins_t pins_info[] = {
|
||||
{ "CSID7", "U14_38", 139, BASE_METHOD_AS_IS, -1, -1},
|
||||
{ "GND", "U14_39", 0, BASE_METHOD_AS_IS, -1, -1},
|
||||
{ "GND", "U14_40", 0, BASE_METHOD_AS_IS, -1, -1},
|
||||
{ NULL, NULL, 0 }
|
||||
{ NULL, NULL, 0, 0, -1, -1}
|
||||
};
|
||||
|
||||
|
||||
@ -178,10 +178,10 @@ int get_xio_base(void)
|
||||
/* Found the expander, get the contents of base */
|
||||
snprintf(base_file, sizeof(base_file), "%s/%s/base", GPIO_PATH, ent->d_name); BUF2SMALL(base_file);
|
||||
base_fp = fopen(base_file, "r"); ASSRT(base_fp != NULL);
|
||||
s = fgets(input_line, sizeof(input_line), base_fp);
|
||||
ASSRT(s == input_line && strlen(input_line) < sizeof(input_line)-1);
|
||||
s = fgets(input_line, sizeof(input_line), base_fp); BUF2SMALL(input_line); ASSRT(s);
|
||||
fclose(base_fp);
|
||||
xio_base_address = atoi(input_line); /* remember the result */
|
||||
/* Remember the value in the static local. */
|
||||
xio_base_address = atoi(input_line); ASSRT(xio_base_address > 0);
|
||||
num_get_xio_base++; /* for self-test purposes */
|
||||
}
|
||||
} /* if label file is open */
|
||||
@ -377,7 +377,7 @@ int build_path(const char *partial_path, const char *prefix, char *full_path, si
|
||||
dp = opendir (partial_path);
|
||||
if (dp != NULL) {
|
||||
while ((ep = readdir (dp))) {
|
||||
// Enforce that the prefix must be the first part of the file
|
||||
// Enforce that the prefix must be the first part of the file name
|
||||
char* found_string = strstr(ep->d_name, prefix);
|
||||
|
||||
if (found_string != NULL && (ep->d_name - found_string) == 0) {
|
||||
@ -419,3 +419,75 @@ int get_spi_bus_path_number(unsigned int spi)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct dyn_int_array {
|
||||
int num_elements;
|
||||
int *array;
|
||||
};
|
||||
|
||||
void *dyn_int_array_create(int initial_num_elements, int initial_val)
|
||||
{
|
||||
struct dyn_int_array *new_array = (struct dyn_int_array *)malloc(sizeof(struct dyn_int_array));
|
||||
ASSRT(new_array != NULL);
|
||||
new_array->num_elements = initial_num_elements;
|
||||
new_array->array = (int *)malloc(initial_num_elements * sizeof(int));
|
||||
ASSRT(new_array->array != NULL);
|
||||
int i;
|
||||
for (i = 0; i < initial_num_elements; i++)
|
||||
new_array->array[i] = initial_val;
|
||||
|
||||
return (void *)new_array;
|
||||
} /* dyn_int_array_create */
|
||||
|
||||
|
||||
void dyn_int_array_set(void **in_array, int i, int val, int initial_val)
|
||||
{
|
||||
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
|
||||
if (array == NULL)
|
||||
array = dyn_int_array_create(i * 3 / 2, initial_val);
|
||||
|
||||
if (i >= array->num_elements) {
|
||||
int new_num_elements = i * 3 / 2; /* half-again larger than current request */
|
||||
array->array = realloc(array->array, new_num_elements * sizeof(int));
|
||||
ASSRT(array->array != NULL);
|
||||
// Zero out the newly allocated elements.
|
||||
while (array->num_elements < new_num_elements) {
|
||||
array->array[array->num_elements] = initial_val;
|
||||
array->num_elements ++;
|
||||
}
|
||||
}
|
||||
|
||||
array->array[i] = val;
|
||||
*in_array = (void *)array;
|
||||
} /* dyn_int_array_set */
|
||||
|
||||
|
||||
int dyn_int_array_get(void **in_array, int i, int initial_val)
|
||||
{
|
||||
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
|
||||
if (array == NULL)
|
||||
array = dyn_int_array_create(i * 3 / 2, initial_val);
|
||||
|
||||
if (i >= array->num_elements) {
|
||||
int new_num_elements = i * 3 / 2; /* half-again larger than current request */
|
||||
array->array = realloc(array->array, new_num_elements * sizeof(int));
|
||||
ASSRT(array->array != NULL);
|
||||
// Zero out the newly allocated elements.
|
||||
while (array->num_elements < new_num_elements) {
|
||||
array->array[array->num_elements] = initial_val;
|
||||
array->num_elements ++;
|
||||
}
|
||||
}
|
||||
|
||||
return array->array[i];
|
||||
*in_array = (void *)array;
|
||||
} /* dyn_int_array_get */
|
||||
|
||||
|
||||
void dyn_int_array_delete(void **in_array)
|
||||
{
|
||||
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
|
||||
free(array->array);
|
||||
free(array);
|
||||
} /* dyn_int_array_delete */
|
||||
|
@ -41,7 +41,7 @@ SOFTWARE.
|
||||
// See http://blog.geeky-boy.com/2016/06/of-compiler-warnings-and-asserts-in.html
|
||||
#define ASSRT(cond_expr) do { \
|
||||
if (!(cond_expr)) { \
|
||||
fprintf(stderr, "ASSRT failed at %s:%d (%s)", __FILE__, __LINE__, #cond_expr); \
|
||||
fprintf(stderr, "ASSRT failed at %s:%d (%s)\n", __FILE__, __LINE__, #cond_expr); \
|
||||
fflush(stderr); \
|
||||
abort(); \
|
||||
} } while (0)
|
||||
@ -75,6 +75,7 @@ int setup_error;
|
||||
int module_setup;
|
||||
|
||||
int get_xio_base(void);
|
||||
int gpio_number(pins_t *pin);
|
||||
int lookup_gpio_by_key(const char *key);
|
||||
int lookup_gpio_by_name(const char *name);
|
||||
int lookup_ain_by_key(const char *key);
|
||||
@ -89,3 +90,6 @@ int get_pwm_key(const char *input, char *key);
|
||||
int get_adc_ain(const char *key, unsigned int *ain);
|
||||
int build_path(const char *partial_path, const char *prefix, char *full_path, size_t full_path_len);
|
||||
int get_spi_bus_path_number(unsigned int spi);
|
||||
void dyn_int_array_set(void **in_array, int i, int val, int initial_val);
|
||||
int dyn_int_array_get(void **in_array, int i, int initial_val);
|
||||
void dyn_int_array_delete(void **in_array);
|
||||
|
@ -77,7 +77,7 @@ struct gpio_exp
|
||||
struct gpio_exp *exported_gpios = NULL;
|
||||
|
||||
pthread_t threads;
|
||||
int event_occurred[430] = { 0 };
|
||||
void *event_occurred = NULL;
|
||||
int thread_running = 0;
|
||||
int epfd = -1;
|
||||
|
||||
@ -92,8 +92,12 @@ int gpio_export(unsigned int gpio)
|
||||
return -1;
|
||||
}
|
||||
len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); BUF2SMALL(str_gpio);
|
||||
ssize_t s = write(fd, str_gpio, len); ASSRT(s == len);
|
||||
ssize_t s = write(fd, str_gpio, len);
|
||||
close(fd);
|
||||
if (s != len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// add to list
|
||||
new_gpio = malloc(sizeof(struct gpio_exp));
|
||||
@ -183,8 +187,9 @@ int open_value_file(unsigned int gpio)
|
||||
// create file descriptor of value file
|
||||
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", gpio); BUF2SMALL(filename);
|
||||
|
||||
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0)
|
||||
return -1;
|
||||
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
add_fd_list(gpio, fd);
|
||||
return fd;
|
||||
}
|
||||
@ -240,7 +245,6 @@ int gpio_set_direction(unsigned int gpio, unsigned int in_flag)
|
||||
} else {
|
||||
strncpy(direction, "in", ARRAY_SIZE(direction) - 1);
|
||||
}
|
||||
|
||||
ssize_t s = write(fd, direction, strlen(direction)); ASSRT(s == strlen(direction));
|
||||
close(fd);
|
||||
return 0;
|
||||
@ -285,8 +289,11 @@ int gpio_set_value(unsigned int gpio, unsigned int value)
|
||||
strncpy(vstr, "0", ARRAY_SIZE(vstr) - 1);
|
||||
}
|
||||
|
||||
ssize_t s = write(fd, vstr, strlen(vstr)); ASSRT(s == strlen(vstr));
|
||||
ssize_t s = write(fd, vstr, strlen(vstr));
|
||||
close(fd);
|
||||
|
||||
if (s != strlen(vstr))
|
||||
return -2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -454,11 +461,12 @@ void *poll_thread(void *threadarg)
|
||||
thread_running = 0;
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
// The return value represents the ending level after the edge.
|
||||
gpio = gpio_lookup(events.data.fd);
|
||||
if (gpio_initial(gpio)) { // ignore first epoll trigger
|
||||
set_initial_false(gpio);
|
||||
} else {
|
||||
event_occurred[gpio] = 1;
|
||||
dyn_int_array_set(&event_occurred, gpio, 1, 0);
|
||||
run_callbacks(gpio);
|
||||
}
|
||||
}
|
||||
@ -512,6 +520,7 @@ int gpio_event_remove(unsigned int gpio)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// add_edge_detect assumes the caller has ensured the GPIO is already exported.
|
||||
int add_edge_detect(unsigned int gpio, unsigned int edge)
|
||||
// return values:
|
||||
// 0 - Success
|
||||
@ -528,31 +537,34 @@ int add_edge_detect(unsigned int gpio, unsigned int edge)
|
||||
return 1;
|
||||
|
||||
// export /sys/class/gpio interface
|
||||
gpio_export(gpio);
|
||||
gpio_set_direction(gpio, 0); // 0=input
|
||||
gpio_set_edge(gpio, edge);
|
||||
|
||||
if (!fd)
|
||||
{
|
||||
if ((fd = open_value_file(gpio)) == -1)
|
||||
if ((fd = open_value_file(gpio)) == -1) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
// create epfd if not already open
|
||||
if ((epfd == -1) && ((epfd = epoll_create(1)) == -1))
|
||||
if ((epfd == -1) && ((epfd = epoll_create(1)) == -1)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// add to epoll fd
|
||||
ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
|
||||
ev.data.fd = fd;
|
||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
|
||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// start poll thread if it is not already running
|
||||
if (!thread_running)
|
||||
{
|
||||
if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0)
|
||||
if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -576,13 +588,13 @@ void remove_edge_detect(unsigned int gpio)
|
||||
gpio_event_remove(gpio);
|
||||
|
||||
// clear detected flag
|
||||
event_occurred[gpio] = 0;
|
||||
dyn_int_array_set(&event_occurred, gpio, 0, 0);
|
||||
}
|
||||
|
||||
int event_detected(unsigned int gpio)
|
||||
{
|
||||
if (event_occurred[gpio]) {
|
||||
event_occurred[gpio] = 0;
|
||||
if (dyn_int_array_get(&event_occurred, gpio, 0)) {
|
||||
dyn_int_array_set(&event_occurred, gpio, 0, 0);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@ -612,7 +624,7 @@ int blocking_wait_for_edge(unsigned int gpio, unsigned int edge)
|
||||
return 2;
|
||||
|
||||
// export /sys/class/gpio interface
|
||||
gpio_export(gpio);
|
||||
gpio_export(gpio); // ignore errors
|
||||
gpio_set_direction(gpio, 0); // 0=input
|
||||
gpio_set_edge(gpio, edge);
|
||||
|
||||
|
188
source/py_gpio.c
188
source/py_gpio.c
@ -45,7 +45,7 @@ SOFTWARE.
|
||||
static int gpio_warnings = 1;
|
||||
|
||||
int max_gpio = -1;
|
||||
int *gpio_direction = NULL;
|
||||
void *gpio_direction = NULL;
|
||||
|
||||
struct py_callback
|
||||
{
|
||||
@ -60,26 +60,15 @@ static struct py_callback *py_callbacks = NULL;
|
||||
|
||||
static int init_module(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
max_gpio = 1024;
|
||||
gpio_direction = (int *)malloc(max_gpio * sizeof(int));
|
||||
for (i=0; i<max_gpio; i++)
|
||||
gpio_direction[i] = -1;
|
||||
|
||||
module_setup = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void set_gpio_direction(int gpio, int direction)
|
||||
static void remember_gpio_direction(int gpio, int direction)
|
||||
{
|
||||
if (gpio >= max_gpio) { /* Does gpio_direction need to be expanded? */
|
||||
max_gpio = gpio + (gpio / 2);
|
||||
gpio_direction = (int *)realloc(gpio_direction, max_gpio * sizeof(int));
|
||||
}
|
||||
gpio_direction[gpio] = direction;
|
||||
dyn_int_array_set(&gpio_direction, gpio, direction, -1);
|
||||
}
|
||||
|
||||
// python function cleanup()
|
||||
@ -124,21 +113,23 @@ static PyObject *py_setup_channel(PyObject *self, PyObject *args, PyObject *kwar
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
return NULL;
|
||||
|
||||
gpio_export(gpio);
|
||||
gpio_set_direction(gpio, direction);
|
||||
// For some reason, the following code doesn't work for XIOs. Skip.
|
||||
if (!(gpio >= lookup_gpio_by_name("XIO-P0") && gpio <= lookup_gpio_by_name("XIO-P7"))) {
|
||||
if (direction == OUTPUT) {
|
||||
gpio_set_value(gpio, initial);
|
||||
} else {
|
||||
gpio_set_value(gpio, pud);
|
||||
}
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid value for channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
set_gpio_direction(gpio, direction);
|
||||
int result = gpio_export(gpio);
|
||||
if (result < 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "Channel in use (already exported)");
|
||||
return NULL;
|
||||
}
|
||||
gpio_set_direction(gpio, direction);
|
||||
// For some reason, the following code doesn't work for XIOs. Skip.
|
||||
if (direction == OUTPUT) {
|
||||
gpio_set_value(gpio, initial);
|
||||
}
|
||||
|
||||
remember_gpio_direction(gpio, direction);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@ -153,16 +144,22 @@ static PyObject *py_output_gpio(PyObject *self, PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "si", &channel, &value))
|
||||
return NULL;
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!module_setup || gpio_direction[gpio] != OUTPUT)
|
||||
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != OUTPUT)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "The GPIO channel has not been setup() as an OUTPUT");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gpio_set_value(gpio, value);
|
||||
int result = gpio_set_value(gpio, value);
|
||||
if (result < 0) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Could not write to channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@ -178,11 +175,13 @@ static PyObject *py_input_gpio(PyObject *self, PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "s", &channel))
|
||||
return NULL;
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check channel is set up as an input or output
|
||||
if (!module_setup || (gpio_direction[gpio] != INPUT && gpio_direction[gpio] != OUTPUT))
|
||||
if (!module_setup || (dyn_int_array_get(&gpio_direction, gpio, -1) == -1))
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel first");
|
||||
return NULL;
|
||||
@ -282,8 +281,10 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
return NULL;
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check to ensure gpio is one of the allowed pins
|
||||
if (gpio != lookup_gpio_by_name("AP-EINT3")
|
||||
@ -294,7 +295,7 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
|
||||
}
|
||||
|
||||
// check channel is set up as an input
|
||||
if (!module_setup || gpio_direction[gpio] != INPUT)
|
||||
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
|
||||
return NULL;
|
||||
@ -305,7 +306,6 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
|
||||
PyErr_SetString(PyExc_RuntimeError, "Add event detection using add_event_detect first before adding a callback");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (add_py_callback(channel, gpio, bouncetime, cb_func) != 0)
|
||||
return NULL;
|
||||
|
||||
@ -331,8 +331,10 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check to ensure gpio is one of the allowed pins
|
||||
if (gpio != lookup_gpio_by_name("AP-EINT3")
|
||||
@ -343,7 +345,7 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
|
||||
}
|
||||
|
||||
// check channel is set up as an input
|
||||
if (!module_setup || gpio_direction[gpio] != INPUT)
|
||||
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
|
||||
return NULL;
|
||||
@ -387,8 +389,10 @@ static PyObject *py_remove_event_detect(PyObject *self, PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "s", &channel))
|
||||
return NULL;
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
return NULL;
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check to ensure gpio is one of the allowed pins
|
||||
if (gpio != lookup_gpio_by_name("AP-EINT3")
|
||||
@ -431,8 +435,10 @@ static PyObject *py_event_detected(PyObject *self, PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "s", &channel))
|
||||
return NULL;
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (event_detected(gpio))
|
||||
Py_RETURN_TRUE;
|
||||
@ -451,8 +457,10 @@ static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "si", &channel, &edge))
|
||||
return NULL;
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
return NULL;
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check to ensure gpio is one of the allowed pins
|
||||
if (gpio != lookup_gpio_by_name("AP-EINT3")
|
||||
@ -463,7 +471,7 @@ static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
// check channel is setup as an input
|
||||
if (!module_setup || gpio_direction[gpio] != INPUT)
|
||||
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
|
||||
return NULL;
|
||||
@ -507,8 +515,10 @@ static PyObject *py_gpio_function(PyObject *self, PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "s", &channel))
|
||||
return NULL;
|
||||
|
||||
if (get_gpio_number(channel, &gpio))
|
||||
if (get_gpio_number(channel, &gpio)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (setup_error)
|
||||
{
|
||||
@ -538,17 +548,105 @@ static PyObject *py_setwarnings(PyObject *self, PyObject *args)
|
||||
|
||||
// Internal unit tests
|
||||
extern int num_get_xio_base;
|
||||
extern pins_t pins_info[];
|
||||
static PyObject *py_selftest(PyObject *self, PyObject *args)
|
||||
{
|
||||
int input;
|
||||
if (!PyArg_ParseTuple(args, "i", &input))
|
||||
return NULL;
|
||||
|
||||
printf("Testing get_xio_base\n");
|
||||
ASSRT(num_get_xio_base == 0);
|
||||
int base = get_xio_base(); ASSRT(base > 0 && base < 1024);
|
||||
ASSRT(num_get_xio_base == 1);
|
||||
int second_base = get_xio_base(); ASSRT(second_base == base);
|
||||
ASSRT(num_get_xio_base == 1); /* make sure it didn't do the full calc a second time. */
|
||||
printf("base=%d\n", base);
|
||||
|
||||
printf("Testing lookup_gpio_by_key\n");
|
||||
ASSRT(0 == lookup_gpio_by_key("U13_1"));
|
||||
ASSRT(48 == lookup_gpio_by_key("U13_9"));
|
||||
ASSRT(47 == lookup_gpio_by_key("U13_11"));
|
||||
ASSRT(base == lookup_gpio_by_key("U14_13"));
|
||||
ASSRT((base+1) == lookup_gpio_by_key("U14_14"));
|
||||
ASSRT((base+6) == lookup_gpio_by_key("U14_19"));
|
||||
ASSRT((base+7) == lookup_gpio_by_key("U14_20"));
|
||||
ASSRT(193 == lookup_gpio_by_key("U14_23"));
|
||||
ASSRT(139 == lookup_gpio_by_key("U14_38"));
|
||||
ASSRT(0 == lookup_gpio_by_key("U14_40"));
|
||||
ASSRT(0 == lookup_gpio_by_key("NOTFOUND"));
|
||||
ASSRT(0 == lookup_gpio_by_key("U14_"));
|
||||
ASSRT(0 == lookup_gpio_by_key("U14_4000"));
|
||||
|
||||
printf("Testing lookup_gpio_by_name\n");
|
||||
ASSRT(0 == lookup_gpio_by_name("GND"));
|
||||
ASSRT(48 == lookup_gpio_by_name("TWI1-SDA"));
|
||||
ASSRT(47 == lookup_gpio_by_name("TWI1-SCK"));
|
||||
ASSRT(base == lookup_gpio_by_name("XIO-P0"));
|
||||
ASSRT((base+6) == lookup_gpio_by_name("XIO-P6"));
|
||||
ASSRT((base+7) == lookup_gpio_by_name("XIO-P7"));
|
||||
ASSRT(139 == lookup_gpio_by_name("CSID7"));
|
||||
ASSRT(0 == lookup_gpio_by_name("NOTFOUND"));
|
||||
ASSRT(0 == lookup_gpio_by_name("CSID"));
|
||||
ASSRT(0 == lookup_gpio_by_name("CSID777"));
|
||||
|
||||
printf("Testing lookup_ain_by_key\n");
|
||||
ASSRT(-1 == lookup_ain_by_key("U14_1"));
|
||||
ASSRT(0 == lookup_ain_by_key("U14_11"));
|
||||
ASSRT(-1 == lookup_ain_by_key("NOTFOUND"));
|
||||
ASSRT(-1 == lookup_ain_by_key("U14_"));
|
||||
ASSRT(-1 == lookup_ain_by_key("U14_1111"));
|
||||
|
||||
printf("Testing lookup_ain_by_name\n");
|
||||
ASSRT(-1 == lookup_ain_by_name("GND"));
|
||||
ASSRT(0 == lookup_ain_by_name("LRADC"));
|
||||
ASSRT(-1 == lookup_ain_by_name("NOTFOUND"));
|
||||
ASSRT(-1 == lookup_ain_by_name("LR"));
|
||||
ASSRT(-1 == lookup_ain_by_name("LRADCCC"));
|
||||
|
||||
char k[9];
|
||||
|
||||
printf("Testing copy_key_by_key\n");
|
||||
ASSRT(1 == copy_key_by_key("U13_1", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U13_1", k));
|
||||
ASSRT(1 == copy_key_by_key("U14_40", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U14_40", k));
|
||||
ASSRT(0 == copy_key_by_key("NOTFOUND", k));
|
||||
ASSRT(0 == copy_key_by_key("U14_", k));
|
||||
ASSRT(0 == copy_key_by_key("U14_4000", k));
|
||||
|
||||
printf("Testing copy_pwm_key_by_key\n");
|
||||
ASSRT(1 == copy_pwm_key_by_key("U13_18", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U13_18", k));
|
||||
ASSRT(0 == copy_pwm_key_by_key("U13_1", k));
|
||||
ASSRT(0 == copy_pwm_key_by_key("U14_40", k));
|
||||
ASSRT(0 == copy_pwm_key_by_key("NOTFOUND", k));
|
||||
ASSRT(0 == copy_pwm_key_by_key("U13_", k));
|
||||
ASSRT(0 == copy_pwm_key_by_key("U13_1888", k));
|
||||
|
||||
printf("Testing get_key_by_name\n");
|
||||
ASSRT(1 == get_key_by_name("GND", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U13_1", k));
|
||||
ASSRT(1 == get_key_by_name("CSID7", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U14_38", k));
|
||||
ASSRT(0 == get_key_by_name("NOTFOUND", k));
|
||||
ASSRT(0 == get_key_by_name("CSID", k));
|
||||
ASSRT(0 == get_key_by_name("CSID777", k));
|
||||
|
||||
printf("Testing get_pwm_key_by_name\n");
|
||||
ASSRT(1 == get_pwm_key_by_name("PWM0", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U13_18", k));
|
||||
ASSRT(0 == get_pwm_key_by_name("NOTFOUND", k));
|
||||
ASSRT(0 == get_pwm_key_by_name("PWM", k));
|
||||
ASSRT(0 == get_pwm_key_by_name("PWM000", k));
|
||||
|
||||
char fp[80];
|
||||
|
||||
printf("Testing build_path\n");
|
||||
ASSRT(1 == build_path("/home", "ch", fp, sizeof(fp))); ASSRT(0 == strcmp("/home/chip", fp));
|
||||
ASSRT(1 == build_path("/home", "chip", fp, sizeof(fp))); ASSRT(0 == strcmp("/home/chip", fp));
|
||||
ASSRT(0 == build_path("/home", "NOTFOUND", fp, sizeof(fp)));
|
||||
ASSRT(0 == build_path("/home", "chipp", fp, sizeof(fp)));
|
||||
ASSRT(0 == build_path("/home", "ip", fp, sizeof(fp)));
|
||||
ASSRT(0 == build_path("/NOTFOUND", "ch", fp, sizeof(fp)));
|
||||
|
||||
printf("Testing get_spi_bus_path_number\n");
|
||||
ASSRT(2 == get_spi_bus_path_number(0)); /* doesn't really work on CHIP */
|
||||
ASSRT(2 == get_spi_bus_path_number(1)); /* doesn't really work on CHIP */
|
||||
|
||||
int value = input;
|
||||
|
||||
|
@ -32,13 +32,13 @@ SOFTWARE.
|
||||
#include "Python.h"
|
||||
#include "constants.h"
|
||||
#include "common.h"
|
||||
#include "c_softpwm.h"
|
||||
#include "c_softpwm.h"
|
||||
|
||||
// python function cleanup()
|
||||
static PyObject *py_cleanup(PyObject *self, PyObject *args)
|
||||
{
|
||||
// unexport the PWM
|
||||
softpwm_cleanup();
|
||||
softpwm_cleanup();
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@ -47,7 +47,7 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args)
|
||||
static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
char key[8];
|
||||
char *channel;
|
||||
char *channel = NULL;
|
||||
float frequency = 2000.0;
|
||||
float duty_cycle = 0.0;
|
||||
int polarity = 0;
|
||||
@ -56,6 +56,7 @@ static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwar
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ffi", kwlist, &channel, &duty_cycle, &frequency, &polarity)) {
|
||||
return NULL;
|
||||
}
|
||||
ASSRT(channel != NULL);
|
||||
|
||||
if (!get_key(channel, key)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid SOFTPWM key or name.");
|
||||
@ -79,7 +80,7 @@ static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwar
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!softpwm_start(key, duty_cycle, frequency, polarity))
|
||||
if (!softpwm_start(key, duty_cycle, frequency, polarity))
|
||||
return NULL;
|
||||
|
||||
Py_RETURN_NONE;
|
||||
@ -94,12 +95,12 @@ static PyObject *py_stop_channel(PyObject *self, PyObject *args, PyObject *kwarg
|
||||
if (!PyArg_ParseTuple(args, "s", &channel))
|
||||
return NULL;
|
||||
|
||||
if (!get_key(channel, key)) {
|
||||
if (!get_key(channel, key)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
softpwm_disable(key);
|
||||
softpwm_disable(key);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@ -121,12 +122,12 @@ static PyObject *py_set_duty_cycle(PyObject *self, PyObject *args, PyObject *kwa
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!get_key(channel, key)) {
|
||||
if (!get_key(channel, key)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (softpwm_set_duty_cycle(key, duty_cycle) == -1) {
|
||||
if (softpwm_set_duty_cycle(key, duty_cycle) == -1) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "You must start() the PWM channel first");
|
||||
return NULL;
|
||||
}
|
||||
@ -145,13 +146,13 @@ static PyObject *py_set_frequency(PyObject *self, PyObject *args, PyObject *kwar
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|f", kwlist, &channel, &frequency))
|
||||
return NULL;
|
||||
|
||||
if ((frequency <= 0.0) || (frequency > 10000.0))
|
||||
if ((frequency <= 0.0) || (frequency > 10000.0))
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "frequency must be greater than 0.0 and less than 10000.0");
|
||||
PyErr_SetString(PyExc_ValueError, "frequency must be greater than 0.0 and less than 10000.0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!get_key(channel, key)) {
|
||||
if (!get_key(channel, key)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
|
||||
return NULL;
|
||||
}
|
||||
|
96
test/.ropeproject/config.py
Normal file
96
test/.ropeproject/config.py
Normal file
@ -0,0 +1,96 @@
|
||||
# The default ``config.py``
|
||||
|
||||
|
||||
def set_prefs(prefs):
|
||||
"""This function is called before opening the project"""
|
||||
|
||||
# Specify which files and folders to ignore in the project.
|
||||
# Changes to ignored resources are not added to the history and
|
||||
# VCSs. Also they are not returned in `Project.get_files()`.
|
||||
# Note that ``?`` and ``*`` match all characters but slashes.
|
||||
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
|
||||
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
|
||||
# '.svn': matches 'pkg/.svn' and all of its children
|
||||
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
|
||||
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
|
||||
prefs['ignored_resources'] = [
|
||||
'*.pyc', '*~', '.ropeproject', '.hg', '.svn', '_svn', '.git',
|
||||
'.tox', '.env', 'node_modules', 'bower_components']
|
||||
|
||||
# Specifies which files should be considered python files. It is
|
||||
# useful when you have scripts inside your project. Only files
|
||||
# ending with ``.py`` are considered to be python files by
|
||||
# default.
|
||||
#prefs['python_files'] = ['*.py']
|
||||
|
||||
# Custom source folders: By default rope searches the project
|
||||
# for finding source folders (folders that should be searched
|
||||
# for finding modules). You can add paths to that list. Note
|
||||
# that rope guesses project source folders correctly most of the
|
||||
# time; use this if you have any problems.
|
||||
# The folders should be relative to project root and use '/' for
|
||||
# separating folders regardless of the platform rope is running on.
|
||||
# 'src/my_source_folder' for instance.
|
||||
#prefs.add('source_folders', 'src')
|
||||
|
||||
# You can extend python path for looking up modules
|
||||
#prefs.add('python_path', '~/python/')
|
||||
|
||||
# Should rope save object information or not.
|
||||
prefs['save_objectdb'] = True
|
||||
prefs['compress_objectdb'] = False
|
||||
|
||||
# If `True`, rope analyzes each module when it is being saved.
|
||||
prefs['automatic_soa'] = True
|
||||
# The depth of calls to follow in static object analysis
|
||||
prefs['soa_followed_calls'] = 0
|
||||
|
||||
# If `False` when running modules or unit tests "dynamic object
|
||||
# analysis" is turned off. This makes them much faster.
|
||||
prefs['perform_doa'] = True
|
||||
|
||||
# Rope can check the validity of its object DB when running.
|
||||
prefs['validate_objectdb'] = True
|
||||
|
||||
# How many undos to hold?
|
||||
prefs['max_history_items'] = 32
|
||||
|
||||
# Shows whether to save history across sessions.
|
||||
prefs['save_history'] = True
|
||||
prefs['compress_history'] = False
|
||||
|
||||
# Set the number spaces used for indenting. According to
|
||||
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
|
||||
# unit-tests use 4 spaces it is more reliable, too.
|
||||
prefs['indent_size'] = 4
|
||||
|
||||
# Builtin and c-extension modules that are allowed to be imported
|
||||
# and inspected by rope.
|
||||
prefs['extension_modules'] = []
|
||||
|
||||
# Add all standard c-extensions to extension_modules list.
|
||||
prefs['import_dynload_stdmods'] = True
|
||||
|
||||
# If `True` modules with syntax errors are considered to be empty.
|
||||
# The default value is `False`; When `False` syntax errors raise
|
||||
# `rope.base.exceptions.ModuleSyntaxError` exception.
|
||||
prefs['ignore_syntax_errors'] = False
|
||||
|
||||
# If `True`, rope ignores unresolvable imports. Otherwise, they
|
||||
# appear in the importing namespace.
|
||||
prefs['ignore_bad_imports'] = False
|
||||
|
||||
# If `True`, rope will transform a comma list of imports into
|
||||
# multiple separate import statements when organizing
|
||||
# imports.
|
||||
prefs['split_imports'] = False
|
||||
|
||||
# If `True`, rope will sort imports alphabetically by module name
|
||||
# instead of alphabetically by import statement, with from imports
|
||||
# after normal imports.
|
||||
prefs['sort_imports_alphabetically'] = False
|
||||
|
||||
|
||||
def project_opened(project):
|
||||
"""This function is called after opening the project"""
|
||||
# Do whatever you like here!
|
2
test/.ropeproject/globalnames
Normal file
2
test/.ropeproject/globalnames
Normal file
@ -0,0 +1,2 @@
|
||||
<EFBFBD>}q(Utest_softpwm_setup]q(Uteardown_moduleqUTestSoftpwmSetupqeUtest_gpio_output]q(hUTestGPIOOutputqeUtest_pwm_setup]q(hUTestPwmSetupqeUtest_gpio_setup]q (hU TestSetupq
|
||||
eUtest_gpio_input]q(hU
|
1
test/.ropeproject/history
Normal file
1
test/.ropeproject/history
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>]q(]q]qe.
|
5
test/.ropeproject/objectdb
Normal file
5
test/.ropeproject/objectdb
Normal file
@ -0,0 +1,5 @@
|
||||
<EFBFBD>}qUS/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py}q(U
|
||||
Thread._blockcrope.base.oi.memorydb
|
||||
ScopeInfo
|
||||
q)<29>q}qUinstanceqUdefinedqUS/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.pyUThreadq<08><><EFBFBD>hhUS/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.pyU
|
||||
_Conditionq <09><>s}q
|
@ -1,27 +1,49 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import CHIP_IO.GPIO as GPIO
|
||||
import time, os, threading
|
||||
import time
|
||||
import threading
|
||||
|
||||
num_callbacks = 0
|
||||
|
||||
|
||||
def myfuncallback(channel):
|
||||
global num_callbacks
|
||||
num_callbacks += 1
|
||||
print "CALLBACK LIKE DRAKE IN HOTLINE BLING"
|
||||
|
||||
|
||||
|
||||
loopfunction_exit = False
|
||||
|
||||
|
||||
def loopfunction():
|
||||
print "LOOP FUNCTION"
|
||||
for i in xrange(20):
|
||||
for i in xrange(4):
|
||||
if loopfunction_exit:
|
||||
break
|
||||
if i % 2:
|
||||
print "SETTING CSID0 LOW"
|
||||
GPIO.output("CSID0",GPIO.LOW)
|
||||
print "SETTING CSID0 LOW (i=", i, ")"
|
||||
GPIO.output("CSID0", GPIO.LOW)
|
||||
else:
|
||||
print "SETTING CSID0 HIGH"
|
||||
GPIO.output("CSID0",GPIO.HIGH)
|
||||
print "SETTING CSID0 HIGH (i=", i, ")"
|
||||
GPIO.output("CSID0", GPIO.HIGH)
|
||||
print "SLEEPING"
|
||||
time.sleep(1)
|
||||
|
||||
print "SETUP XIO-P0"
|
||||
GPIO.setup("XIO-P0", GPIO.IN)
|
||||
|
||||
print "SETUP CSID0"
|
||||
|
||||
GPIO.selftest(0)
|
||||
|
||||
GPIO.setup("XIO-P0", GPIO.IN)
|
||||
GPIO.setup("CSID0", GPIO.OUT, initial=GPIO.HIGH)
|
||||
assert(GPIO.input("XIO-P0") == GPIO.HIGH)
|
||||
GPIO.cleanup()
|
||||
|
||||
GPIO.setup("XIO-P0", GPIO.IN)
|
||||
GPIO.setup("CSID0", GPIO.OUT, initial=GPIO.LOW)
|
||||
assert(GPIO.input("XIO-P0") == GPIO.LOW)
|
||||
GPIO.cleanup()
|
||||
|
||||
GPIO.setup("XIO-P0", GPIO.IN)
|
||||
GPIO.setup("CSID0", GPIO.OUT)
|
||||
|
||||
# VERIFY SIMPLE FUNCTIONALITY
|
||||
@ -29,51 +51,57 @@ print "VERIFY SIMPLE FUNCTIONALITY"
|
||||
|
||||
print "READING XIO-PI"
|
||||
GPIO.output("CSID0", GPIO.HIGH)
|
||||
print "HIGH", GPIO.input("XIO-P0")
|
||||
assert(GPIO.input("XIO-P0") == GPIO.HIGH)
|
||||
|
||||
GPIO.output("CSID0", GPIO.LOW)
|
||||
print "LOW", GPIO.input("XIO-P0")
|
||||
assert(GPIO.input("XIO-P0") == GPIO.LOW)
|
||||
|
||||
# ==============================================
|
||||
# EDGE DETECTION - AP-EINT1
|
||||
print "SETTING UP EDGE DETECTION ON AP-EINT1"
|
||||
GPIO.setup("AP-EINT1", GPIO.IN)
|
||||
GPIO.add_event_detect("AP-EINT1",GPIO.FALLING)
|
||||
print "adding event detect"
|
||||
GPIO.add_event_detect("AP-EINT1", GPIO.RISING)
|
||||
|
||||
print "VERIFYING EDGE DETECT"
|
||||
f = open("/sys/class/gpio/gpio193/edge","r")
|
||||
f = open("/sys/class/gpio/gpio193/edge", "r")
|
||||
edge = f.read()
|
||||
f.close()
|
||||
print "EDGE: %s" % edge
|
||||
print "edge='", edge, "'"
|
||||
assert(edge == "rising\n")
|
||||
GPIO.remove_event_detect("AP-EINT1")
|
||||
|
||||
# ==============================================
|
||||
# EDGE DETECTION - AP-EINT3
|
||||
print "SETTING UP EDGE DETECTION ON AP-EINT3"
|
||||
GPIO.setup("AP-EINT3", GPIO.IN)
|
||||
GPIO.add_event_detect("AP-EINT3",GPIO.FALLING)
|
||||
GPIO.add_event_detect("AP-EINT3", GPIO.BOTH)
|
||||
|
||||
print "VERIFYING EDGE DETECT"
|
||||
f = open("/sys/class/gpio/gpio35/edge","r")
|
||||
f = open("/sys/class/gpio/gpio35/edge", "r")
|
||||
edge = f.read()
|
||||
f.close()
|
||||
print "EDGE: %s" % edge
|
||||
assert(edge == "both\n")
|
||||
GPIO.remove_event_detect("AP-EINT3")
|
||||
|
||||
# ==============================================
|
||||
# EDGE DETECTION - EXPANDED GPIO
|
||||
print "SETTING UP EDGE DETECTION ON XIO-P0"
|
||||
GPIO.add_event_detect("XIO-P0",GPIO.FALLING,myfuncallback)
|
||||
GPIO.add_event_detect("XIO-P0", GPIO.FALLING, myfuncallback)
|
||||
|
||||
print "VERIFYING EDGE DETECT"
|
||||
f = open("/sys/class/gpio/gpio408/edge","r")
|
||||
f = open("/sys/class/gpio/gpio408/edge", "r")
|
||||
edge = f.read()
|
||||
f.close()
|
||||
print "EDGE: %s" % edge
|
||||
assert(edge == "falling\n")
|
||||
|
||||
# LOOP WRITING ON CSID0 TO HOPEFULLY GET CALLBACK TO WORK
|
||||
print "WAITING FOR CALLBACKS"
|
||||
loopfunction()
|
||||
print "num_callbacks=", num_callbacks
|
||||
|
||||
print "PRESS CONTROL-C TO EXIT IF SCRIPT GETS STUCK"
|
||||
GPIO.remove_event_detect("XIO-P0")
|
||||
@ -82,18 +110,30 @@ try:
|
||||
t = threading.Thread(target=loopfunction)
|
||||
t.start()
|
||||
print "WAITING FOR EDGE"
|
||||
GPIO.wait_for_edge("XIO-P0",GPIO.FALLING)
|
||||
GPIO.wait_for_edge("XIO-P0", GPIO.FALLING)
|
||||
print "WE'VE FALLEN LIKE COOLIO'S CAREER"
|
||||
print "ATTEMPTING TO CANCEL THE TIMER"
|
||||
t.cancel()
|
||||
except:
|
||||
pass
|
||||
|
||||
print "Exit thread"
|
||||
loopfunction_exit = True
|
||||
t.join() # Wait till the thread exits.
|
||||
GPIO.remove_event_detect("XIO-P0")
|
||||
|
||||
print "TESTING ERRORS THROWN WHEN SPECIFYING EDGE DETECTION ON UNAUTHORIZED GPIO"
|
||||
GPIO.setup("CSID1",GPIO.IN)
|
||||
GPIO.add_event_detect("CSID1",GPIO.FALLING,myfuncallback)
|
||||
GPIO.setup("CSID1", GPIO.IN)
|
||||
try:
|
||||
GPIO.add_event_detect("CSID1", GPIO.FALLING, myfuncallback)
|
||||
print "Oops, it did not throw an exception! BUG!!!"
|
||||
except:
|
||||
pass
|
||||
|
||||
print "TESTING ERRORS THROWN WHEN WRITING TO A GPIO WITH NO DIRECTION"
|
||||
try:
|
||||
GPIO.output("CSID1", GPIO.LOW)
|
||||
print "Oops, it did not throw an exception! BUG!!!"
|
||||
except:
|
||||
pass
|
||||
|
||||
print "CLEANUP"
|
||||
GPIO.remove_event_detect("XIO-P0")
|
||||
GPIO.cleanup()
|
||||
|
||||
|
7
unexport_all.sh
Executable file
7
unexport_all.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
for F in /sys/class/gpio/gpio[0-9]*; do :
|
||||
GPIO=`echo $F | sed 's/^[^0-9]*//'`
|
||||
echo $F $GPIO
|
||||
echo $GPIO >/sys/class/gpio/unexport
|
||||
done
|
Reference in New Issue
Block a user