15 Commits

Author SHA1 Message Date
NIIBE Yutaka
9977bac715 Version 2.3.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-10-12 11:09:38 +09:00
NIIBE Yutaka
446e31a7c4 usbip: Fix the value of URB_DATA_SIZE again.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-10-11 10:22:19 +09:00
NIIBE Yutaka
f10cdce66c more fix for libccid.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-10-04 13:58:44 +09:00
NIIBE Yutaka
86ccc02be7 Fix USB emulation driver for GNU/Linux.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-10-04 10:05:45 +09:00
NIIBE Yutaka
d36e9274b1 Add comment for chopstx_mutex_lock.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-10-04 09:26:50 +09:00
NIIBE Yutaka
5a3a3e98d4 Version 2.2.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-26 09:16:49 +09:00
NIIBE Yutaka
7ad2c9030a One more change for Cortex-M3/M4 asm for shorter result.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-26 09:15:18 +09:00
NIIBE Yutaka
a70b1acbf6 Change asm for Cortex-M0/3/4.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-25 12:52:26 +09:00
NIIBE Yutaka
fd8bb46b8b Fix for Cortex-M0.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-25 10:35:29 +09:00
NIIBE Yutaka
95fe257dc0 cortex-m: Fix chx_handle_intr.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-19 15:56:43 +09:00
NIIBE Yutaka
2fb3c1c503 GNU/Linux: Use getrandom for ADC driver.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-17 16:24:22 +09:00
NIIBE Yutaka
f84f6c1cac GNU/Linux: Add start-up message for USB driver.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-17 10:29:08 +09:00
NIIBE Yutaka
68b78a0ade GNU/Linux: Fix AckBtn driver, again.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-17 10:12:08 +09:00
NIIBE Yutaka
8c48b0d7d3 GNU/Linux: Fix AckBtn driver.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-17 09:53:49 +09:00
NIIBE Yutaka
b3c35aebdd Add new driver for AckBtn for GNU/Linux emulation.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-17 09:47:19 +09:00
13 changed files with 481 additions and 90 deletions

View File

@@ -1,3 +1,50 @@
2021-10-12 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 2.3
* doc/chopstx.texi (VERSION): 2.3.
2021-10-11 NIIBE Yutaka <gniibe@fsij.org>
* mcu/usb-usbip.c (URB_DATA_SIZE): Tweak the value.
2021-02-26 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 2.2
* doc/chopstx.texi (VERSION): 2.2.
2021-02-25 NIIBE Yutaka <gniibe@fsij.org>
* rules.mk (MCFLAGS): Add -masm-syntax-unified.
* entry-cortex-m.c (entry): Use Thumb-16 instruction in unified
asm syntax. This means that no output change for Cortex-M0,
but change for Cortex-M3/M4 (shorter, different semantics).
* example-fsm-55/reset.c (reset): Likewise.
* chopstx-cortex-m.c
[__ARM_ARCH_6M__] (involuntary_context_switch): Use unified syntax.
[__ARM_ARCH_7M__] (involuntary_context_switch): Use Thumb-16
instruction.
[__ARM_ARCH_6M__] (chx_handle_intr): Use unified syntax.
[__ARM_ARCH_7M__] (chx_handle_intr): Use Thumb-16 instruction.
[__ARM_ARCH_6M__] (voluntary_context_switch): Use unified syntax.
[__ARM_ARCH_7M__] (svc): Use Thumb-16 instruction.
2021-02-19 NIIBE Yutaka <gniibe@fsij.org>
* chopstx-cortex-m.c (chx_handle_intr): Fix SUB instruction.
2021-02-17 NIIBE Yutaka <gniibe@fsij.org>
* contrib/adc-gnu-linux.c (adc_start_conversion): Use getrandom.
* mcu/usb-usbip.c (usbip_run_server): Add start-up message.
2021-02-16 NIIBE Yutaka <gniibe@fsij.org>
* contrib/ackbtn-gnu-linux.c: New.
2021-02-12 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 2.1

