Compare commits
8 Commits
71cc5a8f32
...
a8e9074faf
| Author | SHA1 | Date | |
|---|---|---|---|
| a8e9074faf | |||
|
|
e12a7e0bb3 | ||
|
|
fdbe91600d | ||
|
|
daca396027 | ||
|
|
a6b96fe434 | ||
|
|
c5a83cb9a5 | ||
|
|
8f20122e54 | ||
|
|
c31a91947d |
50
ChangeLog
50
ChangeLog
@@ -1,3 +1,53 @@
|
|||||||
|
2022-04-22 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* VERSION: 1.21.
|
||||||
|
* doc/chopstx.texi (VERSION): 1.21.
|
||||||
|
|
||||||
|
2022-04-21 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
Backport the changes from master.
|
||||||
|
* chopstx.c (struct chx_pq): Use struct qh.
|
||||||
|
(struct chx_px): Use struct qh.
|
||||||
|
(struct chx_thread): Use struct qh.
|
||||||
|
(FOR_QUEUE): Remove.
|
||||||
|
(ll_dequeue): Follow the changes of above.
|
||||||
|
(ll_prio_push): Use struct qh for the loop.
|
||||||
|
(ll_prio_enqueue): Likewise.
|
||||||
|
(chx_set_timer): Use struct qh for the first argument.
|
||||||
|
(chx_timer_insert, chx_timer_dequeue): Use struct qh for the loop.
|
||||||
|
(chx_timer_expired): Likewise.
|
||||||
|
(chx_init, chopstx_create, chx_proxy_init): Use the address at q.
|
||||||
|
(chx_exit): Use struct qh for the loop.
|
||||||
|
(chx_mutex_unlock): Fix the calculation of the priority.
|
||||||
|
* chopstx-cortex-m.c (chx_handle_intr): Not use FOR_QUEUE macro.
|
||||||
|
* chopstx-gnu-linux.c (chx_handle_intr): Not use FOR_QUEUE macro.
|
||||||
|
|
||||||
|
2022-04-08 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
Backport the changes from master.
|
||||||
|
* chopstx.h (struct chx_qh): Change the type for next and prev.
|
||||||
|
* chopstx.c (FOR_QUEUE): New macro.
|
||||||
|
(ll_empty): Follow the change of struct chx_qh.
|
||||||
|
(ll_insert): Change the type of the first argument.
|
||||||
|
(ll_pop): Follow the change of struct chx_qh.
|
||||||
|
(ll_prio_push): Use FOR_QUEUE macro. Follow the change of
|
||||||
|
ll_insert.
|
||||||
|
(ll_prio_enqueue, chx_timer_insert): Likewise.
|
||||||
|
(chx_timer_dequeue, chx_init, chx_exit): Likewise.
|
||||||
|
(chopstx_mutex_init, chopstx_cond_init): Likewise.
|
||||||
|
* chopstx-cortex-m.c (chx_handle_intr): Use FOR_QUEUE macro.
|
||||||
|
* chopstx-gnu-linux.c (chx_handle_intr): Use FOR_QUEUE macro.
|
||||||
|
|
||||||
|
2021-10-12 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* VERSION: 1.20.
|
||||||
|
* doc/chopstx.texi (VERSION): 1.20.
|
||||||
|
|
||||||
|
2021-10-11 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
Backport from master.
|
||||||
|
* mcu/usb-usbip.c (URB_DATA_SIZE): Tweak the value.
|
||||||
|
|
||||||
2021-02-18 NIIBE Yutaka <gniibe@fsij.org>
|
2021-02-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
* VERSION: 1.19.
|
* VERSION: 1.19.
|
||||||
|
|||||||
19
NEWS
19
NEWS
@@ -1,6 +1,25 @@
|
|||||||
NEWS - Noteworthy changes
|
NEWS - Noteworthy changes
|
||||||
|
|
||||||
|
|
||||||
|
* Major changes in Chopstx 1.21
|
||||||
|
|
||||||
|
Released 2022-04-22
|
||||||
|
|
||||||
|
** Fix of struct chx_qh and struct chx_thread/pq/px.
|
||||||
|
|
||||||
|
Good compiler complains/warns for possible different size of
|
||||||
|
structures. To avoid this, access to the objects are fixed.
|
||||||
|
|
||||||
|
|
||||||
|
* Major changes in Chopstx 1.20
|
||||||
|
|
||||||
|
Released 2021-10-12
|
||||||
|
|
||||||
|
** Fix of USB driver for GNU/Linux emulation
|
||||||
|
|
||||||
|
Fix the value of URB_DATA_SIZE, so that Gnuk can work with PC/SC.
|
||||||
|
|
||||||
|
|
||||||
* Major changes in Chopstx 1.19
|
* Major changes in Chopstx 1.19
|
||||||
|
|
||||||
Released 2021-02-18
|
Released 2021-02-18
|
||||||
|
|||||||
12
README
12
README
@@ -1,6 +1,6 @@
|
|||||||
Chopstx - Threads and only Threads
|
Chopstx - Threads and only Threads
|
||||||
Version 1.19
|
Version 1.21
|
||||||
2021-02-18
|
2021-04-22
|
||||||
Niibe Yutaka
|
Niibe Yutaka
|
||||||
Flying Stone Technology
|
Flying Stone Technology
|
||||||
|
|
||||||
@@ -62,12 +62,4 @@ Future Works
|
|||||||
|
|
||||||
RISC-V port (for GD32VF103) is available in 2.x. Please have a look
|
RISC-V port (for GD32VF103) is available in 2.x. Please have a look
|
||||||
at the master branch, and test it if possible.
|
at the master branch, and test it if possible.
|
||||||
|
|
||||||
Convenience function to determine the bottom of thread stack,
|
|
||||||
configuration of thread size by compiler's output would be next things
|
|
||||||
to be done.
|
|
||||||
|
|
||||||
Experimental SMP port for Cortex-A7 is under development. For SMP,
|
|
||||||
more careful considerations for shared access to objects of struct
|
|
||||||
chx_pq is needed. So, modifications required will not be small.
|
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ chx_cpu_sched_unlock (void)
|
|||||||
void
|
void
|
||||||
chx_handle_intr (void)
|
chx_handle_intr (void)
|
||||||
{
|
{
|
||||||
struct chx_pq *p;
|
struct chx_qh *q;
|
||||||
register uint32_t irq_num;
|
register uint32_t irq_num;
|
||||||
|
|
||||||
asm volatile ("mrs %0, IPSR\n\t"
|
asm volatile ("mrs %0, IPSR\n\t"
|
||||||
@@ -276,16 +276,20 @@ chx_handle_intr (void)
|
|||||||
|
|
||||||
chx_disable_intr (irq_num);
|
chx_disable_intr (irq_num);
|
||||||
chx_spin_lock (&q_intr.lock);
|
chx_spin_lock (&q_intr.lock);
|
||||||
for (p = q_intr.q.next; p != (struct chx_pq *)&q_intr.q; p = p->next)
|
for (q = q_intr.q.next; q != &q_intr.q; q = q->next)
|
||||||
if (p->v == irq_num)
|
{
|
||||||
{ /* should be one at most. */
|
struct chx_pq *p = (struct chx_pq *)q;
|
||||||
struct chx_px *px = (struct chx_px *)p;
|
|
||||||
|
|
||||||
ll_dequeue (p);
|
if (p->v == irq_num)
|
||||||
chx_wakeup (p);
|
{ /* should be one at most. */
|
||||||
chx_request_preemption (px->master->prio);
|
struct chx_px *px = (struct chx_px *)p;
|
||||||
break;
|
|
||||||
}
|
ll_dequeue (p);
|
||||||
|
chx_wakeup (p);
|
||||||
|
chx_request_preemption (px->master->prio);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
chx_spin_unlock (&q_intr.lock);
|
chx_spin_unlock (&q_intr.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -154,21 +154,24 @@ idle (void)
|
|||||||
void
|
void
|
||||||
chx_handle_intr (uint32_t irq_num)
|
chx_handle_intr (uint32_t irq_num)
|
||||||
{
|
{
|
||||||
struct chx_pq *p;
|
struct chx_qh *q;
|
||||||
|
|
||||||
chx_disable_intr (irq_num);
|
chx_disable_intr (irq_num);
|
||||||
chx_spin_lock (&q_intr.lock);
|
chx_spin_lock (&q_intr.lock);
|
||||||
for (p = q_intr.q.next; p != (struct chx_pq *)&q_intr.q; p = p->next)
|
for (q = q_intr.q.next; q != &q_intr.q; q = q->next)
|
||||||
if (p->v == irq_num)
|
{
|
||||||
{ /* should be one at most. */
|
struct chx_pq *p = (struct chx_pq *)q;
|
||||||
struct chx_px *px = (struct chx_px *)p;
|
if (p->v == irq_num)
|
||||||
|
{ /* should be one at most. */
|
||||||
|
struct chx_px *px = (struct chx_px *)p;
|
||||||
|
|
||||||
ll_dequeue (p);
|
ll_dequeue (p);
|
||||||
chx_wakeup (p);
|
chx_wakeup (p);
|
||||||
chx_spin_unlock (&q_intr.lock);
|
chx_spin_unlock (&q_intr.lock);
|
||||||
chx_request_preemption (px->master->prio);
|
chx_request_preemption (px->master->prio);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
chx_spin_unlock (&q_intr.lock);
|
chx_spin_unlock (&q_intr.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
173
chopstx.c
173
chopstx.c
@@ -88,6 +88,9 @@ struct chx_queue {
|
|||||||
struct chx_spinlock lock;
|
struct chx_spinlock lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Forward declaration. */
|
||||||
|
struct chx_pq;
|
||||||
|
|
||||||
/* READY: priority queue. */
|
/* READY: priority queue. */
|
||||||
static struct chx_queue q_ready;
|
static struct chx_queue q_ready;
|
||||||
|
|
||||||
@@ -126,7 +129,7 @@ static void chx_spin_unlock (struct chx_spinlock *lk)
|
|||||||
|
|
||||||
/**************/
|
/**************/
|
||||||
struct chx_pq {
|
struct chx_pq {
|
||||||
struct chx_pq *next, *prev;
|
struct chx_qh q;
|
||||||
uint32_t : 4;
|
uint32_t : 4;
|
||||||
uint32_t : 5;
|
uint32_t : 5;
|
||||||
uint32_t : 6;
|
uint32_t : 6;
|
||||||
@@ -138,7 +141,7 @@ struct chx_pq {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct chx_px { /* inherits PQ */
|
struct chx_px { /* inherits PQ */
|
||||||
struct chx_pq *next, *prev;
|
struct chx_qh q;
|
||||||
uint32_t : 4;
|
uint32_t : 4;
|
||||||
uint32_t : 5;
|
uint32_t : 5;
|
||||||
uint32_t : 6;
|
uint32_t : 6;
|
||||||
@@ -154,7 +157,7 @@ struct chx_px { /* inherits PQ */
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct chx_thread { /* inherits PQ */
|
struct chx_thread { /* inherits PQ */
|
||||||
struct chx_pq *next, *prev;
|
struct chx_qh q;
|
||||||
uint32_t state : 4;
|
uint32_t state : 4;
|
||||||
uint32_t flag_detached : 1;
|
uint32_t flag_detached : 1;
|
||||||
uint32_t flag_got_cancel : 1;
|
uint32_t flag_got_cancel : 1;
|
||||||
@@ -180,63 +183,69 @@ struct chx_thread { /* inherits PQ */
|
|||||||
static int
|
static int
|
||||||
ll_empty (struct chx_qh *q)
|
ll_empty (struct chx_qh *q)
|
||||||
{
|
{
|
||||||
return q == (struct chx_qh *)q->next;
|
return q == q->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct chx_pq *
|
static struct chx_pq *
|
||||||
ll_dequeue (struct chx_pq *pq)
|
ll_dequeue (struct chx_pq *pq)
|
||||||
{
|
{
|
||||||
pq->next->prev = pq->prev;
|
pq->q.next->prev = pq->q.prev;
|
||||||
pq->prev->next = pq->next;
|
pq->q.prev->next = pq->q.next;
|
||||||
pq->prev = pq->next = pq;
|
pq->q.prev = pq->q.next = &pq->q;
|
||||||
return pq;
|
return pq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ll_insert (struct chx_pq *pq0, struct chx_qh *q)
|
ll_insert (struct chx_qh *q0, struct chx_qh *q)
|
||||||
{
|
{
|
||||||
struct chx_pq *pq = (struct chx_pq *)q;
|
q0->next = q;
|
||||||
|
q0->prev = q->prev;
|
||||||
pq0->next = (struct chx_pq *)pq;
|
q->prev->next = q0;
|
||||||
pq0->prev = pq->prev;
|
q->prev = q0;
|
||||||
pq->prev->next = (struct chx_pq *)pq0;
|
|
||||||
pq->prev = pq0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct chx_pq *
|
static struct chx_pq *
|
||||||
ll_pop (struct chx_qh *q)
|
ll_pop (struct chx_qh *q)
|
||||||
{
|
{
|
||||||
if (q == (struct chx_qh *)q->next)
|
if (q == q->next)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return ll_dequeue (q->next);
|
return ll_dequeue ((struct chx_pq *)q->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ll_prio_push (struct chx_pq *pq0, struct chx_qh *q0)
|
ll_prio_push (struct chx_pq *pq0, struct chx_qh *q0)
|
||||||
{
|
{
|
||||||
struct chx_pq *p;
|
struct chx_qh *q;
|
||||||
|
|
||||||
for (p = q0->next; p != (struct chx_pq *)q0; p = p->next)
|
for (q = q0->next; q != q0; q = q->next)
|
||||||
if (p->prio <= pq0->prio)
|
{
|
||||||
break;
|
struct chx_pq *p = (struct chx_pq *)q;
|
||||||
|
|
||||||
|
if (p->prio <= pq0->prio)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
pq0->parent = q0;
|
pq0->parent = q0;
|
||||||
ll_insert (pq0, (struct chx_qh *)p);
|
ll_insert (&pq0->q, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ll_prio_enqueue (struct chx_pq *pq0, struct chx_qh *q0)
|
ll_prio_enqueue (struct chx_pq *pq0, struct chx_qh *q0)
|
||||||
{
|
{
|
||||||
struct chx_pq *p;
|
struct chx_qh *q;
|
||||||
|
|
||||||
for (p = q0->next; p != (struct chx_pq *)q0; p = p->next)
|
for (q = q0->next; q != q0; q = q->next)
|
||||||
if (p->prio < pq0->prio)
|
{
|
||||||
break;
|
struct chx_pq *p = (struct chx_pq *)q;
|
||||||
|
|
||||||
|
if (p->prio < pq0->prio)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
pq0->parent = q0;
|
pq0->parent = q0;
|
||||||
ll_insert (pq0, (struct chx_qh *)p);
|
ll_insert (&pq0->q, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -308,29 +317,35 @@ chx_ready_enqueue (struct chx_thread *tp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
chx_set_timer (struct chx_thread *tp, uint32_t ticks)
|
chx_set_timer (struct chx_qh *q, uint32_t ticks)
|
||||||
{
|
{
|
||||||
if (tp == (struct chx_thread *)&q_timer.q)
|
if (q == &q_timer.q)
|
||||||
chx_systick_reload (ticks);
|
chx_systick_reload (ticks);
|
||||||
else
|
else
|
||||||
tp->v = ticks;
|
{
|
||||||
|
struct chx_thread *tp = (struct chx_thread *)q;
|
||||||
|
|
||||||
|
tp->v = ticks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct chx_thread *
|
static struct chx_thread *
|
||||||
chx_timer_insert (struct chx_thread *tp, uint32_t usec)
|
chx_timer_insert (struct chx_thread *tp, uint32_t usec)
|
||||||
{
|
{
|
||||||
struct chx_pq *p;
|
struct chx_qh *q;
|
||||||
uint32_t ticks = usec_to_ticks (usec);
|
uint32_t ticks = usec_to_ticks (usec);
|
||||||
uint32_t next_ticks = chx_systick_get ();
|
uint32_t next_ticks = chx_systick_get ();
|
||||||
|
|
||||||
for (p = q_timer.q.next; p != (struct chx_pq *)&q_timer.q; p = p->next)
|
for (q = q_timer.q.next; q != &q_timer.q; q = q->next)
|
||||||
{
|
{
|
||||||
|
struct chx_pq *p = (struct chx_pq *)q;
|
||||||
|
|
||||||
if (ticks < next_ticks)
|
if (ticks < next_ticks)
|
||||||
{
|
{
|
||||||
tp->parent = &q_timer.q;
|
tp->parent = &q_timer.q;
|
||||||
ll_insert ((struct chx_pq *)tp, (struct chx_qh *)p);
|
ll_insert (&tp->q, q);
|
||||||
chx_set_timer ((struct chx_thread *)tp->prev, ticks);
|
chx_set_timer (tp->q.prev, ticks);
|
||||||
chx_set_timer (tp, (next_ticks - ticks));
|
chx_set_timer (&tp->q, (next_ticks - ticks));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -340,12 +355,12 @@ chx_timer_insert (struct chx_thread *tp, uint32_t usec)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == (struct chx_pq *)&q_timer.q)
|
if (q == &q_timer.q)
|
||||||
{
|
{
|
||||||
tp->parent = &q_timer.q;
|
tp->parent = &q_timer.q;
|
||||||
ll_insert ((struct chx_pq *)tp, (struct chx_qh *)p);
|
ll_insert (&tp->q, q);
|
||||||
chx_set_timer ((struct chx_thread *)tp->prev, ticks);
|
chx_set_timer (tp->q.prev, ticks);
|
||||||
chx_set_timer (tp, 1); /* Non-zero for the last entry. */
|
chx_set_timer (&tp->q, 1); /* Non-zero for the last entry. */
|
||||||
}
|
}
|
||||||
|
|
||||||
return tp;
|
return tp;
|
||||||
@@ -355,25 +370,30 @@ chx_timer_insert (struct chx_thread *tp, uint32_t usec)
|
|||||||
static uint32_t
|
static uint32_t
|
||||||
chx_timer_dequeue (struct chx_thread *tp)
|
chx_timer_dequeue (struct chx_thread *tp)
|
||||||
{
|
{
|
||||||
struct chx_thread *tp_prev;
|
struct chx_qh *q_prev;
|
||||||
uint32_t ticks_remained;
|
uint32_t ticks_remained;
|
||||||
|
|
||||||
chx_spin_lock (&q_timer.lock);
|
chx_spin_lock (&q_timer.lock);
|
||||||
ticks_remained = chx_systick_get ();
|
ticks_remained = chx_systick_get ();
|
||||||
tp_prev = (struct chx_thread *)tp->prev;
|
q_prev = tp->q.prev;
|
||||||
if (tp_prev == (struct chx_thread *)&q_timer.q)
|
if (q_prev == &q_timer.q)
|
||||||
{
|
{
|
||||||
if (tp->next == (struct chx_pq *)&q_timer.q)
|
if (tp->q.next == &q_timer.q)
|
||||||
chx_systick_reload (0); /* Cancel timer. */
|
chx_systick_reload (0); /* Cancel timer. */
|
||||||
else
|
else
|
||||||
chx_systick_reload (ticks_remained + tp->v); /* Update timer. */
|
chx_systick_reload (ticks_remained + tp->v); /* Update timer. */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct chx_pq *p;
|
struct chx_thread *tp_prev = (struct chx_thread *)q_prev;
|
||||||
|
struct chx_qh *q;
|
||||||
|
|
||||||
for (p = q_timer.q.next; p != (struct chx_pq *)tp; p = p->next)
|
for (q = q_timer.q.next; q != &q_timer.q; q = q->next)
|
||||||
ticks_remained += p->v;
|
{
|
||||||
|
struct chx_pq *p = (struct chx_pq *)q;
|
||||||
|
|
||||||
|
ticks_remained += p->v;
|
||||||
|
}
|
||||||
|
|
||||||
tp_prev->v += tp->v;
|
tp_prev->v += tp->v;
|
||||||
}
|
}
|
||||||
@@ -406,15 +426,17 @@ chx_timer_expired (void)
|
|||||||
|
|
||||||
if (!ll_empty (&q_timer.q))
|
if (!ll_empty (&q_timer.q))
|
||||||
{
|
{
|
||||||
struct chx_thread *tp_next;
|
struct chx_qh *q, *q_next;
|
||||||
|
|
||||||
for (tp = (struct chx_thread *)q_timer.q.next;
|
for (q = q_timer.q.next;
|
||||||
tp != (struct chx_thread *)&q_timer.q && next_tick == 0;
|
q != &q_timer.q && next_tick == 0;
|
||||||
tp = tp_next)
|
q = q_next)
|
||||||
{
|
{
|
||||||
|
tp = (struct chx_thread *)q;
|
||||||
|
|
||||||
next_tick = tp->v;
|
next_tick = tp->v;
|
||||||
tp->v = (uintptr_t)0;
|
tp->v = (uintptr_t)0;
|
||||||
tp_next = (struct chx_thread *)tp->next;
|
q_next = tp->q.next;
|
||||||
ll_dequeue ((struct chx_pq *)tp);
|
ll_dequeue ((struct chx_pq *)tp);
|
||||||
chx_ready_enqueue (tp);
|
chx_ready_enqueue (tp);
|
||||||
if (tp == running)
|
if (tp == running)
|
||||||
@@ -425,7 +447,7 @@ chx_timer_expired (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!ll_empty (&q_timer.q))
|
if (!ll_empty (&q_timer.q))
|
||||||
chx_set_timer ((struct chx_thread *)&q_timer.q, next_tick);
|
chx_set_timer (&q_timer.q, next_tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,15 +482,15 @@ chx_init (struct chx_thread *tp)
|
|||||||
chx_init_arch (tp);
|
chx_init_arch (tp);
|
||||||
chx_spin_init (&chx_enable_sleep_lock);
|
chx_spin_init (&chx_enable_sleep_lock);
|
||||||
|
|
||||||
q_ready.q.next = q_ready.q.prev = (struct chx_pq *)&q_ready.q;
|
q_ready.q.next = q_ready.q.prev = &q_ready.q;
|
||||||
chx_spin_init (&q_ready.lock);
|
chx_spin_init (&q_ready.lock);
|
||||||
q_timer.q.next = q_timer.q.prev = (struct chx_pq *)&q_timer.q;
|
q_timer.q.next = q_timer.q.prev = &q_timer.q;
|
||||||
chx_spin_init (&q_timer.lock);
|
chx_spin_init (&q_timer.lock);
|
||||||
q_join.q.next = q_join.q.prev = (struct chx_pq *)&q_join.q;
|
q_join.q.next = q_join.q.prev = &q_join.q;
|
||||||
chx_spin_init (&q_join.lock);
|
chx_spin_init (&q_join.lock);
|
||||||
q_intr.q.next = q_intr.q.prev = (struct chx_pq *)&q_intr.q;
|
q_intr.q.next = q_intr.q.prev = &q_intr.q;
|
||||||
chx_spin_init (&q_intr.lock);
|
chx_spin_init (&q_intr.lock);
|
||||||
tp->next = tp->prev = (struct chx_pq *)tp;
|
tp->q.next = tp->q.prev = &tp->q;
|
||||||
tp->mutex_list = NULL;
|
tp->mutex_list = NULL;
|
||||||
tp->clp = NULL;
|
tp->clp = NULL;
|
||||||
tp->state = THREAD_RUNNING;
|
tp->state = THREAD_RUNNING;
|
||||||
@@ -542,20 +564,24 @@ chx_wakeup (struct chx_pq *pq)
|
|||||||
static void __attribute__((noreturn))
|
static void __attribute__((noreturn))
|
||||||
chx_exit (void *retval)
|
chx_exit (void *retval)
|
||||||
{
|
{
|
||||||
struct chx_pq *p;
|
struct chx_qh *q;
|
||||||
struct chx_thread *running = chx_running ();
|
struct chx_thread *running = chx_running ();
|
||||||
|
|
||||||
chx_cpu_sched_lock ();
|
chx_cpu_sched_lock ();
|
||||||
if (running->flag_join_req)
|
if (running->flag_join_req)
|
||||||
{ /* wake up a thread which requests to join */
|
{ /* wake up a thread which requests to join */
|
||||||
chx_spin_lock (&q_join.lock);
|
chx_spin_lock (&q_join.lock);
|
||||||
for (p = q_join.q.next; p != (struct chx_pq *)&q_join.q; p = p->next)
|
for (q = q_join.q.next; q != &q_join.q; q = q->next)
|
||||||
if (p->v == (uintptr_t)running)
|
{
|
||||||
{ /* should be one at most. */
|
struct chx_pq *p = (struct chx_pq *)q;
|
||||||
ll_dequeue (p);
|
|
||||||
chx_wakeup (p);
|
if (p->v == (uintptr_t)running)
|
||||||
break;
|
{ /* should be one at most. */
|
||||||
}
|
ll_dequeue (p);
|
||||||
|
chx_wakeup (p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
chx_spin_unlock (&q_join.lock);
|
chx_spin_unlock (&q_join.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,9 +625,14 @@ chx_mutex_unlock (chopstx_mutex_t *mutex)
|
|||||||
|
|
||||||
/* Examine mutexes we hold, and determine new priority for running. */
|
/* Examine mutexes we hold, and determine new priority for running. */
|
||||||
for (m = running->mutex_list; m; m = m->list)
|
for (m = running->mutex_list; m; m = m->list)
|
||||||
if (!ll_empty (&m->q)
|
if (!ll_empty (&m->q))
|
||||||
&& ((struct chx_thread *)(m->q.next))->prio > newprio)
|
{
|
||||||
newprio = ((struct chx_thread *)m->q.next)->prio;
|
struct chx_thread *tp_m = (struct chx_thread *)m->q.next;
|
||||||
|
uint16_t prio_m = tp_m->prio;
|
||||||
|
|
||||||
|
if (prio_m > newprio)
|
||||||
|
newprio = prio_m;
|
||||||
|
}
|
||||||
/* Then, assign it. */
|
/* Then, assign it. */
|
||||||
running->prio = newprio;
|
running->prio = newprio;
|
||||||
|
|
||||||
@@ -632,7 +663,7 @@ chopstx_create (uint32_t flags_and_prio,
|
|||||||
|
|
||||||
tp = chopstx_create_arch (stack_addr, stack_size, thread_entry,
|
tp = chopstx_create_arch (stack_addr, stack_size, thread_entry,
|
||||||
arg);
|
arg);
|
||||||
tp->next = tp->prev = (struct chx_pq *)tp;
|
tp->q.next = tp->q.prev = &tp->q;
|
||||||
tp->mutex_list = NULL;
|
tp->mutex_list = NULL;
|
||||||
tp->clp = NULL;
|
tp->clp = NULL;
|
||||||
tp->state = THREAD_EXITED;
|
tp->state = THREAD_EXITED;
|
||||||
@@ -744,7 +775,7 @@ void
|
|||||||
chopstx_mutex_init (chopstx_mutex_t *mutex)
|
chopstx_mutex_init (chopstx_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
chx_spin_init (&mutex->lock);
|
chx_spin_init (&mutex->lock);
|
||||||
mutex->q.next = mutex->q.prev = (struct chx_pq *)&mutex->q;
|
mutex->q.next = mutex->q.prev = &mutex->q;
|
||||||
mutex->list = NULL;
|
mutex->list = NULL;
|
||||||
mutex->owner = NULL;
|
mutex->owner = NULL;
|
||||||
}
|
}
|
||||||
@@ -880,7 +911,7 @@ void
|
|||||||
chopstx_cond_init (chopstx_cond_t *cond)
|
chopstx_cond_init (chopstx_cond_t *cond)
|
||||||
{
|
{
|
||||||
chx_spin_init (&cond->lock);
|
chx_spin_init (&cond->lock);
|
||||||
cond->q.next = cond->q.prev = (struct chx_pq *)&cond->q;
|
cond->q.next = cond->q.prev = &cond->q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1372,7 +1403,7 @@ chx_proxy_init (struct chx_px *px, uint32_t *cp)
|
|||||||
{
|
{
|
||||||
struct chx_thread *running = chx_running ();
|
struct chx_thread *running = chx_running ();
|
||||||
|
|
||||||
px->next = px->prev = (struct chx_pq *)px;
|
px->q.next = px->q.prev = &px->q;
|
||||||
px->flag_is_proxy = 1;
|
px->flag_is_proxy = 1;
|
||||||
px->prio = running->prio;
|
px->prio = running->prio;
|
||||||
px->parent = NULL;
|
px->parent = NULL;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct chx_qh {
|
struct chx_qh {
|
||||||
struct chx_pq *next, *prev;
|
struct chx_qh *next, *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uintptr_t chopstx_t;
|
typedef uintptr_t chopstx_t;
|
||||||
|
|||||||
@@ -66,6 +66,15 @@ ackbtn_init (chopstx_intr_t *intr)
|
|||||||
pin_config |= PINCFG_EDGE_RISING;
|
pin_config |= PINCFG_EDGE_RISING;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BOARD_ID_ST_DONGLE:
|
||||||
|
/* PA5 is connected to a switch */
|
||||||
|
afio_exticr_index = 0;
|
||||||
|
afio_exticr_extiX_pY = AFIO_EXTICR2_EXTI5_PA;
|
||||||
|
irq_num = EXTI9_5_IRQ;
|
||||||
|
pin_config = 0x0020; /* EXTI_PR_PR5 == EXTI_IMR_MR5 == EXTI_RTSR_TR5 */
|
||||||
|
pin_config |= PINCFG_EDGE_RISING;
|
||||||
|
break;
|
||||||
|
|
||||||
case BOARD_ID_FST_01SZ:
|
case BOARD_ID_FST_01SZ:
|
||||||
default:
|
default:
|
||||||
/* PA3 is connected to a hall sensor DRV5032FA */
|
/* PA3 is connected to a hall sensor DRV5032FA */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
\input texinfo @c -*-texinfo-*-
|
\input texinfo @c -*-texinfo-*-
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
@setfilename chopstx.info
|
@setfilename chopstx.info
|
||||||
@set VERSION 1.19
|
@set VERSION 1.21
|
||||||
@settitle Chopstx Reference Manual
|
@settitle Chopstx Reference Manual
|
||||||
@c Unify some of the indices.
|
@c Unify some of the indices.
|
||||||
@syncodeindex tp fn
|
@syncodeindex tp fn
|
||||||
|
|||||||
126
mcu/usb-usbip.c
126
mcu/usb-usbip.c
@@ -22,10 +22,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
FIXME:
|
* This driver is intended to emulate USB full-speed device, which
|
||||||
RESET handling
|
* maximum packet size is 64.
|
||||||
USB Shutdown
|
*
|
||||||
Use reply structure of its own
|
* "USBIP" is actually URB over network (instead of USB packet over
|
||||||
|
* network), and its (current) naive protocol may expose possible
|
||||||
|
* demarcation problem, which never occurs in real host-device; In
|
||||||
|
* real host-device relationship, it is host side, which does
|
||||||
|
* composition/decomposition of URB to/from packets. In an
|
||||||
|
* implmentation of USB device with USBIP, it needs to be device side,
|
||||||
|
* which does composition/decomposition of URB to/from packets.
|
||||||
|
*
|
||||||
|
* In this implementation of USB driver, URB_DATA_SIZE is defined as
|
||||||
|
* (65544+10), because (major) target device intended is CCID. In the
|
||||||
|
* CCID specification, you can find the value 65544+10.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* FIXME:
|
||||||
|
* RESET handling
|
||||||
|
* USB Shutdown
|
||||||
|
* Use reply structure of its own
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@@ -96,7 +112,7 @@ struct urb {
|
|||||||
struct urb *next;
|
struct urb *next;
|
||||||
struct urb *prev;
|
struct urb *prev;
|
||||||
|
|
||||||
uint16_t remain;
|
uint32_t remain;
|
||||||
char *data_p;
|
char *data_p;
|
||||||
|
|
||||||
pthread_t tid;
|
pthread_t tid;
|
||||||
@@ -236,7 +252,67 @@ attach_device (char busid[32], size_t *len_p)
|
|||||||
return (const char *)&usbip_usb_device;
|
return (const char *)&usbip_usb_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define URB_DATA_SIZE 65535
|
/*
|
||||||
|
* The number 65544 comes from ISO 7816-4, which defines data format
|
||||||
|
* of smartcard; CLS INS P1 P2 occupies four octets. Then, Lc-octet
|
||||||
|
* to represent size of command data block, then command data block.
|
||||||
|
* Lastly, Le-octet to represent size of response data block to be
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* /----- for CLS INS P1 P2
|
||||||
|
* |
|
||||||
|
* | /-- for Lc
|
||||||
|
* | |
|
||||||
|
* | | /-- for data block
|
||||||
|
* | | |
|
||||||
|
* | | | /-- for Le
|
||||||
|
* | | | |
|
||||||
|
* v v v v
|
||||||
|
* 4 + 3 + 65535 + 2 = 65544
|
||||||
|
*
|
||||||
|
* The number 10 comes from the CCID protocol specification; It is the
|
||||||
|
* header size of CCID. Besides, we can find the number 65544 in the
|
||||||
|
* CCID protocol specification, too.
|
||||||
|
*
|
||||||
|
* And... we have "AND ONE MORE" three times.
|
||||||
|
*
|
||||||
|
* We accept that, as Buddha did.
|
||||||
|
*
|
||||||
|
* There are different interpretations for the historical fact and the
|
||||||
|
* idiom. Most likely, nowadays, here, third-time is considered a
|
||||||
|
* strikeout, perhaps, due to popularity of baseball.
|
||||||
|
*/
|
||||||
|
#define URB_DATA_SIZE (65544+10+1+1+1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The reasons why there are "+1" three times.
|
||||||
|
*
|
||||||
|
* Wrong (1): +1, because of confusion of data size maximum.
|
||||||
|
* Wrong (2): +1, because of confusion of the size for Le.
|
||||||
|
* Wrong (3): +1, because of keeping applying old patch.
|
||||||
|
*
|
||||||
|
* Something like this may occur, unfortunately, in our world.
|
||||||
|
*
|
||||||
|
* We need to consider the real case of the max buffer size for
|
||||||
|
* libusb_bulk_transfer with CCID (let us call this "CASE_MAX").
|
||||||
|
*
|
||||||
|
* (1) Although the data size maximum (for all cases) is 65536, it
|
||||||
|
* only occurs when Le size is zero. In the particular case of
|
||||||
|
* CASE_MAX, it is actually 65535. When just applying the max value
|
||||||
|
* 65536, +1 occurs.
|
||||||
|
*
|
||||||
|
* (2) Although maximum size to represent Le is 3, it only occurs when
|
||||||
|
* Lc size is zero. In the particular case of CASE_MAX, it is
|
||||||
|
* actually 2. When just applying the max value 3, +1 occurs.
|
||||||
|
*
|
||||||
|
* (3) Fedora keeps a old patch for Ominikey 3121. The patch was
|
||||||
|
* written when the value of CMD_BUF_SIZE in libccid was small for
|
||||||
|
* short extended APDU exchange. In the patch, it uses the value 11
|
||||||
|
* for the header size (instead of 10) of TPDU, for its special
|
||||||
|
* support. Historically, CMD_BUF_SIZE in libccid was updated
|
||||||
|
* to bigger value to handle extended APDU exchange. When just applying
|
||||||
|
* the old patch using 11, +1 occurs.
|
||||||
|
*/
|
||||||
|
|
||||||
struct usbip_msg_cmd {
|
struct usbip_msg_cmd {
|
||||||
uint32_t devid;
|
uint32_t devid;
|
||||||
@@ -299,12 +375,14 @@ static int write_data_transaction (struct usb_control *usbc_p,
|
|||||||
static int read_data_transaction (struct usb_control *usbc_p,
|
static int read_data_transaction (struct usb_control *usbc_p,
|
||||||
int ep_num, char *buf, uint16_t count);
|
int ep_num, char *buf, uint16_t count);
|
||||||
|
|
||||||
|
#define USB_MAX_PACKET_SIZE 64 /* For USB fullspeed device. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hc_handle_control_urb (struct urb *urb)
|
hc_handle_control_urb (struct urb *urb)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
uint16_t remain = urb->len;
|
uint32_t remain = urb->len;
|
||||||
uint64_t l;
|
uint64_t l;
|
||||||
|
|
||||||
if ((debug & DEBUG_USB))
|
if ((debug & DEBUG_USB))
|
||||||
@@ -325,10 +403,10 @@ hc_handle_control_urb (struct urb *urb)
|
|||||||
|
|
||||||
while (r == 0)
|
while (r == 0)
|
||||||
{
|
{
|
||||||
if (remain > 64)
|
if (remain > USB_MAX_PACKET_SIZE)
|
||||||
count = 64;
|
count = USB_MAX_PACKET_SIZE;
|
||||||
else
|
else
|
||||||
count = remain;
|
count = (uint16_t)remain;
|
||||||
|
|
||||||
read (usbc_ep0.eventfd, &l, sizeof (l));
|
read (usbc_ep0.eventfd, &l, sizeof (l));
|
||||||
r = control_write_data_transaction (urb->data_p, count);
|
r = control_write_data_transaction (urb->data_p, count);
|
||||||
@@ -337,7 +415,7 @@ hc_handle_control_urb (struct urb *urb)
|
|||||||
|
|
||||||
urb->data_p += count;
|
urb->data_p += count;
|
||||||
remain -= count;
|
remain -= count;
|
||||||
if (count < 64)
|
if (count < USB_MAX_PACKET_SIZE)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
@@ -353,10 +431,10 @@ hc_handle_control_urb (struct urb *urb)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (remain > 64)
|
if (remain > USB_MAX_PACKET_SIZE)
|
||||||
count = 64;
|
count = USB_MAX_PACKET_SIZE;
|
||||||
else
|
else
|
||||||
count = remain;
|
count = (uint16_t)remain;
|
||||||
|
|
||||||
read (usbc_ep0.eventfd, &l, sizeof (l));
|
read (usbc_ep0.eventfd, &l, sizeof (l));
|
||||||
r = control_read_data_transaction (urb->data_p, count);
|
r = control_read_data_transaction (urb->data_p, count);
|
||||||
@@ -368,7 +446,7 @@ hc_handle_control_urb (struct urb *urb)
|
|||||||
|
|
||||||
remain -= r;
|
remain -= r;
|
||||||
urb->data_p += r;
|
urb->data_p += r;
|
||||||
if (r < 64)
|
if (r < USB_MAX_PACKET_SIZE)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,10 +594,10 @@ hc_handle_data_urb (struct usb_control *usbc_p)
|
|||||||
if ((debug & DEBUG_USB))
|
if ((debug & DEBUG_USB))
|
||||||
puts ("hc_hdu 0");
|
puts ("hc_hdu 0");
|
||||||
|
|
||||||
if (urb->remain > 64)
|
if (urb->remain > USB_MAX_PACKET_SIZE)
|
||||||
count = 64;
|
count = USB_MAX_PACKET_SIZE;
|
||||||
else
|
else
|
||||||
count = urb->remain;
|
count = (uint16_t)urb->remain;
|
||||||
|
|
||||||
if (urb->dir == USBIP_DIR_OUT)
|
if (urb->dir == USBIP_DIR_OUT)
|
||||||
{ /* Output from host to device. */
|
{ /* Output from host to device. */
|
||||||
@@ -533,7 +611,7 @@ hc_handle_data_urb (struct usb_control *usbc_p)
|
|||||||
urb->data_p += count;
|
urb->data_p += count;
|
||||||
urb->remain -= count;
|
urb->remain -= count;
|
||||||
|
|
||||||
if (urb->remain == 0 || count < 64)
|
if (urb->remain == 0 || count < USB_MAX_PACKET_SIZE)
|
||||||
{
|
{
|
||||||
size_t len = urb->len - urb->remain;
|
size_t len = urb->len - urb->remain;
|
||||||
|
|
||||||
@@ -565,7 +643,7 @@ hc_handle_data_urb (struct usb_control *usbc_p)
|
|||||||
|
|
||||||
urb->remain -= r;
|
urb->remain -= r;
|
||||||
urb->data_p += r;
|
urb->data_p += r;
|
||||||
if (urb->remain == 0 || r < 64)
|
if (urb->remain == 0 || r < USB_MAX_PACKET_SIZE)
|
||||||
{
|
{
|
||||||
size_t len = urb->len - urb->remain;
|
size_t len = urb->len - urb->remain;
|
||||||
|
|
||||||
@@ -596,7 +674,7 @@ issue_get_desc (void)
|
|||||||
{
|
{
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
|
|
||||||
urb = malloc (sizeof (struct urb) + 64);
|
urb = malloc (sizeof (struct urb) + USB_MAX_PACKET_SIZE);
|
||||||
|
|
||||||
urb->next = urb->prev = urb;
|
urb->next = urb->prev = urb;
|
||||||
|
|
||||||
@@ -606,14 +684,14 @@ issue_get_desc (void)
|
|||||||
urb->setup[3] = 1; /* Value H: desc_type */
|
urb->setup[3] = 1; /* Value H: desc_type */
|
||||||
urb->setup[4] = 0; /* Index */
|
urb->setup[4] = 0; /* Index */
|
||||||
urb->setup[5] = 0;
|
urb->setup[5] = 0;
|
||||||
urb->setup[6] = 64; /* Length */
|
urb->setup[6] = USB_MAX_PACKET_SIZE; /* Length */
|
||||||
urb->setup[7] = 0;
|
urb->setup[7] = 0;
|
||||||
urb->data_p = urb->data;
|
urb->data_p = urb->data;
|
||||||
urb->seq = 0;
|
urb->seq = 0;
|
||||||
urb->devid = 0;
|
urb->devid = 0;
|
||||||
urb->dir = USBIP_DIR_IN;
|
urb->dir = USBIP_DIR_IN;
|
||||||
urb->ep = 0;
|
urb->ep = 0;
|
||||||
urb->remain = urb->len = 64;
|
urb->remain = urb->len = USB_MAX_PACKET_SIZE;
|
||||||
hc_handle_control_urb (urb);
|
hc_handle_control_urb (urb);
|
||||||
return urb;
|
return urb;
|
||||||
}
|
}
|
||||||
@@ -729,7 +807,7 @@ usbip_handle_urb (uint32_t seq)
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
msg.cmd = htonl (REP_URB_SUBMIT);
|
msg.cmd = htonl (REP_URB_SUBMIT);
|
||||||
msg.seq = htonl (urb->seq);
|
msg.seq = htonl (seq);
|
||||||
|
|
||||||
memset (&msg_rep, 0, sizeof (msg_rep));
|
memset (&msg_rep, 0, sizeof (msg_rep));
|
||||||
msg_rep.status = htonl (r);
|
msg_rep.status = htonl (r);
|
||||||
|
|||||||
Reference in New Issue
Block a user