Now, it works with svc holding lock.

This commit is contained in:
NIIBE Yutaka
2013-06-04 10:20:53 +09:00
parent ca47da23f1
commit 7a09ac9a10
4 changed files with 75 additions and 46 deletions

View File

@@ -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.

View File

@@ -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 ();
} }

View File

@@ -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);
} }

View File

@@ -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);
} }