29
NEWS
View File

@@ -1,6 +1,33 @@
NEWS - Noteworthy changes
* Major changes in Chopstx 2.3
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 2.2
Released 2021-02-25
** Acknowledge button support for GNU/Linux emulation
User is asked acknowledge by RET with standard input.
** USB driver for GNU/Linux emulation
It shows start-up message now.
** ADC driver for GNU/Linux emulation
It uses getrandom(2), output is not deterministic any more.
** Bug fix for Cortex-M3/M4 Support
In 2.1, preemption doesn't work well, because of the difference of
assembler syntax.
* Major changes in Chopstx 2.1
Released 2021-02-12
@@ -17,7 +44,7 @@ In 2.0, GNU/Linux emulation doesn't work well with chx_idle when it
handles interrupt synchronously and the waken thread is the same one
which called chx_idle.
** Bug fix for Cortex-M0/Cortex-M3 Support
** Bug fix for Cortex-M0/M3/M4 Support
In 2.0, Cortex-M0 with no tail-chaining support (e.g. STM32F030)
doesn't work. In 2.0, Cortex-M3/M4 may fail when two or more
interrupts occur simultaneously; A waken thread (which is about to

15
README
View File

@@ -1,6 +1,6 @@
Chopstx - Threads and only Threads
Version 2.0
2020-06-26
Version 2.3
2021-10-12
Niibe Yutaka
Flying Stone Technology
@@ -9,7 +9,7 @@ What's Chopstx?
Chopstx is an RT thread library for STM32F103 and GD32F103 (ARM
Cortex-M3), STM32F030 (ARM Cortex-M0), MKL27Z (ARM Cortex-M0plus),
STM32L432 (ARM Cortex-M4), GD32V103 (RISC-V Bumblebee) and emulation
STM32L432 (ARM Cortex-M4), GD32VF103 (RISC-V Bumblebee) and emulation
on GNU/Linux.
While most RTOSes come with many features, drivers, and protocol
@@ -28,7 +28,8 @@ Note that this library is _not_ related to the hand game:
https://en.wikipedia.org/wiki/Chopsticks_(hand_game)
Thanks to Yao Wei and Enrico Zini for giving me an opportunity
visiting the wiki page above, when my children were playing the game.
visiting the wiki page above in Debconf Taiwan, when my children were
playing the game.
License
@@ -65,7 +66,7 @@ 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.
We have an experimental SMP port for Cortex-A7. For SMP, more careful
considerations for shared access to objects of struct chx_pq is
needed. So, modifications required will not be small.
--

View File

@@ -1 +1 @@
release/2.1
release/2.3

View File

@@ -272,7 +272,7 @@ involuntary_context_switch (struct chx_thread *tp_next)
{
/* Save registers onto CHX_THREAD struct. */
asm volatile (
"add %0, #20\n\t"
"adds %0, #20\n\t"
"stm %0!, {r4, r5, r6, r7}\n\t"
"mov r2, r8\n\t"
"mov r3, r9\n\t"
@@ -287,7 +287,7 @@ involuntary_context_switch (struct chx_thread *tp_next)
* works. R7 keeps its value, but having "r7" here prevents
* use of R7 before this asm statement.
*/
: "r2", "r3", "r4", "r5", "r6", "r7", "memory");
: "cc", "r2", "r3", "r4", "r5", "r6", "r7", "memory");
tp_next = chx_running_preempted (tp_next);
}
@@ -301,7 +301,7 @@ involuntary_context_switch (struct chx_thread *tp_next)
/* Update running: chx_set_running */
"str r0, [r1]\n\t"
/**/
"add r0, #20\n\t"
"adds r0, #20\n\t"
"ldm r0!, {r4, r5, r6, r7}\n\t"
#if defined(__ARM_ARCH_6M__)
"ldm r0!, {r1, r2, r3}\n\t"
@@ -319,8 +319,8 @@ involuntary_context_switch (struct chx_thread *tp_next)
"ldr r1, [r0], #4\n\t"
"msr PSP, r1\n\t"
#endif
"mov r0, #0\n\t"
"sub r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
"movs r0, #0\n\t"
"subs r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
"bx r0"
: /* no output */ : "r" (tp_next) : "memory");
}
@@ -334,14 +334,15 @@ chx_handle_intr (void)
register struct chx_thread *tp_next asm ("r0");;
asm volatile ("mrs %0, IPSR\n\t"
"sub %0, #16\n\t" /* Exception # - 16 = interrupt number. */
/* Exception # - 16 = interrupt number. */
"subs %0, #16\n\t"
"bpl 0f\n\t"
"bl chx_timer_expired\n\t"
"b 1f\n"
"0:\n\t"
"bl chx_recv_irq\n"
"1:"
: "=r" (tp_next) : /* no input */ : "memory");
: "=r" (tp_next) : /* no input */ : "cc", "memory");
if (tp_next)
asm volatile (
@@ -349,8 +350,8 @@ chx_handle_intr (void)
: /*no input */ : /* no input */ : "memory");
else
asm volatile (
"mov r0, #0\n\t"
"sub r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
"movs r0, #0\n\t"
"subs r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
"bx r0"
: /*no input */ : /* no input */ : "memory");
}
@@ -392,10 +393,10 @@ voluntary_context_switch (struct chx_thread *tp_next)
*/
asm ("mov %0, lr\n\t"
"ldr r2, =.L_CONTEXT_SWITCH_FINISH\n\t"
"mov r3, #128\n\t"
"lsl r3, #17\n\t"
"movs r3, #128\n\t"
"lsls r3, #17\n\t"
"push {%0, r2, r3}\n\t"
"mov %0, #0\n\t"
"movs %0, #0\n\t"
"mov r2, %0\n\t"
"mov r3, %0\n\t"
"push {%0, r2, r3}\n\t"
@@ -404,10 +405,10 @@ voluntary_context_switch (struct chx_thread *tp_next)
"push {%0, r3}\n\t"
: "=r" (tp)
: /* no input */
: "r2", "r3", "memory");
: "cc", "r2", "r3", "memory");
/* Save registers onto CHX_THREAD struct. */
asm ("add r1, #20\n\t"
asm ("adds r1, #20\n\t"
"stm r1!, {r4, r5, r6, r7}\n\t"
"mov r2, r8\n\t"
"mov r3, r9\n\t"
@@ -415,10 +416,10 @@ voluntary_context_switch (struct chx_thread *tp_next)
"mov r5, r11\n\t"
"mov r6, sp\n\t"
"stm r1!, {r2, r3, r4, r5, r6}\n\t"
"sub r1, #56"
"subs r1, #56"
: /* no output */
: "r" (tp)
: "r2", "r3", "r4", "r5", "r6", "r7", "memory");
: "cc", "r2", "r3", "r4", "r5", "r6", "r7", "memory");
asm volatile (/* Now, r0 points to the thread to be switched. */
/* Put it to *running. */
@@ -439,7 +440,7 @@ voluntary_context_switch (struct chx_thread *tp_next)
/* Normal context switch */
"0:\n\t"
"add r0, #20\n\t"
"adds r0, #20\n\t"
"ldm r0!, {r4, r5, r6, r7}\n\t"
"ldm r0!, {r1, r2, r3}\n\t"
"mov r8, r1\n\t"
@@ -464,12 +465,12 @@ voluntary_context_switch (struct chx_thread *tp_next)
[28 or 32] <-- pc
*/
"ldr r0, [sp, #28]\n\t"
"lsl r1, r0, #23\n\t"
"lsls r1, r0, #23\n\t"
"bcc 2f\n\t"
/**/
"ldr r2, [sp, #24]\n\t"
"mov r1, #1\n\t"
"orr r2, r1\n\t" /* Ensure Thumb-mode */
"movs r1, #1\n\t"
"orrs r2, r1\n\t" /* Ensure Thumb-mode */
"str r2, [sp, #32]\n\t"
"msr APSR_nzcvq, r0\n\t"
/**/
@@ -482,8 +483,8 @@ voluntary_context_switch (struct chx_thread *tp_next)
"pop {pc}\n"
"2:\n\t"
"ldr r2, [sp, #24]\n\t"
"mov r1, #1\n\t"
"orr r2, r1\n\t" /* Ensure Thumb-mode */
"movs r1, #1\n\t"
"orrs r2, r1\n\t" /* Ensure Thumb-mode */
"str r2, [sp, #28]\n\t"
"msr APSR_nzcvq, r0\n\t"
/**/
@@ -495,11 +496,11 @@ voluntary_context_switch (struct chx_thread *tp_next)
"add sp, #12\n\t"
"pop {pc}\n\t"
".L_CONTEXT_SWITCH_FINISH:\n\t"
"add r0, #16\n\t"
"adds r0, #16\n\t"
"ldr r0, [r0]" /* Get tp->v */
: "=r" (result) /* Return value in R0 */
: "0" (tp_next)
: "memory");
: "cc", "memory");
#endif
return result;
}
@@ -548,7 +549,7 @@ svc (void)
asm ("ldr r1, =running\n\t"
"ldr r1, [r1]\n\t"
"add r1, #20\n\t"
"adds r1, #20\n\t"
/* Save registers onto CHX_THREAD struct. */
"stm r1!, {r4, r5, r6, r7}\n\t"
"mov r2, r8\n\t"
@@ -558,11 +559,11 @@ svc (void)
"mrs r6, PSP\n\t" /* r13(=SP) in user space. */
"stm r1!, {r2, r3, r4, r5, r6}\n\t"
"ldr r0, [r6]\n\t"
"sub r1, #56\n\t"
"subs r1, #56\n\t"
"str r1, [r6]"
: "=r" (tp_next)
: /* no input */
: "r1", "r2", "r3", "r4", "r5", "r6", "memory");
: "cc", "r1", "r2", "r3", "r4", "r5", "r6", "memory");
asm volatile (
/* Now, r0 points to the thread to be switched. */
@@ -572,7 +573,7 @@ svc (void)
"str r0, [r1]\n\t"
"cbz r0, 1f\n\t"
/**/
"add r0, #20\n\t"
"adds r0, #20\n\t"
"ldm r0!, {r4, r5, r6, r7}\n\t"
"ldr r8, [r0], #4\n\t"
"ldr r9, [r0], #4\n\t"
@@ -581,27 +582,27 @@ svc (void)
"ldr r1, [r0], #4\n\t"
"msr PSP, r1\n\t"
/* Unmask interrupts. */
"mov r0, #0\n\t"
"movs r0, #0\n\t"
"msr BASEPRI, r0\n\t"
"sub r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
"subs r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
"bx r0\n"
"1:\n\t"
/* Spawn an IDLE thread. */
"ldr r0, =__main_stack_end__-32\n\t"
"msr PSP, r0\n\t"
"mov r1, #0\n\t"
"mov r2, #0\n\t"
"mov r3, #0\n\t"
"movs r1, #0\n\t"
"movs r2, #0\n\t"
"movs r3, #0\n\t"
"stm r0!, {r1, r2, r3}\n\t"
"stm r0!, {r1, r2, r3}\n\t"
"ldr r1, =chx_idle\n\t" /* PC = idle */
"mov r2, #0x010\n\t"
"lsl r2, r2, #20\n\t" /* xPSR = T-flag set (Thumb) */
"movs r2, #0x010\n\t"
"lsls r2, r2, #20\n\t" /* xPSR = T-flag set (Thumb) */
"stm r0!, {r1, r2}\n\t"
/* Unmask interrupts. */
"mov r0, #0\n\t"
"movs r0, #0\n\t"
"msr BASEPRI, r0\n"
"sub r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
"subs r0, #3\n\t" /* EXC_RETURN to a thread with PSP */
"bx r0"
: /* no output */ : "r" (tp_next) : "memory");
}

