Use anonymous structs instead of void for public kernel API.
This commit is contained in:
parent
b8f4d5cd53
commit
ef79b4343d
|
@ -33,7 +33,7 @@
|
|||
|
||||
|
||||
|
||||
void LGYFB_init(const KEvent frameReadyEvent);
|
||||
void LGYFB_init(KEvent *frameReadyEvent);
|
||||
void LGYFB_deinit(void);
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
#include "kernel.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 r4;
|
||||
|
@ -37,11 +42,6 @@ typedef struct
|
|||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
KRes switchContext(KRes res, void *oldSp, uintptr_t newSp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -18,7 +18,7 @@ typedef enum
|
|||
TASK_STATE_RUNNING_SHORT = 3 // Continue task as soon as the woken ones are finished.
|
||||
} TaskState;
|
||||
|
||||
typedef struct
|
||||
struct TaskCb
|
||||
{
|
||||
ListNode node;
|
||||
u8 core; // TODO: Multicore
|
||||
|
@ -29,7 +29,8 @@ typedef struct
|
|||
void *stack;
|
||||
// Name?
|
||||
// Exit code?
|
||||
} TaskCb; // Task context
|
||||
}; // Task context
|
||||
typedef struct TaskCb TaskCb;
|
||||
static_assert(offsetof(TaskCb, node) == 0, "Error: Member node of TaskCb is not at offset 0!");
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
#include <stdint.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
KRES_OK = 0, // No error.
|
||||
|
@ -33,18 +38,13 @@ enum
|
|||
};
|
||||
|
||||
typedef uintptr_t KRes; // See createTask()
|
||||
typedef void* KTask;
|
||||
typedef struct TaskCb KTask;
|
||||
typedef void (*TaskFunc)(void*);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Init the kernel. Only call this once.
|
||||
* @brief Initializes the kernel. Only call this once.
|
||||
*
|
||||
* @param[in] priority The priority of the main task.
|
||||
*/
|
||||
|
@ -61,7 +61,7 @@ void kernelInit(uint8_t priority);
|
|||
*
|
||||
* @return Returns a KTask handle.
|
||||
*/
|
||||
KTask createTask(size_t stackSize, uint8_t priority, TaskFunc entry, void *taskArg);
|
||||
KTask* createTask(size_t stackSize, uint8_t priority, TaskFunc entry, void *taskArg);
|
||||
|
||||
/**
|
||||
* @brief Switches to the next task. Use with care.
|
||||
|
|
|
@ -22,65 +22,65 @@
|
|||
#include "kernel.h"
|
||||
|
||||
|
||||
typedef void* KEvent;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct KEvent KEvent;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new KEvent.
|
||||
*
|
||||
* @param[in] oneShot Event fires only once and auto clears if true.
|
||||
*
|
||||
* @return The KEvent handle or NULL when out of memory.
|
||||
* @return The KEvent pointer or NULL when out of memory.
|
||||
*/
|
||||
KEvent createEvent(bool oneShot);
|
||||
KEvent* createEvent(bool oneShot);
|
||||
|
||||
/**
|
||||
* @brief Deletes a KEvent handle.
|
||||
* @brief Deletes a KEvent.
|
||||
*
|
||||
* @param[in] kevent The KEvent handle.
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
*/
|
||||
void deleteEvent(const KEvent kevent);
|
||||
void deleteEvent(KEvent *const kevent);
|
||||
|
||||
/**
|
||||
* @brief Binds the given KEvent to an interrupt.
|
||||
*
|
||||
* @param[in] kevent The KEvent handle.
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
* @param[in] id The interrupt id.
|
||||
* @param[in] prio The interrupt priority.
|
||||
*/
|
||||
void bindInterruptToEvent(const KEvent kevent, uint8_t id, uint8_t prio);
|
||||
void bindInterruptToEvent(KEvent *const kevent, uint8_t id, uint8_t prio);
|
||||
|
||||
void unbindInterruptEvent(uint8_t id);
|
||||
|
||||
/**
|
||||
* @brief Waits for the given KEvent to be signaled.
|
||||
*
|
||||
* @param[in] kevent The KEvent handle.
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
*
|
||||
* @return Returns the result. See Kres above.
|
||||
*/
|
||||
KRes waitForEvent(const KEvent kevent);
|
||||
KRes waitForEvent(KEvent *const kevent);
|
||||
|
||||
/**
|
||||
* @brief Signals a KEvent.
|
||||
*
|
||||
* @param[in] kevent The KEvent handle.
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
* @param[in] reschedule Set to true to immediately reschedule.
|
||||
*/
|
||||
void signalEvent(const KEvent kevent, bool reschedule);
|
||||
void signalEvent(KEvent *const kevent, bool reschedule);
|
||||
|
||||
/**
|
||||
* @brief Clears a KEvent.
|
||||
*
|
||||
* @param[in] kevent The KEvent handle.
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
*/
|
||||
void clearEvent(const KEvent kevent);
|
||||
void clearEvent(KEvent *const kevent);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -21,47 +21,47 @@
|
|||
#include "kernel.h"
|
||||
|
||||
|
||||
typedef void* KMutex; // TODO: Implement this using semaphores?
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Creates a mutex.
|
||||
*
|
||||
* @return The KMutex handle or NULL when out of memory.
|
||||
*/
|
||||
KMutex createMutex(void);
|
||||
typedef struct KMutex KMutex; // TODO: Implement this using semaphores?
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes a KMutex handle.
|
||||
* @brief Creates a new KMutex.
|
||||
*
|
||||
* @param[in] kmutex The KMutex handle.
|
||||
* @return The KMutex pointer or NULL when out of memory.
|
||||
*/
|
||||
void deleteMutex(const KMutex kmutex);
|
||||
KMutex* createMutex(void);
|
||||
|
||||
/**
|
||||
* @brief Deletes a KMutex.
|
||||
*
|
||||
* @param[in] kmutex The KMutex pointer.
|
||||
*/
|
||||
void deleteMutex(KMutex *const kmutex);
|
||||
|
||||
/**
|
||||
* @brief Locks a KMutex.
|
||||
*
|
||||
* @param[in] kmutex The KMutex handle.
|
||||
* @param[in] kmutex The KMutex pointer.
|
||||
*
|
||||
* @return Returns the result. See Kres.
|
||||
*/
|
||||
KRes lockMutex(const KMutex kmutex);
|
||||
KRes lockMutex(KMutex *const kmutex);
|
||||
|
||||
/**
|
||||
* @brief Unlocks a KMutex.
|
||||
*
|
||||
* @param[in] kmutex The KMutex handle.
|
||||
* @param[in] kmutex The KMutex pointer.
|
||||
*
|
||||
* @return Returns KRES_NO_PERMISSIONS if the current task
|
||||
* @return is not the locker. Otherwise KRES_OK.
|
||||
* @return is not the owner. Otherwise KRES_OK.
|
||||
*/
|
||||
KRes unlockMutex(const KMutex kmutex);
|
||||
KRes unlockMutex(KMutex *const kmutex);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -23,57 +23,57 @@
|
|||
#include "kernel.h"
|
||||
|
||||
|
||||
typedef void* KSema;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct KSema KSema;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a KSema handle.
|
||||
* @brief Creates a new KSema.
|
||||
*
|
||||
* @param[in] count The initial count of the semaphore.
|
||||
*
|
||||
* @return The KSema handle or NULL when out of memory.
|
||||
* @return The KSema pointer or NULL when out of memory.
|
||||
*/
|
||||
KSema createSemaphore(int32_t count);
|
||||
KSema* createSemaphore(int32_t count);
|
||||
|
||||
/**
|
||||
* @brief Deletes a KSema handle.
|
||||
* @brief Deletes a KSema.
|
||||
*
|
||||
* @param[in] ksema The KSema handle.
|
||||
*/
|
||||
void deleteSemaphore(const KSema ksema);
|
||||
void deleteSemaphore(KSema *const ksema);
|
||||
|
||||
/**
|
||||
* @brief Polls a KSema.
|
||||
*
|
||||
* @param[in] ksema The KSema handle.
|
||||
* @param[in] ksema The KSema pointer.
|
||||
*
|
||||
* @return Returns KRES_OK or KRES_WOULD_BLOCK.
|
||||
*/
|
||||
KRes pollSemaphore(const KSema ksema);
|
||||
KRes pollSemaphore(KSema *const ksema);
|
||||
|
||||
/**
|
||||
* @brief Decreases the semaphore and blocks if <=0.
|
||||
*
|
||||
* @param[in] ksema The KSema handle.
|
||||
* @param[in] ksema The KSema pointer.
|
||||
*
|
||||
* @return Returns the result. See Kres above.
|
||||
*/
|
||||
KRes waitForSemaphore(const KSema ksema);
|
||||
KRes waitForSemaphore(KSema *const ksema);
|
||||
|
||||
/**
|
||||
* @brief Increases the semaphore and wakes up signalCount waiting tasks if any.
|
||||
*
|
||||
* @param[in] ksema The KSema handle.
|
||||
* @param[in] ksema The KSema pointer.
|
||||
* @param[in] signalCount The number to increase the semaphore by.
|
||||
* @param[in] reschedule Set to true to immediately reschedule.
|
||||
*/
|
||||
void signalSemaphore(const KSema ksema, uint32_t signalCount, bool reschedule);
|
||||
void signalSemaphore(KSema *const ksema, uint32_t signalCount, bool reschedule);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -21,24 +21,24 @@
|
|||
#include "kernel.h"
|
||||
|
||||
|
||||
typedef void* KTimer;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
KTimer createTimer(bool pulse);
|
||||
typedef struct KTimer KTimer;
|
||||
|
||||
void deleteTimer(const KTimer ktimer);
|
||||
|
||||
void startTimer(const KTimer ktimer, uint32_t usec);
|
||||
|
||||
void stopTimer(const KTimer ktimer);
|
||||
KTimer* createTimer(bool pulse);
|
||||
|
||||
KRes waitForTimer(const KTimer ktimer);
|
||||
void deleteTimer(KTimer *const ktimer);
|
||||
|
||||
void startTimer(KTimer *const ktimer, uint32_t usec);
|
||||
|
||||
void stopTimer(KTimer *const ktimer);
|
||||
|
||||
KRes waitForTimer(KTimer *const ktimer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <stdnoreturn.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "kernel.h"
|
||||
#include "internal/config.h"
|
||||
#include "internal/kernel_private.h"
|
||||
#include "internal/kmemcpy_set.h"
|
||||
|
@ -9,7 +10,6 @@
|
|||
#include "internal/util.h"
|
||||
#include "internal/list.h"
|
||||
#include "internal/contextswitch.h"
|
||||
#include "kernel.h"
|
||||
#include "arm.h"
|
||||
|
||||
|
||||
|
@ -75,7 +75,7 @@ void kernelInit(uint8_t priority)
|
|||
g_numTasks = 2;
|
||||
}
|
||||
|
||||
KTask createTask(size_t stackSize, uint8_t priority, TaskFunc entry, void *taskArg)
|
||||
KTask* createTask(size_t stackSize, uint8_t priority, TaskFunc entry, void *taskArg)
|
||||
{
|
||||
if(priority > MAX_PRIO_BITS - 1u) return NULL;
|
||||
|
||||
|
|
|
@ -9,22 +9,22 @@
|
|||
#include "internal/config.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
struct KEvent
|
||||
{
|
||||
bool signaled;
|
||||
const bool oneShot;
|
||||
ListNode waitQueue;
|
||||
} Event;
|
||||
};
|
||||
|
||||
|
||||
static SlabHeap g_eventSlab = {0};
|
||||
static KEvent g_irqEventTable[128 - 32] = {0}; // 128 - 32 private interrupts.
|
||||
static KEvent *g_irqEventTable[128 - 32] = {0}; // 128 - 32 private interrupts.
|
||||
|
||||
|
||||
|
||||
void _eventSlabInit(void)
|
||||
{
|
||||
slabInit(&g_eventSlab, sizeof(Event), MAX_EVENTS);
|
||||
slabInit(&g_eventSlab, sizeof(KEvent), MAX_EVENTS);
|
||||
}
|
||||
|
||||
static void eventIrqHandler(u32 intSource)
|
||||
|
@ -32,29 +32,27 @@ static void eventIrqHandler(u32 intSource)
|
|||
signalEvent(g_irqEventTable[intSource - 32], false);
|
||||
}
|
||||
|
||||
KEvent createEvent(bool oneShot)
|
||||
KEvent* createEvent(bool oneShot)
|
||||
{
|
||||
Event *const event = (Event*)slabAlloc(&g_eventSlab);
|
||||
KEvent *const kevent = (KEvent*)slabAlloc(&g_eventSlab);
|
||||
|
||||
event->signaled = false;
|
||||
*(bool*)&event->oneShot = oneShot;
|
||||
listInit(&event->waitQueue);
|
||||
kevent->signaled = false;
|
||||
*(bool*)&kevent->oneShot = oneShot;
|
||||
listInit(&kevent->waitQueue);
|
||||
|
||||
return event;
|
||||
return kevent;
|
||||
}
|
||||
|
||||
void deleteEvent(const KEvent kevent)
|
||||
void deleteEvent(KEvent *const kevent)
|
||||
{
|
||||
Event *const event = (Event*)kevent;
|
||||
|
||||
kernelLock();
|
||||
waitQueueWakeN(&event->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
waitQueueWakeN(&kevent->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
|
||||
slabFree(&g_eventSlab, event);
|
||||
slabFree(&g_eventSlab, kevent);
|
||||
}
|
||||
|
||||
// TODO: Critical sections needed for bin/unbind?
|
||||
void bindInterruptToEvent(const KEvent kevent, uint8_t id, uint8_t prio)
|
||||
// TODO: Critical sections needed for bind/unbind?
|
||||
void bindInterruptToEvent(KEvent *const kevent, uint8_t id, uint8_t prio)
|
||||
{
|
||||
if(id < 32 || id > 127) return;
|
||||
|
||||
|
@ -71,49 +69,44 @@ void unbindInterruptEvent(uint8_t id)
|
|||
}
|
||||
|
||||
// TODO: Timeout.
|
||||
KRes waitForEvent(const KEvent kevent)
|
||||
KRes waitForEvent(KEvent *const kevent)
|
||||
{
|
||||
Event *const event = (Event*)kevent;
|
||||
KRes res;
|
||||
|
||||
kernelLock();
|
||||
if(event->signaled)
|
||||
if(kevent->signaled)
|
||||
{
|
||||
if(event->oneShot) event->signaled = false;
|
||||
if(kevent->oneShot) kevent->signaled = false;
|
||||
kernelUnlock();
|
||||
res = KRES_OK;
|
||||
}
|
||||
else res = waitQueueBlock(&event->waitQueue);
|
||||
else res = waitQueueBlock(&kevent->waitQueue);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void signalEvent(const KEvent kevent, bool reschedule)
|
||||
void signalEvent(KEvent *const kevent, bool reschedule)
|
||||
{
|
||||
Event *const event = (Event*)kevent;
|
||||
|
||||
kernelLock();
|
||||
if(!event->signaled)
|
||||
if(!kevent->signaled)
|
||||
{
|
||||
if(event->oneShot)
|
||||
if(kevent->oneShot)
|
||||
{
|
||||
if(!waitQueueWakeN(&event->waitQueue, 1, KRES_OK, reschedule))
|
||||
event->signaled = true;
|
||||
if(!waitQueueWakeN(&kevent->waitQueue, 1, KRES_OK, reschedule))
|
||||
kevent->signaled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->signaled = true;
|
||||
waitQueueWakeN(&event->waitQueue, (u32)-1, KRES_OK, reschedule);
|
||||
kevent->signaled = true;
|
||||
waitQueueWakeN(&kevent->waitQueue, (u32)-1, KRES_OK, reschedule);
|
||||
}
|
||||
}
|
||||
else kernelUnlock();
|
||||
}
|
||||
|
||||
void clearEvent(const KEvent kevent)
|
||||
void clearEvent(KEvent *const kevent)
|
||||
{
|
||||
Event *const event = (Event*)kevent;
|
||||
|
||||
kernelLock(); // TODO: Can we do this without locks?
|
||||
event->signaled = false;
|
||||
kevent->signaled = false;
|
||||
kernelUnlock();
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
#include "internal/config.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
struct KMutex
|
||||
{
|
||||
const TaskCb *owner;
|
||||
ListNode waitQueue;
|
||||
} Mutex;
|
||||
};
|
||||
|
||||
|
||||
static SlabHeap g_mutexSlab = {0};
|
||||
|
@ -21,47 +21,43 @@ static SlabHeap g_mutexSlab = {0};
|
|||
|
||||
void _mutexSlabInit(void)
|
||||
{
|
||||
slabInit(&g_mutexSlab, sizeof(Mutex), MAX_MUTEXES);
|
||||
slabInit(&g_mutexSlab, sizeof(KMutex), MAX_MUTEXES);
|
||||
}
|
||||
|
||||
// TODO: Test mutex with multiple cores.
|
||||
KMutex createMutex(void)
|
||||
KMutex* createMutex(void)
|
||||
{
|
||||
Mutex *const mutex = (Mutex*)slabAlloc(&g_mutexSlab);
|
||||
KMutex *const kmutex = (KMutex*)slabAlloc(&g_mutexSlab);
|
||||
|
||||
mutex->owner = NULL;
|
||||
listInit(&mutex->waitQueue);
|
||||
kmutex->owner = NULL;
|
||||
listInit(&kmutex->waitQueue);
|
||||
|
||||
return mutex;
|
||||
return kmutex;
|
||||
}
|
||||
|
||||
void deleteMutex(const KMutex kmutex)
|
||||
void deleteMutex(KMutex *const kmutex)
|
||||
{
|
||||
Mutex *const mutex = (Mutex*)kmutex;
|
||||
|
||||
kernelLock();
|
||||
waitQueueWakeN(&mutex->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
waitQueueWakeN(&kmutex->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
|
||||
slabFree(&g_mutexSlab, mutex);
|
||||
slabFree(&g_mutexSlab, kmutex);
|
||||
}
|
||||
|
||||
KRes lockMutex(const KMutex kmutex)
|
||||
KRes lockMutex(KMutex *const kmutex)
|
||||
{
|
||||
KRes res;
|
||||
|
||||
do
|
||||
{
|
||||
Mutex *const mutex = (Mutex*)kmutex;
|
||||
|
||||
kernelLock();
|
||||
if(UNLIKELY(mutex->owner != NULL))
|
||||
if(UNLIKELY(kmutex->owner != NULL))
|
||||
{
|
||||
res = waitQueueBlock(&mutex->waitQueue);
|
||||
res = waitQueueBlock(&kmutex->waitQueue);
|
||||
if(UNLIKELY(res != KRES_OK)) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex->owner = getCurrentTask();
|
||||
kmutex->owner = getCurrentTask();
|
||||
kernelUnlock();
|
||||
res = KRES_OK;
|
||||
break;
|
||||
|
@ -72,18 +68,17 @@ KRes lockMutex(const KMutex kmutex)
|
|||
}
|
||||
|
||||
// TODO: Test if it works and only unlocks if current task == owner.
|
||||
KRes unlockMutex(const KMutex kmutex)
|
||||
KRes unlockMutex(KMutex *const kmutex)
|
||||
{
|
||||
Mutex *const mutex = (Mutex*)kmutex;
|
||||
KRes res = KRES_OK;
|
||||
|
||||
kernelLock();
|
||||
if(LIKELY(mutex->owner != NULL))
|
||||
if(LIKELY(kmutex->owner != NULL))
|
||||
{
|
||||
if(LIKELY(mutex->owner == getCurrentTask()))
|
||||
if(LIKELY(kmutex->owner == getCurrentTask()))
|
||||
{
|
||||
mutex->owner = NULL;
|
||||
waitQueueWakeN(&mutex->waitQueue, 1, KRES_OK, true);
|
||||
kmutex->owner = NULL;
|
||||
waitQueueWakeN(&kmutex->waitQueue, 1, KRES_OK, true);
|
||||
}
|
||||
else res = KRES_NO_PERMISSIONS;
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
#include "internal/config.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
struct KSema
|
||||
{
|
||||
s32 count;
|
||||
ListNode waitQueue;
|
||||
} Semaphore;
|
||||
};
|
||||
|
||||
|
||||
static SlabHeap g_semaSlab = {0};
|
||||
|
@ -22,63 +22,57 @@ static SlabHeap g_semaSlab = {0};
|
|||
|
||||
void _semaphoreSlabInit(void)
|
||||
{
|
||||
slabInit(&g_semaSlab, sizeof(Semaphore), MAX_SEMAPHORES);
|
||||
slabInit(&g_semaSlab, sizeof(KSema), MAX_SEMAPHORES);
|
||||
}
|
||||
|
||||
// TODO: Test semaphore with multiple cores.
|
||||
KSema createSemaphore(int32_t count)
|
||||
KSema* createSemaphore(int32_t count)
|
||||
{
|
||||
Semaphore *const sema = (Semaphore*)slabAlloc(&g_semaSlab);
|
||||
KSema *const ksema = (KSema*)slabAlloc(&g_semaSlab);
|
||||
|
||||
sema->count = count;
|
||||
listInit(&sema->waitQueue);
|
||||
ksema->count = count;
|
||||
listInit(&ksema->waitQueue);
|
||||
|
||||
return sema;
|
||||
return ksema;
|
||||
}
|
||||
|
||||
void deleteSemaphore(const KSema ksema)
|
||||
void deleteSemaphore(KSema *const ksema)
|
||||
{
|
||||
Semaphore *const sema = (Semaphore*)ksema;
|
||||
|
||||
kernelLock();
|
||||
waitQueueWakeN(&sema->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
waitQueueWakeN(&ksema->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
|
||||
slabFree(&g_semaSlab, sema);
|
||||
slabFree(&g_semaSlab, ksema);
|
||||
}
|
||||
|
||||
KRes pollSemaphore(const KSema ksema)
|
||||
KRes pollSemaphore(KSema *const ksema)
|
||||
{
|
||||
Semaphore *const sema = (Semaphore*)ksema;
|
||||
KRes res;
|
||||
|
||||
// TODO: Plain spinlocks instead?
|
||||
kernelLock();
|
||||
if(UNLIKELY(sema->count <= 0)) res = KRES_WOULD_BLOCK;
|
||||
else {sema->count--; res = KRES_OK;}
|
||||
if(UNLIKELY(ksema->count <= 0)) res = KRES_WOULD_BLOCK;
|
||||
else {ksema->count--; res = KRES_OK;}
|
||||
kernelUnlock();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
KRes waitForSemaphore(const KSema ksema)
|
||||
KRes waitForSemaphore(KSema *const ksema)
|
||||
{
|
||||
Semaphore *const sema = (Semaphore*)ksema;
|
||||
KRes res;
|
||||
|
||||
kernelLock();
|
||||
if(UNLIKELY(--sema->count < 0)) res = waitQueueBlock(&sema->waitQueue);
|
||||
if(UNLIKELY(--ksema->count < 0)) res = waitQueueBlock(&ksema->waitQueue);
|
||||
else {kernelUnlock(); res = KRES_OK;}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void signalSemaphore(const KSema ksema, uint32_t signalCount, bool reschedule)
|
||||
void signalSemaphore(KSema *const ksema, uint32_t signalCount, bool reschedule)
|
||||
{
|
||||
Semaphore *const sema = (Semaphore*)ksema;
|
||||
|
||||
kernelLock();
|
||||
//if(UNLIKELY(++sema->count <= 0))
|
||||
if(UNLIKELY((sema->count += signalCount) <= 0))
|
||||
waitQueueWakeN(&sema->waitQueue, signalCount, KRES_OK, reschedule);
|
||||
//if(UNLIKELY(++ksema->count <= 0))
|
||||
if(UNLIKELY((ksema->count += signalCount) <= 0))
|
||||
waitQueueWakeN(&ksema->waitQueue, signalCount, KRES_OK, reschedule);
|
||||
else kernelUnlock();
|
||||
}
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
//#include "arm11/fmt.h"
|
||||
|
||||
|
||||
/*typedef struct
|
||||
/*struct KTimer
|
||||
{
|
||||
ListNode node;
|
||||
u32 delta;
|
||||
u32 ticks;
|
||||
const bool pulse;
|
||||
ListNode waitQueue;
|
||||
} Timer;
|
||||
};
|
||||
|
||||
|
||||
static SlabHeap g_timerSlab = {0};
|
||||
|
@ -26,91 +26,85 @@ static ListNode g_deltaQueue = {0};
|
|||
|
||||
|
||||
|
||||
static void timerIrqHandler(UNUSED u32 intSource);
|
||||
static void addToDeltaQueue(Timer *const timer, u32 ticks);
|
||||
static void timerIsr(UNUSED u32 intSource);
|
||||
static void addToDeltaQueue(KTimer *const timer, u32 ticks);
|
||||
|
||||
void _timerInit(void)
|
||||
{
|
||||
slabInit(&g_timerSlab, sizeof(Timer), MAX_TIMERS);
|
||||
slabInit(&g_timerSlab, sizeof(KTimer), MAX_TIMERS);
|
||||
listInit(&g_deltaQueue);
|
||||
IRQ_registerHandler(IRQ_TIMER, 12, 0, true, timerIrqHandler);
|
||||
IRQ_registerIsr(IRQ_TIMER, 12, 0, timerIsr);
|
||||
}
|
||||
|
||||
KTimer createTimer(bool pulse)
|
||||
KTimer* createTimer(bool pulse)
|
||||
{
|
||||
Timer *const timer = (Timer*)slabAlloc(&g_timerSlab);
|
||||
KTimer *const ktimer = (KTimer*)slabAlloc(&g_timerSlab);
|
||||
|
||||
*(bool*)&timer->pulse = pulse;
|
||||
listInit(&timer->waitQueue);
|
||||
*(bool*)&ktimer->pulse = pulse;
|
||||
listInit(&ktimer->waitQueue);
|
||||
|
||||
return timer;
|
||||
return ktimer;
|
||||
}
|
||||
|
||||
void deleteTimer(const KTimer ktimer)
|
||||
void deleteTimer(KTimer *const ktimer)
|
||||
{
|
||||
Timer *const timer = (Timer*)ktimer;
|
||||
|
||||
kernelLock();
|
||||
waitQueueWakeN(&timer->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
waitQueueWakeN(&ktimer->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
|
||||
slabFree(&g_timerSlab, timer);
|
||||
slabFree(&g_timerSlab, ktimer);
|
||||
}
|
||||
|
||||
static void timerIrqHandler(UNUSED u32 intSource)
|
||||
static void timerIsr(UNUSED u32 intSource)
|
||||
{
|
||||
kernelLock();
|
||||
//if(listEmpty(&g_deltaQueue)) *((vu32*)4) = 4; // This should never happen
|
||||
Timer *timer = LIST_ENTRY(listPop(&g_deltaQueue), Timer, node);
|
||||
if(timer->pulse) addToDeltaQueue(timer, timer->ticks);
|
||||
KTimer *ktimer = LIST_ENTRY(listPop(&g_deltaQueue), KTimer, node);
|
||||
if(ktimer->pulse) addToDeltaQueue(ktimer, ktimer->ticks);
|
||||
if(!listEmpty(&g_deltaQueue))
|
||||
{
|
||||
// Don't use fp math in ISRs.
|
||||
TIMER_start(1, LIST_FIRST_ENTRY(&g_deltaQueue, Timer, node)->delta, false, true);
|
||||
TIMER_start(1, LIST_FIRST_ENTRY(&g_deltaQueue, KTimer, node)->delta, false, true);
|
||||
}
|
||||
waitQueueWakeN(&timer->waitQueue, (u32)-1, KRES_OK, false);
|
||||
waitQueueWakeN(&ktimer->waitQueue, (u32)-1, KRES_OK, false);
|
||||
}
|
||||
|
||||
static void addToDeltaQueue(Timer *const timer, u32 ticks)
|
||||
static void addToDeltaQueue(KTimer *const ktimer, u32 ticks)
|
||||
{
|
||||
Timer *pos;
|
||||
KTimer *pos;
|
||||
u32 deltaSum = 0;
|
||||
LIST_FOR_EACH_ENTRY(pos, &g_deltaQueue, node)
|
||||
{
|
||||
deltaSum += pos->delta;
|
||||
if(deltaSum > ticks)
|
||||
{
|
||||
timer->delta = ticks - (deltaSum - pos->delta);
|
||||
listAddBefore(&pos->node, &timer->node);
|
||||
ktimer->delta = ticks - (deltaSum - pos->delta);
|
||||
listAddBefore(&pos->node, &ktimer->node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
timer->delta = ticks;
|
||||
listPush(&g_deltaQueue, &timer->node);
|
||||
ktimer->delta = ticks;
|
||||
listPush(&g_deltaQueue, &ktimer->node);
|
||||
}
|
||||
|
||||
void startTimer(const KTimer ktimer, uint32_t usec)
|
||||
void startTimer(KTimer *const ktimer, uint32_t usec)
|
||||
{
|
||||
Timer *const timer = (Timer*)ktimer;
|
||||
|
||||
const u32 ticks = TIMER_FREQ(1, 1000000) * usec;
|
||||
timer->ticks = ticks;
|
||||
ktimer->ticks = ticks;
|
||||
|
||||
kernelLock();
|
||||
const bool firstTimer = listEmpty(&g_deltaQueue);
|
||||
addToDeltaQueue(timer, ticks);
|
||||
addToDeltaQueue(ktimer, ticks);
|
||||
kernelUnlock();
|
||||
if(firstTimer) TIMER_start(1, ticks, false, true);
|
||||
}
|
||||
|
||||
void stopTimer(const KTimer ktimer)
|
||||
void stopTimer(KTimer *const ktimer)
|
||||
{
|
||||
}
|
||||
|
||||
KRes waitForTimer(const KTimer ktimer)
|
||||
KRes waitForTimer(KTimer *const ktimer)
|
||||
{
|
||||
Timer *const timer = (Timer*)ktimer;
|
||||
|
||||
kernelLock();
|
||||
return waitQueueBlock(&timer->waitQueue);
|
||||
return waitQueueBlock(&ktimer->waitQueue);
|
||||
}*/
|
||||
|
|
|
@ -43,7 +43,7 @@ static struct
|
|||
{
|
||||
u8 lcdPower; // 1 = on. Bit 4 top light, bit 2 bottom light, bit 0 LCDs.
|
||||
u8 lcdLights[2]; // LCD backlight brightness. Top, bottom.
|
||||
KEvent events[6];
|
||||
KEvent *events[6];
|
||||
u32 swap; // Currently active framebuffer.
|
||||
void *framebufs[2][4]; // For each screen A1, A2, B1, B2
|
||||
u8 doubleBuf[2]; // Top, bottom, 1 = enable.
|
||||
|
@ -98,7 +98,7 @@ void GFX_init(GfxFbFmt fmtTop, GfxFbFmt fmtBot)
|
|||
// PSC0, PSC1, PDC0, PDC1, PPF, P3D
|
||||
for(u8 i = 0; i < 6; i++)
|
||||
{
|
||||
KEvent tmp = createEvent(false);
|
||||
KEvent *tmp = createEvent(false);
|
||||
bindInterruptToEvent(tmp, IRQ_PSC0 + i, 14);
|
||||
g_gfxState.events[i] = tmp;
|
||||
}
|
||||
|
@ -389,7 +389,7 @@ void GFX_swapFramebufs(void)
|
|||
|
||||
void GFX_waitForEvent(GfxEvent event, bool discard)
|
||||
{
|
||||
const KEvent kevent = g_gfxState.events[event];
|
||||
KEvent *kevent = g_gfxState.events[event];
|
||||
|
||||
if(discard) clearEvent(kevent);
|
||||
waitForEvent(kevent);
|
||||
|
|
|
@ -68,8 +68,8 @@ static const struct
|
|||
typedef struct
|
||||
{
|
||||
I2cRegs *const regs;
|
||||
KEvent event;
|
||||
KMutex mutex;
|
||||
KEvent *event;
|
||||
KMutex *mutex;
|
||||
} I2cState;
|
||||
static I2cState g_i2cState[3] = {{(I2cRegs*)I2C1_REGS_BASE, NULL, NULL},
|
||||
{(I2cRegs*)I2C2_REGS_BASE, NULL, NULL},
|
||||
|
@ -89,14 +89,14 @@ static bool checkAck(I2cRegs *const regs)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void sendByte(I2cRegs *const regs, u8 data, u8 params, const KEvent event)
|
||||
static void sendByte(I2cRegs *const regs, u8 data, u8 params, KEvent *const event)
|
||||
{
|
||||
regs->I2C_DATA = data;
|
||||
regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_WRITE | params;
|
||||
waitForEvent(event);
|
||||
}
|
||||
|
||||
static u8 recvByte(I2cRegs *const regs, u8 params, const KEvent event)
|
||||
static u8 recvByte(I2cRegs *const regs, u8 params, KEvent *const event)
|
||||
{
|
||||
regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_READ | params;
|
||||
waitForEvent(event);
|
||||
|
@ -110,7 +110,7 @@ void I2C_init(void)
|
|||
inited = true;
|
||||
|
||||
|
||||
KEvent tmp = createEvent(true);
|
||||
KEvent *tmp = createEvent(true);
|
||||
bindInterruptToEvent(tmp, IRQ_I2C1, 14);
|
||||
g_i2cState[0].event = tmp;
|
||||
tmp = createEvent(true);
|
||||
|
@ -144,7 +144,7 @@ static bool startTransfer(u8 devAddr, u8 regAddr, bool read, const I2cState *con
|
|||
do
|
||||
{
|
||||
I2cRegs *const regs = state->regs;
|
||||
const KEvent event = state->event;
|
||||
KEvent *const event = state->event;
|
||||
|
||||
// Edge case on previous transfer error (NACK).
|
||||
// This is a special case where we can't predict when or if
|
||||
|
@ -179,8 +179,8 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
|
|||
const u8 devAddr = i2cDevTable[devId].devAddr;
|
||||
const I2cState *const state = &g_i2cState[i2cDevTable[devId].busId];
|
||||
I2cRegs *const regs = state->regs;
|
||||
const KEvent event = state->event;
|
||||
const KMutex mutex = state->mutex;
|
||||
KEvent *const event = state->event;
|
||||
KMutex *const mutex = state->mutex;
|
||||
|
||||
|
||||
bool res = true;
|
||||
|
@ -203,8 +203,8 @@ bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
|
|||
const u8 devAddr = i2cDevTable[devId].devAddr;
|
||||
const I2cState *const state = &g_i2cState[i2cDevTable[devId].busId];
|
||||
I2cRegs *const regs = state->regs;
|
||||
const KEvent event = state->event;
|
||||
const KMutex mutex = state->mutex;
|
||||
KEvent *const event = state->event;
|
||||
KMutex *const mutex = state->mutex;
|
||||
|
||||
|
||||
lockMutex(mutex);
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
#define LGYFB_BOT_FIFO *((const vu32*)(0x10310000))
|
||||
|
||||
|
||||
static KEvent g_frameReadyEvent = NULL;
|
||||
static KEvent *g_frameReadyEvent = NULL;
|
||||
|
||||
|
||||
|
||||
|
@ -118,11 +118,11 @@ static void setScaleMatrixTop(u32 len, u32 patt, const s16 *const matrix)
|
|||
}
|
||||
}
|
||||
|
||||
void LGYFB_init(const KEvent frameReadyEvent)
|
||||
void LGYFB_init(KEvent *frameReadyEvent)
|
||||
{
|
||||
if(DMA330_run(0, program)) return;
|
||||
|
||||
g_frameReadyEvent = (KEvent)frameReadyEvent;
|
||||
g_frameReadyEvent = frameReadyEvent;
|
||||
|
||||
//REG_LGYFB_TOP_SIZE = LGYFB_SIZE(240u, 160u);
|
||||
REG_LGYFB_TOP_SIZE = LGYFB_SIZE(360u, 240u);
|
||||
|
|
|
@ -274,7 +274,7 @@ void debugTests(void)
|
|||
|
||||
static void gbaGfxHandler(void *args)
|
||||
{
|
||||
const KEvent event = (KEvent)args;
|
||||
KEvent *const event = (KEvent*)args;
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
@ -343,9 +343,9 @@ int main(void)
|
|||
if(MCU_getSystemModel() != 3) GFX_powerOffBacklights(GFX_BLIGHT_BOT);
|
||||
#endif
|
||||
|
||||
const KEvent frameReadyEvent = createEvent(false);
|
||||
KEvent *const frameReadyEvent = createEvent(false);
|
||||
LGYFB_init(frameReadyEvent); // Setup Legacy Framebuffer.
|
||||
/*const KTask gfxTask =*/ createTask(0x800, 3, gbaGfxHandler, frameReadyEvent);
|
||||
/*KTask *const gfxTask =*/ createTask(0x800, 3, gbaGfxHandler, frameReadyEvent);
|
||||
|
||||
// Adjust gamma table and sync LgyFb start with LCD VBlank.
|
||||
adjustGammaTableForGba();
|
||||
|
@ -363,7 +363,7 @@ int main(void)
|
|||
} while(1);
|
||||
|
||||
LGYFB_deinit();
|
||||
deleteEvent(frameReadyEvent); // gfxTask() will automatically terminate.
|
||||
deleteEvent(frameReadyEvent); // gbaGfxHandler() will automatically terminate.
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
Loading…
Reference in New Issue