git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@346 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2008-07-22 09:55:51 +00:00
parent 71a1820c4a
commit 49c3629538
12 changed files with 1949 additions and 1867 deletions

View File

@ -24,6 +24,8 @@
#include "stm32_serial.h"
#include "stm32lib/stm32f10x_nvic.h"
#define USART_BITRATE (38400)
#ifdef USE_USART1
FullDuplexDriver COM1;
static uint8_t ib1[SERIAL_BUFFERS_SIZE];
@ -175,7 +177,7 @@ void InitSerial(uint32_t prio1, uint32_t prio2, uint32_t prio3) {
#ifdef USE_USART1
chFDDInit(&COM1, ib1, sizeof ib1, NULL, ob1, sizeof ob1, OutNotify1);
RCC->APB2ENR |= 0x00004000;
SetUSARTI(USART1, 38400, 0, CR2_STOP1_BITS | CR2_LINEN, 0);
SetUSARTI(USART1, USART_BITRATE, 0, CR2_STOP1_BITS | CR2_LINEN, 0);
GPIOA->CRH = (GPIOA->CRH & 0xFFFFF00F) | 0x000004B0;
NVICEnableVector(USART1_IRQChannel, prio1);
#endif
@ -183,7 +185,7 @@ void InitSerial(uint32_t prio1, uint32_t prio2, uint32_t prio3) {
#ifdef USE_USART2
chFDDInit(&COM2, ib2, sizeof ib2, NULL, ob2, sizeof ob2, OutNotify2);
RCC->APB1ENR |= 0x00020000;
SetUSARTI(USART2, 38400, 0, CR2_STOP1_BITS | CR2_LINEN, 0);
SetUSARTI(USART2, USART_BITRATE, 0, CR2_STOP1_BITS | CR2_LINEN, 0);
GPIOA->CRL = (GPIOA->CRL & 0xFFFF00FF) | 0x00004B00;
NVICEnableVector(USART2_IRQChannel, prio2);
#endif
@ -191,7 +193,7 @@ void InitSerial(uint32_t prio1, uint32_t prio2, uint32_t prio3) {
#ifdef USE_USART3
chFDDInit(&COM3, ib3, sizeof ib3, NULL, ob3, sizeof ob3, OutNotify3);
RCC->APB1ENR |= 0x00040000;
SetUSARTI(USART3, 38400, 0, CR2_STOP1_BITS | CR2_LINEN, 0);
SetUSARTI(USART3, USART_BITRATE, 0, CR2_STOP1_BITS | CR2_LINEN, 0);
GPIOB->CRH = (GPIOB->CRH & 0xFFFF00FF) | 0x00004B00;
NVICEnableVector(USART3_IRQChannel, prio3);
#endif

View File

@ -49,6 +49,12 @@ void chSysHalt(void) {
}
}
/*
* Start a thread by invoking its work function.
*
* Start a thread by calling its work function. If the work function returns,
* call chThdExit and chSysHalt.
*/
__attribute__((naked, weak))
void threadstart(void) {
@ -80,7 +86,15 @@ void *retaddr;
*/
__attribute__((naked))
void SVCallVector(Thread *otp, Thread *ntp) {
/* { r0 = otp, r1 = ntp } */
/* get the BASEPRI in r3 */
/* get the PSP in r12 */
/* push the registers on the PSP stack */
/* stores the modified PSP into the thread context */
/* fetches the PSP position from the new thread context */
/* pop the registers from the PSP stack */
/* set the PSP from r12 */
/* set the BASEPRI from R3 */
#ifdef CH_CURRP_REGISTER_CACHE
asm volatile ("mrs r3, BASEPRI \n\t" \
"mrs r12, PSP \n\t" \
@ -135,6 +149,7 @@ void PendSVVector(void) {
(otp = currp)->p_ctx.r13 = sp_thd;
chSchReadyI(otp);
(currp = fifo_remove(&rlist.r_queue))->p_state = PRCURR;
/* set the round-robin time quantum */
rlist.r_preempt = CH_TIME_QUANTUM;
#ifdef CH_USE_TRACE
chDbgTrace(otp, currp);

View File

@ -66,6 +66,9 @@ typedef struct {
/*
* Platform dependent part of the \p chThdCreate() API.
*
* The top of the workspace is used for the intctx datastructure.
*
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
@ -104,7 +107,10 @@ typedef struct {
INT_REQUIRED_STACK)
#define WorkingArea(s, n) uint32_t s[UserStackSize(n) >> 2];
/* called on each interrupt entry, currently nothing is done */
#define chSysIRQEnterI()
/* called on each interrupt exit, pends a supervisor handler for
* execution after all higher priority interrupts; PendSVVector() */
#define chSysIRQExitI() { \
SCB_ICSR = ICSR_PENDSVSET; \
}

View File

@ -43,6 +43,7 @@ ResetHandler:
ldr r0, =__ram_end__
ldr r1, =__main_stack_size__
sub r0, r0, r1
/* { r0 = main stack low address } */
msr PSP, r0
// ldr r1, =__process_stack_size__
// sub r0, r0, r1

View File

@ -74,6 +74,12 @@ Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
*** Releases ***
*****************************************************************************
*** 0.6.8 ***
- FIX: Fixed a bug in the priority inheritance mechanism, the bug was only a
problems when the CH_USE_MESSAGES_PRIORITY was enabled, this option is
disabled by default in ChibiOS/RT so it should not affect any user.
- Merged the documentation fixes submitted by Leon Woestenberg (thank you).
*** 0.6.7 ***
- NEW: New chThdCreateFast() API, it is a simplified form of chThdCreate()
that allows even faster threads creation. The new API does not support

View File

@ -60,14 +60,19 @@ void chSysInit(void) {
}
/**
* Preemption routine, this function must be called into an interrupt
* handler invoked by a system timer.
* The frequency of the timer determines the system tick granularity and,
* Handles time ticks for round robin preemption and timer increments.
*
* Decrements the remaining time quantum of the running thread and preempts
* it when the quantum is used up. Increments system time and manages the
* timers.
*
* @note The frequency of the timer determines the system tick granularity and,
* together with the \p CH_TIME_QUANTUM macro, the round robin interval.
*/
void chSysTimerHandlerI(void) {
/* running thread has not used up quantum yet? */
if (rlist.r_preempt > 0)
/* decrement remaining quantum */
rlist.r_preempt--;
#ifdef CH_USE_SYSTEMTIME
rlist.r_stime++;

View File

@ -51,34 +51,46 @@ void chMtxLock(Mutex *mp) {
/**
* Locks the specified mutex.
*
* @param mp pointer to the \p Mutex structure
* @note This function must be called within a \p chSysLock() / \p chSysUnlock()
* block.
*/
void chMtxLockS(Mutex *mp) {
/* the mutex is already locked? */
if (mp->m_owner != NULL) {
/*
* Inheritance, explores the thread-mutex dependances adjusting
* the priority of all the affected threads.
* Priority inheritance protocol; explores the thread-mutex dependencies
* boosting the priority of all the affected threads to equal the priority
* of the running thread requesting the mutex.
*/
Thread *tp = mp->m_owner;
/* { tp is the thread currently owning the mutex } */
/* the running thread has higher priority than tp? */
while (tp->p_prio < currp->p_prio) {
/* make priority of thread tp match the running thread's priority */
tp->p_prio = currp->p_prio;
/*
* The following states need priority queues reordering.
*/
switch (tp->p_state) {
/* thread tp is waiting on a mutex? */
case PRWTMTX:
/* requeue tp with its new priority on the mutex wait queue */
prio_insert(dequeue(tp), &tp->p_wtmtxp->m_queue);
/* boost the owner of this mutex if needed */
tp = tp->p_wtmtxp->m_owner;
continue;
#ifdef CH_USE_MESSAGES_PRIORITY
case PRSNDMSG:
if (tp->p_flags & P_MSGBYPRIO)
/* requeue tp with its new priority on (?) */
prio_insert(dequeue(tp), &tp->p_wtthdp->p_msgqueue);
break;
#endif
/* thread tp is ready? */
case PRREADY:
/* requeue tp with its new priority on the ready list */
chSchReadyI(dequeue(tp));
}
break;
@ -157,21 +169,26 @@ void chMtxUnlock(void) {
* If a thread is waiting on the mutex then the hard part begins.
*/
if (chMtxQueueNotEmptyS(mp)) {
/* get the highest priority thread waiting for the unlocked mutex */
Thread *tp = fifo_remove(&mp->m_queue);
/*
* Recalculates the optimal thread priority by scanning the owned mutexes list.
*/
tprio_t newprio = currp->p_realprio;
/* iterate mp over all the (other) mutexes the current thread still owns */
mp = currp->p_mtxlist;
while (mp != NULL) {
/* mutex mp has a higher priority thread pending? */
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
/* boost current thread's priority to waiting thread */
newprio = mp->m_queue.p_next->p_prio;
mp = mp->m_next;
}
/* (possibly) boost the priority of the current thread */
currp->p_prio = newprio;
/* awaken the highest priority thread waiting for the unlocked mutex */
chSchWakeupS(tp, RDY_OK);
}
chSysUnlock();
}

View File

@ -44,6 +44,7 @@ void chSchInit(void) {
/**
* Inserts a thread in the Ready List.
*
* @param tp the Thread to be made ready
* @return the Thread pointer
* @note The function must be called in the system mutex zone.
@ -103,9 +104,12 @@ static void wakeup(void *p) {
}
/**
* Puts the current thread to sleep into the specified state, the next highest
* priority thread becomes running. The thread is automatically awakened after
* the specified time elapsed.
* Put the current thread to sleep.
*
* Puts the current thread to sleep into the specified state. The next highest
* priority thread becomes running. The thread put to sleep is awakened after
* the specified time has elapsed.
*
* @param newstate the new thread state
* @param time the number of ticks before the operation timouts
* @return the wakeup message, it is \p RDY_TIMEOUT if a timeout occurs
@ -124,8 +128,10 @@ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
#endif /* CH_USE_VIRTUAL_TIMERS */
/**
* Wakeups a thread, the thread is inserted into the ready list or made
* running directly depending on its relative priority compared to the current
* Wakes up a thread.
*
* Wakes up a thread. The thread is inserted into the ready list or immediately
* made running depending on its relative priority compared to the current
* thread.
* @param ntp the Thread to be made ready
* @param msg message to the awakened thread
@ -135,11 +141,14 @@ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
* \p chSchRescheduleS() but much more efficient.
*/
void chSchWakeupS(Thread *ntp, msg_t msg) {
ntp->p_rdymsg = msg;
/* the woken thread has equal or lower priority than the running thread? */
if (ntp->p_prio <= currp->p_prio)
/* put the woken thread on the ready queue */
chSchReadyI(ntp);
/* the woken thread has higher priority than the running thread */
else {
/* put the running thread on the ready queue */
Thread *otp = currp;
chSchReadyI(otp);
(currp = ntp)->p_state = PRCURR;
@ -147,46 +156,59 @@ void chSchWakeupS(Thread *ntp, msg_t msg) {
#ifdef CH_USE_TRACE
chDbgTrace(otp, ntp);
#endif
/* switch the thread context */
chSysSwitchI(otp, ntp);
}
}
/**
* Performs a reschedulation. It is meant to be called if
* \p chSchRescRequired() evaluates to \p TRUE.
* Switch to the first thread on the runnable queue.
*
* Intended to be called if \p chSchRescRequired() evaluates to \p TRUE.
*/
void chSchDoRescheduleI(void) {
/* put the running thread on the ready queue */
Thread *otp = currp;
chSchReadyI(otp);
/* pick the first thread from the ready queue */
(currp = fifo_remove(&rlist.r_queue))->p_state = PRCURR;
rlist.r_preempt = CH_TIME_QUANTUM;
#ifdef CH_USE_TRACE
chDbgTrace(otp, currp);
#endif
/* switch thread context */
chSysSwitchI(otp, currp);
}
/**
* If a thread with an higher priority than the current thread is in the
* ready list then it becomes running.
* Reschedule only if a higher priority thread is runnable.
*
* If a thread with a higher priority than the current thread is in the
* ready list then make the higher priority thread running.
*
* @note The function must be called in the system mutex zone.
*/
void chSchRescheduleS(void) {
/* first thread in the runnable queue has higher priority than the running
* thread? */
if (firstprio(&rlist.r_queue) > currp->p_prio)
chSchDoRescheduleI();
}
/**
* Evaluates if a reschedulation is required.
* Evaluates if rescheduling is required.
*
* @return \p TRUE if there is a thread that should go in running state
* immediatly else \p FALSE.
* immediately else \p FALSE.
*/
bool_t chSchRescRequiredI(void) {
tprio_t p1 = firstprio(&rlist.r_queue);
tprio_t p2 = currp->p_prio;
/* If the running thread has not reached its time quantum, reschedule only
* if the first thread on the ready queue has a higher priority.
* Otherwise, if the running thread has used up its time quantum, reschedule
* if the first thread on the ready queue has equal or higher priority.
*/
return rlist.r_preempt ? p1 > p2 : p1 >= p2;
}

View File

@ -34,6 +34,7 @@ void init_thread(tprio_t prio, tmode_t mode, Thread *tp) {
tp->p_flags = mode;
tp->p_prio = prio;
#ifdef CH_USE_MUTEXES
/* realprio is the thread's own, non-inherited, priority */
tp->p_realprio = prio;
tp->p_mtxlist = NULL;
#endif
@ -89,6 +90,7 @@ static void memfill(uint8_t *p, uint32_t n, uint8_t v) {
*/
Thread *chThdCreate(tprio_t prio, tmode_t mode, void *workspace,
size_t wsize, tfunc_t pf, void *arg) {
/* thread structure is layed out in the lower part of the thread workspace */
Thread *tp = workspace;
chDbgAssert((wsize >= UserStackSize(0)) && (prio <= HIGHPRIO) &&
@ -146,8 +148,9 @@ Thread *chThdCreateFast(tprio_t prio, void *workspace,
}
/**
* Changes the thread priority, reschedules if necessary.
* @param newprio the new priority of the invoking thread
* Changes the running thread priority, reschedules if necessary.
*
* @param newprio the new priority of the running thread
*/
void chThdSetPriority(tprio_t newprio) {
@ -236,6 +239,7 @@ void chThdTerminate(Thread *tp) {
/**
* Terminates the current thread by specifying an exit status code.
*
* @param msg the thread exit code. The code can be retrieved by using
* \p chThdWait().
*/
@ -258,6 +262,7 @@ void chThdExit(msg_t msg) {
/**
* Blocks the execution of the invoking thread until the specified thread
* terminates then the exit code is returned.
*
* @param tp the pointer to the thread
* @return the exit code
* @note The function is available only if the \p CH_USE_WAITEXIT

View File

@ -27,11 +27,12 @@
/** Normal \p chSchReadyI() message. */
#define RDY_OK 0
/** Returned if the thread was made ready because a timeout.*/
/** Returned when the thread was made ready because of a timeout. */
#define RDY_TIMEOUT -1
/** Returned if the thread was made ready because a reset.*/
/** Returned when the thread was made ready because of a reset. */
#define RDY_RESET -2
/** The priority of the first thread on the given ready list. */
#define firstprio(rlp) ((rlp)->p_next->p_prio)
/**
@ -42,6 +43,7 @@ typedef struct {
tprio_t r_prio;
cnt_t r_preempt;
#ifndef CH_CURRP_REGISTER_CACHE
/** the currently running thread */
Thread *r_current;
#endif
#ifdef CH_USE_SYSTEMTIME

View File

@ -101,8 +101,9 @@ struct Thread {
eventmask_t p_epending;
#endif
#ifdef CH_USE_MUTEXES
/** Owner mutexes list, \p NULL terminated.*/
/** List of mutexes owned by this thread, \p NULL terminated.*/
Mutex *p_mtxlist;
/** Thread's own, non-inherited, priority */
tprio_t p_realprio;
#endif
};