View File

@@ -949,7 +949,9 @@ chopstx_mutex_lock (chopstx_mutex_t *mutex)
* chopstx_mutex_unlock - Unlock the mutex
* @mutex: Mutex
*
* Unlock @mutex.
* Unlock @mutex. Note that Chopstx doesn't allow unlocking by
* non-owner of the lock. chopstx_mutex_unlock should be called
* by a thread which did chopstx_mutex_lock.
*/
void
chopstx_mutex_unlock (chopstx_mutex_t *mutex)

232
contrib/ackbtn-gnu-linux.c Normal file
View File

@@ -0,0 +1,232 @@
/*
* ackbtn-gnu-linux.c - Acknowledge button support for GNU/Linux
*
* Copyright (C) 2021 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Chopstx, a thread library for embedded.
*
* Chopstx is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Chopstx is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* As additional permission under GNU GPL version 3 section 7, you may
* distribute non-source form of the Program without the copy of the
* GNU GPL normally required by section 4, provided you inform the
* recipients of GNU GPL by a written offer.
*
*/
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <chopstx.h>
#include <stdio.h>
#include <signal.h>
#include <sys/eventfd.h>
#include <poll.h>
#include <errno.h>
#include <stdlib.h>
static pthread_t tid_main;
static pthread_t tid_ui;
static pthread_mutex_t mutex;
static pthread_cond_t cond;
static int enabled;
static int event_fd;
static void
ackbtn_intr (int signum, siginfo_t *siginfo, void *arg)
{
extern void chx_sigmask (ucontext_t *uc);
extern void chx_handle_intr (int signum);
ucontext_t *uc = arg;
(void)signum;
(void)siginfo;
chx_handle_intr (SIGUSR2);
chx_sigmask (uc);
}
#define ACKBTN_ACKED (1 << 0)
#define ACKBTN_TIMEOUT (1 << 2)
static void *
user_interaction (void *arg)
{
struct pollfd pollfds[2];
(void)arg;
pollfds[0].fd = 0; /* standard input */
pollfds[0].events = POLLIN;
pollfds[1].fd = event_fd;
pollfds[1].events = POLLIN;
fputs ("User interaction thread for AckBtn started.\n", stdout);
while (1)
{
unsigned int acked_or_timeout = 0;
char buf[256];
pthread_mutex_lock (&mutex);
while (!enabled)
pthread_cond_wait (&cond, &mutex);
pthread_mutex_unlock (&mutex);
/* Consume all input if any. */
while (1)
{
int r;
pollfds[0].revents = 0;
r = poll (pollfds, 1, 0);
if (r < 0)
{
if (errno == EINTR)
continue;
perror ("poll");
exit (1);
}
if (r == 0)
break;
if ((pollfds[0].revents & POLLIN))
read (0, buf, sizeof buf);
}
fputs ("Type RET to acknowledge (or wait for timeout) > ", stdout);
fflush (stdout);
while (!acked_or_timeout)
{
pollfds[0].revents = 0;
pollfds[1].revents = 0;
if (poll (pollfds, 2, -1) < 0)
{
if (errno == EINTR)
continue;
perror ("poll");
exit (1);
}
if ((pollfds[0].revents & POLLIN))
{
read (0, buf, sizeof buf);
acked_or_timeout |= ACKBTN_ACKED;
}
if ((pollfds[1].revents & POLLIN))
acked_or_timeout |= ACKBTN_TIMEOUT;
}
pthread_mutex_lock (&mutex);
if ((acked_or_timeout & ACKBTN_ACKED))
{
if ((acked_or_timeout & ACKBTN_TIMEOUT))
/* No output of newline, as it follows timeout message. */
fputs ("Input ignored", stdout);
else
{
pthread_kill (tid_main, SIGUSR2);
fputs ("Acknowledged\n", stdout);
}
}
if ((acked_or_timeout & ACKBTN_TIMEOUT))
fputs ("\nTimeout\n", stdout);
while (enabled)
pthread_cond_wait (&cond, &mutex);
read (event_fd, buf, sizeof (uint64_t));
pthread_mutex_unlock (&mutex);
}
}
void
ackbtn_init (chopstx_intr_t *intr)
{
int r;
sigset_t sigset;
struct sigaction act;
event_fd = eventfd (0, EFD_CLOEXEC);
if (event_fd < 0)
{
perror ("eventfd");
exit (1);
}
pthread_mutex_init (&mutex, NULL);
pthread_cond_init (&cond, NULL);
enabled = 0;
sigemptyset (&sigset);
sigaddset (&sigset, SIGUSR2);
sigaddset (&sigset, SIGALRM);
tid_main = pthread_self ();
/* Launch the thread for user interaction. */
pthread_sigmask (SIG_BLOCK, &sigset, NULL);
r = pthread_create (&tid_ui, NULL, user_interaction, NULL);
if (r)
{
fprintf (stderr, "ackbtn_init: %s\n", strerror (r));
exit (1);
}
act.sa_sigaction = ackbtn_intr;
sigfillset (&act.sa_mask);
act.sa_flags = SA_SIGINFO|SA_RESTART;
sigaction (SIGUSR2, &act, NULL);
pthread_sigmask (SIG_UNBLOCK, &sigset, NULL);
chopstx_claim_irq (intr, SIGUSR2);
}
void
ackbtn_enable (void)
{
pthread_mutex_lock (&mutex);
enabled = 1;
pthread_cond_signal (&cond);
pthread_mutex_unlock (&mutex);
}
void
ackbtn_disable (void)
{
const uint64_t l = 1;
pthread_mutex_lock (&mutex);
enabled = 0;
write (event_fd, &l, sizeof (l));
pthread_cond_signal (&cond);
pthread_mutex_unlock (&mutex);
}

