Merge "Add EcOs RTOS abstraction layer and pthreads implementation"

This commit is contained in:
Randall Spangler
2011-10-24 10:46:04 -07:00
committed by Gerrit Code Review
6 changed files with 871 additions and 3 deletions

View File

@@ -6,13 +6,22 @@ LIB_SRCS=\
lib/ec_console.c
STUB_SRCS=\
chip_stub/ec_os.c \
chip_stub/ec_uart.c
all: fakemain
TESTPROGS=fakemain ec_os_test
CFLAGS=-Wall -I include -I chip_stub -pthread
all: $(TESTPROGS)
clean:
rm -f fakemain
rm -f $(TESTPROGS)
ec_os_test: test/ec_os_test.c chip_stub/ec_os.c
gcc $(CFLAGS) -o ec_os_test \
test/ec_os_test.c chip_stub/ec_os.c
fakemain: test/fakemain.c $(LIB_SRCS) $(STUB_SRCS)
gcc -Wall -I include -o fakemain test/fakemain.c \
gcc $(CFLAGS) -o fakemain test/fakemain.c \
$(LIB_SRCS) $(STUB_SRCS)

516
cros_ec/chip_stub/ec_os.c Normal file
View File

@@ -0,0 +1,516 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Operating system library EC */
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "ec_common.h"
#include "ec_os.h"
static int os_has_started = 0;
static pthread_mutex_t os_start_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t os_start_cond = PTHREAD_COND_INITIALIZER;
/* Waits for OS to start */
static void WaitForOsStart(void) {
pthread_mutex_lock(&os_start_mutex);
if (!os_has_started)
pthread_cond_wait(&os_start_cond, &os_start_mutex);
pthread_mutex_unlock(&os_start_mutex);
}
static void UsecToTimespec(int usec, struct timespec* ts) {
ts->tv_sec = usec / 1000000;
ts->tv_nsec = 1000 * (long)(usec % 1000000);
}
/*****************************************************************************/
/* Tasks */
/* Internal data for a task */
typedef struct EcTaskInternal {
pthread_t thread;
void (*task_func)(void*);
void* param;
struct EcTaskInternal* next;
} EcTaskInternal;
static EcTaskInternal* task_list = NULL;
static pthread_mutex_t task_list_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Task wrapper. Waits for OS to start, then runs the task function. */
static void* EcTaskWrapper(void* param) {
EcTaskInternal* ti = (EcTaskInternal*)param;
WaitForOsStart();
/* Chain to the task function */
ti->task_func(ti->param);
return NULL;
}
EcError EcTaskCreate(EcTask* task, int priority, int stack_size,
void (*task_func)(void*), void* param) {
EcTaskInternal* ti = (EcTaskInternal*)task;
pthread_attr_t attr;
/* TODO: priority */
/* Initialize task data */
ti->task_func = task_func;
ti->param = param;
/* Add it to the task list */
pthread_mutex_lock(&task_list_mutex);
ti->next = task_list;
task_list = ti;
pthread_mutex_unlock(&task_list_mutex);
/* Mark thread as joinable */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
/* Create the thread */
if (pthread_create(&ti->thread, &attr, EcTaskWrapper, ti) != 0)
return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
void EcTaskSleep(int usec) {
usleep(usec);
}
void EcTaskExit(void) {
pthread_exit(NULL);
}
/*****************************************************************************/
/* Software interrupts (SWI)
*
* SWIs don't exist in pthreads. Simulate them with a thread which waits
* on a semaphore and calls the SWI function when it wakes. */
typedef struct EcSwiInternal {
pthread_t thread;
pthread_cond_t cond;
pthread_mutex_t mutex;
uint32_t pending_bits;
void (*swi_func)(void *, uint32_t);
void* param;
} EcSwiInternal;
/* SWI wrapper. Loops and calls SWI function when semaphore is signalled. */
static void* EcSwiWrapper(void* param) {
EcSwiInternal* si = (EcSwiInternal*)param;
WaitForOsStart();
while (1) {
int bits;
pthread_mutex_lock(&si->mutex);
pthread_cond_wait(&si->cond, &si->mutex);
bits = si->pending_bits;
si->pending_bits = 0;
pthread_mutex_unlock(&si->mutex);
if (bits)
si->swi_func(si->param, bits);
}
return NULL;
}
EcError EcSwiCreate(EcSwi* swi, int priority,
void (*swi_func)(void*, uint32_t), void* param) {
EcSwiInternal* si = (EcSwiInternal*)swi;
/* TODO: priority */
/* Init internal data */
si->pending_bits = 0;
si->swi_func = swi_func;
si->param = param;
/* Allocate pthreads objects for the swi */
if (pthread_mutex_init(&si->mutex, NULL) != 0)
return EC_ERROR_UNKNOWN;
if (pthread_cond_init(&si->cond, NULL) != 0)
return EC_ERROR_UNKNOWN;
if (pthread_create(&si->thread, NULL, EcSwiWrapper, si) != 0)
return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
/* Sets the specified bits in the SWI. */
EcError EcSwiPost(EcSwi* swi, uint32_t bits) {
EcSwiInternal* si = (EcSwiInternal*)swi;
int prev_bits;
pthread_mutex_lock(&si->mutex);
prev_bits = si->pending_bits;
si->pending_bits |= bits;
if (!prev_bits)
pthread_cond_signal(&si->cond);
pthread_mutex_unlock(&si->mutex);
return EC_SUCCESS;
}
/*****************************************************************************/
/* Timers */
typedef struct EcTimerInternal {
pthread_t thread;
pthread_cond_t cond;
pthread_mutex_t mutex;
int interval_usec;
int flags;
void (*timer_func)(void *);
void* param;
} EcTimerInternal;
/* Timer flags */
/* Timer is periodic; if not present, timer is one-shot. */
#define EC_TIMER_FLAG_PERIODIC 0x01
#define EC_TIMER_FLAG_STARTED 0x02
/* Timer wrapper. Loops and calls timer function. */
static void* EcTimerWrapper(void* param) {
EcTimerInternal* ti = (EcTimerInternal*)param;
WaitForOsStart();
while (1) {
/* Wait for timer to be enabled */
pthread_mutex_lock(&ti->mutex);
if (!(ti->flags & EC_TIMER_FLAG_STARTED))
pthread_cond_wait(&ti->cond, &ti->mutex);
pthread_mutex_unlock(&ti->mutex);
/* TODO: should really sleep for interval, less the time used by
* the previous call. Or we could use a second thread to
* pthread_cond_signal() and then immediately go back to sleep. */
usleep(ti->interval_usec);
/* Only call the timer func if the flag is still started */
if (ti->flags & EC_TIMER_FLAG_STARTED)
ti->timer_func(ti->param);
if (!(ti->flags & EC_TIMER_FLAG_PERIODIC))
break; /* One-shot timer */
}
return NULL;
}
/* Creates a timer which will call timer_func(param) after the
* specified interval. See EC_TIMER_FLAG_* for valid flags. Fills
* <timer>. */
EcError EcTimerCreate(EcTimer* timer, int interval_usec, int priority,
uint32_t flags, void (*timer_func)(void*), void* param) {
EcTimerInternal* ti = (EcTimerInternal*)timer;
/* TODO: priority */
/* Init internal data */
ti->interval_usec = interval_usec;
ti->flags = flags;
ti->timer_func = timer_func;
ti->param = param;
/* Create thread to call timer func */
if (pthread_mutex_init(&ti->mutex, NULL) != 0)
return EC_ERROR_UNKNOWN;
if (pthread_cond_init(&ti->cond, NULL) != 0)
return EC_ERROR_UNKNOWN;
if (pthread_create(&ti->thread, NULL, EcTimerWrapper, ti) != 0)
return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
/* Stops a timer. */
EcError EcTimerStop(EcTimer* timer) {
EcTimerInternal* ti = (EcTimerInternal*)timer;
pthread_mutex_lock(&ti->mutex);
ti->flags &= ~EC_TIMER_FLAG_STARTED;
pthread_mutex_unlock(&ti->mutex);
return EC_SUCCESS;
}
/* Starts a timer. */
EcError EcTimerStart(EcTimer* timer) {
EcTimerInternal* ti = (EcTimerInternal*)timer;
pthread_mutex_lock(&ti->mutex);
ti->flags |= EC_TIMER_FLAG_STARTED;
pthread_cond_signal(&ti->cond);
pthread_mutex_unlock(&ti->mutex);
return EC_SUCCESS;
}
/*****************************************************************************/
/* Semaphores */
typedef struct EcSemaphoreInternal {
sem_t sem;
} EcSemaphoreInternal;
EcError EcSemaphoreCreate(EcSemaphore* semaphore, int initial_count) {
EcSemaphoreInternal* si = (EcSemaphoreInternal*)semaphore;
if (sem_init(&si->sem, 0, initial_count) != 0)
return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
EcError EcSemaphorePost(EcSemaphore* semaphore) {
EcSemaphoreInternal* si = (EcSemaphoreInternal*)semaphore;
if (sem_post(&si->sem) != 0)
return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
EcError EcSemaphoreWait(EcSemaphore* semaphore, int timeout_usec) {
EcSemaphoreInternal* si = (EcSemaphoreInternal*)semaphore;
int rv;
if (timeout_usec == 0) {
rv = sem_trywait(&si->sem);
} else if (timeout_usec == EC_OS_FOREVER) {
rv = sem_wait(&si->sem);
if (errno == EAGAIN)
return EC_ERROR_TIMEOUT;
} else {
struct timespec ts;
UsecToTimespec(timeout_usec, &ts);
rv = sem_timedwait(&si->sem, &ts);
if (errno == ETIMEDOUT)
return EC_ERROR_TIMEOUT;
}
return (rv == 0 ? EC_SUCCESS : EC_ERROR_UNKNOWN);
}
EcError EcSemaphoreGetCount(EcSemaphore* semaphore, int* count_ptr) {
EcSemaphoreInternal* si = (EcSemaphoreInternal*)semaphore;
if (sem_getvalue(&si->sem, count_ptr) != 0)
return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
/*****************************************************************************/
/* Events */
typedef struct EcEventInternal {
pthread_mutex_t mutex;
pthread_cond_t cond;
uint32_t bits_set;
uint32_t bits_or;
uint32_t bits_and;
} EcEventInternal;
EcError EcEventCreate(EcEvent* event, uint32_t initial_bits) {
EcEventInternal* ei = (EcEventInternal*)event;
/* Init internal data */
ei->bits_set = initial_bits;
ei->bits_or = ei->bits_and = 0;
if (pthread_mutex_init(&ei->mutex, NULL) != 0)
return EC_ERROR_UNKNOWN;
if (pthread_cond_init(&ei->cond, NULL) != 0)
return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
/* Turns on the specified bits in the event. */
EcError EcEventPost(EcEvent* event, uint32_t bits) {
EcEventInternal* ei = (EcEventInternal*)event;
pthread_mutex_lock(&ei->mutex);
ei->bits_set |= bits;
/* See if that's enough bits to release the thread waiting on us */
if (ei->bits_or & ei->bits_set) {
ei->bits_or = 0;
pthread_cond_signal(&ei->cond);
} else if (ei->bits_and && (ei->bits_and & ei->bits_set) == ei->bits_and) {
ei->bits_and = 0;
pthread_cond_signal(&ei->cond);
}
pthread_mutex_unlock(&ei->mutex);
return EC_SUCCESS;
}
EcError EcEventWaitAll(EcEvent* event, uint32_t bits, int timeout_usec) {
EcEventInternal* ei = (EcEventInternal*)event;
int rv;
pthread_mutex_lock(&ei->mutex);
/* Only wait if we don't have the bits we need */
if ((ei->bits_set & bits) != bits) {
ei->bits_and = bits;
if (timeout_usec == EC_OS_FOREVER) {
rv = pthread_cond_wait(&ei->cond, &ei->mutex);
} else {
struct timespec ts;
UsecToTimespec(timeout_usec, &ts);
rv = pthread_cond_timedwait(&ei->cond, &ei->mutex, &ts);
}
}
/* If we succeeded, consume all the bits we waited for */
if (!rv)
ei->bits_set &= ~bits;
pthread_mutex_unlock(&ei->mutex);
if (rv == ETIMEDOUT)
return EC_ERROR_TIMEOUT;
else
return (rv == 0 ? EC_SUCCESS : EC_ERROR_UNKNOWN);
}
EcError EcEventWaitAny(EcEvent* event, uint32_t bits, uint32_t* got_bits_ptr,
int timeout_usec) {
EcEventInternal* ei = (EcEventInternal*)event;
int rv;
pthread_mutex_lock(&ei->mutex);
/* Only wait if we don't have the bits we need */
if (!(ei->bits_set & bits)) {
ei->bits_or = bits;
if (timeout_usec == EC_OS_FOREVER) {
rv = pthread_cond_wait(&ei->cond, &ei->mutex);
} else {
struct timespec ts;
UsecToTimespec(timeout_usec, &ts);
rv = pthread_cond_timedwait(&ei->cond, &ei->mutex, &ts);
}
}
/* If we succeeded, consume all the bits we waited for */
if (!rv) {
if (got_bits_ptr)
*got_bits_ptr = ei->bits_set & bits;
ei->bits_set &= ~bits;
}
pthread_mutex_unlock(&ei->mutex);
if (rv == ETIMEDOUT)
return EC_ERROR_TIMEOUT;
else
return (rv == 0 ? EC_SUCCESS : EC_ERROR_UNKNOWN);
}
/*****************************************************************************/
/* Other functions */
void EcOsInit(void) {
/* Make sure struct sizes are correct */
//printf("%ld", sizeof(EcTimerInternal));
assert(EC_TASK_STRUCT_SIZE == sizeof(EcTaskInternal));
assert(EC_SWI_STRUCT_SIZE == sizeof(EcSwiInternal));
assert(EC_TIMER_STRUCT_SIZE == sizeof(EcTimerInternal));
assert(EC_SEMAPHORE_STRUCT_SIZE == sizeof(EcSemaphoreInternal));
assert(EC_EVENT_STRUCT_SIZE == sizeof(EcEventInternal));
}
void EcOsStart(void) {
EcTaskInternal* ti;
/* Kick off threads */
pthread_mutex_lock(&os_start_mutex);
os_has_started = 1;
pthread_cond_broadcast(&os_start_cond);
pthread_mutex_unlock(&os_start_mutex);
/* Wait for all task threads to run */
while (1) {
EcTaskInternal* ti_wait;
/* Find the next task */
pthread_mutex_lock(&task_list_mutex);
ti_wait = task_list;
pthread_mutex_unlock(&task_list_mutex);
if (!ti_wait)
break; /* No tasks left */
/* Wait for it to die */
pthread_join(ti_wait->thread, NULL);
/* Remove the dead thread from the list */
pthread_mutex_lock(&task_list_mutex);
if (task_list == ti_wait)
task_list = ti_wait->next;
else {
for (ti = task_list; ti->next == ti_wait; ti = ti->next);
if (ti)
ti->next = ti_wait->next;
}
pthread_mutex_unlock(&task_list_mutex);
}
/* The remaining tasks for SWIs, etc, will die when the process exits */
}

View File

@@ -0,0 +1,93 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Operating system object types for EC. These are
* implementation-dependent; this file should come from the
* implementation include directory. */
#ifndef __CROS_EC_OS_TYPES_H
#define __CROS_EC_OS_TYPES_H
#include "ec_common.h"
/* Structure sizes depend on the underlying implementation. These
* sizes are correct for the pthreads implementation. */
#define EC_TASK_STRUCT_SIZE 32
#define EC_SWI_STRUCT_SIZE 120
#define EC_TIMER_STRUCT_SIZE 120
#define EC_SEMAPHORE_STRUCT_SIZE 32
#define EC_EVENT_STRUCT_SIZE 104
/*****************************************************************************/
/* Tasks */
/* Task priority range */
#define EC_TASK_PRIORITY_LOWEST 0
#define EC_TASK_PRIORITY_DEFAULT 3
#define EC_TASK_PRIORITY_HIGHEST 7
/* Task instance. Treat this as an opaque identifier. */
typedef struct EcTask {
union {
uint64_t align; /* Align on something big */
uint8_t data[EC_TASK_STRUCT_SIZE];
};
} EcTask;
/*****************************************************************************/
/* Software interrupts (SWI) */
/* SWI priority range */
#define EC_SWI_PRIORITY_LOWEST 0
#define EC_SWI_PRIORITY_DEFAULT 3
#define EC_SWI_PRIORITY_HIGHEST 7
/* SWI instance. Treat this as an opaque identifier. */
typedef struct EcSwi {
union {
uint64_t align; /* Align on something big */
uint8_t data[EC_SWI_STRUCT_SIZE];
};
} EcSwi;
/*****************************************************************************/
/* Timers */
/* Timer priority range */
#define EC_TIMER_PRIORITY_LOWEST 0
#define EC_TIMER_PRIORITY_DEFAULT 3
#define EC_TIMER_PRIORITY_HIGHEST 7
/* Timer instance. Treat this as an opaque identifier. */
typedef struct EcTimer {
union {
uint64_t align; /* Align on something big */
uint8_t data[EC_TIMER_STRUCT_SIZE];
};
} EcTimer;
/*****************************************************************************/
/* Semaphores */
/* Semaphore instance. Treat this as an opaque identifier. */
typedef struct EcSemaphore {
union {
uint64_t align; /* Align on something big */
uint8_t data[EC_SEMAPHORE_STRUCT_SIZE];
};
} EcSemaphore;
/*****************************************************************************/
/* Events */
/* Event instance. Treat this as an opaque identifier. */
typedef struct EcEvent {
union {
uint64_t align; /* Align on something big */
uint8_t data[EC_EVENT_STRUCT_SIZE];
};
} EcEvent;
#endif

View File

@@ -25,6 +25,8 @@ enum EcErrorList {
EC_ERROR_UNIMPLEMENTED = 2,
/* Overflow error; too much input provided. */
EC_ERROR_OVERFLOW = 3,
/* Timeout */
EC_ERROR_TIMEOUT = 4,
/* Module-internal error codes may use this range. */
EC_ERROR_INTERNAL_FIRST = 0x10000,

119
cros_ec/include/ec_os.h Normal file
View File

@@ -0,0 +1,119 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Operating system objects for EC */
#ifndef __CROS_EC_OS_H
#define __CROS_EC_OS_H
#include "ec_common.h"
#include "ec_os_types.h"
/* Timeout value which means "wait forever". */
#define EC_OS_FOREVER -1
/*****************************************************************************/
/* Tasks */
/* Creates a task of the specified priority and stack size. If
* stack_size=0, uses the default stack size. The task will call
* task_func(param). Fills <task>. */
EcError EcTaskCreate(EcTask* task, int priority, int stack_size,
void (*task_func)(void*), void* param);
/* Sleep for the specified number of microseconds. */
void EcTaskSleep(int usec);
/* Exits the current task. */
void EcTaskExit(void);
/*****************************************************************************/
/* Software interrupts (SWI) */
/* Creates a SWI of the specified priority. When the SWI is
* triggered, it will call swi_func(param, bits), where <bits> is the
* accumulated bits value from all preceding calls to EcSwiPost().
* Fills <swi>. */
EcError EcSwiCreate(EcSwi* swi, int priority,
void (*swi_func)(void*, uint32_t), void* param);
/* Sets the specified bits in the SWI. */
EcError EcSwiPost(EcSwi* swi, uint32_t bits);
/*****************************************************************************/
/* Timers */
/* Timer flags */
/* Timer is periodic; if not present, timer is one-shot. */
#define EC_TIMER_FLAG_PERIODIC 0x01
#define EC_TIMER_FLAG_STARTED 0x02
/* Creates a timer which will call timer_func(param) after the
* specified interval. See EC_TIMER_FLAG_* for valid flags. Fills
* <timer>. */
EcError EcTimerCreate(EcTimer* timer, int interval_usec, int priority,
uint32_t flags, void (*timer_func)(void*), void* param);
/* Stops a timer. */
EcError EcTimerStop(EcTimer* timer);
/* Starts a timer. */
EcError EcTimerStart(EcTimer* timer);
/*****************************************************************************/
/* Semaphores */
/* Creates a semaphore with the specified initial count. Fills <semaphore>. */
EcError EcSemaphoreCreate(EcSemaphore* semaphore, int initial_count);
/* Posts the semaphore, incrementing its count by one. If count>0,
* this will allow the next task pending on the semaphore to run. */
EcError EcSemaphorePost(EcSemaphore* semaphore);
/* Waits up to <timeout_usec> microseconds (or forever, if
* timeout_usec==EC_OS_FOREVER) for the semaphore. If it's unable to
* acquire the semaphore before the timeout, returns
* EC_ERROR_TIMEOUT. */
EcError EcSemaphoreWait(EcSemaphore* semaphore, int timeout_usec);
/* Stores the current semaphore count into <count_ptr>. */
EcError EcSemaphoreGetCount(EcSemaphore* semaphore, int* count_ptr);
/*****************************************************************************/
/* Events
*
* To be compatible with all platforms, only one task at a time may
* wait on an event. */
/* Creates an event with the specified initial bits. Fills <event>. */
EcError EcEventCreate(EcEvent* event, uint32_t initial_bits);
/* Turns on the specified bits in the event. */
EcError EcEventPost(EcEvent* event, uint32_t bits);
/* Waits up to <timeout_usec> microseconds (or forever, if
* timeout_usec==EC_OS_FOREVER) for all of the requested bits to be
* set in the event. Returns EC_ERROR_TIMEOUT on timeout. */
EcError EcEventWaitAll(EcEvent* event, uint32_t bits, int timeout_usec);
/* Waits up to <timeout_usec> microseconds (or forever, if
* timeout_usec==EC_OS_FOREVER) for any of the requested bits to be
* set in the event. If got_bits_ptr!=NULL, sets it to the bits which
* were posted, and clears those bits. Returns EC_ERROR_TIMEOUT on timeout. */
EcError EcEventWaitAny(EcEvent* event, uint32_t bits, uint32_t* got_bits_ptr,
int timeout_usec);
/*****************************************************************************/
/* Other OS functions */
/* Initializes the OS. Must be called before any of the functions above. */
void EcOsInit(void);
/* Starts OS task management. Returns when all threads have exited.
* This function should be called by main(). */
void EcOsStart(void);
#endif

129
cros_ec/test/ec_os_test.c Normal file
View File

@@ -0,0 +1,129 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Basic test for EcOs objects */
#include <stdio.h>
#include <stdint.h>
#include "ec_os.h"
EcTask t1, t2, t3, t4;
EcSemaphore sem;
EcSwi swi;
EcTimer timer1, timer2;
EcEvent ev1, ev2;
void Thread1(void* arg) {
int i;
for (i = 0; i < 5; i++) {
EcSemaphoreWait(&sem, EC_OS_FOREVER);
/* Do some work */
EcTaskSleep(5000);
fprintf(stderr, "Hello from thread1: %s\n", (char*)arg);
EcSemaphorePost(&sem);
/* Two rapid posts to SWI, to see that they merge */
EcSwiPost(&swi, 1 << i);
EcSwiPost(&swi, 0x100 << i);
EcTaskSleep(100);
}
EcTaskSleep(500000);
fprintf(stderr, "Goodbye from thread1\n");
}
void Thread2(void* arg) {
int i;
for (i = 0; i < 5; i++) {
EcSemaphoreWait(&sem, EC_OS_FOREVER);
/* Do some work */
EcTaskSleep(5000);
fprintf(stderr, "Hello from thread2: %s\n", (char*)arg);
EcSemaphorePost(&sem);
/* Post events */
EcEventPost(&ev1, 1 << i);
EcEventPost(&ev2, 1 << i);
EcTaskSleep(100);
}
EcTaskSleep(50000);
fprintf(stderr, "Goodbye from thread2\n");
}
void Thread3(void* arg) {
uint32_t got_bits = 0;
while(got_bits != 0x10) {
/* Wait for any of the bits to be set */
EcEventWaitAny(&ev1, 0x1c, &got_bits, EC_OS_FOREVER);
fprintf(stderr, "Event thread 3 got bits: 0x%x\n", got_bits);
}
fprintf(stderr, "Goodbye from event thread 3\n");
}
void Thread4(void* arg) {
/* Wait on event bit from creation and a few posted bits. */
EcEventWaitAll(&ev2, 0x10e, EC_OS_FOREVER);
fprintf(stderr, "Event thread 4 got all bits\n");
fprintf(stderr, "Goodbye from event thread 4\n");
}
void SwiFunc(void* arg, uint32_t bits) {
fprintf(stderr, "Hello from SWI with bits=0x%x\n", bits);
}
void TimerFunc(void* arg) {
fprintf(stderr, "Hello from timer: %s\n", (char*)arg);
/* Start the one-shot timer. */
EcTimerStart(&timer2);
}
void OneTimerFunc(void* arg) {
fprintf(stderr, "Hello from one-shot timer: %s\n", (char*)arg);
/* Stop the periodic timer */
EcTimerStop(&timer1);
}
int main(void) {
fprintf(stderr, "Hello, world.\n");
EcOsInit();
EcTaskCreate(&t1, EC_TASK_PRIORITY_DEFAULT, 0, Thread1, "Foo1");
EcTaskCreate(&t2, EC_TASK_PRIORITY_DEFAULT, 0, Thread2, "Foo2");
EcTaskCreate(&t3, EC_TASK_PRIORITY_DEFAULT, 0, Thread3, "EventTask1");
EcTaskCreate(&t4, EC_TASK_PRIORITY_DEFAULT, 0, Thread4, "EventTask2");
EcSwiCreate(&swi, EC_SWI_PRIORITY_DEFAULT, SwiFunc, "Swi1");
EcTimerCreate(&timer1, 100000, EC_TIMER_PRIORITY_DEFAULT,
EC_TIMER_FLAG_STARTED|EC_TIMER_FLAG_PERIODIC,
TimerFunc, "Timer1");
EcTimerCreate(&timer2, 150000, EC_TIMER_PRIORITY_DEFAULT,
0, OneTimerFunc, "Timer2");
EcSemaphoreCreate(&sem, 1);
EcEventCreate(&ev1, 0);
EcEventCreate(&ev2, 0x100);
fprintf(stderr, "EcOs objects created.\n");
EcOsStart();
return 0;
}