Now, it works with svc holding lock.
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
2013-06-04 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* chopstx.c (AIRCR): New.
|
||||||
|
(chx_init): Setting for PRIGROUP 2-bit:2-bit.
|
||||||
|
(sched): Unlock cpu_sched_lock on return to thread.
|
||||||
|
(preempt, chx_timer_expired, chx_handle_intr): Those can be
|
||||||
|
considered holding cpu_sched_lock (by its equal exception
|
||||||
|
priorities), thus no acquiring lock required.
|
||||||
|
|
||||||
2013-06-03 Niibe Yutaka <gniibe@fsij.org>
|
2013-06-03 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
* chopstx.c (chx_spin_lock, chx_spin_unlock): Rename.
|
* chopstx.c (chx_spin_lock, chx_spin_unlock): Rename.
|
||||||
|
|||||||
67
chopstx.c
67
chopstx.c
@@ -34,17 +34,22 @@
|
|||||||
/*
|
/*
|
||||||
* Note: Lower has higher precedence.
|
* Note: Lower has higher precedence.
|
||||||
*
|
*
|
||||||
* Prio 0: svc
|
* Prio 0x30: svc
|
||||||
* Prio 32: thread temporarily inhibiting schedule for critical region
|
* ---------------------
|
||||||
* Prio 64: systick, external interrupt
|
* Prio 0x40: thread temporarily inhibiting schedule for critical region
|
||||||
* Prio 96: pendsv
|
* Prio 0x50: systick
|
||||||
|
* Prio 0x60: external interrupt
|
||||||
|
* Prio 0x70: pendsv
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CPU_EXCEPTION_PRIORITY_SVC 0
|
|
||||||
#define CPU_EXCEPTION_PRIORITY_CLEAR 0
|
#define CPU_EXCEPTION_PRIORITY_CLEAR 0
|
||||||
#define CPU_EXCEPTION_PRIORITY_INHIBIT_SCHED 32
|
|
||||||
#define CPU_EXCEPTION_PRIORITY_INTERRUPT 64
|
#define CPU_EXCEPTION_PRIORITY_SVC 0x30
|
||||||
#define CPU_EXCEPTION_PRIORITY_PENDSV 96
|
|
||||||
|
#define CPU_EXCEPTION_PRIORITY_INHIBIT_SCHED 0x40
|
||||||
|
#define CPU_EXCEPTION_PRIORITY_SYSTICK 0x50
|
||||||
|
#define CPU_EXCEPTION_PRIORITY_INTERRUPT 0x60
|
||||||
|
#define CPU_EXCEPTION_PRIORITY_PENDSV 0x70
|
||||||
|
|
||||||
static void
|
static void
|
||||||
chx_cpu_sched_lock (void)
|
chx_cpu_sched_lock (void)
|
||||||
@@ -335,7 +340,6 @@ sched (void)
|
|||||||
register uint32_t r0 asm ("r0");
|
register uint32_t r0 asm ("r0");
|
||||||
|
|
||||||
r0 = chx_ready_pop ();
|
r0 = chx_ready_pop ();
|
||||||
|
|
||||||
asm volatile (/* Now, r0 points to the thread to be switched. */
|
asm volatile (/* Now, r0 points to the thread to be switched. */
|
||||||
/* Put it to *running. */
|
/* Put it to *running. */
|
||||||
"ldr r1, =running\n\t"
|
"ldr r1, =running\n\t"
|
||||||
@@ -354,8 +358,10 @@ sched (void)
|
|||||||
"ldr r1, [r0]\n\t"
|
"ldr r1, [r0]\n\t"
|
||||||
"msr PSP, r1\n\t"
|
"msr PSP, r1\n\t"
|
||||||
/**/
|
/**/
|
||||||
"mov r0, #-1\n\t"
|
"mov r0, #0\n\t"
|
||||||
"sub r0, #2\n\t" /* EXC_RETURN to a thread with PSP */
|
"msr BASEPRI, r0\n\t" /* Unmask interrupts. */
|
||||||
|
/**/
|
||||||
|
"sub r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
|
||||||
"bx r0\n"
|
"bx r0\n"
|
||||||
"3:\n\t"
|
"3:\n\t"
|
||||||
/* Spawn an IDLE thread. */
|
/* Spawn an IDLE thread. */
|
||||||
@@ -375,8 +381,7 @@ sched (void)
|
|||||||
"mov r0, #0\n\t"
|
"mov r0, #0\n\t"
|
||||||
"msr BASEPRI, r0\n\t" /* Unmask interrupts. */
|
"msr BASEPRI, r0\n\t" /* Unmask interrupts. */
|
||||||
/**/
|
/**/
|
||||||
"mov r0, #-1\n\t"
|
"sub r0, #7\n\t" /* EXC_RETURN to a thread with MSP */
|
||||||
"sub r0, #6\n\t" /* EXC_RETURN to a thread with MSP */
|
|
||||||
"bx r0\n"
|
"bx r0\n"
|
||||||
: /* no output */ : "r" (r0) : "memory");
|
: /* no output */ : "r" (r0) : "memory");
|
||||||
}
|
}
|
||||||
@@ -390,8 +395,6 @@ preempt (void)
|
|||||||
"ldr r0, [r1]\n\t"
|
"ldr r0, [r1]\n\t"
|
||||||
"cbnz r0, 0f\n\t"
|
"cbnz r0, 0f\n\t"
|
||||||
/* It's idle which was preempted. */
|
/* It's idle which was preempted. */
|
||||||
"mov r0, #2\n\t"
|
|
||||||
"msr BASEPRI, r0\n\t" /* mask any interrupts. */
|
|
||||||
"ldr r1, =__main_stack_end__\n\t"
|
"ldr r1, =__main_stack_end__\n\t"
|
||||||
"msr MSP, r1\n\t"
|
"msr MSP, r1\n\t"
|
||||||
"b sched\n"
|
"b sched\n"
|
||||||
@@ -409,7 +412,6 @@ preempt (void)
|
|||||||
: /* no input */
|
: /* no input */
|
||||||
: "r1", "r2", "r3", "r4", "r7", "cc", "memory");
|
: "r1", "r2", "r3", "r4", "r7", "cc", "memory");
|
||||||
|
|
||||||
chx_cpu_sched_lock ();
|
|
||||||
chx_ready_push ((struct chx_thread *)r0);
|
chx_ready_push ((struct chx_thread *)r0);
|
||||||
running = NULL;
|
running = NULL;
|
||||||
|
|
||||||
@@ -534,7 +536,6 @@ chx_timer_expired (void)
|
|||||||
struct chx_thread *tp;
|
struct chx_thread *tp;
|
||||||
chopstx_prio_t prio = 0;
|
chopstx_prio_t prio = 0;
|
||||||
|
|
||||||
chx_cpu_sched_lock ();
|
|
||||||
chx_spin_lock (&q_timer.lock);
|
chx_spin_lock (&q_timer.lock);
|
||||||
if ((tp = ll_pop (&q_timer)))
|
if ((tp = ll_pop (&q_timer)))
|
||||||
{
|
{
|
||||||
@@ -566,7 +567,6 @@ chx_timer_expired (void)
|
|||||||
if (running == NULL || running->prio < prio)
|
if (running == NULL || running->prio < prio)
|
||||||
chx_request_preemption ();
|
chx_request_preemption ();
|
||||||
chx_spin_unlock (&q_timer.lock);
|
chx_spin_unlock (&q_timer.lock);
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -603,7 +603,6 @@ chx_handle_intr (void)
|
|||||||
chopstx_intr_t *intr;
|
chopstx_intr_t *intr;
|
||||||
register uint32_t irq_num;
|
register uint32_t irq_num;
|
||||||
|
|
||||||
chx_cpu_sched_lock ();
|
|
||||||
asm volatile ("mrs %0, IPSR\n\t"
|
asm volatile ("mrs %0, IPSR\n\t"
|
||||||
"sub %0, #16" /* Exception # - 16 = interrupt number. */
|
"sub %0, #16" /* Exception # - 16 = interrupt number. */
|
||||||
: "=r" (irq_num) : /* no input */ : "memory");
|
: "=r" (irq_num) : /* no input */ : "memory");
|
||||||
@@ -622,7 +621,6 @@ chx_handle_intr (void)
|
|||||||
chx_request_preemption ();
|
chx_request_preemption ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -633,6 +631,7 @@ chx_systick_init (void)
|
|||||||
*SYST_CSR = 7;
|
*SYST_CSR = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t *const AIRCR = (uint32_t *const)0xE000ED0C;
|
||||||
static uint32_t *const SHPR2 = (uint32_t *const)0xE000ED1C;
|
static uint32_t *const SHPR2 = (uint32_t *const)0xE000ED1C;
|
||||||
static uint32_t *const SHPR3 = (uint32_t *const)0xE000ED20;
|
static uint32_t *const SHPR3 = (uint32_t *const)0xE000ED20;
|
||||||
|
|
||||||
@@ -641,9 +640,10 @@ static uint32_t *const SHPR3 = (uint32_t *const)0xE000ED20;
|
|||||||
void
|
void
|
||||||
chx_init (struct chx_thread *tp)
|
chx_init (struct chx_thread *tp)
|
||||||
{
|
{
|
||||||
*SHPR2 = (CPU_EXCEPTION_PRIORITY_SVC << 24); /* SVCall */
|
*AIRCR = 0x05FA0000 | ( 5 << 8); /* PRIGROUP = 5, 2-bit:2-bit. */
|
||||||
*SHPR3 = ((CPU_EXCEPTION_PRIORITY_INTERRUPT << 24) /* SysTick */
|
*SHPR2 = (CPU_EXCEPTION_PRIORITY_SVC << 24);
|
||||||
| (CPU_EXCEPTION_PRIORITY_PENDSV << 16)); /* PendSV */
|
*SHPR3 = ((CPU_EXCEPTION_PRIORITY_SYSTICK << 24)
|
||||||
|
| (CPU_EXCEPTION_PRIORITY_PENDSV << 16));
|
||||||
|
|
||||||
memset (&tp->tc, 0, sizeof (tp->tc));
|
memset (&tp->tc, 0, sizeof (tp->tc));
|
||||||
q_ready.next = q_ready.prev = (struct chx_thread *)&q_ready;
|
q_ready.next = q_ready.prev = (struct chx_thread *)&q_ready;
|
||||||
@@ -718,7 +718,6 @@ chx_exit (void *retval)
|
|||||||
asm volatile ("" : : "r" (r8) : "memory");
|
asm volatile ("" : : "r" (r8) : "memory");
|
||||||
chx_sched ();
|
chx_sched ();
|
||||||
/* never comes here. */
|
/* never comes here. */
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,7 +812,8 @@ chopstx_create (chopstx_t *thd, const chopstx_attr_t *attr,
|
|||||||
chx_ready_enqueue (tp);
|
chx_ready_enqueue (tp);
|
||||||
if (tp->prio > running->prio)
|
if (tp->prio > running->prio)
|
||||||
chx_yield ();
|
chx_yield ();
|
||||||
chx_cpu_sched_unlock ();
|
else
|
||||||
|
chx_cpu_sched_unlock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -829,7 +829,6 @@ chopstx_usec_wait (uint32_t usec)
|
|||||||
chx_timer_insert (running, usec0);
|
chx_timer_insert (running, usec0);
|
||||||
chx_spin_unlock (&q_timer.lock);
|
chx_spin_unlock (&q_timer.lock);
|
||||||
chx_sched ();
|
chx_sched ();
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
usec -= usec0;
|
usec -= usec0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -900,7 +899,6 @@ chopstx_mutex_lock (chopstx_mutex_t *mutex)
|
|||||||
tp->v = (uint32_t)mutex;
|
tp->v = (uint32_t)mutex;
|
||||||
chx_spin_unlock (&mutex->lock);
|
chx_spin_unlock (&mutex->lock);
|
||||||
chx_sched ();
|
chx_sched ();
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -918,7 +916,8 @@ chopstx_mutex_unlock (chopstx_mutex_t *mutex)
|
|||||||
chx_spin_unlock (&mutex->lock);
|
chx_spin_unlock (&mutex->lock);
|
||||||
if (prio > running->prio)
|
if (prio > running->prio)
|
||||||
chx_yield ();
|
chx_yield ();
|
||||||
chx_cpu_sched_unlock ();
|
else
|
||||||
|
chx_cpu_sched_unlock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -949,7 +948,6 @@ chopstx_cond_wait (chopstx_cond_t *cond, chopstx_mutex_t *mutex)
|
|||||||
tp->v = (uint32_t)cond;
|
tp->v = (uint32_t)cond;
|
||||||
chx_spin_unlock (&cond->lock);
|
chx_spin_unlock (&cond->lock);
|
||||||
chx_sched ();
|
chx_sched ();
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
|
|
||||||
if (mutex)
|
if (mutex)
|
||||||
chopstx_mutex_lock (mutex);
|
chopstx_mutex_lock (mutex);
|
||||||
@@ -974,7 +972,8 @@ chopstx_cond_signal (chopstx_cond_t *cond)
|
|||||||
chx_spin_unlock (&cond->lock);
|
chx_spin_unlock (&cond->lock);
|
||||||
if (yield)
|
if (yield)
|
||||||
chx_yield ();
|
chx_yield ();
|
||||||
chx_cpu_sched_unlock ();
|
else
|
||||||
|
chx_cpu_sched_unlock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -995,7 +994,8 @@ chopstx_cond_broadcast (chopstx_cond_t *cond)
|
|||||||
chx_spin_unlock (&cond->lock);
|
chx_spin_unlock (&cond->lock);
|
||||||
if (yield)
|
if (yield)
|
||||||
chx_yield ();
|
chx_yield ();
|
||||||
chx_cpu_sched_unlock ();
|
else
|
||||||
|
chx_cpu_sched_unlock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1069,7 +1069,6 @@ chopstx_intr_wait (chopstx_intr_t *intr)
|
|||||||
chx_sched ();
|
chx_sched ();
|
||||||
}
|
}
|
||||||
intr->ready--;
|
intr->ready--;
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1129,7 +1128,6 @@ chopstx_join (chopstx_t thd, void **ret)
|
|||||||
tp->state = THREAD_FINISHED;
|
tp->state = THREAD_FINISHED;
|
||||||
if (ret)
|
if (ret)
|
||||||
*ret = (void *)tp->tc.reg[REG_EXIT]; /* R8 */
|
*ret = (void *)tp->tc.reg[REG_EXIT]; /* R8 */
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1164,7 +1162,8 @@ chopstx_cancel (chopstx_t thd)
|
|||||||
}
|
}
|
||||||
if (yield)
|
if (yield)
|
||||||
chx_yield ();
|
chx_yield ();
|
||||||
chx_cpu_sched_unlock ();
|
else
|
||||||
|
chx_cpu_sched_unlock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <chopstx.h>
|
#include <chopstx.h>
|
||||||
#include "sys.h" /* for set_led */
|
#include "sys.h" /* for set_led */
|
||||||
#include "usb_lld.h" /* for set_led */
|
#include "usb_lld.h" /* for set_led */
|
||||||
@@ -9,8 +10,7 @@ static chopstx_cond_t cnd0;
|
|||||||
static chopstx_cond_t cnd1;
|
static chopstx_cond_t cnd1;
|
||||||
|
|
||||||
chopstx_mutex_t usb_mtx;
|
chopstx_mutex_t usb_mtx;
|
||||||
chopstx_cond_t cnd_usb_connection;
|
chopstx_cond_t cnd_usb;
|
||||||
chopstx_cond_t cnd_usb_buffer_ready;
|
|
||||||
|
|
||||||
static uint8_t u, v;
|
static uint8_t u, v;
|
||||||
static uint8_t m; /* 0..100 */
|
static uint8_t m; /* 0..100 */
|
||||||
@@ -102,12 +102,23 @@ const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
|
|||||||
const uint32_t __stackaddr_intr = (uint32_t)&__process3_stack_base__;
|
const uint32_t __stackaddr_intr = (uint32_t)&__process3_stack_base__;
|
||||||
const size_t __stacksize_intr = (size_t)&__process3_stack_size__;
|
const size_t __stacksize_intr = (size_t)&__process3_stack_size__;
|
||||||
|
|
||||||
|
static char hexchar (uint8_t x)
|
||||||
|
{
|
||||||
|
if (x <= 0x09)
|
||||||
|
return '0' + x;
|
||||||
|
else if (x <= 0x0f)
|
||||||
|
return 'a' + x - 10;
|
||||||
|
else
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
chopstx_t thd;
|
chopstx_t thd;
|
||||||
chopstx_attr_t attr;
|
chopstx_attr_t attr;
|
||||||
|
uint8_t count;
|
||||||
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
@@ -117,8 +128,7 @@ main (int argc, const char *argv[])
|
|||||||
chopstx_cond_init (&cnd1);
|
chopstx_cond_init (&cnd1);
|
||||||
|
|
||||||
chopstx_mutex_init (&usb_mtx);
|
chopstx_mutex_init (&usb_mtx);
|
||||||
chopstx_cond_init (&cnd_usb_connection);
|
chopstx_cond_init (&cnd_usb);
|
||||||
chopstx_cond_init (&cnd_usb_buffer_ready);
|
|
||||||
|
|
||||||
m = 10;
|
m = 10;
|
||||||
|
|
||||||
@@ -149,21 +159,33 @@ main (int argc, const char *argv[])
|
|||||||
{
|
{
|
||||||
extern uint8_t connected;
|
extern uint8_t connected;
|
||||||
|
|
||||||
|
count= 0;
|
||||||
|
u = 1;
|
||||||
/* waiting USB connection */
|
/* waiting USB connection */
|
||||||
chopstx_mutex_lock (&usb_mtx);
|
chopstx_mutex_lock (&usb_mtx);
|
||||||
if (!connected)
|
if (!connected)
|
||||||
chopstx_cond_wait (&cnd_usb_connection, &usb_mtx);
|
chopstx_cond_wait (&cnd_usb, &usb_mtx);
|
||||||
chopstx_mutex_unlock (&usb_mtx);
|
chopstx_mutex_unlock (&usb_mtx);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
char s[32];
|
||||||
|
|
||||||
u ^= 1;
|
u ^= 1;
|
||||||
chopstx_usec_wait (200*1000*6);
|
chopstx_usec_wait (200*1000*6);
|
||||||
|
|
||||||
usb_lld_write (ENDP1, "Hello, World with Chopstx!\r\n", 28);
|
memcpy (s, "xx: Hello, World with Chopstx!\r\n", 32);
|
||||||
|
s[0] = hexchar (count >> 4);
|
||||||
|
s[1] = hexchar (count & 0x0f);
|
||||||
|
count++;
|
||||||
|
|
||||||
chopstx_mutex_lock (&usb_mtx);
|
chopstx_mutex_lock (&usb_mtx);
|
||||||
chopstx_cond_wait (&cnd_usb_buffer_ready, &usb_mtx);
|
if (connected)
|
||||||
if (!connected)
|
{
|
||||||
|
usb_lld_write (ENDP1, s, 32);
|
||||||
|
chopstx_cond_wait (&cnd_usb, &usb_mtx);
|
||||||
|
}
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
chopstx_mutex_unlock (&usb_mtx);
|
chopstx_mutex_unlock (&usb_mtx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
#include "usb_lld.h"
|
#include "usb_lld.h"
|
||||||
|
|
||||||
extern chopstx_mutex_t usb_mtx;
|
extern chopstx_mutex_t usb_mtx;
|
||||||
extern chopstx_cond_t cnd_usb_connection;
|
extern chopstx_cond_t cnd_usb;
|
||||||
extern chopstx_cond_t cnd_usb_buffer_ready;
|
|
||||||
|
|
||||||
#define ENDP0_RXADDR (0x40)
|
#define ENDP0_RXADDR (0x40)
|
||||||
#define ENDP0_TXADDR (0x80)
|
#define ENDP0_TXADDR (0x80)
|
||||||
@@ -241,7 +240,7 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
|
|||||||
|
|
||||||
chopstx_mutex_lock (&usb_mtx);
|
chopstx_mutex_lock (&usb_mtx);
|
||||||
if (connected != connected_saved)
|
if (connected != connected_saved)
|
||||||
chopstx_cond_signal (&cnd_usb_connection);
|
chopstx_cond_signal (&cnd_usb);
|
||||||
chopstx_mutex_unlock (&usb_mtx);
|
chopstx_mutex_unlock (&usb_mtx);
|
||||||
|
|
||||||
return USB_SUCCESS;
|
return USB_SUCCESS;
|
||||||
@@ -416,7 +415,7 @@ void
|
|||||||
EP1_IN_Callback (void)
|
EP1_IN_Callback (void)
|
||||||
{
|
{
|
||||||
chopstx_mutex_lock (&usb_mtx);
|
chopstx_mutex_lock (&usb_mtx);
|
||||||
chopstx_cond_signal (&cnd_usb_buffer_ready);
|
chopstx_cond_signal (&cnd_usb);
|
||||||
chopstx_mutex_unlock (&usb_mtx);
|
chopstx_mutex_unlock (&usb_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user