1
0
mirror of https://github.com/xtacocorex/CHIP_IO synced 2025-07-20 12:53:22 +00:00

Adds mutex protection

This commit is contained in:
Brady L. Hurlburt
2016-04-24 13:09:36 -04:00
parent d7bf982b11
commit 41203a46a6

View File

@ -44,26 +44,28 @@ SOFTWARE.
#define KEYLEN 7 #define KEYLEN 7
#define NOTCHIPHW
#define PERIOD 0 #define PERIOD 0
#define DUTY 1 #define DUTY 1
int pwm_initialized = 0; int pwm_initialized = 0;
// pwm exports struct pwm_params
struct softpwm
{ {
char key[KEYLEN+1]; /* leave room for terminating NUL byte */
float duty; float duty;
float freq; float freq;
pthread_t thread;
struct softpwm *next;
bool enabled; bool enabled;
bool stop_flag; bool stop_flag;
int polarity; int polarity;
}; };
struct softpwm
{
char key[KEYLEN+1]; /* leave room for terminating NUL byte */
struct pwm_params params;
pthread_mutex_t* params_lock;
pthread_t thread;
struct softpwm *next;
};
struct softpwm *exported_pwms = NULL; struct softpwm *exported_pwms = NULL;
struct softpwm *lookup_exported_pwm(const char *key) struct softpwm *lookup_exported_pwm(const char *key)
@ -93,7 +95,9 @@ int softpwm_set_frequency(const char *key, float freq) {
return -1; return -1;
} }
pwm->freq = freq; pthread_mutex_lock(pwm->params_lock);
pwm->params.freq = freq;
pthread_mutex_unlock(pwm->params_lock);
return 1; return 1;
} }
@ -111,7 +115,9 @@ int softpwm_set_polarity(const char *key, int polarity) {
return -1; return -1;
} }
pwm->polarity = polarity; pthread_mutex_lock(pwm->params_lock);
pwm->params.polarity = polarity;
pthread_mutex_unlock(pwm->params_lock);
return 0; return 0;
} }
@ -128,7 +134,9 @@ int softpwm_set_duty_cycle(const char *key, float duty) {;
return -1; return -1;
} }
pwm->duty = duty; pthread_mutex_lock(pwm->params_lock);
pwm->params.duty = duty;
pthread_mutex_unlock(pwm->params_lock);
return 0; return 0;
} }
@ -149,17 +157,31 @@ void* softpwm_thread_toggle(void *key)
*/ */
unsigned int freq_local = 0; unsigned int freq_local = 0;
unsigned int duty_local = 0; unsigned int duty_local = 0;
unsigned int polarity_local = 0;
bool stop_flag_local = false;
bool enabled_local = false;
bool recalculate_timing = false;
get_gpio_number(key, &gpio); get_gpio_number(key, &gpio);
pwm = lookup_exported_pwm((char*)key); pwm = lookup_exported_pwm((char*)key);
while (pwm->enabled) { while (!stop_flag_local) {
pthread_mutex_lock(pwm->params_lock);
if ((freq_local != pwm->params.freq) || (duty_local != pwm->params.duty)) {
recalculate_timing = true;
}
freq_local = pwm->params.freq;
duty_local = pwm->params.duty;
enabled_local = pwm->params.enabled;
stop_flag_local = pwm->params.stop_flag;
polarity_local = pwm->params.polarity;
pthread_mutex_unlock(pwm->params_lock);
/* If freq or duty has been changed, update the /* If freq or duty has been changed, update the
* sleep times * sleep times
*/ */
if ((freq_local != pwm->freq) || (duty_local != pwm->duty)) { if (recalculate_timing) {
period_ns = (unsigned long)(1e9 / pwm->freq); period_ns = (unsigned long)(1e9 / freq_local);
on_ns = (unsigned long)(period_ns * (pwm->duty/100)); on_ns = (unsigned long)(period_ns * (duty_local/100));
off_ns = period_ns - on_ns; off_ns = period_ns - on_ns;
sec = (unsigned int)(on_ns/1e9); /* Intentional truncation */ sec = (unsigned int)(on_ns/1e9); /* Intentional truncation */
tim_on.tv_sec = sec; tim_on.tv_sec = sec;
@ -167,51 +189,28 @@ void* softpwm_thread_toggle(void *key)
sec = (unsigned int)(off_ns/1e9); /* Intentional truncation */ sec = (unsigned int)(off_ns/1e9); /* Intentional truncation */
tim_off.tv_sec = sec; tim_off.tv_sec = sec;
tim_off.tv_nsec = off_ns - (sec*1e9); tim_off.tv_nsec = off_ns - (sec*1e9);
freq_local = pwm->freq; recalculate_timing = false;
duty_local = pwm->duty;
} }
if (enabled_local)
{
/* Set gpio */ /* Set gpio */
if (pwm->polarity) if (polarity_local)
{
#ifdef NOTCHIPHW
printf("Setting gpio high");
#else
gpio_set_value(gpio, HIGH); gpio_set_value(gpio, HIGH);
#endif
}
else else
{ gpio_set_value(gpio, LOW);
#ifdef NOTCHIPHW
printf("Setting gpio low");
#else
//gpio_set_value(gpio, LOW);
#endif
}
nanosleep(&tim_on, NULL); nanosleep(&tim_on, NULL);
/* Unset gpio */ /* Unset gpio */
if (pwm->polarity) if (polarity_local)
{
#ifdef NOTCHIPHW
printf("Setting gpio low");
#else
gpio_set_value(gpio, LOW); gpio_set_value(gpio, LOW);
#endif
}
else else
{
#ifdef NOTCHIPHW
printf("Setting gpio high");
#else
gpio_set_value(gpio, HIGH); gpio_set_value(gpio, HIGH);
#endif
}
nanosleep(&tim_off, NULL); nanosleep(&tim_off, NULL);
} }
}
/* This pwm has been disabled */ /* This pwm has been disabled */
pthread_exit(NULL); pthread_exit(NULL);
@ -221,14 +220,13 @@ int softpwm_start(const char *key, float duty, float freq, int polarity)
{ {
struct softpwm *new_pwm, *pwm; struct softpwm *new_pwm, *pwm;
pthread_t *new_thread; pthread_t *new_thread;
pthread_mutex_t *new_params_lock;
unsigned int gpio; unsigned int gpio;
int ret; int ret;
get_gpio_number(key, &gpio); get_gpio_number(key, &gpio);
#ifndef NOTCHIPHW
gpio_export(gpio); gpio_export(gpio);
gpio_set_direction(gpio, OUTPUT); gpio_set_direction(gpio, OUTPUT);
#endif
// add to list // add to list
new_pwm = malloc(sizeof(struct softpwm)); new_pwm = malloc(sizeof(struct softpwm));
@ -236,10 +234,17 @@ int softpwm_start(const char *key, float duty, float freq, int polarity)
return -1; // out of memory return -1; // out of memory
} }
new_params_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
if (new_pwm == 0) {
return -1; // out of memory
}
pthread_mutex_init(new_params_lock, NULL);
strncpy(new_pwm->key, key, KEYLEN); /* can leave string unterminated */ strncpy(new_pwm->key, key, KEYLEN); /* can leave string unterminated */
new_pwm->key[KEYLEN] = '\0'; /* terminate string */ new_pwm->key[KEYLEN] = '\0'; /* terminate string */
new_pwm->enabled = false; new_pwm->params.enabled = false;
new_pwm->stop_flag = false; new_pwm->params.stop_flag = false;
new_pwm->params_lock = new_params_lock;
new_pwm->next = NULL; new_pwm->next = NULL;
if (exported_pwms == NULL) if (exported_pwms == NULL)
@ -265,7 +270,9 @@ int softpwm_start(const char *key, float duty, float freq, int polarity)
exit(-1); exit(-1);
} }
new_pwm->thread = *new_thread; new_pwm->thread = *new_thread;
new_pwm->enabled = true; pthread_mutex_lock(new_params_lock);
new_pwm->params.enabled = true;
pthread_mutex_unlock(new_params_lock);
return 1; return 1;
} }
@ -286,11 +293,11 @@ int softpwm_disable(const char *key)
{ {
if (strcmp(pwm->key, key) == 0) if (strcmp(pwm->key, key) == 0)
{ {
pwm->stop_flag = true; pthread_mutex_lock(pwm->params_lock);
pwm->params.stop_flag = true;
pthread_mutex_unlock(pwm->params_lock);
get_gpio_number(key, &gpio); get_gpio_number(key, &gpio);
#ifndef NOTCHIPHW
gpio_unexport(gpio); gpio_unexport(gpio);
#endif
if (prev_pwm == NULL) if (prev_pwm == NULL)
{ {
@ -302,6 +309,7 @@ int softpwm_disable(const char *key)
temp = pwm; temp = pwm;
pwm = pwm->next; pwm = pwm->next;
free(temp->params_lock);
free(temp); free(temp);
} else { } else {
prev_pwm = pwm; prev_pwm = pwm;