Compare commits
97 Commits
release/1.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
802dbbd639 | ||
|
|
2764fc4ea2 | ||
|
|
f500ac03da | ||
|
|
808aa5b186 | ||
|
|
f781ac9e6a | ||
|
|
32d0b8200d | ||
|
|
05382581e8 | ||
|
|
aa97af66db | ||
|
|
e6a53c99c4 | ||
|
|
cb770e9ae3 | ||
|
|
aa63ac79bc | ||
|
|
74cff25b78 | ||
|
|
5cd4871a94 | ||
|
|
c0a84627b6 | ||
|
|
8dabbe6e1c | ||
|
|
0a68140530 | ||
|
|
ce3cd63144 | ||
|
|
199db97025 | ||
|
|
1533284ace | ||
|
|
0e9737eb61 | ||
|
|
265fb971c0 | ||
|
|
26d5bb0115 | ||
|
|
bf1ac08e6c | ||
|
|
530ddcfeda | ||
|
|
19b0590c1f | ||
|
|
72210e4250 | ||
|
|
61892c85b0 | ||
|
|
75e6b06dd5 | ||
|
|
dd190c8207 | ||
|
|
22039ee717 | ||
|
|
cb628fe317 | ||
|
|
f3cc662548 | ||
|
|
b58dd05c9d | ||
|
|
7b1c442d88 | ||
|
|
b4b9aace03 | ||
|
|
741aba1997 | ||
|
|
022666402c | ||
|
|
69677aecd4 | ||
|
|
bc35bc81cf | ||
|
|
499e575528 | ||
|
|
9f9aeae4bf | ||
|
|
ecd90b1b99 | ||
|
|
39e53ae747 | ||
|
|
9b9d40c16b | ||
|
|
1eff465303 | ||
|
|
de895e6b65 | ||
|
|
d4cca9f0dc | ||
|
|
de9eb6f1e7 | ||
|
|
2c14f21b20 | ||
|
|
9e527b0532 | ||
|
|
817167dbcc | ||
|
|
63974743b4 | ||
|
|
14c4256337 | ||
|
|
8c4ea854cb | ||
|
|
a610821458 | ||
|
|
3071929c62 | ||
|
|
14cb38e56f | ||
|
|
a362f32cdd | ||
|
|
e684e853c8 | ||
|
|
2b98dc3de8 | ||
|
|
44054415c8 | ||
|
|
66b4eb3058 | ||
|
|
b72154f47b | ||
|
|
378201a1c7 | ||
|
|
1a7bd3e202 | ||
|
|
b34b9b6440 | ||
|
|
d745c9fdb9 | ||
|
|
3552fc5615 | ||
|
|
621dff7cb3 | ||
|
|
83643c53ca | ||
|
|
040f389449 | ||
|
|
44273a70fc | ||
|
|
7257f30636 | ||
|
|
941a8f6fbd | ||
|
|
13926ac05a | ||
|
|
bbe09de209 | ||
|
|
f161928b0b | ||
|
|
035057db24 | ||
|
|
5ac8a1f251 | ||
|
|
168af852a5 | ||
|
|
e398fc9689 | ||
|
|
5a08752b9c | ||
|
|
b572e3f8e0 | ||
|
|
55b011a721 | ||
|
|
c191d86bf2 | ||
|
|
96d2a81331 | ||
|
|
fa7cecc0b4 | ||
|
|
a34937453c | ||
|
|
dd54b5ff20 | ||
|
|
c08044e22b | ||
|
|
5b7c5a9996 | ||
|
|
bc39f0e582 | ||
|
|
e671a539b0 | ||
|
|
2c9191c4b3 | ||
|
|
af5982507f | ||
|
|
a1b993c2e2 | ||
|
|
e73d14ca27 |
15
.gitlab-ci.yml
Normal file
15
.gitlab-ci.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
image: debian:stable
|
||||
|
||||
before_script:
|
||||
- apt-get update && apt-get -y install texi2html
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- mkdir -p html && (cd html && texi2html ../doc/chopstx.texi)
|
||||
- mv html/ public
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
12
AUTHORS
12
AUTHORS
@@ -19,7 +19,7 @@ Kenji Rikitake:
|
||||
|
||||
Kiwamu Okabe:
|
||||
Wrote an OpenOCD scirpt:
|
||||
example-fsm-55/stlink-v2.cfg
|
||||
example-fsm-55/stlink-v2.cfg
|
||||
|
||||
Mateusz Zalega:
|
||||
Added Nitrokey-Start support.
|
||||
@@ -28,7 +28,7 @@ Mateusz Zalega:
|
||||
NIIBE Yutaka:
|
||||
Wrote the library:
|
||||
chopstx.c, entry.c, eventflag.c,
|
||||
chopstx.h, eventflag.h
|
||||
chopstx.h, eventflag.h
|
||||
Wrote the drivers mcu/*:
|
||||
clk_gpio_init-mkl27z.c, clk_gpio_init-stm32.c,
|
||||
sys-stm32f103.c, sys-stm32f030.c, sys-mkl27z.c,
|
||||
@@ -36,9 +36,10 @@ NIIBE Yutaka:
|
||||
Drew the logo:
|
||||
chopstx.svg, chopstx.png
|
||||
Wrote examples:
|
||||
example-led, example-cdc, example-fsm-55, example-fs-bb48
|
||||
example-led, example-cdc, example-fsm-55, example-fs-bb48,
|
||||
example-usb-serial
|
||||
Wrote board/*:
|
||||
board-fst-01.h, board-fst-01-00.h,
|
||||
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,
|
||||
|
||||
@@ -47,7 +48,8 @@ NIIBE Yutaka:
|
||||
board-fs-bb48.h
|
||||
|
||||
Under contract of g10 Code GmbH, wrote:
|
||||
mcu/usb-usbip.c
|
||||
mcu/usb-usbip.c
|
||||
contrib/usart-stm32f103.c
|
||||
|
||||
Paul Fertser:
|
||||
Added Blue Pill support.
|
||||
|
||||
236
ChangeLog
236
ChangeLog
@@ -1,3 +1,239 @@
|
||||
2018-05-09 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.9.
|
||||
* doc/chopstx.texi (VERSION): 1.9.
|
||||
|
||||
2018-05-08 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* board/board-blue-pill.h (GPIO_USB_SET_TO_ENABLE): Remove.
|
||||
|
||||
* doc/chopstx.texi (Compile-time macro): New chapter.
|
||||
|
||||
* mcu/sys-stm32f103.c (usb_lld_sys_init): Use MHZ.
|
||||
(flash_protect): Fix for GD32F103.
|
||||
|
||||
2018-04-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* board/board-blue-pill-g.h: New. Define STM32_ADCPRE and
|
||||
STM32_USBPRE for 96MHz clock.
|
||||
* mcu/stm32.h (STM32_USBPRE_DIV2): New for GD32F103.
|
||||
* mcu/clk_gpio_init-stm32.c: Allow constants, which are defined by
|
||||
board.h (STM32_ADCPRE and STM32_USBPRE).
|
||||
* mcu/chx-stm32f103.c: Use STM32_ADCPRE and STM32_USBPRE.
|
||||
|
||||
* mcu/usb-stm32f103.c (usb_lld_init): BTABLE setting at
|
||||
initialization.
|
||||
(usb_lld_reset): Not at each reset.
|
||||
|
||||
* contrib/adc-stm32f103.c [MCU_STM32F1_GD32F1]: Use continuous
|
||||
sampling with no DELIBARATELY_DO_IT_WRONG_START_STOP.
|
||||
(adc_init): Wait after ADC_CR2_ADON.
|
||||
(adc_start): Likewise. Enabling by ADC_CR2_ADON after all other
|
||||
registers configuration.
|
||||
|
||||
2018-01-19 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.8.
|
||||
* doc/chopstx.texi (VERSION): 1.8.
|
||||
|
||||
2018-01-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* mcu/stm32f103.h: Include stm32.h and cortex-m.h.
|
||||
|
||||
2018-01-09 Anthony Romano <romanoanthony061@gmail.com>
|
||||
|
||||
* contrib/adc-stm32f103.c: Support IN8 config.
|
||||
|
||||
2017-12-19 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.7.
|
||||
* doc/chopstx.texi (VERSION): 1.7.
|
||||
|
||||
2017-12-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* contrib/usart-stm32f103.c: New.
|
||||
* example-usb-serial: New example.
|
||||
|
||||
2017-12-16 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx.c (chx_timer_expired): Bug fix of wake up.
|
||||
(chx_mutex_unlock): Avoid non-deterministic thing.
|
||||
|
||||
2017-12-14 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* board/board-st-nucleo-f103.h: Update.
|
||||
|
||||
* mcu/sys-stm32f103.h (BOARD_ID_FST_01G): New.
|
||||
|
||||
* contrib/adc-stm32f103.c (get_adc_config): Add a case for
|
||||
BOARD_ID_FST_01G and BOARD_ID_ST_NUCLEO_F103.
|
||||
|
||||
2017-11-24 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.6.
|
||||
* doc/chopstx.texi (VERSION): 1.6.
|
||||
* doc/chopstx-api.texi: Regenerated.
|
||||
|
||||
2017-11-21 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* example-fsm-55: Update using stack-def.h.
|
||||
|
||||
2017-11-20 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* example-led: Update using stack-def.h.
|
||||
|
||||
* chopstx-cortex-m.c [__ARM_ARCH_6M__] (chx_sched): Fix.
|
||||
|
||||
2017-11-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* example-fsm-55/hh.c (main): Just return.
|
||||
|
||||
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* mcu/chx-stm32f103.c (configure_clock): Change prescaler on
|
||||
sleep.
|
||||
|
||||
* mcu/clk_gpio_init-stm32.c (clock_init): Don't turn on CRC
|
||||
module.
|
||||
|
||||
* mcu/clk_gpio_init-stm32.c (STM32_*): Move to...
|
||||
* mcu/stm32.h (STM32_*): ... this header file.
|
||||
|
||||
* mcu/stm32f103.h, mcu/clk_gpio_init-stm32.c (RCC): Move to...
|
||||
* mcu/stm32.h (RCC): ... this header file.
|
||||
|
||||
* example-fsm-55: Update for new sleep API.
|
||||
|
||||
* rules.mk (CSRC): Add mcu/chx-$(CHIP).c.
|
||||
|
||||
* chopstx-cortex-m.c (idle, chx_sleep_mode): Remove.
|
||||
(chx_sched, preempt): Call chx_idle.
|
||||
* mcu/chx-mkl27z.c, mcu/chx-stm32f0.c, mcu/chx-stm32f103.c: New.
|
||||
* mcu/stm32.h: New.
|
||||
|
||||
* chopstx-gnu-linux.c (chx_sleep_mode): Move to...
|
||||
* mcu/chx-gnu-linux.c: Here.
|
||||
|
||||
* mcu/stm32f103.h (DBGMCU): New.
|
||||
|
||||
* mcu/cortex-m.h: New.
|
||||
* mcu/sys-stm32f0.c, mcu/sys-stm32f103.c: Use mcu/cortex-m.h.
|
||||
|
||||
* chopstx.c (chopstx_conf_idle): Call chx_sleep_mode before
|
||||
changing chx_allow_sleep.
|
||||
|
||||
* board/board-blue-pill.h, board/board-cq-starm.h,
|
||||
board/board-fst-01-00.h, board/board-fst-01.h,
|
||||
board/board-fst-01g.h, board/board-maple-mini.h,
|
||||
board/board-nitrokey-start.h, board/board-olimex-stm32-h103.h,
|
||||
board/board-st-dongle.h, board/board-st-nucleo-f103.h,
|
||||
board/board-stbee-mini.h, board/board-stbee.h,
|
||||
board/board-stm32-primer2.h: Add MCU_STM32F1.
|
||||
|
||||
2017-11-16 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx.h (chopstx_poll): API change.
|
||||
* chopstx.c (chopstx_poll): Use const pointer.
|
||||
|
||||
* chopstx-cortex-m.c (idle): Support WFE.
|
||||
[!MCU_STM32F0] (chx_sleep_mode): Clock feed by HSI.
|
||||
|
||||
2017-11-15 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx.c (chopstx_conf_idle): Call chx_sleep_mode.
|
||||
* chopstx-cortex-m.c (chx_sleep_mode): New.
|
||||
* chopstx-gnu-linux.c (chx_sleep_mode): New.
|
||||
|
||||
2017-11-15 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* example-fsm-55/hh.c (main): Add call to chopstx_conf_idle.
|
||||
* example-fsm-55/Makefile (DEFS): Remove USE_WFI_FOR_IDLE.
|
||||
|
||||
* chopstx.c (chx_init): Initialize sleep lock.
|
||||
(chopstx_conf_idle): New.
|
||||
* chopstx-cortex-m.c (idle): Support sleep.
|
||||
|
||||
* mcu/usb-stm32f103.c (usb_lld_event_handler): Fix suspend/resume.
|
||||
|
||||
2017-11-14 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* usb_lld.h (DEVICE_STATE): Add prefix USB_DEVICE_STATE_.
|
||||
(USB_DEVICE_STATE_DEFAULT): New.
|
||||
|
||||
* mcu/usb-stm32f103.c (usb_lld_init): Suspend/resume init.
|
||||
(usb_lld_event_handler): Add suspend/resume support.
|
||||
|
||||
* example-cdc/usb-cdc.c: Follow the change of usb_lld.h.
|
||||
* example-cdc-gnu-linux/usb-cdc.c: Ditto.
|
||||
* example-fs-bb48/usb-cdc.c: Ditto.
|
||||
* example-fraucheky/main.c: Ditto.
|
||||
* example-fraucheky/Makefile (USE_SYS): Add for debug.
|
||||
|
||||
2017-11-13 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* mcu/usb-stm32f103.c (usb_lld_init): Set up interrupt on errors.
|
||||
|
||||
* usb_lld.h (USB_EVENT_DEVICE_WAKEUP): New.
|
||||
(INTR_REQ_USB): Define here.
|
||||
* mcu/usb-usbip.c, example-cdc/usb-cdc.c,
|
||||
example-fraucheky/main.c, example-fs-bb48/usb-cdc.c: Change
|
||||
for INTR_REQ_USB.
|
||||
|
||||
2017-11-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx-cortex-m.c (svc): Replace stack top to TP.
|
||||
(chx_sched): Return ->v correctly.
|
||||
|
||||
* chopstx.c (chx_timer_expired): Fix timeout.
|
||||
|
||||
2017-10-11 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* mcu/sys-stm32f103.h (nonreturn_handler0, nonreturn_handler1): New.
|
||||
|
||||
2017-10-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* mcu/usb-usbip.c (usbip_run_server): Shutdown support.
|
||||
(usb_lld_shutdown): Shutdown glace-fully.
|
||||
|
||||
2017-10-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.5.
|
||||
* doc/chopstx.texi (VERSION): 1.5.
|
||||
* doc/chopstx-api.texi: Regenerated.
|
||||
|
||||
2017-10-09 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* example-cdc-gnu-linux/sample.c (main): Support debug option.
|
||||
|
||||
* mcu/sys-gnu-linux.h (debug): New.
|
||||
* mcu/sys-gnu-linux.c: Use debug.
|
||||
* mcu/usb-usbip.c: Use debug.
|
||||
|
||||
* example-cdc/sample.ld (.process_stack, .main_stack): Add NOLOAD.
|
||||
|
||||
2017-09-29 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* mcu/sys-stm32f103.c (flash_program_halfword, flash_erase_page)
|
||||
(flash_write, flash_erase_all_and_exec): Use uintptr_t.
|
||||
|
||||
2017-09-08 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* mcu/sys-gnu-linux.c: Flash emulation implemented.
|
||||
|
||||
2017-09-05 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* example-cdc: Use stack-def.h.
|
||||
* example-cdc/stack-def.h: New.
|
||||
|
||||
2017-09-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* mcu/sys-stm32f103.h (nvic_system_reset): Add noreturn attribute.
|
||||
|
||||
* sys.h: Add mcu/sys-gnu-linux.h.
|
||||
|
||||
* mcu/sys-gnu-linux.c: New.
|
||||
* mcu/sys-gnu-linux.h: New.
|
||||
|
||||
2017-08-11 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.4.
|
||||
|
||||
90
NEWS
90
NEWS
@@ -1,6 +1,96 @@
|
||||
NEWS - Noteworthy changes
|
||||
|
||||
|
||||
* Major changes in Chopstx 1.9
|
||||
|
||||
Released 2018-05-09
|
||||
|
||||
** GD32F103 support
|
||||
GD32F103 is an alternative implementation of STM32F103 by Giga Device,
|
||||
which can run at 96MHz.
|
||||
|
||||
** Minor USB driver fix for STM32F103/GD32F103
|
||||
BTABLE setting should be done at initialization, not at USB RESET.
|
||||
|
||||
** Minor SYS driver fix for GD32F103
|
||||
flash_protect should check FLASH_CR_OPTWRE.
|
||||
|
||||
** Minor ADC driver change for GD32F103
|
||||
ADC on GD32F103 is another implementation and its behavior is somewhat
|
||||
different. It requires waits after enabling. So, we use continuous
|
||||
sampling, instead of start and stop for each sample. Still, we
|
||||
observe enough noise (> 4.7 bit/byte) for each ADC sampling.
|
||||
|
||||
|
||||
* Major changes in Chopstx 1.8
|
||||
|
||||
Released 2018-01-19
|
||||
|
||||
** Minor driver API fix
|
||||
In version 1.6, part of mcu/stm32f103.h was moved into mcu/cortex-m.h
|
||||
and mcu/stm32.h. Now, mcu/stm32f103.h automatically includes
|
||||
mcu/cortex-m.h and mcu/stm32.h, so that it doesn't break existing
|
||||
applications.
|
||||
|
||||
|
||||
* Major changes in Chopstx 1.7
|
||||
|
||||
Released 2017-12-19
|
||||
|
||||
** Fix: timer wakeup
|
||||
Timer expiration had a bug. When it is waken up, the wake up doesn't
|
||||
handle as a timer expiration when there are multiple threads on same
|
||||
timing of expire. It confuses as if it were forced wakeup.
|
||||
|
||||
** New driver: USART for STM32.
|
||||
USART driver for STM32 is added.
|
||||
|
||||
|
||||
* Major changes in Chopstx 1.6
|
||||
|
||||
Released 2017-11-24
|
||||
|
||||
** Fix cancellation
|
||||
In Chopstx 1.4 and 1.5, cancellation doesn't work for real MCU. This
|
||||
is due to the change of chx_sched interface, introduced for GNU/Linux
|
||||
emulation. This bug is fixed.
|
||||
|
||||
** New feature: sleep mode
|
||||
New function chopstx_conf_idle is added to support sleep. Note that
|
||||
use of sleep by this feature requires careful preparation. For
|
||||
example, enabling sleep, a board with no RESET pin cannot be debugged
|
||||
by JTAG/SWD. Setting of DBGMCU_CR (0xE0042004) is required beforehand
|
||||
(hardware default is zero).
|
||||
|
||||
** API change: chopstx_poll
|
||||
This is a kind of clarification. The third argument is now an array
|
||||
of constant pointers. We don't touch the array itself, just use it.
|
||||
This allows having the array in read-only memory and can contribute
|
||||
less use of RAM.
|
||||
|
||||
** USB API changes
|
||||
INTR_REQ_USB is now defined by usb_lld.h. Enumeration type of
|
||||
DEVICE_STATE now has USB_DEVICE_STATE_ prefix.
|
||||
|
||||
** USB driver change
|
||||
USB suspend and wakeup events are supported for STM32F103.
|
||||
|
||||
|
||||
* Major changes in Chopstx 1.5
|
||||
|
||||
Released 2017-10-10
|
||||
|
||||
** Stack size definition by stack-def.h
|
||||
Stack size of each thread was used to be defined in ldscript.
|
||||
While emulation on GNU/Linux doesn't use ldscript, it is better
|
||||
to put those definitions in independent header file. Please see
|
||||
example-cdc/stack-def.h and example-cdc/sample.ld.
|
||||
|
||||
** More support for emulation on GNU/Linux
|
||||
We have SYS driver for emulation on GNU/Linux. It has flash ROM
|
||||
emulation.
|
||||
|
||||
|
||||
* Major changes in Chopstx 1.4
|
||||
|
||||
Released 2017-08-11
|
||||
|
||||
32
README
32
README
@@ -1,22 +1,34 @@
|
||||
Chopstx - Threads and only Threads
|
||||
Version 1.4
|
||||
2017-08-11
|
||||
Version 1.9
|
||||
2018-05-09
|
||||
Niibe Yutaka
|
||||
Flying Stone Technology
|
||||
|
||||
What's Chopstx?
|
||||
===============
|
||||
|
||||
Chopstx is an RT thread library for STM32F103 (ARM Cortex-M3),
|
||||
STM32F030 (ARM Cortex-M0), MKL27Z (ARM Cortex-M0plus), and
|
||||
Chopstx is an RT thread library for STM32F103 and GD32F103 (ARM
|
||||
Cortex-M3), STM32F030 (ARM Cortex-M0), MKL27Z (ARM Cortex-M0plus), and
|
||||
emulation on GNU/Linux.
|
||||
|
||||
While most RTOSes come with many features, drivers, and stacks,
|
||||
Chopstx just offers a simple RT thread library.
|
||||
While most RTOSes come with many features, drivers, and protocol
|
||||
stacks, Chopstx just offers a simple RT thread library.
|
||||
|
||||
With Chopstx, interrupt handling is also done by a thread. This
|
||||
enables coherent code for ease of maintenance.
|
||||
|
||||
While threads are important, we don't need more threads than
|
||||
necessary. Chopstx provides a feature of poll, so that we can
|
||||
minimize use of threads.
|
||||
|
||||
|
||||
Note that this library is _not_ related to the hand game:
|
||||
|
||||
https://en.wikipedia.org/wiki/Chopsticks_(hand_game)
|
||||
|
||||
Thanks to Yao Wei and Enrico Zini for giving me an opportunity
|
||||
visiting the wiki page above, when my children were playing the game.
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
@@ -30,13 +42,15 @@ Example code
|
||||
============
|
||||
|
||||
We have some examples in this distribution; Useful ones are LED
|
||||
blinker and USB CDC-ACM function. For STM32F103, you can build it
|
||||
USB CDC-ACM demo by:
|
||||
blinker and USB CDC-ACM device. For STM32F103, you can build it USB
|
||||
CDC-ACM demo by:
|
||||
|
||||
$ cd example-cdc
|
||||
$ ln -sf ../board/board-olimex-stm32-h103.h board.h
|
||||
$ make
|
||||
|
||||
If you want to try GD32F103, Add -DMHZ=96 to DEFS in Makefile.
|
||||
|
||||
For a specific board named FSM-55, an example of LED matrix dynamic
|
||||
driver is provided. See the directory: example-fsm-55.
|
||||
|
||||
@@ -47,7 +61,7 @@ Future Works
|
||||
============
|
||||
|
||||
Convenience function to determine the bottom of thread stack,
|
||||
configuration of thread size by comiler's output would be next things
|
||||
configuration of thread size by compiler's output would be next things
|
||||
to be done.
|
||||
|
||||
Experimental SMP port for Cortex-A7 is under development. For SMP,
|
||||
|
||||
42
board/board-blue-pill-g.h
Normal file
42
board/board-blue-pill-g.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#define BOARD_NAME "Blue Pill GD32F103"
|
||||
/* http://wiki.stm32duino.com/index.php?title=Blue_Pill */
|
||||
/* echo -n "Blue Pill GD32F103" | shasum -a 256 | sed -e 's/^.*\(........\) -$/\1/' */
|
||||
#define BOARD_ID 0xed415594
|
||||
|
||||
#define MCU_STM32F1_GD32F1 1
|
||||
#define STM32_USBPRE STM32_USBPRE_DIV2
|
||||
#define STM32_ADCPRE STM32_ADCPRE_DIV8
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
#define STM32_PLLMUL_VALUE 12
|
||||
#define STM32_HSECLK 8000000
|
||||
|
||||
#define GPIO_LED_BASE GPIOC_BASE
|
||||
#define GPIO_LED_CLEAR_TO_EMIT 13
|
||||
#define GPIO_USB_BASE GPIOA_BASE
|
||||
#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)
|
||||
*
|
||||
* Port C setup.
|
||||
* 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)
|
||||
@@ -3,6 +3,7 @@
|
||||
/* echo -n "Blue Pill" | shasum -a 256 | sed -e 's/^.*\(........\) -$/\1/' */
|
||||
#define BOARD_ID 0xa1099d43
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
@@ -12,13 +13,14 @@
|
||||
#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)
|
||||
*
|
||||
* Port C setup.
|
||||
* PC13 - Push pull output 50MHz (LED 1:ON 0:OFF)
|
||||
* ------------------------ Default
|
||||
* PAx - input with pull-up
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BOARD_NAME "CQ STARM"
|
||||
#define BOARD_ID 0xc5480875
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BOARD_NAME "FST-01-00"
|
||||
#define BOARD_ID 0x613870a9
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define BOARD_ID 0x696886af
|
||||
/* echo -n "FST-01" | sha256sum | sed -e 's/^.*\(........\) -$/\1/' */
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define BOARD_ID 0x8801277f
|
||||
/* echo -n "FST-01G" | sha256sum | sed -e 's/^.*\(........\) -$/\1/' */
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BOARD_NAME "Maple Mini"
|
||||
#define BOARD_ID 0x7a445272
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BOARD_NAME "NITROKEY-START"
|
||||
#define BOARD_ID 0xad1e7ebd
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BOARD_NAME "Olimex STM32-H103"
|
||||
#define BOARD_ID 0xf92bb594
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
@@ -30,11 +31,3 @@
|
||||
|
||||
#define RCC_ENR_IOP_EN RCC_APB2ENR_IOPCEN
|
||||
#define RCC_RSTR_IOP_RST RCC_APB2RSTR_IOPCRST
|
||||
|
||||
/* NeuG settings for ADC2. */
|
||||
#define NEUG_ADC_SETTING2_SMPR1 ADC_SMPR1_SMP_AN10(ADC_SAMPLE_1P5) \
|
||||
| ADC_SMPR1_SMP_AN11(ADC_SAMPLE_1P5)
|
||||
#define NEUG_ADC_SETTING2_SMPR2 0
|
||||
#define NEUG_ADC_SETTING2_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_IN10) \
|
||||
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN11)
|
||||
#define NEUG_ADC_SETTING2_NUM_CHANNELS 2
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/* echo -n "ST Dongle" | shasum -a 256 | sed -e 's/^.*\(........\) -$/\1/' */
|
||||
#define BOARD_ID 0x2cd4e471
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* GND BLACK --> 20 GND
|
||||
*/
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
@@ -25,21 +26,40 @@
|
||||
#define GPIO_LED_BASE GPIOA_BASE
|
||||
#define GPIO_LED_SET_TO_EMIT 5
|
||||
#undef GPIO_USB_BASE /* No external DISCONNECT/RENUM circuit. */
|
||||
#undef GPIO_OTHER_BASE
|
||||
#define GPIO_OTHER_BASE GPIOB_BASE
|
||||
|
||||
/*
|
||||
* Port A setup.
|
||||
* PA0 - input with pull-up. AN0
|
||||
* PA1 - input with pull-up. AN1
|
||||
* PA5 - Push pull output 50MHz (LED 1:ON 0:OFF)
|
||||
* PA0 - Input with pull-up USART2-CTS
|
||||
* PA1 - Alternate function push pull output 2MHz USART2-RTS
|
||||
* PA2 - Alternate function push pull output 2MHz USART2-TX
|
||||
* PA3 - Input with pull-up USART2-RX
|
||||
* PA4 - Alternate function push pull output 2MHz USART2-CK
|
||||
* PA5 - Push pull output 2MHz (LED 1:ON 0:OFF)
|
||||
* PA11 - Push Pull output 10MHz 0 default (until USB enabled) (USBDM)
|
||||
* PA12 - Push Pull output 10MHz 0 default (until USB enabled) (USBDP)
|
||||
* ------------------------ Default
|
||||
* PAx - input with pull-up
|
||||
*/
|
||||
#define VAL_GPIO_LED_ODR 0xFFFFE7FF
|
||||
#define VAL_GPIO_LED_CRL 0x88388888 /* PA7...PA0 */
|
||||
#define VAL_GPIO_LED_CRL 0x882A8AA8 /* PA7...PA0 */
|
||||
#define VAL_GPIO_LED_CRH 0x88811888 /* PA15...PA8 */
|
||||
|
||||
#define RCC_ENR_IOP_EN RCC_APB2ENR_IOPAEN
|
||||
#define RCC_RSTR_IOP_RST RCC_APB2RSTR_IOPARST
|
||||
/*
|
||||
* Port B setup.
|
||||
* PB0 - input with pull-up: AN8 for NeuG
|
||||
* PB1 - input with pull-up: AN9 for NeuG
|
||||
* PB10 - Alternate function push pull output 2MHz USART3-TX
|
||||
* PB11 - Input with pull-up USART3-RX
|
||||
* PB12 - Alternate function push pull output 2MHz USART3-CK
|
||||
* PB13 - Input with pull-up USART3-CTS
|
||||
* PB14 - Alternate function push pull output 2MHz USART3-RTS
|
||||
* ------------------------ Default
|
||||
* PBx - input with pull-up.
|
||||
*/
|
||||
#define VAL_GPIO_OTHER_ODR 0xFFFFFFFF
|
||||
#define VAL_GPIO_OTHER_CRL 0x88888888 /* PB7...PB0 */
|
||||
#define VAL_GPIO_OTHER_CRH 0x8A8A8A88 /* PB15...PB8 */
|
||||
|
||||
#define RCC_ENR_IOP_EN (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN)
|
||||
#define RCC_RSTR_IOP_RST (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BOARD_NAME "STBee Mini"
|
||||
#define BOARD_ID 0x1f341961
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#define BOARD_NAME "STBee"
|
||||
#define BOARD_ID 0x945c37e8
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
/* High-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
#define STM32_PLLMUL_VALUE 6
|
||||
#define STM32_HSECLK 12000000
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#define BOARD_NAME "STM32 Primer2"
|
||||
#define BOARD_ID 0x21e5798d
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
/* High-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
#define STM32_PLLMUL_VALUE 6
|
||||
#define STM32_HSECLK 12000000
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#define BOARD_NAME "STM32F0 Discovery"
|
||||
#define BOARD_ID 0xde4b4bc1
|
||||
|
||||
#define MCU_STM32F0 1
|
||||
|
||||
/*
|
||||
* Running at 48MHz with HSI as clock source.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BOARD_NAME "STM8S Discovery"
|
||||
#define BOARD_ID 0x2f0976bb
|
||||
|
||||
#define MCU_STM32F1 1
|
||||
#define STM32F10X_MD /* Medium-density device */
|
||||
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
|
||||
@@ -229,18 +229,6 @@ chx_cpu_sched_unlock (void)
|
||||
}
|
||||
|
||||
|
||||
static void __attribute__((naked, used))
|
||||
idle (void)
|
||||
{
|
||||
#if defined(USE_WFI_FOR_IDLE)
|
||||
for (;;)
|
||||
asm volatile ("wfi" : : : "memory");
|
||||
#else
|
||||
for (;;);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
chx_handle_intr (void)
|
||||
{
|
||||
@@ -299,7 +287,7 @@ chx_request_preemption (uint16_t prio)
|
||||
*
|
||||
* Returns:
|
||||
* 1 on wakeup by others.
|
||||
* 0 on normal wakeup.
|
||||
* 0 on normal wakeup (timer expiration, lock aquirement).
|
||||
* -1 on cancellation.
|
||||
*/
|
||||
static uintptr_t __attribute__ ((naked, noinline))
|
||||
@@ -309,25 +297,24 @@ chx_sched (uint32_t yield)
|
||||
|
||||
#if defined(__ARM_ARCH_7M__)
|
||||
asm volatile (
|
||||
"svc #0\n\t"
|
||||
"bx lr"
|
||||
"svc #0"
|
||||
: "=r" (tp) : "0" (yield): "memory");
|
||||
#else
|
||||
register uint32_t arg_yield asm ("r1");
|
||||
|
||||
/* Build stack data as if it were an exception entry. */
|
||||
/*
|
||||
* r0: 0 scratch
|
||||
* r0: TP scratch
|
||||
* r1: 0 scratch
|
||||
* r2: 0 scratch
|
||||
* r3: 0 scratch
|
||||
* r12: 0 scratch
|
||||
* lr as-is
|
||||
* pc: return address (= lr)
|
||||
* pc: return address (= .L_CONTEXT_SWITCH_FINISH)
|
||||
* psr: INITIAL_XPSR scratch
|
||||
*/
|
||||
asm ("mov r1, lr\n\t"
|
||||
"mov r2, r1\n\t"
|
||||
"ldr r2, =.L_CONTEXT_SWITCH_FINISH\n\t"
|
||||
"mov r3, #128\n\t"
|
||||
"lsl r3, #17\n\t"
|
||||
"push {r1, r2, r3}\n\t"
|
||||
@@ -335,16 +322,16 @@ chx_sched (uint32_t yield)
|
||||
"mov r2, r1\n\t"
|
||||
"mov r3, r1\n\t"
|
||||
"push {r1, r2, r3}\n\t"
|
||||
"push {r1, r2}"
|
||||
: /* no output*/
|
||||
: /* no input */
|
||||
: "r1", "r2", "r3", "memory");
|
||||
|
||||
/* Save registers onto CHX_THREAD struct. */
|
||||
asm ("mov r1, r0\n\t"
|
||||
"mov r1, r0\n\t"
|
||||
"ldr r2, =running\n\t"
|
||||
"ldr r0, [r2]\n\t"
|
||||
"add r0, #20\n\t"
|
||||
"push {r0, r3}"
|
||||
: "=r" (tp), "=r" (arg_yield)
|
||||
: "0" (yield)
|
||||
: "r2", "r3", "memory");
|
||||
|
||||
/* Save registers onto CHX_THREAD struct. */
|
||||
asm ("add r0, #20\n\t"
|
||||
"stm r0!, {r4, r5, r6, r7}\n\t"
|
||||
"mov r2, r8\n\t"
|
||||
"mov r3, r9\n\t"
|
||||
@@ -353,8 +340,8 @@ chx_sched (uint32_t yield)
|
||||
"mov r6, sp\n\t"
|
||||
"stm r0!, {r2, r3, r4, r5, r6}\n\t"
|
||||
"sub r0, #56"
|
||||
: "=r" (tp), "=r" (arg_yield)
|
||||
: "0" (yield)
|
||||
: /* no output */
|
||||
: "r" (tp)
|
||||
: "r2", "r3", "r4", "r5", "r6", "r7", "memory");
|
||||
|
||||
if (arg_yield)
|
||||
@@ -383,7 +370,7 @@ chx_sched (uint32_t yield)
|
||||
/* Spawn an IDLE thread. */
|
||||
"ldr r1, =__main_stack_end__\n\t"
|
||||
"mov sp, r1\n\t"
|
||||
"ldr r0, =idle\n\t" /* PC = idle */
|
||||
"ldr r0, =chx_idle\n\t" /* PC = idle */
|
||||
/**/
|
||||
/* Unmask interrupts. */
|
||||
"cpsie i\n\t"
|
||||
@@ -391,11 +378,7 @@ chx_sched (uint32_t yield)
|
||||
|
||||
/* Normal context switch */
|
||||
"0:\n\t"
|
||||
"add r0, #16\n\t" /* ->V */
|
||||
"ldr r1, [r0]\n\t"
|
||||
"str r1, [sp]\n\t"
|
||||
/**/
|
||||
"add r0, #4\n\t"
|
||||
"add r0, #20\n\t"
|
||||
"ldm r0!, {r4, r5, r6, r7}\n\t"
|
||||
"ldm r0!, {r1, r2, r3}\n\t"
|
||||
"mov r8, r1\n\t"
|
||||
@@ -455,12 +438,17 @@ chx_sched (uint32_t yield)
|
||||
"mov r12, r0\n\t"
|
||||
"pop {r0, r1, r2, r3}\n\t"
|
||||
"add sp, #12\n\t"
|
||||
"pop {pc}"
|
||||
"pop {pc}\n\t"
|
||||
".L_CONTEXT_SWITCH_FINISH:"
|
||||
: "=r" (tp) /* Return value in R0 */
|
||||
: "0" (tp)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
asm volatile ("bx lr"
|
||||
: "=r" (tp)
|
||||
: "0" (tp->v)
|
||||
: "memory");
|
||||
return (uintptr_t)tp;
|
||||
}
|
||||
|
||||
@@ -631,7 +619,7 @@ preempt (void)
|
||||
"mov r3, #0\n\t"
|
||||
"stm r0!, {r1, r2, r3}\n\t"
|
||||
"stm r0!, {r1, r2, r3}\n\t"
|
||||
"ldr r1, =idle\n\t" /* PC = idle */
|
||||
"ldr r1, =chx_idle\n\t" /* PC = idle */
|
||||
"mov r2, #0x010\n\t"
|
||||
"lsl r2, r2, #20\n\t" /* xPSR = T-flag set (Thumb) */
|
||||
"stm r0!, {r1, r2}\n\t"
|
||||
@@ -675,7 +663,8 @@ svc (void)
|
||||
"mov r5, r11\n\t"
|
||||
"mrs r6, PSP\n\t" /* r13(=SP) in user space. */
|
||||
"stm r1!, {r2, r3, r4, r5, r6}\n\t"
|
||||
"ldr r1, [r6]"
|
||||
"ldr r1, [r6]\n\t"
|
||||
"str r0, [r6]"
|
||||
: "=r" (tp), "=r" (orig_r0)
|
||||
: /* no input */
|
||||
: "r2", "r3", "r4", "r5", "r6", "memory");
|
||||
@@ -697,10 +686,6 @@ svc (void)
|
||||
}
|
||||
|
||||
asm volatile (
|
||||
"cbz r0, 0f\n\t"
|
||||
"ldr r1, [r0, #16]\n\t" /* ->V */
|
||||
"str r1, [sp]\n\t"
|
||||
"0:\n\t"
|
||||
"b .L_CONTEXT_SWITCH"
|
||||
: /* no output */ : "r" (tp) : "memory");
|
||||
}
|
||||
|
||||
47
chopstx.c
47
chopstx.c
@@ -79,7 +79,11 @@ chx_fatal (uint32_t err_code)
|
||||
#include "chopstx-cortex-m.h"
|
||||
#endif
|
||||
|
||||
/* RUNNING: the current thread. */
|
||||
/* ALLOW_SLEEP for the idle thread. */
|
||||
int chx_allow_sleep;
|
||||
static struct chx_spinlock chx_enable_sleep_lock;
|
||||
|
||||
/* RUNNING: the current thread. */
|
||||
struct chx_thread *running;
|
||||
|
||||
struct chx_queue {
|
||||
@@ -382,6 +386,7 @@ chx_timer_expired (void)
|
||||
{
|
||||
uint32_t next_tick = tp->v;
|
||||
|
||||
tp->v = (uintptr_t)0;
|
||||
chx_ready_enqueue (tp);
|
||||
if (tp == running) /* tp->flag_sched_rr == 1 */
|
||||
prio = MAX_PRIO;
|
||||
@@ -398,6 +403,7 @@ chx_timer_expired (void)
|
||||
tp = tp_next)
|
||||
{
|
||||
next_tick = tp->v;
|
||||
tp->v = (uintptr_t)0;
|
||||
tp_next = (struct chx_thread *)tp->next;
|
||||
ll_dequeue ((struct chx_pq *)tp);
|
||||
chx_ready_enqueue (tp);
|
||||
@@ -440,6 +446,7 @@ chx_init (struct chx_thread *tp)
|
||||
{
|
||||
chx_prio_init ();
|
||||
chx_init_arch (tp);
|
||||
chx_spin_init (&chx_enable_sleep_lock);
|
||||
|
||||
q_ready.q.next = q_ready.q.prev = (struct chx_pq *)&q_ready.q;
|
||||
chx_spin_init (&q_ready.lock);
|
||||
@@ -569,6 +576,7 @@ chx_mutex_unlock (chopstx_mutex_t *mutex)
|
||||
uint16_t newprio = running->prio_orig;
|
||||
chopstx_mutex_t *m;
|
||||
|
||||
tp->v = (uintptr_t)0;
|
||||
chx_ready_enqueue (tp);
|
||||
|
||||
/* Examine mutexes we hold, and determine new priority for running. */
|
||||
@@ -1316,7 +1324,7 @@ chx_proxy_init (struct chx_px *px, uint32_t *cp)
|
||||
* Returns number of active descriptors.
|
||||
*/
|
||||
int
|
||||
chopstx_poll (uint32_t *usec_p, int n, struct chx_poll_head *pd_array[])
|
||||
chopstx_poll (uint32_t *usec_p, int n, struct chx_poll_head *const pd_array[])
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
int i;
|
||||
@@ -1469,3 +1477,38 @@ chopstx_setpriority (chopstx_prio_t prio_new)
|
||||
|
||||
return prio_orig;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* chopstx_conf_idle - Configure IDLE thread
|
||||
* @enable_sleep: Enable sleep on idle or not
|
||||
*
|
||||
* If @enable_sleep is > 0, allow sleep for the idle thread.
|
||||
*
|
||||
* Behavior of @enable_sleep >= 1 depends on MCU.
|
||||
*
|
||||
* For STM32F0, 1 for Sleep (CPU clock OFF only), 2 for Stop (Wakeup
|
||||
* by EXTI, voltage regulator on), 3 for Stop (Wakeup by EXTI, voltage
|
||||
* regulator low-power), 4 for Standby (Wakeup by RESET, voltage
|
||||
* regulator off).
|
||||
*
|
||||
* For STM32F103, 1 for normal sleep, and 2 for sleep with lower 8MHz
|
||||
* clock.
|
||||
*
|
||||
* Return previous value of @enable_sleep.
|
||||
*/
|
||||
extern void chx_sleep_mode (int enable_sleep);
|
||||
|
||||
int
|
||||
chopstx_conf_idle (int enable_sleep)
|
||||
{
|
||||
int r;
|
||||
|
||||
chx_spin_lock (&chx_enable_sleep_lock);
|
||||
r = chx_allow_sleep;
|
||||
chx_sleep_mode (enable_sleep);
|
||||
chx_allow_sleep = enable_sleep;
|
||||
chx_spin_unlock (&chx_enable_sleep_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* chopstx.h - Threads and only threads.
|
||||
*
|
||||
* Copyright (C) 2013, 2016 Flying Stone Technology
|
||||
* Copyright (C) 2013, 2016, 2017 Flying Stone Technology
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Chopstx, a thread library for embedded.
|
||||
@@ -158,6 +158,9 @@ 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, struct chx_poll_head *pd_array[]);
|
||||
int chopstx_poll (uint32_t *usec_p, int n,
|
||||
struct chx_poll_head *const pd_array[]);
|
||||
|
||||
int chopstx_conf_idle (int enable_sleep);
|
||||
|
||||
#define CHOPSTX_THREAD_SIZE 64
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* In this ADC driver, there are NeuG specific parts.
|
||||
* You need to modify to use this as generic ADC driver.
|
||||
*
|
||||
* Copyright (C) 2011, 2012, 2013, 2015, 2016
|
||||
* Copyright (C) 2011, 2012, 2013, 2015, 2016, 2017, 2018
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <chopstx.h>
|
||||
#include <mcu/stm32f103.h>
|
||||
#include "adc.h"
|
||||
#include "board.h"
|
||||
#include "sys.h"
|
||||
|
||||
#define STM32_ADC_ADC1_DMA_PRIORITY 2
|
||||
|
||||
@@ -46,6 +48,7 @@
|
||||
#define ADC_SMPR2_SMP_AN0(n) ((n) << 0)
|
||||
#define ADC_SMPR2_SMP_AN1(n) ((n) << 3)
|
||||
#define ADC_SMPR2_SMP_AN2(n) ((n) << 6)
|
||||
#define ADC_SMPR2_SMP_AN8(n) ((n) << 24)
|
||||
#define ADC_SMPR2_SMP_AN9(n) ((n) << 27)
|
||||
|
||||
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
|
||||
@@ -60,6 +63,7 @@
|
||||
#define ADC_CHANNEL_IN0 0
|
||||
#define ADC_CHANNEL_IN1 1
|
||||
#define ADC_CHANNEL_IN2 2
|
||||
#define ADC_CHANNEL_IN8 8
|
||||
#define ADC_CHANNEL_IN9 9
|
||||
#define ADC_CHANNEL_IN10 10
|
||||
#define ADC_CHANNEL_IN11 11
|
||||
@@ -67,7 +71,9 @@
|
||||
#define ADC_CHANNEL_VREFINT 17
|
||||
|
||||
#define DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
|
||||
#ifndef MCU_STM32F1_GD32F1
|
||||
#define DELIBARATELY_DO_IT_WRONG_START_STOP
|
||||
#endif
|
||||
|
||||
#ifdef DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
|
||||
#define ADC_SAMPLE_VREF ADC_SAMPLE_1P5
|
||||
@@ -112,6 +118,8 @@ adc_init (void)
|
||||
|
||||
ADC1->CR1 = 0;
|
||||
ADC1->CR2 = ADC_CR2_ADON;
|
||||
chopstx_usec_wait (1000);
|
||||
|
||||
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
|
||||
while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0)
|
||||
;
|
||||
@@ -122,6 +130,8 @@ adc_init (void)
|
||||
|
||||
ADC2->CR1 = 0;
|
||||
ADC2->CR2 = ADC_CR2_ADON;
|
||||
chopstx_usec_wait (1000);
|
||||
|
||||
ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
|
||||
while ((ADC2->CR2 & ADC_CR2_RSTCAL) != 0)
|
||||
;
|
||||
@@ -135,15 +145,13 @@ adc_init (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "board.h"
|
||||
#include "sys.h"
|
||||
|
||||
static void
|
||||
get_adc_config (uint32_t config[4])
|
||||
{
|
||||
config[2] = ADC_SQR1_NUM_CH(2);
|
||||
switch (SYS_BOARD_ID)
|
||||
{
|
||||
case BOARD_ID_FST_01G:
|
||||
case BOARD_ID_FST_01:
|
||||
config[0] = 0;
|
||||
config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
|
||||
@@ -169,13 +177,20 @@ get_adc_config (uint32_t config[4])
|
||||
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN2);
|
||||
break;
|
||||
|
||||
case BOARD_ID_ST_NUCLEO_F103:
|
||||
config[0] = 0;
|
||||
config[1] = ADC_SMPR2_SMP_AN8(ADC_SAMPLE_1P5)
|
||||
| ADC_SMPR2_SMP_AN9(ADC_SAMPLE_1P5);
|
||||
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN8)
|
||||
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN9);
|
||||
break;
|
||||
|
||||
case BOARD_ID_CQ_STARM:
|
||||
case BOARD_ID_FST_01_00:
|
||||
case BOARD_ID_MAPLE_MINI:
|
||||
case BOARD_ID_STM32_PRIMER2:
|
||||
case BOARD_ID_STM8S_DISCOVERY:
|
||||
case BOARD_ID_ST_DONGLE:
|
||||
case BOARD_ID_ST_NUCLEO_F103:
|
||||
case BOARD_ID_NITROKEY_START:
|
||||
default:
|
||||
config[0] = 0;
|
||||
@@ -202,24 +217,26 @@ adc_start (void)
|
||||
|
||||
RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
|
||||
|
||||
ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
|
||||
| ADC_CR1_SCAN);
|
||||
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
|
||||
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
|
||||
ADC1->SMPR1 = NEUG_ADC_SETTING1_SMPR1;
|
||||
ADC1->SMPR2 = NEUG_ADC_SETTING1_SMPR2;
|
||||
ADC1->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING1_NUM_CHANNELS);
|
||||
ADC1->SQR2 = 0;
|
||||
ADC1->SQR3 = NEUG_ADC_SETTING1_SQR3;
|
||||
|
||||
ADC2->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
|
||||
ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
|
||||
| ADC_CR1_SCAN);
|
||||
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
|
||||
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
|
||||
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
|
||||
chopstx_usec_wait (1000);
|
||||
|
||||
ADC2->SMPR1 = config[0];
|
||||
ADC2->SMPR2 = config[1];
|
||||
ADC2->SQR1 = config[2];
|
||||
ADC2->SQR2 = 0;
|
||||
ADC2->SQR3 = config[3];
|
||||
ADC2->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
|
||||
| ADC_CR1_SCAN);
|
||||
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
|
||||
chopstx_usec_wait (1000);
|
||||
|
||||
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
|
||||
/*
|
||||
|
||||
624
contrib/usart-stm32f103.c
Normal file
624
contrib/usart-stm32f103.c
Normal file
@@ -0,0 +1,624 @@
|
||||
/*
|
||||
* usart-stm32.c - USART driver for STM32F103 (USART2 and USART3)
|
||||
*
|
||||
* Copyright (C) 2017 g10 Code GmbH
|
||||
* 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>
|
||||
#include <chopstx.h>
|
||||
#include <mcu/stm32.h>
|
||||
#include <contrib/usart.h>
|
||||
|
||||
struct USART {
|
||||
volatile uint32_t SR;
|
||||
volatile uint32_t DR;
|
||||
volatile uint32_t BRR;
|
||||
volatile uint32_t CR1;
|
||||
volatile uint32_t CR2;
|
||||
volatile uint32_t CR3;
|
||||
volatile uint32_t GTPR;
|
||||
};
|
||||
|
||||
#define USART2_BASE (APB1PERIPH_BASE + 0x4400)
|
||||
#define USART3_BASE (APB1PERIPH_BASE + 0x4800)
|
||||
static struct USART *const USART2 = (struct USART *)USART2_BASE;
|
||||
static struct USART *const USART3 = (struct USART *)USART3_BASE;
|
||||
|
||||
#define USART_SR_CTS (1 << 9)
|
||||
#define USART_SR_LBD (1 << 8)
|
||||
#define USART_SR_TXE (1 << 7)
|
||||
#define USART_SR_TC (1 << 6)
|
||||
#define USART_SR_RXNE (1 << 5)
|
||||
#define USART_SR_IDLE (1 << 4)
|
||||
#define USART_SR_ORE (1 << 3)
|
||||
#define USART_SR_NE (1 << 2)
|
||||
#define USART_SR_FE (1 << 1)
|
||||
#define USART_SR_PE (1 << 0)
|
||||
|
||||
|
||||
#define USART_CR1_UE (1 << 13)
|
||||
#define USART_CR1_M (1 << 12)
|
||||
#define USART_CR1_WAKE (1 << 11)
|
||||
#define USART_CR1_PCE (1 << 10)
|
||||
#define USART_CR1_PS (1 << 9)
|
||||
#define USART_CR1_PEIE (1 << 8)
|
||||
#define USART_CR1_TXEIE (1 << 7)
|
||||
#define USART_CR1_TCIE (1 << 6)
|
||||
#define USART_CR1_RXNEIE (1 << 5)
|
||||
#define USART_CR1_IDLEIE (1 << 4)
|
||||
#define USART_CR1_TE (1 << 3)
|
||||
#define USART_CR1_RE (1 << 2)
|
||||
#define USART_CR1_RWU (1 << 1)
|
||||
#define USART_CR1_SBK (1 << 0)
|
||||
|
||||
|
||||
static struct USART *
|
||||
get_usart_dev (uint8_t dev_no)
|
||||
{
|
||||
if (dev_no == 2)
|
||||
return USART2;
|
||||
else if (dev_no == 3)
|
||||
return USART3;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We assume 36MHz f_PCLK */
|
||||
struct brr_setting {
|
||||
uint8_t baud_spec;
|
||||
uint16_t brr_value;
|
||||
};
|
||||
#define NUM_BAUD (int)(sizeof (brr_table) / sizeof (struct brr_setting))
|
||||
|
||||
static const struct brr_setting brr_table[] = {
|
||||
{ B600, (3750 << 4)},
|
||||
{ B1200, (1875 << 4)},
|
||||
{ B2400, ( 937 << 4)|8},
|
||||
{ B9600, ( 234 << 4)|6},
|
||||
{ B19200, ( 117 << 4)|3},
|
||||
{ B57600, ( 39 << 4)|1},
|
||||
{ B115200, ( 19 << 4)|8},
|
||||
{ B230400, ( 9 << 4)|12},
|
||||
{ B460800, ( 4 << 4)|14},
|
||||
{ B921600, ( 2 << 4)|7},
|
||||
};
|
||||
|
||||
static void *usart_main (void *arg);
|
||||
|
||||
static struct usart_stat usart2_stat;
|
||||
static struct usart_stat usart3_stat;
|
||||
|
||||
int
|
||||
usart_config (uint8_t dev_no, uint32_t config_bits)
|
||||
{
|
||||
struct USART *USARTx = get_usart_dev (dev_no);
|
||||
uint8_t baud_spec = (config_bits & MASK_BAUD);
|
||||
int i;
|
||||
uint32_t cr1_config = (USART_CR1_UE | USART_CR1_RXNEIE
|
||||
| USART_CR1_TE | USART_CR1_RE);
|
||||
/* TXEIE will be enabled when putting char */
|
||||
/* No CTSIE, PEIE, TCIE, IDLEIE, LBDIE */
|
||||
if (USARTx == NULL)
|
||||
return -1;
|
||||
|
||||
/* Disable USART before configure. */
|
||||
USARTx->CR1 &= ~USART_CR1_UE;
|
||||
|
||||
if (((config_bits & MASK_CS) == CS7 && (config_bits & PARENB))
|
||||
|| ((config_bits & MASK_CS) == CS8 && (config_bits & PARENB) == 0))
|
||||
cr1_config &= ~USART_CR1_M;
|
||||
else if ((config_bits & MASK_CS) == CS8)
|
||||
cr1_config |= USART_CR1_M;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if ((config_bits & PARENB) == 0)
|
||||
cr1_config &= ~USART_CR1_PCE;
|
||||
else
|
||||
cr1_config |= USART_CR1_PCE;
|
||||
|
||||
if ((config_bits & PARODD) == 0)
|
||||
cr1_config &= ~USART_CR1_PS;
|
||||
else
|
||||
cr1_config |= USART_CR1_PS;
|
||||
|
||||
if ((config_bits & MASK_STOP) == STOP0B5)
|
||||
USARTx->CR2 = (0x1 << 12);
|
||||
else if ((config_bits & MASK_STOP) == STOP1B)
|
||||
USARTx->CR2 = (0x0 << 12);
|
||||
else if ((config_bits & MASK_STOP) == STOP1B5)
|
||||
USARTx->CR2 = (0x3 << 12);
|
||||
else /* if ((config_bits & MASK_STOP) == STOP2B) */
|
||||
USARTx->CR2 = (0x2 << 12);
|
||||
|
||||
for (i = 0; i < NUM_BAUD; i++)
|
||||
if (brr_table[i].baud_spec == baud_spec)
|
||||
break;
|
||||
|
||||
if (i >= NUM_BAUD)
|
||||
return -1;
|
||||
|
||||
USARTx->BRR = brr_table[i].brr_value;
|
||||
|
||||
if ((config_bits & MASK_FLOW))
|
||||
USARTx->CR3 = (1 << 9) | (1 << 8);
|
||||
else
|
||||
USARTx->CR3 = 0;
|
||||
|
||||
USARTx->CR1 = cr1_config;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int (*ss_notify_callback) (uint8_t dev_no, uint16_t notify_bits);
|
||||
|
||||
void
|
||||
usart_init (uint16_t prio, uintptr_t stack_addr, size_t stack_size,
|
||||
int (*cb) (uint8_t dev_no, uint16_t notify_bits))
|
||||
{
|
||||
ss_notify_callback = cb;
|
||||
usart2_stat.dev_no = 2;
|
||||
usart3_stat.dev_no = 3;
|
||||
|
||||
/* Enable USART2 and USART3 clocks, and strobe reset. */
|
||||
RCC->APB1ENR |= ((1 << 18) | (1 << 17));
|
||||
RCC->APB1RSTR = ((1 << 18) | (1 << 17));
|
||||
RCC->APB1RSTR = 0;
|
||||
|
||||
usart_config (2, B115200 | CS8 | STOP1B);
|
||||
usart_config (3, B115200 | CS8 | STOP1B);
|
||||
chopstx_create (prio, stack_addr, stack_size, usart_main, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ring buffer
|
||||
*/
|
||||
#define MAX_RB_BUF 1024
|
||||
|
||||
struct rb {
|
||||
uint8_t *buf;
|
||||
chopstx_mutex_t m;
|
||||
chopstx_cond_t data_available;
|
||||
chopstx_cond_t space_available;
|
||||
uint32_t head :10;
|
||||
uint32_t tail :10;
|
||||
uint32_t size :10;
|
||||
uint32_t full : 1;
|
||||
uint32_t empty : 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: size = 1024 can still work, regardless of the limit of 10-bit.
|
||||
*/
|
||||
static void
|
||||
rb_init (struct rb *rb, uint8_t *p, uint16_t size)
|
||||
{
|
||||
rb->buf = p;
|
||||
rb->size = size;
|
||||
chopstx_mutex_init (&rb->m);
|
||||
chopstx_cond_init (&rb->data_available);
|
||||
chopstx_cond_init (&rb->space_available);
|
||||
rb->head = rb->tail = 0;
|
||||
rb->full = 0;
|
||||
rb->empty = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
rb_add (struct rb *rb, uint8_t v)
|
||||
{
|
||||
rb->buf[rb->tail++] = v;
|
||||
if (rb->tail == rb->size)
|
||||
rb->tail = 0;
|
||||
if (rb->tail == rb->head)
|
||||
rb->full = 1;
|
||||
rb->empty = 0;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
rb_del (struct rb *rb)
|
||||
{
|
||||
uint32_t v = rb->buf[rb->head++];
|
||||
|
||||
if (rb->head == rb->size)
|
||||
rb->head = 0;
|
||||
if (rb->head == rb->tail)
|
||||
rb->empty = 1;
|
||||
rb->full = 0;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Application: consumer
|
||||
* Hardware: generator
|
||||
*/
|
||||
static int
|
||||
rb_ll_put (struct rb *rb, uint8_t v)
|
||||
{
|
||||
int r;
|
||||
|
||||
chopstx_mutex_lock (&rb->m);
|
||||
if (rb->full)
|
||||
r = -1;
|
||||
else
|
||||
{
|
||||
r = 0;
|
||||
rb_add (rb, v);
|
||||
chopstx_cond_signal (&rb->data_available);
|
||||
}
|
||||
chopstx_mutex_unlock (&rb->m);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Application: generator
|
||||
* Hardware: consumer
|
||||
*/
|
||||
static int
|
||||
rb_ll_get (struct rb *rb)
|
||||
{
|
||||
int r;
|
||||
|
||||
chopstx_mutex_lock (&rb->m);
|
||||
if (rb->empty)
|
||||
r = -1;
|
||||
else
|
||||
{
|
||||
r = rb_del (rb);
|
||||
chopstx_cond_signal (&rb->space_available);
|
||||
}
|
||||
chopstx_mutex_unlock (&rb->m);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
rb_ll_flush (struct rb *rb)
|
||||
{
|
||||
chopstx_mutex_lock (&rb->m);
|
||||
while (!rb->empty)
|
||||
rb_del (rb);
|
||||
chopstx_cond_signal (&rb->space_available);
|
||||
chopstx_mutex_unlock (&rb->m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Application: consumer
|
||||
* Hardware: generator
|
||||
*/
|
||||
static int
|
||||
rb_read (struct rb *rb, uint8_t *buf, uint16_t buflen)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
chopstx_mutex_lock (&rb->m);
|
||||
while (rb->empty)
|
||||
chopstx_cond_wait (&rb->data_available, &rb->m);
|
||||
|
||||
while (i < buflen)
|
||||
{
|
||||
buf[i++] = rb_del (rb);
|
||||
if (rb->empty)
|
||||
break;
|
||||
}
|
||||
chopstx_cond_signal (&rb->space_available);
|
||||
chopstx_mutex_unlock (&rb->m);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Application: generator
|
||||
* Hardware: consumer
|
||||
*/
|
||||
static void
|
||||
rb_write (struct rb *rb, uint8_t *buf, uint16_t buflen)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
chopstx_mutex_lock (&rb->m);
|
||||
|
||||
do
|
||||
{
|
||||
while (rb->full)
|
||||
chopstx_cond_wait (&rb->space_available, &rb->m);
|
||||
|
||||
while (i < buflen)
|
||||
{
|
||||
rb_add (rb, buf[i++]);
|
||||
if (rb->full)
|
||||
{
|
||||
chopstx_cond_signal (&rb->data_available);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i < buflen);
|
||||
|
||||
if (i)
|
||||
chopstx_cond_signal (&rb->data_available);
|
||||
chopstx_mutex_unlock (&rb->m);
|
||||
}
|
||||
|
||||
static int
|
||||
rb_empty_check (void *arg)
|
||||
{
|
||||
struct rb *rb = arg;
|
||||
return rb->empty == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rb_get_prepare_poll (struct rb *rb, chopstx_poll_cond_t *poll_desc)
|
||||
{
|
||||
poll_desc->type = CHOPSTX_POLL_COND;
|
||||
poll_desc->ready = 0;
|
||||
poll_desc->cond = &rb->data_available;
|
||||
poll_desc->mutex = &rb->m;
|
||||
poll_desc->check = rb_empty_check;
|
||||
poll_desc->arg = rb;
|
||||
}
|
||||
|
||||
#define INTR_REQ_USART2 38
|
||||
#define INTR_REQ_USART3 39
|
||||
|
||||
static uint8_t buf_usart2_rb_a2h[256];
|
||||
static uint8_t buf_usart2_rb_h2a[512];
|
||||
static uint8_t buf_usart3_rb_a2h[256];
|
||||
static uint8_t buf_usart3_rb_h2a[512];
|
||||
|
||||
static struct chx_intr usart2_intr;
|
||||
static struct chx_intr usart3_intr;
|
||||
|
||||
static struct rb usart2_rb_a2h;
|
||||
static struct rb usart2_rb_h2a;
|
||||
static struct rb usart3_rb_a2h;
|
||||
static struct rb usart3_rb_h2a;
|
||||
|
||||
static chopstx_poll_cond_t usart2_app_write_event;
|
||||
static chopstx_poll_cond_t usart3_app_write_event;
|
||||
|
||||
static struct chx_poll_head *usart_poll[4];
|
||||
|
||||
/* Global variables so that it can be easier to debug. */
|
||||
static int usart2_tx_ready;
|
||||
static int usart3_tx_ready;
|
||||
|
||||
#define UART_STATE_BITMAP_RX_CARRIER (1 << 0)
|
||||
#define UART_STATE_BITMAP_TX_CARRIER (1 << 1)
|
||||
#define UART_STATE_BITMAP_BREAK (1 << 2)
|
||||
#define UART_STATE_BITMAP_RINGSIGNAL (1 << 3)
|
||||
#define UART_STATE_BITMAP_FRAMING (1 << 4)
|
||||
#define UART_STATE_BITMAP_PARITY (1 << 5)
|
||||
#define UART_STATE_BITMAP_OVERRUN (1 << 6)
|
||||
|
||||
static int
|
||||
handle_intr (struct USART *USARTx, struct rb *rb2a, struct usart_stat *stat)
|
||||
{
|
||||
int tx_ready = 0;
|
||||
uint32_t r = USARTx->SR;
|
||||
int notify_bits = 0;
|
||||
|
||||
if ((r & USART_SR_TXE))
|
||||
{
|
||||
tx_ready = 1;
|
||||
USARTx->CR1 &= ~USART_CR1_TXEIE;
|
||||
}
|
||||
|
||||
if ((r & USART_SR_RXNE))
|
||||
{
|
||||
uint32_t data = USARTx->DR;
|
||||
|
||||
/* DR register should be accessed even if data is not used.
|
||||
* Its read-access has side effect of clearing error flags.
|
||||
*/
|
||||
asm volatile ("" : : "r" (data) : "memory");
|
||||
|
||||
if ((r & USART_SR_NE))
|
||||
stat->err_rx_noise++;
|
||||
else if ((r & USART_SR_FE))
|
||||
{
|
||||
/* NOTE: Noway to distinguish framing error and break */
|
||||
|
||||
stat->rx_break++;
|
||||
notify_bits |= UART_STATE_BITMAP_BREAK;
|
||||
}
|
||||
else if ((r & USART_SR_PE))
|
||||
{
|
||||
stat->err_rx_parity++;
|
||||
notify_bits |= UART_STATE_BITMAP_PARITY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((r & USART_SR_ORE))
|
||||
{
|
||||
stat->err_rx_overrun++;
|
||||
notify_bits |= UART_STATE_BITMAP_OVERRUN;
|
||||
}
|
||||
|
||||
/* XXX: if CS is 7-bit, mask it, or else parity bit in upper layer */
|
||||
if (rb_ll_put (rb2a, (data & 0xff)) < 0)
|
||||
stat->err_rx_overflow++;
|
||||
else
|
||||
stat->rx++;
|
||||
}
|
||||
}
|
||||
else if ((r & USART_SR_ORE))
|
||||
{ /* Clear ORE */
|
||||
uint32_t data = USARTx->DR;
|
||||
asm volatile ("" : : "r" (data) : "memory");
|
||||
stat->err_rx_overrun++;
|
||||
notify_bits |= UART_STATE_BITMAP_OVERRUN;
|
||||
}
|
||||
|
||||
if (notify_bits)
|
||||
{
|
||||
if ((*ss_notify_callback) (stat->dev_no, notify_bits))
|
||||
stat->err_notify_overflow++;
|
||||
}
|
||||
|
||||
return tx_ready;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_tx_ready (struct USART *USARTx, struct rb *rb2h,
|
||||
struct usart_stat *stat)
|
||||
{
|
||||
int tx_ready = 1;
|
||||
int c = rb_ll_get (rb2h);
|
||||
|
||||
if (c >= 0)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
USARTx->DR = (c & 0xff);
|
||||
stat->tx++;
|
||||
r = USARTx->SR;
|
||||
if ((r & USART_SR_TXE) == 0)
|
||||
{
|
||||
tx_ready = 0;
|
||||
USARTx->CR1 |= USART_CR1_TXEIE;
|
||||
}
|
||||
}
|
||||
|
||||
return tx_ready;
|
||||
}
|
||||
|
||||
static void *
|
||||
usart_main (void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
usart2_tx_ready = 1;
|
||||
usart3_tx_ready = 1;
|
||||
|
||||
chopstx_claim_irq (&usart2_intr, INTR_REQ_USART2);
|
||||
chopstx_claim_irq (&usart3_intr, INTR_REQ_USART3);
|
||||
|
||||
rb_init (&usart2_rb_a2h, buf_usart2_rb_a2h, sizeof buf_usart2_rb_a2h);
|
||||
rb_init (&usart2_rb_h2a, buf_usart2_rb_h2a, sizeof buf_usart2_rb_h2a);
|
||||
rb_init (&usart3_rb_a2h, buf_usart3_rb_a2h, sizeof buf_usart3_rb_a2h);
|
||||
rb_init (&usart3_rb_h2a, buf_usart3_rb_h2a, sizeof buf_usart3_rb_h2a);
|
||||
|
||||
rb_get_prepare_poll (&usart2_rb_a2h, &usart2_app_write_event);
|
||||
rb_get_prepare_poll (&usart3_rb_a2h, &usart3_app_write_event);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
usart_poll[n++] = (struct chx_poll_head *)&usart2_intr;
|
||||
usart_poll[n++] = (struct chx_poll_head *)&usart3_intr;
|
||||
if (usart2_tx_ready)
|
||||
usart_poll[n++] = (struct chx_poll_head *)&usart2_app_write_event;
|
||||
else
|
||||
usart2_app_write_event.ready = 0;
|
||||
if (usart3_tx_ready)
|
||||
usart_poll[n++] = (struct chx_poll_head *)&usart3_app_write_event;
|
||||
else
|
||||
usart3_app_write_event.ready = 0;
|
||||
|
||||
chopstx_poll (NULL, n, usart_poll);
|
||||
|
||||
if (usart2_intr.ready)
|
||||
usart2_tx_ready = handle_intr (USART2, &usart2_rb_h2a, &usart2_stat);
|
||||
|
||||
if (usart3_intr.ready)
|
||||
usart3_tx_ready = handle_intr (USART3, &usart3_rb_h2a, &usart3_stat);
|
||||
|
||||
if (usart2_tx_ready && usart2_app_write_event.ready)
|
||||
usart2_tx_ready = handle_tx_ready (USART2,
|
||||
&usart2_rb_a2h, &usart2_stat);
|
||||
|
||||
if (usart3_tx_ready && usart3_app_write_event.ready)
|
||||
usart3_tx_ready = handle_tx_ready (USART3,
|
||||
&usart3_rb_a2h, &usart3_stat);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
usart_read (uint8_t dev_no, char *buf, uint16_t buflen)
|
||||
{
|
||||
struct rb *rb;
|
||||
|
||||
if (dev_no == 2)
|
||||
rb = &usart2_rb_h2a;
|
||||
else if (dev_no == 3)
|
||||
rb = &usart3_rb_h2a;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (buf == NULL && buflen == 0)
|
||||
{
|
||||
rb_ll_flush (rb);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return rb_read (rb, (uint8_t *)buf, buflen);
|
||||
}
|
||||
|
||||
int
|
||||
usart_write (uint8_t dev_no, char *buf, uint16_t buflen)
|
||||
{
|
||||
struct rb *rb;
|
||||
|
||||
if (dev_no == 2)
|
||||
rb = &usart2_rb_a2h;
|
||||
else if (dev_no == 3)
|
||||
rb = &usart3_rb_a2h;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (buf == NULL && buflen == 0)
|
||||
rb_ll_flush (rb);
|
||||
else
|
||||
rb_write (rb, (uint8_t *)buf, buflen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct usart_stat *
|
||||
usart_stat (uint8_t dev_no)
|
||||
{
|
||||
if (dev_no == 2)
|
||||
return &usart2_stat;
|
||||
else if (dev_no == 3)
|
||||
return &usart3_stat;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
usart_send_break (uint8_t dev_no)
|
||||
{
|
||||
struct USART *USARTx = get_usart_dev (dev_no);
|
||||
if (USARTx == NULL)
|
||||
return -1;
|
||||
|
||||
if ((USARTx->CR1 & 0x01))
|
||||
return 1; /* Busy sending break, which was requested before. */
|
||||
|
||||
USARTx->CR1 |= 0x01;
|
||||
return 0;
|
||||
}
|
||||
66
contrib/usart.h
Normal file
66
contrib/usart.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#define B0 0 /* POSIX to hang up */
|
||||
|
||||
/* POSIX supports B75 to B300 */
|
||||
#define B600 16
|
||||
#define B1200 17
|
||||
#define B2400 19
|
||||
#define B9600 21
|
||||
#define B19200 22
|
||||
#define B57600 24
|
||||
#define B115200 25
|
||||
#define B230400 26
|
||||
#define B460800 27
|
||||
#define B921600 28
|
||||
#define MASK_BAUD 0x3f
|
||||
|
||||
/* POSIX supports 5, 6. USB suppots 16 */
|
||||
#define CS7 (2 << 6)
|
||||
#define CS8 (3 << 6)
|
||||
#define MASK_CS (0x7 << 6)
|
||||
|
||||
#define STOP0B5 (0 << 9) /* USART Hardware only */
|
||||
#define STOP1B (1 << 9) /* USB, POSIX */
|
||||
#define STOP1B5 (2 << 9) /* USB */
|
||||
#define STOP2B (3 << 9) /* USB, POSIX */
|
||||
#define MASK_STOP (0x3 << 9)
|
||||
|
||||
#define PARENB (1 << 11)
|
||||
#define PARODD (2 << 11)
|
||||
#define MASK_PAR (0x7 << 11)
|
||||
/* USB 0: none, 1: odd, 2: even, 3: mark, 4: space */
|
||||
|
||||
#define CRTSCTS (1 << 14)
|
||||
#define MASK_FLOW (0x1 << 14)
|
||||
|
||||
/*
|
||||
BAUD_BITS 6
|
||||
CS_BITS 3
|
||||
STOP_BITS 2
|
||||
PAR_BITS 3
|
||||
*/
|
||||
/* USB: SET_CONTROL_LINE_STATE
|
||||
DTR RTS */
|
||||
/* USB: SERIAL_STATE
|
||||
DSR DCD RI */
|
||||
|
||||
struct usart_stat {
|
||||
uint8_t dev_no;
|
||||
|
||||
uint32_t tx;
|
||||
uint32_t rx;
|
||||
uint32_t rx_break;
|
||||
uint32_t err_notify_overflow;
|
||||
uint32_t err_rx_overflow; /* software side */
|
||||
uint32_t err_rx_overrun; /* hardware side */
|
||||
uint32_t err_rx_noise;
|
||||
uint32_t err_rx_parity;
|
||||
};
|
||||
|
||||
|
||||
void usart_init (uint16_t prio, uintptr_t stack_addr, size_t stack_size,
|
||||
int (*ss_notify_callback) (uint8_t dev_no, uint16_t notify_bits));
|
||||
int usart_config (uint8_t dev_no, uint32_t config_bits);
|
||||
int usart_read (uint8_t dev_no, char *buf, uint16_t buflen);
|
||||
int usart_write (uint8_t dev_no, char *buf, uint16_t buflen);
|
||||
const struct usart_stat *usart_stat (uint8_t dev_no);
|
||||
int usart_send_break (uint8_t dev_no);
|
||||
@@ -9,7 +9,7 @@ stop further execution of code. It never returns.
|
||||
|
||||
@subheading chopstx_create
|
||||
@anchor{chopstx_create}
|
||||
@deftypefun {chopstx_t} {chopstx_create} (uint32_t @var{flags_and_prio}, uint32_t @var{stack_addr}, size_t @var{stack_size}, voidfunc @var{thread_entry}, void * @var{arg})
|
||||
@deftypefun {chopstx_t} {chopstx_create} (uint32_t @var{flags_and_prio}, uintptr_t @var{stack_addr}, size_t @var{stack_size}, voidfunc @var{thread_entry}, void * @var{arg})
|
||||
@var{flags_and_prio}: Flags and priority
|
||||
|
||||
@var{stack_addr}: Stack address
|
||||
@@ -176,7 +176,7 @@ 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}, struct chx_poll_head * [] @var{pd_array})
|
||||
@deftypefun {int} {chopstx_poll} (uint32_t * @var{usec_p}, int @var{n}, struct chx_poll_head *const [] @var{pd_array})
|
||||
@var{usec_p}: Pointer to usec for timeout. Forever if NULL.
|
||||
|
||||
@var{n}: Number of poll descriptors
|
||||
@@ -201,3 +201,23 @@ which starts its execution with priority of CHX_PRIO_MAIN_INIT, and
|
||||
let it change its priority after initialization of other threads.
|
||||
@end deftypefun
|
||||
|
||||
@subheading chx_sleep_mode
|
||||
@anchor{chx_sleep_mode}
|
||||
@deftypefun {extern void} {chx_sleep_mode} (int @var{enable_sleep})
|
||||
@var{enable_sleep}: Enable sleep on idle or not
|
||||
|
||||
If @var{enable_sleep} is > 0, allow sleep for the idle thread.
|
||||
|
||||
Behavior of @var{enable_sleep} >= 1 depends on MCU.
|
||||
|
||||
For STM32F0, 1 for Sleep (CPU clock OFF only), 2 for Stop (Wakeup
|
||||
by EXTI, voltage regulator on), 3 for Stop (Wakeup by EXTI, voltage
|
||||
regulator low-power), 4 for Standby (Wakeup by RESET, voltage
|
||||
regulator off).
|
||||
|
||||
For STM32F103, 1 for normal sleep, and 2 for sleep with lower 8MHz
|
||||
clock.
|
||||
|
||||
Return previous value of @var{enable_sleep}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename chopstx.info
|
||||
@set VERSION 1.4
|
||||
@set VERSION 1.9
|
||||
@settitle Chopstx Reference Manual
|
||||
@c Unify some of the indices.
|
||||
@syncodeindex tp fn
|
||||
@@ -11,7 +11,7 @@
|
||||
This manual is for Chopstx (version @value{VERSION}).
|
||||
|
||||
@noindent
|
||||
Copyright @copyright{} 2013, 2015, 2016 Flying Stone Technology @*
|
||||
Copyright @copyright{} 2013, 2015, 2016, 2017, 2018 Flying Stone Technology @*
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
@@ -59,6 +59,10 @@ section entitled ``Copying''.
|
||||
|
||||
@menu
|
||||
* Introduction:: What is Chopstx.
|
||||
* Threads and only Threads:: Threads and only Threads.
|
||||
* Poll or Pole:: Poll or Pole.
|
||||
* Note (Use of sleep mode):: Use it carefully.
|
||||
* Compile-time macro:: Macro to be defined.
|
||||
* API:: API.
|
||||
|
||||
Appendix
|
||||
@@ -83,16 +87,91 @@ Indexes
|
||||
@node Introduction
|
||||
@chapter Introduction
|
||||
|
||||
Chopstx is an RT thread library for ARM Cortex-M0, Cortex-M0plus and
|
||||
Cortex-M3. Specifically, it is used for STM32F030, MKL27Z and
|
||||
STM32F103.
|
||||
Chopstx is an RT thread library for ARM Cortex-M0, Cortex-M0plus,
|
||||
Cortex-M3 and GNU/Linux emulation. Specifically, it is used for
|
||||
STM32F030, MKL27Z, STM32F103, GD32F103 and as a command on GNU/Linux.
|
||||
|
||||
While most RTOSes come with many features, drivers, and stacks,
|
||||
Chopstx just offers a RT thread library.
|
||||
Chopstx just offers an RT thread library.
|
||||
|
||||
With Chopstx, interrupt handling is also done by a thread. This
|
||||
enables coherent code for ease of maintenance.
|
||||
|
||||
While threads are important, we don't need more threads than
|
||||
necessary. Chopstx provides a feature of poll, so that we can
|
||||
minimize use of threads.
|
||||
|
||||
|
||||
@node Threads and only Threads
|
||||
@chapter Threads and only Threads
|
||||
|
||||
Chopstx doesn't use the feature of (prioritized) nested vector
|
||||
interrupt mechanism at all. All interrupts are equally handled by a
|
||||
single entry of chx_handle_intr which just wakes up corresponding
|
||||
thread. This is the feature of Chopstx.
|
||||
|
||||
Nested vector interrupt machanism would be useful for interrupt-driven
|
||||
programming style for specific application targets, or, some other
|
||||
programing style like the one with spl of Unix. Some engineers
|
||||
(especially, hardware side) still seem to believe that it is a good
|
||||
feature to have. But from the view point of programming and
|
||||
maintenance of software, this is one of the most difficult part with
|
||||
little benefit, if any.
|
||||
|
||||
With traditional interrupt handling, a demarcation of what should be
|
||||
done by interrupt handler, bottom half, and thead is crucial for
|
||||
applications' performance. And because the demarcation should be done
|
||||
at an early stage of an application development, it has a tendency,
|
||||
many parts are getting demanding higher priority. Amount of code for
|
||||
higher priority interrupt hander is getting bigger and bigger, while
|
||||
losing performance.
|
||||
|
||||
On the other hand, ``Threads (and only Threads)'' programming style
|
||||
gives us best flexibility and it can make an application more
|
||||
predictable, deterministic and easy to maintain.
|
||||
|
||||
There are some applications, like square wave generator, which are not
|
||||
suited to this programming style; Another programming style can
|
||||
support more performance (frequency). In general, such an example is
|
||||
best suited by hardware (not software).
|
||||
|
||||
|
||||
@node Poll or Pole
|
||||
@chapter Poll or Pole
|
||||
Chopstx provides the @code{chopstx_poll} function to wait on multiple events.
|
||||
|
||||
Using @code{chopstx_poll}, we can write an application by event-driven
|
||||
programming style, with minimum number of threads, avoiding
|
||||
complicated dependency between threads.
|
||||
|
||||
|
||||
@node Note (Use of sleep mode)
|
||||
@chapter Note (Use of sleep mode)
|
||||
|
||||
Calling the chopstx_conf_idle function (> 0) to allow the idle thread
|
||||
going to sleep. MCU will be in sleep mode when no threads are
|
||||
running. By setting relevant bits of system registers, MCU will be
|
||||
able to be into stop or stand-by mode, which is MCU dependent.
|
||||
|
||||
If you use this sleep feature, please consider and implement your
|
||||
program carefully. Enabling sleep, it may result a bricked board; A
|
||||
board with no RESET pin cannot be debugged by JTAG/SWD.
|
||||
|
||||
|
||||
@node Compile-time macro
|
||||
@chapter Compile-time macro
|
||||
|
||||
Compiling Chopstx, a macro MHZ should be supplied.
|
||||
|
||||
For example, when using the makefile rule of chopstx/rules.mk, please
|
||||
define the make variable DEFS with -DMHZ=72 before inclusion of the rule file.
|
||||
|
||||
@subheading MHZ
|
||||
@anchor{MHZ}
|
||||
@defmac {MHZ}
|
||||
Running CPU clock in MHz. Used for chopstx_usec_wait.
|
||||
@end defmac
|
||||
|
||||
|
||||
@node API
|
||||
@chapter API
|
||||
|
||||
35
entry.c
35
entry.c
@@ -205,23 +205,23 @@ handler vector_table[] __attribute__ ((section(".startup.vectors"))) = {
|
||||
preempt, /* PendSV */
|
||||
chx_timer_expired, /* SysTick */
|
||||
/* 0x40 */
|
||||
chx_handle_intr /* WWDG */, chx_handle_intr /* PVD */,
|
||||
chx_handle_intr /* TAMPER */, chx_handle_intr /* RTC */,
|
||||
chx_handle_intr /* FLASH */, chx_handle_intr /* RCC */,
|
||||
chx_handle_intr /* EXTI0 */, chx_handle_intr /* EXTI1 */,
|
||||
chx_handle_intr /* WWDG */, chx_handle_intr /* PVD */,
|
||||
chx_handle_intr /* TAMPER */, chx_handle_intr /* RTC */,
|
||||
chx_handle_intr /* FLASH */, chx_handle_intr /* RCC */,
|
||||
chx_handle_intr /* EXTI0 */, chx_handle_intr /* EXTI1 */,
|
||||
/* 0x60 */
|
||||
chx_handle_intr /* EXTI2 */, chx_handle_intr /* EXTI3 */,
|
||||
chx_handle_intr /* EXTI4 */, chx_handle_intr /* DMA1 CH1 */,
|
||||
chx_handle_intr /* DMA1 CH2 */, chx_handle_intr /* DMA1 CH3 */,
|
||||
chx_handle_intr /* DMA1 CH4 */, chx_handle_intr /* DMA1 CH5 */,
|
||||
chx_handle_intr /* EXTI2 */, chx_handle_intr /* EXTI3 */,
|
||||
chx_handle_intr /* EXTI4 */, chx_handle_intr /* DMA1 CH1 */,
|
||||
chx_handle_intr /* DMA1 CH2 */, chx_handle_intr /* DMA1 CH3 */,
|
||||
chx_handle_intr /* DMA1 CH4 */, chx_handle_intr /* DMA1 CH5 */,
|
||||
/* 0x80 */
|
||||
chx_handle_intr /* DMA1 CH6 */, chx_handle_intr /* DMA1 CH7 */,
|
||||
chx_handle_intr /* ADC1_2 */, chx_handle_intr /* USB HP */,
|
||||
chx_handle_intr /* DMA1 CH6 */, chx_handle_intr /* DMA1 CH7 */,
|
||||
chx_handle_intr /* ADC1_2 */, chx_handle_intr /* USB HP */,
|
||||
/* 0x90 */
|
||||
chx_handle_intr /* USB LP */, chx_handle_intr /* CAN */,
|
||||
/* ... and more. EXT9_5, TIMx, I2C, SPI, USART, EXT15_10 */
|
||||
chx_handle_intr, chx_handle_intr,
|
||||
/* 0xA0 */
|
||||
chx_handle_intr /* USB LP */, chx_handle_intr /* CAN RX1 */,
|
||||
chx_handle_intr /* CAN SCE */, chx_handle_intr /* EXT9_5 */,
|
||||
/* 0xa0 */
|
||||
/* ... and more. TIMx, I2C, SPI, USART... */
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
/* 0xc0 */
|
||||
@@ -229,15 +229,16 @@ handler vector_table[] __attribute__ ((section(".startup.vectors"))) = {
|
||||
/* STM32F0 doesn't have more. */
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
/* 0xe0 */
|
||||
chx_handle_intr /* EXT15_10 */, chx_handle_intr /* RTCAlarm */,
|
||||
chx_handle_intr /* USBWakeup */, chx_handle_intr,
|
||||
#endif
|
||||
#if !defined(STM32F10X_MD)
|
||||
/* High-density chips have more; RTCAlarm, USBWakeup, ... , DMA2_Channel4_5 */
|
||||
/* High-density chips have more; ... DMA2_Channel4_5 */
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
chx_handle_intr, chx_handle_intr, chx_handle_intr,
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -6,12 +6,12 @@ PROJECT = sample
|
||||
|
||||
CHOPSTX = ..
|
||||
LDSCRIPT=
|
||||
CSRC = sample.c usb-cdc.c
|
||||
CSRC = sample.c usb-cdc.c command.c
|
||||
|
||||
CHIP=gnu-linux
|
||||
# USE_SYS = yes
|
||||
USE_SYS =
|
||||
USE_SYS = yes
|
||||
USE_USB = yes
|
||||
USE_ADC = yes
|
||||
EMULATION=yes
|
||||
|
||||
###################################
|
||||
@@ -22,7 +22,7 @@ OBJCOPY = $(CROSS)objcopy
|
||||
|
||||
MCU = none
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
DEFS = -DGNU_LINUX_EMULATION
|
||||
DEFS = -DGNU_LINUX_EMULATION -DUSE_SYS_BOARD_ID
|
||||
OPT = -g # -O3 -Os
|
||||
LIBS = -lpthread
|
||||
|
||||
@@ -34,3 +34,10 @@ board.h:
|
||||
@exit 1
|
||||
|
||||
distclean: clean
|
||||
|
||||
build/flash.data: Makefile
|
||||
@echo 'Generating 8192-byte flash.data'
|
||||
@/bin/echo -n -e '\xff\xff\xff\xff\xff\xff\xff\xff' >$@
|
||||
@for i in $(shell seq 1023); do /bin/echo -n -e '\xff\xff\xff\xff\xff\xff\xff\xff' >>$@; done
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
(0) Build and generate initial flash data
|
||||
|
||||
$ make
|
||||
$ make build/flash.data
|
||||
|
||||
|
||||
(1) preparation as root
|
||||
|
||||
Don't run ModemManager
|
||||
|
||||
579
example-cdc-gnu-linux/command.c
Normal file
579
example-cdc-gnu-linux/command.c
Normal file
@@ -0,0 +1,579 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <chopstx.h>
|
||||
#include "tty.h"
|
||||
#include "config.h"
|
||||
#ifdef ADC_SUPPORT
|
||||
#include "adc.h"
|
||||
static int adc_initialized = 0;
|
||||
#endif
|
||||
#include "board.h"
|
||||
#include "sys.h"
|
||||
|
||||
struct command_table
|
||||
{
|
||||
const char *name;
|
||||
void (*handler) (struct tty *tty, const char *line);
|
||||
};
|
||||
|
||||
/*
|
||||
* Put a line (or lines) to TTY.
|
||||
* LINE should be terminated with newline.
|
||||
*/
|
||||
static void
|
||||
put_line (struct tty *tty, const char *line)
|
||||
{
|
||||
tty_send (tty, line, strlen (line));
|
||||
}
|
||||
|
||||
static const char *help_string =
|
||||
"mdb ADDR [COUNT]; memory display byte\r\n"
|
||||
"mwh ADDR VALUE [COUNT]; memory write halfword\r\n"
|
||||
"fes ADDR [COUNT]; flash erase sector\r\n"
|
||||
"fwh ADDR VALUE [COUNT]; flash write halfword\r\n"
|
||||
#ifdef CRC32_SUPPORT
|
||||
"crc32 string; CRC32 calc string\r\n"
|
||||
#endif
|
||||
#ifdef ADC_SUPPORT
|
||||
"adc; get 256-byte from ADC\r\n"
|
||||
#endif
|
||||
"sysinfo; system information\r\n"
|
||||
"help\r\n";
|
||||
|
||||
static char hexchar (uint8_t x)
|
||||
{
|
||||
x &= 0x0f;
|
||||
if (x <= 0x09)
|
||||
return '0' + x;
|
||||
else if (x <= 0x0f)
|
||||
return 'a' + x - 10;
|
||||
else
|
||||
return '?';
|
||||
}
|
||||
|
||||
#ifdef TOUCH_SUPPORT
|
||||
static char *
|
||||
compose_decimal (char *s, int value)
|
||||
{
|
||||
uint32_t v;
|
||||
int col = 1000000000;
|
||||
int d;
|
||||
int digit_output = 0;
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
*s++ = '-';
|
||||
v = 1 + ~((uint32_t)value);
|
||||
}
|
||||
else
|
||||
v = (uint32_t)value;
|
||||
|
||||
while (col >= 10)
|
||||
{
|
||||
if (v >= (uint32_t)col)
|
||||
{
|
||||
d = v / col;
|
||||
v = v - d * col;
|
||||
*s++ = d + '0';
|
||||
digit_output = 1;
|
||||
}
|
||||
else if (digit_output)
|
||||
*s++ = '0';
|
||||
|
||||
col = col / 10;
|
||||
}
|
||||
|
||||
*s++ = v + '0';
|
||||
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
char *
|
||||
compose_hex_ptr (char *s, uintptr_t v)
|
||||
{
|
||||
s[0] = hexchar (v >> 60);
|
||||
s[1] = hexchar (v >> 56);
|
||||
s[2] = hexchar (v >> 52);
|
||||
s[3] = hexchar (v >> 48);
|
||||
s[4] = hexchar (v >> 44);
|
||||
s[5] = hexchar (v >> 40);
|
||||
s[6] = hexchar (v >> 36);
|
||||
s[7] = hexchar (v >> 32);
|
||||
s[8] = hexchar (v >> 28);
|
||||
s[9] = hexchar (v >> 24);
|
||||
s[10] = hexchar (v >> 20);
|
||||
s[11] = hexchar (v >> 16);
|
||||
s[12] = hexchar (v >> 12);
|
||||
s[13] = hexchar (v >> 8);
|
||||
s[14] = hexchar (v >> 4);
|
||||
s[15] = hexchar (v);
|
||||
return s+16;
|
||||
}
|
||||
|
||||
static char *
|
||||
compose_hex (char *s, uint32_t v)
|
||||
{
|
||||
s[0] = hexchar (v >> 28);
|
||||
s[1] = hexchar (v >> 24);
|
||||
s[2] = hexchar (v >> 20);
|
||||
s[3] = hexchar (v >> 16);
|
||||
s[4] = hexchar (v >> 12);
|
||||
s[5] = hexchar (v >> 8);
|
||||
s[6] = hexchar (v >> 4);
|
||||
s[7] = hexchar (v);
|
||||
return s+8;
|
||||
}
|
||||
|
||||
static char *
|
||||
compose_hex_byte (char *s, uint8_t v)
|
||||
{
|
||||
s[0] = hexchar (v >> 4);
|
||||
s[1] = hexchar (v);
|
||||
return s+2;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_hex (struct tty *tty, const char *s, uintptr_t *v_p)
|
||||
{
|
||||
uintptr_t v = 0;
|
||||
char c;
|
||||
|
||||
if (s[0] == '0' && s[1] == 'x')
|
||||
s = s + 2;
|
||||
while (1)
|
||||
{
|
||||
c = *s++;
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
s--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == ' ')
|
||||
break;
|
||||
|
||||
v = (v << 4);
|
||||
if (c >= '0' && c <= '9')
|
||||
v += (c - '0');
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
v += (c - 'a') + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
v += (c - 'A') + 10;
|
||||
else
|
||||
{
|
||||
put_line (tty, "hex error\r\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*v_p = v;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TOUCH_SUPPORT
|
||||
#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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
cmd_mdb (struct tty *tty, const char *line)
|
||||
{
|
||||
int i;
|
||||
uintptr_t addr = 0;
|
||||
int count = 0;
|
||||
char c;
|
||||
const char *s = line;
|
||||
|
||||
s = get_hex (tty, s, &addr);
|
||||
addr &= ~3;
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
if (*s == 0)
|
||||
count = 1;
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
c = *s++;
|
||||
|
||||
if (c == 0 || c == ' ')
|
||||
break;
|
||||
|
||||
count = count * 10;
|
||||
if (c >= '0' && c <= '9')
|
||||
count += c - '0';
|
||||
else
|
||||
{
|
||||
put_line (tty, "mdb error\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < count)
|
||||
{
|
||||
uint8_t v;
|
||||
char output[68];
|
||||
char *s;
|
||||
|
||||
s = compose_hex_ptr (output, addr);
|
||||
*s++ = ':';
|
||||
*s++ = ' ';
|
||||
|
||||
while (1)
|
||||
{
|
||||
v = *(uint8_t *)addr;
|
||||
s = compose_hex_byte (s, v);
|
||||
i++;
|
||||
addr += 1;
|
||||
if (i >= count || (i % 16) == 0)
|
||||
break;
|
||||
*s++ = ' ';
|
||||
}
|
||||
|
||||
*s++ = '\r';
|
||||
*s++ = '\n';
|
||||
tty_send (tty, output, s - output);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_mwh (struct tty *tty, const char *line)
|
||||
{
|
||||
(void)tty;
|
||||
(void)line;
|
||||
put_line (tty, "mwh not yet supported\r\n");
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_fes (struct tty *tty, const char *line)
|
||||
{
|
||||
int i;
|
||||
uintptr_t addr = 0;
|
||||
int count = 0;
|
||||
char c;
|
||||
const char *s = line;
|
||||
|
||||
s = get_hex (tty, s, &addr);
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
if (*s == 0)
|
||||
count = 1;
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
c = *s++;
|
||||
|
||||
if (c == 0 || c == ' ')
|
||||
break;
|
||||
|
||||
count = count * 10;
|
||||
if (c >= '0' && c <= '9')
|
||||
count += c - '0';
|
||||
else
|
||||
{
|
||||
put_line (tty, "fww error\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
flash_erase_page (addr);
|
||||
addr += 1024;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_fwh (struct tty *tty, const char *line)
|
||||
{
|
||||
int i;
|
||||
uintptr_t addr = 0;
|
||||
uintptr_t d;
|
||||
uint16_t value = 0;
|
||||
int count = 0;
|
||||
char c;
|
||||
const char *s = line;
|
||||
|
||||
s = get_hex (tty, s, &addr);
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
if (*s == 0)
|
||||
return;
|
||||
|
||||
s = get_hex (tty, s, &d);
|
||||
value = (uint16_t)d;
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
if (*s == 0)
|
||||
count = 1;
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
c = *s++;
|
||||
|
||||
if (c == 0 || c == ' ')
|
||||
break;
|
||||
|
||||
count = count * 10;
|
||||
if (c >= '0' && c <= '9')
|
||||
count += c - '0';
|
||||
else
|
||||
{
|
||||
put_line (tty, "fww error\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
flash_program_halfword (addr, value);
|
||||
addr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CRC32_SUPPORT
|
||||
static unsigned int crc_value;
|
||||
|
||||
static void
|
||||
cmd_crc32 (struct tty *tty, const char *line)
|
||||
{
|
||||
uint32_t v;
|
||||
char string[10];
|
||||
char *s;
|
||||
|
||||
crc32_init (&crc_value);
|
||||
while (*line)
|
||||
crc32_u8 (&crc_value, *line++);
|
||||
v = crc_value ^ 0xffffffff;
|
||||
|
||||
s = compose_hex (string, v);
|
||||
*s++ = '\r';
|
||||
*s++ = '\n';
|
||||
tty_send (tty, string, sizeof (string));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ADC_SUPPORT
|
||||
static void
|
||||
cmd_adc (struct tty *tty, const char *line)
|
||||
{
|
||||
int i;
|
||||
char output[73];
|
||||
char *s;
|
||||
|
||||
(void)line;
|
||||
|
||||
if (!adc_initialized)
|
||||
{
|
||||
if (adc_init ())
|
||||
{
|
||||
put_line (tty, "adc_init error\r\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
adc_start ();
|
||||
adc_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
adc_start_conversion (0, 64);
|
||||
adc_wait_completion ();
|
||||
|
||||
i = 0;
|
||||
s = output;
|
||||
while (1)
|
||||
{
|
||||
s = compose_hex (s, adc_buf[i]);
|
||||
i++;
|
||||
if ((i % 8))
|
||||
*s++ = ' ';
|
||||
else
|
||||
{
|
||||
*s++ = '\r';
|
||||
*s++ = '\n';
|
||||
tty_send (tty, output, s - output);
|
||||
s = output;
|
||||
if (i >= 64)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cmd_sysinfo (struct tty *tty, const char *line)
|
||||
{
|
||||
char output[73];
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
(void)line;
|
||||
memcpy (output, "SYS version: ", 13);
|
||||
s = output + 13;
|
||||
*s++ = sys_version[2];
|
||||
*s++ = sys_version[4];
|
||||
*s++ = sys_version[6];
|
||||
*s++ = '\r';
|
||||
*s++ = '\n';
|
||||
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, output, s - output);
|
||||
|
||||
memcpy (output, "Board name: ", 12);
|
||||
s = output + 12;
|
||||
for (i = 0; i < (int)sizeof (output) - 2; i ++)
|
||||
if ((*s = sys_board_name[i]) == 0)
|
||||
break;
|
||||
else
|
||||
s++;
|
||||
|
||||
*s++ = '\r';
|
||||
*s++ = '\n';
|
||||
tty_send (tty, output, s - output);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_help (struct tty *tty, const char *line)
|
||||
{
|
||||
(void)line;
|
||||
put_line (tty, help_string);
|
||||
}
|
||||
|
||||
|
||||
struct command_table command_table[] = {
|
||||
#ifdef TOUCH_SUPPORT
|
||||
{ "button", cmd_button },
|
||||
{ "touch", cmd_touch },
|
||||
#endif
|
||||
{ "mdb", cmd_mdb },
|
||||
{ "mwh", cmd_mwh },
|
||||
{ "fes", cmd_fes },
|
||||
{ "fwh", cmd_fwh },
|
||||
#ifdef CRC32_SUPPORT
|
||||
{ "crc32", cmd_crc32 },
|
||||
#endif
|
||||
#ifdef ADC_SUPPORT
|
||||
{ "adc", cmd_adc },
|
||||
#endif
|
||||
{ "sysinfo", cmd_sysinfo },
|
||||
{ "help", cmd_help },
|
||||
};
|
||||
|
||||
#define N_CMDS (int)(sizeof (command_table) / sizeof (struct command_table))
|
||||
|
||||
|
||||
/*
|
||||
* Dispatch a command parsing LINE.
|
||||
* Line is NULL terminated with no newline.
|
||||
*/
|
||||
void
|
||||
cmd_dispatch (struct tty *tty, const char *line)
|
||||
{
|
||||
int i;
|
||||
const char *p;
|
||||
unsigned int n = 0;
|
||||
|
||||
p = line;
|
||||
while (*p)
|
||||
{
|
||||
if (*p++ == ' ')
|
||||
break;
|
||||
n++;
|
||||
}
|
||||
|
||||
for (i = 0; i < N_CMDS; i++)
|
||||
if (n == strlen (command_table[i].name)
|
||||
&& strncmp ((const char *)line, command_table[i].name, n) == 0)
|
||||
break;
|
||||
|
||||
if (i != N_CMDS)
|
||||
(*command_table[i].handler) (tty, p);
|
||||
else
|
||||
{
|
||||
char crlf[] = { '\r', '\n' };
|
||||
|
||||
put_line (tty, "No such command: ");
|
||||
tty_send (tty, line, n);
|
||||
tty_send (tty, crlf, sizeof (crlf));
|
||||
}
|
||||
}
|
||||
2
example-cdc-gnu-linux/command.h
Normal file
2
example-cdc-gnu-linux/command.h
Normal file
@@ -0,0 +1,2 @@
|
||||
void cmd_dispatch (struct tty *tty, const char *line);
|
||||
char * compose_hex_ptr (char *s, uintptr_t v);
|
||||
2
example-cdc-gnu-linux/config.h
Normal file
2
example-cdc-gnu-linux/config.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#undef CRC32_SUPPORT
|
||||
#define ADC_SUPPORT
|
||||
@@ -5,33 +5,15 @@
|
||||
|
||||
#include <chopstx.h>
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
#include "usb_lld.h"
|
||||
#include "tty.h"
|
||||
#include "command.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void
|
||||
set_led (int on)
|
||||
{
|
||||
#if 0
|
||||
/* For debugging, no output of LED. */
|
||||
#if 1
|
||||
if (on)
|
||||
write (1, "********\x08\x08\x08\x08\x08\x08\x08\x08", 16);
|
||||
else
|
||||
write (1, " \x08\x08\x08\x08\x08\x08\x08\x08", 16);
|
||||
#else
|
||||
if (on)
|
||||
puts ("!");
|
||||
else
|
||||
puts ("");
|
||||
#endif
|
||||
#else
|
||||
(void)on;
|
||||
#endif
|
||||
}
|
||||
|
||||
static chopstx_mutex_t mtx;
|
||||
static chopstx_cond_t cnd0;
|
||||
static chopstx_cond_t cnd1;
|
||||
@@ -114,9 +96,10 @@ main (int argc, const char *argv[])
|
||||
{
|
||||
struct tty *tty;
|
||||
uint8_t count;
|
||||
uintptr_t addr;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
if (argc >= 2 && !strncmp (argv[1], "--debug=", 8))
|
||||
debug = strtol (&argv[1][8], NULL, 10);
|
||||
|
||||
chopstx_mutex_init (&mtx);
|
||||
chopstx_cond_init (&cnd0);
|
||||
@@ -134,6 +117,9 @@ main (int argc, const char *argv[])
|
||||
chopstx_cond_signal (&cnd1);
|
||||
chopstx_mutex_unlock (&mtx);
|
||||
|
||||
addr = flash_init ("flash.data");
|
||||
flash_unlock ();
|
||||
|
||||
u = 1;
|
||||
|
||||
tty = tty_open ();
|
||||
@@ -145,6 +131,7 @@ main (int argc, const char *argv[])
|
||||
{
|
||||
char s[LINEBUFSIZE];
|
||||
|
||||
connection_loop:
|
||||
u = 1;
|
||||
tty_wait_connection (tty);
|
||||
|
||||
@@ -157,39 +144,52 @@ main (int argc, const char *argv[])
|
||||
memcpy (s, "xx: Hello, World with Chopstx!\r\n", 32);
|
||||
s[0] = hexchar (count >> 4);
|
||||
s[1] = hexchar (count & 0x0f);
|
||||
count++;
|
||||
|
||||
puts("send hello");
|
||||
if (tty_send (tty, s, 32) < 0)
|
||||
continue;
|
||||
|
||||
s[0] = hexchar (count >> 4);
|
||||
s[1] = hexchar (count & 0x0f);
|
||||
s[2] = ':';
|
||||
s[3] = ' ';
|
||||
compose_hex_ptr (s+4, addr);
|
||||
s[20] = '\r';
|
||||
s[21] = '\n';
|
||||
|
||||
count++;
|
||||
|
||||
if (tty_send (tty, s, 22) < 0)
|
||||
continue;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int size;
|
||||
uint32_t usec;
|
||||
|
||||
puts("recv msg");
|
||||
usec = 3000000; /* 3.0 seconds */
|
||||
size = tty_recv (tty, s + 4, &usec);
|
||||
if (size < 0)
|
||||
/* Prompt */
|
||||
if (tty_send (tty, "> ", 2) < 0)
|
||||
break;
|
||||
|
||||
if (size)
|
||||
usec = 3000000; /* 3.0 seconds */
|
||||
while (1)
|
||||
{
|
||||
size--;
|
||||
int size = tty_recv (tty, s, &usec);
|
||||
u ^= 1;
|
||||
|
||||
puts("send msg");
|
||||
s[0] = hexchar (size >> 4);
|
||||
s[1] = hexchar (size & 0x0f);
|
||||
s[2] = ':';
|
||||
s[3] = ' ';
|
||||
s[size + 4] = '\r';
|
||||
s[size + 5] = '\n';
|
||||
if (tty_send (tty, s, size + 6) < 0)
|
||||
if (size < 0)
|
||||
goto connection_loop;
|
||||
|
||||
if (size == 1)
|
||||
/* Do nothing but prompt again. */
|
||||
break;
|
||||
else if (size)
|
||||
{
|
||||
/* Newline into NUL */
|
||||
s[size - 1] = 0;
|
||||
cmd_dispatch (tty, (char *)s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ usb_device_reset (struct usb_dev *dev)
|
||||
tty0.flag_connected = 0;
|
||||
tty0.flag_send_ready = 1;
|
||||
tty0.flag_input_avail = 0;
|
||||
tty0.device_state = ATTACHED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ATTACHED;
|
||||
memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -414,7 +414,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
vcom_setup_endpoints_for_interface (dev, i, 0);
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = CONFIGURED;
|
||||
tty0.device_state = USB_DEVICE_STATE_CONFIGURED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -427,7 +427,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
vcom_setup_endpoints_for_interface (dev, i, 1);
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = ADDRESSED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ADDRESSED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -629,8 +629,6 @@ usb_rx_ready (uint8_t ep_num, uint16_t len)
|
||||
|
||||
static void *tty_main (void *arg);
|
||||
|
||||
#include <signal.h>
|
||||
#define INTR_REQ_USB SIGUSR1
|
||||
#define PRIO_TTY 4
|
||||
|
||||
static char __process3_stack_base__[4096];
|
||||
@@ -647,7 +645,7 @@ tty_open (void)
|
||||
tty0.flag_connected = 0;
|
||||
tty0.flag_send_ready = 1;
|
||||
tty0.flag_input_avail = 0;
|
||||
tty0.device_state = UNCONNECTED;
|
||||
tty0.device_state = USB_DEVICE_STATE_UNCONNECTED;
|
||||
memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
|
||||
|
||||
chopstx_create (PRIO_TTY, STACK_ADDR_TTY, STACK_SIZE_TTY, tty_main, &tty0);
|
||||
@@ -734,7 +732,7 @@ tty_main (void *arg)
|
||||
* OK.
|
||||
*/
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = ADDRESSED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ADDRESSED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
continue;
|
||||
@@ -790,7 +788,7 @@ tty_main (void *arg)
|
||||
}
|
||||
|
||||
chopstx_mutex_lock (&t->mtx);
|
||||
if (t->device_state == CONFIGURED && t->flag_connected
|
||||
if (t->device_state == USB_DEVICE_STATE_CONFIGURED && t->flag_connected
|
||||
&& t->flag_send_ready)
|
||||
{
|
||||
uint8_t line[32];
|
||||
@@ -814,7 +812,7 @@ void
|
||||
tty_wait_configured (struct tty *t)
|
||||
{
|
||||
chopstx_mutex_lock (&t->mtx);
|
||||
while (t->device_state != CONFIGURED)
|
||||
while (t->device_state != USB_DEVICE_STATE_CONFIGURED)
|
||||
chopstx_cond_wait (&t->cnd, &t->mtx);
|
||||
chopstx_mutex_unlock (&t->mtx);
|
||||
}
|
||||
|
||||
@@ -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__[];
|
||||
|
||||
#define STACK_ADDR_PWM ((uint32_t)__process1_stack_base__)
|
||||
#define STACK_SIZE_PWM ((uint32_t)__process1_stack_size__)
|
||||
|
||||
#define STACK_ADDR_BLK ((uint32_t)__process2_stack_base__)
|
||||
#define STACK_SIZE_BLK ((uint32_t)__process2_stack_size__)
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#define STACK_PROCESS_2
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_PWM ((uint32_t)process1_base)
|
||||
#define STACK_SIZE_PWM (sizeof process1_base)
|
||||
#define STACK_ADDR_BLK ((uint32_t)process2_base)
|
||||
#define STACK_SIZE_BLK (sizeof process2_base)
|
||||
|
||||
|
||||
static char hexchar (uint8_t x)
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
/*
|
||||
* ST32F103 memory setup.
|
||||
*/
|
||||
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||
__process0_stack_size__ = 0x0400; /* Main program */
|
||||
__process1_stack_size__ = 0x0200; /* first thread program */
|
||||
__process2_stack_size__ = 0x0200; /* second thread program */
|
||||
__process3_stack_size__ = 0x0200; /* third thread program */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
@@ -78,34 +73,21 @@ SECTIONS
|
||||
_etext = .;
|
||||
_textdata = _etext;
|
||||
|
||||
.process_stack :
|
||||
.process_stack (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__process3_stack_base__ = .;
|
||||
. += __process3_stack_size__;
|
||||
*(.process_stack.3)
|
||||
*(.process_stack.2)
|
||||
*(.process_stack.1)
|
||||
*(.process_stack.0)
|
||||
. = ALIGN(8);
|
||||
__process3_stack_end__ = .;
|
||||
__process2_stack_base__ = .;
|
||||
. += __process2_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process2_stack_end__ = .;
|
||||
__process1_stack_base__ = .;
|
||||
. += __process1_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process1_stack_end__ = .;
|
||||
__process0_stack_base__ = .;
|
||||
. += __process0_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process0_stack_end__ = .;
|
||||
} > ram
|
||||
|
||||
.main_stack :
|
||||
.main_stack (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__main_stack_base__ = .;
|
||||
. += __main_stack_size__;
|
||||
*(.main_stack)
|
||||
. = ALIGN(8);
|
||||
__main_stack_end__ = .;
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
|
||||
24
example-cdc/stack-def.h
Normal file
24
example-cdc/stack-def.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#if defined(STACK_MAIN)
|
||||
/* Idle+Exception handlers */
|
||||
char __main_stack_end__[0] __attribute__ ((section(".main_stack")));
|
||||
char main_base[0x0100] __attribute__ ((section(".main_stack")));
|
||||
|
||||
/* Main program */
|
||||
char __process0_stack_end__[0] __attribute__ ((section(".process_stack.0")));
|
||||
char process0_base[0x0400] __attribute__ ((section(".process_stack.0")));
|
||||
#endif
|
||||
|
||||
/* First thread program */
|
||||
#if defined(STACK_PROCESS_1)
|
||||
char process1_base[0x0200] __attribute__ ((section(".process_stack.1")));
|
||||
#endif
|
||||
|
||||
/* Second thread program */
|
||||
#if defined(STACK_PROCESS_2)
|
||||
char process2_base[0x0200] __attribute__ ((section(".process_stack.2")));
|
||||
#endif
|
||||
|
||||
/* Third thread program */
|
||||
#if defined(STACK_PROCESS_3)
|
||||
char process3_base[0x0200] __attribute__ ((section(".process_stack.3")));
|
||||
#endif
|
||||
@@ -248,7 +248,7 @@ usb_device_reset (struct usb_dev *dev)
|
||||
tty0.flag_connected = 0;
|
||||
tty0.flag_send_ready = 1;
|
||||
tty0.flag_input_avail = 0;
|
||||
tty0.device_state = ATTACHED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ATTACHED;
|
||||
memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -417,7 +417,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
vcom_setup_endpoints_for_interface (i, 0);
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = CONFIGURED;
|
||||
tty0.device_state = USB_DEVICE_STATE_CONFIGURED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -430,7 +430,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
vcom_setup_endpoints_for_interface (i, 1);
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = ADDRESSED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ADDRESSED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -639,12 +639,12 @@ usb_rx_ready (uint8_t ep_num, uint16_t len)
|
||||
|
||||
static void *tty_main (void *arg);
|
||||
|
||||
#define INTR_REQ_USB 20
|
||||
#define PRIO_TTY 4
|
||||
|
||||
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__)
|
||||
#define STACK_PROCESS_3
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_TTY ((uint32_t)process3_base)
|
||||
#define STACK_SIZE_TTY (sizeof process3_base)
|
||||
|
||||
struct tty *
|
||||
tty_open (void)
|
||||
@@ -656,7 +656,7 @@ tty_open (void)
|
||||
tty0.flag_connected = 0;
|
||||
tty0.flag_send_ready = 1;
|
||||
tty0.flag_input_avail = 0;
|
||||
tty0.device_state = UNCONNECTED;
|
||||
tty0.device_state = USB_DEVICE_STATE_UNCONNECTED;
|
||||
memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
|
||||
|
||||
chopstx_create (PRIO_TTY, STACK_ADDR_TTY, STACK_SIZE_TTY, tty_main, &tty0);
|
||||
@@ -743,7 +743,7 @@ tty_main (void *arg)
|
||||
* OK.
|
||||
*/
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = ADDRESSED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ADDRESSED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
continue;
|
||||
@@ -799,7 +799,7 @@ tty_main (void *arg)
|
||||
}
|
||||
|
||||
chopstx_mutex_lock (&t->mtx);
|
||||
if (t->device_state == CONFIGURED && t->flag_connected
|
||||
if (t->device_state == USB_DEVICE_STATE_CONFIGURED && t->flag_connected
|
||||
&& t->flag_send_ready)
|
||||
{
|
||||
uint8_t line[32];
|
||||
@@ -823,7 +823,7 @@ void
|
||||
tty_wait_configured (struct tty *t)
|
||||
{
|
||||
chopstx_mutex_lock (&t->mtx);
|
||||
while (t->device_state != CONFIGURED)
|
||||
while (t->device_state != USB_DEVICE_STATE_CONFIGURED)
|
||||
chopstx_cond_wait (&t->cnd, &t->mtx);
|
||||
chopstx_mutex_unlock (&t->mtx);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ LDSCRIPT=
|
||||
|
||||
CSRC = main.c
|
||||
CHIP=gnu-linux
|
||||
USE_SYS =
|
||||
USE_SYS = yes
|
||||
USE_USB = yes
|
||||
EMULATION=yes
|
||||
# USE_ADC = yes
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
|
||||
static chopstx_mutex_t usb_mtx;
|
||||
static chopstx_cond_t usb_cnd;
|
||||
static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
|
||||
static uint32_t bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
|
||||
extern void EP6_IN_Callback (uint16_t len);
|
||||
extern void EP6_OUT_Callback (uint16_t len);
|
||||
|
||||
#define MSC_MASS_STORAGE_RESET_COMMAND 0xFF
|
||||
extern int fraucheky_enabled (void);
|
||||
extern void fraucheky_init (void);
|
||||
extern void fraucheky_main (void);
|
||||
|
||||
extern void fraucheky_setup_endpoints_for_interface (struct usb_dev *dev, int stop);
|
||||
@@ -41,13 +42,9 @@ usb_device_reset (struct usb_dev *dev)
|
||||
/* Initialize Endpoint 0. */
|
||||
usb_lld_setup_endp (dev, ENDP0, 1, 1);
|
||||
|
||||
/* Stop the interface */
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
setup_endpoints_for_interface (dev, i, 1);
|
||||
|
||||
/* Notify upper layer. */
|
||||
chopstx_mutex_lock (&usb_mtx);
|
||||
bDeviceState = ATTACHED;
|
||||
bDeviceState = USB_DEVICE_STATE_ATTACHED;
|
||||
chopstx_cond_signal (&usb_cnd);
|
||||
chopstx_mutex_unlock (&usb_mtx);
|
||||
}
|
||||
@@ -95,7 +92,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
setup_endpoints_for_interface (dev, i, 0);
|
||||
chopstx_mutex_lock (&usb_mtx);
|
||||
bDeviceState = CONFIGURED;
|
||||
bDeviceState = USB_DEVICE_STATE_CONFIGURED;
|
||||
chopstx_mutex_unlock (&usb_mtx);
|
||||
}
|
||||
else if (current_conf != dev->dev_req.value)
|
||||
@@ -107,7 +104,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
setup_endpoints_for_interface (dev, i, 1);
|
||||
chopstx_mutex_lock (&usb_mtx);
|
||||
bDeviceState = ADDRESSED;
|
||||
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
|
||||
chopstx_cond_signal (&usb_cnd);
|
||||
chopstx_mutex_unlock (&usb_mtx);
|
||||
}
|
||||
@@ -164,7 +161,6 @@ static void usb_tx_done (uint8_t ep_num, uint16_t len);
|
||||
static void usb_rx_ready (uint8_t ep_num, uint16_t len);
|
||||
|
||||
|
||||
#define INTR_REQ_USB SIGUSR1
|
||||
#define PRIO_USB 3
|
||||
|
||||
static void *
|
||||
@@ -207,7 +203,7 @@ usb_main (void *arg)
|
||||
|
||||
case USB_EVENT_DEVICE_ADDRESSED:
|
||||
chopstx_mutex_lock (&usb_mtx);
|
||||
bDeviceState = ADDRESSED;
|
||||
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
|
||||
chopstx_cond_signal (&usb_cnd);
|
||||
chopstx_mutex_unlock (&usb_mtx);
|
||||
continue;
|
||||
@@ -305,16 +301,17 @@ main (int argc, char **argv)
|
||||
chopstx_mutex_init (&usb_mtx);
|
||||
chopstx_cond_init (&usb_cnd);
|
||||
|
||||
bDeviceState = UNCONNECTED;
|
||||
bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
usb_thd = chopstx_create (PRIO_USB, STACK_ADDR_USB, STACK_SIZE_USB,
|
||||
usb_main, NULL);
|
||||
while (bDeviceState != CONFIGURED)
|
||||
fraucheky_init ();
|
||||
while (bDeviceState != USB_DEVICE_STATE_CONFIGURED)
|
||||
chopstx_usec_wait (250*1000);
|
||||
fraucheky_main ();
|
||||
chopstx_cancel (usb_thd);
|
||||
chopstx_join (usb_thd, NULL);
|
||||
usb_lld_shutdown ();
|
||||
bDeviceState = UNCONNECTED;
|
||||
bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ usb_device_reset (struct usb_dev *dev)
|
||||
tty0.flag_connected = 0;
|
||||
tty0.flag_send_ready = 1;
|
||||
tty0.flag_input_avail = 0;
|
||||
tty0.device_state = ATTACHED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ATTACHED;
|
||||
memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -409,7 +409,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
vcom_setup_endpoints_for_interface (dev, i, 0);
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = CONFIGURED;
|
||||
tty0.device_state = USB_DEVICE_STATE_CONFIGURED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -422,7 +422,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
vcom_setup_endpoints_for_interface (dev, i, 1);
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = ADDRESSED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ADDRESSED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
}
|
||||
@@ -626,7 +626,6 @@ usb_rx_ready (uint8_t ep_num, uint16_t len)
|
||||
|
||||
static void *tty_main (void *arg);
|
||||
|
||||
#define INTR_REQ_USB 24
|
||||
#define PRIO_TTY 4
|
||||
|
||||
extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
|
||||
@@ -643,7 +642,7 @@ tty_open (void)
|
||||
tty0.flag_connected = 0;
|
||||
tty0.flag_send_ready = 1;
|
||||
tty0.flag_input_avail = 0;
|
||||
tty0.device_state = UNCONNECTED;
|
||||
tty0.device_state = USB_DEVICE_STATE_UNCONNECTED;
|
||||
memcpy (&tty0.line_coding, &line_coding0, sizeof (struct line_coding));
|
||||
|
||||
chopstx_create (PRIO_TTY, STACK_ADDR_TTY, STACK_SIZE_TTY, tty_main, &tty0);
|
||||
@@ -733,7 +732,7 @@ tty_main (void *arg)
|
||||
* OK.
|
||||
*/
|
||||
chopstx_mutex_lock (&tty0.mtx);
|
||||
tty0.device_state = ADDRESSED;
|
||||
tty0.device_state = USB_DEVICE_STATE_ADDRESSED;
|
||||
chopstx_cond_signal (&tty0.cnd);
|
||||
chopstx_mutex_unlock (&tty0.mtx);
|
||||
continue;
|
||||
@@ -789,7 +788,7 @@ tty_main (void *arg)
|
||||
}
|
||||
|
||||
chopstx_mutex_lock (&t->mtx);
|
||||
if (t->device_state == CONFIGURED && t->flag_connected
|
||||
if (t->device_state == USB_DEVICE_STATE_CONFIGURED && t->flag_connected
|
||||
&& t->flag_send_ready)
|
||||
{
|
||||
uint8_t line[32];
|
||||
@@ -813,7 +812,7 @@ void
|
||||
tty_wait_configured (struct tty *t)
|
||||
{
|
||||
chopstx_mutex_lock (&t->mtx);
|
||||
while (t->device_state != CONFIGURED)
|
||||
while (t->device_state != USB_DEVICE_STATE_CONFIGURED)
|
||||
chopstx_cond_wait (&t->cnd, &t->mtx);
|
||||
chopstx_mutex_unlock (&t->mtx);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ LDSCRIPT= hacker-emblem.ld
|
||||
|
||||
CSRC = reset.c hh.c
|
||||
|
||||
CHIP=stm32f0
|
||||
|
||||
# Hacker Emblem and "Happy Hacking!" demonstration
|
||||
# CSRC = reset.c hh.c
|
||||
|
||||
@@ -25,7 +27,7 @@ OBJCOPY = $(CROSS)objcopy
|
||||
MCU = cortex-m0 # -save-temps
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
DEFS = -DMAKE_ENTRY_PUBLIC \
|
||||
-DFREE_STANDING -DMHZ=48 -DUSE_WFI_FOR_IDLE
|
||||
-DFREE_STANDING -DMHZ=48
|
||||
OPT = -O3 -Os -g
|
||||
LIBS =
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
static uint8_t main_finished;
|
||||
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APBPERIPH_BASE PERIPH_BASE
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000)
|
||||
@@ -163,17 +163,19 @@ button (void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#define STACK_PROCESS_2
|
||||
#include "stack-def.h"
|
||||
|
||||
#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__[];
|
||||
#define STACK_ADDR_LED ((uint32_t)process1_base)
|
||||
#define STACK_SIZE_LED (sizeof process1_base)
|
||||
|
||||
#define STACK_ADDR_LED ((uint32_t)__process1_stack_base__)
|
||||
#define STACK_SIZE_LED ((uint32_t)__process1_stack_size__)
|
||||
|
||||
#define STACK_ADDR_BUTTON ((uint32_t)__process2_stack_base__)
|
||||
#define STACK_SIZE_BUTTON ((uint32_t)__process2_stack_size__)
|
||||
#define STACK_ADDR_BUTTON ((uint32_t)process2_base)
|
||||
#define STACK_SIZE_BUTTON (sizeof process2_base)
|
||||
|
||||
#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))
|
||||
@@ -365,8 +367,6 @@ text_display (uint8_t kind)
|
||||
}
|
||||
|
||||
|
||||
static void setup_scr_sleepdeep (void);
|
||||
|
||||
int
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
@@ -378,6 +378,8 @@ main (int argc, const char *argv[])
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
chopstx_conf_idle (1);
|
||||
|
||||
chopstx_mutex_init (&mtx);
|
||||
chopstx_cond_init (&cnd0);
|
||||
chopstx_cond_init (&cnd1);
|
||||
@@ -418,56 +420,6 @@ main (int argc, const char *argv[])
|
||||
chopstx_join (button_thd, NULL);
|
||||
chopstx_join (led_thd, NULL);
|
||||
|
||||
setup_scr_sleepdeep ();
|
||||
for (;;)
|
||||
asm volatile ("wfi" : : : "memory");
|
||||
|
||||
chopstx_conf_idle (4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct SCB
|
||||
{
|
||||
volatile uint32_t CPUID;
|
||||
volatile uint32_t ICSR;
|
||||
volatile uint32_t VTOR;
|
||||
volatile uint32_t AIRCR;
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t CCR;
|
||||
volatile uint8_t SHP[12];
|
||||
volatile uint32_t SHCSR;
|
||||
volatile uint32_t CFSR;
|
||||
volatile uint32_t HFSR;
|
||||
volatile uint32_t DFSR;
|
||||
volatile uint32_t MMFAR;
|
||||
volatile uint32_t BFAR;
|
||||
volatile uint32_t AFSR;
|
||||
volatile uint32_t PFR[2];
|
||||
volatile uint32_t DFR;
|
||||
volatile uint32_t ADR;
|
||||
volatile uint32_t MMFR[4];
|
||||
volatile uint32_t ISAR[5];
|
||||
};
|
||||
|
||||
#define SCS_BASE (0xE000E000)
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00)
|
||||
static struct SCB *const SCB = ((struct SCB *)SCB_BASE);
|
||||
|
||||
#define SCB_SCR_SLEEPDEEP (1 << 2)
|
||||
|
||||
struct PWR
|
||||
{
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CSR;
|
||||
};
|
||||
#define PWR_CR_PDDS 0x0002
|
||||
#define PWR_CR_CWUF 0x0004
|
||||
|
||||
#define PWR_BASE (APBPERIPH_BASE + 0x00007000)
|
||||
#define PWR ((struct PWR *) PWR_BASE)
|
||||
|
||||
static void setup_scr_sleepdeep (void)
|
||||
{
|
||||
PWR->CR |= PWR_CR_CWUF;
|
||||
PWR->CR |= PWR_CR_PDDS;
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
/*
|
||||
* ST32F0 memory setup.
|
||||
*/
|
||||
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||
__process0_stack_size__ = 0x0100; /* Main program */
|
||||
__process1_stack_size__ = 0x0100; /* first thread program */
|
||||
__process2_stack_size__ = 0x0100; /* second thread program */
|
||||
__process3_stack_size__ = 0x0100; /* third thread program */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash : org = 0x08000000, len = 16k
|
||||
@@ -61,34 +55,15 @@ SECTIONS
|
||||
_etext = .;
|
||||
_textdata = _etext;
|
||||
|
||||
.process_stack :
|
||||
.stacks (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__process3_stack_base__ = .;
|
||||
. += __process3_stack_size__;
|
||||
*(.main_stack)
|
||||
*(.process_stack.0)
|
||||
*(.process_stack.1)
|
||||
*(.process_stack.2)
|
||||
*(.process_stack.3)
|
||||
. = ALIGN(8);
|
||||
__process3_stack_end__ = .;
|
||||
__process2_stack_base__ = .;
|
||||
. += __process2_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process2_stack_end__ = .;
|
||||
__process1_stack_base__ = .;
|
||||
. += __process1_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process1_stack_end__ = .;
|
||||
__process0_stack_base__ = .;
|
||||
. += __process0_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process0_stack_end__ = .;
|
||||
} > ram
|
||||
|
||||
.main_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__main_stack_base__ = .;
|
||||
. += __main_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__main_stack_end__ = .;
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
static uint8_t main_finished;
|
||||
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APBPERIPH_BASE PERIPH_BASE
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000)
|
||||
@@ -166,14 +166,16 @@ 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__[];
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#define STACK_PROCESS_2
|
||||
#include "stack-def.h"
|
||||
|
||||
#define STACK_ADDR_LED ((uint32_t)__process1_stack_base__)
|
||||
#define STACK_SIZE_LED ((uint32_t)__process1_stack_size__)
|
||||
#define STACK_ADDR_LED ((uint32_t)process1_base)
|
||||
#define STACK_SIZE_LED (sizeof process1_base)
|
||||
|
||||
#define STACK_ADDR_BUTTON ((uint32_t)__process2_stack_base__)
|
||||
#define STACK_SIZE_BUTTON ((uint32_t)__process2_stack_size__)
|
||||
#define STACK_ADDR_BUTTON ((uint32_t)process2_base)
|
||||
#define STACK_SIZE_BUTTON (sizeof process2_base)
|
||||
|
||||
#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))
|
||||
@@ -355,8 +357,6 @@ text_display (uint8_t kind)
|
||||
}
|
||||
|
||||
|
||||
static void setup_scr_sleepdeep (void);
|
||||
|
||||
int
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
@@ -366,6 +366,8 @@ main (int argc, const char *argv[])
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
chopstx_conf_idle (1);
|
||||
|
||||
chopstx_mutex_init (&mtx);
|
||||
chopstx_cond_init (&cnd0);
|
||||
chopstx_cond_init (&cnd1);
|
||||
@@ -406,56 +408,6 @@ main (int argc, const char *argv[])
|
||||
chopstx_join (button_thd, NULL);
|
||||
chopstx_join (led_thd, NULL);
|
||||
|
||||
setup_scr_sleepdeep ();
|
||||
for (;;)
|
||||
asm volatile ("wfi" : : : "memory");
|
||||
|
||||
chopstx_conf_idle (4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct SCB
|
||||
{
|
||||
volatile uint32_t CPUID;
|
||||
volatile uint32_t ICSR;
|
||||
volatile uint32_t VTOR;
|
||||
volatile uint32_t AIRCR;
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t CCR;
|
||||
volatile uint8_t SHP[12];
|
||||
volatile uint32_t SHCSR;
|
||||
volatile uint32_t CFSR;
|
||||
volatile uint32_t HFSR;
|
||||
volatile uint32_t DFSR;
|
||||
volatile uint32_t MMFAR;
|
||||
volatile uint32_t BFAR;
|
||||
volatile uint32_t AFSR;
|
||||
volatile uint32_t PFR[2];
|
||||
volatile uint32_t DFR;
|
||||
volatile uint32_t ADR;
|
||||
volatile uint32_t MMFR[4];
|
||||
volatile uint32_t ISAR[5];
|
||||
};
|
||||
|
||||
#define SCS_BASE (0xE000E000)
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00)
|
||||
static struct SCB *const SCB = ((struct SCB *)SCB_BASE);
|
||||
|
||||
#define SCB_SCR_SLEEPDEEP (1 << 2)
|
||||
|
||||
struct PWR
|
||||
{
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CSR;
|
||||
};
|
||||
#define PWR_CR_PDDS 0x0002
|
||||
#define PWR_CR_CWUF 0x0004
|
||||
|
||||
#define PWR_BASE (APBPERIPH_BASE + 0x00007000)
|
||||
#define PWR ((struct PWR *) PWR_BASE)
|
||||
|
||||
static void setup_scr_sleepdeep (void)
|
||||
{
|
||||
PWR->CR |= PWR_CR_CWUF;
|
||||
PWR->CR |= PWR_CR_PDDS;
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "board.h"
|
||||
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APBPERIPH_BASE PERIPH_BASE
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000)
|
||||
@@ -86,12 +86,16 @@ led_enable_column (uint8_t col)
|
||||
}
|
||||
|
||||
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#define STACK_PROCESS_2
|
||||
#define STACK_PROCESS_3
|
||||
#include "stack-def.h"
|
||||
|
||||
#define PRIO_LED 3
|
||||
|
||||
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
|
||||
|
||||
#define STACK_ADDR_LED ((uint32_t)__process1_stack_base__)
|
||||
#define STACK_SIZE_LED ((uint32_t)__process1_stack_size__)
|
||||
#define STACK_ADDR_LED ((uint32_t)process1_base)
|
||||
#define STACK_SIZE_LED (sizeof process1_base)
|
||||
|
||||
static void *
|
||||
led (void *arg)
|
||||
@@ -119,10 +123,9 @@ led (void *arg)
|
||||
|
||||
|
||||
#define PRIO_SPK 4
|
||||
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
|
||||
|
||||
#define STACK_ADDR_SPK ((uint32_t)__process2_stack_base__)
|
||||
#define STACK_SIZE_SPK ((uint32_t)__process2_stack_size__)
|
||||
#define STACK_ADDR_SPK ((uint32_t)process2_base)
|
||||
#define STACK_SIZE_SPK (sizeof process2_base)
|
||||
|
||||
static chopstx_mutex_t spk_mtx;
|
||||
static chopstx_cond_t spk_cnd;
|
||||
@@ -193,10 +196,9 @@ spk (void *arg)
|
||||
|
||||
|
||||
#define PRIO_MUSIC 2
|
||||
extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
|
||||
|
||||
#define STACK_ADDR_MUSIC ((uint32_t)__process3_stack_base__)
|
||||
#define STACK_SIZE_MUSIC ((uint32_t)__process3_stack_size__)
|
||||
#define STACK_ADDR_MUSIC ((uint32_t)process3_base)
|
||||
#define STACK_SIZE_MUSIC (sizeof process3_base)
|
||||
|
||||
#define C 0
|
||||
#define D 1
|
||||
|
||||
54
example-fsm-55/stack-def.h
Normal file
54
example-fsm-55/stack-def.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#define MAIN_SIZE 0x0080 /* Idle+Exception handlers */
|
||||
#define SIZE_0 0x0100 /* Main program */
|
||||
#define SIZE_1 0x0100 /* first thread program */
|
||||
#define SIZE_2 0x0100 /* second thread program */
|
||||
#define SIZE_3 0x0100 /* third thread program */
|
||||
|
||||
#if defined(STACK_MAIN)
|
||||
/*
|
||||
* The terminology of "main" is confusing in ARM architecture.
|
||||
* Here, "main_base" is for exception handlers.
|
||||
*/
|
||||
/* Idle+Exception handlers */
|
||||
char __main_stack_end__[0] __attribute__ ((section(".main_stack")));
|
||||
char main_base[MAIN_SIZE] __attribute__ ((section(".main_stack")));
|
||||
|
||||
/* Main program */
|
||||
char __process0_stack_end__[0] __attribute__ ((section(".process_stack.0")));
|
||||
char process0_base[SIZE_0] __attribute__ ((section(".process_stack.0")));
|
||||
#endif
|
||||
|
||||
/* First thread program */
|
||||
#if defined(STACK_PROCESS_1)
|
||||
char process1_base[SIZE_1] __attribute__ ((section(".process_stack.1")));
|
||||
#endif
|
||||
|
||||
/* Second thread program */
|
||||
#if defined(STACK_PROCESS_2)
|
||||
char process2_base[SIZE_2] __attribute__ ((section(".process_stack.2")));
|
||||
#endif
|
||||
|
||||
/* Third thread program */
|
||||
#if defined(STACK_PROCESS_3)
|
||||
char process3_base[SIZE_3] __attribute__ ((section(".process_stack.3")));
|
||||
#endif
|
||||
|
||||
/* Fourth thread program */
|
||||
#if defined(STACK_PROCESS_4)
|
||||
char process4_base[SIZE_4] __attribute__ ((section(".process_stack.4")));
|
||||
#endif
|
||||
|
||||
/* Fifth thread program */
|
||||
#if defined(STACK_PROCESS_5)
|
||||
char process5_base[SIZE_5] __attribute__ ((section(".process_stack.5")));
|
||||
#endif
|
||||
|
||||
/* Sixth thread program */
|
||||
#if defined(STACK_PROCESS_6)
|
||||
char process6_base[SIZE_6] __attribute__ ((section(".process_stack.6")));
|
||||
#endif
|
||||
|
||||
/* Seventh thread program */
|
||||
#if defined(STACK_PROCESS_7)
|
||||
char process7_base[SIZE_7] __attribute__ ((section(".process_stack.7")));
|
||||
#endif
|
||||
@@ -72,14 +72,17 @@ 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__[];
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#define STACK_PROCESS_2
|
||||
#include "stack-def.h"
|
||||
|
||||
#define STACK_ADDR_PWM ((uint32_t)__process1_stack_base__)
|
||||
#define STACK_SIZE_PWM ((uint32_t)__process1_stack_size__)
|
||||
|
||||
#define STACK_ADDR_BLK ((uint32_t)__process2_stack_base__)
|
||||
#define STACK_SIZE_BLK ((uint32_t)__process2_stack_size__)
|
||||
#define STACK_ADDR_PWM ((uint32_t)process1_base)
|
||||
#define STACK_SIZE_PWM (sizeof process1_base)
|
||||
|
||||
#define STACK_ADDR_BLK ((uint32_t)process2_base)
|
||||
#define STACK_SIZE_BLK (sizeof process2_base)
|
||||
|
||||
|
||||
int
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
/*
|
||||
* ST32F0 memory setup.
|
||||
*/
|
||||
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||
__process0_stack_size__ = 0x0100; /* Main program */
|
||||
__process1_stack_size__ = 0x0100; /* first thread program */
|
||||
__process2_stack_size__ = 0x0100; /* second thread program */
|
||||
__process3_stack_size__ = 0x0100; /* third thread program */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = 0x08000000, len = 4k
|
||||
@@ -87,34 +81,15 @@ SECTIONS
|
||||
KEEP(*(.bss.startup.*))
|
||||
} > ram
|
||||
|
||||
.process_stack :
|
||||
.stacks (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__process3_stack_base__ = .;
|
||||
. += __process3_stack_size__;
|
||||
*(.main_stack)
|
||||
*(.process_stack.0)
|
||||
*(.process_stack.1)
|
||||
*(.process_stack.2)
|
||||
*(.process_stack.3)
|
||||
. = ALIGN(8);
|
||||
__process3_stack_end__ = .;
|
||||
__process2_stack_base__ = .;
|
||||
. += __process2_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process2_stack_end__ = .;
|
||||
__process1_stack_base__ = .;
|
||||
. += __process1_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process1_stack_end__ = .;
|
||||
__process0_stack_base__ = .;
|
||||
. += __process0_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process0_stack_end__ = .;
|
||||
} > ram
|
||||
|
||||
.main_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__main_stack_base__ = .;
|
||||
. += __main_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__main_stack_end__ = .;
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
/*
|
||||
* ST32F103 memory setup.
|
||||
*/
|
||||
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||
__process0_stack_size__ = 0x0100; /* Main program */
|
||||
__process1_stack_size__ = 0x0100; /* first thread program */
|
||||
__process2_stack_size__ = 0x0100; /* second thread program */
|
||||
__process3_stack_size__ = 0x0100; /* third thread program */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = 0x08000000, len = 4k
|
||||
@@ -78,34 +72,14 @@ SECTIONS
|
||||
_etext = .;
|
||||
_textdata = _etext;
|
||||
|
||||
.process_stack :
|
||||
.stacks (NOLOAD) :
|
||||
{
|
||||
*(.main_stack)
|
||||
*(.process_stack.0)
|
||||
*(.process_stack.1)
|
||||
*(.process_stack.2)
|
||||
*(.process_stack.3)
|
||||
. = ALIGN(8);
|
||||
__process3_stack_base__ = .;
|
||||
. += __process3_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process3_stack_end__ = .;
|
||||
__process2_stack_base__ = .;
|
||||
. += __process2_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process2_stack_end__ = .;
|
||||
__process1_stack_base__ = .;
|
||||
. += __process1_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process1_stack_end__ = .;
|
||||
__process0_stack_base__ = .;
|
||||
. += __process0_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process0_stack_end__ = .;
|
||||
} > ram
|
||||
|
||||
.main_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__main_stack_base__ = .;
|
||||
. += __main_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__main_stack_end__ = .;
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
|
||||
53
example-led/stack-def.h
Normal file
53
example-led/stack-def.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#define MAIN_SIZE 0x0080 /* Idle+Exception handlers */
|
||||
#define SIZE_0 0x0100 /* Main program */
|
||||
#define SIZE_1 0x0100 /* first thread program */
|
||||
#define SIZE_2 0x0100 /* second thread program */
|
||||
|
||||
#if defined(STACK_MAIN)
|
||||
/*
|
||||
* The terminology of "main" is confusing in ARM architecture.
|
||||
* Here, "main_base" is for exception handlers.
|
||||
*/
|
||||
/* Idle+Exception handlers */
|
||||
char __main_stack_end__[0] __attribute__ ((section(".main_stack")));
|
||||
char main_base[MAIN_SIZE] __attribute__ ((section(".main_stack")));
|
||||
|
||||
/* Main program */
|
||||
char __process0_stack_end__[0] __attribute__ ((section(".process_stack.0")));
|
||||
char process0_base[SIZE_0] __attribute__ ((section(".process_stack.0")));
|
||||
#endif
|
||||
|
||||
/* First thread program */
|
||||
#if defined(STACK_PROCESS_1)
|
||||
char process1_base[SIZE_1] __attribute__ ((section(".process_stack.1")));
|
||||
#endif
|
||||
|
||||
/* Second thread program */
|
||||
#if defined(STACK_PROCESS_2)
|
||||
char process2_base[SIZE_2] __attribute__ ((section(".process_stack.2")));
|
||||
#endif
|
||||
|
||||
/* Third thread program */
|
||||
#if defined(STACK_PROCESS_3)
|
||||
char process3_base[SIZE_3] __attribute__ ((section(".process_stack.3")));
|
||||
#endif
|
||||
|
||||
/* Fourth thread program */
|
||||
#if defined(STACK_PROCESS_4)
|
||||
char process4_base[SIZE_4] __attribute__ ((section(".process_stack.4")));
|
||||
#endif
|
||||
|
||||
/* Fifth thread program */
|
||||
#if defined(STACK_PROCESS_5)
|
||||
char process5_base[SIZE_5] __attribute__ ((section(".process_stack.5")));
|
||||
#endif
|
||||
|
||||
/* Sixth thread program */
|
||||
#if defined(STACK_PROCESS_6)
|
||||
char process6_base[SIZE_6] __attribute__ ((section(".process_stack.6")));
|
||||
#endif
|
||||
|
||||
/* Seventh thread program */
|
||||
#if defined(STACK_PROCESS_7)
|
||||
char process7_base[SIZE_7] __attribute__ ((section(".process_stack.7")));
|
||||
#endif
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "board.h"
|
||||
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APBPERIPH_BASE PERIPH_BASE
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
|
||||
struct GPIO {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "board.h"
|
||||
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APBPERIPH_BASE PERIPH_BASE
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
|
||||
struct GPIO {
|
||||
|
||||
37
example-usb-serial/Makefile
Normal file
37
example-usb-serial/Makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
# Makefile for example application of Chopstx
|
||||
|
||||
PROJECT = sample
|
||||
|
||||
CHOPSTX = ..
|
||||
LDSCRIPT= sample.ld
|
||||
CSRC = sample.c usb-cdc.c
|
||||
|
||||
CHIP=stm32f103
|
||||
|
||||
USE_SYS = yes
|
||||
USE_USB = yes
|
||||
USE_USART = yes
|
||||
|
||||
###################################
|
||||
CROSS = arm-none-eabi-
|
||||
CC = $(CROSS)gcc
|
||||
LD = $(CROSS)gcc
|
||||
OBJCOPY = $(CROSS)objcopy
|
||||
|
||||
MCU = cortex-m3
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
DEFS = -DUSE_SYS3 -DFREE_STANDING
|
||||
OPT = -O3 -Os -g
|
||||
LIBS =
|
||||
|
||||
####################
|
||||
include ../rules.mk
|
||||
|
||||
board.h:
|
||||
@echo Please make a symbolic link \'board.h\' to a file in ../board;
|
||||
@exit 1
|
||||
|
||||
sys.c: board.h
|
||||
|
||||
distclean: clean
|
||||
rm -f board.h
|
||||
22
example-usb-serial/README
Normal file
22
example-usb-serial/README
Normal file
@@ -0,0 +1,22 @@
|
||||
This is an application example using ST Nucleo F103 board.
|
||||
|
||||
SB62 and SB63 should be soldered.
|
||||
ST-Link/V2 is disconnected (SB13 and SB14).
|
||||
|
||||
NOTE:
|
||||
|
||||
Using the USB CDC-ACM for serial communication is a kind of wrong,
|
||||
because it's designed for modem; No way to control CTSRTS.
|
||||
|
||||
TIOCGICOUNT
|
||||
|
||||
|
||||
TODO:
|
||||
* Use of DMA for serial communication
|
||||
* RS-232 support: GPIO with DTR (out), DCD (in), DSR (in), RI (in)
|
||||
* serial config setting of CTSRTS?
|
||||
By vendor specific control?
|
||||
* stats report control
|
||||
By vendor specific control?
|
||||
* Half-duplex support
|
||||
* Support of other communication mode: smartcard, IrDA, etc.
|
||||
1
example-usb-serial/board.h
Symbolic link
1
example-usb-serial/board.h
Symbolic link
@@ -0,0 +1 @@
|
||||
../board/board-st-nucleo-f103.h
|
||||
17
example-usb-serial/cdc.h
Normal file
17
example-usb-serial/cdc.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#define BUFSIZE 64
|
||||
|
||||
struct cdc;
|
||||
|
||||
void
|
||||
cdc_init (uint16_t prio, uintptr_t stack_addr, size_t stack_size,
|
||||
void (*sendbrk_callback) (uint8_t dev_no, uint16_t duration),
|
||||
void (*config_callback) (uint8_t dev_no,
|
||||
uint32_t bitrate, uint8_t format,
|
||||
uint8_t paritytype, uint8_t databits));
|
||||
void cdc_wait_configured (void);
|
||||
|
||||
struct cdc *cdc_open (uint8_t num);
|
||||
void cdc_wait_connection (struct cdc *);
|
||||
int cdc_send (struct cdc *s, const char *buf, int count);
|
||||
int cdc_recv (struct cdc *s, char *buf, uint32_t *timeout);
|
||||
int cdc_ss_notify (struct cdc *s, uint16_t state_bits);
|
||||
257
example-usb-serial/sample.c
Normal file
257
example-usb-serial/sample.c
Normal file
@@ -0,0 +1,257 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <chopstx.h>
|
||||
#include <contrib/usart.h>
|
||||
|
||||
#include <usb_lld.h>
|
||||
#include "cdc.h"
|
||||
|
||||
/* For set_led */
|
||||
#include "board.h"
|
||||
#include "sys.h"
|
||||
|
||||
static void *
|
||||
blk (void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
while (1)
|
||||
{
|
||||
set_led (0);
|
||||
chopstx_usec_wait (200*1000);
|
||||
set_led (1);
|
||||
chopstx_usec_wait (200*1000);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define PRIO_USART 4
|
||||
#define PRIO_CDC2USART 3
|
||||
#define PRIO_USART2CDC 3
|
||||
#define PRIO_CDC 2
|
||||
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#define STACK_PROCESS_2
|
||||
#define STACK_PROCESS_3
|
||||
#define STACK_PROCESS_4
|
||||
#define STACK_PROCESS_5
|
||||
#define STACK_PROCESS_6
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_CDC ((uintptr_t)process1_base)
|
||||
#define STACK_SIZE_CDC (sizeof process1_base)
|
||||
|
||||
#define STACK_ADDR_USART ((uint32_t)process2_base)
|
||||
#define STACK_SIZE_USART (sizeof process2_base)
|
||||
|
||||
#define STACK_ADDR_CDC2USART0 ((uint32_t)process3_base)
|
||||
#define STACK_SIZE_CDC2USART0 (sizeof process3_base)
|
||||
|
||||
#define STACK_ADDR_USART2CDC0 ((uint32_t)process4_base)
|
||||
#define STACK_SIZE_USART2CDC0 (sizeof process4_base)
|
||||
|
||||
#define STACK_ADDR_CDC2USART1 ((uint32_t)process5_base)
|
||||
#define STACK_SIZE_CDC2USART1 (sizeof process5_base)
|
||||
|
||||
#define STACK_ADDR_USART2CDC1 ((uint32_t)process6_base)
|
||||
#define STACK_SIZE_USART2CDC1 (sizeof process6_base)
|
||||
|
||||
|
||||
struct cdc_usart {
|
||||
uint8_t dev_no;
|
||||
struct cdc *cdc;
|
||||
};
|
||||
|
||||
static void *
|
||||
usart_to_cdc_loop (void *arg)
|
||||
{
|
||||
struct cdc_usart *cdc_usart = arg;
|
||||
|
||||
while (1)
|
||||
{
|
||||
char s[BUFSIZE];
|
||||
|
||||
cdc_wait_connection (cdc_usart->cdc);
|
||||
|
||||
/* Flush USART buffers */
|
||||
usart_read (cdc_usart->dev_no, NULL, 0);
|
||||
usart_write (cdc_usart->dev_no, NULL, 0);
|
||||
|
||||
chopstx_usec_wait (100*1000);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int size = usart_read (cdc_usart->dev_no, s, BUFSIZE);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
if (cdc_send (cdc_usart->cdc, s, size) < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
cdc_to_usart_loop (void *arg)
|
||||
{
|
||||
struct cdc_usart *cdc_usart = arg;
|
||||
|
||||
while (1)
|
||||
{
|
||||
char s[BUFSIZE];
|
||||
|
||||
cdc_wait_connection (cdc_usart->cdc);
|
||||
|
||||
/* Flush USART buffers */
|
||||
usart_read (cdc_usart->dev_no, NULL, 0);
|
||||
usart_write (cdc_usart->dev_no, NULL, 0);
|
||||
|
||||
chopstx_usec_wait (50*1000);
|
||||
|
||||
/* Send ZLP at the beginning. */
|
||||
cdc_send (cdc_usart->cdc, s, 0);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int size;
|
||||
uint32_t usec = 3000000; /* 3.0 seconds */
|
||||
|
||||
size = cdc_recv (cdc_usart->cdc, s, &usec);
|
||||
if (size < 0)
|
||||
break;
|
||||
|
||||
if (size)
|
||||
usart_write (cdc_usart->dev_no, s, size);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct cdc_usart cdc_usart0;
|
||||
static struct cdc_usart cdc_usart1;
|
||||
|
||||
static int
|
||||
ss_notify (uint8_t dev_no, uint16_t state_bits)
|
||||
{
|
||||
struct cdc *s;
|
||||
|
||||
if (dev_no == cdc_usart0.dev_no)
|
||||
s = cdc_usart0.cdc;
|
||||
else if (dev_no == cdc_usart1.dev_no)
|
||||
s = cdc_usart1.cdc;
|
||||
else
|
||||
return -1;
|
||||
|
||||
return cdc_ss_notify (s, state_bits);
|
||||
}
|
||||
|
||||
static void
|
||||
send_break (uint8_t dev_no, uint16_t duration)
|
||||
{
|
||||
(void)duration; /* Not supported by USART. */
|
||||
usart_send_break (dev_no);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_usart_config (uint8_t dev_no, uint32_t bitrate, uint8_t format,
|
||||
uint8_t paritytype, uint8_t databits)
|
||||
{
|
||||
/* Check supported config(s) */
|
||||
uint32_t config_bits;
|
||||
|
||||
if (bitrate == 9600)
|
||||
config_bits = B9600;
|
||||
else if (bitrate == 19200)
|
||||
config_bits = B19200;
|
||||
else if (bitrate == 57600)
|
||||
config_bits = B57600;
|
||||
else if (bitrate == 115200)
|
||||
config_bits = B115200;
|
||||
else
|
||||
{
|
||||
bitrate = 115200;
|
||||
config_bits = B115200;
|
||||
}
|
||||
|
||||
if (format == 0)
|
||||
config_bits |= STOP1B;
|
||||
else if (format == 1)
|
||||
config_bits |= STOP1B5;
|
||||
else if (format == 2)
|
||||
config_bits |= STOP2B;
|
||||
else
|
||||
{
|
||||
format = 0;
|
||||
config_bits |= STOP1B;
|
||||
}
|
||||
|
||||
if (paritytype == 0)
|
||||
config_bits |= 0;
|
||||
else if (paritytype == 1)
|
||||
config_bits |= (PARENB | PARODD);
|
||||
else if (paritytype == 2)
|
||||
config_bits |= PARENB;
|
||||
else
|
||||
{
|
||||
paritytype = 0;
|
||||
config_bits |= 0;
|
||||
}
|
||||
|
||||
if (databits == 7)
|
||||
config_bits |= CS7;
|
||||
else if (databits == 7)
|
||||
config_bits |= CS8;
|
||||
else
|
||||
{
|
||||
databits = 8;
|
||||
config_bits |= CS8;
|
||||
}
|
||||
|
||||
if (databits == 7 && paritytype == 0)
|
||||
{
|
||||
databits = 8;
|
||||
config_bits &= ~MASK_CS;
|
||||
config_bits |= CS8;
|
||||
}
|
||||
|
||||
usart_config (dev_no, config_bits);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
chopstx_usec_wait (200*1000);
|
||||
|
||||
cdc_init (PRIO_CDC, STACK_ADDR_CDC, STACK_SIZE_CDC,
|
||||
send_break, setup_usart_config);
|
||||
cdc_wait_configured ();
|
||||
|
||||
usart_init (PRIO_USART, STACK_ADDR_USART, STACK_SIZE_USART, ss_notify);
|
||||
|
||||
cdc_usart0.cdc = cdc_open (0);
|
||||
cdc_usart0.dev_no = 2;
|
||||
cdc_usart1.cdc = cdc_open (1);
|
||||
cdc_usart1.dev_no = 3;
|
||||
|
||||
chopstx_create (PRIO_USART2CDC, STACK_ADDR_USART2CDC0,
|
||||
STACK_SIZE_USART2CDC0, usart_to_cdc_loop, &cdc_usart0);
|
||||
chopstx_create (PRIO_USART2CDC, STACK_ADDR_USART2CDC1,
|
||||
STACK_SIZE_USART2CDC1, usart_to_cdc_loop, &cdc_usart1);
|
||||
chopstx_create (PRIO_CDC2USART, STACK_ADDR_CDC2USART0,
|
||||
STACK_SIZE_CDC2USART0, cdc_to_usart_loop, &cdc_usart0);
|
||||
chopstx_create (PRIO_CDC2USART, STACK_ADDR_CDC2USART1,
|
||||
STACK_SIZE_CDC2USART1, cdc_to_usart_loop, &cdc_usart1);
|
||||
|
||||
blk (NULL);
|
||||
return 0;
|
||||
}
|
||||
127
example-usb-serial/sample.ld
Normal file
127
example-usb-serial/sample.ld
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* ST32F103 memory setup.
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = 0x08000000, len = 4k
|
||||
flash : org = 0x08000000+0x1000, len = 60k
|
||||
ram : org = 0x20000000, len = 20k
|
||||
}
|
||||
|
||||
__ram_start__ = ORIGIN(ram);
|
||||
__ram_size__ = 20k;
|
||||
__ram_end__ = __ram_start__ + __ram_size__;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
|
||||
.sys : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
_sys = .;
|
||||
KEEP(*(.vectors))
|
||||
. = ALIGN(16);
|
||||
KEEP(*(.sys.version))
|
||||
KEEP(*(.sys.board_id))
|
||||
KEEP(*(.sys.board_name))
|
||||
build/sys-*.o(.text)
|
||||
build/sys-*.o(.text.*)
|
||||
build/sys-*.o(.rodata)
|
||||
build/sys-*.o(.rodata.*)
|
||||
. = ALIGN(1024);
|
||||
*(.sys.0)
|
||||
*(.sys.1)
|
||||
*(.sys.2)
|
||||
} > flash0
|
||||
|
||||
_text = .;
|
||||
|
||||
.startup : ALIGN(128) SUBALIGN(128)
|
||||
{
|
||||
KEEP(*(.startup.vectors))
|
||||
. = ALIGN (16);
|
||||
} > flash =0xffffffff
|
||||
|
||||
.text : ALIGN(16) SUBALIGN(16)
|
||||
{
|
||||
*(.text.startup.*)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.glue_7t)
|
||||
*(.glue_7)
|
||||
*(.gcc*)
|
||||
. = ALIGN(8);
|
||||
} > flash
|
||||
|
||||
.ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > flash
|
||||
|
||||
.ARM.exidx : {
|
||||
PROVIDE(__exidx_start = .);
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
PROVIDE(__exidx_end = .);
|
||||
} > flash
|
||||
|
||||
.eh_frame_hdr : {*(.eh_frame_hdr)} > flash
|
||||
|
||||
.eh_frame : ONLY_IF_RO {*(.eh_frame)} > flash
|
||||
|
||||
.textalign : ONLY_IF_RO { . = ALIGN(8); } > flash
|
||||
|
||||
_etext = .;
|
||||
_textdata = _etext;
|
||||
|
||||
.process_stack (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
*(.process_stack.6)
|
||||
*(.process_stack.5)
|
||||
*(.process_stack.4)
|
||||
*(.process_stack.3)
|
||||
*(.process_stack.2)
|
||||
*(.process_stack.1)
|
||||
*(.process_stack.0)
|
||||
. = ALIGN(8);
|
||||
} > ram
|
||||
|
||||
.main_stack (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
*(.main_stack)
|
||||
. = ALIGN(8);
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE(_data = .);
|
||||
*(.data)
|
||||
. = ALIGN(4);
|
||||
*(.data.*)
|
||||
. = ALIGN(4);
|
||||
*(.ramtext)
|
||||
. = ALIGN(4);
|
||||
PROVIDE(_edata = .);
|
||||
} > ram AT > flash
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE(_bss_start = .);
|
||||
*(.bss)
|
||||
. = ALIGN(4);
|
||||
*(.bss.*)
|
||||
. = ALIGN(4);
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
PROVIDE(_bss_end = .);
|
||||
} > ram
|
||||
|
||||
PROVIDE(end = .);
|
||||
_end = .;
|
||||
}
|
||||
|
||||
__heap_base__ = _end;
|
||||
__heap_end__ = __ram_end__;
|
||||
39
example-usb-serial/stack-def.h
Normal file
39
example-usb-serial/stack-def.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#if defined(STACK_MAIN)
|
||||
/* Idle+Exception handlers */
|
||||
char __main_stack_end__[0] __attribute__ ((section(".main_stack")));
|
||||
char main_base[0x0080] __attribute__ ((section(".main_stack")));
|
||||
|
||||
/* Main program */
|
||||
char __process0_stack_end__[0] __attribute__ ((section(".process_stack.0")));
|
||||
char process0_base[0x0400] __attribute__ ((section(".process_stack.0")));
|
||||
#endif
|
||||
|
||||
/* First thread program */
|
||||
#if defined(STACK_PROCESS_1)
|
||||
char process1_base[0x0200] __attribute__ ((section(".process_stack.1")));
|
||||
#endif
|
||||
|
||||
/* Second thread program */
|
||||
#if defined(STACK_PROCESS_2)
|
||||
char process2_base[0x0200] __attribute__ ((section(".process_stack.2")));
|
||||
#endif
|
||||
|
||||
/* Third thread program */
|
||||
#if defined(STACK_PROCESS_3)
|
||||
char process3_base[0x0200] __attribute__ ((section(".process_stack.3")));
|
||||
#endif
|
||||
|
||||
/* Fourth thread program */
|
||||
#if defined(STACK_PROCESS_4)
|
||||
char process4_base[0x0200] __attribute__ ((section(".process_stack.4")));
|
||||
#endif
|
||||
|
||||
/* Fifth thread program */
|
||||
#if defined(STACK_PROCESS_5)
|
||||
char process5_base[0x0200] __attribute__ ((section(".process_stack.5")));
|
||||
#endif
|
||||
|
||||
/* Sixth thread program */
|
||||
#if defined(STACK_PROCESS_6)
|
||||
char process6_base[0x0200] __attribute__ ((section(".process_stack.6")));
|
||||
#endif
|
||||
1033
example-usb-serial/usb-cdc.c
Normal file
1033
example-usb-serial/usb-cdc.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -57,7 +57,7 @@ In the development of Gnuk, we developed:
|
||||
|
||||
It is now maintained as example-cdc/sys.c.
|
||||
|
||||
There is another version in example-led/sys.c, which also support
|
||||
There is another version in example-led/sys.c, which also supports
|
||||
STM32F030, as well as STM32F103. But, it wouldn't be useful for
|
||||
STM32F030. In fact, the file example-fsm-55/sys.c has name sys.c
|
||||
but it doesn't include any system routines.
|
||||
@@ -74,7 +74,7 @@ Later on, we add another point.
|
||||
(3) It is good if the executable of Gnuk could be shared among
|
||||
different boards.
|
||||
|
||||
For (1) and (2), we decided put some useful routines and data which is
|
||||
For (1) and (2), we decided put some useful routines and data which are
|
||||
not need to be changed.
|
||||
|
||||
Now, the first 4KiB of flash ROM consists of:
|
||||
@@ -84,7 +84,7 @@ Now, the first 4KiB of flash ROM consists of:
|
||||
|
||||
SYS consists of:
|
||||
|
||||
Internal: reset entry, end of RAM
|
||||
Internal: reset entry, address of the end of RAM
|
||||
Data: board identification
|
||||
Routines: board specific
|
||||
board independent
|
||||
@@ -94,7 +94,7 @@ and here is the list of all.
|
||||
* Internal routines
|
||||
|
||||
reset entry
|
||||
end of RAM
|
||||
address of the end of RAM
|
||||
|
||||
* Board identification
|
||||
|
||||
|
||||
5
mcu/chx-gnu-linux.c
Normal file
5
mcu/chx-gnu-linux.c
Normal file
@@ -0,0 +1,5 @@
|
||||
void
|
||||
chx_sleep_mode (int enable_sleep)
|
||||
{
|
||||
(void)enable_sleep;
|
||||
}
|
||||
23
mcu/chx-mkl27z.c
Normal file
23
mcu/chx-mkl27z.c
Normal file
@@ -0,0 +1,23 @@
|
||||
extern int chx_allow_sleep;
|
||||
|
||||
void
|
||||
chx_sleep_mode (int enable_sleep)
|
||||
{
|
||||
(void)enable_sleep;
|
||||
}
|
||||
|
||||
void __attribute__((naked))
|
||||
chx_idle (void)
|
||||
{
|
||||
int sleep_enabled;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
asm ("ldr %0, %1" : "=r" (sleep_enabled): "m" (chx_allow_sleep));
|
||||
if (sleep_enabled)
|
||||
{
|
||||
asm volatile ("wfi" : : : "memory");
|
||||
/* NOTE: it never comes here. Don't add lines after this. */
|
||||
}
|
||||
}
|
||||
}
|
||||
42
mcu/chx-stm32f0.c
Normal file
42
mcu/chx-stm32f0.c
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <stdint.h>
|
||||
#include <mcu/cortex-m.h>
|
||||
#define MCU_STM32F0
|
||||
#include <mcu/stm32.h>
|
||||
|
||||
extern int chx_allow_sleep;
|
||||
|
||||
void
|
||||
chx_sleep_mode (int how)
|
||||
{
|
||||
PWR->CR |= PWR_CR_CWUF;
|
||||
PWR->CR &= ~(PWR_CR_PDDS|PWR_CR_LPDS);
|
||||
|
||||
if (how == 0 || how == 1 /* Sleep only (not deepsleep) */)
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP;
|
||||
else
|
||||
{ /* Deepsleep */
|
||||
/* how == 2: deepsleep but regulator ON */
|
||||
if (how == 3)
|
||||
PWR->CR |= PWR_CR_LPDS; /* regulator low-power mode */
|
||||
else if (how == 4)
|
||||
PWR->CR |= PWR_CR_PDDS; /* Power down: All OFF */
|
||||
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP;
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((naked))
|
||||
chx_idle (void)
|
||||
{
|
||||
int sleep_enabled;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
asm ("ldr %0, %1" : "=r" (sleep_enabled): "m" (chx_allow_sleep));
|
||||
if (sleep_enabled)
|
||||
{
|
||||
asm volatile ("wfi" : : : "memory");
|
||||
/* NOTE: it never comes here. Don't add lines after this. */
|
||||
}
|
||||
}
|
||||
}
|
||||
92
mcu/chx-stm32f103.c
Normal file
92
mcu/chx-stm32f103.c
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <stdint.h>
|
||||
#include <mcu/stm32f103.h>
|
||||
#include "board.h"
|
||||
|
||||
extern int chx_allow_sleep;
|
||||
|
||||
#define STM32_PLLSRC STM32_PLLSRC_HSE
|
||||
#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18)
|
||||
#ifndef STM32_ADCPRE
|
||||
#define STM32_ADCPRE STM32_ADCPRE_DIV6
|
||||
#endif
|
||||
#ifndef STM32_USBPRE
|
||||
#define STM32_USBPRE STM32_USBPRE_DIV1P5
|
||||
#endif
|
||||
|
||||
static void
|
||||
configure_clock (int high)
|
||||
{
|
||||
uint32_t cfg_sw;
|
||||
uint32_t cfg;
|
||||
|
||||
if (high)
|
||||
{
|
||||
cfg = STM32_MCO_NOCLOCK | STM32_USBPRE
|
||||
| STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC
|
||||
| STM32_ADCPRE | STM32_PPRE2_DIV1
|
||||
| STM32_PPRE1_DIV2 | STM32_HPRE_DIV1;
|
||||
|
||||
cfg_sw = RCC_CFGR_SW_PLL;
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg = STM32_MCO_NOCLOCK | STM32_USBPRE
|
||||
| STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC
|
||||
| STM32_ADCPRE_DIV8 | STM32_PPRE2_DIV16
|
||||
| STM32_PPRE1_DIV16 | STM32_HPRE_DIV8;
|
||||
|
||||
cfg_sw = RCC_CFGR_SW_HSI;
|
||||
}
|
||||
|
||||
RCC->CFGR = cfg | cfg_sw;
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != (cfg_sw << 2))
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* When HOW=0 or HOW=1, SYSCLK is PLL (72MHz).
|
||||
* When HOW=2, SYSCLK will be 1MHz with HSI (8MHz) on sleep.
|
||||
*
|
||||
* With lower clock, it can achieve lower power consumption.
|
||||
*
|
||||
* Implementation note: Deepsleep is only useful with RTC, Watch Dog,
|
||||
* or WKUP pin. We can't use deepsleep for USB, it never wakes up.
|
||||
*
|
||||
*/
|
||||
void
|
||||
chx_sleep_mode (int how)
|
||||
{
|
||||
if (how == 0 || how == 1)
|
||||
configure_clock (1);
|
||||
|
||||
/* how == 2: Defer setting to 8MHz clock to the idle function */
|
||||
}
|
||||
|
||||
void __attribute__((naked))
|
||||
chx_idle (void)
|
||||
{
|
||||
int sleep_enabled;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
asm ("ldr %0, %1" : "=r" (sleep_enabled): "m" (chx_allow_sleep));
|
||||
if (sleep_enabled)
|
||||
{
|
||||
asm volatile ("cpsid i" : : : "memory");
|
||||
if (sleep_enabled == 1)
|
||||
{
|
||||
/* Allow JTAG/SWD access on sleep. */
|
||||
DBGMCU->CR |= DBG_SLEEP;
|
||||
}
|
||||
else if (sleep_enabled == 2)
|
||||
{
|
||||
DBGMCU->CR &= ~DBG_SLEEP; /* Disable HCLK on sleep */
|
||||
configure_clock (0);
|
||||
}
|
||||
asm volatile ("cpsie i" : : : "memory");
|
||||
|
||||
asm volatile ("wfi" : : : "memory");
|
||||
/* NOTE: it never comes here. Don't add lines after this. */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,28 +26,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define STM32_SW_HSI (0 << 0)
|
||||
#define STM32_SW_PLL (2 << 0)
|
||||
#define STM32_PLLSRC_HSI (0 << 16)
|
||||
#define STM32_PLLSRC_HSE (1 << 16)
|
||||
|
||||
#define STM32_PLLXTPRE_DIV1 (0 << 17)
|
||||
#define STM32_PLLXTPRE_DIV2 (1 << 17)
|
||||
|
||||
#define STM32_HPRE_DIV1 (0 << 4)
|
||||
|
||||
#define STM32_PPRE1_DIV1 (0 << 8)
|
||||
#define STM32_PPRE1_DIV2 (4 << 8)
|
||||
|
||||
#define STM32_PPRE2_DIV1 (0 << 11)
|
||||
#define STM32_PPRE2_DIV2 (4 << 11)
|
||||
|
||||
#define STM32_ADCPRE_DIV4 (1 << 14)
|
||||
#define STM32_ADCPRE_DIV6 (2 << 14)
|
||||
|
||||
#define STM32_USBPRE_DIV1P5 (0 << 22)
|
||||
|
||||
#define STM32_MCO_NOCLOCK (0 << 24)
|
||||
#include <mcu/stm32.h>
|
||||
|
||||
#if defined(MCU_STM32F0)
|
||||
#define STM32_PPRE1 STM32_PPRE1_DIV1
|
||||
@@ -64,9 +43,13 @@
|
||||
#define STM32_SW STM32_SW_PLL
|
||||
#define STM32_HPRE STM32_HPRE_DIV1
|
||||
#define STM32_PPRE2 STM32_PPRE2_DIV1
|
||||
#ifndef STM32_ADCPRE
|
||||
#define STM32_ADCPRE STM32_ADCPRE_DIV6
|
||||
#endif
|
||||
#define STM32_MCOSEL STM32_MCO_NOCLOCK
|
||||
#define STM32_USBPRE STM32_USBPRE_DIV1P5
|
||||
#ifndef STM32_USBPRE
|
||||
#define STM32_USBPRE STM32_USBPRE_DIV1P5
|
||||
#endif
|
||||
|
||||
#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18)
|
||||
#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE)
|
||||
@@ -74,85 +57,6 @@
|
||||
#define STM32_HCLK (STM32_SYSCLK / 1)
|
||||
|
||||
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APBPERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000)
|
||||
|
||||
struct RCC {
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CFGR;
|
||||
volatile uint32_t CIR;
|
||||
volatile uint32_t APB2RSTR;
|
||||
volatile uint32_t APB1RSTR;
|
||||
volatile uint32_t AHBENR;
|
||||
volatile uint32_t APB2ENR;
|
||||
volatile uint32_t APB1ENR;
|
||||
volatile uint32_t BDCR;
|
||||
volatile uint32_t CSR;
|
||||
#if defined(MCU_STM32F0)
|
||||
volatile uint32_t AHBRSTR;
|
||||
volatile uint32_t CFGR2;
|
||||
volatile uint32_t CFGR3;
|
||||
volatile uint32_t CR2;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
|
||||
static struct RCC *const RCC = (struct RCC *)RCC_BASE;
|
||||
|
||||
#define RCC_APB1ENR_USBEN 0x00800000
|
||||
#define RCC_APB1RSTR_USBRST 0x00800000
|
||||
|
||||
#define RCC_CR_HSION 0x00000001
|
||||
#define RCC_CR_HSIRDY 0x00000002
|
||||
#define RCC_CR_HSITRIM 0x000000F8
|
||||
#define RCC_CR_HSEON 0x00010000
|
||||
#define RCC_CR_HSERDY 0x00020000
|
||||
#define RCC_CR_PLLON 0x01000000
|
||||
#define RCC_CR_PLLRDY 0x02000000
|
||||
|
||||
#define RCC_CFGR_SWS 0x0000000C
|
||||
#define RCC_CFGR_SWS_HSI 0x00000000
|
||||
|
||||
#define RCC_AHBENR_CRCEN 0x0040
|
||||
|
||||
#if defined(MCU_STM32F0)
|
||||
#define RCC_AHBRSTR_IOPARST 0x00020000
|
||||
#define RCC_AHBRSTR_IOPBRST 0x00040000
|
||||
#define RCC_AHBRSTR_IOPCRST 0x00080000
|
||||
#define RCC_AHBRSTR_IOPDRST 0x00100000
|
||||
#define RCC_AHBRSTR_IOPFRST 0x00400000
|
||||
|
||||
#define RCC_AHBENR_IOPAEN 0x00020000
|
||||
#define RCC_AHBENR_IOPBEN 0x00040000
|
||||
#define RCC_AHBENR_IOPCEN 0x00080000
|
||||
#define RCC_AHBENR_IOPDEN 0x00100000
|
||||
#define RCC_AHBENR_IOPFEN 0x00400000
|
||||
|
||||
#define RCC_APB2RSTR_SYSCFGRST 0x00000001
|
||||
#define RCC_APB2ENR_SYSCFGEN 0x00000001
|
||||
#else
|
||||
#define RCC_APB2RSTR_AFIORST 0x00000001
|
||||
#define RCC_APB2RSTR_IOPARST 0x00000004
|
||||
#define RCC_APB2RSTR_IOPBRST 0x00000008
|
||||
#define RCC_APB2RSTR_IOPCRST 0x00000010
|
||||
#define RCC_APB2RSTR_IOPDRST 0x00000020
|
||||
#define RCC_APB2RSTR_IOPERST 0x00000040
|
||||
#define RCC_APB2RSTR_IOPFRST 0x00000080
|
||||
#define RCC_APB2RSTR_IOPGRST 0x00000100
|
||||
|
||||
#define RCC_APB2ENR_AFIOEN 0x00000001
|
||||
#define RCC_APB2ENR_IOPAEN 0x00000004
|
||||
#define RCC_APB2ENR_IOPBEN 0x00000008
|
||||
#define RCC_APB2ENR_IOPCEN 0x00000010
|
||||
#define RCC_APB2ENR_IOPDEN 0x00000020
|
||||
#define RCC_APB2ENR_IOPEEN 0x00000040
|
||||
#define RCC_APB2ENR_IOPFEN 0x00000080
|
||||
#define RCC_APB2ENR_IOPGEN 0x00000100
|
||||
#endif
|
||||
|
||||
#if defined(MCU_STM32F0)
|
||||
struct SYSCFG {
|
||||
volatile uint32_t CFGR1;
|
||||
@@ -162,7 +66,7 @@ struct SYSCFG {
|
||||
};
|
||||
#define SYSCFG_CFGR1_MEM_MODE 0x03
|
||||
|
||||
#define SYSCFG_BASE (APBPERIPH_BASE + 0x00010000)
|
||||
#define SYSCFG_BASE (APB1PERIPH_BASE + 0x00010000)
|
||||
static struct SYSCFG *const SYSCFG = (struct SYSCFG *)SYSCFG_BASE;
|
||||
#endif
|
||||
|
||||
@@ -218,9 +122,6 @@ clock_init (void)
|
||||
/* Flash setup */
|
||||
FLASH->ACR = STM32_FLASHBITS;
|
||||
|
||||
/* CRC */
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
|
||||
/* Switching on the configured clock source. */
|
||||
RCC->CFGR |= STM32_SW;
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
|
||||
|
||||
29
mcu/cortex-m.h
Normal file
29
mcu/cortex-m.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* System Control Block */
|
||||
struct SCB
|
||||
{
|
||||
volatile uint32_t CPUID;
|
||||
volatile uint32_t ICSR;
|
||||
volatile uint32_t VTOR;
|
||||
volatile uint32_t AIRCR;
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t CCR;
|
||||
volatile uint8_t SHP[12];
|
||||
volatile uint32_t SHCSR;
|
||||
volatile uint32_t CFSR;
|
||||
volatile uint32_t HFSR;
|
||||
volatile uint32_t DFSR;
|
||||
volatile uint32_t MMAR;
|
||||
volatile uint32_t BFAR;
|
||||
volatile uint32_t AFSR;
|
||||
volatile uint32_t PFR[2];
|
||||
volatile uint32_t DFR;
|
||||
volatile uint32_t AFR;
|
||||
volatile uint32_t MMFR[4];
|
||||
volatile uint32_t ISAR[5];
|
||||
};
|
||||
|
||||
#define SCS_BASE 0xE000E000
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00)
|
||||
static struct SCB *const SCB = (struct SCB *)SCB_BASE;
|
||||
#define SCB_SCR_SLEEPDEEP (1 << 2)
|
||||
#define SCB_AIRCR_SYSRESETREQ 0x04
|
||||
142
mcu/stm32.h
Normal file
142
mcu/stm32.h
Normal file
@@ -0,0 +1,142 @@
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000)
|
||||
|
||||
struct RCC {
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CFGR;
|
||||
volatile uint32_t CIR;
|
||||
volatile uint32_t APB2RSTR;
|
||||
volatile uint32_t APB1RSTR;
|
||||
volatile uint32_t AHBENR;
|
||||
volatile uint32_t APB2ENR;
|
||||
volatile uint32_t APB1ENR;
|
||||
volatile uint32_t BDCR;
|
||||
volatile uint32_t CSR;
|
||||
#if defined(MCU_STM32F0)
|
||||
volatile uint32_t AHBRSTR;
|
||||
volatile uint32_t CFGR2;
|
||||
volatile uint32_t CFGR3;
|
||||
volatile uint32_t CR2;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
|
||||
static struct RCC *const RCC = (struct RCC *)RCC_BASE;
|
||||
|
||||
#define RCC_APB1ENR_USBEN 0x00800000
|
||||
#define RCC_APB1RSTR_USBRST 0x00800000
|
||||
|
||||
#define RCC_CR_HSION 0x00000001
|
||||
#define RCC_CR_HSIRDY 0x00000002
|
||||
#define RCC_CR_HSITRIM 0x000000F8
|
||||
#define RCC_CR_HSEON 0x00010000
|
||||
#define RCC_CR_HSERDY 0x00020000
|
||||
#define RCC_CR_PLLON 0x01000000
|
||||
#define RCC_CR_PLLRDY 0x02000000
|
||||
|
||||
#define RCC_CFGR_SWS 0x0000000C
|
||||
#define RCC_CFGR_SWS_HSI 0x00000000
|
||||
#define RCC_CFGR_SW_HSI (0 << 0)
|
||||
#define RCC_CFGR_SW_HSE (1 << 0)
|
||||
#define RCC_CFGR_SW_PLL (2 << 0)
|
||||
#define RCC_CFGR_SW_MASK (3 << 0)
|
||||
|
||||
#define RCC_AHBENR_DMA1EN 0x00000001
|
||||
#define RCC_AHBENR_CRCEN 0x00000040
|
||||
|
||||
#if defined(MCU_STM32F0)
|
||||
#define RCC_AHBRSTR_IOPARST 0x00020000
|
||||
#define RCC_AHBRSTR_IOPBRST 0x00040000
|
||||
#define RCC_AHBRSTR_IOPCRST 0x00080000
|
||||
#define RCC_AHBRSTR_IOPDRST 0x00100000
|
||||
#define RCC_AHBRSTR_IOPFRST 0x00400000
|
||||
|
||||
#define RCC_AHBENR_IOPAEN 0x00020000
|
||||
#define RCC_AHBENR_IOPBEN 0x00040000
|
||||
#define RCC_AHBENR_IOPCEN 0x00080000
|
||||
#define RCC_AHBENR_IOPDEN 0x00100000
|
||||
#define RCC_AHBENR_IOPFEN 0x00400000
|
||||
|
||||
#define RCC_APB2RSTR_SYSCFGRST 0x00000001
|
||||
#define RCC_APB2ENR_SYSCFGEN 0x00000001
|
||||
#else
|
||||
#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 RCC_APB2RSTR_AFIORST 0x00000001
|
||||
#define RCC_APB2RSTR_IOPARST 0x00000004
|
||||
#define RCC_APB2RSTR_IOPBRST 0x00000008
|
||||
#define RCC_APB2RSTR_IOPCRST 0x00000010
|
||||
#define RCC_APB2RSTR_IOPDRST 0x00000020
|
||||
#define RCC_APB2RSTR_IOPERST 0x00000040
|
||||
#define RCC_APB2RSTR_IOPFRST 0x00000080
|
||||
#define RCC_APB2RSTR_IOPGRST 0x00000100
|
||||
|
||||
#define RCC_APB2ENR_AFIOEN 0x00000001
|
||||
#define RCC_APB2ENR_IOPAEN 0x00000004
|
||||
#define RCC_APB2ENR_IOPBEN 0x00000008
|
||||
#define RCC_APB2ENR_IOPCEN 0x00000010
|
||||
#define RCC_APB2ENR_IOPDEN 0x00000020
|
||||
#define RCC_APB2ENR_IOPEEN 0x00000040
|
||||
#define RCC_APB2ENR_IOPFEN 0x00000080
|
||||
#define RCC_APB2ENR_IOPGEN 0x00000100
|
||||
#endif
|
||||
|
||||
|
||||
/* Clock setting values.
|
||||
* Due to historical reason, it has the prefix of STM32_.
|
||||
*/
|
||||
#define STM32_SW_HSI (0 << 0)
|
||||
#define STM32_SW_HSE (1 << 0)
|
||||
#define STM32_SW_PLL (2 << 0)
|
||||
|
||||
#define STM32_PLLSRC_HSI (0 << 16)
|
||||
#define STM32_PLLSRC_HSE (1 << 16)
|
||||
|
||||
#define STM32_PLLXTPRE_DIV1 (0 << 17)
|
||||
#define STM32_PLLXTPRE_DIV2 (1 << 17)
|
||||
|
||||
#define STM32_HPRE_DIV1 (0 << 4)
|
||||
#define STM32_HPRE_DIV8 (10 << 4)
|
||||
#define STM32_HPRE_DIV16 (11 << 4)
|
||||
|
||||
#define STM32_PPRE1_DIV1 (0 << 8)
|
||||
#define STM32_PPRE1_DIV2 (4 << 8)
|
||||
#define STM32_PPRE1_DIV16 (7 << 8)
|
||||
|
||||
#define STM32_PPRE2_DIV1 (0 << 11)
|
||||
#define STM32_PPRE2_DIV2 (4 << 11)
|
||||
#define STM32_PPRE2_DIV16 (7 << 11)
|
||||
|
||||
#define STM32_ADCPRE_DIV4 (1 << 14)
|
||||
#define STM32_ADCPRE_DIV6 (2 << 14)
|
||||
#define STM32_ADCPRE_DIV8 (3 << 14)
|
||||
|
||||
#define STM32_USBPRE_DIV1P5 (0 << 22)
|
||||
#define STM32_USBPRE_DIV2 (3 << 22) /* Not for STM32, but GD32F103 */
|
||||
|
||||
#define STM32_MCO_NOCLOCK (0 << 24)
|
||||
|
||||
struct PWR
|
||||
{
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CSR;
|
||||
};
|
||||
static struct PWR *const PWR = ((struct PWR *)0x40007000);
|
||||
#define PWR_CR_LPDS 0x0001 /* Low-power deepsleep */
|
||||
#define PWR_CR_PDDS 0x0002 /* Power down deepsleep */
|
||||
#define PWR_CR_CWUF 0x0004 /* Clear wakeup flag */
|
||||
@@ -1,40 +1,5 @@
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
|
||||
struct RCC {
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CFGR;
|
||||
volatile uint32_t CIR;
|
||||
volatile uint32_t APB2RSTR;
|
||||
volatile uint32_t APB1RSTR;
|
||||
volatile uint32_t AHBENR;
|
||||
volatile uint32_t APB2ENR;
|
||||
volatile uint32_t APB1ENR;
|
||||
volatile uint32_t BDCR;
|
||||
volatile uint32_t CSR;
|
||||
};
|
||||
|
||||
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
|
||||
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
|
||||
#include <mcu/stm32.h>
|
||||
#include <mcu/cortex-m.h>
|
||||
|
||||
#define CRC_CR_RESET 0x00000001
|
||||
|
||||
@@ -182,36 +147,6 @@ static struct DMA *const DMA1 = (struct DMA *)DMA1_BASE;
|
||||
static struct DMA_Channel *const DMA1_Channel1 =
|
||||
(struct DMA_Channel *)DMA1_Channel1_BASE;
|
||||
|
||||
/* System Control Block */
|
||||
struct SCB
|
||||
{
|
||||
volatile uint32_t CPUID;
|
||||
volatile uint32_t ICSR;
|
||||
volatile uint32_t VTOR;
|
||||
volatile uint32_t AIRCR;
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t CCR;
|
||||
volatile uint8_t SHP[12];
|
||||
volatile uint32_t SHCSR;
|
||||
volatile uint32_t CFSR;
|
||||
volatile uint32_t HFSR;
|
||||
volatile uint32_t DFSR;
|
||||
volatile uint32_t MMFAR;
|
||||
volatile uint32_t BFAR;
|
||||
volatile uint32_t AFSR;
|
||||
volatile uint32_t PFR[2];
|
||||
volatile uint32_t DFR;
|
||||
volatile uint32_t ADR;
|
||||
volatile uint32_t MMFR[4];
|
||||
volatile uint32_t ISAR[5];
|
||||
uint32_t RESERVED0[5];
|
||||
volatile uint32_t CPACR;
|
||||
};
|
||||
|
||||
#define SCS_BASE 0xE000E000
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00)
|
||||
static struct SCB *const SCB = (struct SCB *)SCB_BASE;
|
||||
|
||||
/* Timer */
|
||||
struct TIM
|
||||
{
|
||||
@@ -698,3 +633,12 @@ static struct AFIO *const AFIO = (struct AFIO *)AFIO_BASE;
|
||||
|
||||
#define AFIO_MAPR_TIM3_REMAP_PARTIALREMAP 0x00000800
|
||||
#define AFIO_MAPR_SWJ_CFG_DISABLE 0x04000000
|
||||
|
||||
|
||||
struct DBGMCU {
|
||||
volatile uint32_t CR;
|
||||
};
|
||||
|
||||
#define DBGMCU_BASE 0xE0042004
|
||||
#define DBG_SLEEP 1
|
||||
static struct DBGMCU *const DBGMCU = (struct DBGMCU *)DBGMCU_BASE;
|
||||
|
||||
251
mcu/sys-gnu-linux.c
Normal file
251
mcu/sys-gnu-linux.c
Normal file
@@ -0,0 +1,251 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "sys.h"
|
||||
|
||||
const uint8_t sys_version[8] = {
|
||||
3*2+2, /* bLength */
|
||||
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */
|
||||
/* sys version: "3.0" */
|
||||
'3', 0, '.', 0, '0', 0,
|
||||
};
|
||||
|
||||
#if defined(USE_SYS3) || defined(USE_SYS_BOARD_ID)
|
||||
const uint32_t sys_board_id = BOARD_ID;
|
||||
const uint8_t sys_board_name[] = BOARD_NAME;
|
||||
#endif
|
||||
|
||||
int debug;
|
||||
|
||||
void
|
||||
set_led (int on)
|
||||
{
|
||||
if ((debug & DEBUG_LED))
|
||||
puts (on ? "*": "");
|
||||
}
|
||||
|
||||
static const char *flash_path;
|
||||
static size_t flash_size;
|
||||
static void * flash_addr;
|
||||
static int flash_fd;
|
||||
|
||||
uintptr_t
|
||||
flash_init (const char *f_name)
|
||||
{
|
||||
int fd;
|
||||
struct stat sb;
|
||||
void *addr;
|
||||
|
||||
fd = open (f_name, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror ("flash_init: open");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (fstat (fd, &sb) < 0)
|
||||
{
|
||||
perror ("flash_init: fstat");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
addr = mmap (NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (addr == MAP_FAILED)
|
||||
{
|
||||
perror ("flash_init: mmap");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (close (fd) < 0)
|
||||
{
|
||||
perror ("flash_init: close");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
flash_path = f_name;
|
||||
flash_addr = addr;
|
||||
flash_size = sb.st_size;
|
||||
|
||||
return (uintptr_t)addr;
|
||||
}
|
||||
|
||||
void
|
||||
flash_unlock (void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open (flash_path, O_WRONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror ("flash_unlock: open");
|
||||
exit (1);
|
||||
}
|
||||
flash_fd = fd;
|
||||
}
|
||||
|
||||
int
|
||||
flash_program_halfword (uintptr_t addr, uint16_t data)
|
||||
{
|
||||
off_t offset;
|
||||
char buf[2];
|
||||
|
||||
if ((debug & DEBUG_FLASH))
|
||||
fprintf (stderr, "flash_program_halfword: addr=%016lx, data=%04x\n",
|
||||
addr, data);
|
||||
offset = (off_t)(addr - (uintptr_t)flash_addr);
|
||||
if (offset < 0 || offset >= (off_t)flash_size)
|
||||
{
|
||||
perror ("flash_program_halfword");
|
||||
return 1;
|
||||
}
|
||||
|
||||
offset = lseek (flash_fd, offset, SEEK_SET);
|
||||
if (offset == (off_t)-1)
|
||||
{
|
||||
perror ("flash_program_halfword");
|
||||
return 1;
|
||||
}
|
||||
buf[0] = (data & 0xff);
|
||||
buf[1] = (data >> 8);
|
||||
if (write (flash_fd, buf, 2) != 2)
|
||||
{
|
||||
perror ("flash_program_halfword");
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const uint8_t erased[] = { [0 ... 1023 ] = 0xff };
|
||||
|
||||
int
|
||||
flash_erase_page (uintptr_t addr)
|
||||
{
|
||||
off_t offset;
|
||||
|
||||
if ((debug & DEBUG_FLASH))
|
||||
fprintf (stderr, "flash_erase_page: addr=%016lx\n", addr);
|
||||
|
||||
offset = (off_t)(addr - (uintptr_t)flash_addr);
|
||||
if (offset < 0 || offset >= (off_t)flash_size)
|
||||
{
|
||||
perror ("flash_erase_page");
|
||||
return 1;
|
||||
}
|
||||
|
||||
offset = lseek (flash_fd, offset, SEEK_SET);
|
||||
if (offset == (off_t)-1)
|
||||
{
|
||||
perror ("flash_erase_page");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (write (flash_fd, erased, sizeof (erased)) != sizeof (erased))
|
||||
{
|
||||
perror ("flash_erase_page");
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
flash_check_blank (const uint8_t *p_start, size_t size)
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
if (p_start < (const uint8_t *)flash_addr
|
||||
|| p_start + size > (const uint8_t *)flash_addr + flash_size)
|
||||
{
|
||||
perror ("flash_check_blank");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (p = p_start; p < p_start + size; p++)
|
||||
if (*p != 0xff)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
flash_write (uintptr_t dst_addr, const uint8_t *src, size_t len)
|
||||
{
|
||||
off_t offset;
|
||||
|
||||
if ((debug & DEBUG_FLASH))
|
||||
fprintf (stderr, "flash_write: addr=%016lx, %p, %zd\n",
|
||||
dst_addr, src, len);
|
||||
|
||||
offset = (off_t)(dst_addr - (uintptr_t)flash_addr);
|
||||
if (offset < 0 || offset >= (off_t)flash_size)
|
||||
{
|
||||
perror ("flash_write");
|
||||
return 1;
|
||||
}
|
||||
|
||||
offset = lseek (flash_fd, offset, SEEK_SET);
|
||||
if (offset == (off_t)-1)
|
||||
{
|
||||
perror ("flash_write");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (write (flash_fd, src, len) != (ssize_t)len)
|
||||
{
|
||||
perror ("flash_write");
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
flash_protect (void)
|
||||
{
|
||||
if ((debug & DEBUG_FLASH))
|
||||
fprintf (stderr, "flash_protect\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __attribute__((noreturn))
|
||||
flash_erase_all_and_exec (void (*entry)(void))
|
||||
{
|
||||
(void)entry;
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_sys_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_sys_shutdown (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((noreturn))
|
||||
nvic_system_reset (void)
|
||||
{
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
clock_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gpio_init (void)
|
||||
{
|
||||
}
|
||||
52
mcu/sys-gnu-linux.h
Normal file
52
mcu/sys-gnu-linux.h
Normal file
@@ -0,0 +1,52 @@
|
||||
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[];
|
||||
# define SYS_BOARD_ID sys_board_id
|
||||
#else
|
||||
# define SYS_BOARD_ID BOARD_ID
|
||||
#endif
|
||||
|
||||
#define DEBUG_LED (1 << 1)
|
||||
#define DEBUG_FLASH (1 << 2)
|
||||
#define DEBUG_USB (1 << 3)
|
||||
|
||||
extern int debug;
|
||||
|
||||
static inline const uint8_t *
|
||||
unique_device_id (void)
|
||||
{
|
||||
/*
|
||||
* STM32F103 has 96-bit unique device identifier.
|
||||
* This routine mimics that.
|
||||
*/
|
||||
|
||||
static const uint8_t id[] = { /* My RSA fingerprint */
|
||||
0x12, 0x41, 0x24, 0xBD, 0x3B, 0x48, 0x62, 0xAF,
|
||||
0x7A, 0x0A, 0x42, 0xF1, 0x00, 0xB4, 0x5E, 0xBD,
|
||||
0x4C, 0xA7, 0xBA, 0xBE
|
||||
};
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void set_led (int on);
|
||||
|
||||
uintptr_t flash_init (const char *f_name);
|
||||
void flash_unlock (void);
|
||||
int flash_program_halfword (uintptr_t addr, uint16_t data);
|
||||
int flash_erase_page (uintptr_t addr);
|
||||
int flash_check_blank (const uint8_t *p_start, size_t size);
|
||||
int flash_write (uintptr_t dst_addr, const uint8_t *src, size_t len);
|
||||
int flash_protect (void);
|
||||
void __attribute__((noreturn))
|
||||
flash_erase_all_and_exec (void (*entry)(void));
|
||||
|
||||
void usb_lld_sys_init (void);
|
||||
void usb_lld_sys_shutdown (void);
|
||||
|
||||
void __attribute__((noreturn))
|
||||
nvic_system_reset (void);
|
||||
|
||||
void clock_init (void);
|
||||
void gpio_init (void);
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* sys.c - system routines for the initial page for STM32F030 / STM32F103.
|
||||
* sys-stm32f0.c - system routines for the initial page for STM32F030.
|
||||
*
|
||||
* Copyright (C) 2013, 2014, 2015, 2016 Flying Stone Technology
|
||||
* Copyright (C) 2013, 2014, 2015, 2016, 2017
|
||||
* Flying Stone Technology
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* Copying and distribution of this file, with or without modification,
|
||||
@@ -18,6 +19,7 @@
|
||||
#include "board.h"
|
||||
|
||||
#define STM32F0_USE_VECTOR_ON_RAM
|
||||
#include "mcu/cortex-m.h"
|
||||
#include "mcu/clk_gpio_init-stm32.c"
|
||||
|
||||
|
||||
@@ -298,38 +300,11 @@ flash_erase_all_and_exec (void (*entry)(void))
|
||||
for (;;);
|
||||
}
|
||||
|
||||
struct SCB
|
||||
{
|
||||
volatile uint32_t CPUID;
|
||||
volatile uint32_t ICSR;
|
||||
volatile uint32_t VTOR;
|
||||
volatile uint32_t AIRCR;
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t CCR;
|
||||
volatile uint8_t SHP[12];
|
||||
volatile uint32_t SHCSR;
|
||||
volatile uint32_t CFSR;
|
||||
volatile uint32_t HFSR;
|
||||
volatile uint32_t DFSR;
|
||||
volatile uint32_t MMFAR;
|
||||
volatile uint32_t BFAR;
|
||||
volatile uint32_t AFSR;
|
||||
volatile uint32_t PFR[2];
|
||||
volatile uint32_t DFR;
|
||||
volatile uint32_t ADR;
|
||||
volatile uint32_t MMFR[4];
|
||||
volatile uint32_t ISAR[5];
|
||||
};
|
||||
|
||||
#define SCS_BASE (0xE000E000)
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00)
|
||||
static struct SCB *const SCB = (struct SCB *)SCB_BASE;
|
||||
|
||||
#define SYSRESETREQ 0x04
|
||||
static void
|
||||
nvic_system_reset (void)
|
||||
{
|
||||
SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ);
|
||||
SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SCB_AIRCR_SYSRESETREQ);
|
||||
asm volatile ("dsb");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ usb_lld_sys_shutdown (void)
|
||||
(*vector[11]) ();
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline void __attribute__((noreturn))
|
||||
nvic_system_reset (void)
|
||||
{
|
||||
(*vector[12]) ();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* sys.c - system routines for the initial page for STM32F103.
|
||||
* sys-stm32f103.c - system routines for the initial page for STM32F103.
|
||||
*
|
||||
* Copyright (C) 2013, 2014, 2015, 2016 Flying Stone Technology
|
||||
* Copyright (C) 2013, 2014, 2015, 2016, 2017, 2018
|
||||
* Flying Stone Technology
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* Copying and distribution of this file, with or without modification,
|
||||
@@ -17,6 +18,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "board.h"
|
||||
|
||||
#include "mcu/cortex-m.h"
|
||||
#include "mcu/clk_gpio_init-stm32.c"
|
||||
|
||||
|
||||
@@ -80,7 +82,7 @@ usb_lld_sys_init (void)
|
||||
{
|
||||
usb_lld_sys_shutdown ();
|
||||
/* Disconnect requires SE0 (>= 2.5uS). */
|
||||
wait (300);
|
||||
wait (5*MHZ);
|
||||
}
|
||||
|
||||
usb_cable_config (1);
|
||||
@@ -148,7 +150,7 @@ flash_wait_for_last_operation (uint32_t timeout)
|
||||
#define FLASH_ERASE_TIMEOUT 0x01000000
|
||||
|
||||
static int
|
||||
flash_program_halfword (uint32_t addr, uint16_t data)
|
||||
flash_program_halfword (uintptr_t addr, uint16_t data)
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -170,7 +172,7 @@ flash_program_halfword (uint32_t addr, uint16_t data)
|
||||
}
|
||||
|
||||
static int
|
||||
flash_erase_page (uint32_t addr)
|
||||
flash_erase_page (uintptr_t addr)
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -210,13 +212,13 @@ flash_check_blank (const uint8_t *p_start, size_t size)
|
||||
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
|
||||
|
||||
static int
|
||||
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
||||
flash_write (uintptr_t dst_addr, const uint8_t *src, size_t len)
|
||||
{
|
||||
int status;
|
||||
#if defined(STM32F103_OVERRIDE_FLASH_SIZE_KB)
|
||||
uint32_t flash_end = FLASH_START_ADDR + STM32F103_OVERRIDE_FLASH_SIZE_KB*1024;
|
||||
uintptr_t flash_end = FLASH_START_ADDR + STM32F103_OVERRIDE_FLASH_SIZE_KB*1024;
|
||||
#else
|
||||
uint32_t flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
|
||||
uintptr_t flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
|
||||
#endif
|
||||
|
||||
if (dst_addr < FLASH_START || dst_addr + len > flash_end)
|
||||
@@ -254,6 +256,9 @@ flash_protect (void)
|
||||
FLASH->OPTKEYR = FLASH_KEY1;
|
||||
FLASH->OPTKEYR = FLASH_KEY2;
|
||||
|
||||
while (!(FLASH->CR & FLASH_CR_OPTWRE))
|
||||
;
|
||||
|
||||
FLASH->CR |= FLASH_CR_OPTER;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
|
||||
@@ -272,11 +277,11 @@ flash_protect (void)
|
||||
static void __attribute__((naked))
|
||||
flash_erase_all_and_exec (void (*entry)(void))
|
||||
{
|
||||
uint32_t addr = FLASH_START;
|
||||
uintptr_t addr = FLASH_START;
|
||||
#if defined(STM32F103_OVERRIDE_FLASH_SIZE_KB)
|
||||
uint32_t end = FLASH_START_ADDR + STM32F103_OVERRIDE_FLASH_SIZE_KB*1024;
|
||||
uintptr_t end = FLASH_START_ADDR + STM32F103_OVERRIDE_FLASH_SIZE_KB*1024;
|
||||
#else
|
||||
uint32_t end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
|
||||
uintptr_t end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
|
||||
#endif
|
||||
uint32_t page_size = 1024;
|
||||
int r;
|
||||
@@ -299,38 +304,10 @@ flash_erase_all_and_exec (void (*entry)(void))
|
||||
for (;;);
|
||||
}
|
||||
|
||||
struct SCB
|
||||
{
|
||||
volatile uint32_t CPUID;
|
||||
volatile uint32_t ICSR;
|
||||
volatile uint32_t VTOR;
|
||||
volatile uint32_t AIRCR;
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t CCR;
|
||||
volatile uint8_t SHP[12];
|
||||
volatile uint32_t SHCSR;
|
||||
volatile uint32_t CFSR;
|
||||
volatile uint32_t HFSR;
|
||||
volatile uint32_t DFSR;
|
||||
volatile uint32_t MMFAR;
|
||||
volatile uint32_t BFAR;
|
||||
volatile uint32_t AFSR;
|
||||
volatile uint32_t PFR[2];
|
||||
volatile uint32_t DFR;
|
||||
volatile uint32_t ADR;
|
||||
volatile uint32_t MMFR[4];
|
||||
volatile uint32_t ISAR[5];
|
||||
};
|
||||
|
||||
#define SCS_BASE (0xE000E000)
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00)
|
||||
static struct SCB *const SCB = (struct SCB *)SCB_BASE;
|
||||
|
||||
#define SYSRESETREQ 0x04
|
||||
static void
|
||||
nvic_system_reset (void)
|
||||
{
|
||||
SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ);
|
||||
SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SCB_AIRCR_SYSRESETREQ);
|
||||
asm volatile ("dsb");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BOARD_ID_CQ_STARM 0xc5480875
|
||||
#define BOARD_ID_FST_01_00 0x613870a9
|
||||
#define BOARD_ID_FST_01 0x696886af
|
||||
#define BOARD_ID_FST_01G 0x8801277f
|
||||
#define BOARD_ID_MAPLE_MINI 0x7a445272
|
||||
#define BOARD_ID_OLIMEX_STM32_H103 0xf92bb594
|
||||
#define BOARD_ID_STBEE_MINI 0x1f341961
|
||||
@@ -21,6 +22,8 @@ extern const uint8_t sys_board_name[];
|
||||
#endif
|
||||
|
||||
typedef void (*handler)(void);
|
||||
typedef void (*nonreturn_handler0)(void)__attribute__((noreturn));
|
||||
typedef void (*nonreturn_handler1)(void *)__attribute__((noreturn));
|
||||
extern handler vector[16];
|
||||
|
||||
static inline const uint8_t *
|
||||
@@ -47,17 +50,17 @@ flash_unlock (void)
|
||||
}
|
||||
|
||||
static inline int
|
||||
flash_program_halfword (uint32_t addr, uint16_t data)
|
||||
flash_program_halfword (uintptr_t addr, uint16_t data)
|
||||
{
|
||||
int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[4];
|
||||
int (*func) (uintptr_t, uint16_t) = (int (*)(uintptr_t, uint16_t))vector[4];
|
||||
|
||||
return (*func) (addr, data);
|
||||
}
|
||||
|
||||
static inline int
|
||||
flash_erase_page (uint32_t addr)
|
||||
flash_erase_page (uintptr_t addr)
|
||||
{
|
||||
int (*func) (uint32_t) = (int (*)(uint32_t))vector[5];
|
||||
int (*func) (uintptr_t) = (int (*)(uintptr_t))vector[5];
|
||||
|
||||
return (*func) (addr);
|
||||
}
|
||||
@@ -71,10 +74,10 @@ flash_check_blank (const uint8_t *p_start, size_t size)
|
||||
}
|
||||
|
||||
static inline int
|
||||
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
||||
flash_write (uintptr_t dst_addr, const uint8_t *src, size_t len)
|
||||
{
|
||||
int (*func) (uint32_t, const uint8_t *, size_t)
|
||||
= (int (*)(uint32_t, const uint8_t *, size_t))vector[7];
|
||||
int (*func) (uintptr_t, const uint8_t *, size_t)
|
||||
= (int (*)(uintptr_t, const uint8_t *, size_t))vector[7];
|
||||
|
||||
return (*func) (dst_addr, src, len);
|
||||
}
|
||||
@@ -90,10 +93,9 @@ flash_protect (void)
|
||||
static inline void __attribute__((noreturn))
|
||||
flash_erase_all_and_exec (void (*entry)(void))
|
||||
{
|
||||
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))vector[9];
|
||||
nonreturn_handler1 func = (nonreturn_handler1) vector[9] ;
|
||||
|
||||
(*func) (entry);
|
||||
for (;;);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -108,10 +110,12 @@ usb_lld_sys_shutdown (void)
|
||||
(*vector[11]) ();
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline void __attribute__((noreturn))
|
||||
nvic_system_reset (void)
|
||||
{
|
||||
(*vector[12]) ();
|
||||
nonreturn_handler0 func = (nonreturn_handler0)vector[12];
|
||||
|
||||
(func) ();
|
||||
}
|
||||
|
||||
#ifdef REQUIRE_CLOCK_GPIO_SETTING_IN_SYS
|
||||
|
||||
@@ -41,6 +41,7 @@ struct endpoint_ctl {
|
||||
};
|
||||
static struct endpoint_ctl ep[16];
|
||||
|
||||
#if 0
|
||||
struct USB_CONF {
|
||||
const uint8_t PERID; /* Peripheral ID register */
|
||||
uint8_t rsvd0[3]; /* */
|
||||
@@ -51,6 +52,7 @@ struct USB_CONF {
|
||||
volatile uint8_t ADDINFO; /* Peripheral Additional Info register */
|
||||
};
|
||||
static struct USB_CONF *const USB_CONF = (struct USB_CONF *)0x40072000;
|
||||
#endif
|
||||
|
||||
struct USB_CTRL0 {
|
||||
volatile uint8_t OTGCTL; /* OTG Control register */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* usb-stm32f103.c - USB driver for STM32F103
|
||||
*
|
||||
* Copyright (C) 2016 Flying Stone Technology
|
||||
* Copyright (C) 2016, 2017 Flying Stone Technology
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Chopstx, a thread library for embedded.
|
||||
@@ -339,7 +339,25 @@ void usb_lld_init (struct usb_dev *dev, uint8_t feature)
|
||||
|
||||
/* Clear Interrupt Status Register, and enable interrupt for USB */
|
||||
st103_set_istr (0);
|
||||
st103_set_cntr (CNTR_CTRM | CNTR_RESETM);
|
||||
|
||||
st103_set_btable ();
|
||||
|
||||
st103_set_cntr (CNTR_CTRM | CNTR_OVRM | CNTR_ERRM
|
||||
| CNTR_WKUPM | CNTR_SUSPM | CNTR_RESETM);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Since stop mode makes PLL, HSI & HES oscillators stop, USB clock is
|
||||
* not supplied in stop mode. Thus, USB wakeup can't occur.
|
||||
*
|
||||
* So, only sleep mode can be supported with USB, which doesn't
|
||||
* require use of EXTI.
|
||||
*/
|
||||
#include "mcu/stm32f103.h"
|
||||
/* Setting of EXTI wakeup event to break stop mode. */
|
||||
EXTI->EMR |= (1 << 18); /* Event mask cleared */
|
||||
EXTI->RTSR |= (1 << 18); /* Rising trigger selection */
|
||||
#endif
|
||||
}
|
||||
|
||||
void usb_lld_prepare_shutdown (void)
|
||||
@@ -367,6 +385,19 @@ usb_lld_event_handler (struct usb_dev *dev)
|
||||
st103_set_istr (CLR_RESET);
|
||||
return USB_MAKE_EV (USB_EVENT_DEVICE_RESET);
|
||||
}
|
||||
else if ((istr_value & ISTR_WKUP))
|
||||
{
|
||||
*CNTR &= ~CNTR_FSUSP;
|
||||
st103_set_istr (CLR_WKUP);
|
||||
return USB_MAKE_EV (USB_EVENT_DEVICE_WAKEUP);
|
||||
}
|
||||
else if ((istr_value & ISTR_SUSP))
|
||||
{
|
||||
*CNTR |= CNTR_FSUSP;
|
||||
st103_set_istr (CLR_SUSP);
|
||||
*CNTR |= CNTR_LPMODE;
|
||||
return USB_MAKE_EV (USB_EVENT_DEVICE_SUSPEND);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((istr_value & ISTR_OVR))
|
||||
@@ -878,7 +909,6 @@ void usb_lld_reset (struct usb_dev *dev, uint8_t feature)
|
||||
{
|
||||
usb_lld_set_configuration (dev, 0);
|
||||
dev->feature = feature;
|
||||
st103_set_btable ();
|
||||
st103_set_daddr (0);
|
||||
}
|
||||
|
||||
|
||||
257
mcu/usb-usbip.c
257
mcu/usb-usbip.c
@@ -51,6 +51,8 @@
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#include "sys.h" /* for debug */
|
||||
|
||||
static pthread_t tid_main;
|
||||
static pthread_t tid_usbip;
|
||||
|
||||
@@ -185,6 +187,7 @@ enum {
|
||||
USB_INTR_DATA_TRANSFER,
|
||||
USB_INTR_RESET,
|
||||
USB_INTR_SUSPEND,
|
||||
USB_INTR_SHUTDOWN
|
||||
};
|
||||
|
||||
struct usb_controller {
|
||||
@@ -304,17 +307,22 @@ hc_handle_control_urb (struct urb *urb)
|
||||
uint16_t remain = urb->len;
|
||||
uint64_t l;
|
||||
|
||||
puts ("hcu 0");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hcu 0");
|
||||
|
||||
usbc_ep0.urb = urb;
|
||||
r = control_setup_transaction (urb);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
puts ("hcu 1");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hcu 1");
|
||||
|
||||
if (urb->dir == USBIP_DIR_OUT)
|
||||
{ /* Output from host to device. */
|
||||
printf ("hcu: %d\n", r);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("hcu: %d\n", r);
|
||||
|
||||
while (r == 0)
|
||||
{
|
||||
if (remain > 64)
|
||||
@@ -340,7 +348,9 @@ hc_handle_control_urb (struct urb *urb)
|
||||
}
|
||||
else
|
||||
{ /* Input from device to host. */
|
||||
puts ("hcu 2");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hcu 2");
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (remain > 64)
|
||||
@@ -353,28 +363,38 @@ hc_handle_control_urb (struct urb *urb)
|
||||
if (r < 0)
|
||||
break;
|
||||
|
||||
puts ("hcu 3");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hcu 3");
|
||||
|
||||
remain -= r;
|
||||
urb->data_p += r;
|
||||
if (r < 64)
|
||||
break;
|
||||
}
|
||||
puts ("hcu 4");
|
||||
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hcu 4");
|
||||
|
||||
if (r >= 0)
|
||||
{
|
||||
puts ("hcu 5");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hcu 5");
|
||||
|
||||
read (usbc_ep0.eventfd, &l, sizeof (l));
|
||||
r = control_read_status_transaction ();
|
||||
if (r >= 0)
|
||||
r = remain;
|
||||
}
|
||||
puts ("hcu 6");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hcu 6");
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
error:
|
||||
fprintf (stderr, "hcu 7 %d\n", r);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("hcu 7 %d\n", r);
|
||||
|
||||
/* recovery. */
|
||||
usbc_ep0.state = USB_STATE_READY;
|
||||
}
|
||||
@@ -393,7 +413,9 @@ hc_handle_control_urb (struct urb *urb)
|
||||
else
|
||||
urb->len = 0;
|
||||
|
||||
printf ("hu-next: %d (%d)\n", urb->len, urb->seq);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("hu-next: %d (%d)\n", urb->len, urb->seq);
|
||||
|
||||
usbc_ep0.urb = NULL;
|
||||
return r;
|
||||
}
|
||||
@@ -436,6 +458,7 @@ usbip_handle_data_urb (struct urb *urb)
|
||||
}
|
||||
|
||||
static int fd;
|
||||
static int shutdown_notify_fd;
|
||||
static pthread_mutex_t fd_mutex;
|
||||
|
||||
static void unlink_urb (struct urb *urb);
|
||||
@@ -452,7 +475,8 @@ usbip_finish_urb (struct urb *urb, int r)
|
||||
memset (&msg_rep, 0, sizeof (msg_rep));
|
||||
msg_rep.len = htonl (urb->len);
|
||||
|
||||
fprintf (stderr, "ufu: %d (%d)\n", r, urb->seq);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("ufu: %d (%d)\n", r, urb->seq);
|
||||
|
||||
if (r < 0)
|
||||
msg_rep.status = htonl (r);
|
||||
@@ -489,7 +513,9 @@ hc_handle_data_urb (struct usb_control *usbc_p)
|
||||
uint16_t count;
|
||||
struct urb *urb = usbc_p->urb;
|
||||
|
||||
puts ("hc_hdu 0");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hc_hdu 0");
|
||||
|
||||
if (urb->remain > 64)
|
||||
count = 64;
|
||||
else
|
||||
@@ -497,7 +523,9 @@ hc_handle_data_urb (struct usb_control *usbc_p)
|
||||
|
||||
if (urb->dir == USBIP_DIR_OUT)
|
||||
{ /* Output from host to device. */
|
||||
puts ("hc_hdu 1");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hc_hdu 1");
|
||||
|
||||
r = write_data_transaction (usbc_p, urb->ep, urb->data_p, count);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -509,14 +537,17 @@ hc_handle_data_urb (struct usb_control *usbc_p)
|
||||
{
|
||||
size_t len = urb->len - urb->remain;
|
||||
|
||||
fprintf (stderr, "->data: %lu\n", len);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("->data: %lu\n", len);
|
||||
|
||||
// successfully finished
|
||||
if (len)
|
||||
{
|
||||
char *s = alloca (len + 1);
|
||||
memcpy (s, urb->data, len);
|
||||
s[len] = 0;
|
||||
fprintf (stderr, " : %s\n", s);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf (" : %s\n", s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -525,7 +556,9 @@ hc_handle_data_urb (struct usb_control *usbc_p)
|
||||
}
|
||||
else
|
||||
{ /* Input from device to host. */
|
||||
puts ("hc_hdu 2");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("hc_hdu 2");
|
||||
|
||||
r = read_data_transaction (usbc_p, urb->ep, urb->data_p, count);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -536,14 +569,17 @@ hc_handle_data_urb (struct usb_control *usbc_p)
|
||||
{
|
||||
size_t len = urb->len - urb->remain;
|
||||
|
||||
fprintf (stderr, "<-data: %lu %d\n", len, r);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("<-data: %lu %d\n", len, r);
|
||||
|
||||
// successfully finished
|
||||
if (len)
|
||||
{
|
||||
char *s = alloca (len + 1);
|
||||
memcpy (s, urb->data, len);
|
||||
s[len] = 0;
|
||||
fprintf (stderr, " : %s\n", s);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf (" : %s\n", s);
|
||||
}
|
||||
urb->len = len;
|
||||
return 0;
|
||||
@@ -652,8 +688,9 @@ usbip_handle_urb (uint32_t seq)
|
||||
urb->remain = urb->len = ntohl (msg_cmd.len);
|
||||
urb->data_p = urb->data;
|
||||
|
||||
printf ("URB: dir=%s, ep=%d, len=%d\n", urb->dir==USBIP_DIR_IN? "IN": "OUT",
|
||||
urb->ep, urb->len);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("URB: dir=%s, ep=%d, len=%d\n", urb->dir==USBIP_DIR_IN? "IN": "OUT",
|
||||
urb->ep, urb->len);
|
||||
|
||||
if (recv (fd, (char *)urb->setup, sizeof (urb->setup), 0) != sizeof (urb->setup))
|
||||
{
|
||||
@@ -663,9 +700,10 @@ usbip_handle_urb (uint32_t seq)
|
||||
}
|
||||
|
||||
if (urb->ep == 0)
|
||||
printf ("URB: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
urb->setup[0], urb->setup[1], urb->setup[2], urb->setup[3],
|
||||
urb->setup[4], urb->setup[5], urb->setup[6], urb->setup[7]);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("URB: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
urb->setup[0], urb->setup[1], urb->setup[2], urb->setup[3],
|
||||
urb->setup[4], urb->setup[5], urb->setup[6], urb->setup[7]);
|
||||
|
||||
if (urb->dir == USBIP_DIR_OUT && urb->len)
|
||||
{
|
||||
@@ -765,7 +803,8 @@ usbip_process_cmd (void)
|
||||
|
||||
if (recv (fd, (char *)&msg, sizeof (msg), 0) != sizeof (msg))
|
||||
{
|
||||
perror ("msg recv");
|
||||
if (errno)
|
||||
perror ("msg recv");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -777,7 +816,9 @@ usbip_process_cmd (void)
|
||||
const char *device_list;
|
||||
size_t device_list_size;
|
||||
|
||||
printf ("Device List\n");
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("Device List\n");
|
||||
|
||||
if (attached)
|
||||
{
|
||||
fprintf (stderr, "REQ list while attached\n");
|
||||
@@ -808,7 +849,9 @@ usbip_process_cmd (void)
|
||||
size_t attach_size;
|
||||
char busid[32];
|
||||
|
||||
printf ("Attach device\n");
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("Attach device\n");
|
||||
|
||||
if (attached)
|
||||
{
|
||||
fprintf (stderr, "REQ attach while attached\n");
|
||||
@@ -828,7 +871,8 @@ usbip_process_cmd (void)
|
||||
if (attach
|
||||
&& (size_t)send (fd, attach, attach_size, 0) == attach_size)
|
||||
{
|
||||
printf ("Attach device!\n");
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("Attach device!\n");
|
||||
attached = 1;
|
||||
pthread_mutex_unlock (&fd_mutex);
|
||||
}
|
||||
@@ -847,7 +891,8 @@ usbip_process_cmd (void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf ("URB SUBMIT! %d\n", msg.seq);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("URB SUBMIT! %d\n", msg.seq);
|
||||
usbip_handle_urb (msg.seq);
|
||||
}
|
||||
else if (msg.cmd == CMD_URB_UNLINK)
|
||||
@@ -908,7 +953,8 @@ usbip_process_cmd (void)
|
||||
if (found)
|
||||
msg_rep.status = htonl(-ECONNRESET);
|
||||
|
||||
printf ("URB UNLINK! %d: %s\n", seq, found?"o":"x");
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("URB UNLINK! %d: %s\n", seq, found?"o":"x");
|
||||
|
||||
pthread_mutex_lock (&fd_mutex);
|
||||
if ((size_t)send (fd, &msg, sizeof (msg), 0) != sizeof (msg))
|
||||
@@ -940,7 +986,9 @@ usbip_ep_ready (struct usb_control *usbc_p)
|
||||
|
||||
if (!usbc_p->urb)
|
||||
{
|
||||
puts ("???usbip_ep_ready");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("???usbip_ep_ready");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -994,6 +1042,9 @@ usbip_run_server (void *arg)
|
||||
const int one = 1;
|
||||
struct pollfd pollfds[16];
|
||||
int i;
|
||||
int r = 0;
|
||||
|
||||
(void)arg;
|
||||
|
||||
pthread_mutex_init (&usbc.mutex, NULL);
|
||||
pthread_cond_init (&usbc.cond, NULL);
|
||||
@@ -1001,7 +1052,6 @@ usbip_run_server (void *arg)
|
||||
pthread_mutex_init (&fd_mutex, NULL);
|
||||
pthread_mutex_init (&urb_mutex, NULL);
|
||||
|
||||
(void)arg;
|
||||
if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
perror ("socket");
|
||||
@@ -1030,9 +1080,7 @@ usbip_run_server (void *arg)
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* FIXME: We don't use this pollstruct as EP0 is handled
|
||||
synchronously. */
|
||||
pollfds[1].fd = usbc_ep0.eventfd;
|
||||
pollfds[1].fd = shutdown_notify_fd;
|
||||
pollfds[1].events = POLLIN;
|
||||
pollfds[1].revents = 0;
|
||||
|
||||
@@ -1052,14 +1100,15 @@ usbip_run_server (void *arg)
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Since EP0 is handled synchronously, we don't poll on
|
||||
* usbc_ep0.eventfd. We poll on socket and shutdown request.
|
||||
*/
|
||||
pollfds[0].fd = fd;
|
||||
pollfds[0].events = POLLIN;
|
||||
pollfds[0].revents = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int r;
|
||||
|
||||
for (i = 1; i < 8; i++)
|
||||
{
|
||||
if (usbc_ep_in[i].urb)
|
||||
@@ -1079,7 +1128,7 @@ usbip_run_server (void *arg)
|
||||
if (poll (pollfds, 16, -1) < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
continue;
|
||||
|
||||
perror ("poll");
|
||||
exit (1);
|
||||
@@ -1088,7 +1137,8 @@ usbip_run_server (void *arg)
|
||||
if ((pollfds[0].revents & POLLNVAL)
|
||||
|| (pollfds[0].revents & POLLERR))
|
||||
{
|
||||
fprintf (stderr, "Error on USBIP client socket: %d\n", pollfds[0].revents);
|
||||
fprintf (stderr, "Error on USBIP client socket: %d\n",
|
||||
pollfds[0].revents);
|
||||
exit (1);
|
||||
}
|
||||
if ((pollfds[0].revents & POLLIN))
|
||||
@@ -1100,6 +1150,20 @@ usbip_run_server (void *arg)
|
||||
goto again;
|
||||
}
|
||||
|
||||
if ((pollfds[1].revents & POLLNVAL)
|
||||
|| (pollfds[1].revents & POLLERR))
|
||||
{
|
||||
fprintf (stderr, "Error on USBIP client socket: %d\n",
|
||||
pollfds[1].revents);
|
||||
exit (1);
|
||||
}
|
||||
if ((pollfds[1].revents & POLLIN))
|
||||
{
|
||||
/* Shutdown request */
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 1; i < 8; i++)
|
||||
{
|
||||
if ((pollfds[i*2].revents & POLLNVAL)
|
||||
@@ -1110,7 +1174,9 @@ usbip_run_server (void *arg)
|
||||
}
|
||||
if ((pollfds[i*2].revents & POLLIN))
|
||||
{
|
||||
puts ("poll in read");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("poll in read");
|
||||
|
||||
usbip_ep_ready (&usbc_ep_in[i]);
|
||||
}
|
||||
|
||||
@@ -1122,15 +1188,49 @@ usbip_run_server (void *arg)
|
||||
}
|
||||
if ((pollfds[i*2+1].revents & POLLIN))
|
||||
{
|
||||
puts ("poll out read");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("poll out read");
|
||||
|
||||
usbip_ep_ready (&usbc_ep_out[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct urb *urb;
|
||||
|
||||
pthread_mutex_lock (&urb_mutex);
|
||||
if ((urb = urb_list))
|
||||
{
|
||||
do
|
||||
{
|
||||
unlink_urb (urb);
|
||||
unlink_urb_ep (urb);
|
||||
free (urb);
|
||||
}
|
||||
while ((urb = urb_list));
|
||||
}
|
||||
pthread_mutex_unlock (&urb_mutex);
|
||||
}
|
||||
|
||||
close (fd);
|
||||
close (sock);
|
||||
exit (0);
|
||||
|
||||
close (shutdown_notify_fd);
|
||||
close (usbc_ep0.eventfd);
|
||||
|
||||
for (i = 1; i < 8; i++)
|
||||
{
|
||||
close (usbc_ep_in[i].eventfd);
|
||||
close (usbc_ep_out[i].eventfd);
|
||||
}
|
||||
|
||||
attached = 0;
|
||||
|
||||
if (r < 0)
|
||||
/* It was detach request from client. */
|
||||
exit (0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1163,7 +1263,8 @@ control_setup_transaction (struct urb *urb)
|
||||
r = -EAGAIN;
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "cst error %d\n", usbc_ep0.state);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("cst error %d\n", usbc_ep0.state);
|
||||
r = -EPIPE;
|
||||
}
|
||||
pthread_mutex_unlock (&usbc_ep0.mutex);
|
||||
@@ -1187,7 +1288,8 @@ control_write_data_transaction (char *buf, uint16_t count)
|
||||
{
|
||||
if (usbc_ep0.len < count)
|
||||
{
|
||||
fprintf (stderr, "*** usbc_ep0.len < count");
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("*** usbc_ep0.len < count");
|
||||
r = -EPIPE;
|
||||
usbc_ep0.state = USB_STATE_STALL;
|
||||
}
|
||||
@@ -1224,9 +1326,12 @@ control_write_status_transaction (void)
|
||||
pthread_mutex_lock (&usbc_ep0.mutex);
|
||||
if (usbc_ep0.state == USB_STATE_READY)
|
||||
{
|
||||
puts ("control_write_status_transaction");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("control_write_status_transaction");
|
||||
|
||||
if (usbc_ep0.len != 0)
|
||||
fprintf (stderr, "*** ACK length %d\n", usbc_ep0.len);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("*** ACK length %d\n", usbc_ep0.len);
|
||||
usbc_ep0.state = USB_STATE_NAK;
|
||||
notify_device (USB_INTR_DATA_TRANSFER, 0, USBIP_DIR_IN);
|
||||
r = 0;
|
||||
@@ -1255,7 +1360,10 @@ control_read_data_transaction (char *buf, uint16_t count)
|
||||
if (usbc_ep0.state == USB_STATE_READY)
|
||||
{
|
||||
if (usbc_ep0.len > count)
|
||||
fprintf (stderr, "***c read: length %d > %d\n", usbc_ep0.len, count);
|
||||
{
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("***c read: length %d > %d\n", usbc_ep0.len, count);
|
||||
}
|
||||
else
|
||||
count = usbc_ep0.len;
|
||||
|
||||
@@ -1337,7 +1445,10 @@ read_data_transaction (struct usb_control *usbc_p,
|
||||
int ep_num, char *buf, uint16_t count)
|
||||
{
|
||||
if (usbc_p->len > count)
|
||||
fprintf (stderr, "*** length %d > %d\n", usbc_p->len, count);
|
||||
{
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("*** length %d > %d\n", usbc_p->len, count);
|
||||
}
|
||||
else
|
||||
count = usbc_p->len;
|
||||
|
||||
@@ -1347,9 +1458,8 @@ read_data_transaction (struct usb_control *usbc_p,
|
||||
return count;
|
||||
}
|
||||
|
||||
void chx_handle_intr (uint32_t irq_num);
|
||||
extern void chx_handle_intr (uint32_t irq_num);
|
||||
|
||||
#define INTR_REQ_USB SIGUSR1
|
||||
|
||||
static void
|
||||
usb_intr (int signum, siginfo_t *siginfo, void *arg)
|
||||
@@ -1384,6 +1494,13 @@ usb_lld_init (struct usb_dev *dev, uint8_t feature)
|
||||
|
||||
pthread_sigmask (SIG_BLOCK, &sigset, NULL);
|
||||
|
||||
shutdown_notify_fd = eventfd (0, EFD_CLOEXEC);
|
||||
if (shutdown_notify_fd < 0)
|
||||
{
|
||||
perror ("eventfd");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_mutex_init (&usbc_ep0.mutex, NULL);
|
||||
usbc_ep0.urb = NULL;
|
||||
usbc_ep0.eventfd = eventfd (0, EFD_CLOEXEC);
|
||||
@@ -1445,12 +1562,14 @@ usb_lld_prepare_shutdown (void)
|
||||
void
|
||||
usb_lld_shutdown (void)
|
||||
{
|
||||
const uint64_t l = 1;
|
||||
|
||||
/*
|
||||
* Stop USBIP server thread.
|
||||
* Tell USBIP server thread about shutdown.
|
||||
*/
|
||||
pthread_cancel (tid_usbip);
|
||||
write (shutdown_notify_fd, &l, sizeof (l));
|
||||
pthread_join (tid_usbip, NULL);
|
||||
/* FIXME: Cancel all URB in the list here. */
|
||||
notify_device (USB_INTR_SHUTDOWN, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1489,6 +1608,11 @@ usb_lld_event_handler (struct usb_dev *dev)
|
||||
return USB_MAKE_EV (handle_setup0 (dev));
|
||||
else if (intr == USB_INTR_DATA_TRANSFER)
|
||||
return usb_handle_transfer (dev, dir, ep_num);
|
||||
else if (intr == USB_INTR_SHUTDOWN)
|
||||
{
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("USB shutdown");
|
||||
}
|
||||
|
||||
return USB_EVENT_OK;
|
||||
}
|
||||
@@ -1902,7 +2026,9 @@ static int handle_in0 (struct usb_dev *dev)
|
||||
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
|
||||
{
|
||||
/* XXX: record the assigned address of this device??? */
|
||||
printf ("Set Address: %d\n", dev->dev_req.value);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("Set Address: %d\n", dev->dev_req.value);
|
||||
|
||||
r = USB_EVENT_DEVICE_ADDRESSED;
|
||||
}
|
||||
else
|
||||
@@ -1917,7 +2043,9 @@ static int handle_in0 (struct usb_dev *dev)
|
||||
}
|
||||
else
|
||||
{
|
||||
puts ("handle_in0 error");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("handle_in0 error");
|
||||
|
||||
dev->state = STALLED;
|
||||
pthread_mutex_lock (&usbc_ep0.mutex);
|
||||
usbc_ep0.state = USB_STATE_STALL;
|
||||
@@ -1955,7 +2083,9 @@ static void handle_out0 (struct usb_dev *dev)
|
||||
* Or else, unexpected state.
|
||||
* STALL the endpoint, until we receive the next SETUP token.
|
||||
*/
|
||||
puts ("handle_out0 error");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("handle_out0 error");
|
||||
|
||||
dev->state = STALLED;
|
||||
pthread_mutex_lock (&usbc_ep0.mutex);
|
||||
usbc_ep0.state = USB_STATE_STALL;
|
||||
@@ -2077,7 +2207,9 @@ usb_lld_current_configuration (struct usb_dev *dev)
|
||||
void
|
||||
usb_lld_ctrl_error (struct usb_dev *dev)
|
||||
{
|
||||
puts ("ctrl_error");
|
||||
if ((debug & DEBUG_USB))
|
||||
puts ("ctrl_error");
|
||||
|
||||
dev->state = STALLED;
|
||||
pthread_mutex_lock (&usbc_ep0.mutex);
|
||||
usbc_ep0.state = USB_STATE_STALL;
|
||||
@@ -2134,7 +2266,9 @@ usb_lld_stall_tx (int ep_num)
|
||||
usbc_p->state = USB_STATE_STALL;
|
||||
notify_hostcontroller (usbc_p);
|
||||
pthread_mutex_unlock (&usbc_p->mutex);
|
||||
printf ("stall tx %d\n", ep_num);
|
||||
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("stall tx %d\n", ep_num);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2146,7 +2280,8 @@ usb_lld_stall_rx (int ep_num)
|
||||
usbc_p->state = USB_STATE_STALL;
|
||||
notify_hostcontroller (usbc_p);
|
||||
pthread_mutex_unlock (&usbc_p->mutex);
|
||||
printf ("stall rx %d\n", ep_num);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("stall rx %d\n", ep_num);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2161,7 +2296,8 @@ usb_lld_rx_enable_buf (int ep_num, void *buf, size_t len)
|
||||
|
||||
notify_hostcontroller (usbc_p);
|
||||
pthread_mutex_unlock (&usbc_p->mutex);
|
||||
printf ("usb_lld_rx_enable_buf: %d\n", ep_num);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("usb_lld_rx_enable_buf: %d\n", ep_num);
|
||||
}
|
||||
|
||||
|
||||
@@ -2176,5 +2312,6 @@ usb_lld_tx_enable_buf (int ep_num, const void *buf, size_t len)
|
||||
usbc_p->len = len;
|
||||
notify_hostcontroller (usbc_p);
|
||||
pthread_mutex_unlock (&usbc_p->mutex);
|
||||
printf ("usb_lld_tx_enable_buf: %d %ld\n", ep_num, len);
|
||||
if ((debug & DEBUG_USB))
|
||||
printf ("usb_lld_tx_enable_buf: %d %ld\n", ep_num, len);
|
||||
}
|
||||
|
||||
9
rules.mk
9
rules.mk
@@ -6,6 +6,12 @@ ifneq ($(USE_EVENTFLAG),)
|
||||
CSRC += $(CHOPSTX)/eventflag.c
|
||||
endif
|
||||
|
||||
ifeq ($(EMULATION),)
|
||||
CSRC += $(CHOPSTX)/mcu/chx-$(CHIP).c
|
||||
else
|
||||
CSRC += $(CHOPSTX)/mcu/chx-gnu-linux.c
|
||||
endif
|
||||
|
||||
ifneq ($(USE_SYS),)
|
||||
CSRC += $(CHOPSTX)/mcu/sys-$(CHIP).c
|
||||
endif
|
||||
@@ -19,6 +25,9 @@ endif
|
||||
ifneq ($(USE_ADC),)
|
||||
CSRC += $(CHOPSTX)/contrib/adc-$(CHIP).c
|
||||
endif
|
||||
ifneq ($(USE_USART),)
|
||||
CSRC += $(CHOPSTX)/contrib/usart-$(CHIP).c
|
||||
endif
|
||||
|
||||
INCDIR += $(CHOPSTX)
|
||||
|
||||
|
||||
4
sys.h
4
sys.h
@@ -1,4 +1,6 @@
|
||||
#if defined(MCU_KINETIS_L)
|
||||
#if defined(GNU_LINUX_EMULATION)
|
||||
#include "mcu/sys-gnu-linux.h"
|
||||
#elif defined(MCU_KINETIS_L)
|
||||
#include "mcu/sys-mkl27z.h"
|
||||
#elif defined(MCU_STM32F0)
|
||||
#include "mcu/sys-stm32f0.h"
|
||||
|
||||
18
usb_lld.h
18
usb_lld.h
@@ -64,6 +64,7 @@ enum {
|
||||
/* Device reset and suspend. */
|
||||
USB_EVENT_DEVICE_RESET,
|
||||
USB_EVENT_DEVICE_SUSPEND,
|
||||
USB_EVENT_DEVICE_WAKEUP,
|
||||
/* Device Requests (Control WRITE Transfer): Standard */
|
||||
USB_EVENT_SET_CONFIGURATION,
|
||||
USB_EVENT_SET_INTERFACE,
|
||||
@@ -83,12 +84,13 @@ enum {
|
||||
};
|
||||
|
||||
enum DEVICE_STATE {
|
||||
UNCONNECTED,
|
||||
ATTACHED,
|
||||
POWERED,
|
||||
SUSPENDED,
|
||||
ADDRESSED,
|
||||
CONFIGURED
|
||||
USB_DEVICE_STATE_UNCONNECTED = 0, /* No USB */
|
||||
USB_DEVICE_STATE_ATTACHED = 1,
|
||||
USB_DEVICE_STATE_POWERED = 2,
|
||||
USB_DEVICE_STATE_DEFAULT = 3,
|
||||
USB_DEVICE_STATE_ADDRESSED = 4,
|
||||
USB_DEVICE_STATE_CONFIGURED = 5,
|
||||
USB_DEVICE_STATE_SUSPEND = 128 /* Or-ed to other states */
|
||||
};
|
||||
|
||||
void usb_lld_init (struct usb_dev *dev, uint8_t feature);
|
||||
@@ -135,12 +137,15 @@ void usb_lld_prepare_shutdown (void);
|
||||
void usb_lld_shutdown (void);
|
||||
|
||||
#if defined(MCU_KINETIS_L)
|
||||
#define INTR_REQ_USB 24
|
||||
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 (struct usb_dev *dev, int ep_num, int rx_en, int tx_en);
|
||||
void usb_lld_stall (int ep_num);
|
||||
#elif defined(GNU_LINUX_EMULATION)
|
||||
#include <signal.h>
|
||||
#define INTR_REQ_USB SIGUSR1
|
||||
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);
|
||||
|
||||
@@ -148,6 +153,7 @@ void usb_lld_setup_endp (struct usb_dev *dev, int ep_num, int rx_en, int tx_en);
|
||||
void usb_lld_stall_tx (int ep_num);
|
||||
void usb_lld_stall_rx (int ep_num);
|
||||
#else
|
||||
#define INTR_REQ_USB 20
|
||||
/* EP_TYPE[1:0] EndPoint TYPE */
|
||||
#define EP_BULK (0x0000) /* EndPoint BULK */
|
||||
#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
|
||||
|
||||
Reference in New Issue
Block a user