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:
@ -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;
|
||||||
|
Reference in New Issue
Block a user