View File

@@ -3,7 +3,7 @@
* This ADC driver just fills pseudo random values.
* It's completely useless other than for NeuG.
*
* Copyright (C) 2017 Free Software Initiative of Japan
* Copyright (C) 2017, 2021 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Chopstx, a thread library for embedded.
@@ -33,7 +33,7 @@
#include <chopstx.h>
#include "adc.h"
#define ADC_RANDOM_SEED 0x01034649 /* "Hello, father!" in Japanese */
#include <sys/random.h>
/*
* Do calibration for ADC.
@@ -41,7 +41,6 @@
int
adc_init (void)
{
srandom (ADC_RANDOM_SEED);
return 0;
}
@@ -55,8 +54,7 @@ uint32_t adc_buf[64];
void
adc_start_conversion (int offset, int count)
{
while (count--)
adc_buf[offset++] = random ();
getrandom (adc_buf+offset, count, 0);
}

View File

@@ -1,7 +1,7 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename chopstx.info
@set VERSION 2.1
@set VERSION 2.3
@settitle Chopstx Reference Manual
@c Unify some of the indices.
@syncodeindex tp fn

View File

@@ -113,7 +113,7 @@ entry (void)
{
asm volatile ("bl clock_init\n\t"
/* Clear BSS section. */
"mov r0, #0\n\t"
"movs r0, #0\n\t"
"ldr r1, =_bss_start\n\t"
"ldr r2, =_bss_end\n"
"0:\n\t"
@@ -121,7 +121,7 @@ entry (void)
"beq 1f\n\t"
#if defined(__ARM_ARCH_6M__)
"str r0, [r1]\n\t"
"add r1, #4\n\t"
"adds r1, #4\n\t"
#else
"str r0, [r1], #4\n\t"
#endif
@@ -137,8 +137,8 @@ entry (void)
#if defined(__ARM_ARCH_6M__)
"ldr r0, [r3]\n\t"
"str r0, [r1]\n\t"
"add r3, #4\n\t"
"add r1, #4\n\t"
"adds r3, #4\n\t"
"adds r1, #4\n\t"
#else
"ldr r0, [r3], #4\n\t"
"str r0, [r1], #4\n\t"
@@ -147,9 +147,9 @@ entry (void)
"3:\n\t"
/* Switch to PSP. */
"ldr r0, =__process0_stack_end__\n\t"
COMPOSE_STATEMENT ("sub r0, #", CHOPSTX_THREAD_SIZE, "\n\t")
COMPOSE_STATEMENT ("subs r0, #", CHOPSTX_THREAD_SIZE, "\n\t")
"msr PSP, r0\n\t" /* Process (main routine) stack. */
"mov r1, #2\n\t"
"movs r1, #2\n\t"
"msr CONTROL, r1\n\t"
"isb\n\t"
"bl chx_init\n\t"
@@ -157,7 +157,7 @@ entry (void)
"bl gpio_init\n\t"
/* Enable interrupts. */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
"mov r0, #0\n\t"
"movs r0, #0\n\t"
"msr BASEPRI, r0\n\t"
#endif
"cpsie i\n\t"

