git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@346 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
71a1820c4a
commit
49c3629538
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; \
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
13
src/chinit.c
13
src/chinit.c
|
@ -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++;
|
||||
|
|
25
src/chmtx.c
25
src/chmtx.c
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
52
src/chschd.c
52
src/chschd.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue