Compare commits

31 Commits

Author SHA1 Message Date
NIIBE Yutaka
89eb54929e Version 1.3. 2017-02-02 12:56:13 +09:00
NIIBE Yutaka
a96f84ff74 Add Blue Pill support. 2017-02-01 17:31:52 +09:00
Szczepan Zalega
9d84537c13 Switch off red LED for Nitrokey Start.
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2017-02-01 15:24:55 +09:00
NIIBE Yutaka
d448d3c678 Version 1.2 2016-10-13 10:18:47 +09:00
NIIBE Yutaka
bc664fe943 chopstx_join is cancellation point. 2016-10-12 12:06:37 +09:00
NIIBE Yutaka
08cca6b9f8 stackaddr/size change 2016-07-11 17:21:32 +09:00
NIIBE Yutaka
c9d59a3f3f mcu/stm32f103.h: Add more constants from Gnuk 1.1.9 2016-07-11 11:38:58 +09:00
NIIBE Yutaka
09f27704f5 Version 1.1 2016-07-01 11:50:25 +09:00
NIIBE Yutaka
1f23bd4048 Change touch button for MKL27Z 2016-07-01 10:58:05 +09:00
NIIBE Yutaka
f5880ee5d5 Change API of chopstx_setpriority 2016-07-01 09:51:32 +09:00
NIIBE Yutaka
c7e571eca0 update doc 2016-06-30 16:41:32 +09:00
NIIBE Yutaka
0decd305b9 chopstx_poll example fix 2016-06-30 16:26:52 +09:00
NIIBE Yutaka
a2a29146a6 const pointer cleanup 2016-06-30 16:23:29 +09:00
NIIBE Yutaka
e7bd234a0d Update for MKL27Z 2016-06-30 16:16:39 +09:00
NIIBE Yutaka
c71a24ddcb MKL27Z touch 2016-06-29 17:05:33 +09:00
NIIBE Yutaka
663cbabe7c Fix MKL27Z TPM registers 2016-06-29 16:51:16 +09:00
NIIBE Yutaka
41ac81a66b Update example for fs-bb48 2016-06-29 16:38:18 +09:00
NIIBE Yutaka
986518fba7 fix setpriority 2016-06-29 16:36:53 +09:00
NIIBE Yutaka
15a4403f24 chopstx_poll change 2016-06-28 15:48:15 +09:00
Niibe Yutaka
40adf95c24 Version 1.0 2016-06-16 11:46:38 +09:00
Niibe Yutaka
5a7381ece6 Add FST-01G 2016-06-16 11:31:10 +09:00
Niibe Yutaka
52626a3368 chopstx_exit change 2016-06-15 12:41:12 +09:00
Niibe Yutaka
440188c373 Fix USB for STM32 2016-06-14 15:10:07 +09:00
NIIBE Yutaka
a6541cbcc6 NONE sounds bad, use OK instead 2016-06-10 08:25:00 +09:00
NIIBE Yutaka
74c7b5bcb3 minor comment change 2016-06-09 10:07:31 +09:00
NIIBE Yutaka
4d7e97028e More update of USB API 2016-06-09 09:53:15 +09:00
NIIBE Yutaka
d061e6f931 USB for FS-BB48 2016-06-08 15:43:11 +09:00
NIIBE Yutaka
5f1c26ff17 USB API major change 2016-06-08 15:40:55 +09:00
NIIBE Yutaka
78718e57df Move files 2016-06-02 11:01:11 +09:00
NIIBE Yutaka
a756987d2a Fix chx_fatal 2016-06-01 07:47:58 +09:00
NIIBE Yutaka
b6e3a1aba1 Relicense ADC driver with GPLv3+ plus EXCEPTION 2016-05-31 21:41:40 +09:00
44 changed files with 2371 additions and 1127 deletions

29
AUTHORS
View File

@@ -22,17 +22,30 @@ Mateusz Zalega:
board/board-nitrokey-start.h
NIIBE Yutaka:
Write the library:
chopstx.c, eventflag.c, entry.c,
clk_gpio_init-kl.c, clk_gpio_init-stm32.c
Wrote the library:
chopstx.c, entry.c, eventflag.c,
chopstx.h, eventflag.h
Draw the logo:
Wrote the drivers mcu/*:
clk_gpio_init-mkl27z.c, clk_gpio_init-stm32.c,
sys-stm32f103.c, sys-stm32f030.c, sys-mkl27z.c,
adc-stm32f103.c, adc-mkl27z.c
Drew the logo:
chopstx.svg, chopstx.png
Write examples:
example-led, example-cdc, example-fsm-55
Write board:
Wrote examples:
example-led, example-cdc, example-fsm-55, example-fs-bb48
Wrote board/*:
board-fst-01.h, board-fst-01-00.h,
board-olimex-stm32-h103.h, board-stm8s-discovery.h
board-cq-starm.h, board-stbee-mini.h, board-stbee.h,
board-stm32f0-discovery.h, board-fsm-55.h
board-stm32f0-discovery.h, board-fsm-55.h,
board-fs-bb48.h
Paul Fertser:
Added Blue Pill support.
board/board-blue-pill.h
Szczepan Zalega:
Modified Nitrokey-Start support.
board/board-nitrokey-start.h

127
ChangeLog
View File

@@ -1,3 +1,130 @@
2017-02-02 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.3.
* doc/chopstx.texi (VERSION): 1.3.
2017-02-01 Paul Fertser <fercerpav@gmail.com>
* board/board-blue-pill.h: New.
2016-12-08 Szczepan Zalega <szczepan@nitrokey.com>
* board/board-nitrokey-start.h (VAL_GPIO_USB_ODR): Switch off red
LED for Nitrokey Start.
2016-10-13 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.
* doc/chopstx.texi (VERSION): 1.2.
2016-10-12 NIIBE Yutaka <gniibe@fsij.org>
* chopstx.c (chopstx_join, chopstx_cancel): chopstx_join is
cancellation point.
2016-07-11 NIIBE Yutaka <gniibe@fsij.org>
* mcu/stm32f103.h: Add more from Gnuk 1.1.9.
* example-cdc, example-fs-bb48, example-fsm-55, example-led:
Update for stack addr/size.
2016-07-01 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.1.
* doc/chopstx.texi (VERSION): 1.1.
* chopstx.c (chopstx_setpriority): Change the API.
2016-06-30 NIIBE Yutaka <gniibe@fsij.org>
* example-cdc/usb-cdc.c (tty_recv, tty_main): Follow the change of
chopstx_poll.
2016-06-29 NIIBE Yutaka <gniibe@fsij.org>
* example-fs-bb48: Update.
* example-fs-bb48/touch.c: New.
* chopstx.c (chopstx_setpriority): Fix sched_lock/unlock.
2016-06-28 NIIBE Yutaka <gniibe@fsij.org>
* chopstx.h (struct chx_poll_head): Declare here.
* chopstx.c (chopstx_poll): Don't use varargs, but use
an array of pointer.
(chopstx_intr_wait): Follow the change of chopstx_poll.
* eventflag.c (eventflag_wait_timeout): Likewise.
* contrib/adc-stm32f103.c (adc_wait_completion): Likewise.
* contrib/adc-mkl27z.c (adc_wait_completion): Likewise.
2016-06-16 Niibe Yutaka <gniibe@fsij.org>
* VERSION: 1.0.
* doc/chopstx.texi (VERSION): 1.0.
* board/board-fst-01g.h: New.
2016-06-15 Niibe Yutaka <gniibe@fsij.org>
* chopstx.c (chopstx_exit): Add "naked" attribute.
2016-06-14 Niibe Yutaka <gniibe@fsij.org>
* mcu/usb-stm32f103.c (usb_lld_ctrl_recv): Fix the state and make
the endpoint 0 RX_VALID.
2016-06-10 NIIBE Yutaka <gniibe@fsij.org>
* usb_lld.h (USB_EVENT_OK): Rename.
* mcu/usb-stm32f103.c: Update.
* mcu/usb-mkl27z.c: Likewise.
* example-cdc/usb-cdc.c: Follow the change of API.
* example-fs-bb48/usb-cdc.c: Likewise.
2016-06-09 NIIBE Yutaka <gniibe@fsij.org>
* mcu/usb-stm32f103.c (usb_lld_ctrl_recv): Rename.
(usb_lld_ctrl_send): Rename.
(usb_lld_ctrl_ack): Rename and let have return value.
* mcu/usb-mkl27z.c: Likewise.
* example-cdc/usb-cdc.c: Follow the change of API.
* example-fs-bb48/usb-cdc.c: Likewise.
2016-06-08 NIIBE Yutaka <gniibe@fsij.org>
* mcu/usb-stm32f103.c: Rewrite to be event driven API.
* mcu/usb-mkl27z.c: Likewise.
* example-cdc/usb-cdc.c: Update to new USB API.
* example-fs-bb48/usb-cdc.c: Likewise.
* example-cdc/tty.h: Change tty API to be C string (char*)
friendly.
* example-fs-bb48/tty.h: Ditto.
2016-06-02 Niibe Yutaka <gniibe@fsij.org>
* contrib/adc-mkl27z.c: Move from mcu.
* contrib/adc-stm32f103.c: Move from mcu.
* example-led/Makefile (CHIP): Define as stm32f0.
* mcu/sys-stm32f0.h: Rename from sys-stm32f030.h,
as we share it among STM32F030 and STM32F050.
* mcu/sys-stm32f0.c: Likewise.
* board/board-stm32f0-discovery.h (MCU_STM32F0): Define.
* sys.h: Support STM32F0.
2016-06-01 NIIBE Yutaka <gniibe@fsij.org>
* chopstx.h (chx_fatal): Remove weak attribute from declaration.
* chopstx.c (chx_fatal): Add weak attribute to implementation.
2016-05-31 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 0.12.

47
NEWS
View File

@@ -1,6 +1,53 @@
NEWS - Noteworthy changes
* Major changes in Chopstx 1.3
Released 2017-02-02
** New board support: Blue Pill
It is contributed by Paul Fertser.
* Major changes in Chopstx 1.2
Released 2016-10-13
** Fix: chopstx_join
chopstx_join is now cancellation point.
* Major changes in Chopstx 1.1
Released 2016-07-01
** API change: chopstx_poll
In version 1.0, chopstx_poll has variable arguments. It found that
it's challenging for ffi or lower level C implementation, if C
compiler is new for the specific MCU target. Another example is that
a program touches FPU registers for varargs, even if no argument is
float. So, we decided to avoid use of varargs in Chopstx.
** API change: chopstx_setpriority
In version 1.0, chopstx_setpriority does not return value. It is
changed to return old value of the priority.
* Major changes in Chopstx 1.0
Released 2016-06-16
** New USB API
Now, USB driver is included in Chopstx. So, it should be good one.
It used to be the code which was derived from interrupt driven API
with callbacks. It's changed to event driven API, so that a user can
do as wish, beyond the restriction of callbacks.
** New board support: FST-01G
FST-01G is a new revision of original FST-01 with fixed pull-up of
D+ line.
* Major changes in Chopstx 0.12
Released 2016-05-31

9
README
View File

@@ -1,6 +1,6 @@
Chopstx - Threads and only Threads
Version 0.12
2016-05-31
Version 1.3
2017-02-02
Niibe Yutaka
Flying Stone Technology
@@ -45,8 +45,9 @@ For STM32 Primer2, see the directory: example-primer2.
Future Works
============
Convenience function to determine the bottom of thread stack, thread
local storage would be next things to be done.
Convenience function to determine the bottom of thread stack,
configuration of thread size by comiler'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

View File

@@ -1 +1 @@
release/0.12
release/1.3

36
board/board-blue-pill.h Normal file
View File

@@ -0,0 +1,36 @@
#define BOARD_NAME "Blue Pill"
/* http://wiki.stm32duino.com/index.php?title=Blue_Pill */
/* echo -n "Blue Pill" | shasum -a 256 | sed -e 's/^.*\(........\) -$/\1/' */
#define BOARD_ID 0xa1099d43
#define STM32F10X_MD /* Medium-density device */
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE 9
#define STM32_HSECLK 8000000
#define GPIO_LED_BASE GPIOC_BASE
#define GPIO_LED_CLEAR_TO_EMIT 13
#define GPIO_USB_BASE GPIOA_BASE
#define GPIO_USB_SET_TO_ENABLE 12
#undef GPIO_OTHER_BASE
/*
* Port A setup.
* PA11 - Push Pull output 10MHz 0 default (until USB enabled) (USBDM)
* PA12 - Push Pull output 10MHz 0 default (until USB enabled) (USBDP)
* PC13 - Push pull output 50MHz (LED 1:ON 0:OFF)
* ------------------------ Default
* PAx - input with pull-up
* PCx - input with pull-up
*/
#define VAL_GPIO_USB_ODR 0xFFFFE7FF
#define VAL_GPIO_USB_CRL 0x88888888 /* PA7...PA0 */
#define VAL_GPIO_USB_CRH 0x88811888 /* PA15...PA8 */
#define VAL_GPIO_LED_ODR 0xFFFFFFFF
#define VAL_GPIO_LED_CRL 0x88888888 /* PC7...PC0 */
#define VAL_GPIO_LED_CRH 0x88388888 /* PC15...PC8 */
#define RCC_ENR_IOP_EN (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN)
#define RCC_RSTR_IOP_RST (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPCRST)

84
board/board-fst-01g.h Normal file
View File

@@ -0,0 +1,84 @@
#define BOARD_NAME "FST-01G"
#define BOARD_ID 0x8801277f
/* echo -n "FST-01G" | sha256sum | sed -e 's/^.*\(........\) -$/\1/' */
#define STM32F10X_MD /* Medium-density device */
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE 6
#define STM32_HSECLK 12000000
#define GPIO_LED_BASE GPIOB_BASE
#define GPIO_LED_SET_TO_EMIT 0
#define GPIO_USB_BASE GPIOA_BASE
#undef GPIO_OTHER_BASE
/*
* Port A setup.
* PA0 - input with pull-up (TIM2_CH1): AN0 for NeuG
* PA1 - input with pull-down (TIM2_CH2)
* PA2 - input with pull-up (TIM2_CH3) connected to CIR module
* PA3 - input with pull-up: external pin available to user
* PA4 - Push pull output (SPI1_NSS)
* PA5 - Alternate Push pull output (SPI1_SCK)
* PA6 - Alternate Push pull output (SPI1_MISO)
* PA7 - Alternate Push pull output (SPI1_MOSI)
* PA10 - Push pull output 1 default
* (so that binary for FST-01G also works on FST-01)
* PA11 - Push Pull output 10MHz 0 default (until USB enabled) (USBDM)
* PA12 - Push Pull output 10MHz 0 default (until USB enabled) (USBDP)
* ------------------------ Default
* PA8 - input with pull-up.
* PA9 - input with pull-up.
* PA13 - input with pull-up.
* PA14 - input with pull-up.
* PA15 - input with pull-up.
*/
#define VAL_GPIO_USB_ODR 0xFFFFE7FD
#define VAL_GPIO_USB_CRL 0xBBB38888 /* PA7...PA0 */
#define VAL_GPIO_USB_CRH 0x88811388 /* PA15...PA8 */
/*
* Port B setup.
* PB0 - Push pull output (LED 1:ON 0:OFF)
* PB1 - input with pull-up: AN9 for NeuG
* ------------------------ Default
* PBx - input with pull-up.
*/
#define VAL_GPIO_LED_ODR 0xFFFFFFFF
#define VAL_GPIO_LED_CRL 0x88888883 /* PA7...PA0 */
#define VAL_GPIO_LED_CRH 0x88888888 /* PA15...PA8 */
#define RCC_ENR_IOP_EN (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN)
#define RCC_RSTR_IOP_RST (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST)
/*
* Board specific information other than clock and GPIO initial
* setting should not be in board-*.h, but each driver should include
* information by itself.
*
* Please see NeuG's ADC driver how board specific handling is done.
*
* Given the situation of Chopstx's boards support, which is not that
* huge, this works well. If scalability and flexibility will matter,
* we will need something like device tree in which boot process can
* pass information to application program.
*
* Following constants are here, because experimental CIR driver is
* written before this design decision of Chopstx.
*
* Those will be removed soon, once such an driver will be improved
* in new style.
*/
/* For pin-cir settings of Gnuk */
#define TIMx TIM2
#define INTR_REQ_TIM TIM2_IRQ
#define AFIO_EXTICR_INDEX 0
#define AFIO_EXTICR1_EXTIx_Py AFIO_EXTICR1_EXTI2_PA
#define EXTI_PR EXTI_PR_PR2
#define EXTI_IMR EXTI_IMR_MR2
#define EXTI_FTSR_TR EXTI_FTSR_TR2
#define INTR_REQ_EXTI EXTI2_IRQ
#define ENABLE_RCC_APB1
#define RCC_APBnENR_TIMxEN RCC_APB1ENR_TIM2EN
#define RCC_APBnRSTR_TIMxRST RCC_APB1RSTR_TIM2RST

View File

@@ -22,7 +22,7 @@
* PA4 - floating input
* PA5 - floating input
* PA6 - floating input
* PA7 - Push pull output (LED1 1:ON 0:OFF)
* PA7 - Push pull output (Red LED1 1:ON 0:OFF)
* PA8 - floating input (smartcard, SCDSA)
* PA9 - floating input
* PA10 - floating input
@@ -37,13 +37,13 @@
* PA14 - input with pull-up.
* PA15 - Push pull output (USB 1:ON 0:OFF)
*/
#define VAL_GPIO_USB_ODR 0xFFFFE7FF
#define VAL_GPIO_USB_ODR 0xFFFFE77F
#define VAL_GPIO_USB_CRL 0x34444488 /* PA7...PA0 */
#define VAL_GPIO_USB_CRH 0x38811444 /* PA15...PA8 */
/*
* Port B setup.
* PB0 - Push pull output (LED2 1:ON 0:OFF)
* PB0 - Push pull output (Green LED2 1:ON 0:OFF)
* ------------------------ Default
* PBx - input with pull-up.
*/

View File

@@ -1,6 +1,8 @@
#define BOARD_NAME "STM32F0 Discovery"
#define BOARD_ID 0xde4b4bc1
#define MCU_STM32F0 1
/*
* Running at 48MHz with HSI as clock source.
*

View File

@@ -104,9 +104,9 @@
* System tick
*/
/* SysTick registers. */
static volatile uint32_t *const SYST_CSR = (uint32_t *const)0xE000E010;
static volatile uint32_t *const SYST_RVR = (uint32_t *const)0xE000E014;
static volatile uint32_t *const SYST_CVR = (uint32_t *const)0xE000E018;
static volatile uint32_t *const SYST_CSR = (uint32_t *)0xE000E010;
static volatile uint32_t *const SYST_RVR = (uint32_t *)0xE000E014;
static volatile uint32_t *const SYST_CVR = (uint32_t *)0xE000E018;
static void
chx_systick_reset (void)
@@ -158,7 +158,7 @@ struct NVIC {
volatile uint32_t IPR[60];
};
static struct NVIC *const NVIC = (struct NVIC *const)0xE000E100;
static struct NVIC *const NVIC = (struct NVIC *)0xE000E100;
#define NVIC_ISER(n) (NVIC->ISER[n >> 5])
#define NVIC_ICER(n) (NVIC->ICER[n >> 5])
#define NVIC_ICPR(n) (NVIC->ICPR[n >> 5])
@@ -192,12 +192,12 @@ chx_set_intr_prio (uint8_t n)
| (CPU_EXCEPTION_PRIORITY_INTERRUPT << sh);
}
static volatile uint32_t *const ICSR = (uint32_t *const)0xE000ED04;
static volatile uint32_t *const ICSR = (uint32_t *)0xE000ED04;
/* Priority control. */
static uint32_t *const AIRCR = (uint32_t *const)0xE000ED0C;
static uint32_t *const SHPR2 = (uint32_t *const)0xE000ED1C;
static uint32_t *const SHPR3 = (uint32_t *const)0xE000ED20;
static uint32_t *const AIRCR = (uint32_t *)0xE000ED0C;
static uint32_t *const SHPR2 = (uint32_t *)0xE000ED1C;
static uint32_t *const SHPR3 = (uint32_t *)0xE000ED20;
static void
chx_prio_init (void)
@@ -208,6 +208,8 @@ chx_prio_init (void)
| (CPU_EXCEPTION_PRIORITY_PENDSV << 16));
}
void __attribute__((weak)) chx_fatal (uint32_t err_code);
/**
* chx_fatal - Fatal error point.
* @err_code: Error code
@@ -333,11 +335,6 @@ struct chx_thread { /* inherits PQ */
struct chx_cleanup *clp;
};
struct chx_poll_head {
uint16_t type;
uint16_t ready;
};
static void
chx_cpu_sched_lock (void)
@@ -444,8 +441,8 @@ enum {
THREAD_WAIT_MTX,
THREAD_WAIT_CND,
THREAD_WAIT_TIME,
THREAD_WAIT_EXIT,
THREAD_WAIT_POLL,
THREAD_JOIN,
/**/
THREAD_EXITED=0x0E,
THREAD_FINISHED=0x0F
@@ -1191,7 +1188,7 @@ requeue (struct chx_thread *tp)
chx_spin_unlock (&cond->lock);
/* We don't know who can wake up this thread. */
}
else if (tp->state == THREAD_JOIN)
else if (tp->state == THREAD_WAIT_EXIT)
/* Requeue is not needed as waiting for the thread is only by one. */
return (struct chx_thread *)tp->v;
@@ -1462,7 +1459,7 @@ chx_intr_hook (struct chx_px *px, struct chx_poll_head *pd)
void
chopstx_intr_wait (chopstx_intr_t *intr)
{
chopstx_poll (NULL, 1, intr);
chopstx_poll (NULL, 1, (struct chx_poll_head **)&intr);
}
@@ -1500,6 +1497,12 @@ chopstx_cleanup_pop (int execute)
}
/*
* We put "naked" attribute to chopstx_exit function. Since it never
* returns, function prologue is not needed.
*/
void chopstx_exit (void *retval) __attribute__ ((naked));
/**
* chopstx_exit - Terminate the execution of running thread
* @retval: Return value (to be caught by a joining thread)
@@ -1556,6 +1559,8 @@ chopstx_join (chopstx_t thd, void **ret)
* We don't offer deadlock detection. It's users' responsibility.
*/
chopstx_testcancel ();
chx_cpu_sched_lock ();
if (tp->flag_detached)
{
@@ -1572,7 +1577,7 @@ chopstx_join (chopstx_t thd, void **ret)
chx_spin_lock (&q_join.lock);
ll_prio_enqueue ((struct chx_pq *)running, &q_join.q);
running->v = (uint32_t)tp;
running->state = THREAD_JOIN;
running->state = THREAD_WAIT_EXIT;
tp->flag_join_req = 1;
/* Priority inheritance. */
@@ -1658,7 +1663,7 @@ chopstx_cancel (chopstx_t thd)
return;
}
/* Cancellation points: cond_wait, usec_wait, and poll. */
/* Cancellation points: cond_wait, usec_wait, join, and poll. */
if (tp->state == THREAD_WAIT_CND)
{
struct chx_cond *cond = (struct chx_cond *)tp->parent;
@@ -1669,6 +1674,12 @@ chopstx_cancel (chopstx_t thd)
}
else if (tp->state == THREAD_WAIT_TIME)
chx_timer_dequeue (tp);
else if (tp->state == THREAD_WAIT_EXIT)
{
chx_spin_lock (&q_join.lock);
ll_dequeue ((struct chx_pq *)tp);
chx_spin_unlock (&q_join.lock);
}
else if (tp->state == THREAD_WAIT_POLL)
{
if (tp->parent == &q_timer.q)
@@ -1741,17 +1752,17 @@ chx_proxy_init (struct chx_px *px, uint32_t *cp)
* chopstx_poll - wait for condition variable, thread's exit, or IRQ
* @usec_p: Pointer to usec for timeout. Forever if NULL.
* @n: Number of poll descriptors
* @VARARGS: Pointers to an object which should be one of:
* @pd_array: Pointer to an array of poll descriptor pointer which
* should be one of:
* chopstx_poll_cond_t, chopstx_poll_join_t, or chopstx_intr_t.
*
* Returns number of active descriptors.
*/
int
chopstx_poll (uint32_t *usec_p, int n, ...)
chopstx_poll (uint32_t *usec_p, int n, struct chx_poll_head *pd_array[])
{
uint32_t counter = 0;
int i;
va_list ap;
struct chx_px px[n];
struct chx_poll_head *pd;
int r = 0;
@@ -1761,10 +1772,9 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
for (i = 0; i < n; i++)
chx_proxy_init (&px[i], &counter);
va_start (ap, n);
for (i = 0; i < n; i++)
{
pd = va_arg (ap, struct chx_poll_head *);
pd = pd_array[i];
pd->ready = 0;
px[i].ready_p = &pd->ready;
if (pd->type == CHOPSTX_POLL_COND)
@@ -1774,7 +1784,6 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
else
chx_join_hook (&px[i], pd);
}
va_end (ap);
chx_cpu_sched_lock ();
chx_spin_lock (&px->lock);
@@ -1810,11 +1819,9 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
while (r == 0);
}
va_start (ap, n);
for (i = 0; i < n; i++)
{
pd = va_arg (ap, struct chx_poll_head *);
pd = pd_array[i];
chx_cpu_sched_lock ();
chx_spin_lock (&px[i].lock);
if (pd->type == CHOPSTX_POLL_COND)
@@ -1856,7 +1863,6 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
chx_spin_unlock (&px[i].lock);
chx_cpu_sched_unlock ();
}
va_end (ap);
if (r < 0)
chopstx_exit (CHOPSTX_CANCELED);
@@ -1870,6 +1876,7 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
* @prio: priority
*
* Change the schedule priority with @prio.
* Returns the old priority.
*
* In general, it is not recommended to use this function because
* dynamically changing schedule priorities complicates the system.
@@ -1877,15 +1884,33 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
* which starts its execution with priority of CHX_PRIO_MAIN_INIT, and
* let it change its priority after initialization of other threads.
*/
void
chopstx_setpriority (chopstx_prio_t prio)
chopstx_prio_t
chopstx_setpriority (chopstx_prio_t prio_new)
{
struct chx_thread *tp = running;
chopstx_prio_t prio_orig, prio_cur;
tp->prio_orig = prio;
if (prio >= CHOPSTX_PRIO_INHIBIT_PREEMPTION)
chx_cpu_sched_lock ();
tp->prio = prio;
prio_orig = tp->prio_orig;
prio_cur = tp->prio;
tp->prio_orig = prio_new;
if (prio_cur == prio_orig)
/* No priority inheritance is active. */
tp->prio = prio_new;
else
/* Priority inheritance is active. */
/* In this case, only when new priority is greater, change the
priority of this thread. */
if (prio_new > prio_cur)
tp->prio = prio_new;
if (tp->prio < prio_cur)
chx_sched (CHX_YIELD);
else if (tp->prio < CHOPSTX_PRIO_INHIBIT_PREEMPTION)
chx_cpu_sched_unlock ();
return prio_orig;
}
/*

View File

@@ -83,7 +83,7 @@ void chopstx_cond_broadcast (chopstx_cond_t *cond);
* Library provides default implementation as weak reference.
* User can replace it.
*/
void chx_fatal (uint32_t err_code) __attribute__((__weak__, __noreturn__));
void chx_fatal (uint32_t err_code) __attribute__((__noreturn__));
int chopstx_join (chopstx_t, void **);
void chopstx_exit (void *retval) __attribute__((__noreturn__));
@@ -113,7 +113,7 @@ typedef struct chx_cleanup {
void chopstx_cleanup_push (chopstx_cleanup_t *clp);
void chopstx_cleanup_pop (int execute);
void chopstx_setpriority (chopstx_prio_t);
chopstx_prio_t chopstx_setpriority (chopstx_prio_t);
enum {
CHOPSTX_POLL_COND = 0,
@@ -121,6 +121,11 @@ enum {
CHOPSTX_POLL_JOIN,
};
struct chx_poll_head {
uint16_t type;
uint16_t ready;
};
struct chx_poll_cond {
uint16_t type;
uint16_t ready;
@@ -153,6 +158,6 @@ void chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num);
void chopstx_intr_wait (chopstx_intr_t *intr); /* DEPRECATED */
int chopstx_poll (uint32_t *usec_p, int n, ...);
int chopstx_poll (uint32_t *usec_p, int n, struct chx_poll_head *pd_array[]);
#define CHOPSTX_THREAD_SIZE 64

View File

@@ -40,7 +40,7 @@ struct DMAMUX {
volatile uint32_t CHCFG2;
volatile uint32_t CHCFG3;
};
static struct DMAMUX *const DMAMUX = (struct DMAMUX *const)0x40021000;
static struct DMAMUX *const DMAMUX = (struct DMAMUX *)0x40021000;
#define INTR_REQ_DMA0 0
@@ -50,8 +50,8 @@ struct DMA {
volatile uint32_t DSR_BCR;
volatile uint32_t DCR;
};
static struct DMA *const DMA0 = (struct DMA *const)0x40008100;
static struct DMA *const DMA1 = (struct DMA *const)0x40008110;
static struct DMA *const DMA0 = (struct DMA *)0x40008100;
static struct DMA *const DMA1 = (struct DMA *)0x40008110;
/* We don't use ADC interrupt. Just for reference. */
@@ -92,7 +92,7 @@ struct ADC {
volatile uint32_t CLM1;
volatile uint32_t CLM0;
};
static struct ADC *const ADC0 = (struct ADC *const)0x4003B000;
static struct ADC *const ADC0 = (struct ADC *)0x4003B000;
/* SC1 */
#define ADC_SC1_DIFF (1 << 5)
@@ -295,12 +295,13 @@ adc_stop (void)
int
adc_wait_completion (void)
{
while (1)
{
struct chx_poll_head *pd_array[1] = { (struct chx_poll_head *)&adc_intr };
int i;
while (1)
{
/* Wait DMA completion */
chopstx_poll (NULL, 1, &adc_intr);
chopstx_poll (NULL, 1, pd_array);
DMA0->DSR_BCR = (1 << 24);
DMA1->DSR_BCR = (1 << 24);

View File

@@ -7,22 +7,26 @@
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of NeuG, a True Random Number Generator
* implementation based on quantization error of ADC (for STM32F103).
* This file is a part of Chopstx, a thread library for embedded.
*
* NeuG is free software: you can redistribute it and/or modify it
* 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.
*
* NeuG 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.
* 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
* receipents of GNU GPL by a written offer.
*
*/
#include <stdint.h>
@@ -294,10 +298,11 @@ int
adc_wait_completion (void)
{
uint32_t flags;
struct chx_poll_head *pd_array[1] = { (struct chx_poll_head *)&adc_intr };
while (1)
{
chopstx_poll (NULL, 1, &adc_intr);
chopstx_poll (NULL, 1, pd_array);
flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause. */
/*
* Clear interrupt cause of channel 1.

View File

@@ -176,20 +176,23 @@ Returns old state which is 0 when it was enabled.
@subheading chopstx_poll
@anchor{chopstx_poll}
@deftypefun {int} {chopstx_poll} (uint32_t * @var{usec_p}, int @var{n}, @var{...})
@deftypefun {int} {chopstx_poll} (uint32_t * @var{usec_p}, int @var{n}, struct chx_poll_head * [] @var{pd_array})
@var{usec_p}: Pointer to usec for timeout. Forever if NULL.
@var{n}: Number of poll descriptors
@var{pd_array}: Pointer to an array of poll descriptor pointer which
should be one of:
chopstx_poll_cond_t, chopstx_poll_join_t, or chopstx_intr_t.
Returns number of active descriptors.
@end deftypefun
@subheading chopstx_setpriority
@anchor{chopstx_setpriority}
@deftypefun {void} {chopstx_setpriority} (chopstx_prio_t @var{prio})
@var{prio}: priority
@deftypefun {chopstx_prio_t} {chopstx_setpriority} (chopstx_prio_t @var{prio_new})
Change the schedule priority with @var{prio}.
Returns the old priority.
In general, it is not recommended to use this function because
dynamically changing schedule priorities complicates the system.

View File

@@ -1,7 +1,7 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename chopstx.info
@set VERSION 0.12
@set VERSION 1.3
@settitle Chopstx Reference Manual
@c Unify some of the indices.
@syncodeindex tp fn
@@ -83,8 +83,9 @@ Indexes
@node Introduction
@chapter Introduction
Chopstx is an RT thread library for ARM Cortex-M0 and Cortex-M3.
Specifically, it is used for STM32F030, STM32F103, and KL27Z.
Chopstx is an RT thread library for ARM Cortex-M0, Cortex-M0plus and
Cortex-M3. Specifically, it is used for STM32F030, MKL27Z and
STM32F103.
While most RTOSes come with many features, drivers, and stacks,
Chopstx just offers a RT thread library.

View File

@@ -111,9 +111,10 @@ eventmask_t
eventflag_wait_timeout (struct eventflag *ev, uint32_t usec)
{
chopstx_poll_cond_t poll_desc;
struct chx_poll_head *pd_array[1] = { (struct chx_poll_head *)&poll_desc };
eventflag_prepare_poll (ev, &poll_desc);
chopstx_poll (&usec, 1, &poll_desc);
chopstx_poll (&usec, 1, pd_array);
return eventflag_get (ev);
}

View File

@@ -61,14 +61,14 @@ blk (void *arg)
#define PRIO_PWM 3
#define PRIO_BLK 2
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process2_stack_base__, __process2_stack_size__;
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
const uint32_t __stackaddr_pwm = (uint32_t)&__process1_stack_base__;
const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
#define STACK_ADDR_PWM ((uint32_t)__process1_stack_base__)
#define STACK_SIZE_PWM ((uint32_t)__process1_stack_size__)
const uint32_t __stackaddr_blk = (uint32_t)&__process2_stack_base__;
const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
#define STACK_ADDR_BLK ((uint32_t)__process2_stack_base__)
#define STACK_SIZE_BLK ((uint32_t)__process2_stack_size__)
static char hexchar (uint8_t x)
@@ -98,8 +98,8 @@ main (int argc, const char *argv[])
m = 10;
chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL);
chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL);
chopstx_create (PRIO_PWM, STACK_ADDR_PWM, STACK_SIZE_PWM, pwm, NULL);
chopstx_create (PRIO_BLK, STACK_ADDR_BLK, STACK_SIZE_BLK, blk, NULL);
chopstx_usec_wait (200*1000);
@@ -117,7 +117,7 @@ main (int argc, const char *argv[])
m = 50;
while (1)
{
uint8_t s[LINEBUFSIZE];
char s[LINEBUFSIZE];
u = 1;
tty_wait_connection (tty);

View File

@@ -5,5 +5,5 @@ struct tty;
struct tty *tty_open (void);
void tty_wait_configured (struct tty *tty);
void tty_wait_connection (struct tty *tty);
int tty_send (struct tty *tty, uint8_t *buf, int count);
int tty_recv (struct tty *tty, uint8_t *buf, uint32_t *timeout);
int tty_send (struct tty *tty, const char *buf, int count);
int tty_recv (struct tty *tty, char *buf, uint32_t *timeout);

View File

@@ -30,7 +30,7 @@ static const struct line_coding line_coding0 = {
*
* In that case, add argument to TTY_OPEN function and
* modify TTY_GET function to get the TTY structure. Functions which
* directy accesses TTY0 (usb_cb_device_reset and usb_cb_handle_event)
* directy accesses TTY0 (usb_device_reset and usb_set_configuration)
* should be modified, too.
*
* Modification of TTY_MAIN thread will be also needed to echo back
@@ -234,10 +234,10 @@ static const uint8_t vcom_string3[28] = {
#define NUM_INTERFACES 2
void
usb_cb_device_reset (void)
static void
usb_device_reset (struct usb_dev *dev)
{
usb_lld_reset (VCOM_FEATURE_BUS_POWERED);
usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
/* Initialize Endpoint 0 */
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
@@ -256,13 +256,15 @@ usb_cb_device_reset (void)
#define CDC_CTRL_DTR 0x0001
void
usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
static void
usb_ctrl_write_finish (struct usb_dev *dev)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
struct device_req *arg = &dev->dev_req;
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
&& USB_SETUP_SET (req) && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
&& USB_SETUP_SET (arg->type)
&& arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
{
struct tty *t = tty_get (arg->index, 0);
@@ -272,63 +274,74 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
chopstx_cond_signal (&t->cnd);
chopstx_mutex_unlock (&t->mtx);
}
/*
* The transaction was already finished. So, it is no use to call
* usb_lld_ctrl_error when the condition does not match.
*/
}
static int
vcom_port_data_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
vcom_port_data_setup (struct usb_dev *dev)
{
if (USB_SETUP_GET (req))
struct device_req *arg = &dev->dev_req;
if (USB_SETUP_GET (arg->type))
{
struct tty *t = tty_get (arg->index, 0);
if (req_no == USB_CDC_REQ_GET_LINE_CODING)
return usb_lld_reply_request (&t->line_coding,
sizeof (struct line_coding), arg);
if (arg->request == USB_CDC_REQ_GET_LINE_CODING)
return usb_lld_ctrl_send (dev, &t->line_coding,
sizeof (struct line_coding));
}
else /* USB_SETUP_SET (req) */
{
if (req_no == USB_CDC_REQ_SET_LINE_CODING
if (arg->request == USB_CDC_REQ_SET_LINE_CODING
&& arg->len == sizeof (struct line_coding))
{
struct tty *t = tty_get (arg->index, 0);
usb_lld_set_data_to_recv (&t->line_coding,
return usb_lld_ctrl_recv (dev, &t->line_coding,
sizeof (struct line_coding));
return USB_SUCCESS;
}
else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
return USB_SUCCESS;
else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
return usb_lld_ctrl_ack (dev);
}
return USB_UNSUPPORT;
return -1;
}
int
usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
static int
usb_setup (struct usb_dev *dev)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
struct device_req *arg = &dev->dev_req;
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0)
return vcom_port_data_setup (req, req_no, arg);
return vcom_port_data_setup (dev);
return USB_UNSUPPORT;
return -1;
}
int
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
struct req_args *arg)
static int
usb_get_descriptor (struct usb_dev *dev)
{
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
uint8_t desc_type = (arg->value >> 8);
uint8_t desc_index = (arg->value & 0xff);
if (rcp != DEVICE_RECIPIENT)
return USB_UNSUPPORT;
return -1;
if (desc_type == DEVICE_DESCRIPTOR)
return usb_lld_reply_request (vcom_device_desc, sizeof (vcom_device_desc),
arg);
return usb_lld_ctrl_send (dev,
vcom_device_desc, sizeof (vcom_device_desc));
else if (desc_type == CONFIG_DESCRIPTOR)
return usb_lld_reply_request (vcom_config_desc, sizeof (vcom_config_desc),
arg);
return usb_lld_ctrl_send (dev,
vcom_config_desc, sizeof (vcom_config_desc));
else if (desc_type == STRING_DESCRIPTOR)
{
const uint8_t *str;
@@ -353,13 +366,13 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
size = sizeof (vcom_string3);
break;
default:
return USB_UNSUPPORT;
return -1;
}
return usb_lld_reply_request (str, size, arg);
return usb_lld_ctrl_send (dev, str, size);
}
return USB_UNSUPPORT;
return -1;
}
static void
@@ -388,83 +401,87 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
}
}
int
usb_cb_handle_event (uint8_t event_type, uint16_t value)
static int
usb_set_configuration (struct usb_dev *dev)
{
int i;
uint8_t current_conf;
switch (event_type)
{
case USB_EVENT_ADDRESS:
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = ADDRESSED;
chopstx_mutex_unlock (&tty0.mtx);
return USB_SUCCESS;
case USB_EVENT_CONFIG:
current_conf = usb_lld_current_configuration ();
current_conf = usb_lld_current_configuration (dev);
if (current_conf == 0)
{
if (value != 1)
return USB_UNSUPPORT;
if (dev->dev_req.value != 1)
return -1;
usb_lld_set_configuration (1);
usb_lld_set_configuration (dev, 1);
for (i = 0; i < NUM_INTERFACES; i++)
vcom_setup_endpoints_for_interface (i, 0);
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = CONFIGURED;
chopstx_cond_signal (&tty0.cnd);
chopstx_mutex_unlock (&tty0.mtx);
}
else if (current_conf != value)
else if (current_conf != dev->dev_req.value)
{
if (value != 0)
return USB_UNSUPPORT;
if (dev->dev_req.value != 0)
return -1;
usb_lld_set_configuration (0);
usb_lld_set_configuration (dev, 0);
for (i = 0; i < NUM_INTERFACES; i++)
vcom_setup_endpoints_for_interface (i, 1);
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = ADDRESSED;
chopstx_cond_signal (&tty0.cnd);
chopstx_mutex_unlock (&tty0.mtx);
}
/* Do nothing when current_conf == value */
return USB_SUCCESS;
default:
break;
}
return USB_UNSUPPORT;
usb_lld_ctrl_ack (dev);
return 0;
}
int
usb_cb_interface (uint8_t cmd, struct req_args *arg)
static int
usb_set_interface (struct usb_dev *dev)
{
const uint8_t zero = 0;
uint16_t interface = arg->index;
uint16_t alt = arg->value;
uint16_t interface = dev->dev_req.index;
uint16_t alt = dev->dev_req.value;
if (interface >= NUM_INTERFACES)
return USB_UNSUPPORT;
return -1;
switch (cmd)
{
case USB_SET_INTERFACE:
if (alt != 0)
return USB_UNSUPPORT;
return -1;
else
{
vcom_setup_endpoints_for_interface (interface, 0);
return USB_SUCCESS;
usb_lld_ctrl_ack (dev);
return 0;
}
}
case USB_GET_INTERFACE:
return usb_lld_reply_request (&zero, 1, arg);
static int
usb_get_interface (struct usb_dev *dev)
{
const uint8_t zero = 0;
uint16_t interface = dev->dev_req.index;
default:
case USB_QUERY_INTERFACE:
return USB_SUCCESS;
}
if (interface >= NUM_INTERFACES)
return -1;
/* We don't have alternate interface, so, always return 0. */
return usb_lld_ctrl_send (dev, &zero, 1);
}
static int
usb_get_status_interface (struct usb_dev *dev)
{
const uint16_t status_info = 0;
uint16_t interface = dev->dev_req.index;
if (interface >= NUM_INTERFACES)
return -1;
return usb_lld_ctrl_send (dev, &status_info, 2);
}
@@ -515,8 +532,8 @@ tty_echo_char (struct tty *t, int c)
}
void
usb_cb_tx_done (uint8_t ep_num, uint32_t len)
static void
usb_tx_done (uint8_t ep_num, uint16_t len)
{
struct tty *t = tty_get (-1, ep_num);
@@ -598,19 +615,18 @@ tty_input_char (struct tty *t, int c)
return r;
}
void
usb_cb_rx_ready (uint8_t ep_num)
static void
usb_rx_ready (uint8_t ep_num, uint16_t len)
{
uint8_t recv_buf[64];
struct tty *t = tty_get (-1, ep_num);
if (ep_num == ENDP3)
{
int i, r;
int i;
r = usb_lld_rx_data_len (ENDP3);
usb_lld_rxcpy (recv_buf, ep_num, 0, r);
for (i = 0; i < r; i++)
usb_lld_rxcpy (recv_buf, ep_num, 0, len);
for (i = 0; i < len; i++)
if (tty_input_char (t, recv_buf[i]))
break;
@@ -626,9 +642,9 @@ static void *tty_main (void *arg);
#define INTR_REQ_USB 20
#define PRIO_TTY 4
extern uint8_t __process3_stack_base__, __process3_stack_size__;
const uint32_t __stackaddr_tty = (uint32_t)&__process3_stack_base__;
const size_t __stacksize_tty = (size_t)&__process3_stack_size__;
extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
#define STACK_ADDR_TTY ((uint32_t)__process3_stack_base__)
#define STACK_SIZE_TTY ((uint32_t)__process3_stack_size__)
struct tty *
tty_open (void)
@@ -643,7 +659,7 @@ tty_open (void)
tty0.device_state = UNCONNECTED;
memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
chopstx_create (PRIO_TTY, __stackaddr_tty, __stacksize_tty, tty_main, &tty0);
chopstx_create (PRIO_TTY, STACK_ADDR_TTY, STACK_SIZE_TTY, tty_main, &tty0);
return &tty0;
}
@@ -652,6 +668,8 @@ static void *
tty_main (void *arg)
{
struct tty *t = arg;
struct usb_dev dev;
int e;
#if defined(OLDER_SYS_H)
/*
@@ -660,9 +678,9 @@ tty_main (void *arg)
*
* When USB interrupt occurs between usb_lld_init (which assumes
* ISR) and chopstx_claim_irq (which clears pending interrupt),
* invocation of usb_interrupt_handler won't occur.
* invocation of usb_lld_event_handler won't occur.
*
* Calling usb_interrupt_handler is no harm even if there were no
* Calling usb_lld_event_handler is no harm even if there were no
* interrupts, thus, we call it unconditionally here, just in case
* if there is a request.
*
@@ -671,19 +689,114 @@ tty_main (void *arg)
* chopstx_claim_irq after usb_lld_init overrides that.
*
*/
usb_lld_init (VCOM_FEATURE_BUS_POWERED);
usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
usb_interrupt_handler ();
goto event_handle;
#else
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
usb_lld_init (VCOM_FEATURE_BUS_POWERED);
usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
#endif
while (1)
{
chopstx_poll (NULL, 1, &usb_intr);
chopstx_intr_wait (&usb_intr);
if (usb_intr.ready)
usb_interrupt_handler ();
{
uint8_t ep_num;
#if defined(OLDER_SYS_H)
event_handle:
#endif
/*
* When interrupt is detected, call usb_lld_event_handler.
* The event may be one of following:
* (1) Transfer to endpoint (bulk or interrupt)
* In this case EP_NUM is encoded in the variable E.
* (2) "NONE" event: some trasfer was done, but all was
* done by lower layer, no other work is needed in
* upper layer.
* (3) Device events: Reset or Suspend
* (4) Device requests to the endpoint zero.
*
*/
e = usb_lld_event_handler (&dev);
ep_num = USB_EVENT_ENDP (e);
if (ep_num != 0)
{
if (USB_EVENT_TXRX (e))
usb_tx_done (ep_num, USB_EVENT_LEN (e));
else
usb_rx_ready (ep_num, USB_EVENT_LEN (e));
}
else
switch (USB_EVENT_ID (e))
{
case USB_EVENT_DEVICE_RESET:
usb_device_reset (&dev);
continue;
case USB_EVENT_DEVICE_ADDRESSED:
/* The addres is assigned to the device. We don't
* need to do anything for this actually, but in this
* application, we maintain the USB status of the
* device. Usually, just "continue" as EVENT_OK is
* OK.
*/
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = ADDRESSED;
chopstx_cond_signal (&tty0.cnd);
chopstx_mutex_unlock (&tty0.mtx);
continue;
case USB_EVENT_GET_DESCRIPTOR:
if (usb_get_descriptor (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_SET_CONFIGURATION:
if (usb_set_configuration (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_SET_INTERFACE:
if (usb_set_interface (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_CTRL_REQUEST:
/* Device specific device request. */
if (usb_setup (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_GET_STATUS_INTERFACE:
if (usb_get_status_interface (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_GET_INTERFACE:
if (usb_get_interface (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_SET_FEATURE_DEVICE:
case USB_EVENT_SET_FEATURE_ENDPOINT:
case USB_EVENT_CLEAR_FEATURE_DEVICE:
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
usb_lld_ctrl_ack (&dev);
continue;
case USB_EVENT_CTRL_WRITE_FINISH:
/* Control WRITE transfer finished. */
usb_ctrl_write_finish (&dev);
continue;
case USB_EVENT_OK:
case USB_EVENT_DEVICE_SUSPEND:
default:
continue;
}
}
chopstx_mutex_lock (&t->mtx);
if (t->device_state == CONFIGURED && t->flag_connected
@@ -743,10 +856,10 @@ check_tx (struct tty *t)
}
int
tty_send (struct tty *t, uint8_t *buf, int len)
tty_send (struct tty *t, const char *buf, int len)
{
int r;
uint8_t *p;
const char *p;
int count;
p = buf;
@@ -801,7 +914,7 @@ check_rx (void *arg)
*
*/
int
tty_recv (struct tty *t, uint8_t *buf, uint32_t *timeout)
tty_recv (struct tty *t, char *buf, uint32_t *timeout)
{
int r;
chopstx_poll_cond_t poll_desc;
@@ -815,7 +928,10 @@ tty_recv (struct tty *t, uint8_t *buf, uint32_t *timeout)
while (1)
{
chopstx_poll (timeout, 1, &poll_desc);
struct chx_poll_head *pd_array[1] = {
(struct chx_poll_head *)&poll_desc
};
chopstx_poll (timeout, 1, pd_array);
chopstx_mutex_lock (&t->mtx);
r = check_rx (t);
chopstx_mutex_unlock (&t->mtx);

View File

@@ -6,7 +6,7 @@ PROJECT = sample
CHOPSTX = ..
LDSCRIPT= sample.ld
CSRC = sample.c usb-cdc.c command.c
CSRC = sample.c usb-cdc.c command.c touch.c
CHIP=mkl27z
USE_SYS = yes

View File

@@ -23,7 +23,7 @@ struct command_table
static void
put_line (struct tty *tty, const char *line)
{
tty_send (tty, (uint8_t *)line, strlen (line));
tty_send (tty, line, strlen (line));
}
static const char *help_string =
@@ -51,7 +51,6 @@ static char hexchar (uint8_t x)
return '?';
}
#ifdef ENABLE_DECIMAL_OUTPUT
static char *
compose_decimal (char *s, int value)
{
@@ -87,7 +86,7 @@ compose_decimal (char *s, int value)
return s;
}
#endif
static char *
compose_hex (char *s, uint32_t v)
@@ -143,6 +142,68 @@ get_hex (struct tty *tty, const char *s, uint32_t *v_p)
}
#define TOUCH_VALUE_HIGH 100
#define TOUCH_VALUE_LOW 50
static void
cmd_button (struct tty *tty, const char *line)
{
int i = 0;
extern uint16_t touch_get (void);
uint16_t v0 = 0;
int touched = 0;
(void)line;
put_line (tty, "Please touch the bear.\r\n");
while (i < 16)
{
uint16_t v = touch_get ();
v0 = (v0 * 2 + v)/3;
if (touched == 0 && v0 > TOUCH_VALUE_HIGH)
{
tty_send (tty, "!", 1);
touched = 1;
}
else if (touched == 1 && v0 < TOUCH_VALUE_LOW)
{
tty_send (tty, ".", 1);
touched = 0;
i++;
}
chopstx_usec_wait (10*1000);
}
tty_send (tty, "\r\n", 2);
}
static void
cmd_touch (struct tty *tty, const char *line)
{
int i;
extern uint16_t touch_get (void);
(void)line;
put_line (tty, "Please touch the bear.\r\n");
for (i = 0; i < 20; i++)
{
uint16_t v;
char output[8];
char *s;
chopstx_usec_wait (1000*1000);
v = touch_get ();
s = compose_decimal (output, v);
*s++ = '\r';
*s++ = '\n';
tty_send (tty, output, s - output);
}
}
static void
cmd_mdw (struct tty *tty, const char *line)
{
@@ -203,7 +264,7 @@ cmd_mdw (struct tty *tty, const char *line)
*s++ = '\r';
*s++ = '\n';
tty_send (tty, (uint8_t *)output, s - output);
tty_send (tty, output, s - output);
}
}
@@ -326,7 +387,7 @@ cmd_crc32 (struct tty *tty, const char *line)
s = compose_hex (string, v);
*s++ = '\r';
*s++ = '\n';
tty_send (tty, (uint8_t *)string, sizeof (string));
tty_send (tty, string, sizeof (string));
}
#endif
@@ -369,7 +430,7 @@ cmd_adc (struct tty *tty, const char *line)
{
*s++ = '\r';
*s++ = '\n';
tty_send (tty, (uint8_t *)output, s - output);
tty_send (tty, output, s - output);
s = output;
if (i >= 64)
break;
@@ -393,14 +454,14 @@ cmd_sysinfo (struct tty *tty, const char *line)
*s++ = sys_version[6];
*s++ = '\r';
*s++ = '\n';
tty_send (tty, (uint8_t *)output, s - output);
tty_send (tty, output, s - output);
memcpy (output, "Board ID: ", 10);
s = output + 10;
s = compose_hex (s, sys_board_id);
*s++ = '\r';
*s++ = '\n';
tty_send (tty, (uint8_t *)output, s - output);
tty_send (tty, output, s - output);
memcpy (output, "Board name: ", 12);
s = output + 12;
@@ -412,7 +473,7 @@ cmd_sysinfo (struct tty *tty, const char *line)
*s++ = '\r';
*s++ = '\n';
tty_send (tty, (uint8_t *)output, s - output);
tty_send (tty, output, s - output);
}
@@ -425,6 +486,8 @@ cmd_help (struct tty *tty, const char *line)
struct command_table command_table[] = {
{ "button", cmd_button },
{ "touch", cmd_touch },
{ "mdw", cmd_mdw },
{ "mww", cmd_mww },
{ "fes", cmd_fes },
@@ -470,10 +533,10 @@ cmd_dispatch (struct tty *tty, const char *line)
(*command_table[i].handler) (tty, p);
else
{
uint8_t crlf[] = { '\r', '\n' };
char crlf[] = { '\r', '\n' };
put_line (tty, "No such command: ");
tty_send (tty, (const uint8_t *)line, n);
tty_send (tty, line, n);
tty_send (tty, crlf, sizeof (crlf));
}
}

View File

@@ -1,4 +1,4 @@
const unsigned int *const crc32_table= (const unsigned int *const)0x00000480;
const unsigned int *const crc32_table= (const unsigned int *)0x00000480;
void
crc32_init (unsigned int *p)

View File

@@ -7,27 +7,7 @@
#include "tty.h"
#include "board.h"
#include "command.h"
struct GPIO {
volatile uint32_t PDOR; /* Port Data Output Register */
volatile uint32_t PSOR; /* Port Set Output Register */
volatile uint32_t PCOR; /* Port Clear Output Register */
volatile uint32_t PTOR; /* Port Toggle Output Register */
volatile uint32_t PDIR; /* Port Data Input Register */
volatile uint32_t PDDR; /* Port Data Direction Register */
};
static struct GPIO *const GPIOB = (struct GPIO *const)0x400FF040;
static struct GPIO *const GPIOD = (struct GPIO *const)0x400FF0C0;
static struct GPIO *const GPIOE = (struct GPIO *const)0x400FF100;
static void
set_led (int on)
{
if (on)
GPIOB->PCOR = (1 << 0); /* PTB0: Clear: Light on */
else
GPIOB->PSOR = (1 << 0); /* PTB0: Set : Light off */
}
#include <sys.h>
static chopstx_mutex_t mtx;
static chopstx_cond_t cnd0;
@@ -95,14 +75,14 @@ blk (void *arg)
#define PRIO_PWM 3
#define PRIO_BLK 2
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process2_stack_base__, __process2_stack_size__;
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
const uint32_t __stackaddr_pwm = (uint32_t)&__process1_stack_base__;
const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
#define STACK_ADDR_PWM ((uint32_t)__process1_stack_base__)
#define STACK_SIZE_PWM ((uint32_t)__process1_stack_size__)
const uint32_t __stackaddr_blk = (uint32_t)&__process2_stack_base__;
const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
#define STACK_ADDR_BLK ((uint32_t)__process2_stack_base__)
#define STACK_SIZE_BLK ((uint32_t)__process2_stack_size__)
static char hexchar (uint8_t x)
@@ -117,6 +97,8 @@ static char hexchar (uint8_t x)
}
extern void touch_init (void);
int
main (int argc, const char *argv[])
{
@@ -132,8 +114,8 @@ main (int argc, const char *argv[])
m = 10;
chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL);
chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL);
chopstx_create (PRIO_PWM, STACK_ADDR_PWM, STACK_SIZE_PWM, pwm, NULL);
chopstx_create (PRIO_BLK, STACK_ADDR_BLK, STACK_SIZE_BLK, blk, NULL);
chopstx_usec_wait (200*1000);
@@ -144,6 +126,8 @@ main (int argc, const char *argv[])
u = 1;
touch_init ();
tty = tty_open ();
tty_wait_configured (tty);
@@ -151,7 +135,7 @@ main (int argc, const char *argv[])
m = 50;
while (1)
{
uint8_t s[LINEBUFSIZE];
char s[LINEBUFSIZE];
connection_loop:
u = 1;
@@ -175,7 +159,7 @@ main (int argc, const char *argv[])
uint32_t usec;
/* Prompt */
if (tty_send (tty, (uint8_t *)"> ", 2) < 0)
if (tty_send (tty, "> ", 2) < 0)
break;
usec = 3000000; /* 3.0 seconds */

98
example-fs-bb48/touch.c Normal file
View File

@@ -0,0 +1,98 @@
#include <stdint.h>
#include <stdlib.h>
#include <chopstx.h>
#include <mcu/mkl27z.h>
struct TPM {
volatile uint32_t SC;
volatile uint32_t CNT;
volatile uint32_t MOD;
volatile uint32_t C0SC;
volatile uint32_t C0V;
volatile uint32_t C1SC;
volatile uint32_t C1V;
uint32_t rsvd0[13];
volatile uint32_t STATUS;
uint32_t rsvd1[7];
volatile uint32_t POL;
uint32_t rsvd2[4];
volatile uint32_t CONF;
};
static struct TPM *const TPM1 = (struct TPM *)0x40039000;
static chopstx_intr_t tpm1_intr;
#define INTR_REQ_TPM1 18
static void
gpio_assert_low (void)
{
/* Assert LOW. */
PORTB->PCR1 = (1<<8) /* GPIO */
| (0<<6) /* DriveStrengthEnable=0 */
| (0<<4) /* PassiveFilterEnable=0 */
| (1<<2) /* SlewRateEnable = slow */
| (0<<1) /* pull enable = 0 */
| (0<<0) /* pull up select= 0 */
;
GPIOB->PCOR = (1 << 1); /* PTB1: Clear: Output 0 */
}
uint16_t
touch_get (void)
{
chopstx_prio_t prio_old;
uint16_t v;
prio_old = chopstx_setpriority (CHOPSTX_PRIO_INHIBIT_PREEMPTION);
/*
* Start the timer's counter.
* TOF clear, TOIE=1, CPWMS=0, CMOD=1, PS=011.
*/
TPM1->SC = 0xcb;
/* Let the register to pull it up. */
PORTB->PCR1 = (3<<8) /* TPM1_CH1 */
| (0<<6) /* DriveStrengthEnable=0 */
| (0<<4) /* PassiveFilterEnable=0 */
| (1<<2) /* SlewRateEnable = slow */
| (0<<1) /* pull enable = 0 */
| (0<<0) /* pullup select= 0 */
;
chopstx_setpriority (prio_old);
chopstx_intr_wait (&tpm1_intr);
gpio_assert_low ();
v = TPM1->C1V;
/* Clear overflow and CH1 capture. */
TPM1->STATUS = 0x102;
/* Stop the timer. */
TPM1->SC = 0;
TPM1->CNT = 0xffff; /* Writing causes reset of the counter. */
return v;
}
void
touch_init (void)
{
chopstx_claim_irq (&tpm1_intr, INTR_REQ_TPM1);
/* Input capture mode: MSB = 0, MSA = 0 */
/* Rising edge: ELSB=0 ELSA=1 */
TPM1->C1SC = 0x84;
TPM1->POL=0;
/* No trigger. */
/* Stop on overflow: CSOO=1 */
/* Run the timer in the debug mode */
TPM1->CONF = 0x000200c0;
TPM1->CNT = 0xffff; /* Writing causes reset of the counter. */
gpio_assert_low ();
}

View File

@@ -5,5 +5,5 @@ struct tty;
struct tty *tty_open (void);
void tty_wait_configured (struct tty *tty);
void tty_wait_connection (struct tty *tty);
int tty_send (struct tty *tty, const uint8_t *buf, int count);
int tty_recv (struct tty *tty, uint8_t *buf, uint32_t *timeout);
int tty_send (struct tty *tty, const char *buf, int count);
int tty_recv (struct tty *tty, char *buf, uint32_t *timeout);

View File

@@ -31,7 +31,7 @@ static const struct line_coding line_coding0 = {
*
* In that case, add argument to TTY_OPEN function and
* modify TTY_GET function to get the TTY structure. Functions which
* directy accesses TTY0 (usb_cb_device_reset and usb_cb_handle_event)
* directy accesses TTY0 (usb_device_reset and usb_set_configuration)
* should be modified, too.
*
* Modification of TTY_MAIN thread will be also needed to echo back
@@ -231,13 +231,13 @@ static const uint8_t vcom_string3[28] = {
#define NUM_INTERFACES 2
void
usb_cb_device_reset (void)
static void
usb_device_reset (struct usb_dev *dev)
{
usb_lld_reset (VCOM_FEATURE_BUS_POWERED);
usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
/* Initialize Endpoint 0 */
usb_lld_setup_endp (ENDP0, 1, 1);
usb_lld_setup_endp (dev, ENDP0, 1, 1);
chopstx_mutex_lock (&tty0.mtx);
tty0.inputline_len = 0;
@@ -253,13 +253,15 @@ usb_cb_device_reset (void)
#define CDC_CTRL_DTR 0x0001
void
usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
static void
usb_ctrl_write_finish (struct usb_dev *dev)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
struct device_req *arg = &dev->dev_req;
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
&& USB_SETUP_SET (req) && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
&& USB_SETUP_SET (arg->type)
&& arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
{
struct tty *t = tty_get (arg->index, 0);
@@ -272,60 +274,65 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
}
static int
vcom_port_data_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
vcom_port_data_setup (struct usb_dev *dev)
{
if (USB_SETUP_GET (req))
struct device_req *arg = &dev->dev_req;
if (USB_SETUP_GET (arg->type))
{
struct tty *t = tty_get (arg->index, 0);
if (req_no == USB_CDC_REQ_GET_LINE_CODING)
return usb_lld_reply_request (&t->line_coding,
sizeof (struct line_coding), arg);
if (arg->request == USB_CDC_REQ_GET_LINE_CODING)
return usb_lld_ctrl_send (dev, &t->line_coding,
sizeof (struct line_coding));
}
else /* USB_SETUP_SET (req) */
{
if (req_no == USB_CDC_REQ_SET_LINE_CODING
if (arg->request == USB_CDC_REQ_SET_LINE_CODING
&& arg->len == sizeof (struct line_coding))
{
struct tty *t = tty_get (arg->index, 0);
usb_lld_set_data_to_recv (&t->line_coding,
return usb_lld_ctrl_recv (dev, &t->line_coding,
sizeof (struct line_coding));
return USB_SUCCESS;
}
else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
return USB_SUCCESS;
else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
return usb_lld_ctrl_ack (dev);
}
return USB_UNSUPPORT;
return -1;
}
int
usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
static int
usb_setup (struct usb_dev *dev)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
struct device_req *arg = &dev->dev_req;
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0)
return vcom_port_data_setup (req, req_no, arg);
return vcom_port_data_setup (dev);
return USB_UNSUPPORT;
return -1;
}
int
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
struct req_args *arg)
static int
usb_get_descriptor (struct usb_dev *dev)
{
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
uint8_t desc_type = (arg->value >> 8);
uint8_t desc_index = (arg->value & 0xff);
if (rcp != DEVICE_RECIPIENT)
return USB_UNSUPPORT;
return -1;
if (desc_type == DEVICE_DESCRIPTOR)
return usb_lld_reply_request (vcom_device_desc, sizeof (vcom_device_desc),
arg);
return usb_lld_ctrl_send (dev,
vcom_device_desc, sizeof (vcom_device_desc));
else if (desc_type == CONFIG_DESCRIPTOR)
return usb_lld_reply_request (vcom_config_desc, sizeof (vcom_config_desc),
arg);
return usb_lld_ctrl_send (dev,
vcom_config_desc, sizeof (vcom_config_desc));
else if (desc_type == STRING_DESCRIPTOR)
{
const uint8_t *str;
@@ -350,22 +357,23 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
size = sizeof (vcom_string3);
break;
default:
return USB_UNSUPPORT;
return -1;
}
return usb_lld_reply_request (str, size, arg);
return usb_lld_ctrl_send (dev, str, size);
}
return USB_UNSUPPORT;
return -1;
}
static void
vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
vcom_setup_endpoints_for_interface (struct usb_dev *dev,
uint16_t interface, int stop)
{
if (interface == 0)
{
if (!stop)
usb_lld_setup_endp (ENDP2, 0, 1);
usb_lld_setup_endp (dev, ENDP2, 0, 1);
else
usb_lld_stall (ENDP2);
}
@@ -373,8 +381,8 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
{
if (!stop)
{
usb_lld_setup_endp (ENDP1, 0, 1);
usb_lld_setup_endp (ENDP3, 1, 0);
usb_lld_setup_endp (dev, ENDP1, 0, 1);
usb_lld_setup_endp (dev, ENDP3, 1, 0);
/* Start with no data receiving (ENDP3 not enabled)*/
}
else
@@ -385,83 +393,85 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
}
}
int
usb_cb_handle_event (uint8_t event_type, uint16_t value)
static int
usb_set_configuration (struct usb_dev *dev)
{
int i;
uint8_t current_conf;
switch (event_type)
{
case USB_EVENT_ADDRESS:
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = ADDRESSED;
chopstx_mutex_unlock (&tty0.mtx);
return USB_SUCCESS;
case USB_EVENT_CONFIG:
current_conf = usb_lld_current_configuration ();
current_conf = usb_lld_current_configuration (dev);
if (current_conf == 0)
{
if (value != 1)
return USB_UNSUPPORT;
if (dev->dev_req.value != 1)
return -1;
usb_lld_set_configuration (1);
usb_lld_set_configuration (dev, 1);
for (i = 0; i < NUM_INTERFACES; i++)
vcom_setup_endpoints_for_interface (i, 0);
vcom_setup_endpoints_for_interface (dev, i, 0);
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = CONFIGURED;
chopstx_cond_signal (&tty0.cnd);
chopstx_mutex_unlock (&tty0.mtx);
}
else if (current_conf != value)
else if (current_conf != dev->dev_req.value)
{
if (value != 0)
return USB_UNSUPPORT;
if (dev->dev_req.value != 0)
return -1;
usb_lld_set_configuration (0);
usb_lld_set_configuration (dev, 0);
for (i = 0; i < NUM_INTERFACES; i++)
vcom_setup_endpoints_for_interface (i, 1);
vcom_setup_endpoints_for_interface (dev, i, 1);
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = ADDRESSED;
chopstx_cond_signal (&tty0.cnd);
chopstx_mutex_unlock (&tty0.mtx);
}
/* Do nothing when current_conf == value */
return USB_SUCCESS;
default:
break;
}
return USB_UNSUPPORT;
return usb_lld_ctrl_ack (dev);
}
int
usb_cb_interface (uint8_t cmd, struct req_args *arg)
static int
usb_set_interface (struct usb_dev *dev)
{
const uint8_t zero = 0;
uint16_t interface = arg->index;
uint16_t alt = arg->value;
uint16_t interface = dev->dev_req.index;
uint16_t alt = dev->dev_req.value;
if (interface >= NUM_INTERFACES)
return USB_UNSUPPORT;
return -1;
switch (cmd)
{
case USB_SET_INTERFACE:
if (alt != 0)
return USB_UNSUPPORT;
return -1;
else
{
vcom_setup_endpoints_for_interface (interface, 0);
return USB_SUCCESS;
vcom_setup_endpoints_for_interface (dev, interface, 0);
return usb_lld_ctrl_ack (dev);
}
}
case USB_GET_INTERFACE:
return usb_lld_reply_request (&zero, 1, arg);
static int
usb_get_interface (struct usb_dev *dev)
{
const uint8_t zero = 0;
uint16_t interface = dev->dev_req.index;
default:
case USB_QUERY_INTERFACE:
return USB_SUCCESS;
}
if (interface >= NUM_INTERFACES)
return -1;
/* We don't have alternate interface, so, always return 0. */
return usb_lld_ctrl_send (dev, &zero, 1);
}
static int
usb_get_status_interface (struct usb_dev *dev)
{
const uint16_t status_info = 0;
uint16_t interface = dev->dev_req.index;
if (interface >= NUM_INTERFACES)
return -1;
return usb_lld_ctrl_send (dev, &status_info, 2);
}
@@ -511,8 +521,8 @@ tty_echo_char (struct tty *t, int c)
put_char_to_ringbuffer (t, c);
}
void
usb_cb_tx_done (uint8_t ep_num, uint32_t len)
static void
usb_tx_done (uint8_t ep_num, uint16_t len)
{
struct tty *t = tty_get (-1, ep_num);
@@ -594,17 +604,16 @@ tty_input_char (struct tty *t, int c)
return r;
}
void
usb_cb_rx_ready (uint8_t ep_num)
static void
usb_rx_ready (uint8_t ep_num, uint16_t len)
{
struct tty *t = tty_get (-1, ep_num);
if (ep_num == ENDP3)
{
int i, r;
int i;
r = usb_lld_rx_data_len (ENDP3);
for (i = 0; i < r; i++)
for (i = 0; i < len; i++)
if (tty_input_char (t, t->recv_buf0[i]))
break;
@@ -620,9 +629,9 @@ static void *tty_main (void *arg);
#define INTR_REQ_USB 24
#define PRIO_TTY 4
extern uint8_t __process3_stack_base__, __process3_stack_size__;
const uint32_t __stackaddr_tty = (uint32_t)&__process3_stack_base__;
const size_t __stacksize_tty = (size_t)&__process3_stack_size__;
extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
#define STACK_ADDR_TTY ((uint32_t)__process3_stack_base__)
#define STACK_SIZE_TTY ((uint32_t)__process3_stack_size__)
struct tty *
tty_open (void)
@@ -637,7 +646,7 @@ tty_open (void)
tty0.device_state = UNCONNECTED;
memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
chopstx_create (PRIO_TTY, __stackaddr_tty, __stacksize_tty, tty_main, &tty0);
chopstx_create (PRIO_TTY, STACK_ADDR_TTY, STACK_SIZE_TTY, tty_main, &tty0);
return &tty0;
}
@@ -646,6 +655,8 @@ static void *
tty_main (void *arg)
{
struct tty *t = arg;
struct usb_dev dev;
int e;
#if defined(OLDER_SYS_H)
/*
@@ -654,9 +665,9 @@ tty_main (void *arg)
*
* When USB interrupt occurs between usb_lld_init (which assumes
* ISR) and chopstx_claim_irq (which clears pending interrupt),
* invocation of usb_interrupt_handler won't occur.
* invocation of usb_lld_event_handler won't occur.
*
* Calling usb_interrupt_handler is no harm even if there were no
* Calling usb_lld_event_handler is no harm even if there were no
* interrupts, thus, we call it unconditionally here, just in case
* if there is a request.
*
@@ -665,19 +676,117 @@ tty_main (void *arg)
* chopstx_claim_irq after usb_lld_init overrides that.
*
*/
usb_lld_init (VCOM_FEATURE_BUS_POWERED);
usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
usb_interrupt_handler ();
goto event_handle;
#else
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
usb_lld_init (VCOM_FEATURE_BUS_POWERED);
usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
#endif
while (1)
{
chopstx_poll (NULL, 1, &usb_intr);
struct chx_poll_head *pd_array[1] = {
(struct chx_poll_head *)&usb_intr
};
chopstx_poll (NULL, 1, pd_array);
if (usb_intr.ready)
usb_interrupt_handler ();
{
uint8_t ep_num;
#if defined(OLDER_SYS_H)
event_handle:
#endif
/*
* When interrupt is detected, call usb_lld_event_handler.
* The event may be one of following:
* (1) Transfer to endpoint (bulk or interrupt)
* In this case EP_NUM is encoded in the variable E.
* (2) "NONE" event: some trasfer was done, but all was
* done by lower layer, no other work is needed in
* upper layer.
* (3) Device events: Reset or Suspend
* (4) Device requests to the endpoint zero.
*
*/
e = usb_lld_event_handler (&dev);
ep_num = USB_EVENT_ENDP (e);
if (ep_num != 0)
{
if (USB_EVENT_TXRX (e))
usb_tx_done (ep_num, USB_EVENT_LEN (e));
else
usb_rx_ready (ep_num, USB_EVENT_LEN (e));
}
else
switch (USB_EVENT_ID (e))
{
case USB_EVENT_DEVICE_RESET:
usb_device_reset (&dev);
continue;
case USB_EVENT_DEVICE_ADDRESSED:
/* The addres is assigned to the device. We don't
* need to do anything for this actually, but in this
* application, we maintain the USB status of the
* device. Usually, just "continue" as EVENT_OK is
* OK.
*/
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = ADDRESSED;
chopstx_cond_signal (&tty0.cnd);
chopstx_mutex_unlock (&tty0.mtx);
continue;
case USB_EVENT_GET_DESCRIPTOR:
if (usb_get_descriptor (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_SET_CONFIGURATION:
if (usb_set_configuration (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_SET_INTERFACE:
if (usb_set_interface (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_CTRL_REQUEST:
/* Device specific device request. */
if (usb_setup (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_GET_STATUS_INTERFACE:
if (usb_get_status_interface (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_GET_INTERFACE:
if (usb_get_interface (&dev) < 0)
usb_lld_ctrl_error (&dev);
continue;
case USB_EVENT_SET_FEATURE_DEVICE:
case USB_EVENT_SET_FEATURE_ENDPOINT:
case USB_EVENT_CLEAR_FEATURE_DEVICE:
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
usb_lld_ctrl_ack (&dev);
continue;
case USB_EVENT_CTRL_WRITE_FINISH:
/* Control WRITE transfer finished. */
usb_ctrl_write_finish (&dev);
continue;
case USB_EVENT_OK:
case USB_EVENT_DEVICE_SUSPEND:
default:
continue;
}
}
chopstx_mutex_lock (&t->mtx);
if (t->device_state == CONFIGURED && t->flag_connected
@@ -720,8 +829,7 @@ tty_wait_connection (struct tty *t)
t->flag_input_avail = 0;
t->send_head = t->send_tail = 0;
t->inputline_len = 0;
/* Accept input for line */
usb_lld_rx_enable_buf (ENDP3, t->recv_buf0, 64);
usb_lld_rx_enable_buf (ENDP3, t->recv_buf0, 64); /* Accept input for line */
chopstx_mutex_unlock (&t->mtx);
}
@@ -738,10 +846,10 @@ check_tx (struct tty *t)
}
int
tty_send (struct tty *t, const uint8_t *buf, int len)
tty_send (struct tty *t, const char *buf, int len)
{
int r;
const uint8_t *p;
const char *p;
int count;
p = buf;
@@ -800,7 +908,7 @@ check_rx (void *arg)
*
*/
int
tty_recv (struct tty *t, uint8_t *buf, uint32_t *timeout)
tty_recv (struct tty *t, char *buf, uint32_t *timeout)
{
int r;
chopstx_poll_cond_t poll_desc;
@@ -814,7 +922,10 @@ tty_recv (struct tty *t, uint8_t *buf, uint32_t *timeout)
while (1)
{
chopstx_poll (timeout, 1, &poll_desc);
struct chx_poll_head *pd_array[1] = {
(struct chx_poll_head *)&poll_desc
};
chopstx_poll (timeout, 1, pd_array);
chopstx_mutex_lock (&t->mtx);
r = check_rx (t);
chopstx_mutex_unlock (&t->mtx);

View File

@@ -34,8 +34,8 @@ struct GPIO {
#define GPIOF_BASE (AHB2PERIPH_BASE + 0x1400)
#define GPIOF ((struct GPIO *) GPIOF_BASE)
static struct GPIO *const GPIO_LED = ((struct GPIO *const) GPIO_LED_BASE);
static struct GPIO *const GPIO_OTHER = ((struct GPIO *const) GPIO_OTHER_BASE);
static struct GPIO *const GPIO_LED = ((struct GPIO *)GPIO_LED_BASE);
static struct GPIO *const GPIO_OTHER = ((struct GPIO *)GPIO_OTHER_BASE);
static chopstx_mutex_t mtx;
static chopstx_cond_t cnd0, cnd1;
@@ -166,14 +166,14 @@ button (void *arg)
#define PRIO_LED 3
#define PRIO_BUTTON 2
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process2_stack_base__, __process2_stack_size__;
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
const size_t __stacksize_led = (size_t)&__process1_stack_size__;
#define STACK_ADDR_LED ((uint32_t)__process1_stack_base__)
#define STACK_SIZE_LED ((uint32_t)__process1_stack_size__)
const uint32_t __stackaddr_button = (uint32_t)&__process2_stack_base__;
const size_t __stacksize_button = (size_t)&__process2_stack_size__;
#define STACK_ADDR_BUTTON ((uint32_t)__process2_stack_base__)
#define STACK_SIZE_BUTTON ((uint32_t)__process2_stack_size__)
#define DATA55(x0,x1,x2,x3,x4) (x0<<20)|(x1<<15)|(x2<<10)|(x3<< 5)|(x4<< 0)
#define SIZE55(img) (sizeof (img) / sizeof (uint32_t))
@@ -382,10 +382,10 @@ main (int argc, const char *argv[])
chopstx_cond_init (&cnd0);
chopstx_cond_init (&cnd1);
led_thd = chopstx_create (PRIO_LED, __stackaddr_led,
__stacksize_led, led, NULL);
button_thd = chopstx_create (PRIO_BUTTON, __stackaddr_button,
__stacksize_button, button, NULL);
led_thd = chopstx_create (PRIO_LED, STACK_ADDR_LED,
STACK_SIZE_LED, led, NULL);
button_thd = chopstx_create (PRIO_BUTTON, STACK_ADDR_BUTTON,
STACK_SIZE_BUTTON, button, NULL);
chopstx_usec_wait (200*1000);
@@ -450,7 +450,7 @@ struct SCB
#define SCS_BASE (0xE000E000)
#define SCB_BASE (SCS_BASE + 0x0D00)
static struct SCB *const SCB = ((struct SCB *const) SCB_BASE);
static struct SCB *const SCB = ((struct SCB *)SCB_BASE);
#define SCB_SCR_SLEEPDEEP (1 << 2)

View File

@@ -34,8 +34,8 @@ struct GPIO {
#define GPIOF_BASE (AHB2PERIPH_BASE + 0x1400)
#define GPIOF ((struct GPIO *) GPIOF_BASE)
static struct GPIO *const GPIO_LED = ((struct GPIO *const) GPIO_LED_BASE);
static struct GPIO *const GPIO_OTHER = ((struct GPIO *const) GPIO_OTHER_BASE);
static struct GPIO *const GPIO_LED = ((struct GPIO *)GPIO_LED_BASE);
static struct GPIO *const GPIO_OTHER = ((struct GPIO *)GPIO_OTHER_BASE);
static chopstx_mutex_t mtx;
static chopstx_cond_t cnd0, cnd1;
@@ -166,14 +166,14 @@ button (void *arg)
#define PRIO_LED 3
#define PRIO_BUTTON 2
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process2_stack_base__, __process2_stack_size__;
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
const size_t __stacksize_led = (size_t)&__process1_stack_size__;
#define STACK_ADDR_LED ((uint32_t)__process1_stack_base__)
#define STACK_SIZE_LED ((uint32_t)__process1_stack_size__)
const uint32_t __stackaddr_button = (uint32_t)&__process2_stack_base__;
const size_t __stacksize_button = (size_t)&__process2_stack_size__;
#define STACK_ADDR_BUTTON ((uint32_t)__process2_stack_base__)
#define STACK_SIZE_BUTTON ((uint32_t)__process2_stack_size__)
#define DATA55(x0,x1,x2,x3,x4) (x0<<20)|(x1<<15)|(x2<<10)|(x3<< 5)|(x4<< 0)
#define SIZE55(img) (sizeof (img) / sizeof (uint32_t))
@@ -370,10 +370,10 @@ main (int argc, const char *argv[])
chopstx_cond_init (&cnd0);
chopstx_cond_init (&cnd1);
led_thd = chopstx_create (PRIO_LED, __stackaddr_led,
__stacksize_led, led, NULL);
button_thd = chopstx_create (PRIO_BUTTON, __stackaddr_button,
__stacksize_button, button, NULL);
led_thd = chopstx_create (PRIO_LED, STACK_ADDR_LED,
STACK_SIZE_LED, led, NULL);
button_thd = chopstx_create (PRIO_BUTTON, STACK_ADDR_BUTTON,
STACK_SIZE_BUTTON, button, NULL);
chopstx_usec_wait (200*1000);
@@ -438,7 +438,7 @@ struct SCB
#define SCS_BASE (0xE000E000)
#define SCB_BASE (SCS_BASE + 0x0D00)
static struct SCB *const SCB = ((struct SCB *const) SCB_BASE);
static struct SCB *const SCB = ((struct SCB *)SCB_BASE);
#define SCB_SCR_SLEEPDEEP (1 << 2)

View File

@@ -35,8 +35,8 @@ struct GPIO {
#define GPIO_SPEAKER_PIN 1
static struct GPIO *const GPIO_LED = ((struct GPIO *const) GPIO_LED_BASE);
static struct GPIO *const GPIO_OTHER = ((struct GPIO *const) GPIO_OTHER_BASE);
static struct GPIO *const GPIO_LED = ((struct GPIO *)GPIO_LED_BASE);
static struct GPIO *const GPIO_OTHER = ((struct GPIO *)GPIO_OTHER_BASE);
static chopstx_mutex_t mtx;
static chopstx_cond_t cnd;
@@ -88,10 +88,10 @@ led_enable_column (uint8_t col)
#define PRIO_LED 3
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
const uint32_t stackaddr_led = (uint32_t)&__process1_stack_base__;
const size_t stacksize_led = (size_t)&__process1_stack_size__;
#define STACK_ADDR_LED ((uint32_t)__process1_stack_base__)
#define STACK_SIZE_LED ((uint32_t)__process1_stack_size__)
static void *
led (void *arg)
@@ -119,10 +119,10 @@ led (void *arg)
#define PRIO_SPK 4
extern uint8_t __process2_stack_base__, __process2_stack_size__;
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
const uint32_t stackaddr_spk = (uint32_t)&__process2_stack_base__;
const size_t stacksize_spk = (size_t)&__process2_stack_size__;
#define STACK_ADDR_SPK ((uint32_t)__process2_stack_base__)
#define STACK_SIZE_SPK ((uint32_t)__process2_stack_size__)
static chopstx_mutex_t spk_mtx;
static chopstx_cond_t spk_cnd;
@@ -193,10 +193,10 @@ spk (void *arg)
#define PRIO_MUSIC 2
extern uint8_t __process3_stack_base__, __process3_stack_size__;
extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
const uint32_t stackaddr_music = (uint32_t)&__process3_stack_base__;
const size_t stacksize_music = (size_t)&__process3_stack_size__;
#define STACK_ADDR_MUSIC ((uint32_t)__process3_stack_base__)
#define STACK_SIZE_MUSIC ((uint32_t)__process3_stack_size__)
#define C 0
#define D 1
@@ -254,7 +254,7 @@ music (void *arg)
chopstx_cond_init (&spk_cnd);
chopstx_cond_init (&spk_cnd_no_tone);
chopstx_create (PRIO_SPK, stackaddr_spk, stacksize_spk, spk, NULL);
chopstx_create (PRIO_SPK, STACK_ADDR_SPK, STACK_SIZE_SPK, spk, NULL);
while (1)
{
@@ -350,8 +350,8 @@ main (int argc, const char *argv[])
chopstx_mutex_init (&mtx);
chopstx_cond_init (&cnd);
chopstx_create (PRIO_LED, stackaddr_led, stacksize_led, led, NULL);
chopstx_create (PRIO_MUSIC, stackaddr_music, stacksize_music, music, NULL);
chopstx_create (PRIO_LED, STACK_ADDR_LED, STACK_SIZE_LED, led, NULL);
chopstx_create (PRIO_MUSIC, STACK_ADDR_MUSIC, STACK_SIZE_MUSIC, music, NULL);
chopstx_usec_wait (200*1000);

View File

@@ -10,7 +10,7 @@ LDSCRIPT= sample.ld
### LDSCRIPT= sample.ld.m3
CSRC = sample.c
CHIP=stm32f030
CHIP=stm32f0
USE_SYS = yes
###################################

View File

@@ -72,14 +72,14 @@ blk (void *arg)
#define PRIO_BLK 2
#endif
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process2_stack_base__, __process2_stack_size__;
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
const uint32_t __stackaddr_pwm = (uint32_t)&__process1_stack_base__;
const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
#define STACK_ADDR_PWM ((uint32_t)__process1_stack_base__)
#define STACK_SIZE_PWM ((uint32_t)__process1_stack_size__)
const uint32_t __stackaddr_blk = (uint32_t)&__process2_stack_base__;
const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
#define STACK_ADDR_BLK ((uint32_t)__process2_stack_base__)
#define STACK_SIZE_BLK ((uint32_t)__process2_stack_size__)
int
@@ -94,8 +94,8 @@ main (int argc, const char *argv[])
m = 10;
chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL);
chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL);
chopstx_create (PRIO_PWM, STACK_ADDR_PWM, STACK_SIZE_PWM, pwm, NULL);
chopstx_create (PRIO_BLK, STACK_ADDR_BLK, STACK_SIZE_BLK, blk, NULL);
chopstx_usec_wait (200*1000);

View File

@@ -1,5 +1,5 @@
/*
* clk_gpio_init-kl.c - Clock and GPIO initialization for Kinetis L.
* clk_gpio_init-mkl27z.c - Clock and GPIO initialization for Kinetis L.
*
* Copyright (C) 2016 Flying Stone Technology
* Author: NIIBE Yutaka <gniibe@fsij.org>
@@ -38,7 +38,7 @@ struct MCG {
uint8_t reserved2[15]; /* */
volatile uint8_t MC; /* MCG Miscellaneous Control Register */
};
static struct MCG *const MCG = (struct MCG *const)0x40064000;
static struct MCG *const MCG = (struct MCG *)0x40064000;
struct USB_CLK_RECOVER {
volatile uint8_t CTRL; /* USB Clock */
@@ -51,7 +51,7 @@ struct USB_CLK_RECOVER {
/* interrupt status */
};
static struct USB_CLK_RECOVER *const USB_CLK_RECOVER =
(struct USB_CLK_RECOVER *const)0x40072140;
(struct USB_CLK_RECOVER *)0x40072140;
static void __attribute__((used))
clock_init (void)
@@ -66,10 +66,12 @@ clock_init (void)
while ((MCG->S & 0x0c) != 0)
;
SIM->SOPT2 = 0x00040060; /* USBSRC=IRC48, CLOKOUTSEL=LPO, RTC-clock */
/* TPMSRC=IRC48M, USBSRC=IRC48M, CLOKOUTSEL=LPO, RTC-clock */
SIM->SOPT2 = 0x01040060;
SIM->SCGC4 = (1 << 18); /* Enable USB FS clock */
SIM->SCGC5 = (1 << 10); /* Enable Port B clock */
SIM->SCGC6 = (1 << 25)|1; /* Enable TPM1 clock */
SIM->COPC = 0; /* COP disabled */
/* Crystal-less USB setup. */
@@ -78,44 +80,6 @@ clock_init (void)
}
struct PORT {
volatile uint32_t PCR0; volatile uint32_t PCR1;
volatile uint32_t PCR2; volatile uint32_t PCR3;
volatile uint32_t PCR4; volatile uint32_t PCR5;
volatile uint32_t PCR6; volatile uint32_t PCR7;
volatile uint32_t PCR8; volatile uint32_t PCR9;
volatile uint32_t PCR10; volatile uint32_t PCR11;
volatile uint32_t PCR12; volatile uint32_t PCR13;
volatile uint32_t PCR14; volatile uint32_t PCR15;
volatile uint32_t PCR16; volatile uint32_t PCR17;
volatile uint32_t PCR18; volatile uint32_t PCR19;
volatile uint32_t PCR20; volatile uint32_t PCR21;
volatile uint32_t PCR22; volatile uint32_t PCR23;
volatile uint32_t PCR24; volatile uint32_t PCR25;
volatile uint32_t PCR26; volatile uint32_t PCR27;
volatile uint32_t PCR28; volatile uint32_t PCR29;
volatile uint32_t PCR30; volatile uint32_t PCR31;
volatile uint32_t GPCLR; volatile uint32_t GPCHR;
uint32_t reserved[6];
volatile uint32_t ISFR;
};
static struct PORT *const PORTB = (struct PORT *const)0x4004A000;
static struct PORT *const PORTD = (struct PORT *const)0x4004C000;
static struct PORT *const PORTE = (struct PORT *const)0x4004D000;
struct GPIO {
volatile uint32_t PDOR; /* Port Data Output Register */
volatile uint32_t PSOR; /* Port Set Output Register */
volatile uint32_t PCOR; /* Port Clear Output Register */
volatile uint32_t PTOR; /* Port Toggle Output Register */
volatile uint32_t PDIR; /* Port Data Input Register */
volatile uint32_t PDDR; /* Port Data Direction Register */
};
static struct GPIO *const GPIOB = (struct GPIO *const)0x400FF040;
static struct GPIO *const GPIOD = (struct GPIO *const)0x400FF0C0;
static struct GPIO *const GPIOE = (struct GPIO *const)0x400FF100;
static void __attribute__((used))
gpio_init (void)
{
@@ -124,14 +88,14 @@ gpio_init (void)
| (0<<4) /* PassiveFilterEnable=0 */
| (1<<2) /* SlewRateEnable = slow */
| (0<<1) /* pull enable = 0 */
| (0<<0) /* puddselect= 0 */
| (0<<0) /* pull up select= 0 */
;
PORTB->PCR1 = (1<<8) /* GPIO */
| (0<<6) /* DriveStrengthEnable=0 */
| (0<<4) /* PassiveFilterEnable=0 */
| (1<<2) /* SlewRateEnable = slow */
| (0<<1) /* pull enable = 0 */
| (0<<0) /* puddselect= 0 */
| (0<<0) /* pull up select= 0 */
;
GPIOB->PDDR = (1 << 1) | (1 << 0); /* PTB0, PTB1 : Output */

View File

@@ -100,7 +100,7 @@ struct RCC {
};
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
static struct RCC *const RCC = ((struct RCC *const)RCC_BASE);
static struct RCC *const RCC = (struct RCC *)RCC_BASE;
#define RCC_APB1ENR_USBEN 0x00800000
#define RCC_APB1RSTR_USBRST 0x00800000
@@ -163,7 +163,7 @@ struct SYSCFG {
#define SYSCFG_CFGR1_MEM_MODE 0x03
#define SYSCFG_BASE (APBPERIPH_BASE + 0x00010000)
static struct SYSCFG *const SYSCFG = ((struct SYSCFG *const) SYSCFG_BASE);
static struct SYSCFG *const SYSCFG = (struct SYSCFG *)SYSCFG_BASE;
#endif
struct FLASH {
@@ -179,7 +179,7 @@ struct FLASH {
};
#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000)
static struct FLASH *const FLASH = ((struct FLASH *const) FLASH_R_BASE);
static struct FLASH *const FLASH = (struct FLASH *)FLASH_R_BASE;
static void __attribute__((used))
clock_init (void)
@@ -279,7 +279,7 @@ struct AFIO
};
#define AFIO_BASE 0x40010000
static struct AFIO *const AFIO = (struct AFIO *const)AFIO_BASE;
static struct AFIO *const AFIO = (struct AFIO *)AFIO_BASE;
#define AFIO_MAPR_TIM3_REMAP_PARTIALREMAP 0x00000800
#define AFIO_MAPR_SWJ_CFG_DISABLE 0x04000000
@@ -308,12 +308,12 @@ struct GPIO {
#define GPIOE ((struct GPIO *) GPIOE_BASE)
#endif
static struct GPIO *const GPIO_LED = ((struct GPIO *const) GPIO_LED_BASE);
static struct GPIO *const GPIO_LED = (struct GPIO *)GPIO_LED_BASE;
#ifdef GPIO_USB_BASE
static struct GPIO *const GPIO_USB = ((struct GPIO *const) GPIO_USB_BASE);
static struct GPIO *const GPIO_USB = (struct GPIO *)GPIO_USB_BASE;
#endif
#ifdef GPIO_OTHER_BASE
static struct GPIO *const GPIO_OTHER = ((struct GPIO *const) GPIO_OTHER_BASE);
static struct GPIO *const GPIO_OTHER = (struct GPIO *)GPIO_OTHER_BASE;
#endif
static void __attribute__((used))

View File

@@ -28,4 +28,43 @@ struct SIM {
volatile uint32_t COPC; /* COP Control Register */
volatile uint32_t SRVCOP; /* Service COP */
};
static struct SIM *const SIM = (struct SIM *const)0x40047000;
/* Port control. */
struct PORT {
volatile uint32_t PCR0; volatile uint32_t PCR1;
volatile uint32_t PCR2; volatile uint32_t PCR3;
volatile uint32_t PCR4; volatile uint32_t PCR5;
volatile uint32_t PCR6; volatile uint32_t PCR7;
volatile uint32_t PCR8; volatile uint32_t PCR9;
volatile uint32_t PCR10; volatile uint32_t PCR11;
volatile uint32_t PCR12; volatile uint32_t PCR13;
volatile uint32_t PCR14; volatile uint32_t PCR15;
volatile uint32_t PCR16; volatile uint32_t PCR17;
volatile uint32_t PCR18; volatile uint32_t PCR19;
volatile uint32_t PCR20; volatile uint32_t PCR21;
volatile uint32_t PCR22; volatile uint32_t PCR23;
volatile uint32_t PCR24; volatile uint32_t PCR25;
volatile uint32_t PCR26; volatile uint32_t PCR27;
volatile uint32_t PCR28; volatile uint32_t PCR29;
volatile uint32_t PCR30; volatile uint32_t PCR31;
volatile uint32_t GPCLR; volatile uint32_t GPCHR;
uint32_t reserved[6];
volatile uint32_t ISFR;
};
struct GPIO {
volatile uint32_t PDOR; /* Port Data Output Register */
volatile uint32_t PSOR; /* Port Set Output Register */
volatile uint32_t PCOR; /* Port Clear Output Register */
volatile uint32_t PTOR; /* Port Toggle Output Register */
volatile uint32_t PDIR; /* Port Data Input Register */
volatile uint32_t PDDR; /* Port Data Direction Register */
};
static struct SIM *const SIM = (struct SIM *)0x40047000;
static struct PORT *const PORTB = (struct PORT *)0x4004A000;
static struct PORT *const PORTD = (struct PORT *)0x4004C000;
static struct PORT *const PORTE = (struct PORT *)0x4004D000;
static struct GPIO *const GPIOB = (struct GPIO *)0x400FF040;
static struct GPIO *const GPIOD = (struct GPIO *)0x400FF0C0;
static struct GPIO *const GPIOE = (struct GPIO *)0x400FF100;

View File

@@ -1,10 +1,8 @@
#define PERIPH_BASE 0x40000000
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
#define RCC_APB2RSTR_ADC1RST 0x00000200
#define RCC_APB2RSTR_ADC2RST 0x00000400
struct RCC {
volatile uint32_t CR;
volatile uint32_t CFGR;
@@ -19,13 +17,24 @@ struct RCC {
};
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
static struct RCC *const RCC = ((struct RCC *const)RCC_BASE);
static struct RCC *const RCC = (struct RCC *)RCC_BASE;
#define RCC_AHBENR_DMA1EN 0x00000001
#define RCC_AHBENR_CRCEN 0x00000040
#define RCC_APB2ENR_ADC1EN 0x00000200
#define RCC_APB2ENR_ADC2EN 0x00000400
#define RCC_APB2ENR_TIM1EN 0x00000800
#define RCC_APB1ENR_TIM2EN 0x00000001
#define RCC_APB1ENR_TIM3EN 0x00000002
#define RCC_APB1ENR_TIM4EN 0x00000004
#define RCC_APB2RSTR_ADC1RST 0x00000200
#define RCC_APB2RSTR_ADC2RST 0x00000400
#define RCC_APB2RSTR_TIM1RST 0x00000800
#define RCC_APB1RSTR_TIM2RST 0x00000001
#define RCC_APB1RSTR_TIM3RST 0x00000002
#define RCC_APB1RSTR_TIM4RST 0x00000004
#define CRC_CR_RESET 0x00000001
@@ -38,7 +47,7 @@ struct CRC {
};
#define CRC_BASE (AHBPERIPH_BASE + 0x3000)
static struct CRC *const CRC = ((struct CRC *const)CRC_BASE);
static struct CRC *const CRC = (struct CRC *)CRC_BASE;
struct ADC {
@@ -67,8 +76,8 @@ struct ADC {
#define ADC1_BASE (APB2PERIPH_BASE + 0x2400)
#define ADC2_BASE (APB2PERIPH_BASE + 0x2800)
static struct ADC *const ADC1 = (struct ADC *const)ADC1_BASE;
static struct ADC *const ADC2 = (struct ADC *const)ADC2_BASE;
static struct ADC *const ADC1 = (struct ADC *)ADC1_BASE;
static struct ADC *const ADC2 = (struct ADC *)ADC2_BASE;
#define ADC_CR1_DUALMOD_0 0x00010000
#define ADC_CR1_DUALMOD_1 0x00020000
@@ -167,11 +176,11 @@ struct DMA {
#define DMA_ISR_TEIF7 0x08000000
#define DMA1_BASE (AHBPERIPH_BASE + 0x0000)
static struct DMA *const DMA1 = (struct DMA *const)DMA1_BASE;
static struct DMA *const DMA1 = (struct DMA *)DMA1_BASE;
#define DMA1_Channel1_BASE (AHBPERIPH_BASE + 0x0008)
static struct DMA_Channel *const DMA1_Channel1 =
(struct DMA_Channel *const)DMA1_Channel1_BASE;
(struct DMA_Channel *)DMA1_Channel1_BASE;
/* System Control Block */
struct SCB
@@ -201,4 +210,491 @@ struct SCB
#define SCS_BASE 0xE000E000
#define SCB_BASE (SCS_BASE + 0x0D00)
static struct SCB *const SCB = (struct SCB *const)SCB_BASE;
static struct SCB *const SCB = (struct SCB *)SCB_BASE;
/* Timer */
struct TIM
{
volatile uint16_t CR1; uint16_t RESERVED0;
volatile uint16_t CR2; uint16_t RESERVED1;
volatile uint16_t SMCR; uint16_t RESERVED2;
volatile uint16_t DIER; uint16_t RESERVED3;
volatile uint16_t SR; uint16_t RESERVED4;
volatile uint16_t EGR; uint16_t RESERVED5;
volatile uint16_t CCMR1; uint16_t RESERVED6;
volatile uint16_t CCMR2; uint16_t RESERVED7;
volatile uint16_t CCER; uint16_t RESERVED8;
volatile uint16_t CNT; uint16_t RESERVED9;
volatile uint16_t PSC; uint16_t RESERVED10;
volatile uint16_t ARR; uint16_t RESERVED11;
volatile uint16_t RCR; uint16_t RESERVED12;
volatile uint16_t CCR1; uint16_t RESERVED13;
volatile uint16_t CCR2; uint16_t RESERVED14;
volatile uint16_t CCR3; uint16_t RESERVED15;
volatile uint16_t CCR4; uint16_t RESERVED16;
volatile uint16_t BDTR; uint16_t RESERVED17;
volatile uint16_t DCR; uint16_t RESERVED18;
volatile uint16_t DMAR; uint16_t RESERVED19;
};
#define TIM2_BASE 0x40000000
#define TIM3_BASE 0x40000400
#define TIM4_BASE 0x40000800
static struct TIM *const TIM2 = (struct TIM *)TIM2_BASE;
static struct TIM *const TIM3 = (struct TIM *)TIM3_BASE;
static struct TIM *const TIM4 = (struct TIM *)TIM4_BASE;
#define TIM_CR1_CEN 0x0001
#define TIM_CR1_UDIS 0x0002
#define TIM_CR1_URS 0x0004
#define TIM_CR1_OPM 0x0008
#define TIM_CR1_DIR 0x0010
#define TIM_CR1_CMS 0x0060
#define TIM_CR1_CMS_0 0x0020
#define TIM_CR1_CMS_1 0x0040
#define TIM_CR1_ARPE 0x0080
#define TIM_CR1_CKD 0x0300
#define TIM_CR1_CKD_0 0x0100
#define TIM_CR1_CKD_1 0x0200
#define TIM_CR2_CCPC 0x0001
#define TIM_CR2_CCUS 0x0004
#define TIM_CR2_CCDS 0x0008
#define TIM_CR2_MMS 0x0070
#define TIM_CR2_MMS_0 0x0010
#define TIM_CR2_MMS_1 0x0020
#define TIM_CR2_MMS_2 0x0040
#define TIM_CR2_TI1S 0x0080
#define TIM_CR2_OIS1 0x0100
#define TIM_CR2_OIS1N 0x0200
#define TIM_CR2_OIS2 0x0400
#define TIM_CR2_OIS2N 0x0800
#define TIM_CR2_OIS3 0x1000
#define TIM_CR2_OIS3N 0x2000
#define TIM_CR2_OIS4 0x4000
#define TIM_SMCR_SMS 0x0007
#define TIM_SMCR_SMS_0 0x0001
#define TIM_SMCR_SMS_1 0x0002
#define TIM_SMCR_SMS_2 0x0004
#define TIM_SMCR_TS 0x0070
#define TIM_SMCR_TS_0 0x0010
#define TIM_SMCR_TS_1 0x0020
#define TIM_SMCR_TS_2 0x0040
#define TIM_SMCR_MSM 0x0080
#define TIM_SMCR_ETF 0x0F00
#define TIM_SMCR_ETF_0 0x0100
#define TIM_SMCR_ETF_1 0x0200
#define TIM_SMCR_ETF_2 0x0400
#define TIM_SMCR_ETF_3 0x0800
#define TIM_SMCR_ETPS 0x3000
#define TIM_SMCR_ETPS_0 0x1000
#define TIM_SMCR_ETPS_1 0x2000
#define TIM_SMCR_ECE 0x4000
#define TIM_SMCR_ETP 0x8000
#define TIM_DIER_UIE 0x0001
#define TIM_DIER_CC1IE 0x0002
#define TIM_DIER_CC2IE 0x0004
#define TIM_DIER_CC3IE 0x0008
#define TIM_DIER_CC4IE 0x0010
#define TIM_DIER_COMIE 0x0020
#define TIM_DIER_TIE 0x0040
#define TIM_DIER_BIE 0x0080
#define TIM_DIER_UDE 0x0100
#define TIM_DIER_CC1DE 0x0200
#define TIM_DIER_CC2DE 0x0400
#define TIM_DIER_CC3DE 0x0800
#define TIM_DIER_CC4DE 0x1000
#define TIM_DIER_COMDE 0x2000
#define TIM_DIER_TDE 0x4000
#define TIM_SR_UIF 0x0001
#define TIM_SR_CC1IF 0x0002
#define TIM_SR_CC2IF 0x0004
#define TIM_SR_CC3IF 0x0008
#define TIM_SR_CC4IF 0x0010
#define TIM_SR_COMIF 0x0020
#define TIM_SR_TIF 0x0040
#define TIM_SR_BIF 0x0080
#define TIM_SR_CC1OF 0x0200
#define TIM_SR_CC2OF 0x0400
#define TIM_SR_CC3OF 0x0800
#define TIM_SR_CC4OF 0x1000
#define TIM_EGR_UG 0x01
#define TIM_EGR_CC1G 0x02
#define TIM_EGR_CC2G 0x04
#define TIM_EGR_CC3G 0x08
#define TIM_EGR_CC4G 0x10
#define TIM_EGR_COMG 0x20
#define TIM_EGR_TG 0x40
#define TIM_EGR_BG 0x80
#define TIM_CCMR1_CC1S 0x0003
#define TIM_CCMR1_CC1S_0 0x0001
#define TIM_CCMR1_CC1S_1 0x0002
#define TIM_CCMR1_OC1FE 0x0004
#define TIM_CCMR1_OC1PE 0x0008
#define TIM_CCMR1_OC1M 0x0070
#define TIM_CCMR1_OC1M_0 0x0010
#define TIM_CCMR1_OC1M_1 0x0020
#define TIM_CCMR1_OC1M_2 0x0040
#define TIM_CCMR1_OC1CE 0x0080
#define TIM_CCMR1_CC2S 0x0300
#define TIM_CCMR1_CC2S_0 0x0100
#define TIM_CCMR1_CC2S_1 0x0200
#define TIM_CCMR1_OC2FE 0x0400
#define TIM_CCMR1_OC2PE 0x0800
#define TIM_CCMR1_OC2M 0x7000
#define TIM_CCMR1_OC2M_0 0x1000
#define TIM_CCMR1_OC2M_1 0x2000
#define TIM_CCMR1_OC2M_2 0x4000
#define TIM_CCMR1_OC2CE 0x8000
#define TIM_CCMR1_IC1PSC 0x000C
#define TIM_CCMR1_IC1PSC_0 0x0004
#define TIM_CCMR1_IC1PSC_1 0x0008
#define TIM_CCMR1_IC1F 0x00F0
#define TIM_CCMR1_IC1F_0 0x0010
#define TIM_CCMR1_IC1F_1 0x0020
#define TIM_CCMR1_IC1F_2 0x0040
#define TIM_CCMR1_IC1F_3 0x0080
#define TIM_CCMR1_IC2PSC 0x0C00
#define TIM_CCMR1_IC2PSC_0 0x0400
#define TIM_CCMR1_IC2PSC_1 0x0800
#define TIM_CCMR1_IC2F 0xF000
#define TIM_CCMR1_IC2F_0 0x1000
#define TIM_CCMR1_IC2F_1 0x2000
#define TIM_CCMR1_IC2F_2 0x4000
#define TIM_CCMR1_IC2F_3 0x8000
#define TIM_CCMR2_CC3S 0x0003
#define TIM_CCMR2_CC3S_0 0x0001
#define TIM_CCMR2_CC3S_1 0x0002
#define TIM_CCMR2_OC3FE 0x0004
#define TIM_CCMR2_OC3PE 0x0008
#define TIM_CCMR2_OC3M 0x0070
#define TIM_CCMR2_OC3M_0 0x0010
#define TIM_CCMR2_OC3M_1 0x0020
#define TIM_CCMR2_OC3M_2 0x0040
#define TIM_CCMR2_OC3CE 0x0080
#define TIM_CCMR2_CC4S 0x0300
#define TIM_CCMR2_CC4S_0 0x0100
#define TIM_CCMR2_CC4S_1 0x0200
#define TIM_CCMR2_OC4FE 0x0400
#define TIM_CCMR2_OC4PE 0x0800
#define TIM_CCMR2_OC4M 0x7000
#define TIM_CCMR2_OC4M_0 0x1000
#define TIM_CCMR2_OC4M_1 0x2000
#define TIM_CCMR2_OC4M_2 0x4000
#define TIM_CCMR2_OC4CE 0x8000
#define TIM_CCMR2_IC3PSC 0x000C
#define TIM_CCMR2_IC3PSC_0 0x0004
#define TIM_CCMR2_IC3PSC_1 0x0008
#define TIM_CCMR2_IC3F 0x00F0
#define TIM_CCMR2_IC3F_0 0x0010
#define TIM_CCMR2_IC3F_1 0x0020
#define TIM_CCMR2_IC3F_2 0x0040
#define TIM_CCMR2_IC3F_3 0x0080
#define TIM_CCMR2_IC4PSC 0x0C00
#define TIM_CCMR2_IC4PSC_0 0x0400
#define TIM_CCMR2_IC4PSC_1 0x0800
#define TIM_CCMR2_IC4F 0xF000
#define TIM_CCMR2_IC4F_0 0x1000
#define TIM_CCMR2_IC4F_1 0x2000
#define TIM_CCMR2_IC4F_2 0x4000
#define TIM_CCMR2_IC4F_3 0x8000
#define TIM_CCER_CC1E 0x0001
#define TIM_CCER_CC1P 0x0002
#define TIM_CCER_CC1NE 0x0004
#define TIM_CCER_CC1NP 0x0008
#define TIM_CCER_CC2E 0x0010
#define TIM_CCER_CC2P 0x0020
#define TIM_CCER_CC2NE 0x0040
#define TIM_CCER_CC2NP 0x0080
#define TIM_CCER_CC3E 0x0100
#define TIM_CCER_CC3P 0x0200
#define TIM_CCER_CC3NE 0x0400
#define TIM_CCER_CC3NP 0x0800
#define TIM_CCER_CC4E 0x1000
#define TIM_CCER_CC4P 0x2000
#define TIM_CNT_CNT 0xFFFF
#define TIM_PSC_PSC 0xFFFF
#define TIM_ARR_ARR 0xFFFF
#define TIM_RCR_REP 0xFF
#define TIM_CCR1_CCR1 0xFFFF
#define TIM_CCR2_CCR2 0xFFFF
#define TIM_CCR3_CCR3 0xFFFF
#define TIM_CCR4_CCR4 0xFFFF
#define TIM_BDTR_DTG 0x00FF
#define TIM_BDTR_DTG_0 0x0001
#define TIM_BDTR_DTG_1 0x0002
#define TIM_BDTR_DTG_2 0x0004
#define TIM_BDTR_DTG_3 0x0008
#define TIM_BDTR_DTG_4 0x0010
#define TIM_BDTR_DTG_5 0x0020
#define TIM_BDTR_DTG_6 0x0040
#define TIM_BDTR_DTG_7 0x0080
#define TIM_BDTR_LOCK 0x0300
#define TIM_BDTR_LOCK_0 0x0100
#define TIM_BDTR_LOCK_1 0x0200
#define TIM_BDTR_OSSI 0x0400
#define TIM_BDTR_OSSR 0x0800
#define TIM_BDTR_BKE 0x1000
#define TIM_BDTR_BKP 0x2000
#define TIM_BDTR_AOE 0x4000
#define TIM_BDTR_MOE 0x8000
#define TIM_DCR_DBA 0x001F
#define TIM_DCR_DBA_0 0x0001
#define TIM_DCR_DBA_1 0x0002
#define TIM_DCR_DBA_2 0x0004
#define TIM_DCR_DBA_3 0x0008
#define TIM_DCR_DBA_4 0x0010
#define TIM_DCR_DBL 0x1F00
#define TIM_DCR_DBL_0 0x0100
#define TIM_DCR_DBL_1 0x0200
#define TIM_DCR_DBL_2 0x0400
#define TIM_DCR_DBL_3 0x0800
#define TIM_DCR_DBL_4 0x1000
#define TIM_DMAR_DMAB 0xFFFF
struct EXTI
{
volatile uint32_t IMR;
volatile uint32_t EMR;
volatile uint32_t RTSR;
volatile uint32_t FTSR;
volatile uint32_t SWIER;
volatile uint32_t PR;
};
#define EXTI_BASE 0x40010400
static struct EXTI *const EXTI = (struct EXTI *)EXTI_BASE;
#define EXTI_IMR_MR0 0x00000001
#define EXTI_IMR_MR1 0x00000002
#define EXTI_IMR_MR2 0x00000004
#define EXTI_IMR_MR3 0x00000008
#define EXTI_IMR_MR4 0x00000010
#define EXTI_IMR_MR5 0x00000020
#define EXTI_IMR_MR6 0x00000040
#define EXTI_IMR_MR7 0x00000080
#define EXTI_IMR_MR8 0x00000100
#define EXTI_IMR_MR9 0x00000200
#define EXTI_IMR_MR10 0x00000400
#define EXTI_IMR_MR11 0x00000800
#define EXTI_IMR_MR12 0x00001000
#define EXTI_IMR_MR13 0x00002000
#define EXTI_IMR_MR14 0x00004000
#define EXTI_IMR_MR15 0x00008000
#define EXTI_IMR_MR16 0x00010000
#define EXTI_IMR_MR17 0x00020000
#define EXTI_IMR_MR18 0x00040000
#define EXTI_IMR_MR19 0x00080000
#define EXTI_EMR_MR0 0x00000001
#define EXTI_EMR_MR1 0x00000002
#define EXTI_EMR_MR2 0x00000004
#define EXTI_EMR_MR3 0x00000008
#define EXTI_EMR_MR4 0x00000010
#define EXTI_EMR_MR5 0x00000020
#define EXTI_EMR_MR6 0x00000040
#define EXTI_EMR_MR7 0x00000080
#define EXTI_EMR_MR8 0x00000100
#define EXTI_EMR_MR9 0x00000200
#define EXTI_EMR_MR10 0x00000400
#define EXTI_EMR_MR11 0x00000800
#define EXTI_EMR_MR12 0x00001000
#define EXTI_EMR_MR13 0x00002000
#define EXTI_EMR_MR14 0x00004000
#define EXTI_EMR_MR15 0x00008000
#define EXTI_EMR_MR16 0x00010000
#define EXTI_EMR_MR17 0x00020000
#define EXTI_EMR_MR18 0x00040000
#define EXTI_EMR_MR19 0x00080000
#define EXTI_RTSR_TR0 0x00000001
#define EXTI_RTSR_TR1 0x00000002
#define EXTI_RTSR_TR2 0x00000004
#define EXTI_RTSR_TR3 0x00000008
#define EXTI_RTSR_TR4 0x00000010
#define EXTI_RTSR_TR5 0x00000020
#define EXTI_RTSR_TR6 0x00000040
#define EXTI_RTSR_TR7 0x00000080
#define EXTI_RTSR_TR8 0x00000100
#define EXTI_RTSR_TR9 0x00000200
#define EXTI_RTSR_TR10 0x00000400
#define EXTI_RTSR_TR11 0x00000800
#define EXTI_RTSR_TR12 0x00001000
#define EXTI_RTSR_TR13 0x00002000
#define EXTI_RTSR_TR14 0x00004000
#define EXTI_RTSR_TR15 0x00008000
#define EXTI_RTSR_TR16 0x00010000
#define EXTI_RTSR_TR17 0x00020000
#define EXTI_RTSR_TR18 0x00040000
#define EXTI_RTSR_TR19 0x00080000
#define EXTI_FTSR_TR0 0x00000001
#define EXTI_FTSR_TR1 0x00000002
#define EXTI_FTSR_TR2 0x00000004
#define EXTI_FTSR_TR3 0x00000008
#define EXTI_FTSR_TR4 0x00000010
#define EXTI_FTSR_TR5 0x00000020
#define EXTI_FTSR_TR6 0x00000040
#define EXTI_FTSR_TR7 0x00000080
#define EXTI_FTSR_TR8 0x00000100
#define EXTI_FTSR_TR9 0x00000200
#define EXTI_FTSR_TR10 0x00000400
#define EXTI_FTSR_TR11 0x00000800
#define EXTI_FTSR_TR12 0x00001000
#define EXTI_FTSR_TR13 0x00002000
#define EXTI_FTSR_TR14 0x00004000
#define EXTI_FTSR_TR15 0x00008000
#define EXTI_FTSR_TR16 0x00010000
#define EXTI_FTSR_TR17 0x00020000
#define EXTI_FTSR_TR18 0x00040000
#define EXTI_FTSR_TR19 0x00080000
#define EXTI_SWIER_SWIER0 0x00000001
#define EXTI_SWIER_SWIER1 0x00000002
#define EXTI_SWIER_SWIER2 0x00000004
#define EXTI_SWIER_SWIER3 0x00000008
#define EXTI_SWIER_SWIER4 0x00000010
#define EXTI_SWIER_SWIER5 0x00000020
#define EXTI_SWIER_SWIER6 0x00000040
#define EXTI_SWIER_SWIER7 0x00000080
#define EXTI_SWIER_SWIER8 0x00000100
#define EXTI_SWIER_SWIER9 0x00000200
#define EXTI_SWIER_SWIER10 0x00000400
#define EXTI_SWIER_SWIER11 0x00000800
#define EXTI_SWIER_SWIER12 0x00001000
#define EXTI_SWIER_SWIER13 0x00002000
#define EXTI_SWIER_SWIER14 0x00004000
#define EXTI_SWIER_SWIER15 0x00008000
#define EXTI_SWIER_SWIER16 0x00010000
#define EXTI_SWIER_SWIER17 0x00020000
#define EXTI_SWIER_SWIER18 0x00040000
#define EXTI_SWIER_SWIER19 0x00080000
#define EXTI_PR_PR0 0x00000001
#define EXTI_PR_PR1 0x00000002
#define EXTI_PR_PR2 0x00000004
#define EXTI_PR_PR3 0x00000008
#define EXTI_PR_PR4 0x00000010
#define EXTI_PR_PR5 0x00000020
#define EXTI_PR_PR6 0x00000040
#define EXTI_PR_PR7 0x00000080
#define EXTI_PR_PR8 0x00000100
#define EXTI_PR_PR9 0x00000200
#define EXTI_PR_PR10 0x00000400
#define EXTI_PR_PR11 0x00000800
#define EXTI_PR_PR12 0x00001000
#define EXTI_PR_PR13 0x00002000
#define EXTI_PR_PR14 0x00004000
#define EXTI_PR_PR15 0x00008000
#define EXTI_PR_PR16 0x00010000
#define EXTI_PR_PR17 0x00020000
#define EXTI_PR_PR18 0x00040000
#define EXTI_PR_PR19 0x00080000
#define EXTI0_IRQ 6
#define EXTI1_IRQ 7
#define EXTI2_IRQ 8
#define EXTI9_5_IRQ 23
#define TIM2_IRQ 28
#define TIM3_IRQ 29
#define TIM4_IRQ 30
struct AFIO
{
volatile uint32_t EVCR;
volatile uint32_t MAPR;
volatile uint32_t EXTICR[4];
uint32_t RESERVED0;
volatile uint32_t MAPR2;
};
#define AFIO_BASE 0x40010000
static struct AFIO *const AFIO = (struct AFIO *)AFIO_BASE;
#define AFIO_EXTICR1_EXTI0_PA 0x0000
#define AFIO_EXTICR1_EXTI0_PB 0x0001
#define AFIO_EXTICR1_EXTI0_PC 0x0002
#define AFIO_EXTICR1_EXTI0_PD 0x0003
#define AFIO_EXTICR1_EXTI1_PA 0x0000
#define AFIO_EXTICR1_EXTI1_PB 0x0010
#define AFIO_EXTICR1_EXTI1_PC 0x0020
#define AFIO_EXTICR1_EXTI1_PD 0x0030
#define AFIO_EXTICR1_EXTI2_PA 0x0000
#define AFIO_EXTICR1_EXTI2_PB 0x0100
#define AFIO_EXTICR1_EXTI2_PC 0x0200
#define AFIO_EXTICR1_EXTI2_PD 0x0300
#define AFIO_EXTICR1_EXTI3_PA 0x0000
#define AFIO_EXTICR1_EXTI3_PB 0x1000
#define AFIO_EXTICR1_EXTI3_PC 0x2000
#define AFIO_EXTICR1_EXTI3_PD 0x3000
#define AFIO_EXTICR2_EXTI4_PA 0x0000
#define AFIO_EXTICR2_EXTI4_PB 0x0001
#define AFIO_EXTICR2_EXTI4_PC 0x0002
#define AFIO_EXTICR2_EXTI4_PD 0x0003
#define AFIO_EXTICR2_EXTI5_PA 0x0000
#define AFIO_EXTICR2_EXTI5_PB 0x0010
#define AFIO_EXTICR2_EXTI5_PC 0x0020
#define AFIO_EXTICR2_EXTI5_PD 0x0030
#define AFIO_EXTICR2_EXTI6_PA 0x0000
#define AFIO_EXTICR2_EXTI6_PB 0x0100
#define AFIO_EXTICR2_EXTI6_PC 0x0200
#define AFIO_EXTICR2_EXTI6_PD 0x0300
#define AFIO_EXTICR2_EXTI7_PA 0x0000
#define AFIO_EXTICR2_EXTI7_PB 0x1000
#define AFIO_EXTICR2_EXTI7_PC 0x2000
#define AFIO_EXTICR2_EXTI7_PD 0x3000
#define AFIO_MAPR_TIM3_REMAP_PARTIALREMAP 0x00000800
#define AFIO_MAPR_SWJ_CFG_DISABLE 0x04000000

View File

@@ -118,7 +118,7 @@ struct FTFA {
/* Note: addressing (3,2,1,0). Use Bx macro. */
volatile uint8_t FPROT[4];
};
static struct FTFA *const FTFA = (struct FTFA *const)0x40020000;
static struct FTFA *const FTFA = (struct FTFA *)0x40020000;
#define FSTAT_CCIF 0x80
#define B3 0
@@ -297,7 +297,7 @@ crc32_init (unsigned int *p)
}
#ifdef ORIGINAL_IN_C
const unsigned int *const crc32_table= (const unsigned int *const)0x00000500;
const unsigned int *const crc32_table= (const unsigned int *)0x00000500;
#endif
void __attribute__ ((naked,section(".fixed_function.crc32_u8")))

View File

@@ -323,7 +323,7 @@ struct SCB
#define SCS_BASE (0xE000E000)
#define SCB_BASE (SCS_BASE + 0x0D00)
static struct SCB *const SCB = ((struct SCB *const) SCB_BASE);
static struct SCB *const SCB = (struct SCB *)SCB_BASE;
#define SYSRESETREQ 0x04
static void

View File

@@ -16,8 +16,12 @@
#endif
extern const uint8_t sys_version[8];
#if defined(USE_SYS3) || defined(USE_SYS_BOARD_ID)
extern const uint32_t sys_board_id;
extern const uint8_t sys_board_name[];
#else
# define SYS_BOARD_ID BOARD_ID
#endif
typedef void (*handler)(void);
extern handler vector[16];
@@ -113,22 +117,18 @@ nvic_system_reset (void)
(*vector[12]) ();
}
/*
* Users can override INLINE by 'attribute((used))' to have an
* implementation defined.
*/
#if !defined(INLINE)
#define INLINE __inline__
#endif
#ifdef REQUIRE_CLOCK_GPIO_SETTING_IN_SYS
/* Provide the function entries. */
static INLINE void
static void __attribute__ ((used))
clock_init (void)
{
(*vector[13]) ();
}
static INLINE void
static void __attribute__ ((used))
gpio_init (void)
{
(*vector[14]) ();
}
#endif

View File

@@ -316,7 +316,7 @@ struct SCB
#define SCS_BASE (0xE000E000)
#define SCB_BASE (SCS_BASE + 0x0D00)
static struct SCB *const SCB = ((struct SCB *const) SCB_BASE);
static struct SCB *const SCB = (struct SCB *)SCB_BASE;
#define SYSRESETREQ 0x04
static void

View File

@@ -32,6 +32,9 @@
#include "usb_lld.h"
#define DATA0 0
#define DATA1 1
struct endpoint_ctl {
uint32_t rx_odd: 1;
uint32_t tx_odd: 1;
@@ -47,12 +50,12 @@ struct USB_CONF {
uint8_t rsvd2[3]; /* */
volatile uint8_t ADDINFO; /* Peripheral Additional Info register */
};
static struct USB_CONF *const USB_CONF = (struct USB_CONF *const) 0x40072000;
static struct USB_CONF *const USB_CONF = (struct USB_CONF *)0x40072000;
struct USB_CTRL0 {
volatile uint8_t OTGCTL; /* OTG Control register */
};
static struct USB_CTRL0 *const USB_CTRL0 = (struct USB_CTRL0 *const)0x4007201c;
static struct USB_CTRL0 *const USB_CTRL0 = (struct USB_CTRL0 *)0x4007201c;
struct USB_CTRL1 {
volatile uint8_t ISTAT; /* Interrupt Status register */
@@ -79,7 +82,7 @@ struct USB_CTRL1 {
uint8_t rsvd15[3]; /* */
volatile uint8_t BDTPAGE3; /* BDT Page Register 3 */
};
static struct USB_CTRL1 *const USB_CTRL1 = (struct USB_CTRL1 *const)0x40072080;
static struct USB_CTRL1 *const USB_CTRL1 = (struct USB_CTRL1 *)0x40072080;
/* Interrupt source bits */
#define USB_IS_STALL (1 << 7)
@@ -95,7 +98,7 @@ struct USB_ENDPT {
volatile uint8_t EP; /* Endpoint Control register */
uint8_t rsvd17[3];
};
static struct USB_ENDPT *const USB_ENDPT = (struct USB_ENDPT *const)0x400720c0;
static struct USB_ENDPT *const USB_ENDPT = (struct USB_ENDPT *)0x400720c0;
struct USB_CTRL2 {
volatile uint8_t USBCTRL; /* USB Control register */
@@ -108,7 +111,7 @@ struct USB_CTRL2 {
uint8_t rsvd36[7]; /* */
volatile uint8_t USBFRMADJUST; /* Frame Adjut Register */
};
static struct USB_CTRL2 *const USB_CTRL2 = (struct USB_CTRL2 *const)0x40072100;
static struct USB_CTRL2 *const USB_CTRL2 = (struct USB_CTRL2 *)0x40072100;
/* Buffer Descriptor */
struct BD {
@@ -133,13 +136,7 @@ struct BD {
extern uint8_t __usb_bdt__;
static struct BD *const BD_table = (struct BD *const)&__usb_bdt__;
static uint8_t setup[8];
/* bmRequestType, bRequest */
/* Value: 2-byte */
/* Index: 2-byte */
/* Length: 2-byte */
static struct BD *const BD_table = (struct BD *)&__usb_bdt__;
static void
kl27z_usb_init (void)
@@ -183,11 +180,11 @@ kl27z_set_daddr (uint8_t daddr)
}
static void
kl27z_prepare_ep0_setup (void)
kl27z_prepare_ep0_setup (struct usb_dev *dev)
{
/* Endpoint 0, TX=0. */
BD_table[ep[0].rx_odd].ctrl = 0x00080088; /* Len=8, OWN=1, DATA01=0, DTS=1 */
BD_table[ep[0].rx_odd].buf = setup;
BD_table[ep[0].rx_odd].buf = &dev->dev_req;
BD_table[!ep[0].rx_odd].ctrl = 0x0000; /* OWN=0 */
BD_table[!ep[0].rx_odd].buf = NULL;
@@ -296,17 +293,11 @@ enum STANDARD_REQUESTS {
enum FEATURE_SELECTOR {
ENDPOINT_STALL,
DEVICE_REMOTE_WAKEUP
FEATURE_ENDPOINT_HALT=0,
FEATURE_DEVICE_REMOTE_WAKEUP=1
};
struct data_ctl {
uint8_t *addr;
uint16_t len;
uint8_t require_zlp;
};
/* The state machine states of a control pipe */
enum {
WAIT_SETUP,
@@ -319,30 +310,7 @@ enum {
PAUSE
};
struct device_ctl {
/* control pipe state */
uint8_t state;
uint32_t tkdone;
uint32_t reset;
uint32_t error;
uint32_t stall;
uint32_t send;
uint32_t recv;
/* Device specific settings */
uint8_t configuration;
uint8_t feature;
};
static struct device_ctl device_ctl;
static struct data_ctl data_ctl;
static struct device_ctl *const dev_p = &device_ctl;
static struct data_ctl *const data_p = &data_ctl;
static void handle_transaction (uint8_t stat);
static int handle_transaction (struct usb_dev *dev, uint8_t stat);
void
usb_lld_stall (int n)
@@ -352,16 +320,28 @@ usb_lld_stall (int n)
void
usb_lld_init (uint8_t feature)
usb_lld_ctrl_error (struct usb_dev *dev)
{
dev_p->state = WAIT_SETUP;
dev_p->tkdone = 0;
dev_p->reset = 0;
dev_p->error = 0;
dev_p->stall = 0;
dev->state = STALLED;
kl27z_ep_stall (ENDP0);
}
usb_lld_set_configuration (0);
dev_p->feature = feature;
int
usb_lld_ctrl_ack (struct usb_dev *dev)
{
/* Zero length packet for ACK. */
dev->state = WAIT_STATUS_IN;
kl27z_prepare_ep0_in (&dev->dev_req, 0, DATA1);
return USB_EVENT_OK;
}
void
usb_lld_init (struct usb_dev *dev, uint8_t feature)
{
usb_lld_set_configuration (dev, 0);
dev->feature = feature;
dev->state = WAIT_SETUP;
kl27z_set_daddr (0);
kl27z_usb_init ();
@@ -376,8 +356,12 @@ usb_lld_init (uint8_t feature)
| USB_IS_ERROR | USB_IS_USBRST;
}
void
usb_interrupt_handler (void)
#define USB_MAKE_EV(event) (event<<24)
#define USB_MAKE_TXRX(ep_num,txrx,len) ((txrx? (1<<23):0)|(ep_num<<16)|len)
int
usb_lld_event_handler (struct usb_dev *dev)
{
uint8_t istat_value = USB_CTRL1->ISTAT;
uint8_t stat = USB_CTRL1->STAT;
@@ -385,20 +369,14 @@ usb_interrupt_handler (void)
if ((istat_value & USB_IS_USBRST))
{
USB_CTRL1->ISTAT = USB_IS_USBRST;
usb_cb_device_reset ();
dev_p->reset++;
return USB_MAKE_EV (USB_EVENT_DEVICE_RESET);
}
else if ((istat_value & USB_IS_TOKDNE))
{
handle_transaction (stat);
dev_p->tkdone++;
}
return handle_transaction (dev, stat);
else if ((istat_value & USB_IS_ERROR))
{ /* Clear Errors. */
USB_CTRL1->ERRSTAT = USB_CTRL1->ERRSTAT;
USB_CTRL1->ISTAT = USB_IS_ERROR;
/*reset???*/
dev_p->error++;
}
else if ((istat_value & USB_IS_STALL))
{
@@ -406,22 +384,22 @@ usb_interrupt_handler (void)
if (kl27z_ep_is_stall (0))
{ /* It's endpoint 0, recover from erorr. */
dev_p->state = WAIT_SETUP;
dev->state = WAIT_SETUP;
kl27z_ep_clear_stall (0);
kl27z_prepare_ep0_setup ();
kl27z_prepare_ep0_setup (dev);
}
USB_CTRL1->ISTAT = USB_IS_STALL;
dev_p->stall++;
}
return USB_EVENT_OK;
}
#define DATA0 0
#define DATA1 1
static void
handle_datastage_out (uint8_t stat)
handle_datastage_out (struct usb_dev *dev, uint8_t stat)
{
struct ctrl_data *data_p = &dev->ctrl_data;
int odd = (stat >> 2)&1;
int data01 = !((BD_table[odd].ctrl >> 6)&1);
uint32_t len = (BD_table[odd].ctrl >> 16)&0x3ff;
@@ -436,43 +414,44 @@ handle_datastage_out (uint8_t stat)
if (data_p->len == 0)
{
/* No more data to receive, proceed to send acknowledge for IN. */
dev_p->state = WAIT_STATUS_IN;
kl27z_prepare_ep0_in (setup, 0, DATA1);
dev->state = WAIT_STATUS_IN;
kl27z_prepare_ep0_in (&dev->dev_req, 0, DATA1);
}
else
{
dev_p->state = OUT_DATA;
dev->state = OUT_DATA;
kl27z_prepare_ep0_out (data_p->addr, len, data01);
}
}
static void
handle_datastage_in (uint8_t stat)
handle_datastage_in (struct usb_dev *dev, uint8_t stat)
{
struct ctrl_data *data_p = &dev->ctrl_data;
int odd = (stat >> 2)&1;
int data01 = !((BD_table[2+odd].ctrl >> 6)&1);
uint32_t len = USB_MAX_PACKET_SIZE;
if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA))
if ((data_p->len == 0) && (dev->state == LAST_IN_DATA))
{
if (data_p->require_zlp)
{
data_p->require_zlp = 0;
/* No more data to send. Send empty packet */
kl27z_prepare_ep0_in (setup, 0, data01);
kl27z_prepare_ep0_in (&dev->dev_req, 0, data01);
}
else
{
/* No more data to send, proceed to receive OUT acknowledge. */
dev_p->state = WAIT_STATUS_OUT;
kl27z_prepare_ep0_out (setup, 8, DATA1);
dev->state = WAIT_STATUS_OUT;
kl27z_prepare_ep0_out (&dev->dev_req, 8, DATA1);
}
return;
}
dev_p->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
dev->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
if (len > data_p->len)
len = data_p->len;
@@ -482,31 +461,32 @@ handle_datastage_in (uint8_t stat)
data_p->addr += len;
}
typedef int (*HANDLER) (uint8_t req, struct req_args *arg);
typedef int (*HANDLER) (struct usb_dev *dev);
static int
std_none (uint8_t req, struct req_args *arg)
std_none (struct usb_dev *dev)
{
(void)req; (void)arg;
return USB_UNSUPPORT;
(void)dev;
return -1;
}
static int
std_get_status (uint8_t req, struct req_args *arg)
std_get_status (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
uint16_t status_info = 0;
if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
|| USB_SETUP_SET (req))
return USB_UNSUPPORT;
|| USB_SETUP_SET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT)
{
if (arg->index == 0)
{
/* Get Device Status */
uint8_t feature = dev_p->feature;
uint8_t feature = dev->feature;
/* Remote Wakeup enabled */
if ((feature & (1 << 5)))
@@ -520,232 +500,226 @@ std_get_status (uint8_t req, struct req_args *arg)
else /* Self-powered */
status_info &= ~1;
return usb_lld_reply_request (&status_info, 2, arg);
return usb_lld_ctrl_send (dev, &status_info, 2);
}
}
else if (rcp == INTERFACE_RECIPIENT)
{
int r;
if (dev->configuration == 0)
return -1;
if (dev_p->configuration == 0)
return USB_UNSUPPORT;
r = usb_cb_interface (USB_QUERY_INTERFACE, arg);
if (r != USB_SUCCESS)
return USB_UNSUPPORT;
return usb_lld_reply_request (&status_info, 2, arg);
return USB_EVENT_GET_STATUS_INTERFACE;
}
else if (rcp == ENDPOINT_RECIPIENT)
{
uint8_t n = (arg->index & 0x0f);
if ((arg->index & 0x70) || n == ENDP0)
return USB_UNSUPPORT;
return -1;
if (kl27z_ep_is_disabled (n))
return USB_UNSUPPORT;
return -1;
status_info = kl27z_ep_is_stall (n);
return usb_lld_reply_request (&status_info, 2, arg);
return usb_lld_ctrl_send (dev, &status_info, 2);
}
return USB_UNSUPPORT;
return -1;
}
static int
std_clear_feature (uint8_t req, struct req_args *arg)
std_clear_feature (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (USB_SETUP_GET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT)
{
if (arg->len != 0 || arg->index != 0)
return USB_UNSUPPORT;
return -1;
if (arg->value == DEVICE_REMOTE_WAKEUP)
if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP)
{
dev_p->feature &= ~(1 << 5);
return USB_SUCCESS;
dev->feature &= ~(1 << 5);
return USB_EVENT_CLEAR_FEATURE_DEVICE;
}
}
else if (rcp == ENDPOINT_RECIPIENT)
{
uint8_t n = (arg->index & 0x0f);
if (dev_p->configuration == 0)
return USB_UNSUPPORT;
if (dev->configuration == 0)
return -1;
if (arg->len != 0 || (arg->index >> 8) != 0
|| arg->value != ENDPOINT_STALL || n == ENDP0)
return USB_UNSUPPORT;
|| arg->value != FEATURE_ENDPOINT_HALT || n == ENDP0)
return -1;
if (kl27z_ep_is_disabled (n))
return USB_UNSUPPORT;
return -1;
kl27z_ep_clear_dtog ((arg->index & 0x80) == 0, n);
// event??
return USB_SUCCESS;
return USB_EVENT_CLEAR_FEATURE_ENDPOINT;
}
return USB_UNSUPPORT;
return -1;
}
static int
std_set_feature (uint8_t req, struct req_args *arg)
std_set_feature (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (USB_SETUP_GET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT)
{
if (arg->len != 0 || arg->index != 0)
return USB_UNSUPPORT;
return -1;
if (arg->value == DEVICE_REMOTE_WAKEUP)
if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP)
{
dev_p->feature |= 1 << 5;
// event??
return USB_SUCCESS;
dev->feature |= 1 << 5;
return USB_EVENT_SET_FEATURE_DEVICE;
}
}
else if (rcp == ENDPOINT_RECIPIENT)
{
uint8_t n = (arg->index & 0x0f);
if (dev_p->configuration == 0)
return USB_UNSUPPORT;
if (dev->configuration == 0)
return -1;
if (arg->len != 0 || (arg->index >> 8) != 0
|| arg->value != 0 || n == ENDP0)
return USB_UNSUPPORT;
|| arg->value != FEATURE_ENDPOINT_HALT || n == ENDP0)
return -1;
if (kl27z_ep_is_disabled (n))
return USB_UNSUPPORT;
return -1;
kl27z_ep_stall (n);
// event??
return USB_SUCCESS;
return USB_EVENT_SET_FEATURE_ENDPOINT;
}
return USB_UNSUPPORT;
return -1;
}
static int
std_set_address (uint8_t req, struct req_args *arg)
std_set_address (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (USB_SETUP_GET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
&& arg->index == 0 && dev_p->configuration == 0)
return USB_SUCCESS;
&& arg->index == 0 && dev->configuration == 0)
return usb_lld_ctrl_ack (dev);
return USB_UNSUPPORT;
return -1;
}
static int
std_get_descriptor (uint8_t req, struct req_args *arg)
std_get_descriptor (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
if (USB_SETUP_SET (arg->type))
return -1;
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
return usb_cb_get_descriptor (rcp, (arg->value >> 8),
(arg->value & 0xff), arg);
return USB_EVENT_GET_DESCRIPTOR;
}
static int
std_get_configuration (uint8_t req, struct req_args *arg)
std_get_configuration (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
(void)arg;
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
if (USB_SETUP_SET (arg->type))
return -1;
if (arg->value != 0 || arg->index != 0 || arg->len != 1)
return -1;
if (rcp == DEVICE_RECIPIENT)
return usb_lld_reply_request (&dev_p->configuration, 1, arg);
return usb_lld_ctrl_send (dev, &dev->configuration, 1);
return USB_UNSUPPORT;
return -1;
}
static int
std_set_configuration (uint8_t req, struct req_args *arg)
std_set_configuration (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (USB_SETUP_GET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0)
return usb_cb_handle_event (USB_EVENT_CONFIG, arg->value);
return USB_EVENT_SET_CONFIGURATION;
return USB_UNSUPPORT;
return -1;
}
static int
std_get_interface (uint8_t req, struct req_args *arg)
std_get_interface (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
if (USB_SETUP_SET (arg->type))
return -1;
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
return -1;
if (dev->configuration == 0)
return -1;
if (rcp == INTERFACE_RECIPIENT)
{
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
return USB_UNSUPPORT;
return USB_EVENT_GET_INTERFACE;
if (dev_p->configuration == 0)
return USB_UNSUPPORT;
return usb_cb_interface (USB_GET_INTERFACE, arg);
}
return USB_UNSUPPORT;
return -1;
}
static int
std_set_interface (uint8_t req, struct req_args *arg)
std_set_interface (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req) || rcp != INTERFACE_RECIPIENT
if (USB_SETUP_GET (arg->type) || rcp != INTERFACE_RECIPIENT
|| arg->len != 0 || (arg->index >> 8) != 0
|| (arg->value >> 8) != 0 || dev_p->configuration == 0)
return USB_UNSUPPORT;
|| (arg->value >> 8) != 0 || dev->configuration == 0)
return -1;
return usb_cb_interface (USB_SET_INTERFACE, arg);
return USB_EVENT_SET_INTERFACE;
}
static void
handle_setup0 (void)
static int
handle_setup0 (struct usb_dev *dev)
{
struct req_args *arg = (struct req_args *)&setup[2];
int r = USB_UNSUPPORT;
struct ctrl_data *data_p = &dev->ctrl_data;
int r = -1;
HANDLER handler;
data_p->addr = NULL;
data_p->len = 0;
data_p->require_zlp = 0;
if ((setup[0] & REQUEST_TYPE) == STANDARD_REQUEST)
if ((dev->dev_req.type & REQUEST_TYPE) == STANDARD_REQUEST)
{
if (setup[1] < TOTAL_REQUEST)
{
switch (setup[1])
switch (dev->dev_req.request)
{
case 0: handler = std_get_status; break;
case 1: handler = std_clear_feature; break;
@@ -759,80 +733,85 @@ handle_setup0 (void)
default: handler = std_none; break;
}
r = (*handler) (setup[0], arg);
}
if ((r = (*handler) (dev)) < 0)
{
usb_lld_ctrl_error (dev);
return USB_EVENT_OK;
}
else
r = usb_cb_setup (setup[0], setup[1], arg);
if (r != USB_SUCCESS)
dev_p->state = STALLED;
else if (USB_SETUP_SET (setup[0]))
{
if (arg->len == 0)
{
/* Zero length packet for ACK. */
kl27z_prepare_ep0_in (setup, 0, DATA1);
dev_p->state = WAIT_STATUS_IN;
}
return r;
}
else
return USB_EVENT_CTRL_REQUEST;
}
static void
handle_in0 (uint8_t stat)
static int
handle_in0 (struct usb_dev *dev, uint8_t stat)
{
if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
handle_datastage_in (stat);
else if (dev_p->state == WAIT_STATUS_IN)
{ /* Control WRITE transfer done successfully. */
uint16_t value = (setup[3]<<8) | setup[2];
int r = 0;
if ((setup[1] == SET_ADDRESS) &&
((setup[0] & (REQUEST_TYPE | RECIPIENT))
if (dev->state == IN_DATA || dev->state == LAST_IN_DATA)
handle_datastage_in (dev, stat);
else if (dev->state == WAIT_STATUS_IN)
{ /* Control WRITE transfer done successfully. */
uint16_t value = dev->dev_req.value;
if ((dev->dev_req.request == SET_ADDRESS) &&
((dev->dev_req.type & (REQUEST_TYPE | RECIPIENT))
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
{
kl27z_set_daddr (value);
usb_cb_handle_event (USB_EVENT_ADDRESS, value);
ep[0].rx_odd = 0;
r = USB_EVENT_DEVICE_ADDRESSED;
}
else
usb_cb_ctrl_write_finish (setup[0], setup[1],
(struct req_args *)&setup[2]);
r = USB_EVENT_CTRL_WRITE_FINISH;
dev->state = WAIT_SETUP;
kl27z_prepare_ep0_setup (dev);
}
else
{
dev->state = STALLED;
kl27z_ep_stall (ENDP0);
}
dev_p->state = WAIT_SETUP;
kl27z_prepare_ep0_setup ();
}
else
dev_p->state = STALLED;
return r;
}
static void
handle_out0 (uint8_t stat)
handle_out0 (struct usb_dev *dev, uint8_t stat)
{
if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
/* Host aborts the control READ transfer before finish. */
dev_p->state = STALLED;
else if (dev_p->state == OUT_DATA)
if (dev->state == OUT_DATA)
/* It's normal control WRITE transfer. */
handle_datastage_out (stat);
else if (dev_p->state == WAIT_STATUS_OUT)
handle_datastage_out (dev, stat);
else if (dev->state == WAIT_STATUS_OUT)
{ /* Control READ transfer done successfully. */
dev_p->state = WAIT_SETUP;
kl27z_prepare_ep0_setup ();
dev->state = WAIT_SETUP;
kl27z_prepare_ep0_setup (dev);
}
else
dev_p->state = STALLED;
{
/*
* dev->state == IN_DATA || dev->state == LAST_IN_DATA
* (Host aborts the transfer before finish)
* Or else, unexpected state.
* STALL the endpoint, until we receive the next SETUP token.
*/
dev->state = STALLED;
kl27z_ep_stall (ENDP0);
}
}
#define USB_TOKEN_ACK 0x02
#define USB_TOKEN_IN 0x09
#define USB_TOKEN_SETUP 0x0d
static void
handle_transaction (uint8_t stat)
static int
handle_transaction (struct usb_dev *dev, uint8_t stat)
{
int odd = (stat >> 2)&1;
uint8_t ep_num = (stat >> 4);
int r;
if (ep_num == 0)
{
@@ -841,33 +820,36 @@ handle_transaction (uint8_t stat)
ep[0].rx_odd ^= 1;
if (TOK_PID (BD_table[odd].ctrl) == USB_TOKEN_SETUP)
{
handle_setup0 ();
r = handle_setup0 (dev);
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
USB_CTRL1->CTL = 0x01; /* Clear TXSUSPENDTOKENBUSY. */
return USB_MAKE_EV (r);
}
else
{
handle_out0 (dev, stat);
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
handle_out0 (stat);
return USB_EVENT_OK;
}
}
else
{
ep[0].tx_odd ^= 1;
r = handle_in0 (dev, stat);
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
handle_in0 (stat);
return USB_MAKE_EV (r);
}
if (dev_p->state == STALLED)
kl27z_ep_stall (0);
}
else
{
uint16_t len;
if ((stat & 0x08) == 0)
{
dev_p->recv++;
len = (BD_table[4*ep_num+odd].ctrl >> 16)&0x3ff;
ep[ep_num].rx_odd ^= 1;
usb_cb_rx_ready (ep_num);
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
return USB_MAKE_TXRX (ep_num, 0, len);
}
else
{
@@ -878,8 +860,8 @@ handle_transaction (uint8_t stat)
* host: IN ACK
* device: DATA0/1
*
* It is not described in the specification (it's
* ambiguous), but it is actually possible for some host
* Although it is not described in the specification (it's
* ambiguous), it is actually possible for some host
* implementation to send back a NAK on erroneous case like
* a device sent oversized data.
*
@@ -893,39 +875,30 @@ handle_transaction (uint8_t stat)
*/
uint32_t dmaerr = (USB_CTRL1->ERRSTAT & (1 << 5));
int success = (dmaerr == 0);
uint32_t len = (BD_table[4*ep_num+2+odd].ctrl >> 16)&0x3ff;
len = (BD_table[4*ep_num+2+odd].ctrl >> 16)&0x3ff;
if (!success)
{
USB_CTRL1->ERRSTAT = dmaerr; /* Clear error. */
dev_p->error++;
}
dev_p->send++;
ep[ep_num].tx_odd ^= 1;
usb_cb_tx_done (ep_num, len);
}
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
return USB_MAKE_TXRX (ep_num, 1, len);
}
}
}
void
usb_lld_reset (uint8_t feature)
usb_lld_reset (struct usb_dev *dev, uint8_t feature)
{
dev_p->feature = feature;
usb_lld_set_configuration (0);
usb_lld_set_configuration (dev, 0);
dev->feature = feature;
dev->state = WAIT_SETUP;
/* Reset USB */
USB_CTRL2->USBTRC0 = 0xc0;
USB_CTRL1->CTL = 0x00; /* Disable USB FS communication module */
dev_p->state = WAIT_SETUP;
dev_p->tkdone = 0;
dev_p->error = 0;
dev_p->stall = 0;
kl27z_set_daddr (0);
kl27z_usb_init ();
@@ -937,13 +910,13 @@ usb_lld_reset (uint8_t feature)
}
void
usb_lld_setup_endp (int n, int rx_en, int tx_en)
usb_lld_setup_endp (struct usb_dev *dev, int n, int rx_en, int tx_en)
{
if (n == 0)
{
/* Enable the endpoint 0. */
USB_ENDPT[0].EP = 0x0d;
kl27z_prepare_ep0_setup ();
kl27z_prepare_ep0_setup (dev);
}
else
{
@@ -968,27 +941,29 @@ usb_lld_setup_endp (int n, int rx_en, int tx_en)
void
usb_lld_set_configuration (uint8_t config)
usb_lld_set_configuration (struct usb_dev *dev, uint8_t config)
{
dev_p->configuration = config;
dev->configuration = config;
}
uint8_t
usb_lld_current_configuration (void)
usb_lld_current_configuration (struct usb_dev *dev)
{
return dev_p->configuration;
return dev->configuration;
}
void
usb_lld_set_data_to_recv (void *p, size_t len)
int
usb_lld_ctrl_recv (struct usb_dev *dev, void *p, size_t len)
{
struct ctrl_data *data_p = &dev->ctrl_data;
data_p->addr = (uint8_t *)p;
data_p->len = len;
if (len > USB_MAX_PACKET_SIZE)
len = USB_MAX_PACKET_SIZE;
kl27z_prepare_ep0_out (p, len, DATA1);
dev_p->state = OUT_DATA;
dev->state = OUT_DATA;
return USB_EVENT_OK;
}
/*
@@ -998,9 +973,10 @@ usb_lld_set_data_to_recv (void *p, size_t len)
* BUFLEN: size of the data.
*/
int
usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *a)
usb_lld_ctrl_send (struct usb_dev *dev, const void *buf, size_t buflen)
{
uint32_t len_asked = a->len;
struct ctrl_data *data_p = &dev->ctrl_data;
uint32_t len_asked = dev->dev_req.len;
uint32_t len;
data_p->addr = (void *)buf;
@@ -1016,12 +992,12 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *a)
if (data_p->len < USB_MAX_PACKET_SIZE)
{
len = data_p->len;
dev_p->state = LAST_IN_DATA;
dev->state = LAST_IN_DATA;
}
else
{
len = USB_MAX_PACKET_SIZE;
dev_p->state = IN_DATA;
dev->state = IN_DATA;
}
if (len)
@@ -1030,7 +1006,7 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *a)
data_p->len -= len;
data_p->addr += len;
return USB_SUCCESS;
return USB_EVENT_OK;
}
void
@@ -1042,12 +1018,6 @@ usb_lld_rx_enable_buf (int n, void *buf, size_t len)
BD_table[4*n+ep[n].rx_odd].buf = buf;
}
int
usb_lld_rx_data_len (int n)
{
return (BD_table[4*n+!ep[n].rx_odd].ctrl >> 16)&0x3ff;
}
void
usb_lld_tx_enable_buf (int n, const void *buf, size_t len)

View File

@@ -1,3 +1,31 @@
/*
* usb-stm32f103.c - USB driver for STM32F103
*
* Copyright (C) 2016 Flying Stone Technology
* 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
* receipents of GNU GPL by a written offer.
*
*/
#include <stdint.h>
#include <stdlib.h>
@@ -28,50 +56,20 @@ enum STANDARD_REQUESTS
enum CONTROL_STATE
{
WAIT_SETUP,
SETTING_UP,
IN_DATA,
OUT_DATA,
LAST_IN_DATA,
WAIT_STATUS_IN,
WAIT_STATUS_OUT,
STALLED,
PAUSE
};
enum FEATURE_SELECTOR
{
ENDPOINT_STALL,
DEVICE_REMOTE_WAKEUP
FEATURE_ENDPOINT_HALT=0,
FEATURE_DEVICE_REMOTE_WAKEUP=1
};
struct DATA_INFO
{
uint8_t *addr;
uint16_t len;
uint8_t require_zlp;
};
struct DEVICE_INFO
{
uint8_t current_configuration;
uint8_t current_feature;
uint8_t state;
/**/
uint8_t bmRequestType;
uint8_t bRequest;
/**/
uint16_t value;
uint16_t index;
uint16_t len;
};
static struct DEVICE_INFO device_info;
static struct DATA_INFO data_info;
static struct DEVICE_INFO *const dev_p = &device_info;
static struct DATA_INFO *const data_p = &data_info;
#define REG_BASE (0x40005C00UL) /* USB_IP Peripheral Registers base address */
#define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */
@@ -153,7 +151,7 @@ static struct DATA_INFO *const data_p = &data_info;
#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */
#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */
static void usb_handle_transfer (uint16_t istr_value);
static int usb_handle_transfer (struct usb_dev *dev, uint16_t istr_value);
static void st103_set_btable (void)
{
@@ -348,14 +346,29 @@ static void st103_ep_clear_dtog_tx (uint8_t ep_num)
}
}
void usb_lld_init (uint8_t feature)
void
usb_lld_ctrl_error (struct usb_dev *dev)
{
dev->state = STALLED;
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
}
int
usb_lld_ctrl_ack (struct usb_dev *dev)
{
dev->state = WAIT_STATUS_IN;
st103_set_tx_count (ENDP0, 0);
st103_ep_set_rxtx_status (ENDP0, EP_RX_NAK, EP_TX_VALID);
return USB_EVENT_OK;
}
void usb_lld_init (struct usb_dev *dev, uint8_t feature)
{
usb_lld_sys_init ();
dev_p->state = IN_DATA;
usb_lld_set_configuration (0);
dev_p->current_feature = feature;
dev->configuration = 0;
dev->feature = feature;
dev->state = WAIT_SETUP;
/* Reset USB */
st103_set_cntr (CNTR_FRES);
@@ -378,15 +391,18 @@ void usb_lld_shutdown (void)
usb_lld_sys_shutdown ();
}
void
usb_interrupt_handler (void)
#define USB_MAKE_EV(event) (event<<24)
#define USB_MAKE_TXRX(ep_num,txrx,len) ((txrx? (1<<23):0)|(ep_num<<16)|len)
int
usb_lld_event_handler (struct usb_dev *dev)
{
uint16_t istr_value = st103_get_istr ();
if ((istr_value & ISTR_RESET))
{
st103_set_istr (CLR_RESET);
usb_cb_device_reset ();
return USB_MAKE_EV (USB_EVENT_DEVICE_RESET);
}
else
{
@@ -397,42 +413,45 @@ usb_interrupt_handler (void)
st103_set_istr (CLR_ERR);
if ((istr_value & ISTR_CTR))
usb_handle_transfer (istr_value);
return usb_handle_transfer (dev, istr_value);
}
return USB_EVENT_OK;
}
static void handle_datastage_out (void)
static void handle_datastage_out (struct usb_dev *dev)
{
if (data_p->addr && data_p->len)
if (dev->ctrl_data.addr && dev->ctrl_data.len)
{
uint32_t len = st103_get_rx_count (ENDP0);
if (len > data_p->len)
len = data_p->len;
if (len > dev->ctrl_data.len)
len = dev->ctrl_data.len;
usb_lld_from_pmabuf (data_p->addr, st103_get_rx_addr (ENDP0), len);
data_p->len -= len;
data_p->addr += len;
usb_lld_from_pmabuf (dev->ctrl_data.addr, st103_get_rx_addr (ENDP0), len);
dev->ctrl_data.len -= len;
dev->ctrl_data.addr += len;
}
if (data_p->len == 0)
if (dev->ctrl_data.len == 0)
{
dev_p->state = WAIT_STATUS_IN;
dev->state = WAIT_STATUS_IN;
st103_set_tx_count (ENDP0, 0);
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
}
else
{
dev_p->state = OUT_DATA;
dev->state = OUT_DATA;
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
}
}
static void handle_datastage_in (void)
static void handle_datastage_in (struct usb_dev *dev)
{
uint32_t len = USB_MAX_PACKET_SIZE;;
struct ctrl_data *data_p = &dev->ctrl_data;
if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA))
if ((data_p->len == 0) && (dev->state == LAST_IN_DATA))
{
if (data_p->require_zlp)
{
@@ -440,19 +459,19 @@ static void handle_datastage_in (void)
/* No more data to send. Send empty packet */
st103_set_tx_count (ENDP0, 0);
st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_VALID);
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
}
else
{
/* No more data to send, proceed to receive OUT acknowledge.*/
dev_p->state = WAIT_STATUS_OUT;
st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_STALL);
/* No more data to send, proceed to receive OUT acknowledge. */
dev->state = WAIT_STATUS_OUT;
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
}
return;
}
dev_p->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
dev->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
if (len > data_p->len)
len = data_p->len;
@@ -464,29 +483,30 @@ static void handle_datastage_in (void)
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
}
typedef int (*HANDLER) (uint8_t req, struct req_args *arg);
typedef int (*HANDLER) (struct usb_dev *dev);
static int std_none (uint8_t req, struct req_args *arg)
static int std_none (struct usb_dev *dev)
{
(void)req; (void)arg;
return USB_UNSUPPORT;
(void)dev;
return -1;
}
static int std_get_status (uint8_t req, struct req_args *arg)
static int std_get_status (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = (arg->type & RECIPIENT);
uint16_t status_info = 0;
if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
|| USB_SETUP_SET (req))
return USB_UNSUPPORT;
|| USB_SETUP_SET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT)
{
if (arg->index == 0)
{
/* Get Device Status */
uint8_t feature = dev_p->current_feature;
uint8_t feature = dev->feature;
/* Remote Wakeup enabled */
if ((feature & (1 << 5)))
@@ -500,21 +520,15 @@ static int std_get_status (uint8_t req, struct req_args *arg)
else /* Self-powered */
status_info &= ~1;
return usb_lld_reply_request (&status_info, 2, arg);
return usb_lld_ctrl_send (dev, &status_info, 2);
}
}
else if (rcp == INTERFACE_RECIPIENT)
{
int r;
if (dev->configuration == 0)
return -1;
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
r = usb_cb_interface (USB_QUERY_INTERFACE, arg);
if (r != USB_SUCCESS)
return USB_UNSUPPORT;
return usb_lld_reply_request (&status_info, 2, arg);
return USB_EVENT_GET_STATUS_INTERFACE;
}
else if (rcp == ENDPOINT_RECIPIENT)
{
@@ -522,13 +536,13 @@ static int std_get_status (uint8_t req, struct req_args *arg)
uint16_t status;
if ((arg->index & 0x70) || endpoint == ENDP0)
return USB_UNSUPPORT;
return -1;
if ((arg->index & 0x80))
{
status = st103_ep_get_tx_status (endpoint);
if (status == 0) /* Disabled */
return USB_UNSUPPORT;
return -1;
else if (status == EP_TX_STALL)
status_info |= 1; /* IN Endpoint stalled */
}
@@ -536,33 +550,34 @@ static int std_get_status (uint8_t req, struct req_args *arg)
{
status = st103_ep_get_rx_status (endpoint);
if (status == 0) /* Disabled */
return USB_UNSUPPORT;
return -1;
else if (status == EP_RX_STALL)
status_info |= 1; /* OUT Endpoint stalled */
}
return usb_lld_reply_request (&status_info, 2, arg);
return usb_lld_ctrl_send (dev, &status_info, 2);
}
return USB_UNSUPPORT;
return -1;
}
static int std_clear_feature (uint8_t req, struct req_args *arg)
static int std_clear_feature (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (USB_SETUP_GET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT)
{
if (arg->len != 0 || arg->index != 0)
return USB_UNSUPPORT;
return -1;
if (arg->value == DEVICE_REMOTE_WAKEUP)
if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP)
{
dev_p->current_feature &= ~(1 << 5);
return USB_SUCCESS;
dev->feature &= ~(1 << 5);
return USB_EVENT_CLEAR_FEATURE_DEVICE;
}
}
else if (rcp == ENDPOINT_RECIPIENT)
@@ -570,50 +585,49 @@ static int std_clear_feature (uint8_t req, struct req_args *arg)
uint8_t endpoint = (arg->index & 0x0f);
uint16_t status;
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
if (dev->configuration == 0)
return -1;
if (arg->len != 0 || (arg->index >> 8) != 0
|| arg->value != ENDPOINT_STALL || endpoint == ENDP0)
return USB_UNSUPPORT;
|| arg->value != FEATURE_ENDPOINT_HALT || endpoint == ENDP0)
return -1;
if ((arg->index & 0x80))
status = st103_ep_get_tx_status (endpoint);
else
status = st103_ep_get_rx_status (endpoint);
if (status == 0) /* Disabled */
return USB_UNSUPPORT;
if (status == 0) /* It's disabled endpoint. */
return -1;
if (arg->index & 0x80) /* IN endpoint */
st103_ep_clear_dtog_tx (endpoint);
else /* OUT endpoint */
st103_ep_clear_dtog_rx (endpoint);
// event??
return USB_SUCCESS;
return USB_EVENT_CLEAR_FEATURE_ENDPOINT;
}
return USB_UNSUPPORT;
return -1;
}
static int std_set_feature (uint8_t req, struct req_args *arg)
static int std_set_feature (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (USB_SETUP_GET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT)
{
if (arg->len != 0 || arg->index != 0)
return USB_UNSUPPORT;
return -1;
if (arg->value == DEVICE_REMOTE_WAKEUP)
if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP)
{
dev_p->current_feature |= 1 << 5;
// event??
return USB_SUCCESS;
dev->feature |= 1 << 5;
return USB_EVENT_SET_FEATURE_DEVICE;
}
}
else if (rcp == ENDPOINT_RECIPIENT)
@@ -621,148 +635,151 @@ static int std_set_feature (uint8_t req, struct req_args *arg)
uint8_t endpoint = (arg->index & 0x0f);
uint32_t status;
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
if (dev->configuration == 0)
return -1;
if (arg->len != 0 || (arg->index >> 8) != 0
|| arg->value != 0 || endpoint == ENDP0)
return USB_UNSUPPORT;
|| arg->value != FEATURE_ENDPOINT_HALT || endpoint == ENDP0)
return -1;
if ((arg->index & 0x80))
status = st103_ep_get_tx_status (endpoint);
else
status = st103_ep_get_rx_status (endpoint);
if (status == 0) /* Disabled */
return USB_UNSUPPORT;
if (status == 0) /* It's disabled endpoint. */
return -1;
if (arg->index & 0x80)
/* IN endpoint */
if (arg->index & 0x80) /* IN endpoint */
st103_ep_set_tx_status (endpoint, EP_TX_STALL);
else
/* OUT endpoint */
else /* OUT endpoint */
st103_ep_set_rx_status (endpoint, EP_RX_STALL);
// event??
return USB_SUCCESS;
return USB_EVENT_SET_FEATURE_ENDPOINT;
}
return USB_UNSUPPORT;
return -1;
}
static int std_set_address (uint8_t req, struct req_args *arg)
static int std_set_address (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (USB_SETUP_GET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
&& arg->index == 0 && dev_p->current_configuration == 0)
return USB_SUCCESS;
&& arg->index == 0 && dev->configuration == 0)
return usb_lld_ctrl_ack (dev);
return USB_UNSUPPORT;
return -1;
}
static int std_get_descriptor (uint8_t req, struct req_args *arg)
static int std_get_descriptor (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
if (USB_SETUP_SET (arg->type))
return -1;
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
return usb_cb_get_descriptor (rcp, (arg->value >> 8),
(arg->value & 0xff), arg);
return USB_EVENT_GET_DESCRIPTOR;
}
static int std_get_configuration (uint8_t req, struct req_args *arg)
static int std_get_configuration (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
if (USB_SETUP_SET (arg->type))
return -1;
if (arg->value != 0 || arg->index != 0 || arg->len != 1)
return -1;
if (rcp == DEVICE_RECIPIENT)
return usb_lld_reply_request (&dev_p->current_configuration, 1, arg);
return usb_lld_ctrl_send (dev, &dev->configuration, 1);
return USB_UNSUPPORT;
return -1;
}
static int std_set_configuration (uint8_t req, struct req_args *arg)
static int std_set_configuration (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (USB_SETUP_GET (arg->type))
return -1;
if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0)
return usb_cb_handle_event (USB_EVENT_CONFIG, arg->value);
if (arg->index != 0 || arg->len != 0)
return -1;
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT)
return USB_EVENT_SET_CONFIGURATION;
return -1;
}
static int std_get_interface (uint8_t req, struct req_args *arg)
static int std_get_interface (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
if (USB_SETUP_SET (arg->type))
return -1;
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
return -1;
if (dev->configuration == 0)
return -1;
if (rcp == INTERFACE_RECIPIENT)
{
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
return USB_UNSUPPORT;
return USB_EVENT_GET_INTERFACE;
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
return usb_cb_interface (USB_GET_INTERFACE, arg);
}
return USB_UNSUPPORT;
return -1;
}
static int std_set_interface (uint8_t req, struct req_args *arg)
static int std_set_interface (struct usb_dev *dev)
{
uint8_t rcp = req & RECIPIENT;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
if (USB_SETUP_GET (req) || rcp != INTERFACE_RECIPIENT
if (USB_SETUP_GET (arg->type) || rcp != INTERFACE_RECIPIENT
|| arg->len != 0 || (arg->index >> 8) != 0
|| (arg->value >> 8) != 0 || dev_p->current_configuration == 0)
return USB_UNSUPPORT;
|| (arg->value >> 8) != 0 || dev->configuration == 0)
return -1;
return usb_cb_interface (USB_SET_INTERFACE, arg);
return USB_EVENT_SET_INTERFACE;
}
static void handle_setup0 (void)
static int handle_setup0 (struct usb_dev *dev)
{
const uint16_t *pw;
uint16_t w;
uint8_t req_no;
int r = USB_UNSUPPORT;
HANDLER handler;
pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2));
w = *pw++;
dev_p->bmRequestType = w & 0xff;
dev_p->bRequest = req_no = w >> 8;
dev->dev_req.type = (w & 0xff);
dev->dev_req.request = req_no = (w >> 8);
pw++;
dev_p->value = *pw++;
dev->dev_req.value = *pw++;
pw++;
dev_p->index = *pw++;
dev->dev_req.index = *pw++;
pw++;
dev_p->len = *pw;
dev->dev_req.len = *pw;
data_p->addr = NULL;
data_p->len = 0;
data_p->require_zlp = 0;
dev->ctrl_data.addr = NULL;
dev->ctrl_data.len = 0;
dev->ctrl_data.require_zlp = 0;
if ((dev_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST)
{
if (req_no < TOTAL_REQUEST)
if ((dev->dev_req.type & REQUEST_TYPE) == STANDARD_REQUEST)
{
int r;
switch (req_no)
{
case 0: handler = std_get_status; break;
@@ -777,126 +794,127 @@ static void handle_setup0 (void)
default: handler = std_none; break;
}
r = (*handler) (dev_p->bmRequestType,
(struct req_args *)&dev_p->value);
}
if ((r = (*handler) (dev)) < 0)
{
usb_lld_ctrl_error (dev);
return USB_EVENT_OK;
}
else
r = usb_cb_setup (dev_p->bmRequestType, req_no,
(struct req_args *)&dev_p->value);
if (r != USB_SUCCESS)
dev_p->state = STALLED;
else
{
if (USB_SETUP_SET (dev_p->bmRequestType))
{
if (dev_p->len == 0)
{
dev_p->state = WAIT_STATUS_IN;
st103_set_tx_count (ENDP0, 0);
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
return r;
}
else
{
dev_p->state = OUT_DATA;
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
}
}
}
return USB_EVENT_CTRL_REQUEST;
}
static void handle_in0 (void)
static int handle_in0 (struct usb_dev *dev)
{
if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
handle_datastage_in ();
else if (dev_p->state == WAIT_STATUS_IN)
int r = 0;
if (dev->state == IN_DATA || dev->state == LAST_IN_DATA)
handle_datastage_in (dev);
else if (dev->state == WAIT_STATUS_IN)
{
if ((dev_p->bRequest == SET_ADDRESS) &&
((dev_p->bmRequestType & (REQUEST_TYPE | RECIPIENT))
dev->state = WAIT_SETUP;
if ((dev->dev_req.request == SET_ADDRESS) &&
((dev->dev_req.type & (REQUEST_TYPE | RECIPIENT))
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
{
st103_set_daddr (dev_p->value);
usb_cb_handle_event (USB_EVENT_ADDRESS, dev_p->value);
st103_set_daddr (dev->dev_req.value);
r = USB_EVENT_DEVICE_ADDRESSED;
}
else
usb_cb_ctrl_write_finish (dev_p->bmRequestType, dev_p->bRequest,
(struct req_args *)&dev_p->value);
dev_p->state = STALLED;
r = USB_EVENT_CTRL_WRITE_FINISH;
}
else
dev_p->state = STALLED;
}
static void handle_out0 (void)
{
if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
/* host aborts the transfer before finish */
dev_p->state = STALLED;
else if (dev_p->state == OUT_DATA)
handle_datastage_out ();
else if (dev_p->state == WAIT_STATUS_OUT)
dev_p->state = STALLED;
/* Unexpect state, STALL the endpoint */
else
dev_p->state = STALLED;
}
static void
usb_handle_transfer (uint16_t istr_value)
{
uint16_t ep_value = 0;
uint8_t ep_index;
ep_index = (istr_value & ISTR_EP_ID);
/* Decode and service non control endpoints interrupt */
/* process related endpoint register */
ep_value = st103_get_epreg (ep_index);
if (ep_index == 0)
{
if ((ep_value & EP_CTR_TX))
{
st103_ep_clear_ctr_tx (ep_index);
handle_in0 ();
}
if ((ep_value & EP_CTR_RX))
{
st103_ep_clear_ctr_rx (ep_index);
if ((ep_value & EP_SETUP))
handle_setup0 ();
else
handle_out0 ();
}
if (dev_p->state == STALLED)
dev->state = STALLED;
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
}
return r;
}
static void handle_out0 (struct usb_dev *dev)
{
if (dev->state == OUT_DATA)
/* Usual case. */
handle_datastage_out (dev);
else if (dev->state == WAIT_STATUS_OUT)
/*
* Control READ transfer finished by ZLP.
* Leave ENDP0 status RX_NAK, TX_NAK.
*/
dev->state = WAIT_SETUP;
else
{
/*
* dev->state == IN_DATA || dev->state == LAST_IN_DATA
* (Host aborts the transfer before finish)
* Or else, unexpected state.
* STALL the endpoint, until we receive the next SETUP token.
*/
dev->state = STALLED;
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
}
}
static int
usb_handle_transfer (struct usb_dev *dev, uint16_t istr_value)
{
uint16_t ep_value = 0;
uint8_t ep_num = (istr_value & ISTR_EP_ID);
ep_value = st103_get_epreg (ep_num);
if (ep_num == 0)
{
if ((ep_value & EP_CTR_TX))
{
st103_ep_clear_ctr_tx (ep_num);
return USB_MAKE_EV (handle_in0 (dev));
}
if ((ep_value & EP_CTR_RX))
{
st103_ep_clear_ctr_rx (ep_index);
usb_cb_rx_ready (ep_index);
st103_ep_clear_ctr_rx (ep_num);
if ((ep_value & EP_SETUP))
return USB_MAKE_EV (handle_setup0 (dev));
else
{
handle_out0 (dev);
return USB_EVENT_OK;
}
}
}
else
{
uint16_t len;
if ((ep_value & EP_CTR_RX))
{
len = st103_get_rx_count (ep_num);
st103_ep_clear_ctr_rx (ep_num);
return USB_MAKE_TXRX (ep_num, 0, len);
}
if ((ep_value & EP_CTR_TX))
{
uint32_t len = st103_get_tx_count (ep_index);
len = st103_get_tx_count (ep_num);
st103_ep_clear_ctr_tx (ep_num);
return USB_MAKE_TXRX (ep_num, 1, len);
}
}
st103_ep_clear_ctr_tx (ep_index);
usb_cb_tx_done (ep_index, len);
}
}
return USB_EVENT_OK;
}
void usb_lld_reset (uint8_t feature)
void usb_lld_reset (struct usb_dev *dev, uint8_t feature)
{
usb_lld_set_configuration (0);
dev_p->current_feature = feature;
usb_lld_set_configuration (dev, 0);
dev->feature = feature;
st103_set_btable ();
st103_set_daddr (0);
}
@@ -926,16 +944,6 @@ void usb_lld_tx_enable (int ep_num, size_t len)
st103_ep_set_tx_status (ep_num, EP_TX_VALID);
}
int usb_lld_tx_data_len (int ep_num)
{
return st103_get_tx_count (ep_num);
}
int usb_lld_rx_data_len (int ep_num)
{
return st103_get_rx_count (ep_num);
}
void usb_lld_stall_tx (int ep_num)
{
st103_ep_set_tx_status (ep_num, EP_TX_STALL);
@@ -993,20 +1001,24 @@ void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
st103_set_epreg (ep_num, epreg_value);
}
void usb_lld_set_configuration (uint8_t config)
void usb_lld_set_configuration (struct usb_dev *dev, uint8_t config)
{
dev_p->current_configuration = config;
dev->configuration = config;
}
uint8_t usb_lld_current_configuration (void)
uint8_t usb_lld_current_configuration (struct usb_dev *dev)
{
return dev_p->current_configuration;
return dev->configuration;
}
void usb_lld_set_data_to_recv (void *p, size_t len)
int usb_lld_ctrl_recv (struct usb_dev *dev, void *p, size_t len)
{
struct ctrl_data *data_p = &dev->ctrl_data;
data_p->addr = p;
data_p->len = len;
dev->state = OUT_DATA;
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
return USB_EVENT_OK;
}
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n)
@@ -1090,9 +1102,10 @@ void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n)
* BUFLEN: size of the data.
*/
int
usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl)
usb_lld_ctrl_send (struct usb_dev *dev, const void *buf, size_t buflen)
{
uint32_t len_asked = ctl->len;
struct ctrl_data *data_p = &dev->ctrl_data;
uint32_t len_asked = dev->dev_req.len;
uint32_t len;
data_p->addr = (void *)buf;
@@ -1108,12 +1121,12 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl)
if (data_p->len < USB_MAX_PACKET_SIZE)
{
len = data_p->len;
dev_p->state = LAST_IN_DATA;
dev->state = LAST_IN_DATA;
}
else
{
len = USB_MAX_PACKET_SIZE;
dev_p->state = IN_DATA;
dev->state = IN_DATA;
}
if (len)
@@ -1124,6 +1137,6 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl)
}
st103_set_tx_count (ENDP0, len);
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
return USB_SUCCESS;
st103_ep_set_rxtx_status (ENDP0, EP_RX_NAK, EP_TX_VALID);
return USB_EVENT_OK;
}

View File

@@ -13,7 +13,7 @@ ifneq ($(USE_USB),)
CSRC += $(CHOPSTX)/mcu/usb-$(CHIP).c
endif
ifneq ($(USE_ADC),)
CSRC += $(CHOPSTX)/mcu/adc-$(CHIP).c
CSRC += $(CHOPSTX)/contrib/adc-$(CHIP).c
endif
INCDIR += $(CHOPSTX)

4
sys.h
View File

@@ -1,5 +1,7 @@
#ifdef MCU_KINETIS_L
#if defined(MCU_KINETIS_L)
#include "mcu/sys-mkl27z.h"
#elif defined(MCU_STM32F0)
#include "mcu/sys-stm32f0.h"
#else
#include "mcu/sys-stm32f103.h"
#endif

117
usb_lld.h
View File

@@ -37,45 +37,52 @@ enum DESCRIPTOR_TYPE
#define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0)
#define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0)
enum
{
USB_UNSUPPORT = 0,
USB_SUCCESS = 1,
};
struct req_args {
struct device_req {
uint8_t type;
uint8_t request;
uint16_t value;
uint16_t index;
uint16_t len;
};
void usb_cb_device_reset (void);
int usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg);
int usb_cb_interface (uint8_t cmd, struct req_args *arg);
int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
struct req_args *arg);
int usb_cb_handle_event (uint8_t event_type, uint16_t value);
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
struct req_args *arg);
void usb_cb_tx_done (uint8_t ep_num, uint32_t len);
void usb_cb_rx_ready (uint8_t ep_num);
struct ctrl_data {
uint8_t *addr;
uint16_t len;
uint8_t require_zlp;
};
enum {
USB_EVENT_ADDRESS,
USB_EVENT_CONFIG,
USB_EVENT_SUSPEND,
USB_EVENT_WAKEUP,
USB_EVENT_STALL,
struct usb_dev {
uint8_t configuration;
uint8_t feature;
uint8_t state;
struct device_req dev_req;
struct ctrl_data ctrl_data;
};
enum {
USB_SET_INTERFACE,
USB_GET_INTERFACE,
USB_QUERY_INTERFACE,
USB_EVENT_OK=0, /* Processed in lower layer. */
/* Device reset and suspend. */
USB_EVENT_DEVICE_RESET,
USB_EVENT_DEVICE_SUSPEND,
/* Device Requests (Control WRITE Transfer): Standard */
USB_EVENT_SET_CONFIGURATION,
USB_EVENT_SET_INTERFACE,
USB_EVENT_SET_FEATURE_DEVICE,
USB_EVENT_SET_FEATURE_ENDPOINT,
USB_EVENT_CLEAR_FEATURE_DEVICE,
USB_EVENT_CLEAR_FEATURE_ENDPOINT,
/* Device Requests (Control READ Transfer): Standard */
USB_EVENT_GET_STATUS_INTERFACE,
USB_EVENT_GET_DESCRIPTOR,
USB_EVENT_GET_INTERFACE,
/* Device Requests (Control READ/WRITE Transfer): Non-Standard */
USB_EVENT_CTRL_REQUEST,
USB_EVENT_CTRL_WRITE_FINISH,
/* Device addressed. */
USB_EVENT_DEVICE_ADDRESSED,
};
enum DEVICE_STATE
{
enum DEVICE_STATE {
UNCONNECTED,
ATTACHED,
POWERED,
@@ -84,23 +91,54 @@ enum DEVICE_STATE
CONFIGURED
};
void usb_lld_init (uint8_t feature);
int usb_lld_reply_request (const void *buf, size_t buflen,
struct req_args *arg);
int usb_lld_rx_data_len (int ep_num);
void usb_lld_reset (uint8_t feature);
void usb_lld_set_configuration (uint8_t config);
uint8_t usb_lld_current_configuration (void);
void usb_lld_init (struct usb_dev *dev, uint8_t feature);
/*
* Return value is encoded integer:
* event-no: 8-bit, 0 if TX/RX
* tx/rx-flag: 1-bit, 0 if rx, 1 if tx
* endpoint no: 7-bit
* length: 16-bit
*/
#define USB_EVENT_TXRX(e) ((e >> 23) & 1)
#define USB_EVENT_LEN(e) (e & 0xffff)
#define USB_EVENT_ENDP(e) ((e >> 16) & 0x7f)
#define USB_EVENT_ID(e) ((e >> 24))
int usb_lld_event_handler (struct usb_dev *dev);
/*
* Control Endpoint ENDP0 does device requests handling.
* In response to an event of
* USB_EVENT_SET_CONFIGURATION
* USB_EVENT_SET_INTERFACE
* USB_EVENT_SET_FEATURE_DEVICE
* USB_EVENT_SET_FEATURE_ENDPOINT
* USB_EVENT_CLEAR_FEATURE_DEVICE
* USB_EVENT_CLEAR_FEATURE_ENDPOINT
* USB_EVENT_GET_STATUS_INTERFACE
* USB_EVENT_GET_DESCRIPTOR
* USB_EVENT_GET_INTERFACE
* USB_EVENT_CTRL_REQUEST
* a single action should be done, which is SEND, RECV, or,
* ACKNOWLEDGE (no data to be sent, or to be received).
* Otherwise, it's an error.
*/
int usb_lld_ctrl_send (struct usb_dev *dev, const void *buf, size_t buflen);
int usb_lld_ctrl_recv (struct usb_dev *dev, void *p, size_t len);
int usb_lld_ctrl_ack (struct usb_dev *dev);
void usb_lld_ctrl_error (struct usb_dev *dev);
void usb_lld_reset (struct usb_dev *dev, uint8_t feature);
void usb_lld_set_configuration (struct usb_dev *dev, uint8_t config);
uint8_t usb_lld_current_configuration (struct usb_dev *dev);
void usb_lld_prepare_shutdown (void);
void usb_lld_shutdown (void);
void usb_interrupt_handler (void);
void usb_lld_set_data_to_recv (void *p, size_t len);
#ifdef MCU_KINETIS_L
void usb_lld_tx_enable_buf (int ep_num, const void *buf, size_t len);
void usb_lld_rx_enable_buf (int ep_num, void *buf, size_t len);
void usb_lld_setup_endp (int ep_num, int rx_en, int tx_en);
void usb_lld_setup_endp (struct usb_dev *dev, int ep_num, int rx_en, int tx_en);
void usb_lld_stall (int ep_num);
#else
/* EP_TYPE[1:0] EndPoint TYPE */
@@ -118,10 +156,9 @@ void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
void usb_lld_stall_tx (int ep_num);
void usb_lld_stall_rx (int ep_num);
int usb_lld_tx_data_len (int ep_num);
void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len);
void usb_lld_write (uint8_t ep_num, const void *buf, size_t len);
void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
#endif