前回は、Spresenseで2つのスレッドでそれぞれLEDの点滅を行いました。
今回はセマフォを使ってみました。
セマフォとは、ある資源(今回の例ではcount
という変数)を複数のスレッドで使用している時に、同時にアクセスされないよう排他制御する仕組みです。
詳細はこの記事の説明がわかりやすいので、そちらをご参照ください。
準備
前回作成したtest
プロジェクトに、新たにアプリを追加します。
$ tools/mkcmd.py -d test semaphore_test "My Semaphore test" # アプリ作成
$ make clean
$ tools/config.py -m # My Semaphore testにチェックを入れる
$ make
セマフォを使ってみる
今回は、
- スレッドA: 200 ms周期でLED1を点滅
- スレッドB: 3秒おきに、LED1を1秒間点灯
とします。
どちらのスレッドでもLED1を使用しているので、セマフォを使って排他制御する必要があります。
semaphore_test.c
#include <sdk/config.h>
#include <stdio.h>
#include <semaphore.h>
#include <arch/board/board.h>
#include <arch/chip/pin.h>
#define PIN_LED0 PIN_I2S1_BCK
#define PIN_LED1 PIN_I2S1_LRCK
#define PIN_LED2 PIN_I2S1_DATA_IN
#define PIN_LED3 PIN_I2S1_DATA_OUT
const int led_pin[4] = {
PIN_LED0,
PIN_LED1,
PIN_LED2,
PIN_LED3
};
sem_t sem;
void toggle_led(uint32_t pin){
board_gpio_write(pin, board_gpio_read(pin) == 0 ? 1 : 0);
}
void* task_A(void *arg)
{
while(1)
{
// 200 ms周期でLED1を点滅
sem_wait(&sem);
toggle_led(led_pin[1]);
sem_post(&sem);
usleep(200*1000);
}
return NULL;
}
void* task_B(void *arg)
{
while(1)
{
// 1秒間LED1を点灯
sem_wait(&sem);
board_gpio_write(led_pin[1], 1);
sleep(1);
board_gpio_write(led_pin[1], 0);
sem_post(&sem);
// 2秒間待機
sleep(2);
}
return NULL;
}
#ifdef CONFIG_BUILD_KERNEL
int main(int argc, FAR char *argv[])
#else
int semaphore_test_main(int argc, char *argv[])
#endif
{
for(int i = 0; i < 4; i++){
board_gpio_config(led_pin[i], 0, true, true, PIN_FLOAT); // GPIOの設定
}
sem_init(&sem, 0, 1);
pthread_t thread_A, thread_B;
pthread_create(&thread_A, NULL, task_A, NULL);
pthread_create(&thread_B, NULL, task_B, NULL);
pthread_join(thread_A, NULL);
pthread_join(thread_B, NULL);
sem_destroy(&sem);
return 0;
}
結果
想定どおりの動きをしていることが確認できます。
試しに、task_A,task_B内のsem_wait
,sem_post
をコメントアウトすると、点滅し続けます。