View File

@@ -19,10 +19,10 @@ reset (void)
{
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
"mov r0, pc\n\t" /* r0 = PC & ~0x0fff */
"mov r1, #0x10\n\t"
"lsl r1, #8\n\t"
"sub r1, r1, #1\n\t"
"bic r0, r0, r1\n\t"
"movs r1, #0x10\n\t"
"lsls r1, #8\n\t"
"subs r1, #1\n\t"
"bics r0, r0, r1\n\t"
"ldr r2, [r0]\n\t"
"msr MSP, r2\n\t" /* Main (exception handler) stack. */
"b entry\n\t"

View File

@@ -1,7 +1,7 @@
/*
* usb-usbip.c - USB Device Emulation (server side) by USBIP
*
* Copyright (C) 2017, 2018 g10 Code GmbH
* Copyright (C) 2017, 2018, 2021 g10 Code GmbH
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Chopstx, a thread library for embedded.
@@ -22,10 +22,26 @@
*/
/*
FIXME:
RESET handling
USB Shutdown
Use reply structure of its own
* This driver is intended to emulate USB full-speed device, which
* maximum packet size is 64.
*
* "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>
@@ -96,7 +112,7 @@ struct urb {
struct urb *next;
struct urb *prev;
uint16_t remain;
uint32_t remain;
char *data_p;
pthread_t tid;
@@ -236,7 +252,67 @@ attach_device (char busid[32], size_t *len_p)
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 {
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,
int ep_num, char *buf, uint16_t count);
#define USB_MAX_PACKET_SIZE 64 /* For USB fullspeed device. */
static int
hc_handle_control_urb (struct urb *urb)
{
int r;
uint16_t count;
uint16_t remain = urb->len;
uint32_t remain = urb->len;
uint64_t l;
if ((debug & DEBUG_USB))
@@ -325,10 +403,10 @@ hc_handle_control_urb (struct urb *urb)
while (r == 0)
{
if (remain > 64)
count = 64;
if (remain > USB_MAX_PACKET_SIZE)
count = USB_MAX_PACKET_SIZE;
else
count = remain;
count = (uint16_t)remain;
read (usbc_ep0.eventfd, &l, sizeof (l));
r = control_write_data_transaction (urb->data_p, count);
@@ -337,7 +415,7 @@ hc_handle_control_urb (struct urb *urb)
urb->data_p += count;
remain -= count;
if (count < 64)
if (count < USB_MAX_PACKET_SIZE)
break;
}
if (r >= 0)
@@ -353,10 +431,10 @@ hc_handle_control_urb (struct urb *urb)
while (1)
{
if (remain > 64)
count = 64;
if (remain > USB_MAX_PACKET_SIZE)
count = USB_MAX_PACKET_SIZE;
else
count = remain;
count = (uint16_t)remain;
read (usbc_ep0.eventfd, &l, sizeof (l));
r = control_read_data_transaction (urb->data_p, count);
@@ -368,7 +446,7 @@ hc_handle_control_urb (struct urb *urb)
remain -= r;
urb->data_p += r;
if (r < 64)
if (r < USB_MAX_PACKET_SIZE)
break;
}
@@ -516,10 +594,10 @@ hc_handle_data_urb (struct usb_control *usbc_p)
if ((debug & DEBUG_USB))
puts ("hc_hdu 0");
if (urb->remain > 64)
count = 64;
if (urb->remain > USB_MAX_PACKET_SIZE)
count = USB_MAX_PACKET_SIZE;
else
count = urb->remain;
count = (uint16_t)urb->remain;
if (urb->dir == USBIP_DIR_OUT)
{ /* Output from host to device. */
@@ -533,7 +611,7 @@ hc_handle_data_urb (struct usb_control *usbc_p)
urb->data_p += 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;
@@ -565,7 +643,7 @@ hc_handle_data_urb (struct usb_control *usbc_p)
urb->remain -= 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;
@@ -596,7 +674,7 @@ issue_get_desc (void)
{
struct urb *urb;
urb = malloc (sizeof (struct urb) + 64);
urb = malloc (sizeof (struct urb) + USB_MAX_PACKET_SIZE);
urb->next = urb->prev = urb;
@@ -606,14 +684,14 @@ issue_get_desc (void)
urb->setup[3] = 1; /* Value H: desc_type */
urb->setup[4] = 0; /* Index */
urb->setup[5] = 0;
urb->setup[6] = 64; /* Length */
urb->setup[6] = USB_MAX_PACKET_SIZE; /* Length */
urb->setup[7] = 0;
urb->data_p = urb->data;
urb->seq = 0;
urb->devid = 0;
urb->dir = USBIP_DIR_IN;
urb->ep = 0;
urb->remain = urb->len = 64;
urb->remain = urb->len = USB_MAX_PACKET_SIZE;
hc_handle_control_urb (urb);
return urb;
}
@@ -729,7 +807,7 @@ usbip_handle_urb (uint32_t seq)
leave:
msg.cmd = htonl (REP_URB_SUBMIT);
msg.seq = htonl (urb->seq);
msg.seq = htonl (seq);
memset (&msg_rep, 0, sizeof (msg_rep));
msg_rep.status = htonl (r);
@@ -1080,6 +1158,11 @@ usbip_run_server (void *arg)
exit (1);
}
fputs ("USBIP thread started.\n", stdout);
fputs ("You can use this by attaching following commands:\n", stdout);
fputs (" # modprobe vhci_hcd\n", stdout);
fputs (" # usbip attach -r 127.0.0.1 -b 1-1\n", stdout);
pollfds[1].fd = shutdown_notify_fd;
pollfds[1].events = POLLIN;
pollfds[1].revents = 0;

View File

@@ -71,7 +71,7 @@ MCFLAGS = -march=rv32imac -mabi=ilp32
LDFLAGS = $(MCFLAGS) -nodefaultlibs -nostartfiles -lc -T$(LDSCRIPT) \
-Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch
else
MCFLAGS = -mcpu=$(MCU)
MCFLAGS = -mcpu=$(MCU) -masm-syntax-unified
LDFLAGS = $(MCFLAGS) -nostartfiles -T$(LDSCRIPT) \
-Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch,--gc-sections
endif