Compare commits
44 Commits
release/0.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40adf95c24 | ||
|
|
5a7381ece6 | ||
|
|
52626a3368 | ||
|
|
440188c373 | ||
|
|
a6541cbcc6 | ||
|
|
74c7b5bcb3 | ||
|
|
4d7e97028e | ||
|
|
d061e6f931 | ||
|
|
5f1c26ff17 | ||
|
|
78718e57df | ||
|
|
a756987d2a | ||
|
|
b6e3a1aba1 | ||
|
|
c79a41870a | ||
|
|
4889a5386b | ||
|
|
e02f2e71e6 | ||
|
|
1fa89d1754 | ||
|
|
03a1d46c08 | ||
|
|
3a4e1f2bd5 | ||
|
|
421fd8019b | ||
|
|
e8eaeced77 | ||
|
|
1ae3caf7fc | ||
|
|
a933eebfd5 | ||
|
|
fae4c58d99 | ||
|
|
9f16e5e051 | ||
|
|
b90e58f763 | ||
|
|
8209f38755 | ||
|
|
781ad1847c | ||
|
|
8eb2130664 | ||
|
|
960921f537 | ||
|
|
f2a8b01607 | ||
|
|
890d108114 | ||
|
|
5f57222b73 | ||
|
|
d81767b7c7 | ||
|
|
91823d0fc1 | ||
|
|
51cd47c3b7 | ||
|
|
cf81e7a6dc | ||
|
|
2578fc0f30 | ||
|
|
2704416c38 | ||
|
|
77255b0c1d | ||
|
|
eeb354119c | ||
|
|
72c3d59555 | ||
|
|
8ba91f5db6 | ||
|
|
b6603f6771 | ||
|
|
ee92bb15b3 |
15
AUTHORS
15
AUTHORS
@@ -23,16 +23,21 @@ Mateusz Zalega:
|
|||||||
|
|
||||||
NIIBE Yutaka:
|
NIIBE Yutaka:
|
||||||
Write the library:
|
Write the library:
|
||||||
chopstx.c, eventflag.c, entry.c,
|
chopstx.c, entry.c, eventflag.c,
|
||||||
clk_gpio_init-kl.c, clk_gpio_init-stm32.c
|
|
||||||
chopstx.h, eventflag.h
|
chopstx.h, eventflag.h
|
||||||
|
Write the drivers mcu/*:
|
||||||
|
clk_gpio_init-mkl27z.c, clk_gpio_init-stm32.c,
|
||||||
|
sys-stm32f103.c, sys-stm32f030.c, sys-mkl27z.c,
|
||||||
|
adc-stm32f103.c, adc-mkl27z.c
|
||||||
Draw the logo:
|
Draw the logo:
|
||||||
chopstx.svg, chopstx.png
|
chopstx.svg, chopstx.png
|
||||||
Write examples:
|
Write examples:
|
||||||
example-led, example-cdc, example-fsm-55
|
example-led, example-cdc, example-fsm-55, example-fs-bb48
|
||||||
Write board:
|
Write 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-olimex-stm32-h103.h, board-stm8s-discovery.h
|
||||||
board-cq-starm.h, board-stbee-mini.h, board-stbee.h,
|
board-cq-starm.h, board-stbee-mini.h, board-stbee.h,
|
||||||
|
|
||||||
board-stm32f0-discovery.h, board-fsm-55.h
|
board-stm32f0-discovery.h, board-fsm-55.h,
|
||||||
|
|
||||||
|
board-fs-bb48.h
|
||||||
|
|||||||
165
ChangeLog
165
ChangeLog
@@ -1,3 +1,168 @@
|
|||||||
|
2016-06-16 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* VERSION: 1.0.
|
||||||
|
* doc/chopstx.texi (VERSION): 1.0.
|
||||||
|
|
||||||
|
* board/board-fst-01g.h: New.
|
||||||
|
|
||||||
|
2016-06-15 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* chopstx.c (chopstx_exit): Add "naked" attribute.
|
||||||
|
|
||||||
|
2016-06-14 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* mcu/usb-stm32f103.c (usb_lld_ctrl_recv): Fix the state and make
|
||||||
|
the endpoint 0 RX_VALID.
|
||||||
|
|
||||||
|
2016-06-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* usb_lld.h (USB_EVENT_OK): Rename.
|
||||||
|
* mcu/usb-stm32f103.c: Update.
|
||||||
|
* mcu/usb-mkl27z.c: Likewise.
|
||||||
|
|
||||||
|
* example-cdc/usb-cdc.c: Follow the change of API.
|
||||||
|
* example-fs-bb48/usb-cdc.c: Likewise.
|
||||||
|
|
||||||
|
2016-06-09 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* mcu/usb-stm32f103.c (usb_lld_ctrl_recv): Rename.
|
||||||
|
(usb_lld_ctrl_send): Rename.
|
||||||
|
(usb_lld_ctrl_ack): Rename and let have return value.
|
||||||
|
* mcu/usb-mkl27z.c: Likewise.
|
||||||
|
|
||||||
|
* example-cdc/usb-cdc.c: Follow the change of API.
|
||||||
|
* example-fs-bb48/usb-cdc.c: Likewise.
|
||||||
|
|
||||||
|
2016-06-08 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* mcu/usb-stm32f103.c: Rewrite to be event driven API.
|
||||||
|
* mcu/usb-mkl27z.c: Likewise.
|
||||||
|
|
||||||
|
* example-cdc/usb-cdc.c: Update to new USB API.
|
||||||
|
* example-fs-bb48/usb-cdc.c: Likewise.
|
||||||
|
|
||||||
|
* example-cdc/tty.h: Change tty API to be C string (char*)
|
||||||
|
friendly.
|
||||||
|
* example-fs-bb48/tty.h: Ditto.
|
||||||
|
|
||||||
|
2016-06-02 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* contrib/adc-mkl27z.c: Move from mcu.
|
||||||
|
* contrib/adc-stm32f103.c: Move from mcu.
|
||||||
|
|
||||||
|
* example-led/Makefile (CHIP): Define as stm32f0.
|
||||||
|
|
||||||
|
* mcu/sys-stm32f0.h: Rename from sys-stm32f030.h,
|
||||||
|
as we share it among STM32F030 and STM32F050.
|
||||||
|
* mcu/sys-stm32f0.c: Likewise.
|
||||||
|
|
||||||
|
* board/board-stm32f0-discovery.h (MCU_STM32F0): Define.
|
||||||
|
|
||||||
|
* sys.h: Support STM32F0.
|
||||||
|
|
||||||
|
2016-06-01 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* chopstx.h (chx_fatal): Remove weak attribute from declaration.
|
||||||
|
* chopstx.c (chx_fatal): Add weak attribute to implementation.
|
||||||
|
|
||||||
|
2016-05-31 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* VERSION: 0.12.
|
||||||
|
* doc/chopstx.texi (VERSION): 0.12.
|
||||||
|
|
||||||
|
* sys.h: New.
|
||||||
|
|
||||||
|
* example-cdc, example-fs-bb48: Update.
|
||||||
|
* example-fsm-55, example-led: Update.
|
||||||
|
|
||||||
|
2016-05-30 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* mcu/usb-stm32f103.c (usb_lld_setup_endpoint): Start with
|
||||||
|
EP_RX_NAK.
|
||||||
|
|
||||||
|
* mcu/usb-mkl27z.c (handle_transaction): Handle NAK case.
|
||||||
|
(usb_lld_setup_endp): Rename from usb_lld_setup_endpoint.
|
||||||
|
(usb_lld_rx_enable_buf): Rename from usb_lld_rx_enable.
|
||||||
|
(usb_lld_tx_enable_buf): Rename from usb_lld_tx_enable.
|
||||||
|
|
||||||
|
* mcu/adc-stm32f103.c: New from NeuG.
|
||||||
|
* mcu/stm32f103.h: New from NeuG.
|
||||||
|
|
||||||
|
* example-cdc: Update.
|
||||||
|
|
||||||
|
2016-05-30 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* mcu/adc-mkl27z.c, mcu/sys-mkl27z.c, mcu/usb-mkl27z.c: Moved from
|
||||||
|
example-fs-bb48.
|
||||||
|
|
||||||
|
* mcu/adc-stm32f103.c, mcu/sys-stm32f103.c, mcu/usb-stm32f103.c:
|
||||||
|
Moved from example-cdc.
|
||||||
|
|
||||||
|
2016-05-30 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* example-fs-bb48/sys.c (flash_do_internal, flash_do)
|
||||||
|
(flash_erase_page, flash_program_word): New.
|
||||||
|
* example-fs-bb48/command.c (cmd_fes, cmd_fww): New.
|
||||||
|
|
||||||
|
2016-05-27 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* example-fs-bb48/command.c (cmd_sysinfo): New.
|
||||||
|
* example-fs-bb48/sample.ld: Update.
|
||||||
|
* example-fs-bb48/sys.h: New.
|
||||||
|
Move crc32 functions declarations here.
|
||||||
|
* example-fs-bb48/sys.c: Rename from first-pages.c.
|
||||||
|
Include mcu/clk_gpio_init-kl.c to define clock_init and
|
||||||
|
gpio_init.
|
||||||
|
(set_led): New.
|
||||||
|
(reset): Initialize MSP.
|
||||||
|
(flash_config): Include comparison key.
|
||||||
|
(crc32_init, crc32_u8, crc32_u32): Change the API.
|
||||||
|
Write them in assembler so that the size of functions
|
||||||
|
keep unchanged.
|
||||||
|
(sys_version, sys_board_id, sys_board_name, sys_vector): New.
|
||||||
|
|
||||||
|
2016-05-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* entry.c: Follow the move of clk_gpio_init*.c
|
||||||
|
* example-cdc/sys.c: Likewise.
|
||||||
|
* example-led/sys.c: Likewise. Update to 3.0.
|
||||||
|
* example-primer2/sys.c: Update.
|
||||||
|
|
||||||
|
* mcu/clk_gpio_init-stm32.c: Moved.
|
||||||
|
* mcu/clk_gpio_init-kl.c: Moved.
|
||||||
|
* mcu/kl_sim.h: New (was in example-fs-bb48).
|
||||||
|
|
||||||
|
* example-fs-bb48/adc_kl27z.c: Use DMA0 and DMA1.
|
||||||
|
* example-fs-bb48/adc_kl27z.c (adc_wait_completion): Use only
|
||||||
|
least significant 8-bit (most significant for randomness).
|
||||||
|
* example-fs-bb48/command.c (cmd_adc): Rename from
|
||||||
|
cmd_temperature.
|
||||||
|
|
||||||
|
2016-05-24 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* example-fs-bb48/command.c: New.
|
||||||
|
* example-fs-bb48: Update example CDC device.
|
||||||
|
|
||||||
|
2016-05-23 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* chopst.x (chx_sched) [__ARM_ARCH_6M__]: Maintain PSR.
|
||||||
|
|
||||||
|
2016-05-23 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* chopstx.c (chopstx_poll): Fix a race. Check COUNTER.
|
||||||
|
|
||||||
|
* example-cdc/usb-cdc.c (tty_input_char): Include newline.
|
||||||
|
* example-cdc/sample.c: Handle newline.
|
||||||
|
|
||||||
|
* example-fs-bb48/usb-cdc.c: Update from example-cdc.
|
||||||
|
* example-fs-bb48/tty.h: Likewise.
|
||||||
|
* example-fs-bb48/sample.c: Follow the change.
|
||||||
|
|
||||||
|
2016-05-20 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* chopstx.c (chopstx_usec_wait_var): internal function.
|
||||||
|
(chopstx_wakeup_usec_wait): Remove.
|
||||||
|
|
||||||
2016-05-19 NIIBE Yutaka <gniibe@fsij.org>
|
2016-05-19 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
* VERSION: 0.11.
|
* VERSION: 0.11.
|
||||||
|
|||||||
38
NEWS
38
NEWS
@@ -1,6 +1,44 @@
|
|||||||
NEWS - Noteworthy changes
|
NEWS - Noteworthy changes
|
||||||
|
|
||||||
|
|
||||||
|
* Major changes in Chopstx 1.0
|
||||||
|
|
||||||
|
Released 2016-06-16
|
||||||
|
|
||||||
|
** New USB API
|
||||||
|
Now, USB driver is included in Chopstx. So, it should be good one.
|
||||||
|
It used to be the code which was derived from interrupt driven API
|
||||||
|
with callbacks. It's changed to event driven API, so that a user can
|
||||||
|
do as wish, beyond the restriction of callbacks.
|
||||||
|
|
||||||
|
** New board support: FST-01G
|
||||||
|
FST-01G is a new revision of original FST-01 with fixed pull-up of
|
||||||
|
D+ line.
|
||||||
|
|
||||||
|
|
||||||
|
* Major changes in Chopstx 0.12
|
||||||
|
|
||||||
|
Released 2016-05-31
|
||||||
|
|
||||||
|
** Provide drivers of SYS, USB and ADC
|
||||||
|
Those were only offered as examples, but now, Chopstx provides drivers
|
||||||
|
of SYS, USB, and ADC. Please note that the ADC driver is not for
|
||||||
|
general use (it's specific to NeuG to get noise). To use them, enable
|
||||||
|
variables in Makefile, like following.
|
||||||
|
------------
|
||||||
|
CHIP=stm32f103
|
||||||
|
USE_ADC = yes
|
||||||
|
USE_USB = yes
|
||||||
|
USE_SYS = yes
|
||||||
|
DEFS = -DUSE_SYS3
|
||||||
|
------------
|
||||||
|
|
||||||
|
** Removal of chopstx_usec_wait_var chopstx_wakeup_usec_wait
|
||||||
|
This API was used when we need to wait something with timeout.
|
||||||
|
Now, we have better API with chopstx_poll. Please use chopstx_poll
|
||||||
|
and chopstx_cond_signal.
|
||||||
|
|
||||||
|
|
||||||
* Major changes in Chopstx 0.11
|
* Major changes in Chopstx 0.11
|
||||||
|
|
||||||
Released 2016-05-19
|
Released 2016-05-19
|
||||||
|
|||||||
8
README
8
README
@@ -1,6 +1,6 @@
|
|||||||
Chopstx - Threads and only Threads
|
Chopstx - Threads and only Threads
|
||||||
Version 0.11
|
Version 1.0
|
||||||
2016-05-19
|
2016-06-16
|
||||||
Niibe Yutaka
|
Niibe Yutaka
|
||||||
Flying Stone Technology
|
Flying Stone Technology
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ What's Chopstx?
|
|||||||
===============
|
===============
|
||||||
|
|
||||||
Chopstx is an RT thread library for STM32F103 (ARM Cortex-M3),
|
Chopstx is an RT thread library for STM32F103 (ARM Cortex-M3),
|
||||||
STM32F0 (ARM Cortex-M0), or KL27Z (ARM Cortex-M0plus).
|
STM32F030 (ARM Cortex-M0), and MKL27Z (ARM Cortex-M0plus).
|
||||||
|
|
||||||
While most RTOSes come with many features, drivers, and stacks,
|
While most RTOSes come with many features, drivers, and stacks,
|
||||||
Chopstx just offers a simple RT thread library.
|
Chopstx just offers a simple RT thread library.
|
||||||
@@ -46,7 +46,7 @@ Future Works
|
|||||||
============
|
============
|
||||||
|
|
||||||
Convenience function to determine the bottom of thread stack, thread
|
Convenience function to determine the bottom of thread stack, thread
|
||||||
local storage would be next thing to be done.
|
local storage would be next things to be done.
|
||||||
|
|
||||||
Experimental SMP port for Cortex-A7 is under development. For SMP,
|
Experimental SMP port for Cortex-A7 is under development. For SMP,
|
||||||
more careful considerations for shared access to objects of struct
|
more careful considerations for shared access to objects of struct
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
void adc_init (void);
|
int adc_init (void);
|
||||||
void adc_start (void);
|
void adc_start (void);
|
||||||
void adc_stop (void);
|
void adc_stop (void);
|
||||||
|
|
||||||
extern uint32_t adc_buf[64];
|
extern uint32_t adc_buf[64];
|
||||||
|
|
||||||
void adc_start_conversion (int offset, int count);
|
void adc_start_conversion (int offset, int count);
|
||||||
int adc_wait_completion (chopstx_intr_t *intr);
|
int adc_wait_completion (void);
|
||||||
84
board/board-fst-01g.h
Normal file
84
board/board-fst-01g.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#define BOARD_NAME "FST-01G"
|
||||||
|
#define BOARD_ID 0x8801277f
|
||||||
|
/* echo -n "FST-01G" | sha256sum | sed -e 's/^.*\(........\) -$/\1/' */
|
||||||
|
|
||||||
|
#define STM32F10X_MD /* Medium-density device */
|
||||||
|
|
||||||
|
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||||
|
#define STM32_PLLMUL_VALUE 6
|
||||||
|
#define STM32_HSECLK 12000000
|
||||||
|
|
||||||
|
#define GPIO_LED_BASE GPIOB_BASE
|
||||||
|
#define GPIO_LED_SET_TO_EMIT 0
|
||||||
|
#define GPIO_USB_BASE GPIOA_BASE
|
||||||
|
#undef GPIO_OTHER_BASE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port A setup.
|
||||||
|
* PA0 - input with pull-up (TIM2_CH1): AN0 for NeuG
|
||||||
|
* PA1 - input with pull-down (TIM2_CH2)
|
||||||
|
* PA2 - input with pull-up (TIM2_CH3) connected to CIR module
|
||||||
|
* PA3 - input with pull-up: external pin available to user
|
||||||
|
* PA4 - Push pull output (SPI1_NSS)
|
||||||
|
* PA5 - Alternate Push pull output (SPI1_SCK)
|
||||||
|
* PA6 - Alternate Push pull output (SPI1_MISO)
|
||||||
|
* PA7 - Alternate Push pull output (SPI1_MOSI)
|
||||||
|
* PA10 - Push pull output 1 default
|
||||||
|
* (so that binary for FST-01G also works on FST-01)
|
||||||
|
* PA11 - Push Pull output 10MHz 0 default (until USB enabled) (USBDM)
|
||||||
|
* PA12 - Push Pull output 10MHz 0 default (until USB enabled) (USBDP)
|
||||||
|
* ------------------------ Default
|
||||||
|
* PA8 - input with pull-up.
|
||||||
|
* PA9 - input with pull-up.
|
||||||
|
* PA13 - input with pull-up.
|
||||||
|
* PA14 - input with pull-up.
|
||||||
|
* PA15 - input with pull-up.
|
||||||
|
*/
|
||||||
|
#define VAL_GPIO_USB_ODR 0xFFFFE7FD
|
||||||
|
#define VAL_GPIO_USB_CRL 0xBBB38888 /* PA7...PA0 */
|
||||||
|
#define VAL_GPIO_USB_CRH 0x88811388 /* PA15...PA8 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port B setup.
|
||||||
|
* PB0 - Push pull output (LED 1:ON 0:OFF)
|
||||||
|
* PB1 - input with pull-up: AN9 for NeuG
|
||||||
|
* ------------------------ Default
|
||||||
|
* PBx - input with pull-up.
|
||||||
|
*/
|
||||||
|
#define VAL_GPIO_LED_ODR 0xFFFFFFFF
|
||||||
|
#define VAL_GPIO_LED_CRL 0x88888883 /* PA7...PA0 */
|
||||||
|
#define VAL_GPIO_LED_CRH 0x88888888 /* PA15...PA8 */
|
||||||
|
|
||||||
|
#define RCC_ENR_IOP_EN (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN)
|
||||||
|
#define RCC_RSTR_IOP_RST (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Board specific information other than clock and GPIO initial
|
||||||
|
* setting should not be in board-*.h, but each driver should include
|
||||||
|
* information by itself.
|
||||||
|
*
|
||||||
|
* Please see NeuG's ADC driver how board specific handling is done.
|
||||||
|
*
|
||||||
|
* Given the situation of Chopstx's boards support, which is not that
|
||||||
|
* huge, this works well. If scalability and flexibility will matter,
|
||||||
|
* we will need something like device tree in which boot process can
|
||||||
|
* pass information to application program.
|
||||||
|
*
|
||||||
|
* Following constants are here, because experimental CIR driver is
|
||||||
|
* written before this design decision of Chopstx.
|
||||||
|
*
|
||||||
|
* Those will be removed soon, once such an driver will be improved
|
||||||
|
* in new style.
|
||||||
|
*/
|
||||||
|
/* For pin-cir settings of Gnuk */
|
||||||
|
#define TIMx TIM2
|
||||||
|
#define INTR_REQ_TIM TIM2_IRQ
|
||||||
|
#define AFIO_EXTICR_INDEX 0
|
||||||
|
#define AFIO_EXTICR1_EXTIx_Py AFIO_EXTICR1_EXTI2_PA
|
||||||
|
#define EXTI_PR EXTI_PR_PR2
|
||||||
|
#define EXTI_IMR EXTI_IMR_MR2
|
||||||
|
#define EXTI_FTSR_TR EXTI_FTSR_TR2
|
||||||
|
#define INTR_REQ_EXTI EXTI2_IRQ
|
||||||
|
#define ENABLE_RCC_APB1
|
||||||
|
#define RCC_APBnENR_TIMxEN RCC_APB1ENR_TIM2EN
|
||||||
|
#define RCC_APBnRSTR_TIMxRST RCC_APB1RSTR_TIM2RST
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#define BOARD_NAME "STM32F0 Discovery"
|
#define BOARD_NAME "STM32F0 Discovery"
|
||||||
#define BOARD_ID 0xde4b4bc1
|
#define BOARD_ID 0xde4b4bc1
|
||||||
|
|
||||||
|
#define MCU_STM32F0 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Running at 48MHz with HSI as clock source.
|
* Running at 48MHz with HSI as clock source.
|
||||||
*
|
*
|
||||||
|
|||||||
85
chopstx.c
85
chopstx.c
@@ -208,6 +208,8 @@ chx_prio_init (void)
|
|||||||
| (CPU_EXCEPTION_PRIORITY_PENDSV << 16));
|
| (CPU_EXCEPTION_PRIORITY_PENDSV << 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __attribute__((weak)) chx_fatal (uint32_t err_code);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chx_fatal - Fatal error point.
|
* chx_fatal - Fatal error point.
|
||||||
* @err_code: Error code
|
* @err_code: Error code
|
||||||
@@ -444,8 +446,8 @@ enum {
|
|||||||
THREAD_WAIT_MTX,
|
THREAD_WAIT_MTX,
|
||||||
THREAD_WAIT_CND,
|
THREAD_WAIT_CND,
|
||||||
THREAD_WAIT_TIME,
|
THREAD_WAIT_TIME,
|
||||||
|
THREAD_WAIT_EXIT,
|
||||||
THREAD_WAIT_POLL,
|
THREAD_WAIT_POLL,
|
||||||
THREAD_JOIN,
|
|
||||||
/**/
|
/**/
|
||||||
THREAD_EXITED=0x0E,
|
THREAD_EXITED=0x0E,
|
||||||
THREAD_FINISHED=0x0F
|
THREAD_FINISHED=0x0F
|
||||||
@@ -727,7 +729,7 @@ chx_request_preemption (uint16_t prio)
|
|||||||
* AAPCS: ARM Architecture Procedure Call Standard
|
* AAPCS: ARM Architecture Procedure Call Standard
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* 1 on erroneous wakeup.
|
* 1 on wakeup by others.
|
||||||
* 0 on normal wakeup.
|
* 0 on normal wakeup.
|
||||||
* -1 on cancellation.
|
* -1 on cancellation.
|
||||||
*/
|
*/
|
||||||
@@ -855,11 +857,11 @@ chx_sched (uint32_t yield)
|
|||||||
"lsl r1, r0, #23\n\t"
|
"lsl r1, r0, #23\n\t"
|
||||||
"bcc 2f\n\t"
|
"bcc 2f\n\t"
|
||||||
/**/
|
/**/
|
||||||
"msr APSR_nzcvq, r0\n\t"
|
"ldr r2, [sp, #24]\n\t"
|
||||||
"ldr r0, [sp, #24]\n\t"
|
|
||||||
"mov r1, #1\n\t"
|
"mov r1, #1\n\t"
|
||||||
"orr r0, r1\n\t" /* Ensure Thumb-mode */
|
"orr r2, r1\n\t" /* Ensure Thumb-mode */
|
||||||
"str r0, [sp, #32]\n\t"
|
"str r2, [sp, #32]\n\t"
|
||||||
|
"msr APSR_nzcvq, r0\n\t"
|
||||||
/**/
|
/**/
|
||||||
"ldr r0, [sp, #20]\n\t"
|
"ldr r0, [sp, #20]\n\t"
|
||||||
"mov lr, r0\n\t"
|
"mov lr, r0\n\t"
|
||||||
@@ -869,11 +871,11 @@ chx_sched (uint32_t yield)
|
|||||||
"add sp, #16\n\t"
|
"add sp, #16\n\t"
|
||||||
"pop {pc}\n"
|
"pop {pc}\n"
|
||||||
"2:\n\t"
|
"2:\n\t"
|
||||||
"msr APSR_nzcvq, r0\n\t"
|
"ldr r2, [sp, #24]\n\t"
|
||||||
"ldr r0, [sp, #24]\n\t"
|
|
||||||
"mov r1, #1\n\t"
|
"mov r1, #1\n\t"
|
||||||
"orr r0, r1\n\t" /* Ensure Thumb-mode */
|
"orr r2, r1\n\t" /* Ensure Thumb-mode */
|
||||||
"str r0, [sp, #28]\n\t"
|
"str r2, [sp, #28]\n\t"
|
||||||
|
"msr APSR_nzcvq, r0\n\t"
|
||||||
/**/
|
/**/
|
||||||
"ldr r0, [sp, #20]\n\t"
|
"ldr r0, [sp, #20]\n\t"
|
||||||
"mov lr, r0\n\t"
|
"mov lr, r0\n\t"
|
||||||
@@ -1115,16 +1117,8 @@ chx_snooze (uint32_t state, uint32_t *usec_p)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* chopstx_usec_wait_var - Sleep for micro seconds (specified by variable)
|
static void
|
||||||
* @var: Pointer to usec
|
|
||||||
*
|
|
||||||
* Sleep for micro seconds, specified by @var.
|
|
||||||
* Another thread can clear @var to stop the caller going into sleep.
|
|
||||||
*
|
|
||||||
* This function is DEPRECATED. Please use chopstx_poll.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
chopstx_usec_wait_var (uint32_t *var)
|
chopstx_usec_wait_var (uint32_t *var)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@@ -1199,7 +1193,7 @@ requeue (struct chx_thread *tp)
|
|||||||
chx_spin_unlock (&cond->lock);
|
chx_spin_unlock (&cond->lock);
|
||||||
/* We don't know who can wake up this thread. */
|
/* We don't know who can wake up this thread. */
|
||||||
}
|
}
|
||||||
else if (tp->state == THREAD_JOIN)
|
else if (tp->state == THREAD_WAIT_EXIT)
|
||||||
/* Requeue is not needed as waiting for the thread is only by one. */
|
/* Requeue is not needed as waiting for the thread is only by one. */
|
||||||
return (struct chx_thread *)tp->v;
|
return (struct chx_thread *)tp->v;
|
||||||
|
|
||||||
@@ -1422,11 +1416,11 @@ chx_cond_hook (struct chx_px *px, struct chx_poll_head *pd)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chopstx_claim_irq - Claim interrupt request to handle by this thread
|
* chopstx_claim_irq - Claim interrupt request to handle
|
||||||
* @intr: Pointer to INTR structure
|
* @intr: Pointer to INTR structure
|
||||||
* @irq_num: IRQ Number (hardware specific)
|
* @irq_num: IRQ Number (hardware specific)
|
||||||
*
|
*
|
||||||
* Claim interrupt @intr with @irq_num for this thread.
|
* Claim interrupt @intr with @irq_num
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num)
|
chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num)
|
||||||
@@ -1466,7 +1460,6 @@ chx_intr_hook (struct chx_px *px, struct chx_poll_head *pd)
|
|||||||
*
|
*
|
||||||
* Wait for the interrupt @intr to be occured.
|
* Wait for the interrupt @intr to be occured.
|
||||||
*
|
*
|
||||||
* This function is DEPRECATED. Please use chopstx_poll.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
chopstx_intr_wait (chopstx_intr_t *intr)
|
chopstx_intr_wait (chopstx_intr_t *intr)
|
||||||
@@ -1509,6 +1502,12 @@ chopstx_cleanup_pop (int execute)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We put "naked" attribute to chopstx_exit function. Since it never
|
||||||
|
* returns, function prologue is not needed.
|
||||||
|
*/
|
||||||
|
void chopstx_exit (void *retval) __attribute__ ((naked));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chopstx_exit - Terminate the execution of running thread
|
* chopstx_exit - Terminate the execution of running thread
|
||||||
* @retval: Return value (to be caught by a joining thread)
|
* @retval: Return value (to be caught by a joining thread)
|
||||||
@@ -1581,7 +1580,7 @@ chopstx_join (chopstx_t thd, void **ret)
|
|||||||
chx_spin_lock (&q_join.lock);
|
chx_spin_lock (&q_join.lock);
|
||||||
ll_prio_enqueue ((struct chx_pq *)running, &q_join.q);
|
ll_prio_enqueue ((struct chx_pq *)running, &q_join.q);
|
||||||
running->v = (uint32_t)tp;
|
running->v = (uint32_t)tp;
|
||||||
running->state = THREAD_JOIN;
|
running->state = THREAD_WAIT_EXIT;
|
||||||
tp->flag_join_req = 1;
|
tp->flag_join_req = 1;
|
||||||
|
|
||||||
/* Priority inheritance. */
|
/* Priority inheritance. */
|
||||||
@@ -1647,37 +1646,6 @@ chx_join_hook (struct chx_px *px, struct chx_poll_head *pd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* chopstx_wakeup_usec_wait - wakeup the sleeping thread for timer
|
|
||||||
* @thd: Thread to be awakened
|
|
||||||
*
|
|
||||||
* Canceling the timer, wake up the sleeping thread.
|
|
||||||
* No return value.
|
|
||||||
*
|
|
||||||
* This function is DEPRECATED. Please use chopstx_cond_signal,
|
|
||||||
* where sleeping process calls chopstx_poll.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
chopstx_wakeup_usec_wait (chopstx_t thd)
|
|
||||||
{
|
|
||||||
struct chx_thread *tp = (struct chx_thread *)thd;
|
|
||||||
int yield = 0;
|
|
||||||
|
|
||||||
chx_cpu_sched_lock ();
|
|
||||||
if (tp->state == THREAD_WAIT_TIME)
|
|
||||||
{
|
|
||||||
((struct chx_stack_regs *)tp->tc.reg[REG_SP])->reg[REG_R0] = 1;
|
|
||||||
chx_timer_dequeue (tp);
|
|
||||||
chx_ready_enqueue (tp);
|
|
||||||
if (tp->prio > running->prio)
|
|
||||||
yield = 1;
|
|
||||||
}
|
|
||||||
if (yield)
|
|
||||||
chx_sched (CHX_YIELD);
|
|
||||||
else
|
|
||||||
chx_cpu_sched_unlock ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chopstx_cancel - request a cancellation to a thread
|
* chopstx_cancel - request a cancellation to a thread
|
||||||
* @thd: Thread to be canceled
|
* @thd: Thread to be canceled
|
||||||
@@ -1840,6 +1808,11 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
|
|||||||
{
|
{
|
||||||
chopstx_testcancel ();
|
chopstx_testcancel ();
|
||||||
chx_cpu_sched_lock ();
|
chx_cpu_sched_lock ();
|
||||||
|
if (counter)
|
||||||
|
{
|
||||||
|
chx_cpu_sched_unlock ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
r = chx_snooze (THREAD_WAIT_POLL, usec_p);
|
r = chx_snooze (THREAD_WAIT_POLL, usec_p);
|
||||||
}
|
}
|
||||||
while (r == 0);
|
while (r == 0);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ void chopstx_cond_broadcast (chopstx_cond_t *cond);
|
|||||||
* Library provides default implementation as weak reference.
|
* Library provides default implementation as weak reference.
|
||||||
* User can replace it.
|
* User can replace it.
|
||||||
*/
|
*/
|
||||||
void chx_fatal (uint32_t err_code) __attribute__((__weak__, __noreturn__));
|
void chx_fatal (uint32_t err_code) __attribute__((__noreturn__));
|
||||||
|
|
||||||
int chopstx_join (chopstx_t, void **);
|
int chopstx_join (chopstx_t, void **);
|
||||||
void chopstx_exit (void *retval) __attribute__((__noreturn__));
|
void chopstx_exit (void *retval) __attribute__((__noreturn__));
|
||||||
@@ -113,12 +113,8 @@ typedef struct chx_cleanup {
|
|||||||
void chopstx_cleanup_push (chopstx_cleanup_t *clp);
|
void chopstx_cleanup_push (chopstx_cleanup_t *clp);
|
||||||
void chopstx_cleanup_pop (int execute);
|
void chopstx_cleanup_pop (int execute);
|
||||||
|
|
||||||
|
|
||||||
void chopstx_setpriority (chopstx_prio_t);
|
void chopstx_setpriority (chopstx_prio_t);
|
||||||
|
|
||||||
void chopstx_usec_wait_var (uint32_t *arg); /* DEPRECATED */
|
|
||||||
void chopstx_wakeup_usec_wait (chopstx_t thd); /* DEPRECATED */
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CHOPSTX_POLL_COND = 0,
|
CHOPSTX_POLL_COND = 0,
|
||||||
CHOPSTX_POLL_INTR,
|
CHOPSTX_POLL_INTR,
|
||||||
|
|||||||
320
contrib/adc-mkl27z.c
Normal file
320
contrib/adc-mkl27z.c
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
/*
|
||||||
|
* adc-mkl27z.c - ADC driver for MKL27Z
|
||||||
|
* In this ADC driver, there are NeuG specific parts.
|
||||||
|
* It only records lower 8-bit of 16-bit data.
|
||||||
|
* You need to modify to use this as generic ADC driver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Flying Stone Technology
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* This file is a part of Chopstx, a thread library for embedded.
|
||||||
|
*
|
||||||
|
* Chopstx is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Chopstx is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As additional permission under GNU GPL version 3 section 7, you may
|
||||||
|
* distribute non-source form of the Program without the copy of the
|
||||||
|
* GNU GPL normally required by section 4, provided you inform the
|
||||||
|
* receipents of GNU GPL by a written offer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <chopstx.h>
|
||||||
|
#include <mcu/mkl27z.h>
|
||||||
|
|
||||||
|
struct DMAMUX {
|
||||||
|
volatile uint32_t CHCFG0;
|
||||||
|
volatile uint32_t CHCFG1;
|
||||||
|
volatile uint32_t CHCFG2;
|
||||||
|
volatile uint32_t CHCFG3;
|
||||||
|
};
|
||||||
|
static struct DMAMUX *const DMAMUX = (struct DMAMUX *const)0x40021000;
|
||||||
|
|
||||||
|
#define INTR_REQ_DMA0 0
|
||||||
|
|
||||||
|
struct DMA {
|
||||||
|
volatile uint32_t SAR;
|
||||||
|
volatile uint32_t DAR;
|
||||||
|
volatile uint32_t DSR_BCR;
|
||||||
|
volatile uint32_t DCR;
|
||||||
|
};
|
||||||
|
static struct DMA *const DMA0 = (struct DMA *const)0x40008100;
|
||||||
|
static struct DMA *const DMA1 = (struct DMA *const)0x40008110;
|
||||||
|
|
||||||
|
|
||||||
|
/* We don't use ADC interrupt. Just for reference. */
|
||||||
|
#define INTR_REQ_ADC 15
|
||||||
|
|
||||||
|
struct ADC {
|
||||||
|
volatile uint32_t SC1[2];/* Status and Control Registers 1 */
|
||||||
|
volatile uint32_t CFG1; /* Configuration Register 1 */
|
||||||
|
volatile uint32_t CFG2; /* Configuration Register 2 */
|
||||||
|
volatile uint32_t R[2]; /* Data Result Register */
|
||||||
|
|
||||||
|
/* Compare Value Registers 1, 2 */
|
||||||
|
volatile uint32_t CV1;
|
||||||
|
volatile uint32_t CV2;
|
||||||
|
|
||||||
|
volatile uint32_t SC2; /* Status and Control Register 2 */
|
||||||
|
volatile uint32_t SC3; /* Status and Control Register 3 */
|
||||||
|
|
||||||
|
volatile uint32_t OFS; /* Offset Correction Register */
|
||||||
|
volatile uint32_t PG; /* Plus-Side Gain Register */
|
||||||
|
volatile uint32_t MG; /* Minus-Side Gain Register */
|
||||||
|
|
||||||
|
/* Plus-Side General Calibration Value Registers */
|
||||||
|
volatile uint32_t CLPD;
|
||||||
|
volatile uint32_t CLPS;
|
||||||
|
volatile uint32_t CLP4;
|
||||||
|
volatile uint32_t CLP3;
|
||||||
|
volatile uint32_t CLP2;
|
||||||
|
volatile uint32_t CLP1;
|
||||||
|
volatile uint32_t CLP0;
|
||||||
|
uint32_t rsvd0;
|
||||||
|
/* Minus-Side General Calibration Value Registers */
|
||||||
|
volatile uint32_t CLMD;
|
||||||
|
volatile uint32_t CLMS;
|
||||||
|
volatile uint32_t CLM4;
|
||||||
|
volatile uint32_t CLM3;
|
||||||
|
volatile uint32_t CLM2;
|
||||||
|
volatile uint32_t CLM1;
|
||||||
|
volatile uint32_t CLM0;
|
||||||
|
};
|
||||||
|
static struct ADC *const ADC0 = (struct ADC *const)0x4003B000;
|
||||||
|
|
||||||
|
/* SC1 */
|
||||||
|
#define ADC_SC1_DIFF (1 << 5)
|
||||||
|
#define ADC_SC1_AIEN (1 << 6)
|
||||||
|
#define ADC_SC1_COCO (1 << 7)
|
||||||
|
#define ADC_SC1_TEMPSENSOR 26
|
||||||
|
#define ADC_SC1_BANDGAP 27
|
||||||
|
#define ADC_SC1_ADCSTOP 31
|
||||||
|
|
||||||
|
/* CFG1 */
|
||||||
|
#define ADC_CLOCK_SOURCE_ASYNCH (3 << 0)
|
||||||
|
#define ADC_MODE_16BIT (3 << 2)
|
||||||
|
#define ADC_ADLSMP_SHORT (0 << 4)
|
||||||
|
#define ADC_ADLSMP_LONG (1 << 4)
|
||||||
|
#define ADC_ADIV_1 (0 << 5)
|
||||||
|
#define ADC_ADIV_8 (3 << 5)
|
||||||
|
#define ADC_ADLPC_NORMAL (0 << 7)
|
||||||
|
#define ADC_ADLPC_LOWPOWER (1 << 7)
|
||||||
|
/**/
|
||||||
|
#define ADC_CLOCK_SOURCE ADC_CLOCK_SOURCE_ASYNCH
|
||||||
|
#define ADC_MODE ADC_MODE_16BIT
|
||||||
|
#define ADC_ADLSMP ADC_ADLSMP_SHORT
|
||||||
|
#define ADC_ADIV ADC_ADIV_1
|
||||||
|
#define ADC_ADLPC ADC_ADLPC_LOWPOWER
|
||||||
|
|
||||||
|
/* CFG2 */
|
||||||
|
#define ADC_ADLSTS_DEFAULT 0 /* 24 cycles if CFG1.ADLSMP=1, 4 if not. */
|
||||||
|
#define ADC_ADHSC_NORMAL (0 << 2)
|
||||||
|
#define ADC_ADHSC_HIGHSPEED (1 << 2)
|
||||||
|
#define ADC_ADACK_DISABLE (0 << 3)
|
||||||
|
#define ADC_ADACK_ENABLE (1 << 3)
|
||||||
|
#define ADC_MUXSEL_A (0 << 4)
|
||||||
|
#define ADC_MUXSEL_B (1 << 4)
|
||||||
|
/**/
|
||||||
|
#define ADC_ADLSTS ADC_ADLSTS_DEFAULT
|
||||||
|
#define ADC_ADHSC ADC_ADHSC_NORMAL
|
||||||
|
#define ADC_ADACKEN ADC_ADACK_ENABLE
|
||||||
|
#define ADC_MUXSEL ADC_MUXSEL_A
|
||||||
|
|
||||||
|
/* SC2 */
|
||||||
|
#define ADC_SC2_REFSEL_DEFAULT 1 /* Internal Voltage Reference??? */
|
||||||
|
#define ADC_SC2_DMAEN (1 << 2)
|
||||||
|
#define ADC_SC2_ACREN (1 << 3)
|
||||||
|
#define ADC_SC2_ACFGT (1 << 4)
|
||||||
|
#define ADC_SC2_ACFE (1 << 5)
|
||||||
|
#define ADC_SC2_ADTRG (1 << 6) /* For hardware trigger */
|
||||||
|
|
||||||
|
/* SC3 */
|
||||||
|
#define ADC_SC3_AVGS11 0x03
|
||||||
|
#define ADC_SC3_AVGE (1 << 2)
|
||||||
|
#define ADC_SC3_ADCO (1 << 3)
|
||||||
|
#define ADC_SC3_CALF (1 << 6)
|
||||||
|
#define ADC_SC3_CAL (1 << 7)
|
||||||
|
|
||||||
|
#define ADC_DMA_SLOT_NUM 40
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Buffer to save ADC data.
|
||||||
|
*/
|
||||||
|
uint32_t adc_buf[64];
|
||||||
|
|
||||||
|
static const uint32_t adc0_sc1_setting = ADC_SC1_TEMPSENSOR;
|
||||||
|
|
||||||
|
static chopstx_intr_t adc_intr;
|
||||||
|
|
||||||
|
struct adc_internal {
|
||||||
|
uint32_t buf[64];
|
||||||
|
uint8_t *p;
|
||||||
|
int phase : 8;
|
||||||
|
int count : 8;
|
||||||
|
};
|
||||||
|
struct adc_internal adc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize ADC module, do calibration.
|
||||||
|
*
|
||||||
|
* This is called by MAIN, only once, hopefully before creating any
|
||||||
|
* other threads (to be accurate).
|
||||||
|
*
|
||||||
|
* We configure ADC0 to kick DMA0, configure DMA0 to kick DMA1.
|
||||||
|
* DMA0 records output of ADC0 to the ADC.BUF.
|
||||||
|
* DMA1 kicks ADC0 again to get another value.
|
||||||
|
*
|
||||||
|
* ADC0 --[finish conversion]--> DMA0 --[Link channel 1]--> DMA1
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
adc_init (void)
|
||||||
|
{
|
||||||
|
uint32_t v;
|
||||||
|
|
||||||
|
/* Enable ADC0 and DMAMUX clock. */
|
||||||
|
SIM->SCGC6 |= (1 << 27) | (1 << 1);
|
||||||
|
/* Enable DMA clock. */
|
||||||
|
SIM->SCGC7 |= (1 << 8);
|
||||||
|
|
||||||
|
/* ADC0 setting for calibration. */
|
||||||
|
ADC0->CFG1 = ADC_CLOCK_SOURCE | ADC_MODE | ADC_ADLSMP | ADC_ADIV | ADC_ADLPC;
|
||||||
|
ADC0->CFG2 = ADC_ADLSTS | ADC_ADHSC | ADC_ADACKEN | ADC_MUXSEL;
|
||||||
|
ADC0->SC2 = ADC_SC2_REFSEL_DEFAULT;
|
||||||
|
ADC0->SC3 = ADC_SC3_CAL | ADC_SC3_CALF | ADC_SC3_AVGE | ADC_SC3_AVGS11;
|
||||||
|
|
||||||
|
/* Wait ADC completion */
|
||||||
|
while ((ADC0->SC1[0] & ADC_SC1_COCO) == 0)
|
||||||
|
if ((ADC0->SC3 & ADC_SC3_CALF) != 0)
|
||||||
|
/* Calibration failure */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((ADC0->SC3 & ADC_SC3_CALF) != 0)
|
||||||
|
/* Calibration failure */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Configure PG by the calibration values. */
|
||||||
|
v = ADC0->CLP0 + ADC0->CLP1 + ADC0->CLP2 + ADC0->CLP3 + ADC0->CLP4 + ADC0->CLPS;
|
||||||
|
ADC0->PG = 0x8000 | (v >> 1);
|
||||||
|
|
||||||
|
/* Configure MG by the calibration values. */
|
||||||
|
v = ADC0->CLM0 + ADC0->CLM1 + ADC0->CLM2 + ADC0->CLM3 + ADC0->CLM4 + ADC0->CLMS;
|
||||||
|
ADC0->MG = 0x8000 | (v >> 1);
|
||||||
|
|
||||||
|
ADC0->SC1[0] = ADC_SC1_ADCSTOP;
|
||||||
|
|
||||||
|
/* DMAMUX setting. */
|
||||||
|
DMAMUX->CHCFG0 = (1 << 7) | ADC_DMA_SLOT_NUM;
|
||||||
|
|
||||||
|
/* DMA0 initial setting. */
|
||||||
|
DMA0->SAR = (uint32_t)&ADC0->R[0];
|
||||||
|
|
||||||
|
/* DMA1 initial setting. */
|
||||||
|
DMA1->SAR = (uint32_t)&adc0_sc1_setting;
|
||||||
|
DMA1->DAR = (uint32_t)&ADC0->SC1[0];
|
||||||
|
|
||||||
|
chopstx_claim_irq (&adc_intr, INTR_REQ_DMA0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start using ADC.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
adc_start (void)
|
||||||
|
{
|
||||||
|
ADC0->CFG1 = ADC_CLOCK_SOURCE | ADC_MODE | ADC_ADLSMP | ADC_ADIV | ADC_ADLPC;
|
||||||
|
ADC0->CFG2 = ADC_ADLSTS | ADC_ADHSC | ADC_ADACKEN | ADC_MUXSEL;
|
||||||
|
ADC0->SC2 = ADC_SC2_REFSEL_DEFAULT | ADC_SC2_DMAEN;
|
||||||
|
ADC0->SC3 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kick getting data for COUNT times.
|
||||||
|
* Data will be saved in ADC_BUF starting at OFFSET.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
adc_start_conversion_internal (int count)
|
||||||
|
{
|
||||||
|
/* DMA0 setting. */
|
||||||
|
DMA0->DAR = (uint32_t)&adc.buf[0];
|
||||||
|
DMA0->DSR_BCR = 4 * count;
|
||||||
|
DMA0->DCR = (1 << 31) | (1 << 30) | (1 << 29) | (0 << 20) | (1 << 19)
|
||||||
|
| (0 << 17) | (1 << 7) | (2 << 4) | (1 << 2);
|
||||||
|
|
||||||
|
/* Kick DMA1. */
|
||||||
|
DMA1->DSR_BCR = 4 * count;
|
||||||
|
DMA1->DCR = (1 << 30) | (1 << 29) | (0 << 19) | (0 << 17) | (1 << 16) | (1 << 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kick getting data for COUNT times.
|
||||||
|
* Data will be saved in ADC_BUF starting at OFFSET.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
adc_start_conversion (int offset, int count)
|
||||||
|
{
|
||||||
|
adc.p = (uint8_t *)&adc_buf[offset];
|
||||||
|
adc.phase = 0;
|
||||||
|
adc.count = count;
|
||||||
|
adc_start_conversion_internal (count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
adc_stop_conversion (void)
|
||||||
|
{
|
||||||
|
ADC0->SC1[0] = ADC_SC1_ADCSTOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop using ADC.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
adc_stop (void)
|
||||||
|
{
|
||||||
|
SIM->SCGC6 &= ~(1 << 27);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 0 on success.
|
||||||
|
* Return 1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
adc_wait_completion (void)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Wait DMA completion */
|
||||||
|
chopstx_poll (NULL, 1, &adc_intr);
|
||||||
|
|
||||||
|
DMA0->DSR_BCR = (1 << 24);
|
||||||
|
DMA1->DSR_BCR = (1 << 24);
|
||||||
|
|
||||||
|
adc_stop_conversion ();
|
||||||
|
|
||||||
|
for (i = 0; i < adc.count; i++)
|
||||||
|
*adc.p++ = (uint8_t)adc.buf[i];
|
||||||
|
|
||||||
|
if (++adc.phase >= 4)
|
||||||
|
break;
|
||||||
|
|
||||||
|
adc_start_conversion_internal (adc.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
328
contrib/adc-stm32f103.c
Normal file
328
contrib/adc-stm32f103.c
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
/*
|
||||||
|
* adc_stm32f103.c - ADC driver for STM32F103
|
||||||
|
* 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
|
||||||
|
* Free Software Initiative of Japan
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* This file is a part of Chopstx, a thread library for embedded.
|
||||||
|
*
|
||||||
|
* Chopstx is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Chopstx is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As additional permission under GNU GPL version 3 section 7, you may
|
||||||
|
* distribute non-source form of the Program without the copy of the
|
||||||
|
* GNU GPL normally required by section 4, provided you inform the
|
||||||
|
* receipents of GNU GPL by a written offer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <chopstx.h>
|
||||||
|
#include <mcu/stm32f103.h>
|
||||||
|
#include "adc.h"
|
||||||
|
|
||||||
|
#define STM32_ADC_ADC1_DMA_PRIORITY 2
|
||||||
|
|
||||||
|
#define ADC_SMPR1_SMP_VREF(n) ((n) << 21)
|
||||||
|
#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18)
|
||||||
|
|
||||||
|
#define ADC_SMPR1_SMP_AN10(n) ((n) << 0)
|
||||||
|
#define ADC_SMPR1_SMP_AN11(n) ((n) << 3)
|
||||||
|
|
||||||
|
#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_AN9(n) ((n) << 27)
|
||||||
|
|
||||||
|
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
|
||||||
|
|
||||||
|
#define ADC_SQR3_SQ1_N(n) ((n) << 0)
|
||||||
|
#define ADC_SQR3_SQ2_N(n) ((n) << 5)
|
||||||
|
#define ADC_SQR3_SQ3_N(n) ((n) << 10)
|
||||||
|
#define ADC_SQR3_SQ4_N(n) ((n) << 15)
|
||||||
|
|
||||||
|
#define ADC_SAMPLE_1P5 0
|
||||||
|
|
||||||
|
#define ADC_CHANNEL_IN0 0
|
||||||
|
#define ADC_CHANNEL_IN1 1
|
||||||
|
#define ADC_CHANNEL_IN2 2
|
||||||
|
#define ADC_CHANNEL_IN9 9
|
||||||
|
#define ADC_CHANNEL_IN10 10
|
||||||
|
#define ADC_CHANNEL_IN11 11
|
||||||
|
#define ADC_CHANNEL_SENSOR 16
|
||||||
|
#define ADC_CHANNEL_VREFINT 17
|
||||||
|
|
||||||
|
#define DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
|
||||||
|
#define DELIBARATELY_DO_IT_WRONG_START_STOP
|
||||||
|
|
||||||
|
#ifdef DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
|
||||||
|
#define ADC_SAMPLE_VREF ADC_SAMPLE_1P5
|
||||||
|
#define ADC_SAMPLE_SENSOR ADC_SAMPLE_1P5
|
||||||
|
#else
|
||||||
|
#define ADC_SAMPLE_VREF ADC_SAMPLE_239P5
|
||||||
|
#define ADC_SAMPLE_SENSOR ADC_SAMPLE_239P5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NEUG_DMA_CHANNEL STM32_DMA1_STREAM1
|
||||||
|
#define NEUG_DMA_MODE \
|
||||||
|
( STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY) \
|
||||||
|
| STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD \
|
||||||
|
| STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE \
|
||||||
|
| STM32_DMA_CR_TEIE )
|
||||||
|
|
||||||
|
#define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF) \
|
||||||
|
| ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_SENSOR)
|
||||||
|
#define NEUG_ADC_SETTING1_SMPR2 0
|
||||||
|
#define NEUG_ADC_SETTING1_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT) \
|
||||||
|
| ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR) \
|
||||||
|
| ADC_SQR3_SQ3_N(ADC_CHANNEL_SENSOR) \
|
||||||
|
| ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)
|
||||||
|
#define NEUG_ADC_SETTING1_NUM_CHANNELS 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ADC finish interrupt
|
||||||
|
*/
|
||||||
|
#define INTR_REQ_DMA1_Channel1 11
|
||||||
|
|
||||||
|
static chopstx_intr_t adc_intr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do calibration for both of ADCs.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
adc_init (void)
|
||||||
|
{
|
||||||
|
RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
|
||||||
|
RCC->APB2RSTR = (RCC_APB2RSTR_ADC1RST | RCC_APB2RSTR_ADC2RST);
|
||||||
|
RCC->APB2RSTR = 0;
|
||||||
|
|
||||||
|
ADC1->CR1 = 0;
|
||||||
|
ADC1->CR2 = ADC_CR2_ADON;
|
||||||
|
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
|
||||||
|
while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0)
|
||||||
|
;
|
||||||
|
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
|
||||||
|
while ((ADC1->CR2 & ADC_CR2_CAL) != 0)
|
||||||
|
;
|
||||||
|
ADC1->CR2 = 0;
|
||||||
|
|
||||||
|
ADC2->CR1 = 0;
|
||||||
|
ADC2->CR2 = ADC_CR2_ADON;
|
||||||
|
ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
|
||||||
|
while ((ADC2->CR2 & ADC_CR2_RSTCAL) != 0)
|
||||||
|
;
|
||||||
|
ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
|
||||||
|
while ((ADC2->CR2 & ADC_CR2_CAL) != 0)
|
||||||
|
;
|
||||||
|
ADC2->CR2 = 0;
|
||||||
|
RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
|
||||||
|
|
||||||
|
chopstx_claim_irq (&adc_intr, INTR_REQ_DMA1_Channel1);
|
||||||
|
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_01:
|
||||||
|
config[0] = 0;
|
||||||
|
config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
|
||||||
|
| ADC_SMPR2_SMP_AN9(ADC_SAMPLE_1P5);
|
||||||
|
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
|
||||||
|
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN9);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BOARD_ID_OLIMEX_STM32_H103:
|
||||||
|
case BOARD_ID_STBEE:
|
||||||
|
config[0] = ADC_SMPR1_SMP_AN10(ADC_SAMPLE_1P5)
|
||||||
|
| ADC_SMPR1_SMP_AN11(ADC_SAMPLE_1P5);
|
||||||
|
config[1] = 0;
|
||||||
|
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN10)
|
||||||
|
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN11);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BOARD_ID_STBEE_MINI:
|
||||||
|
config[0] = 0;
|
||||||
|
config[1] = ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
|
||||||
|
| ADC_SMPR2_SMP_AN2(ADC_SAMPLE_1P5);
|
||||||
|
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN1)
|
||||||
|
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN2);
|
||||||
|
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;
|
||||||
|
config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
|
||||||
|
| ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5);
|
||||||
|
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
|
||||||
|
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
adc_start (void)
|
||||||
|
{
|
||||||
|
uint32_t config[4];
|
||||||
|
|
||||||
|
get_adc_config (config);
|
||||||
|
|
||||||
|
/* Use DMA channel 1. */
|
||||||
|
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||||
|
DMA1_Channel1->CCR = STM32_DMA_CCR_RESET_VALUE;
|
||||||
|
DMA1->IFCR = 0xffffffff;
|
||||||
|
|
||||||
|
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
|
||||||
|
| ADC_CR1_SCAN);
|
||||||
|
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
|
||||||
|
ADC2->SMPR1 = config[0];
|
||||||
|
ADC2->SMPR2 = config[1];
|
||||||
|
ADC2->SQR1 = config[2];
|
||||||
|
ADC2->SQR2 = 0;
|
||||||
|
ADC2->SQR3 = config[3];
|
||||||
|
|
||||||
|
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
|
||||||
|
/*
|
||||||
|
* We could just let ADC run continuously always and only enable DMA
|
||||||
|
* to receive stable data from ADC. But our purpose is not to get
|
||||||
|
* correct data but noise. In fact, we can get more noise when we
|
||||||
|
* start/stop ADC each time.
|
||||||
|
*/
|
||||||
|
ADC2->CR2 = 0;
|
||||||
|
ADC1->CR2 = 0;
|
||||||
|
#else
|
||||||
|
/* Start conversion. */
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t adc_buf[64];
|
||||||
|
|
||||||
|
void
|
||||||
|
adc_start_conversion (int offset, int count)
|
||||||
|
{
|
||||||
|
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
|
||||||
|
DMA1_Channel1->CMAR = (uint32_t)&adc_buf[offset]; /* SetMemory0 */
|
||||||
|
DMA1_Channel1->CNDTR = count; /* Counter */
|
||||||
|
DMA1_Channel1->CCR = NEUG_DMA_MODE | DMA_CCR1_EN; /* Mode */
|
||||||
|
|
||||||
|
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
|
||||||
|
/* Power on */
|
||||||
|
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);
|
||||||
|
/*
|
||||||
|
* Start conversion. tSTAB is 1uS, but we don't follow the spec, to
|
||||||
|
* get more noise.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void adc_stop_conversion (void)
|
||||||
|
{
|
||||||
|
DMA1_Channel1->CCR &= ~DMA_CCR1_EN;
|
||||||
|
|
||||||
|
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
|
||||||
|
ADC2->CR2 = 0;
|
||||||
|
ADC1->CR2 = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
adc_stop (void)
|
||||||
|
{
|
||||||
|
ADC1->CR1 = 0;
|
||||||
|
ADC1->CR2 = 0;
|
||||||
|
|
||||||
|
ADC2->CR1 = 0;
|
||||||
|
ADC2->CR2 = 0;
|
||||||
|
|
||||||
|
RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
|
||||||
|
RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t adc_err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 0 on success.
|
||||||
|
* Return 1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
adc_wait_completion (void)
|
||||||
|
{
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
chopstx_poll (NULL, 1, &adc_intr);
|
||||||
|
flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause. */
|
||||||
|
/*
|
||||||
|
* Clear interrupt cause of channel 1.
|
||||||
|
*
|
||||||
|
* Note that CGIFx=0, as CGIFx=1 clears all of GIF, HTIF, TCIF
|
||||||
|
* and TEIF.
|
||||||
|
*/
|
||||||
|
DMA1->IFCR = (flags & ~1);
|
||||||
|
|
||||||
|
if ((flags & STM32_DMA_ISR_TEIF) != 0) /* DMA errors */
|
||||||
|
{
|
||||||
|
/* Should never happened. If any, it's coding error. */
|
||||||
|
/* Access an unmapped address space or alignment violation. */
|
||||||
|
adc_err++;
|
||||||
|
adc_stop_conversion ();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
|
||||||
|
{
|
||||||
|
adc_stop_conversion ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,17 +23,6 @@ stop further execution of code. It never returns.
|
|||||||
Create a thread. Returns thread ID.
|
Create a thread. Returns thread ID.
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
@subheading chopstx_usec_wait_var
|
|
||||||
@anchor{chopstx_usec_wait_var}
|
|
||||||
@deftypefun {void} {chopstx_usec_wait_var} (uint32_t * @var{var})
|
|
||||||
@var{var}: Pointer to usec
|
|
||||||
|
|
||||||
Sleep for micro seconds, specified by @var{var}.
|
|
||||||
Another thread can clear @var{var} to stop the caller going into sleep.
|
|
||||||
|
|
||||||
This function is DEPRECATED. Please use chopstx_poll.
|
|
||||||
@end deftypefun
|
|
||||||
|
|
||||||
@subheading chopstx_usec_wait
|
@subheading chopstx_usec_wait
|
||||||
@anchor{chopstx_usec_wait}
|
@anchor{chopstx_usec_wait}
|
||||||
@deftypefun {void} {chopstx_usec_wait} (uint32_t @var{usec})
|
@deftypefun {void} {chopstx_usec_wait} (uint32_t @var{usec})
|
||||||
@@ -107,7 +96,7 @@ Wake up all threads waiting on @var{cond}.
|
|||||||
|
|
||||||
@var{irq_num}: IRQ Number (hardware specific)
|
@var{irq_num}: IRQ Number (hardware specific)
|
||||||
|
|
||||||
Claim interrupt @var{intr} with @var{irq_num} for this thread.
|
Claim interrupt @var{intr} with @var{irq_num}
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
@subheading chopstx_intr_wait
|
@subheading chopstx_intr_wait
|
||||||
@@ -116,8 +105,6 @@ Claim interrupt @var{intr} with @var{irq_num} for this thread.
|
|||||||
@var{intr}: Pointer to INTR structure
|
@var{intr}: Pointer to INTR structure
|
||||||
|
|
||||||
Wait for the interrupt @var{intr} to be occured.
|
Wait for the interrupt @var{intr} to be occured.
|
||||||
|
|
||||||
This function is DEPRECATED. Please use chopstx_poll.
|
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
@subheading chopstx_cleanup_push
|
@subheading chopstx_cleanup_push
|
||||||
@@ -159,18 +146,6 @@ Waits for the thread of @var{thd} to terminate.
|
|||||||
Returns 0 on success, 1 when waiting is interrupted.
|
Returns 0 on success, 1 when waiting is interrupted.
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
@subheading chopstx_wakeup_usec_wait
|
|
||||||
@anchor{chopstx_wakeup_usec_wait}
|
|
||||||
@deftypefun {void} {chopstx_wakeup_usec_wait} (chopstx_t @var{thd})
|
|
||||||
@var{thd}: Thread to be awakened
|
|
||||||
|
|
||||||
Canceling the timer, wake up the sleeping thread.
|
|
||||||
No return value.
|
|
||||||
|
|
||||||
This function is DEPRECATED. Please use chopstx_cond_signal,
|
|
||||||
where sleeping process calls chopstx_poll.
|
|
||||||
@end deftypefun
|
|
||||||
|
|
||||||
@subheading chopstx_cancel
|
@subheading chopstx_cancel
|
||||||
@anchor{chopstx_cancel}
|
@anchor{chopstx_cancel}
|
||||||
@deftypefun {void} {chopstx_cancel} (chopstx_t @var{thd})
|
@deftypefun {void} {chopstx_cancel} (chopstx_t @var{thd})
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
\input texinfo @c -*-texinfo-*-
|
\input texinfo @c -*-texinfo-*-
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
@setfilename chopstx.info
|
@setfilename chopstx.info
|
||||||
@set VERSION 0.11
|
@set VERSION 1.0
|
||||||
@settitle Chopstx Reference Manual
|
@settitle Chopstx Reference Manual
|
||||||
@c Unify some of the indices.
|
@c Unify some of the indices.
|
||||||
@syncodeindex tp fn
|
@syncodeindex tp fn
|
||||||
@@ -83,8 +83,9 @@ Indexes
|
|||||||
@node Introduction
|
@node Introduction
|
||||||
@chapter Introduction
|
@chapter Introduction
|
||||||
|
|
||||||
Chopstx is an RT thread library for ARM Cortex-M0 and Cortex-M3.
|
Chopstx is an RT thread library for ARM Cortex-M0, Cortex-M0plus and
|
||||||
Specifically, it is used for STM32F030, STM32F103, and KL27Z.
|
Cortex-M3. Specifically, it is used for STM32F030, MKL27Z and
|
||||||
|
STM32F103.
|
||||||
|
|
||||||
While most RTOSes come with many features, drivers, and stacks,
|
While most RTOSes come with many features, drivers, and stacks,
|
||||||
Chopstx just offers a RT thread library.
|
Chopstx just offers a RT thread library.
|
||||||
|
|||||||
17
entry.c
17
entry.c
@@ -31,17 +31,20 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <chopstx.h>
|
#include <chopstx.h>
|
||||||
|
|
||||||
#ifdef HAVE_SYS_H
|
#include "board.h"
|
||||||
#define INLINE __attribute__ ((used))
|
#if defined(USE_SYS3) || defined(USE_SYS_CLOCK_GPIO_SETTING)
|
||||||
|
#define REQUIRE_CLOCK_GPIO_SETTING_IN_SYS
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "board.h"
|
/*
|
||||||
#undef STM32F10X_MD /* Prepare for high density device, too. */
|
* Avoid medium density specific code and prepare for high density
|
||||||
|
* device, too.
|
||||||
|
*/
|
||||||
|
#undef STM32F10X_MD
|
||||||
#else
|
#else
|
||||||
#include "board.h"
|
|
||||||
#if defined (MCU_KINETIS_L)
|
#if defined (MCU_KINETIS_L)
|
||||||
#include "clk_gpio_init-kl.c"
|
#include "mcu/clk_gpio_init-mkl27z.c"
|
||||||
#else
|
#else
|
||||||
#include "clk_gpio_init-stm32.c"
|
#include "mcu/clk_gpio_init-stm32.c"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ PROJECT = sample
|
|||||||
|
|
||||||
CHOPSTX = ..
|
CHOPSTX = ..
|
||||||
LDSCRIPT= sample.ld
|
LDSCRIPT= sample.ld
|
||||||
CSRC = sys.c aes-constant-ft.c sample.c usb-cdc.c usb_stm32f103.c
|
CSRC = sample.c usb-cdc.c
|
||||||
|
|
||||||
|
CHIP=stm32f103
|
||||||
|
|
||||||
|
USE_SYS = yes
|
||||||
|
USE_USB = yes
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
CROSS = arm-none-eabi-
|
CROSS = arm-none-eabi-
|
||||||
@@ -14,7 +19,7 @@ OBJCOPY = $(CROSS)objcopy
|
|||||||
|
|
||||||
MCU = cortex-m3
|
MCU = cortex-m3
|
||||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||||
DEFS = -DHAVE_SYS_H -DFREE_STANDING
|
DEFS = -DUSE_SYS3 -DFREE_STANDING
|
||||||
OPT = -O3 -Os -g
|
OPT = -O3 -Os -g
|
||||||
LIBS =
|
LIBS =
|
||||||
|
|
||||||
|
|||||||
@@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* aes-constant-ft.c - AES forward tables.
|
|
||||||
*
|
|
||||||
* We need something useful for the initial flash ROM page (4 Ki
|
|
||||||
* bytes), which cannot be modified after installation. Even after
|
|
||||||
* upgrade of the firmware, it stays intact.
|
|
||||||
*
|
|
||||||
* We decide to put 3/4 of AES forward tables to fill 3 Ki bytes, as
|
|
||||||
* its useful and it won't change.
|
|
||||||
*
|
|
||||||
* The code was taken from aes.c of PolarSSL version 0.14, and then,
|
|
||||||
* modified to add section names.
|
|
||||||
*
|
|
||||||
* Since this is just a data, it wouldn't be copyright-able, but the
|
|
||||||
* original auther would claim so. Thus, we put original copyright
|
|
||||||
* notice here. It is highly likely that there will be no such a
|
|
||||||
* thing for copyright. Nevertheless, we think that PolarSSL is good
|
|
||||||
* software to address here, and encourage people using it.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Original copyright notice is below:
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIPS-197 compliant AES implementation
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
|
||||||
*
|
|
||||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
|
||||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This program 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 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
|
||||||
*
|
|
||||||
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
|
|
||||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Forward tables
|
|
||||||
*/
|
|
||||||
#define FT \
|
|
||||||
\
|
|
||||||
V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
|
|
||||||
V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
|
|
||||||
V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
|
|
||||||
V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
|
|
||||||
V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
|
|
||||||
V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
|
|
||||||
V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
|
|
||||||
V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
|
|
||||||
V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
|
|
||||||
V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
|
|
||||||
V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
|
|
||||||
V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
|
|
||||||
V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
|
|
||||||
V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
|
|
||||||
V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
|
|
||||||
V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
|
|
||||||
V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
|
|
||||||
V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
|
|
||||||
V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
|
|
||||||
V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
|
|
||||||
V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
|
|
||||||
V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
|
|
||||||
V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
|
|
||||||
V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
|
|
||||||
V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
|
|
||||||
V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
|
|
||||||
V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
|
|
||||||
V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
|
|
||||||
V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
|
|
||||||
V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
|
|
||||||
V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
|
|
||||||
V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
|
|
||||||
V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
|
|
||||||
V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
|
|
||||||
V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
|
|
||||||
V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
|
|
||||||
V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
|
|
||||||
V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
|
|
||||||
V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
|
|
||||||
V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
|
|
||||||
V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
|
|
||||||
V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
|
|
||||||
V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
|
|
||||||
V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
|
|
||||||
V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
|
|
||||||
V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
|
|
||||||
V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
|
|
||||||
V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
|
|
||||||
V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
|
|
||||||
V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
|
|
||||||
V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
|
|
||||||
V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
|
|
||||||
V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
|
|
||||||
V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
|
|
||||||
V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
|
|
||||||
V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
|
|
||||||
V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
|
|
||||||
V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
|
|
||||||
V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
|
|
||||||
V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
|
|
||||||
V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
|
|
||||||
V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
|
|
||||||
V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
|
|
||||||
V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##a##b##c##d
|
|
||||||
const uint32_t FT0[256] __attribute__((section(".sys.0"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##b##c##d##a
|
|
||||||
const uint32_t FT1[256] __attribute__((section(".sys.1"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##c##d##a##b
|
|
||||||
const uint32_t FT2[256] __attribute__((section(".sys.2"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#ifdef ORIGINAL_IMPLEMENTATION
|
|
||||||
#define V(a,b,c,d) 0x##d##a##b##c
|
|
||||||
const uint32_t FT3[256] = { FT };
|
|
||||||
#undef V
|
|
||||||
#endif
|
|
||||||
@@ -3,10 +3,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <chopstx.h>
|
#include <chopstx.h>
|
||||||
|
|
||||||
#include "sys.h" /* for set_led */
|
|
||||||
#include "usb_lld.h"
|
#include "usb_lld.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
|
|
||||||
|
/* For set_led */
|
||||||
|
#include "board.h"
|
||||||
|
#include "sys.h"
|
||||||
|
|
||||||
static chopstx_mutex_t mtx;
|
static chopstx_mutex_t mtx;
|
||||||
static chopstx_cond_t cnd0;
|
static chopstx_cond_t cnd0;
|
||||||
static chopstx_cond_t cnd1;
|
static chopstx_cond_t cnd1;
|
||||||
@@ -114,12 +117,12 @@ main (int argc, const char *argv[])
|
|||||||
m = 50;
|
m = 50;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
uint8_t s[LINEBUFSIZE];
|
char s[LINEBUFSIZE];
|
||||||
|
|
||||||
u = 1;
|
u = 1;
|
||||||
tty_wait_connection (tty);
|
tty_wait_connection (tty);
|
||||||
|
|
||||||
chopstx_usec_wait (500*1000);
|
chopstx_usec_wait (50*1000);
|
||||||
|
|
||||||
/* Send ZLP at the beginning. */
|
/* Send ZLP at the beginning. */
|
||||||
tty_send (tty, s, 0);
|
tty_send (tty, s, 0);
|
||||||
@@ -142,8 +145,10 @@ main (int argc, const char *argv[])
|
|||||||
if (size < 0)
|
if (size < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (usec)
|
if (size)
|
||||||
{
|
{
|
||||||
|
size--;
|
||||||
|
|
||||||
s[0] = hexchar (size >> 4);
|
s[0] = hexchar (size >> 4);
|
||||||
s[1] = hexchar (size & 0x0f);
|
s[1] = hexchar (size & 0x0f);
|
||||||
s[2] = ':';
|
s[2] = ':';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* ST32F103 memory setup.
|
* ST32F103 memory setup.
|
||||||
*/
|
*/
|
||||||
__main_stack_size__ = 0x0100; /* Exception handlers */
|
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||||
__process0_stack_size__ = 0x0400; /* Main program */
|
__process0_stack_size__ = 0x0400; /* Main program */
|
||||||
__process1_stack_size__ = 0x0200; /* first thread program */
|
__process1_stack_size__ = 0x0200; /* first thread program */
|
||||||
__process2_stack_size__ = 0x0200; /* second thread program */
|
__process2_stack_size__ = 0x0200; /* second thread program */
|
||||||
__process3_stack_size__ = 0x0200; /* third thread program */
|
__process3_stack_size__ = 0x0200; /* third thread program */
|
||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
@@ -30,10 +30,10 @@ SECTIONS
|
|||||||
KEEP(*(.sys.version))
|
KEEP(*(.sys.version))
|
||||||
KEEP(*(.sys.board_id))
|
KEEP(*(.sys.board_id))
|
||||||
KEEP(*(.sys.board_name))
|
KEEP(*(.sys.board_name))
|
||||||
build/sys.o(.text)
|
build/sys-*.o(.text)
|
||||||
build/sys.o(.text.*)
|
build/sys-*.o(.text.*)
|
||||||
build/sys.o(.rodata)
|
build/sys-*.o(.rodata)
|
||||||
build/sys.o(.rodata.*)
|
build/sys-*.o(.rodata.*)
|
||||||
. = ALIGN(1024);
|
. = ALIGN(1024);
|
||||||
*(.sys.0)
|
*(.sys.0)
|
||||||
*(.sys.1)
|
*(.sys.1)
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ struct tty;
|
|||||||
struct tty *tty_open (void);
|
struct tty *tty_open (void);
|
||||||
void tty_wait_configured (struct tty *tty);
|
void tty_wait_configured (struct tty *tty);
|
||||||
void tty_wait_connection (struct tty *tty);
|
void tty_wait_connection (struct tty *tty);
|
||||||
int tty_send (struct tty *tty, uint8_t *buf, int count);
|
int tty_send (struct tty *tty, const char *buf, int count);
|
||||||
int tty_recv (struct tty *tty, uint8_t *buf, uint32_t *timeout);
|
int tty_recv (struct tty *tty, char *buf, uint32_t *timeout);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ static const struct line_coding line_coding0 = {
|
|||||||
*
|
*
|
||||||
* In that case, add argument to TTY_OPEN function and
|
* In that case, add argument to TTY_OPEN function and
|
||||||
* modify TTY_GET function to get the TTY structure. Functions which
|
* modify TTY_GET function to get the TTY structure. Functions which
|
||||||
* directy accesses TTY0 (usb_cb_device_reset and usb_cb_handle_event)
|
* directy accesses TTY0 (usb_device_reset and usb_set_configuration)
|
||||||
* should be modified, too.
|
* should be modified, too.
|
||||||
*
|
*
|
||||||
* Modification of TTY_MAIN thread will be also needed to echo back
|
* Modification of TTY_MAIN thread will be also needed to echo back
|
||||||
@@ -234,10 +234,10 @@ static const uint8_t vcom_string3[28] = {
|
|||||||
#define NUM_INTERFACES 2
|
#define NUM_INTERFACES 2
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
usb_cb_device_reset (void)
|
usb_device_reset (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
usb_lld_reset (VCOM_FEATURE_BUS_POWERED);
|
usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
|
||||||
|
|
||||||
/* Initialize Endpoint 0 */
|
/* Initialize Endpoint 0 */
|
||||||
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
|
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
|
||||||
@@ -256,13 +256,15 @@ usb_cb_device_reset (void)
|
|||||||
|
|
||||||
#define CDC_CTRL_DTR 0x0001
|
#define CDC_CTRL_DTR 0x0001
|
||||||
|
|
||||||
void
|
static void
|
||||||
usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
|
usb_ctrl_write_finish (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
|
||||||
|
|
||||||
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
|
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
|
||||||
&& USB_SETUP_SET (req) && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
&& USB_SETUP_SET (arg->type)
|
||||||
|
&& arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||||
{
|
{
|
||||||
struct tty *t = tty_get (arg->index, 0);
|
struct tty *t = tty_get (arg->index, 0);
|
||||||
|
|
||||||
@@ -272,63 +274,74 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
|
|||||||
chopstx_cond_signal (&t->cnd);
|
chopstx_cond_signal (&t->cnd);
|
||||||
chopstx_mutex_unlock (&t->mtx);
|
chopstx_mutex_unlock (&t->mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The transaction was already finished. So, it is no use to call
|
||||||
|
* usb_lld_ctrl_error when the condition does not match.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vcom_port_data_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
|
vcom_port_data_setup (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
if (USB_SETUP_GET (req))
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
|
||||||
|
if (USB_SETUP_GET (arg->type))
|
||||||
{
|
{
|
||||||
struct tty *t = tty_get (arg->index, 0);
|
struct tty *t = tty_get (arg->index, 0);
|
||||||
|
|
||||||
if (req_no == USB_CDC_REQ_GET_LINE_CODING)
|
if (arg->request == USB_CDC_REQ_GET_LINE_CODING)
|
||||||
return usb_lld_reply_request (&t->line_coding,
|
return usb_lld_ctrl_send (dev, &t->line_coding,
|
||||||
sizeof (struct line_coding), arg);
|
sizeof (struct line_coding));
|
||||||
}
|
}
|
||||||
else /* USB_SETUP_SET (req) */
|
else /* USB_SETUP_SET (req) */
|
||||||
{
|
{
|
||||||
if (req_no == USB_CDC_REQ_SET_LINE_CODING
|
if (arg->request == USB_CDC_REQ_SET_LINE_CODING
|
||||||
&& arg->len == sizeof (struct line_coding))
|
&& arg->len == sizeof (struct line_coding))
|
||||||
{
|
{
|
||||||
struct tty *t = tty_get (arg->index, 0);
|
struct tty *t = tty_get (arg->index, 0);
|
||||||
|
|
||||||
usb_lld_set_data_to_recv (&t->line_coding,
|
return usb_lld_ctrl_recv (dev, &t->line_coding,
|
||||||
sizeof (struct line_coding));
|
sizeof (struct line_coding));
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||||
return USB_SUCCESS;
|
return usb_lld_ctrl_ack (dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
|
usb_setup (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
|
||||||
|
|
||||||
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0)
|
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0)
|
||||||
return vcom_port_data_setup (req, req_no, arg);
|
return vcom_port_data_setup (dev);
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
|
usb_get_descriptor (struct usb_dev *dev)
|
||||||
struct req_args *arg)
|
|
||||||
{
|
{
|
||||||
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
uint8_t desc_type = (arg->value >> 8);
|
||||||
|
uint8_t desc_index = (arg->value & 0xff);
|
||||||
|
|
||||||
if (rcp != DEVICE_RECIPIENT)
|
if (rcp != DEVICE_RECIPIENT)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (desc_type == DEVICE_DESCRIPTOR)
|
if (desc_type == DEVICE_DESCRIPTOR)
|
||||||
return usb_lld_reply_request (vcom_device_desc, sizeof (vcom_device_desc),
|
return usb_lld_ctrl_send (dev,
|
||||||
arg);
|
vcom_device_desc, sizeof (vcom_device_desc));
|
||||||
else if (desc_type == CONFIG_DESCRIPTOR)
|
else if (desc_type == CONFIG_DESCRIPTOR)
|
||||||
return usb_lld_reply_request (vcom_config_desc, sizeof (vcom_config_desc),
|
return usb_lld_ctrl_send (dev,
|
||||||
arg);
|
vcom_config_desc, sizeof (vcom_config_desc));
|
||||||
else if (desc_type == STRING_DESCRIPTOR)
|
else if (desc_type == STRING_DESCRIPTOR)
|
||||||
{
|
{
|
||||||
const uint8_t *str;
|
const uint8_t *str;
|
||||||
@@ -353,13 +366,13 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
|
|||||||
size = sizeof (vcom_string3);
|
size = sizeof (vcom_string3);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return usb_lld_reply_request (str, size, arg);
|
return usb_lld_ctrl_send (dev, str, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -378,8 +391,7 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
|
|||||||
{
|
{
|
||||||
usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
|
usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
|
||||||
usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
|
usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
|
||||||
/* Start with no data receiving */
|
/* Start with no data receiving (ENDP3 not enabled)*/
|
||||||
usb_lld_stall_rx (ENDP3);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -389,85 +401,89 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
usb_cb_handle_event (uint8_t event_type, uint16_t value)
|
usb_set_configuration (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint8_t current_conf;
|
uint8_t current_conf;
|
||||||
|
|
||||||
switch (event_type)
|
current_conf = usb_lld_current_configuration (dev);
|
||||||
|
if (current_conf == 0)
|
||||||
{
|
{
|
||||||
case USB_EVENT_ADDRESS:
|
if (dev->dev_req.value != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
usb_lld_set_configuration (dev, 1);
|
||||||
|
for (i = 0; i < NUM_INTERFACES; i++)
|
||||||
|
vcom_setup_endpoints_for_interface (i, 0);
|
||||||
|
chopstx_mutex_lock (&tty0.mtx);
|
||||||
|
tty0.device_state = CONFIGURED;
|
||||||
|
chopstx_cond_signal (&tty0.cnd);
|
||||||
|
chopstx_mutex_unlock (&tty0.mtx);
|
||||||
|
}
|
||||||
|
else if (current_conf != dev->dev_req.value)
|
||||||
|
{
|
||||||
|
if (dev->dev_req.value != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
usb_lld_set_configuration (dev, 0);
|
||||||
|
for (i = 0; i < NUM_INTERFACES; i++)
|
||||||
|
vcom_setup_endpoints_for_interface (i, 1);
|
||||||
chopstx_mutex_lock (&tty0.mtx);
|
chopstx_mutex_lock (&tty0.mtx);
|
||||||
tty0.device_state = ADDRESSED;
|
tty0.device_state = ADDRESSED;
|
||||||
|
chopstx_cond_signal (&tty0.cnd);
|
||||||
chopstx_mutex_unlock (&tty0.mtx);
|
chopstx_mutex_unlock (&tty0.mtx);
|
||||||
return USB_SUCCESS;
|
|
||||||
case USB_EVENT_CONFIG:
|
|
||||||
current_conf = usb_lld_current_configuration ();
|
|
||||||
if (current_conf == 0)
|
|
||||||
{
|
|
||||||
if (value != 1)
|
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
usb_lld_set_configuration (1);
|
|
||||||
for (i = 0; i < NUM_INTERFACES; i++)
|
|
||||||
vcom_setup_endpoints_for_interface (i, 0);
|
|
||||||
chopstx_mutex_lock (&tty0.mtx);
|
|
||||||
tty0.device_state = CONFIGURED;
|
|
||||||
chopstx_mutex_unlock (&tty0.mtx);
|
|
||||||
}
|
|
||||||
else if (current_conf != value)
|
|
||||||
{
|
|
||||||
if (value != 0)
|
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
usb_lld_set_configuration (0);
|
|
||||||
for (i = 0; i < NUM_INTERFACES; i++)
|
|
||||||
vcom_setup_endpoints_for_interface (i, 1);
|
|
||||||
chopstx_mutex_lock (&tty0.mtx);
|
|
||||||
tty0.device_state = ADDRESSED;
|
|
||||||
chopstx_mutex_unlock (&tty0.mtx);
|
|
||||||
}
|
|
||||||
/* Do nothing when current_conf == value */
|
|
||||||
return USB_SUCCESS;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
usb_lld_ctrl_ack (dev);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
usb_cb_interface (uint8_t cmd, struct req_args *arg)
|
usb_set_interface (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
const uint8_t zero = 0;
|
uint16_t interface = dev->dev_req.index;
|
||||||
uint16_t interface = arg->index;
|
uint16_t alt = dev->dev_req.value;
|
||||||
uint16_t alt = arg->value;
|
|
||||||
|
|
||||||
if (interface >= NUM_INTERFACES)
|
if (interface >= NUM_INTERFACES)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
switch (cmd)
|
if (alt != 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
case USB_SET_INTERFACE:
|
vcom_setup_endpoints_for_interface (interface, 0);
|
||||||
if (alt != 0)
|
usb_lld_ctrl_ack (dev);
|
||||||
return USB_UNSUPPORT;
|
return 0;
|
||||||
else
|
|
||||||
{
|
|
||||||
vcom_setup_endpoints_for_interface (interface, 0);
|
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
case USB_GET_INTERFACE:
|
|
||||||
return usb_lld_reply_request (&zero, 1, arg);
|
|
||||||
|
|
||||||
default:
|
|
||||||
case USB_QUERY_INTERFACE:
|
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_get_interface (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
const uint8_t zero = 0;
|
||||||
|
uint16_t interface = dev->dev_req.index;
|
||||||
|
|
||||||
|
if (interface >= NUM_INTERFACES)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* We don't have alternate interface, so, always return 0. */
|
||||||
|
return usb_lld_ctrl_send (dev, &zero, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_get_status_interface (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
const uint16_t status_info = 0;
|
||||||
|
uint16_t interface = dev->dev_req.index;
|
||||||
|
|
||||||
|
if (interface >= NUM_INTERFACES)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return usb_lld_ctrl_send (dev, &status_info, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put a character into the ring buffer to be send back.
|
* Put a character into the ring buffer to be send back.
|
||||||
@@ -516,11 +532,13 @@ tty_echo_char (struct tty *t, int c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
usb_cb_tx_done (uint8_t ep_num)
|
usb_tx_done (uint8_t ep_num, uint16_t len)
|
||||||
{
|
{
|
||||||
struct tty *t = tty_get (-1, ep_num);
|
struct tty *t = tty_get (-1, ep_num);
|
||||||
|
|
||||||
|
(void)len;
|
||||||
|
|
||||||
if (ep_num == ENDP1)
|
if (ep_num == ENDP1)
|
||||||
{
|
{
|
||||||
chopstx_mutex_lock (&t->mtx);
|
chopstx_mutex_lock (&t->mtx);
|
||||||
@@ -549,6 +567,7 @@ tty_input_char (struct tty *t, int c)
|
|||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 0x0d: /* Control-M */
|
case 0x0d: /* Control-M */
|
||||||
|
t->inputline[t->inputline_len++] = '\n';
|
||||||
tty_echo_char (t, 0x0d);
|
tty_echo_char (t, 0x0d);
|
||||||
tty_echo_char (t, 0x0a);
|
tty_echo_char (t, 0x0a);
|
||||||
t->flag_input_avail = 1;
|
t->flag_input_avail = 1;
|
||||||
@@ -582,7 +601,7 @@ tty_input_char (struct tty *t, int c)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (t->inputline_len < sizeof (t->inputline))
|
if (t->inputline_len < sizeof (t->inputline) - 1)
|
||||||
{
|
{
|
||||||
tty_echo_char (t, c);
|
tty_echo_char (t, c);
|
||||||
t->inputline[t->inputline_len++] = c;
|
t->inputline[t->inputline_len++] = c;
|
||||||
@@ -596,19 +615,18 @@ tty_input_char (struct tty *t, int c)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
usb_cb_rx_ready (uint8_t ep_num)
|
usb_rx_ready (uint8_t ep_num, uint16_t len)
|
||||||
{
|
{
|
||||||
uint8_t recv_buf[64];
|
uint8_t recv_buf[64];
|
||||||
struct tty *t = tty_get (-1, ep_num);
|
struct tty *t = tty_get (-1, ep_num);
|
||||||
|
|
||||||
if (ep_num == ENDP3)
|
if (ep_num == ENDP3)
|
||||||
{
|
{
|
||||||
int i, r;
|
int i;
|
||||||
|
|
||||||
r = usb_lld_rx_data_len (ENDP3);
|
usb_lld_rxcpy (recv_buf, ep_num, 0, len);
|
||||||
usb_lld_rxcpy (recv_buf, ep_num, 0, r);
|
for (i = 0; i < len; i++)
|
||||||
for (i = 0; i < r; i++)
|
|
||||||
if (tty_input_char (t, recv_buf[i]))
|
if (tty_input_char (t, recv_buf[i]))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -650,6 +668,8 @@ static void *
|
|||||||
tty_main (void *arg)
|
tty_main (void *arg)
|
||||||
{
|
{
|
||||||
struct tty *t = arg;
|
struct tty *t = arg;
|
||||||
|
struct usb_dev dev;
|
||||||
|
int e;
|
||||||
|
|
||||||
#if defined(OLDER_SYS_H)
|
#if defined(OLDER_SYS_H)
|
||||||
/*
|
/*
|
||||||
@@ -658,9 +678,9 @@ tty_main (void *arg)
|
|||||||
*
|
*
|
||||||
* When USB interrupt occurs between usb_lld_init (which assumes
|
* When USB interrupt occurs between usb_lld_init (which assumes
|
||||||
* ISR) and chopstx_claim_irq (which clears pending interrupt),
|
* ISR) and chopstx_claim_irq (which clears pending interrupt),
|
||||||
* invocation of usb_interrupt_handler won't occur.
|
* invocation of usb_lld_event_handler won't occur.
|
||||||
*
|
*
|
||||||
* Calling usb_interrupt_handler is no harm even if there were no
|
* Calling usb_lld_event_handler is no harm even if there were no
|
||||||
* interrupts, thus, we call it unconditionally here, just in case
|
* interrupts, thus, we call it unconditionally here, just in case
|
||||||
* if there is a request.
|
* if there is a request.
|
||||||
*
|
*
|
||||||
@@ -669,19 +689,114 @@ tty_main (void *arg)
|
|||||||
* chopstx_claim_irq after usb_lld_init overrides that.
|
* chopstx_claim_irq after usb_lld_init overrides that.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
usb_lld_init (VCOM_FEATURE_BUS_POWERED);
|
usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
|
||||||
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
|
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
|
||||||
usb_interrupt_handler ();
|
goto event_handle;
|
||||||
#else
|
#else
|
||||||
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
|
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
|
||||||
usb_lld_init (VCOM_FEATURE_BUS_POWERED);
|
usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
chopstx_poll (NULL, 1, &usb_intr);
|
chopstx_poll (NULL, 1, &usb_intr);
|
||||||
if (usb_intr.ready)
|
if (usb_intr.ready)
|
||||||
usb_interrupt_handler ();
|
{
|
||||||
|
uint8_t ep_num;
|
||||||
|
#if defined(OLDER_SYS_H)
|
||||||
|
event_handle:
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* When interrupt is detected, call usb_lld_event_handler.
|
||||||
|
* The event may be one of following:
|
||||||
|
* (1) Transfer to endpoint (bulk or interrupt)
|
||||||
|
* In this case EP_NUM is encoded in the variable E.
|
||||||
|
* (2) "NONE" event: some trasfer was done, but all was
|
||||||
|
* done by lower layer, no other work is needed in
|
||||||
|
* upper layer.
|
||||||
|
* (3) Device events: Reset or Suspend
|
||||||
|
* (4) Device requests to the endpoint zero.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
e = usb_lld_event_handler (&dev);
|
||||||
|
ep_num = USB_EVENT_ENDP (e);
|
||||||
|
|
||||||
|
if (ep_num != 0)
|
||||||
|
{
|
||||||
|
if (USB_EVENT_TXRX (e))
|
||||||
|
usb_tx_done (ep_num, USB_EVENT_LEN (e));
|
||||||
|
else
|
||||||
|
usb_rx_ready (ep_num, USB_EVENT_LEN (e));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
switch (USB_EVENT_ID (e))
|
||||||
|
{
|
||||||
|
case USB_EVENT_DEVICE_RESET:
|
||||||
|
usb_device_reset (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_DEVICE_ADDRESSED:
|
||||||
|
/* The addres is assigned to the device. We don't
|
||||||
|
* need to do anything for this actually, but in this
|
||||||
|
* application, we maintain the USB status of the
|
||||||
|
* device. Usually, just "continue" as EVENT_OK is
|
||||||
|
* OK.
|
||||||
|
*/
|
||||||
|
chopstx_mutex_lock (&tty0.mtx);
|
||||||
|
tty0.device_state = ADDRESSED;
|
||||||
|
chopstx_cond_signal (&tty0.cnd);
|
||||||
|
chopstx_mutex_unlock (&tty0.mtx);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_GET_DESCRIPTOR:
|
||||||
|
if (usb_get_descriptor (&dev) < 0)
|
||||||
|
usb_lld_ctrl_error (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_SET_CONFIGURATION:
|
||||||
|
if (usb_set_configuration (&dev) < 0)
|
||||||
|
usb_lld_ctrl_error (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_SET_INTERFACE:
|
||||||
|
if (usb_set_interface (&dev) < 0)
|
||||||
|
usb_lld_ctrl_error (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_CTRL_REQUEST:
|
||||||
|
/* Device specific device request. */
|
||||||
|
if (usb_setup (&dev) < 0)
|
||||||
|
usb_lld_ctrl_error (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_GET_STATUS_INTERFACE:
|
||||||
|
if (usb_get_status_interface (&dev) < 0)
|
||||||
|
usb_lld_ctrl_error (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_GET_INTERFACE:
|
||||||
|
if (usb_get_interface (&dev) < 0)
|
||||||
|
usb_lld_ctrl_error (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_SET_FEATURE_DEVICE:
|
||||||
|
case USB_EVENT_SET_FEATURE_ENDPOINT:
|
||||||
|
case USB_EVENT_CLEAR_FEATURE_DEVICE:
|
||||||
|
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
|
||||||
|
usb_lld_ctrl_ack (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_CTRL_WRITE_FINISH:
|
||||||
|
/* Control WRITE transfer finished. */
|
||||||
|
usb_ctrl_write_finish (&dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_OK:
|
||||||
|
case USB_EVENT_DEVICE_SUSPEND:
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
chopstx_mutex_lock (&t->mtx);
|
chopstx_mutex_lock (&t->mtx);
|
||||||
if (t->device_state == CONFIGURED && t->flag_connected
|
if (t->device_state == CONFIGURED && t->flag_connected
|
||||||
@@ -741,10 +856,10 @@ check_tx (struct tty *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tty_send (struct tty *t, uint8_t *buf, int len)
|
tty_send (struct tty *t, const char *buf, int len)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
uint8_t *p;
|
const char *p;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
@@ -792,8 +907,14 @@ check_rx (void *arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns -1 on connection close
|
||||||
|
* 0 on timeout.
|
||||||
|
* >0 length of the inputline (including final \n)
|
||||||
|
*
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
tty_recv (struct tty *t, uint8_t *buf, uint32_t *timeout)
|
tty_recv (struct tty *t, char *buf, uint32_t *timeout)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
chopstx_poll_cond_t poll_desc;
|
chopstx_poll_cond_t poll_desc;
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
#define STANDARD_ENDPOINT_DESC_SIZE 0x09
|
|
||||||
|
|
||||||
/* endpoints enumeration */
|
|
||||||
#define ENDP0 ((uint8_t)0)
|
|
||||||
#define ENDP1 ((uint8_t)1)
|
|
||||||
#define ENDP2 ((uint8_t)2)
|
|
||||||
#define ENDP3 ((uint8_t)3)
|
|
||||||
#define ENDP4 ((uint8_t)4)
|
|
||||||
#define ENDP5 ((uint8_t)5)
|
|
||||||
#define ENDP6 ((uint8_t)6)
|
|
||||||
#define ENDP7 ((uint8_t)7)
|
|
||||||
|
|
||||||
/* EP_TYPE[1:0] EndPoint TYPE */
|
|
||||||
#define EP_BULK (0x0000) /* EndPoint BULK */
|
|
||||||
#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
|
|
||||||
#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
|
|
||||||
#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */
|
|
||||||
|
|
||||||
enum RECIPIENT_TYPE
|
|
||||||
{
|
|
||||||
DEVICE_RECIPIENT = 0, /* Recipient device */
|
|
||||||
INTERFACE_RECIPIENT, /* Recipient interface */
|
|
||||||
ENDPOINT_RECIPIENT, /* Recipient endpoint */
|
|
||||||
OTHER_RECIPIENT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DESCRIPTOR_TYPE
|
|
||||||
{
|
|
||||||
DEVICE_DESCRIPTOR = 1,
|
|
||||||
CONFIG_DESCRIPTOR,
|
|
||||||
STRING_DESCRIPTOR,
|
|
||||||
INTERFACE_DESCRIPTOR,
|
|
||||||
ENDPOINT_DESCRIPTOR
|
|
||||||
};
|
|
||||||
|
|
||||||
#define REQUEST_DIR 0x80 /* Mask to get request dir */
|
|
||||||
#define REQUEST_TYPE 0x60 /* Mask to get request type */
|
|
||||||
#define STANDARD_REQUEST 0x00 /* Standard request */
|
|
||||||
#define CLASS_REQUEST 0x20 /* Class request */
|
|
||||||
#define VENDOR_REQUEST 0x40 /* Vendor request */
|
|
||||||
#define RECIPIENT 0x1F /* Mask to get recipient */
|
|
||||||
|
|
||||||
#define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0)
|
|
||||||
#define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0)
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
USB_UNSUPPORT = 0,
|
|
||||||
USB_SUCCESS = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct req_args {
|
|
||||||
uint16_t value;
|
|
||||||
uint16_t index;
|
|
||||||
uint16_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
void usb_cb_device_reset (void);
|
|
||||||
int usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg);
|
|
||||||
int usb_cb_interface (uint8_t cmd, struct req_args *arg);
|
|
||||||
int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
|
|
||||||
struct req_args *arg);
|
|
||||||
int usb_cb_handle_event (uint8_t event_type, uint16_t value);
|
|
||||||
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
|
|
||||||
struct req_args *arg);
|
|
||||||
void usb_cb_tx_done (uint8_t ep_num);
|
|
||||||
void usb_cb_rx_ready (uint8_t ep_num);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
USB_EVENT_ADDRESS,
|
|
||||||
USB_EVENT_CONFIG,
|
|
||||||
USB_EVENT_SUSPEND,
|
|
||||||
USB_EVENT_WAKEUP,
|
|
||||||
USB_EVENT_STALL,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
USB_SET_INTERFACE,
|
|
||||||
USB_GET_INTERFACE,
|
|
||||||
USB_QUERY_INTERFACE,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DEVICE_STATE
|
|
||||||
{
|
|
||||||
UNCONNECTED,
|
|
||||||
ATTACHED,
|
|
||||||
POWERED,
|
|
||||||
SUSPENDED,
|
|
||||||
ADDRESSED,
|
|
||||||
CONFIGURED
|
|
||||||
};
|
|
||||||
|
|
||||||
void usb_lld_init (uint8_t feature);
|
|
||||||
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
|
|
||||||
void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
|
|
||||||
void usb_lld_stall_tx (int ep_num);
|
|
||||||
void usb_lld_stall_rx (int ep_num);
|
|
||||||
int usb_lld_tx_data_len (int ep_num);
|
|
||||||
void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len);
|
|
||||||
void usb_lld_tx_enable (int ep_num, size_t len);
|
|
||||||
void usb_lld_write (uint8_t ep_num, const void *buf, size_t len);
|
|
||||||
int usb_lld_reply_request (const void *buf, size_t buflen,
|
|
||||||
struct req_args *arg);
|
|
||||||
void usb_lld_rx_enable (int ep_num);
|
|
||||||
int usb_lld_rx_data_len (int ep_num);
|
|
||||||
void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
|
|
||||||
void usb_lld_reset (uint8_t feature);
|
|
||||||
void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
|
|
||||||
int ep_rx_addr, int ep_tx_addr,
|
|
||||||
int ep_rx_memory_size);
|
|
||||||
void usb_lld_set_configuration (uint8_t config);
|
|
||||||
uint8_t usb_lld_current_configuration (void);
|
|
||||||
void usb_lld_set_data_to_recv (void *p, size_t len);
|
|
||||||
|
|
||||||
void usb_lld_prepare_shutdown (void);
|
|
||||||
void usb_lld_shutdown (void);
|
|
||||||
|
|
||||||
void usb_interrupt_handler (void);
|
|
||||||
@@ -6,7 +6,12 @@ PROJECT = sample
|
|||||||
|
|
||||||
CHOPSTX = ..
|
CHOPSTX = ..
|
||||||
LDSCRIPT= sample.ld
|
LDSCRIPT= sample.ld
|
||||||
CSRC = sample.c first-pages.c usb_kl27z.c usb-cdc.c adc_kl27z.c
|
CSRC = sample.c usb-cdc.c command.c
|
||||||
|
CHIP=mkl27z
|
||||||
|
|
||||||
|
USE_SYS = yes
|
||||||
|
USE_USB = yes
|
||||||
|
USE_ADC = yes
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
CROSS = arm-none-eabi-
|
CROSS = arm-none-eabi-
|
||||||
@@ -16,7 +21,7 @@ OBJCOPY = $(CROSS)objcopy
|
|||||||
|
|
||||||
MCU = cortex-m0plus
|
MCU = cortex-m0plus
|
||||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||||
DEFS = -DFREE_STANDING -DMHZ=48
|
DEFS = -DFREE_STANDING -DMHZ=48 -DUSE_SYS3
|
||||||
OPT = -O3 -Os -g
|
OPT = -O3 -Os -g
|
||||||
LIBS =
|
LIBS =
|
||||||
|
|
||||||
|
|||||||
@@ -1,223 +0,0 @@
|
|||||||
/*
|
|
||||||
* adc_kl27z.c - ADC driver for KL27Z
|
|
||||||
* In this ADC driver, there are NeuG specific parts.
|
|
||||||
* You need to modify to use this as generic ADC driver.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2016 Flying Stone Technology
|
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
|
||||||
*
|
|
||||||
* This file is a part of Chopstx, a thread library for embedded.
|
|
||||||
*
|
|
||||||
* Chopstx is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Chopstx is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As additional permission under GNU GPL version 3 section 7, you may
|
|
||||||
* distribute non-source form of the Program without the copy of the
|
|
||||||
* GNU GPL normally required by section 4, provided you inform the
|
|
||||||
* receipents of GNU GPL by a written offer.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <chopstx.h>
|
|
||||||
#include "kl_sim.h"
|
|
||||||
|
|
||||||
#define INTR_REQ_ADC 15
|
|
||||||
|
|
||||||
struct ADC {
|
|
||||||
volatile uint32_t SC1[2];/* Status and Control Registers 1 */
|
|
||||||
volatile uint32_t CFG1; /* Configuration Register 1 */
|
|
||||||
volatile uint32_t CFG2; /* Configuration Register 2 */
|
|
||||||
volatile uint32_t R[2]; /* Data Result Register */
|
|
||||||
|
|
||||||
/* Compare Value Registers 1, 2 */
|
|
||||||
volatile uint32_t CV1;
|
|
||||||
volatile uint32_t CV2;
|
|
||||||
|
|
||||||
volatile uint32_t SC2; /* Status and Control Register 2 */
|
|
||||||
volatile uint32_t SC3; /* Status and Control Register 3 */
|
|
||||||
|
|
||||||
volatile uint32_t OFS; /* Offset Correction Register */
|
|
||||||
volatile uint32_t PG; /* Plus-Side Gain Register */
|
|
||||||
volatile uint32_t MG; /* Minus-Side Gain Register */
|
|
||||||
|
|
||||||
/* Plus-Side General Calibration Value Registers */
|
|
||||||
volatile uint32_t CLPD;
|
|
||||||
volatile uint32_t CLPS;
|
|
||||||
volatile uint32_t CLP4;
|
|
||||||
volatile uint32_t CLP3;
|
|
||||||
volatile uint32_t CLP2;
|
|
||||||
volatile uint32_t CLP1;
|
|
||||||
volatile uint32_t CLP0;
|
|
||||||
uint32_t rsvd0;
|
|
||||||
/* Minus-Side General Calibration Value Registers */
|
|
||||||
volatile uint32_t CLMD;
|
|
||||||
volatile uint32_t CLMS;
|
|
||||||
volatile uint32_t CLM4;
|
|
||||||
volatile uint32_t CLM3;
|
|
||||||
volatile uint32_t CLM2;
|
|
||||||
volatile uint32_t CLM1;
|
|
||||||
volatile uint32_t CLM0;
|
|
||||||
};
|
|
||||||
static struct ADC *const ADC = (struct ADC *const)0x4003B000;
|
|
||||||
|
|
||||||
/* SC1 */
|
|
||||||
#define ADC_SC1_DIFF (1 << 5)
|
|
||||||
#define ADC_SC1_AIEN (1 << 6)
|
|
||||||
#define ADC_SC1_COCO (1 << 7)
|
|
||||||
#define ADC_SC1_TEMPSENSOR 26
|
|
||||||
#define ADC_SC1_BANDGAP 27
|
|
||||||
#define ADC_SC1_ADCSTOP 31
|
|
||||||
|
|
||||||
/* CFG1 */
|
|
||||||
#define ADC_CLOCK_SOURCE_ASYNCH 3
|
|
||||||
#define ADC_RESOLUTION_16BIT 3
|
|
||||||
#define ADC_ADLSMP_SHORT 0
|
|
||||||
#define ADC_ADLSMP_LONG 1
|
|
||||||
#define ADC_ADIV_1 0
|
|
||||||
#define ADC_ADIV_8 3
|
|
||||||
#define ADC_ADLPC_NORMAL 1
|
|
||||||
/**/
|
|
||||||
#define ADC_CLOCK_SOURCE ADC_CLOCK_SOURCE_ASYNCH
|
|
||||||
#define ADC_MODE (ADC_RESOLUTION_16BIT << 2)
|
|
||||||
#define ADC_ADLSMP (ADC_ADLSMP_SHORT << 4)
|
|
||||||
#define ADC_ADIV (ADC_ADIV_8 << 5)
|
|
||||||
#define ADC_ADLPC (ADC_ADLPC_NORMAL << 7)
|
|
||||||
|
|
||||||
/* CFG2 */
|
|
||||||
#define ADC_ADLSTS_DEFAULT 0 /* 24 cycles if CFG1.ADLSMP=1, 4 if not. */
|
|
||||||
#define ADC_ADHSC_NORMAL 0
|
|
||||||
#define ADC_ADHSC_HIGHSPEED 1
|
|
||||||
#define ADC_ADACK_ENABLE 1
|
|
||||||
#define ADC_ADACK_DISABLE 0
|
|
||||||
#define ADC_MUXSEL_A 0
|
|
||||||
#define ADC_MUXSEL_B 1
|
|
||||||
/**/
|
|
||||||
#define ADC_ADLSTS ADC_ADLSTS_DEFAULT
|
|
||||||
#define ADC_ADHSC (ADC_ADHSC_NORMAL << 2)
|
|
||||||
#define ADC_ADACKEN (ADC_ADACK_ENABLE << 3)
|
|
||||||
#define ADC_MUXSEL (ADC_MUXSEL_A << 4)
|
|
||||||
|
|
||||||
/* SC2 */
|
|
||||||
#define ADC_SC2_ADTRG (1 << 6) /* For hardware trigger */
|
|
||||||
#define ADC_SC2_ACFE (1 << 5)
|
|
||||||
#define ADC_SC2_ACFGT (1 << 4)
|
|
||||||
#define ADC_SC2_ACREN (1 << 3)
|
|
||||||
#define ADC_SC2_DMAEN (1 << 2)
|
|
||||||
#define ADC_SC2_REFSEL_DEFAULT 0
|
|
||||||
|
|
||||||
/* SC3 */
|
|
||||||
#define ADC_SC3_CAL (1 << 7)
|
|
||||||
#define ADC_SC3_CALF (1 << 6)
|
|
||||||
#define ADC_SC3_ADCO (1 << 3)
|
|
||||||
#define ADC_SC3_AVGE (1 << 2)
|
|
||||||
#define ADC_SC3_AVGS11 0x03
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize ADC module, do calibration.
|
|
||||||
* This is called by MAIN, only once, before creating any other threads.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
adc_init (void)
|
|
||||||
{
|
|
||||||
uint32_t v;
|
|
||||||
|
|
||||||
/* Enable ADC0 clock. */
|
|
||||||
SIM->SCGC6 |= (1 << 27);
|
|
||||||
|
|
||||||
ADC->CFG1 = ADC_CLOCK_SOURCE | ADC_MODE | ADC_ADLSMP | ADC_ADIV | ADC_ADLPC;
|
|
||||||
ADC->CFG2 = ADC_ADLSTS | ADC_ADHSC | ADC_ADACKEN | ADC_MUXSEL;
|
|
||||||
ADC->SC2 = 0;
|
|
||||||
ADC->SC3 = ADC_SC3_CAL | ADC_SC3_CALF | ADC_SC3_AVGE | ADC_SC3_AVGS11;
|
|
||||||
ADC->SC1[0] = ADC_SC1_TEMPSENSOR;
|
|
||||||
|
|
||||||
/* Wait ADC completion */
|
|
||||||
while ((ADC->SC1[0] & ADC_SC1_COCO) == 0)
|
|
||||||
if ((ADC->SC3 & ADC_SC3_CALF) != 0)
|
|
||||||
/* Calibration failure */
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((ADC->SC3 & ADC_SC3_CALF) != 0)
|
|
||||||
/* Calibration failure */
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Configure PG by the calibration values. */
|
|
||||||
v = ADC->CLP0 + ADC->CLP1 + ADC->CLP2 + ADC->CLP3 + ADC->CLP4 + ADC->CLPS;
|
|
||||||
ADC->PG = 0x8000 | (v >> 1);
|
|
||||||
|
|
||||||
/* Configure MG by the calibration values. */
|
|
||||||
v = ADC->CLM0 + ADC->CLM1 + ADC->CLM2 + ADC->CLM3 + ADC->CLM4 + ADC->CLMS;
|
|
||||||
ADC->MG = 0x8000 | (v >> 1);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start using ADC.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
adc_start (void)
|
|
||||||
{
|
|
||||||
ADC->CFG1 = ADC_CLOCK_SOURCE | ADC_MODE | ADC_ADLSMP | ADC_ADIV | ADC_ADLPC;
|
|
||||||
ADC->CFG2 = ADC_ADLSTS | ADC_ADHSC | ADC_ADACKEN | ADC_MUXSEL;
|
|
||||||
ADC->SC2 = 0;
|
|
||||||
ADC->SC3 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Buffer to save ADC data.
|
|
||||||
*/
|
|
||||||
uint32_t adc_buf[64];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Kick getting data for COUNT times.
|
|
||||||
* Data will be saved in ADC_BUF starting at OFFSET.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
adc_start_conversion (int offset, int count)
|
|
||||||
{
|
|
||||||
ADC->SC1[0] = /*ADC_SC1_AIEN*/0 | ADC_SC1_TEMPSENSOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
adc_stop_conversion (void)
|
|
||||||
{
|
|
||||||
ADC->SC1[0] = ADC_SC1_ADCSTOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stop using ADC.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
adc_stop (void)
|
|
||||||
{
|
|
||||||
SIM->SCGC6 &= ~(1 << 27);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return 0 on success.
|
|
||||||
* Return 1 on error.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
adc_wait_completion (chopstx_intr_t *intr)
|
|
||||||
{
|
|
||||||
/* Wait ADC completion */
|
|
||||||
while ((ADC->SC1[0] & ADC_SC1_COCO) == 0)
|
|
||||||
;
|
|
||||||
|
|
||||||
adc_buf[0] = ADC->R[0];
|
|
||||||
adc_stop_conversion ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
479
example-fs-bb48/command.c
Normal file
479
example-fs-bb48/command.c
Normal file
@@ -0,0 +1,479 @@
|
|||||||
|
#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 =
|
||||||
|
"mdw ADDR [COUNT]; memory display word\r\n"
|
||||||
|
"mww ADDR VALUE [COUNT]; memory write word\r\n"
|
||||||
|
"fes ADDR [COUNT]; flash erase sector\r\n"
|
||||||
|
"fww ADDR VALUE [COUNT]; flash write word\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 ENABLE_DECIMAL_OUTPUT
|
||||||
|
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
|
||||||
|
|
||||||
|
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 const char *
|
||||||
|
get_hex (struct tty *tty, const char *s, uint32_t *v_p)
|
||||||
|
{
|
||||||
|
uint32_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_mdw (struct tty *tty, const char *line)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_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, "mdw error\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < count)
|
||||||
|
{
|
||||||
|
uint32_t v;
|
||||||
|
char output[48];
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
s = compose_hex (output, addr);
|
||||||
|
*s++ = ':';
|
||||||
|
*s++ = ' ';
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
v = *(uint32_t *)addr;
|
||||||
|
s = compose_hex (s, v);
|
||||||
|
i++;
|
||||||
|
addr += 4;
|
||||||
|
if (i >= count || (i % 4) == 0)
|
||||||
|
break;
|
||||||
|
*s++ = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
*s++ = '\r';
|
||||||
|
*s++ = '\n';
|
||||||
|
tty_send (tty, output, s - output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_mww (struct tty *tty, const char *line)
|
||||||
|
{
|
||||||
|
(void)tty;
|
||||||
|
(void)line;
|
||||||
|
put_line (tty, "mww not yet supported\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_fes (struct tty *tty, const char *line)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_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_fww (struct tty *tty, const char *line)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t addr = 0;
|
||||||
|
uint32_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, &value);
|
||||||
|
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_word (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[] = {
|
||||||
|
{ "mdw", cmd_mdw },
|
||||||
|
{ "mww", cmd_mww },
|
||||||
|
{ "fes", cmd_fes },
|
||||||
|
{ "fww", cmd_fww },
|
||||||
|
#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));
|
||||||
|
}
|
||||||
|
}
|
||||||
1
example-fs-bb48/command.h
Normal file
1
example-fs-bb48/command.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
void cmd_dispatch (struct tty *tty, const char *line);
|
||||||
2
example-fs-bb48/config.h
Normal file
2
example-fs-bb48/config.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define CRC32_SUPPORT
|
||||||
|
#define ADC_SUPPORT
|
||||||
22
example-fs-bb48/crc32.c
Normal file
22
example-fs-bb48/crc32.c
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
const unsigned int *const crc32_table= (const unsigned int *const)0x00000480;
|
||||||
|
|
||||||
|
void
|
||||||
|
crc32_init (unsigned int *p)
|
||||||
|
{
|
||||||
|
*p = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
crc32_u8 (unsigned int *p, unsigned char v)
|
||||||
|
{
|
||||||
|
*p = crc32_table[(*p & 0xff) ^ v] ^ (*p >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
crc32_u32 (unsigned int *p, unsigned int u)
|
||||||
|
{
|
||||||
|
crc32_u8 (p, u & 0xff);
|
||||||
|
crc32_u8 (p, (u >> 8)& 0xff);
|
||||||
|
crc32_u8 (p, (u >> 16)& 0xff);
|
||||||
|
crc32_u8 (p, (u >> 24)& 0xff);
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
void crc32_init (void);
|
|
||||||
void crc32_u8 (unsigned char);
|
|
||||||
void crc32_u32 (unsigned int);
|
|
||||||
|
|
||||||
unsigned int crc32_value (void);
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
* first-pages.c - First pages for MKL27Z256.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2016 Flying Stone Technology
|
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
|
||||||
*
|
|
||||||
* Copying and distribution of this file, with or without modification,
|
|
||||||
* are permitted in any medium without royalty provided the copyright
|
|
||||||
* notice and this notice are preserved. This file is offered as-is,
|
|
||||||
* without any warranty.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* First two pages of Flash ROM is difficult to use because of
|
|
||||||
* predefined purposes. It's defined as a default vector page and
|
|
||||||
* flash configuration page.
|
|
||||||
*
|
|
||||||
* We put something useful to those two pages, together with the
|
|
||||||
* data for predefined purposes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern uint8_t __main_stack_end__;
|
|
||||||
|
|
||||||
static void __attribute__ ((naked,section(".flash_config_page")))
|
|
||||||
reset (void)
|
|
||||||
{
|
|
||||||
uint32_t r3 = 0xe000ed08;
|
|
||||||
|
|
||||||
asm volatile ("str %2, [%0]\n\t" /* Set SCR->VTOR */
|
|
||||||
"ldr %0, [%2, #4]\n\t" /* Jump to the entry */
|
|
||||||
"bx %0\n\t"
|
|
||||||
".align 2\n"
|
|
||||||
: "=r" (r3)
|
|
||||||
: "0" (r3), "r" (0x00000800)
|
|
||||||
: "memory");
|
|
||||||
|
|
||||||
/* Never reach here. */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32_t
|
|
||||||
stack_entry[] __attribute__ ((section(".first_page.first_words"),used)) = {
|
|
||||||
(uint32_t)(&__main_stack_end__ - 32),
|
|
||||||
(uint32_t)reset,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: We don't use backdoor comparison key. The area is used by
|
|
||||||
* CRC32 table.
|
|
||||||
*/
|
|
||||||
static uint32_t
|
|
||||||
flash_config[] __attribute__ ((section(".flash_config"),used)) = {
|
|
||||||
0xffffffff, /* Protection bytes */
|
|
||||||
0xffff3ffe, /* FSEC=0xfe, FOPT=0x3f */
|
|
||||||
/* FOPT=0x3f:
|
|
||||||
* BOOTSRC_SEL=00: Boot from flash
|
|
||||||
*/
|
|
||||||
/* FSEC=0xfe:
|
|
||||||
* unsecure
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CRC32 calculation routines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Table of CRC32, generated by gen_crc_table.py
|
|
||||||
*/
|
|
||||||
static unsigned int
|
|
||||||
crc32_table[256] __attribute__ ((section(".first_page"))) = {
|
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
|
||||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
|
||||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
|
||||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
|
||||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
|
||||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
|
||||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
|
||||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
|
||||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
|
||||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
|
||||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
|
||||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
|
||||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
|
||||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
|
||||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
|
||||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
|
||||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
|
||||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
|
||||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
|
||||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
|
||||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
|
||||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
|
||||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
|
||||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
|
||||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
|
||||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
|
||||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
|
||||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
|
||||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
|
||||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
|
||||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
|
||||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
|
||||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
|
||||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
|
||||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
|
||||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
|
||||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
|
||||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
|
||||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
|
||||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
|
||||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
|
||||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
|
||||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned int crc_reg;
|
|
||||||
|
|
||||||
__attribute__ ((section(".flash_config_page")))
|
|
||||||
void
|
|
||||||
crc32_init (void)
|
|
||||||
{
|
|
||||||
crc_reg = 0xffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((section(".flash_config_page")))
|
|
||||||
unsigned int
|
|
||||||
crc32_value (void)
|
|
||||||
{
|
|
||||||
return crc_reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((section(".flash_config_page")))
|
|
||||||
void
|
|
||||||
crc32_u8 (unsigned char bits_eight)
|
|
||||||
{
|
|
||||||
crc_reg = crc32_table[(crc_reg & 0xff) ^ bits_eight] ^ (crc_reg >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((section(".flash_config_page")))
|
|
||||||
void
|
|
||||||
crc32_u32 (unsigned int u)
|
|
||||||
{
|
|
||||||
crc32_u8 (u & 0xff);
|
|
||||||
crc32_u8 ((u >> 8)& 0xff);
|
|
||||||
crc32_u8 ((u >> 16)& 0xff);
|
|
||||||
crc32_u8 ((u >> 24)& 0xff);
|
|
||||||
}
|
|
||||||
@@ -4,11 +4,9 @@
|
|||||||
#include <chopstx.h>
|
#include <chopstx.h>
|
||||||
|
|
||||||
#include "usb_lld.h"
|
#include "usb_lld.h"
|
||||||
#include "stream.h"
|
#include "tty.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
#include "command.h"
|
||||||
#include "crc32.h"
|
|
||||||
#include "adc.h"
|
|
||||||
|
|
||||||
struct GPIO {
|
struct GPIO {
|
||||||
volatile uint32_t PDOR; /* Port Data Output Register */
|
volatile uint32_t PDOR; /* Port Data Output Register */
|
||||||
@@ -93,43 +91,12 @@ blk (void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INTR_REQ_USB 24
|
|
||||||
|
|
||||||
static void *
|
|
||||||
usb_intr (void *arg)
|
|
||||||
{
|
|
||||||
extern void usb_lld_init (uint8_t feature);
|
|
||||||
extern void usb_interrupt_handler (void);
|
|
||||||
|
|
||||||
chopstx_intr_t interrupt;
|
|
||||||
|
|
||||||
(void)arg;
|
|
||||||
chopstx_claim_irq (&interrupt, INTR_REQ_USB);
|
|
||||||
usb_lld_init (0x80); /* Bus powered. */
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
chopstx_intr_wait (&interrupt);
|
|
||||||
|
|
||||||
/* Process interrupt. */
|
|
||||||
usb_interrupt_handler ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BUSY_LOOP)
|
|
||||||
#define PRIO_PWM (CHOPSTX_SCHED_RR|1)
|
|
||||||
#define PRIO_BLK (CHOPSTX_SCHED_RR|1)
|
|
||||||
#else
|
|
||||||
#define PRIO_PWM 3
|
#define PRIO_PWM 3
|
||||||
#define PRIO_BLK 2
|
#define PRIO_BLK 2
|
||||||
#endif
|
|
||||||
#define PRIO_INTR 4
|
|
||||||
|
|
||||||
extern uint8_t __process1_stack_base__, __process1_stack_size__;
|
extern uint8_t __process1_stack_base__, __process1_stack_size__;
|
||||||
extern uint8_t __process2_stack_base__, __process2_stack_size__;
|
extern uint8_t __process2_stack_base__, __process2_stack_size__;
|
||||||
extern uint8_t __process3_stack_base__, __process3_stack_size__;
|
|
||||||
|
|
||||||
const uint32_t __stackaddr_pwm = (uint32_t)&__process1_stack_base__;
|
const uint32_t __stackaddr_pwm = (uint32_t)&__process1_stack_base__;
|
||||||
const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
|
const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
|
||||||
@@ -137,9 +104,6 @@ const size_t __stacksize_pwm = (size_t)&__process1_stack_size__;
|
|||||||
const uint32_t __stackaddr_blk = (uint32_t)&__process2_stack_base__;
|
const uint32_t __stackaddr_blk = (uint32_t)&__process2_stack_base__;
|
||||||
const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
|
const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
|
||||||
|
|
||||||
const uint32_t __stackaddr_intr = (uint32_t)&__process3_stack_base__;
|
|
||||||
const size_t __stacksize_intr = (size_t)&__process3_stack_size__;
|
|
||||||
|
|
||||||
|
|
||||||
static char hexchar (uint8_t x)
|
static char hexchar (uint8_t x)
|
||||||
{
|
{
|
||||||
@@ -153,43 +117,23 @@ static char hexchar (uint8_t x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_recv (void *arg)
|
|
||||||
{
|
|
||||||
struct stream *s = arg;
|
|
||||||
if ((s->flags & FLAG_CONNECTED) == 0)
|
|
||||||
return 1;
|
|
||||||
if ((s->flags & FLAG_RECV_AVAIL))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
struct stream *st;
|
struct tty *tty;
|
||||||
uint8_t count;
|
uint8_t count;
|
||||||
extern uint32_t bDeviceState;
|
|
||||||
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
adc_init ();
|
|
||||||
adc_start ();
|
|
||||||
|
|
||||||
chopstx_mutex_init (&mtx);
|
chopstx_mutex_init (&mtx);
|
||||||
chopstx_cond_init (&cnd0);
|
chopstx_cond_init (&cnd0);
|
||||||
chopstx_cond_init (&cnd1);
|
chopstx_cond_init (&cnd1);
|
||||||
|
|
||||||
st = stream_open ();
|
|
||||||
|
|
||||||
m = 10;
|
m = 10;
|
||||||
|
|
||||||
chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL);
|
chopstx_create (PRIO_PWM, __stackaddr_pwm, __stacksize_pwm, pwm, NULL);
|
||||||
chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL);
|
chopstx_create (PRIO_BLK, __stackaddr_blk, __stacksize_blk, blk, NULL);
|
||||||
chopstx_create (PRIO_INTR, __stackaddr_intr, __stacksize_intr,
|
|
||||||
usb_intr, NULL);
|
|
||||||
|
|
||||||
chopstx_usec_wait (200*1000);
|
chopstx_usec_wait (200*1000);
|
||||||
|
|
||||||
@@ -199,98 +143,61 @@ main (int argc, const char *argv[])
|
|||||||
chopstx_mutex_unlock (&mtx);
|
chopstx_mutex_unlock (&mtx);
|
||||||
|
|
||||||
u = 1;
|
u = 1;
|
||||||
while (bDeviceState != CONFIGURED)
|
|
||||||
chopstx_usec_wait (500*1000);
|
tty = tty_open ();
|
||||||
|
tty_wait_configured (tty);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
m = 50;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
uint8_t s[64];
|
char s[LINEBUFSIZE];
|
||||||
|
|
||||||
|
connection_loop:
|
||||||
u = 1;
|
u = 1;
|
||||||
if (stream_wait_connection (st) < 0)
|
tty_wait_connection (tty);
|
||||||
{
|
|
||||||
chopstx_usec_wait (1000*1000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
chopstx_usec_wait (500*1000);
|
chopstx_usec_wait (50*1000);
|
||||||
|
|
||||||
/* Send ZLP at the beginning. */
|
/* Send ZLP at the beginning. */
|
||||||
stream_send (st, s, 0);
|
tty_send (tty, s, 0);
|
||||||
|
|
||||||
memcpy (s, "xx: Hello, World with Chopstx!\r\n", 32);
|
memcpy (s, "xx: Hello, World with Chopstx!\r\n", 32);
|
||||||
s[0] = hexchar (count >> 4);
|
s[0] = hexchar (count >> 4);
|
||||||
s[1] = hexchar (count & 0x0f);
|
s[1] = hexchar (count & 0x0f);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (stream_send (st, s, 32) < 0)
|
if (tty_send (tty, s, 32) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int size;
|
|
||||||
uint32_t usec;
|
uint32_t usec;
|
||||||
struct chx_poll_cond poll_desc;
|
|
||||||
|
|
||||||
poll_desc.type = CHOPSTX_POLL_COND;
|
/* Prompt */
|
||||||
poll_desc.ready = 0;
|
if (tty_send (tty, "> ", 2) < 0)
|
||||||
poll_desc.cond = &st->cnd;
|
break;
|
||||||
poll_desc.mutex = &st->mtx;
|
|
||||||
poll_desc.check = check_recv;
|
|
||||||
poll_desc.arg = st;
|
|
||||||
|
|
||||||
/* With chopstx_poll, we can do timed cond_wait */
|
usec = 3000000; /* 3.0 seconds */
|
||||||
usec = 3000000;
|
while (1)
|
||||||
if (chopstx_poll (&usec, 1, &poll_desc))
|
|
||||||
{
|
{
|
||||||
size = stream_recv (st, s + 4);
|
int size = tty_recv (tty, s, &usec);
|
||||||
|
u ^= 1;
|
||||||
|
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
|
goto connection_loop;
|
||||||
|
|
||||||
|
if (size == 1)
|
||||||
|
/* Do nothing but prompt again. */
|
||||||
break;
|
break;
|
||||||
|
else if (size)
|
||||||
if (size >= 0)
|
|
||||||
{
|
{
|
||||||
unsigned int value;
|
/* Newline into NUL */
|
||||||
|
s[size - 1] = 0;
|
||||||
if (s[4] == 't')
|
cmd_dispatch (tty, (char *)s);
|
||||||
{
|
break;
|
||||||
s[0] = 'T';
|
|
||||||
s[1] = 'M';
|
|
||||||
|
|
||||||
adc_start_conversion (0, 1);
|
|
||||||
adc_wait_completion (NULL);
|
|
||||||
value = adc_buf[0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
crc32_init ();
|
|
||||||
s[0] = hexchar (size >> 4);
|
|
||||||
s[1] = hexchar (size & 0x0f);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
crc32_u8 (s[4 + i]);
|
|
||||||
value = crc32_value () ^ 0xffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
s[4] = hexchar (value >> 28);
|
|
||||||
s[5] = hexchar (value >> 24);
|
|
||||||
s[6] = hexchar (value >> 20);
|
|
||||||
s[7] = hexchar (value >> 16);
|
|
||||||
s[8] = hexchar (value >> 12);
|
|
||||||
s[9] = hexchar (value >> 8);
|
|
||||||
s[10] = hexchar (value >> 4);
|
|
||||||
s[11] = hexchar (value);
|
|
||||||
s[12] = '\r';
|
|
||||||
s[13] = '\n';
|
|
||||||
if (stream_send (st, s, 14) < 0)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u ^= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* MK27Z memory setup.
|
* MK27Z memory setup.
|
||||||
*/
|
*/
|
||||||
__main_stack_size__ = 0x0100; /* Exception handlers */
|
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||||
__process0_stack_size__ = 0x0300; /* Main program */
|
__process0_stack_size__ = 0x0300; /* Main program */
|
||||||
__process1_stack_size__ = 0x0200; /* first thread program */
|
__process1_stack_size__ = 0x0200; /* first thread program */
|
||||||
__process2_stack_size__ = 0x0100; /* second thread program */
|
__process2_stack_size__ = 0x0100; /* second thread program */
|
||||||
__process3_stack_size__ = 0x0200; /* third thread program */
|
__process3_stack_size__ = 0x0200; /* third thread program */
|
||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
@@ -23,17 +23,32 @@ SECTIONS
|
|||||||
|
|
||||||
_text = .;
|
_text = .;
|
||||||
|
|
||||||
.f2 : ALIGN(16) SUBALIGN(8)
|
.text : ALIGN(16) SUBALIGN(8)
|
||||||
{
|
{
|
||||||
KEEP(*(.first_page.first_words))
|
KEEP(*(.first_page.first_words))
|
||||||
KEEP(*(.first_page))
|
KEEP(*(.sys.version))
|
||||||
KEEP(*(.flash_config))
|
KEEP(*(.sys.board_info))
|
||||||
KEEP(*(.flash_config_page))
|
KEEP(*(.sys.vectors))
|
||||||
} > flash =0xffffffff
|
build/sys-*.o(.text)
|
||||||
|
build/sys-*.o(.text.*)
|
||||||
.text : ALIGN(16) SUBALIGN(16)
|
build/sys-*.o(.rodata)
|
||||||
{
|
build/sys-*.o(.rodata.*)
|
||||||
. = ALIGN(1024);
|
. = ALIGN(1024);
|
||||||
|
KEEP(*(.flash_config))
|
||||||
|
KEEP(*(.fixed_function.reset))
|
||||||
|
KEEP(*(.fixed_function.flash_do_internal))
|
||||||
|
KEEP(*(.fixed_function.flash_do))
|
||||||
|
KEEP(*(.fixed_function.flash_erase_page))
|
||||||
|
KEEP(*(.fixed_function.flash_program_word))
|
||||||
|
KEEP(*(.fixed_function.crc32_init))
|
||||||
|
KEEP(*(.fixed_function.crc32_u8))
|
||||||
|
KEEP(*(.fixed_function.crc32_u32))
|
||||||
|
/*
|
||||||
|
* Because of alignment requirement
|
||||||
|
* of startup.vectors, align to 256.
|
||||||
|
*/
|
||||||
|
. = ALIGN(256);
|
||||||
|
KEEP(*(.crc32_table))
|
||||||
KEEP(*(.startup.vectors))
|
KEEP(*(.startup.vectors))
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
*(.text.startup.*)
|
*(.text.startup.*)
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#define BUFSIZE 128
|
|
||||||
#define FLAG_CONNECTED (1 << 0)
|
|
||||||
#define FLAG_SEND_AVAIL (1 << 1)
|
|
||||||
#define FLAG_RECV_AVAIL (1 << 2)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Current implementation is synchronous and buffers are not yet used.
|
|
||||||
*/
|
|
||||||
struct stream {
|
|
||||||
chopstx_mutex_t mtx;
|
|
||||||
chopstx_cond_t cnd;
|
|
||||||
int sending;
|
|
||||||
unsigned int recv_len;
|
|
||||||
uint8_t recv_buf[BUFSIZE];
|
|
||||||
uint8_t buf_send[BUFSIZE]; /* Not yet used. */
|
|
||||||
uint8_t cnt_send_head; /* Not yet used. */
|
|
||||||
uint8_t cnt_send_tail; /* Not yet used. */
|
|
||||||
uint8_t cnt_recv_head; /* Not yet used. */
|
|
||||||
uint8_t cnt_recv_tail; /* Not yet used. */
|
|
||||||
uint32_t flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stream *stream_open (void);
|
|
||||||
int stream_wait_connection (struct stream *st);
|
|
||||||
int stream_send (struct stream *st, uint8_t *buf, uint8_t count);
|
|
||||||
int stream_recv (struct stream *st, uint8_t *buf);
|
|
||||||
9
example-fs-bb48/tty.h
Normal file
9
example-fs-bb48/tty.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#define LINEBUFSIZE 128
|
||||||
|
|
||||||
|
struct tty;
|
||||||
|
|
||||||
|
struct tty *tty_open (void);
|
||||||
|
void tty_wait_configured (struct tty *tty);
|
||||||
|
void tty_wait_connection (struct tty *tty);
|
||||||
|
int tty_send (struct tty *tty, const char *buf, int count);
|
||||||
|
int tty_recv (struct tty *tty, char *buf, uint32_t *timeout);
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,115 +0,0 @@
|
|||||||
#define STANDARD_ENDPOINT_DESC_SIZE 0x09
|
|
||||||
|
|
||||||
/* endpoints enumeration */
|
|
||||||
#define ENDP0 ((uint8_t)0)
|
|
||||||
#define ENDP1 ((uint8_t)1)
|
|
||||||
#define ENDP2 ((uint8_t)2)
|
|
||||||
#define ENDP3 ((uint8_t)3)
|
|
||||||
#define ENDP4 ((uint8_t)4)
|
|
||||||
#define ENDP5 ((uint8_t)5)
|
|
||||||
#define ENDP6 ((uint8_t)6)
|
|
||||||
#define ENDP7 ((uint8_t)7)
|
|
||||||
|
|
||||||
/* EP_TYPE[1:0] EndPoint TYPE */
|
|
||||||
#define EP_BULK (0x0000) /* EndPoint BULK */
|
|
||||||
#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
|
|
||||||
#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
|
|
||||||
#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */
|
|
||||||
|
|
||||||
enum RECIPIENT_TYPE
|
|
||||||
{
|
|
||||||
DEVICE_RECIPIENT, /* Recipient device */
|
|
||||||
INTERFACE_RECIPIENT, /* Recipient interface */
|
|
||||||
ENDPOINT_RECIPIENT, /* Recipient endpoint */
|
|
||||||
OTHER_RECIPIENT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DESCRIPTOR_TYPE
|
|
||||||
{
|
|
||||||
DEVICE_DESCRIPTOR = 1,
|
|
||||||
CONFIG_DESCRIPTOR,
|
|
||||||
STRING_DESCRIPTOR,
|
|
||||||
INTERFACE_DESCRIPTOR,
|
|
||||||
ENDPOINT_DESCRIPTOR
|
|
||||||
};
|
|
||||||
|
|
||||||
#define REQUEST_DIR 0x80 /* Mask to get request dir */
|
|
||||||
#define REQUEST_TYPE 0x60 /* Mask to get request type */
|
|
||||||
#define STANDARD_REQUEST 0x00 /* Standard request */
|
|
||||||
#define CLASS_REQUEST 0x20 /* Class request */
|
|
||||||
#define VENDOR_REQUEST 0x40 /* Vendor request */
|
|
||||||
#define RECIPIENT 0x1F /* Mask to get recipient */
|
|
||||||
|
|
||||||
#define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0)
|
|
||||||
#define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0)
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
USB_UNSUPPORT = 0,
|
|
||||||
USB_SUCCESS = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct req_args {
|
|
||||||
uint16_t value;
|
|
||||||
uint16_t index;
|
|
||||||
uint16_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
void usb_cb_device_reset (void);
|
|
||||||
int usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg);
|
|
||||||
int usb_cb_interface (uint8_t cmd, struct req_args *arg);
|
|
||||||
int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
|
|
||||||
struct req_args *arg);
|
|
||||||
int usb_cb_handle_event (uint8_t event_type, uint16_t value);
|
|
||||||
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
|
|
||||||
struct req_args *arg);
|
|
||||||
void usb_cb_tx_done (uint8_t ep_num);
|
|
||||||
void usb_cb_rx_ready (uint8_t ep_num);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
USB_EVENT_ADDRESS,
|
|
||||||
USB_EVENT_CONFIG,
|
|
||||||
USB_EVENT_SUSPEND,
|
|
||||||
USB_EVENT_WAKEUP,
|
|
||||||
USB_EVENT_STALL,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
USB_SET_INTERFACE,
|
|
||||||
USB_GET_INTERFACE,
|
|
||||||
USB_QUERY_INTERFACE,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DEVICE_STATE
|
|
||||||
{
|
|
||||||
UNCONNECTED,
|
|
||||||
ATTACHED,
|
|
||||||
POWERED,
|
|
||||||
SUSPENDED,
|
|
||||||
ADDRESSED,
|
|
||||||
CONFIGURED
|
|
||||||
};
|
|
||||||
|
|
||||||
void usb_lld_init (uint8_t feature);
|
|
||||||
|
|
||||||
int usb_lld_reply_request (const void *buf, size_t buflen,
|
|
||||||
struct req_args *arg);
|
|
||||||
void usb_lld_set_data_to_recv (void *p, size_t len);
|
|
||||||
|
|
||||||
void usb_lld_tx_enable (uint8_t ep_num, const void *buf, size_t len);
|
|
||||||
int usb_lld_tx_result (int ep_num);
|
|
||||||
|
|
||||||
void usb_lld_rx_enable (int ep_num, void *buf, size_t len);
|
|
||||||
int usb_lld_rx_data_len (int ep_num);
|
|
||||||
|
|
||||||
void usb_lld_stall (int ep_num);
|
|
||||||
|
|
||||||
void usb_lld_reset (uint8_t feature);
|
|
||||||
void usb_lld_setup_endpoint (int n, int rx_en, int tx_en);
|
|
||||||
void usb_lld_set_configuration (uint8_t config);
|
|
||||||
uint8_t usb_lld_current_configuration (void);
|
|
||||||
|
|
||||||
void usb_lld_prepare_shutdown (void);
|
|
||||||
void usb_lld_shutdown (void);
|
|
||||||
|
|
||||||
void usb_interrupt_handler (void);
|
|
||||||
@@ -5,16 +5,16 @@ PROJECT = hacker-emblem
|
|||||||
CHOPSTX = ..
|
CHOPSTX = ..
|
||||||
LDSCRIPT= hacker-emblem.ld
|
LDSCRIPT= hacker-emblem.ld
|
||||||
|
|
||||||
CSRC = sys.c hh.c
|
CSRC = reset.c hh.c
|
||||||
|
|
||||||
# Hacker Emblem and "Happy Hacking!" demonstration
|
# Hacker Emblem and "Happy Hacking!" demonstration
|
||||||
# CSRC = sys.c hh.c
|
# CSRC = reset.c hh.c
|
||||||
|
|
||||||
# Debian logo demonstration
|
# Debian logo demonstration
|
||||||
# CSRC = sys.c debian-logo.c
|
# CSRC = reset.c debian-logo.c
|
||||||
|
|
||||||
# "Hiroshi & Ayumi with Tulip" demonstration
|
# "Hiroshi & Ayumi with Tulip" demonstration
|
||||||
# CSRC = sys.c hiroshi-ayumi.c
|
# CSRC = reset.c hiroshi-ayumi.c
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
CROSS = arm-none-eabi-
|
CROSS = arm-none-eabi-
|
||||||
@@ -36,7 +36,7 @@ board.h:
|
|||||||
@echo Please make a symbolic link \'board.h\' to a file in ../board;
|
@echo Please make a symbolic link \'board.h\' to a file in ../board;
|
||||||
@exit 1
|
@exit 1
|
||||||
|
|
||||||
sys.c: board.h
|
reset.c: board.h
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f board.h
|
rm -f board.h
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* ST32F0 memory setup.
|
* ST32F0 memory setup.
|
||||||
*/
|
*/
|
||||||
__main_stack_size__ = 0x0100; /* Exception handlers */
|
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||||
__process0_stack_size__ = 0x0100; /* Main program */
|
__process0_stack_size__ = 0x0100; /* Main program */
|
||||||
__process1_stack_size__ = 0x0100; /* first thread program */
|
__process1_stack_size__ = 0x0100; /* first thread program */
|
||||||
__process2_stack_size__ = 0x0100; /* second thread program */
|
__process2_stack_size__ = 0x0100; /* second thread program */
|
||||||
__process3_stack_size__ = 0x0100; /* third thread program */
|
__process3_stack_size__ = 0x0100; /* third thread program */
|
||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* sys.c - No system routines, but only RESET handler for STM32F030.
|
* reset.c - No system routines, but only RESET handler for STM32F030.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Flying Stone Technology
|
* Copyright (C) 2015 Flying Stone Technology
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
@@ -70,7 +70,7 @@ typedef void (*handler)(void);
|
|||||||
extern uint8_t __main_stack_end__;
|
extern uint8_t __main_stack_end__;
|
||||||
|
|
||||||
handler vector[] __attribute__ ((section(".vectors"))) = {
|
handler vector[] __attribute__ ((section(".vectors"))) = {
|
||||||
(handler)&__main_stack_end__,
|
(handler)(&__main_stack_end__ - 32),
|
||||||
reset,
|
reset,
|
||||||
nmi, /* nmi */
|
nmi, /* nmi */
|
||||||
hard_fault, /* hard fault */
|
hard_fault, /* hard fault */
|
||||||
@@ -8,8 +8,10 @@ PROJECT = sample
|
|||||||
CHOPSTX = ..
|
CHOPSTX = ..
|
||||||
LDSCRIPT= sample.ld
|
LDSCRIPT= sample.ld
|
||||||
### LDSCRIPT= sample.ld.m3
|
### LDSCRIPT= sample.ld.m3
|
||||||
CSRC = sys.c sample.c
|
CSRC = sample.c
|
||||||
### CSRC = sys.c aes-constant-ft.c sample.c
|
|
||||||
|
CHIP=stm32f0
|
||||||
|
USE_SYS = yes
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
CROSS = arm-none-eabi-
|
CROSS = arm-none-eabi-
|
||||||
@@ -20,8 +22,8 @@ OBJCOPY = $(CROSS)objcopy
|
|||||||
### MCU = cortex-m3
|
### MCU = cortex-m3
|
||||||
MCU = cortex-m0
|
MCU = cortex-m0
|
||||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||||
DEFS = -DHAVE_SYS_H -DFREE_STANDING -DMHZ=48
|
DEFS = -DUSE_SYS3 -DFREE_STANDING -DMHZ=48
|
||||||
### DEFS = -DFREE_STANDING -DHAVE_SYS_H -DBUSY_LOOP -DCHX_FLAGS_MAIN=CHOPSTX_SCHED_RR
|
### DEFS = -DFREE_STANDING -DUSE_SYS3 -DBUSY_LOOP -DCHX_FLAGS_MAIN=CHOPSTX_SCHED_RR
|
||||||
OPT = -O3 -Os -g
|
OPT = -O3 -Os -g
|
||||||
LIBS =
|
LIBS =
|
||||||
|
|
||||||
|
|||||||
@@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* aes-constant-ft.c - AES forward tables.
|
|
||||||
*
|
|
||||||
* We need something useful for the initial flash ROM page (4 Ki
|
|
||||||
* bytes), which cannot be modified after installation. Even after
|
|
||||||
* upgrade of the firmware, it stays intact.
|
|
||||||
*
|
|
||||||
* We decide to put 3/4 of AES forward tables to fill 3 Ki bytes, as
|
|
||||||
* its useful and it won't change.
|
|
||||||
*
|
|
||||||
* The code was taken from aes.c of PolarSSL version 0.14, and then,
|
|
||||||
* modified to add section names.
|
|
||||||
*
|
|
||||||
* Since this is just a data, it wouldn't be copyright-able, but the
|
|
||||||
* original auther would claim so. Thus, we put original copyright
|
|
||||||
* notice here. It is highly likely that there will be no such a
|
|
||||||
* thing for copyright. Nevertheless, we think that PolarSSL is good
|
|
||||||
* software to address here, and encourage people using it.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Original copyright notice is below:
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIPS-197 compliant AES implementation
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
|
||||||
*
|
|
||||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
|
||||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This program 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 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
|
||||||
*
|
|
||||||
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
|
|
||||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Forward tables
|
|
||||||
*/
|
|
||||||
#define FT \
|
|
||||||
\
|
|
||||||
V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
|
|
||||||
V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
|
|
||||||
V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
|
|
||||||
V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
|
|
||||||
V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
|
|
||||||
V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
|
|
||||||
V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
|
|
||||||
V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
|
|
||||||
V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
|
|
||||||
V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
|
|
||||||
V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
|
|
||||||
V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
|
|
||||||
V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
|
|
||||||
V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
|
|
||||||
V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
|
|
||||||
V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
|
|
||||||
V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
|
|
||||||
V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
|
|
||||||
V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
|
|
||||||
V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
|
|
||||||
V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
|
|
||||||
V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
|
|
||||||
V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
|
|
||||||
V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
|
|
||||||
V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
|
|
||||||
V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
|
|
||||||
V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
|
|
||||||
V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
|
|
||||||
V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
|
|
||||||
V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
|
|
||||||
V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
|
|
||||||
V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
|
|
||||||
V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
|
|
||||||
V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
|
|
||||||
V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
|
|
||||||
V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
|
|
||||||
V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
|
|
||||||
V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
|
|
||||||
V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
|
|
||||||
V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
|
|
||||||
V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
|
|
||||||
V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
|
|
||||||
V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
|
|
||||||
V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
|
|
||||||
V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
|
|
||||||
V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
|
|
||||||
V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
|
|
||||||
V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
|
|
||||||
V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
|
|
||||||
V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
|
|
||||||
V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
|
|
||||||
V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
|
|
||||||
V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
|
|
||||||
V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
|
|
||||||
V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
|
|
||||||
V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
|
|
||||||
V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
|
|
||||||
V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
|
|
||||||
V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
|
|
||||||
V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
|
|
||||||
V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
|
|
||||||
V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
|
|
||||||
V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
|
|
||||||
V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##a##b##c##d
|
|
||||||
const uint32_t FT0[256] __attribute__((section(".sys.0"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##b##c##d##a
|
|
||||||
const uint32_t FT1[256] __attribute__((section(".sys.1"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##c##d##a##b
|
|
||||||
const uint32_t FT2[256] __attribute__((section(".sys.2"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#ifdef ORIGINAL_IMPLEMENTATION
|
|
||||||
#define V(a,b,c,d) 0x##d##a##b##c
|
|
||||||
const uint32_t FT3[256] = { FT };
|
|
||||||
#undef V
|
|
||||||
#endif
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* ST32F0 memory setup.
|
* ST32F0 memory setup.
|
||||||
*/
|
*/
|
||||||
__main_stack_size__ = 0x0100; /* Exception handlers */
|
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||||
__process0_stack_size__ = 0x0100; /* Main program */
|
__process0_stack_size__ = 0x0100; /* Main program */
|
||||||
__process1_stack_size__ = 0x0100; /* first thread program */
|
__process1_stack_size__ = 0x0100; /* first thread program */
|
||||||
__process2_stack_size__ = 0x0100; /* second thread program */
|
__process2_stack_size__ = 0x0100; /* second thread program */
|
||||||
__process3_stack_size__ = 0x0100; /* third thread program */
|
__process3_stack_size__ = 0x0100; /* third thread program */
|
||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
@@ -30,10 +30,10 @@ SECTIONS
|
|||||||
KEEP(*(.sys.version))
|
KEEP(*(.sys.version))
|
||||||
KEEP(*(.sys.board_id))
|
KEEP(*(.sys.board_id))
|
||||||
KEEP(*(.sys.board_name))
|
KEEP(*(.sys.board_name))
|
||||||
build/sys.o(.text)
|
build/sys-*.o(.text)
|
||||||
build/sys.o(.text.*)
|
build/sys-*.o(.text.*)
|
||||||
build/sys.o(.rodata)
|
build/sys-*.o(.rodata)
|
||||||
build/sys.o(.rodata.*)
|
build/sys-*.o(.rodata.*)
|
||||||
. = ALIGN(1024);
|
. = ALIGN(1024);
|
||||||
/*
|
/*
|
||||||
*(.sys.0)
|
*(.sys.0)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* ST32F103 memory setup.
|
* ST32F103 memory setup.
|
||||||
*/
|
*/
|
||||||
__main_stack_size__ = 0x0100; /* Exception handlers */
|
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||||
__process0_stack_size__ = 0x0100; /* Main program */
|
__process0_stack_size__ = 0x0100; /* Main program */
|
||||||
__process1_stack_size__ = 0x0100; /* first thread program */
|
__process1_stack_size__ = 0x0100; /* first thread program */
|
||||||
__process2_stack_size__ = 0x0100; /* second thread program */
|
__process2_stack_size__ = 0x0100; /* second thread program */
|
||||||
__process3_stack_size__ = 0x0100; /* third thread program */
|
__process3_stack_size__ = 0x0100; /* third thread program */
|
||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
@@ -30,10 +30,10 @@ SECTIONS
|
|||||||
KEEP(*(.sys.version))
|
KEEP(*(.sys.version))
|
||||||
KEEP(*(.sys.board_id))
|
KEEP(*(.sys.board_id))
|
||||||
KEEP(*(.sys.board_name))
|
KEEP(*(.sys.board_name))
|
||||||
build/sys.o(.text)
|
build/sys-*.o(.text)
|
||||||
build/sys.o(.text.*)
|
build/sys-*.o(.text.*)
|
||||||
build/sys.o(.rodata)
|
build/sys-*.o(.rodata)
|
||||||
build/sys.o(.rodata.*)
|
build/sys-*.o(.rodata.*)
|
||||||
. = ALIGN(1024);
|
. = ALIGN(1024);
|
||||||
*(.sys.0)
|
*(.sys.0)
|
||||||
*(.sys.1)
|
*(.sys.1)
|
||||||
|
|||||||
@@ -5,8 +5,13 @@ PROJECT = lcd
|
|||||||
CHOPSTX = ..
|
CHOPSTX = ..
|
||||||
NEUGSRC = ./neug/src
|
NEUGSRC = ./neug/src
|
||||||
LDSCRIPT= lcd.ld
|
LDSCRIPT= lcd.ld
|
||||||
CSRC = sys.c aes-constant-ft.c primer2-switches.c primer2-ts.c lcd.c main.c \
|
CSRC = primer2-switches.c primer2-ts.c lcd.c main.c \
|
||||||
adc_stm32f103.c neug.c sha256.c
|
neug.c sha256.c
|
||||||
|
|
||||||
|
CHIP=stm32f103
|
||||||
|
USE_SYS = yes
|
||||||
|
USE_USB = yes
|
||||||
|
USE_ADC = yes
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
CROSS = arm-none-eabi-
|
CROSS = arm-none-eabi-
|
||||||
@@ -15,8 +20,8 @@ LD = $(CROSS)gcc
|
|||||||
OBJCOPY = $(CROSS)objcopy
|
OBJCOPY = $(CROSS)objcopy
|
||||||
MCU = cortex-m3
|
MCU = cortex-m3
|
||||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||||
DEFS = -DHAVE_SYS_H -DFREE_STANDING -DMHZ=48
|
DEFS = -DUSE_SYS3 -DFREE_STANDING -DMHZ=48
|
||||||
# DEFS = -DFREE_STANDING -DHAVE_SYS_H -DBUSY_LOOP -DCHX_FLAGS_MAIN=CHOPSTX_SCHED_RR
|
# DEFS = -DFREE_STANDING -DUSE_SYS3 -DBUSY_LOOP -DCHX_FLAGS_MAIN=CHOPSTX_SCHED_RR
|
||||||
OPT = -O3 -Os -g
|
OPT = -O3 -Os -g
|
||||||
INCDIR = $(NEUGSRC)
|
INCDIR = $(NEUGSRC)
|
||||||
LIBS =
|
LIBS =
|
||||||
|
|||||||
@@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* aes-constant-ft.c - AES forward tables.
|
|
||||||
*
|
|
||||||
* We need something useful for the initial flash ROM page (4 Ki
|
|
||||||
* bytes), which cannot be modified after installation. Even after
|
|
||||||
* upgrade of the firmware, it stays intact.
|
|
||||||
*
|
|
||||||
* We decide to put 3/4 of AES forward tables to fill 3 Ki bytes, as
|
|
||||||
* its useful and it won't change.
|
|
||||||
*
|
|
||||||
* The code was taken from aes.c of PolarSSL version 0.14, and then,
|
|
||||||
* modified to add section names.
|
|
||||||
*
|
|
||||||
* Since this is just a data, it wouldn't be copyright-able, but the
|
|
||||||
* original auther would claim so. Thus, we put original copyright
|
|
||||||
* notice here. It is highly likely that there will be no such a
|
|
||||||
* thing for copyright. Nevertheless, we think that PolarSSL is good
|
|
||||||
* software to address here, and encourage people using it.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Original copyright notice is below:
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIPS-197 compliant AES implementation
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
|
||||||
*
|
|
||||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
|
||||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This program 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 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
|
||||||
*
|
|
||||||
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
|
|
||||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Forward tables
|
|
||||||
*/
|
|
||||||
#define FT \
|
|
||||||
\
|
|
||||||
V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
|
|
||||||
V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
|
|
||||||
V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
|
|
||||||
V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
|
|
||||||
V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
|
|
||||||
V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
|
|
||||||
V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
|
|
||||||
V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
|
|
||||||
V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
|
|
||||||
V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
|
|
||||||
V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
|
|
||||||
V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
|
|
||||||
V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
|
|
||||||
V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
|
|
||||||
V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
|
|
||||||
V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
|
|
||||||
V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
|
|
||||||
V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
|
|
||||||
V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
|
|
||||||
V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
|
|
||||||
V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
|
|
||||||
V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
|
|
||||||
V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
|
|
||||||
V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
|
|
||||||
V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
|
|
||||||
V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
|
|
||||||
V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
|
|
||||||
V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
|
|
||||||
V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
|
|
||||||
V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
|
|
||||||
V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
|
|
||||||
V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
|
|
||||||
V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
|
|
||||||
V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
|
|
||||||
V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
|
|
||||||
V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
|
|
||||||
V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
|
|
||||||
V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
|
|
||||||
V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
|
|
||||||
V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
|
|
||||||
V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
|
|
||||||
V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
|
|
||||||
V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
|
|
||||||
V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
|
|
||||||
V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
|
|
||||||
V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
|
|
||||||
V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
|
|
||||||
V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
|
|
||||||
V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
|
|
||||||
V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
|
|
||||||
V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
|
|
||||||
V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
|
|
||||||
V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
|
|
||||||
V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
|
|
||||||
V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
|
|
||||||
V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
|
|
||||||
V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
|
|
||||||
V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
|
|
||||||
V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
|
|
||||||
V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
|
|
||||||
V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
|
|
||||||
V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
|
|
||||||
V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
|
|
||||||
V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##a##b##c##d
|
|
||||||
const uint32_t FT0[256] __attribute__((section(".sys.0"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##b##c##d##a
|
|
||||||
const uint32_t FT1[256] __attribute__((section(".sys.1"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#define V(a,b,c,d) 0x##c##d##a##b
|
|
||||||
const uint32_t FT2[256] __attribute__((section(".sys.2"))) = { FT };
|
|
||||||
#undef V
|
|
||||||
|
|
||||||
#ifdef ORIGINAL_IMPLEMENTATION
|
|
||||||
#define V(a,b,c,d) 0x##d##a##b##c
|
|
||||||
const uint32_t FT3[256] = { FT };
|
|
||||||
#undef V
|
|
||||||
#endif
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* ST32F103 memory setup.
|
* ST32F103 memory setup.
|
||||||
*/
|
*/
|
||||||
__main_stack_size__ = 0x0100; /* Exception handlers */
|
__main_stack_size__ = 0x0100; /* Idle+Exception handlers */
|
||||||
__process0_stack_size__ = 0x0200; /* main */
|
__process0_stack_size__ = 0x0200; /* main */
|
||||||
__process1_stack_size__ = 0x0100; /* lcd init */
|
__process1_stack_size__ = 0x0100; /* lcd init */
|
||||||
__process2_stack_size__ = 0x0180; /* rng */
|
__process2_stack_size__ = 0x0180; /* rng */
|
||||||
|
|||||||
@@ -1,467 +0,0 @@
|
|||||||
/*
|
|
||||||
* sys.c - system routines for the initial page for STM32F103.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013, 2014, 2015 Flying Stone Technology
|
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
|
||||||
*
|
|
||||||
* Copying and distribution of this file, with or without modification,
|
|
||||||
* are permitted in any medium without royalty provided the copyright
|
|
||||||
* notice and this notice are preserved. This file is offered as-is,
|
|
||||||
* without any warranty.
|
|
||||||
*
|
|
||||||
* When the flash ROM is protected, we cannot modify the initial page.
|
|
||||||
* We put some system routines (which is useful for any program) here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "board.h"
|
|
||||||
|
|
||||||
/* Adds port C for shutdown function. */
|
|
||||||
#undef RCC_ENR_IOP_EN
|
|
||||||
#undef RCC_RSTR_IOP_RST
|
|
||||||
#define RCC_ENR_IOP_EN \
|
|
||||||
(RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_IOPEEN \
|
|
||||||
| RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPBEN)
|
|
||||||
#define RCC_RSTR_IOP_RST \
|
|
||||||
(RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPDRST | RCC_APB2RSTR_IOPERST \
|
|
||||||
| RCC_APB2RSTR_IOPCRST | RCC_APB2RSTR_IOPBRST)
|
|
||||||
|
|
||||||
#include "clk_gpio_init-stm32.c"
|
|
||||||
|
|
||||||
static struct GPIO *const GPIO_OTHER1 = ((struct GPIO *const) GPIOC_BASE);
|
|
||||||
static struct GPIO *const GPIO_OTHER2 = ((struct GPIO *const) GPIOB_BASE);
|
|
||||||
|
|
||||||
static void __attribute__((used))
|
|
||||||
gpio_init_primer2 (void)
|
|
||||||
{
|
|
||||||
gpio_init ();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Port C setup.
|
|
||||||
* Everything input with pull-up except:
|
|
||||||
* PC0 - Analog input (Touch panel L X+)
|
|
||||||
* PC1 - Analog input (Touch panel R X-)
|
|
||||||
* PC2 - Analog input (Touch panel U Y+)
|
|
||||||
* PC3 - Analog input (Touch panel D Y-)
|
|
||||||
* PC6 - Normal input because there is an external resistor.
|
|
||||||
* PC7 - Normal input because there is an external resistor.
|
|
||||||
* PC13 - Push Pull output (SHUTDOWN)
|
|
||||||
*/
|
|
||||||
GPIO_OTHER1->ODR = 0xffffdfff;
|
|
||||||
GPIO_OTHER1->CRL = 0x44880000;
|
|
||||||
GPIO_OTHER1->CRH = 0x88388888;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Port B setup.
|
|
||||||
* Everything input with pull-up except:
|
|
||||||
* PB8 - Backlight enable output.
|
|
||||||
* PB13 - Alternate output (AUDIO SPI2 SCK).
|
|
||||||
* PB14 - Normal input (AUDIO SPI2 MISO).
|
|
||||||
* PB15 - Alternate output (AUDIO SPI2 MOSI).
|
|
||||||
*/
|
|
||||||
GPIO_OTHER2->ODR = 0xffffffff;
|
|
||||||
GPIO_OTHER2->CRL = 0x88888888;
|
|
||||||
GPIO_OTHER2->CRH = 0xb4b88883;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CORTEX_PRIORITY_BITS 4
|
|
||||||
#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS))
|
|
||||||
#define USB_LP_CAN1_RX0_IRQn 20
|
|
||||||
#define STM32_USB_IRQ_PRIORITY 11
|
|
||||||
|
|
||||||
struct NVIC {
|
|
||||||
volatile uint32_t ISER[8];
|
|
||||||
volatile uint32_t unused1[24];
|
|
||||||
volatile uint32_t ICER[8];
|
|
||||||
volatile uint32_t unused2[24];
|
|
||||||
volatile uint32_t ISPR[8];
|
|
||||||
volatile uint32_t unused3[24];
|
|
||||||
volatile uint32_t ICPR[8];
|
|
||||||
volatile uint32_t unused4[24];
|
|
||||||
volatile uint32_t IABR[8];
|
|
||||||
volatile uint32_t unused5[56];
|
|
||||||
volatile uint32_t IPR[60];
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct NVIC *const NVICBase = ((struct NVIC *const)0xE000E100);
|
|
||||||
#define NVIC_ISER(n) (NVICBase->ISER[n >> 5])
|
|
||||||
#define NVIC_ICPR(n) (NVICBase->ICPR[n >> 5])
|
|
||||||
#define NVIC_IPR(n) (NVICBase->IPR[n >> 2])
|
|
||||||
|
|
||||||
static void
|
|
||||||
nvic_enable_vector (uint32_t n, uint32_t prio)
|
|
||||||
{
|
|
||||||
unsigned int sh = (n & 3) << 3;
|
|
||||||
|
|
||||||
NVIC_IPR (n) = (NVIC_IPR(n) & ~(0xFF << sh)) | (prio << sh);
|
|
||||||
NVIC_ICPR (n) = 1 << (n & 0x1F);
|
|
||||||
NVIC_ISER (n) = 1 << (n & 0x1F);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
usb_cable_config (int enable)
|
|
||||||
{
|
|
||||||
#if defined(GPIO_USB_SET_TO_ENABLE)
|
|
||||||
if (enable)
|
|
||||||
GPIO_USB->BSRR = (1 << GPIO_USB_SET_TO_ENABLE);
|
|
||||||
else
|
|
||||||
GPIO_USB->BRR = (1 << GPIO_USB_SET_TO_ENABLE);
|
|
||||||
#elif defined(GPIO_USB_CLEAR_TO_ENABLE)
|
|
||||||
if (enable)
|
|
||||||
GPIO_USB->BRR = (1 << GPIO_USB_CLEAR_TO_ENABLE);
|
|
||||||
else
|
|
||||||
GPIO_USB->BSRR = (1 << GPIO_USB_CLEAR_TO_ENABLE);
|
|
||||||
#else
|
|
||||||
(void)enable;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
set_led (int on)
|
|
||||||
{
|
|
||||||
#if defined(GPIO_LED_CLEAR_TO_EMIT)
|
|
||||||
if (on)
|
|
||||||
GPIO_LED->BRR = (1 << GPIO_LED_CLEAR_TO_EMIT);
|
|
||||||
else
|
|
||||||
GPIO_LED->BSRR = (1 << GPIO_LED_CLEAR_TO_EMIT);
|
|
||||||
#else
|
|
||||||
if (on)
|
|
||||||
GPIO_LED->BSRR = (1 << GPIO_LED_SET_TO_EMIT);
|
|
||||||
else
|
|
||||||
GPIO_LED->BRR = (1 << GPIO_LED_SET_TO_EMIT);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wait (int count)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
asm volatile ("" : : "r" (i) : "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
usb_lld_sys_shutdown (void)
|
|
||||||
{
|
|
||||||
RCC->APB1ENR &= ~RCC_APB1ENR_USBEN;
|
|
||||||
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
|
|
||||||
usb_cable_config (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
usb_lld_sys_init (void)
|
|
||||||
{
|
|
||||||
if ((RCC->APB1ENR & RCC_APB1ENR_USBEN)
|
|
||||||
&& (RCC->APB1RSTR & RCC_APB1RSTR_USBRST) == 0)
|
|
||||||
/* Make sure the device is disconnected, even after core reset. */
|
|
||||||
{
|
|
||||||
usb_lld_sys_shutdown ();
|
|
||||||
/* Disconnect requires SE0 (>= 2.5uS). */
|
|
||||||
wait (300);
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_cable_config (1);
|
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
|
|
||||||
nvic_enable_vector (USB_LP_CAN1_RX0_IRQn,
|
|
||||||
CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY));
|
|
||||||
/*
|
|
||||||
* Note that we also have other IRQ(s):
|
|
||||||
* USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous)
|
|
||||||
* USBWakeUp_IRQn (suspend/resume)
|
|
||||||
*/
|
|
||||||
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
|
|
||||||
RCC->APB1RSTR = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FLASH_KEY1 0x45670123UL
|
|
||||||
#define FLASH_KEY2 0xCDEF89ABUL
|
|
||||||
|
|
||||||
enum flash_status
|
|
||||||
{
|
|
||||||
FLASH_BUSY = 1,
|
|
||||||
FLASH_ERROR_PG,
|
|
||||||
FLASH_ERROR_WRP,
|
|
||||||
FLASH_COMPLETE,
|
|
||||||
FLASH_TIMEOUT
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __attribute__ ((used))
|
|
||||||
flash_unlock (void)
|
|
||||||
{
|
|
||||||
FLASH->KEYR = FLASH_KEY1;
|
|
||||||
FLASH->KEYR = FLASH_KEY2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define intr_disable() asm volatile ("cpsid i" : : : "memory")
|
|
||||||
#define intr_enable() asm volatile ("cpsie i" : : : "memory")
|
|
||||||
|
|
||||||
#define FLASH_SR_BSY 0x01
|
|
||||||
#define FLASH_SR_PGERR 0x04
|
|
||||||
#define FLASH_SR_WRPRTERR 0x10
|
|
||||||
#define FLASH_SR_EOP 0x20
|
|
||||||
|
|
||||||
#define FLASH_CR_PG 0x0001
|
|
||||||
#define FLASH_CR_PER 0x0002
|
|
||||||
#define FLASH_CR_MER 0x0004
|
|
||||||
#define FLASH_CR_OPTPG 0x0010
|
|
||||||
#define FLASH_CR_OPTER 0x0020
|
|
||||||
#define FLASH_CR_STRT 0x0040
|
|
||||||
#define FLASH_CR_LOCK 0x0080
|
|
||||||
#define FLASH_CR_OPTWRE 0x0200
|
|
||||||
#define FLASH_CR_ERRIE 0x0400
|
|
||||||
#define FLASH_CR_EOPIE 0x1000
|
|
||||||
|
|
||||||
static int
|
|
||||||
flash_wait_for_last_operation (uint32_t timeout)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
status = FLASH->SR;
|
|
||||||
if (--timeout == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while ((status & FLASH_SR_BSY) != 0);
|
|
||||||
|
|
||||||
return status & (FLASH_SR_BSY|FLASH_SR_PGERR|FLASH_SR_WRPRTERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FLASH_PROGRAM_TIMEOUT 0x00010000
|
|
||||||
#define FLASH_ERASE_TIMEOUT 0x01000000
|
|
||||||
|
|
||||||
static int
|
|
||||||
flash_program_halfword (uint32_t addr, uint16_t data)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
|
|
||||||
|
|
||||||
intr_disable ();
|
|
||||||
if (status == 0)
|
|
||||||
{
|
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
|
||||||
|
|
||||||
*(volatile uint16_t *)addr = data;
|
|
||||||
|
|
||||||
status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
|
|
||||||
FLASH->CR &= ~FLASH_CR_PG;
|
|
||||||
}
|
|
||||||
intr_enable ();
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
flash_erase_page (uint32_t addr)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
|
|
||||||
|
|
||||||
intr_disable ();
|
|
||||||
if (status == 0)
|
|
||||||
{
|
|
||||||
FLASH->CR |= FLASH_CR_PER;
|
|
||||||
FLASH->AR = addr;
|
|
||||||
FLASH->CR |= FLASH_CR_STRT;
|
|
||||||
|
|
||||||
status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
|
|
||||||
FLASH->CR &= ~FLASH_CR_PER;
|
|
||||||
}
|
|
||||||
intr_enable ();
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
flash_check_blank (const uint8_t *p_start, size_t size)
|
|
||||||
{
|
|
||||||
const uint8_t *p;
|
|
||||||
|
|
||||||
for (p = p_start; p < p_start + size; p++)
|
|
||||||
if (*p != 0xff)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern uint8_t __flash_start__, __flash_end__;
|
|
||||||
|
|
||||||
static int
|
|
||||||
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
uint32_t flash_start = (uint32_t)&__flash_start__;
|
|
||||||
uint32_t flash_end = (uint32_t)&__flash_end__;
|
|
||||||
|
|
||||||
if (dst_addr < flash_start || dst_addr + len > flash_end)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (len)
|
|
||||||
{
|
|
||||||
uint16_t hw = *src++;
|
|
||||||
|
|
||||||
hw |= (*src++ << 8);
|
|
||||||
status = flash_program_halfword (dst_addr, hw);
|
|
||||||
if (status != 0)
|
|
||||||
return 0; /* error return */
|
|
||||||
|
|
||||||
dst_addr += 2;
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define OPTION_BYTES_ADDR 0x1ffff800
|
|
||||||
|
|
||||||
static int
|
|
||||||
flash_protect (void)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
uint32_t option_bytes_value;
|
|
||||||
|
|
||||||
status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
|
|
||||||
|
|
||||||
intr_disable ();
|
|
||||||
if (status == 0)
|
|
||||||
{
|
|
||||||
FLASH->OPTKEYR = FLASH_KEY1;
|
|
||||||
FLASH->OPTKEYR = FLASH_KEY2;
|
|
||||||
|
|
||||||
FLASH->CR |= FLASH_CR_OPTER;
|
|
||||||
FLASH->CR |= FLASH_CR_STRT;
|
|
||||||
|
|
||||||
status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
|
|
||||||
FLASH->CR &= ~FLASH_CR_OPTER;
|
|
||||||
}
|
|
||||||
intr_enable ();
|
|
||||||
|
|
||||||
if (status != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
option_bytes_value = *(uint32_t *)OPTION_BYTES_ADDR;
|
|
||||||
return (option_bytes_value & 0xff) == 0xff ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((naked))
|
|
||||||
flash_erase_all_and_exec (void (*entry)(void))
|
|
||||||
{
|
|
||||||
uint32_t addr = (uint32_t)&__flash_start__;
|
|
||||||
uint32_t end = (uint32_t)&__flash_end__;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
while (addr < end)
|
|
||||||
{
|
|
||||||
r = flash_erase_page (addr);
|
|
||||||
if (r != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
addr += FLASH_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr >= end)
|
|
||||||
(*entry) ();
|
|
||||||
|
|
||||||
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 *const) SCB_BASE);
|
|
||||||
|
|
||||||
#define SYSRESETREQ 0x04
|
|
||||||
static void
|
|
||||||
nvic_system_reset (void)
|
|
||||||
{
|
|
||||||
SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ);
|
|
||||||
asm volatile ("dsb");
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__ ((naked))
|
|
||||||
reset (void)
|
|
||||||
{
|
|
||||||
extern const unsigned long *FT0, *FT1, *FT2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This code may not be at the start of flash ROM, because of DFU.
|
|
||||||
* So, we take the address from PC.
|
|
||||||
*/
|
|
||||||
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
|
||||||
"ldr r0, 1f\n\t" /* r0 = SCR */
|
|
||||||
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
|
||||||
"mov r2, #0x1000\n\t"
|
|
||||||
"add r1, r1, r2\n\t"
|
|
||||||
"sub r2, r2, #1\n\t"
|
|
||||||
"bic r1, r1, r2\n\t"
|
|
||||||
"str r1, [r0, #8]\n\t" /* Set SCR->VCR */
|
|
||||||
"ldr r0, [r1], #4\n\t"
|
|
||||||
"msr MSP, r0\n\t" /* Main (exception handler) stack. */
|
|
||||||
"ldr r0, [r1]\n\t" /* Reset handler. */
|
|
||||||
"bx r0\n\t"
|
|
||||||
".align 2\n"
|
|
||||||
"1: .word 0xe000ed00"
|
|
||||||
: /* no output */ : /* no input */ : "memory");
|
|
||||||
|
|
||||||
/* Never reach here. */
|
|
||||||
/* Artificial entry to refer FT0, FT1, and FT2. */
|
|
||||||
asm volatile (""
|
|
||||||
: : "r" (FT0), "r" (FT1), "r" (FT2));
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef void (*handler)(void);
|
|
||||||
extern uint8_t __ram_end__;
|
|
||||||
|
|
||||||
handler vector[] __attribute__ ((section(".vectors"))) = {
|
|
||||||
(handler)&__ram_end__,
|
|
||||||
reset,
|
|
||||||
(handler)set_led,
|
|
||||||
flash_unlock,
|
|
||||||
(handler)flash_program_halfword,
|
|
||||||
(handler)flash_erase_page,
|
|
||||||
(handler)flash_check_blank,
|
|
||||||
(handler)flash_write,
|
|
||||||
(handler)flash_protect,
|
|
||||||
(handler)flash_erase_all_and_exec,
|
|
||||||
usb_lld_sys_init,
|
|
||||||
usb_lld_sys_shutdown,
|
|
||||||
nvic_system_reset,
|
|
||||||
clock_init,
|
|
||||||
gpio_init_primer2,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
|
|
||||||
3*2+2, /* bLength */
|
|
||||||
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE*/
|
|
||||||
/* sys version: "2.0" */
|
|
||||||
'2', 0, '.', 0, '0', 0,
|
|
||||||
};
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
extern const uint8_t sys_version[8];
|
|
||||||
|
|
||||||
typedef void (*handler)(void);
|
|
||||||
extern handler vector[16];
|
|
||||||
|
|
||||||
static inline const uint8_t *
|
|
||||||
unique_device_id (void)
|
|
||||||
{
|
|
||||||
/* STM32F103 has 96-bit unique device identifier */
|
|
||||||
const uint8_t *addr = (const uint8_t *)0x1ffff7e8;
|
|
||||||
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
set_led (int on)
|
|
||||||
{
|
|
||||||
void (*func) (int) = (void (*)(int))vector[2];
|
|
||||||
|
|
||||||
return (*func) (on);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
flash_unlock (void)
|
|
||||||
{
|
|
||||||
(*vector[3]) ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
flash_program_halfword (uint32_t addr, uint16_t data)
|
|
||||||
{
|
|
||||||
int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[4];
|
|
||||||
|
|
||||||
return (*func) (addr, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
flash_erase_page (uint32_t addr)
|
|
||||||
{
|
|
||||||
int (*func) (uint32_t) = (int (*)(uint32_t))vector[5];
|
|
||||||
|
|
||||||
return (*func) (addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
flash_check_blank (const uint8_t *p_start, size_t size)
|
|
||||||
{
|
|
||||||
int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[6];
|
|
||||||
|
|
||||||
return (*func) (p_start, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
flash_write (uint32_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];
|
|
||||||
|
|
||||||
return (*func) (dst_addr, src, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
flash_protect (void)
|
|
||||||
{
|
|
||||||
int (*func) (void) = (int (*)(void))vector[8];
|
|
||||||
|
|
||||||
return (*func) ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void __attribute__((noreturn))
|
|
||||||
flash_erase_all_and_exec (void (*entry)(void))
|
|
||||||
{
|
|
||||||
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))vector[9];
|
|
||||||
|
|
||||||
(*func) (entry);
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
usb_lld_sys_init (void)
|
|
||||||
{
|
|
||||||
(*vector[10]) ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
usb_lld_sys_shutdown (void)
|
|
||||||
{
|
|
||||||
(*vector[11]) ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
nvic_system_reset (void)
|
|
||||||
{
|
|
||||||
(*vector[12]) ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Users can override INLINE by 'attribute((used))' to have an
|
|
||||||
* implementation defined.
|
|
||||||
*/
|
|
||||||
#if !defined(INLINE)
|
|
||||||
#define INLINE __inline__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static INLINE void
|
|
||||||
clock_init (void)
|
|
||||||
{
|
|
||||||
(*vector[13]) ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static INLINE void
|
|
||||||
gpio_init (void)
|
|
||||||
{
|
|
||||||
(*vector[14]) ();
|
|
||||||
}
|
|
||||||
239
mcu/ABOUT-SYS
Normal file
239
mcu/ABOUT-SYS
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
Consideration about SYS and the first pages of flash ROM
|
||||||
|
========================================================
|
||||||
|
|
||||||
|
Now, I'm developing something like SYS for Kinetis L MCU, so, I write
|
||||||
|
this document.
|
||||||
|
|
||||||
|
* Compatibility
|
||||||
|
|
||||||
|
SYS 1.0: The first verson
|
||||||
|
SYS 2.0: Added clock_init, gpio_init
|
||||||
|
SYS 2.1: Added sys_board_id, sys_board_name
|
||||||
|
SYS 3.0: Don't setup NVIC priority by usb_lld_sys_init
|
||||||
|
|
||||||
|
|
||||||
|
* Macro definition by DEFS in Makefile
|
||||||
|
|
||||||
|
- USE_SYS_CLOCK_GPIO_SETTING
|
||||||
|
|
||||||
|
Define this macro to ask chopstx/entry.c (the runtime code before
|
||||||
|
MAIN function) to use function entries in SYS for clock_init and
|
||||||
|
gpio_init.
|
||||||
|
|
||||||
|
If not defined, entry.c includes the code for clock_init and
|
||||||
|
gpio_init which might be different to a board, and use them (entries
|
||||||
|
in SYS will not be used). This works well with the ROM of SYS
|
||||||
|
1.0.
|
||||||
|
|
||||||
|
Note that SYS entries of clock_init and gpio_init were introduced
|
||||||
|
in SYS 2.0. So, enable this macro only if the ROM is SYS 2.0 or
|
||||||
|
later.
|
||||||
|
|
||||||
|
- USE_SYS_BOARD_ID
|
||||||
|
|
||||||
|
Define this macro in a driver to get "sys_board_id" in SYS, so
|
||||||
|
that the driver can support various boards at runtime by changing
|
||||||
|
the settings according to the board.
|
||||||
|
|
||||||
|
A simple driver could only support a single board, by the compile
|
||||||
|
time (BOARD_ID in board-*.h) choice of of a settings.
|
||||||
|
|
||||||
|
Note that SYS entries of sys_board_id and sys_board_name were
|
||||||
|
introduced in SYS 2.1. So, enable this macro only if the ROM is
|
||||||
|
SYS 2.1 or later.
|
||||||
|
|
||||||
|
- USE_SYS3
|
||||||
|
|
||||||
|
By defining this, it will have same effect of defining both of
|
||||||
|
USE_SYS_CLOCK_GPIO_SETTING and USE_SYS_BOARD_ID internally.
|
||||||
|
|
||||||
|
|
||||||
|
About SYS on STM32F103
|
||||||
|
======================
|
||||||
|
|
||||||
|
In the development of Gnuk, we developed:
|
||||||
|
|
||||||
|
SYS: The system predefined routines for STM32F103
|
||||||
|
|
||||||
|
It is now maintained as example-cdc/sys.c.
|
||||||
|
|
||||||
|
There is another version in example-led/sys.c, which also support
|
||||||
|
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.
|
||||||
|
|
||||||
|
The original issue was:
|
||||||
|
|
||||||
|
(1) When it's protected, STM32F103 can't change the first 4KiB of
|
||||||
|
flash ROM at run time.
|
||||||
|
|
||||||
|
(2) We want to support firmware upgrade through its USB.
|
||||||
|
|
||||||
|
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
|
||||||
|
not need to be changed.
|
||||||
|
|
||||||
|
Now, the first 4KiB of flash ROM consists of:
|
||||||
|
|
||||||
|
1KiB: SYS
|
||||||
|
3KiB: 3/4 of AES forward tables
|
||||||
|
|
||||||
|
SYS consists of:
|
||||||
|
|
||||||
|
Internal: reset entry, end of RAM
|
||||||
|
Data: board identification
|
||||||
|
Routines: board specific
|
||||||
|
board independent
|
||||||
|
|
||||||
|
and here is the list of all.
|
||||||
|
|
||||||
|
* Internal routines
|
||||||
|
|
||||||
|
reset entry
|
||||||
|
end of RAM
|
||||||
|
|
||||||
|
* Board identification
|
||||||
|
|
||||||
|
sys_version
|
||||||
|
sys_board_id
|
||||||
|
sys_board_name
|
||||||
|
|
||||||
|
* Board specific routines
|
||||||
|
|
||||||
|
* led
|
||||||
|
set_led
|
||||||
|
|
||||||
|
* mcu/board lower level
|
||||||
|
clock_init
|
||||||
|
gpio_init
|
||||||
|
|
||||||
|
* usb
|
||||||
|
usb_lld_sys_init
|
||||||
|
usb_lld_sys_shutdown
|
||||||
|
|
||||||
|
* Board independent routines
|
||||||
|
|
||||||
|
* flash ROM access routines
|
||||||
|
|
||||||
|
unlock
|
||||||
|
write halfword
|
||||||
|
erase page
|
||||||
|
brank check
|
||||||
|
write page
|
||||||
|
protect
|
||||||
|
erase_all & exec to ram
|
||||||
|
|
||||||
|
* system reset routine
|
||||||
|
|
||||||
|
nvic_system_reset
|
||||||
|
|
||||||
|
The routines of clock_init and gpio_init are here because of some
|
||||||
|
historical reasons. (We could design a system with no such exported
|
||||||
|
routines: by defining: those things done internally after reset and
|
||||||
|
before calling the application.)
|
||||||
|
|
||||||
|
Those are exported as entries of SYS, and it is the responsibility of
|
||||||
|
the application which do initialize clock and GPIO, calling those
|
||||||
|
routines.
|
||||||
|
|
||||||
|
USB routines are needed because of hardware practice of STM32F103.
|
||||||
|
With STM32F103, each board has different way for handling the pull up
|
||||||
|
of USB D+ and how the device asks re-enumeration to host PC. In my
|
||||||
|
opinion, if it's defined as full speed device and it's OK for us not
|
||||||
|
to use high impedance (but asserting to LOW, instead) of D+ to ask
|
||||||
|
re-enumeration, we can just pull up D+ always. And we wouldn't need
|
||||||
|
such routines in SYS.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
About SYS on Kinetis L
|
||||||
|
======================
|
||||||
|
|
||||||
|
For Kinetis L, because it's ROM has the original firmware upgrade
|
||||||
|
support by the vendor (though USB HID), all that we needed for
|
||||||
|
firmware upgrade would be just erasing to factory settings.
|
||||||
|
|
||||||
|
And it has no limitation like STM32F103's first 4KiB flash ROM.
|
||||||
|
All pages can be updated at run time.
|
||||||
|
|
||||||
|
Nevertheless, the first two pages (2KiB) of KL27Z is still difficult
|
||||||
|
to use.
|
||||||
|
|
||||||
|
So, I decide to introduce something like SYS for Kinetis L.
|
||||||
|
|
||||||
|
|
||||||
|
* Layout
|
||||||
|
|
||||||
|
Three pages (3KiB) usage:
|
||||||
|
|
||||||
|
------------ The first page
|
||||||
|
End of RAM <-- not used but hardware defines this
|
||||||
|
Address of reset entry
|
||||||
|
sys_version
|
||||||
|
sys_board_info (id, name)
|
||||||
|
sys_vector
|
||||||
|
|
||||||
|
other SYS routines and data...
|
||||||
|
|
||||||
|
------------ The second page
|
||||||
|
FLASH CONFIG: 16-byte
|
||||||
|
Reset entry function
|
||||||
|
flash routines
|
||||||
|
CRC-32 routines
|
||||||
|
CRC-32 table (768-byte of CRC-32 table)
|
||||||
|
|
||||||
|
------------ The third page
|
||||||
|
MAGIC 256-byte (256-byte of the last part of CRC-32 table)
|
||||||
|
...
|
||||||
|
vectors (initial MSP, reset, ...)
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
* data: Board identification
|
||||||
|
|
||||||
|
sys_version
|
||||||
|
sys_board_id
|
||||||
|
sys_board_name ; null terminated
|
||||||
|
|
||||||
|
* Board specific routines
|
||||||
|
|
||||||
|
* mcu/board lower level
|
||||||
|
clock_init
|
||||||
|
gpio_init
|
||||||
|
|
||||||
|
* led
|
||||||
|
set_led
|
||||||
|
|
||||||
|
* data: Board independent routines
|
||||||
|
|
||||||
|
* flash ROM access code to be loaded on to RAM
|
||||||
|
|
||||||
|
* system reset routine???
|
||||||
|
|
||||||
|
nvic_system_reset
|
||||||
|
|
||||||
|
|
||||||
|
* data: vectors for routines and data
|
||||||
|
sys_version
|
||||||
|
sys_board_id
|
||||||
|
address of sys_board_name
|
||||||
|
address of set_led
|
||||||
|
address of clock_init
|
||||||
|
address of gpio_init
|
||||||
|
address of ...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
An Example of No-use of SYS
|
||||||
|
===========================
|
||||||
|
|
||||||
|
See example-fsm-55 for an example of no use of SYS.
|
||||||
|
|
||||||
|
While chopstx/entry.c defines vectors in ROM and RAM, those are simply
|
||||||
|
discarded by example-fsm-55/hacker-emblem.ld.
|
||||||
|
|
||||||
|
--
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* clk_gpio_init-kl.c - Clock and GPIO initialization for Kinetis L.
|
* clk_gpio_init-mkl27z.c - Clock and GPIO initialization for Kinetis L.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016 Flying Stone Technology
|
* Copyright (C) 2016 Flying Stone Technology
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "kl_sim.h"
|
#include <mcu/mkl27z.h>
|
||||||
|
|
||||||
struct MCG {
|
struct MCG {
|
||||||
volatile uint8_t C1; /* MCG Control Register 1 */
|
volatile uint8_t C1; /* MCG Control Register 1 */
|
||||||
@@ -231,7 +231,7 @@ clock_init (void)
|
|||||||
RCC->APB2RSTR = RCC_APB2RSTR_SYSCFGRST;
|
RCC->APB2RSTR = RCC_APB2RSTR_SYSCFGRST;
|
||||||
RCC->APB2RSTR = 0;
|
RCC->APB2RSTR = 0;
|
||||||
|
|
||||||
# if defined(HAVE_SYS_H)
|
# if defined(STM32F0_USE_VECTOR_ON_RAM)
|
||||||
/* Use vectors on RAM */
|
/* Use vectors on RAM */
|
||||||
SYSCFG->CFGR1 = (SYSCFG->CFGR1 & ~SYSCFG_CFGR1_MEM_MODE) | 3;
|
SYSCFG->CFGR1 = (SYSCFG->CFGR1 & ~SYSCFG_CFGR1_MEM_MODE) | 3;
|
||||||
# endif
|
# endif
|
||||||
204
mcu/stm32f103.h
Normal file
204
mcu/stm32f103.h
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
#define PERIPH_BASE 0x40000000
|
||||||
|
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||||
|
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||||
|
|
||||||
|
#define RCC_APB2RSTR_ADC1RST 0x00000200
|
||||||
|
#define RCC_APB2RSTR_ADC2RST 0x00000400
|
||||||
|
|
||||||
|
struct RCC {
|
||||||
|
volatile uint32_t CR;
|
||||||
|
volatile uint32_t CFGR;
|
||||||
|
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 *const)RCC_BASE);
|
||||||
|
|
||||||
|
#define RCC_AHBENR_DMA1EN 0x00000001
|
||||||
|
#define RCC_AHBENR_CRCEN 0x00000040
|
||||||
|
|
||||||
|
#define RCC_APB2ENR_ADC1EN 0x00000200
|
||||||
|
#define RCC_APB2ENR_ADC2EN 0x00000400
|
||||||
|
|
||||||
|
#define CRC_CR_RESET 0x00000001
|
||||||
|
|
||||||
|
struct CRC {
|
||||||
|
volatile uint32_t DR;
|
||||||
|
volatile uint8_t IDR;
|
||||||
|
uint8_t RESERVED0;
|
||||||
|
uint16_t RESERVED1;
|
||||||
|
volatile uint32_t CR;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CRC_BASE (AHBPERIPH_BASE + 0x3000)
|
||||||
|
static struct CRC *const CRC = ((struct CRC *const)CRC_BASE);
|
||||||
|
|
||||||
|
|
||||||
|
struct ADC {
|
||||||
|
volatile uint32_t SR;
|
||||||
|
volatile uint32_t CR1;
|
||||||
|
volatile uint32_t CR2;
|
||||||
|
volatile uint32_t SMPR1;
|
||||||
|
volatile uint32_t SMPR2;
|
||||||
|
volatile uint32_t JOFR1;
|
||||||
|
volatile uint32_t JOFR2;
|
||||||
|
volatile uint32_t JOFR3;
|
||||||
|
volatile uint32_t JOFR4;
|
||||||
|
volatile uint32_t HTR;
|
||||||
|
volatile uint32_t LTR;
|
||||||
|
volatile uint32_t SQR1;
|
||||||
|
volatile uint32_t SQR2;
|
||||||
|
volatile uint32_t SQR3;
|
||||||
|
volatile uint32_t JSQR;
|
||||||
|
volatile uint32_t JDR1;
|
||||||
|
volatile uint32_t JDR2;
|
||||||
|
volatile uint32_t JDR3;
|
||||||
|
volatile uint32_t JDR4;
|
||||||
|
volatile uint32_t DR;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ADC1_BASE (APB2PERIPH_BASE + 0x2400)
|
||||||
|
#define ADC2_BASE (APB2PERIPH_BASE + 0x2800)
|
||||||
|
|
||||||
|
static struct ADC *const ADC1 = (struct ADC *const)ADC1_BASE;
|
||||||
|
static struct ADC *const ADC2 = (struct ADC *const)ADC2_BASE;
|
||||||
|
|
||||||
|
#define ADC_CR1_DUALMOD_0 0x00010000
|
||||||
|
#define ADC_CR1_DUALMOD_1 0x00020000
|
||||||
|
#define ADC_CR1_DUALMOD_2 0x00040000
|
||||||
|
#define ADC_CR1_DUALMOD_3 0x00080000
|
||||||
|
|
||||||
|
#define ADC_CR1_SCAN 0x00000100
|
||||||
|
|
||||||
|
#define ADC_CR2_ADON 0x00000001
|
||||||
|
#define ADC_CR2_CONT 0x00000002
|
||||||
|
#define ADC_CR2_CAL 0x00000004
|
||||||
|
#define ADC_CR2_RSTCAL 0x00000008
|
||||||
|
#define ADC_CR2_DMA 0x00000100
|
||||||
|
#define ADC_CR2_ALIGN 0x00000800
|
||||||
|
#define ADC_CR2_EXTSEL 0x000E0000
|
||||||
|
#define ADC_CR2_EXTSEL_0 0x00020000
|
||||||
|
#define ADC_CR2_EXTSEL_1 0x00040000
|
||||||
|
#define ADC_CR2_EXTSEL_2 0x00080000
|
||||||
|
#define ADC_CR2_EXTTRIG 0x00100000
|
||||||
|
#define ADC_CR2_SWSTART 0x00400000
|
||||||
|
#define ADC_CR2_TSVREFE 0x00800000
|
||||||
|
|
||||||
|
struct DMA_Channel {
|
||||||
|
volatile uint32_t CCR;
|
||||||
|
volatile uint32_t CNDTR;
|
||||||
|
volatile uint32_t CPAR;
|
||||||
|
volatile uint32_t CMAR;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DMA {
|
||||||
|
volatile uint32_t ISR;
|
||||||
|
volatile uint32_t IFCR;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STM32_DMA_CR_MINC DMA_CCR1_MINC
|
||||||
|
#define STM32_DMA_CR_MSIZE_WORD DMA_CCR1_MSIZE_1
|
||||||
|
#define STM32_DMA_CR_PSIZE_WORD DMA_CCR1_PSIZE_1
|
||||||
|
#define STM32_DMA_CR_TCIE DMA_CCR1_TCIE
|
||||||
|
#define STM32_DMA_CR_TEIE DMA_CCR1_TEIE
|
||||||
|
#define STM32_DMA_CR_HTIE DMA_CCR1_HTIE
|
||||||
|
#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1
|
||||||
|
#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1
|
||||||
|
#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1
|
||||||
|
|
||||||
|
#define STM32_DMA_ISR_MASK 0x0F
|
||||||
|
#define STM32_DMA_CCR_RESET_VALUE 0x00000000
|
||||||
|
#define STM32_DMA_CR_PL_MASK DMA_CCR1_PL
|
||||||
|
#define STM32_DMA_CR_PL(n) ((n) << 12)
|
||||||
|
|
||||||
|
#define DMA_CCR1_EN 0x00000001
|
||||||
|
#define DMA_CCR1_TCIE 0x00000002
|
||||||
|
#define DMA_CCR1_HTIE 0x00000004
|
||||||
|
#define DMA_CCR1_TEIE 0x00000008
|
||||||
|
#define DMA_CCR1_DIR 0x00000010
|
||||||
|
#define DMA_CCR1_CIRC 0x00000020
|
||||||
|
#define DMA_CCR1_PINC 0x00000040
|
||||||
|
#define DMA_CCR1_MINC 0x00000080
|
||||||
|
#define DMA_CCR1_PSIZE 0x00000300
|
||||||
|
#define DMA_CCR1_PSIZE_0 0x00000100
|
||||||
|
#define DMA_CCR1_PSIZE_1 0x00000200
|
||||||
|
#define DMA_CCR1_MSIZE 0x00000C00
|
||||||
|
#define DMA_CCR1_MSIZE_0 0x00000400
|
||||||
|
#define DMA_CCR1_MSIZE_1 0x00000800
|
||||||
|
#define DMA_CCR1_PL 0x00003000
|
||||||
|
#define DMA_CCR1_PL_0 0x00001000
|
||||||
|
#define DMA_CCR1_PL_1 0x00002000
|
||||||
|
#define DMA_CCR1_MEM2MEM 0x00004000
|
||||||
|
|
||||||
|
#define DMA_ISR_GIF1 0x00000001
|
||||||
|
#define DMA_ISR_TCIF1 0x00000002
|
||||||
|
#define DMA_ISR_HTIF1 0x00000004
|
||||||
|
#define DMA_ISR_TEIF1 0x00000008
|
||||||
|
#define DMA_ISR_GIF2 0x00000010
|
||||||
|
#define DMA_ISR_TCIF2 0x00000020
|
||||||
|
#define DMA_ISR_HTIF2 0x00000040
|
||||||
|
#define DMA_ISR_TEIF2 0x00000080
|
||||||
|
#define DMA_ISR_GIF3 0x00000100
|
||||||
|
#define DMA_ISR_TCIF3 0x00000200
|
||||||
|
#define DMA_ISR_HTIF3 0x00000400
|
||||||
|
#define DMA_ISR_TEIF3 0x00000800
|
||||||
|
#define DMA_ISR_GIF4 0x00001000
|
||||||
|
#define DMA_ISR_TCIF4 0x00002000
|
||||||
|
#define DMA_ISR_HTIF4 0x00004000
|
||||||
|
#define DMA_ISR_TEIF4 0x00008000
|
||||||
|
#define DMA_ISR_GIF5 0x00010000
|
||||||
|
#define DMA_ISR_TCIF5 0x00020000
|
||||||
|
#define DMA_ISR_HTIF5 0x00040000
|
||||||
|
#define DMA_ISR_TEIF5 0x00080000
|
||||||
|
#define DMA_ISR_GIF6 0x00100000
|
||||||
|
#define DMA_ISR_TCIF6 0x00200000
|
||||||
|
#define DMA_ISR_HTIF6 0x00400000
|
||||||
|
#define DMA_ISR_TEIF6 0x00800000
|
||||||
|
#define DMA_ISR_GIF7 0x01000000
|
||||||
|
#define DMA_ISR_TCIF7 0x02000000
|
||||||
|
#define DMA_ISR_HTIF7 0x04000000
|
||||||
|
#define DMA_ISR_TEIF7 0x08000000
|
||||||
|
|
||||||
|
#define DMA1_BASE (AHBPERIPH_BASE + 0x0000)
|
||||||
|
static struct DMA *const DMA1 = (struct DMA *const)DMA1_BASE;
|
||||||
|
|
||||||
|
#define DMA1_Channel1_BASE (AHBPERIPH_BASE + 0x0008)
|
||||||
|
static struct DMA_Channel *const DMA1_Channel1 =
|
||||||
|
(struct DMA_Channel *const)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 *const)SCB_BASE;
|
||||||
414
mcu/sys-mkl27z.c
Normal file
414
mcu/sys-mkl27z.c
Normal file
@@ -0,0 +1,414 @@
|
|||||||
|
/*
|
||||||
|
* sys.c - First pages for MKL27Z256.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Flying Stone Technology
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* Copying and distribution of this file, with or without modification,
|
||||||
|
* are permitted in any medium without royalty provided the copyright
|
||||||
|
* notice and this notice are preserved. This file is offered as-is,
|
||||||
|
* without any warranty.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* First two pages of Flash ROM is difficult to use because of
|
||||||
|
* predefined purposes. It's defined as a default vector page and
|
||||||
|
* a flash configuration page.
|
||||||
|
*
|
||||||
|
* We put something useful to those two pages, together with the
|
||||||
|
* data for predefined purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
#define ADDR_VECTORS (0x00000900)
|
||||||
|
#define ADDR_SCR_VTOR 0xe000ed08
|
||||||
|
|
||||||
|
static void __attribute__ ((naked,section(".fixed_function.reset")))
|
||||||
|
reset (void)
|
||||||
|
{
|
||||||
|
uint32_t r3 = ADDR_SCR_VTOR;
|
||||||
|
|
||||||
|
asm volatile ("str %2, [%0]\n\t" /* Set SCR->VTOR */
|
||||||
|
"ldr %0, [%2]\n\t" /* Stack address */
|
||||||
|
"msr MSP, %0\n\t" /* Exception handler stack. */
|
||||||
|
"ldr %0, [%2, #4]\n\t" /* The entry address */
|
||||||
|
"bx %0\n\t" /* Jump to the entry */
|
||||||
|
".align 2"
|
||||||
|
: "=r" (r3)
|
||||||
|
: "0" (r3), "r" (ADDR_VECTORS)
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
/* Never reach here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
stack_entry[] __attribute__ ((section(".first_page.first_words"),used)) = {
|
||||||
|
/* Since MSP are soon modified in RESET, we put 0 here. */
|
||||||
|
0,
|
||||||
|
(uint32_t)reset,
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "mcu/clk_gpio_init-mkl27z.c"
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_led (int on)
|
||||||
|
{
|
||||||
|
if (on)
|
||||||
|
GPIOB->PCOR = (1 << 0); /* PTB0: Clear: Light on */
|
||||||
|
else
|
||||||
|
GPIOB->PSOR = (1 << 0); /* PTB0: Set : Light off */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here comes other SYS routines and data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
|
||||||
|
3*2+2, /* bLength */
|
||||||
|
0x03, /* bDescriptorType = STRING_DESCRIPTOR */
|
||||||
|
/* sys version: "3.0" */
|
||||||
|
'3', 0, '.', 0, '0', 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t board_name_string[] = BOARD_NAME;
|
||||||
|
|
||||||
|
const uint8_t __attribute__((section(".sys.board_info")))
|
||||||
|
*const sys_board_name = board_name_string;
|
||||||
|
|
||||||
|
const uint32_t __attribute__((section(".sys.board_info")))
|
||||||
|
sys_board_id = BOARD_ID;
|
||||||
|
|
||||||
|
typedef void (*handler)(void);
|
||||||
|
|
||||||
|
handler sys_vector[] __attribute__ ((section(".sys.vectors"))) = {
|
||||||
|
clock_init,
|
||||||
|
gpio_init,
|
||||||
|
(handler)set_led,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
flash_config[] __attribute__ ((section(".flash_config"),used)) = {
|
||||||
|
0xffffffff, 0xffffffff, /* Comparison Key */
|
||||||
|
0xffffffff, /* Protection bytes */
|
||||||
|
0xffff3ffe, /* FSEC=0xfe, FOPT=0x3f */
|
||||||
|
/* FOPT=0x3f:
|
||||||
|
* BOOTSRC_SEL=00: Boot from flash
|
||||||
|
*/
|
||||||
|
/* FSEC=0xfe:
|
||||||
|
* unsecure
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flash memory routine
|
||||||
|
*/
|
||||||
|
struct FTFA {
|
||||||
|
volatile uint8_t FSTAT;
|
||||||
|
volatile uint8_t FCNFG;
|
||||||
|
volatile uint8_t FSEC;
|
||||||
|
volatile uint8_t FOPT;
|
||||||
|
/* Note: addressing (3,2,1,0, 7,6,5,4, B,A,9,8) */
|
||||||
|
/* Use Bx macro. */
|
||||||
|
volatile uint8_t FCCO[12];
|
||||||
|
/* Note: addressing (3,2,1,0). Use Bx macro. */
|
||||||
|
volatile uint8_t FPROT[4];
|
||||||
|
};
|
||||||
|
static struct FTFA *const FTFA = (struct FTFA *const)0x40020000;
|
||||||
|
|
||||||
|
#define FSTAT_CCIF 0x80
|
||||||
|
#define B3 0
|
||||||
|
#define B2 1
|
||||||
|
#define B1 2
|
||||||
|
#define B0 3
|
||||||
|
#define B7 4
|
||||||
|
#define B6 5
|
||||||
|
#define B5 6
|
||||||
|
#define B4 7
|
||||||
|
#define BB 8
|
||||||
|
#define BA 9
|
||||||
|
#define B9 10
|
||||||
|
#define B8 11
|
||||||
|
|
||||||
|
uint32_t __attribute__ ((naked,section(".fixed_function.flash_do_internal")))
|
||||||
|
flash_do_internal (void)
|
||||||
|
{
|
||||||
|
#ifdef ORIGINAL_IN_C
|
||||||
|
uint8_t r;
|
||||||
|
|
||||||
|
asm volatile ("cpsid i" : : : "memory");
|
||||||
|
FTFA->FSTAT |= FSTAT_CCIF;
|
||||||
|
while (((r = FTFA->FSTAT) & FSTAT_CCIF) == 0)
|
||||||
|
;
|
||||||
|
r &= ~FSTAT_CCIF;
|
||||||
|
asm volatile ("cpsie i" : : : "memory");
|
||||||
|
|
||||||
|
return (uint32_t)r;
|
||||||
|
#else
|
||||||
|
register unsigned int r0 asm ("r0");
|
||||||
|
register unsigned int r1 asm ("r1") = (unsigned int)FTFA;
|
||||||
|
register unsigned int r2 asm ("r2") = FSTAT_CCIF;
|
||||||
|
|
||||||
|
asm volatile ("cpsid i\n\t"
|
||||||
|
"ldrb %0, [%1]\n\t"
|
||||||
|
"orr %0, %2\n\t"
|
||||||
|
"strb %0, [%1]\n"
|
||||||
|
"0:\t"
|
||||||
|
"ldrb %0, [%1]\n\t"
|
||||||
|
"uxtb %0, %0\n\t"
|
||||||
|
"tst %0, %2\n\t"
|
||||||
|
"beq 0b\n\t"
|
||||||
|
"cpsie i\n\t"
|
||||||
|
"bic %0, %2\n\t"
|
||||||
|
"bx lr"
|
||||||
|
: "=r" (r0)
|
||||||
|
: "r" (r1), "r" (r2)
|
||||||
|
: "memory");
|
||||||
|
return r0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let execute flash command.
|
||||||
|
* Since the code should be on RAM, we copy the code onto stack
|
||||||
|
* and let it go.
|
||||||
|
*/
|
||||||
|
uint32_t __attribute__ ((naked,section(".fixed_function.flash_do")))
|
||||||
|
flash_do (void)
|
||||||
|
{
|
||||||
|
register unsigned int r0 asm ("r0");
|
||||||
|
register unsigned int r1 asm ("r1");
|
||||||
|
register unsigned int r2 asm ("r2");
|
||||||
|
register unsigned int r3 asm ("r3") = (unsigned int)flash_do_internal&~3;
|
||||||
|
/* Address of Thumb code &1 == 1, so, we clear the last bits. ------^ */
|
||||||
|
|
||||||
|
asm volatile ("sub sp, #32\n\t"
|
||||||
|
"mov %1, sp\n\t"
|
||||||
|
"mov %2, #0\n"
|
||||||
|
"0:\t"
|
||||||
|
"cmp %2, #32\n\t"
|
||||||
|
"beq 1f\n\t"
|
||||||
|
"ldr %0, [%3, %2]\n\t"
|
||||||
|
"str %0, [%1, %2]\n\t"
|
||||||
|
"add %2, #4\n\t"
|
||||||
|
"b 0b\n"
|
||||||
|
"1:\t"
|
||||||
|
"add %1, #1\n\t" /* Thumb code requires LSB=1. */
|
||||||
|
"mov %3, lr\n\t"
|
||||||
|
"blx %1\n\t"
|
||||||
|
"add sp, #32\n\t"
|
||||||
|
"bx %3"
|
||||||
|
: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
|
||||||
|
: "3" (r3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FLASH_COMMAND_PROGRAM_LONGWORD 0x06
|
||||||
|
#define FLASH_COMMAND_ERASE_FLASH_SECTOR 0x09
|
||||||
|
|
||||||
|
int __attribute__ ((naked,section(".fixed_function.flash_erase_page")))
|
||||||
|
flash_erase_page (uint32_t addr)
|
||||||
|
{
|
||||||
|
#ifdef ORIGINAL_IN_C
|
||||||
|
FTFA->FCCO[B0] = FLASH_COMMAND_ERASE_FLASH_SECTOR;
|
||||||
|
FTFA->FCCO[B3] = (addr >> 0) & 0xff;
|
||||||
|
FTFA->FCCO[B2] = (addr >> 8) & 0xff;
|
||||||
|
FTFA->FCCO[B1] = (addr >> 16) & 0xff;
|
||||||
|
flash_do ();
|
||||||
|
#else
|
||||||
|
register unsigned int r0 asm ("r0") = addr;
|
||||||
|
register unsigned int r1 asm ("r1");
|
||||||
|
register unsigned int r2 asm ("r2") = FLASH_COMMAND_ERASE_FLASH_SECTOR;
|
||||||
|
register unsigned int r3 asm ("r3") = (unsigned int)FTFA;
|
||||||
|
|
||||||
|
asm volatile ("strb %2, [%3, #7]\n\t"
|
||||||
|
"strb %0, [%3, #4]\n\t"
|
||||||
|
"lsr %0, #8\n\t"
|
||||||
|
"strb %0, [%3, #5]\n\t"
|
||||||
|
"lsr %0, #8\n\t"
|
||||||
|
"strb %0, [%3, #6]\n\t"
|
||||||
|
"b flash_do"
|
||||||
|
: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
|
||||||
|
: "0" (r0), "2" (r2), "3" (r3));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__ ((naked,section(".fixed_function.flash_program_word")))
|
||||||
|
flash_program_word (uint32_t addr, uint32_t word)
|
||||||
|
{
|
||||||
|
#ifdef ORIGINAL_IN_C
|
||||||
|
FTFA->FCCO[B0] = FLASH_COMMAND_PROGRAM_LONGWORD;
|
||||||
|
FTFA->FCCO[B3] = (addr >> 0) & 0xff;
|
||||||
|
FTFA->FCCO[B2] = (addr >> 8) & 0xff;
|
||||||
|
FTFA->FCCO[B1] = (addr >> 16) & 0xff;
|
||||||
|
FTFA->FCCO[B4] = (word >> 0) & 0xff;
|
||||||
|
FTFA->FCCO[B5] = (word >> 8) & 0xff;
|
||||||
|
FTFA->FCCO[B6] = (word >> 16) & 0xff;
|
||||||
|
FTFA->FCCO[B7] = (word >> 24) & 0xff;
|
||||||
|
flash_do ();
|
||||||
|
#else
|
||||||
|
register unsigned int r0 asm ("r0") = addr;
|
||||||
|
register unsigned int r1 asm ("r1") = word;
|
||||||
|
register unsigned int r2 asm ("r2") = FLASH_COMMAND_PROGRAM_LONGWORD;
|
||||||
|
register unsigned int r3 asm ("r3") = (unsigned int)FTFA;
|
||||||
|
|
||||||
|
asm volatile ("strb %2, [%3, #7]\n\t"
|
||||||
|
"strb %0, [%3, #4]\n\t"
|
||||||
|
"lsr %0, #8\n\t"
|
||||||
|
"strb %0, [%3, #5]\n\t"
|
||||||
|
"lsr %0, #8\n\t"
|
||||||
|
"strb %0, [%3, #6]\n\t"
|
||||||
|
"strb %1, [%3, #11]\n\t"
|
||||||
|
"lsr %1, #8\n\t"
|
||||||
|
"strb %1, [%3, #10]\n\t"
|
||||||
|
"lsr %1, #8\n\t"
|
||||||
|
"strb %1, [%3, #9]\n\t"
|
||||||
|
"lsr %1, #8\n\t"
|
||||||
|
"strb %1, [%3, #8]\n\t"
|
||||||
|
"b flash_do"
|
||||||
|
: "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
|
||||||
|
: "0" (r0), "1" (r1), "2" (r2), "3" (r3));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CRC32 calculation routines.
|
||||||
|
*/
|
||||||
|
void __attribute__ ((naked,section(".fixed_function.crc32_init")))
|
||||||
|
crc32_init (unsigned int *p)
|
||||||
|
{
|
||||||
|
#ifdef ORIGINAL_IN_C
|
||||||
|
*p = 0xffffffff;
|
||||||
|
#else
|
||||||
|
register unsigned int r3 asm ("r3");
|
||||||
|
|
||||||
|
asm volatile ("mov %0, #1\n\t"
|
||||||
|
"neg %0, %0\n\t"
|
||||||
|
"str %0, [%1]\n\t"
|
||||||
|
"bx lr"
|
||||||
|
: "=r" (r3)
|
||||||
|
: "r" (p)
|
||||||
|
: "memory");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ORIGINAL_IN_C
|
||||||
|
const unsigned int *const crc32_table= (const unsigned int *const)0x00000500;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void __attribute__ ((naked,section(".fixed_function.crc32_u8")))
|
||||||
|
crc32_u8 (unsigned int *p, unsigned char v)
|
||||||
|
{
|
||||||
|
#ifdef ORIGINAL_IN_C
|
||||||
|
*p = crc32_table[(*p & 0xff) ^ v] ^ (*p >> 8);
|
||||||
|
#else
|
||||||
|
register unsigned int r2 asm ("r2");
|
||||||
|
register unsigned int r3 asm ("r3");
|
||||||
|
|
||||||
|
asm volatile ("ldrb %2, [%4]\n\t"
|
||||||
|
"eor %0, %2\n\t"
|
||||||
|
"mov %2, #0xa0\n\t" /* (0x0500 >> 3) */
|
||||||
|
"lsl %0, %0, #2\n\t"
|
||||||
|
"lsl %2, %2, #3\n\t"
|
||||||
|
"add %0, %0, %2\n\t"
|
||||||
|
"ldr %2, [%4]\n\t"
|
||||||
|
"ldr %1, [%0]\n\t"
|
||||||
|
"lsr %2, %2, #8\n\t"
|
||||||
|
"eor %2, %1\n\t"
|
||||||
|
"str %2, [%4]\n\t"
|
||||||
|
"bx lr"
|
||||||
|
: "=r" (v), "=r" (r2), "=r" (r3)
|
||||||
|
: "0" (v), "r" (p)
|
||||||
|
: "memory");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__ ((naked,section(".fixed_function.crc32_u32")))
|
||||||
|
crc32_u32 (unsigned int *p, unsigned int u)
|
||||||
|
{
|
||||||
|
#ifdef ORIGINAL_IN_C
|
||||||
|
crc32_u8 (p, u & 0xff);
|
||||||
|
crc32_u8 (p, (u >> 8)& 0xff);
|
||||||
|
crc32_u8 (p, (u >> 16)& 0xff);
|
||||||
|
crc32_u8 (p, (u >> 24)& 0xff);
|
||||||
|
#else
|
||||||
|
register unsigned int r3 asm ("r3");
|
||||||
|
register unsigned int r4 asm ("r4");
|
||||||
|
register unsigned int r5 asm ("r5");
|
||||||
|
|
||||||
|
asm volatile ("push {%1, %2, %3, lr}\n\t"
|
||||||
|
"mov %2, %0\n\t"
|
||||||
|
"mov %3, %5\n\t"
|
||||||
|
"uxtb %0, %0\n\t"
|
||||||
|
"bl crc32_u8\n\t"
|
||||||
|
"lsr %0, %2, #8\n\t"
|
||||||
|
"mov %5, %3\n\t"
|
||||||
|
"uxtb %0, %0\n\t"
|
||||||
|
"bl crc32_u8\n\t"
|
||||||
|
"lsr %0, %2, #16\n\t"
|
||||||
|
"mov %5, %3\n\t"
|
||||||
|
"uxtb %0, %0\n\t"
|
||||||
|
"bl crc32_u8\n\t"
|
||||||
|
"mov %5, %3\n\t"
|
||||||
|
"lsr %0, %2, #24\n\t"
|
||||||
|
"bl crc32_u8\n\t"
|
||||||
|
"pop {%1, %2, %3, pc}"
|
||||||
|
: "=r" (u), "=r" (r3), "=r" (r4), "=r" (r5)
|
||||||
|
: "0" (u), "r" (p)
|
||||||
|
: "memory");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table of CRC32, generated by gen_crc_table.py
|
||||||
|
*/
|
||||||
|
const unsigned int
|
||||||
|
crc32_table[256] __attribute__ ((section(".crc32_table"))) = {
|
||||||
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||||
|
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||||
|
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||||
|
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||||
|
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||||
|
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||||
|
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||||
|
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||||
|
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||||
|
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||||
|
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||||
|
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||||
|
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||||
|
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||||
|
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||||
|
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||||
|
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||||
|
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||||
|
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||||
|
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||||
|
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||||
|
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||||
|
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||||
|
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||||
|
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||||
|
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||||
|
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||||
|
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||||
|
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||||
|
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||||
|
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||||
|
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||||
|
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||||
|
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||||
|
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||||
|
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||||
|
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||||
|
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||||
|
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||||
|
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||||
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||||
|
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||||
|
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||||
|
};
|
||||||
39
mcu/sys-mkl27z.h
Normal file
39
mcu/sys-mkl27z.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
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 char *const sys_board_name;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*handler)(void);
|
||||||
|
extern handler sys_vector[16];
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_led (int on)
|
||||||
|
{
|
||||||
|
void (*func) (int) = (void (*)(int))sys_vector[2];
|
||||||
|
|
||||||
|
return (*func) (on);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crc32_init (unsigned int *);
|
||||||
|
void crc32_u8 (unsigned int *, unsigned char);
|
||||||
|
void crc32_u32 (unsigned int *, unsigned int);
|
||||||
|
|
||||||
|
int flash_erase_page (uint32_t addr);
|
||||||
|
int flash_program_word (uint32_t addr, uint32_t word);
|
||||||
|
|
||||||
|
#ifdef REQUIRE_CLOCK_GPIO_SETTING_IN_SYS
|
||||||
|
/* Provide the function entries. */
|
||||||
|
|
||||||
|
static void __attribute__ ((used))
|
||||||
|
clock_init (void)
|
||||||
|
{
|
||||||
|
(*sys_vector[0]) ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__ ((used))
|
||||||
|
gpio_init (void)
|
||||||
|
{
|
||||||
|
(*sys_vector[1]) ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* sys.c - system routines for the initial page for STM32F103.
|
* sys.c - system routines for the initial page for STM32F030 / STM32F103.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013, 2014, 2015, 2016 Flying Stone Technology
|
* Copyright (C) 2013, 2014, 2015, 2016 Flying Stone Technology
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
*
|
*
|
||||||
* Copying and distribution of this file, with or without modification,
|
* Copying and distribution of this file, with or without modification,
|
||||||
@@ -17,7 +17,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
|
||||||
#include "clk_gpio_init-stm32.c"
|
#define STM32F0_USE_VECTOR_ON_RAM
|
||||||
|
#include "mcu/clk_gpio_init-stm32.c"
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -203,11 +204,17 @@ flash_check_blank (const uint8_t *p_start, size_t size)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FLASH_START_ADDR 0x08000000 /* Fixed for all STM32F1. */
|
#define FLASH_START_ADDR 0x08000000 /* Fixed for all STM32F0/F1. */
|
||||||
#define FLASH_OFFSET 0x1000 /* First pages are not-writable. */
|
#define FLASH_OFFSET 0x1000 /* First pages are not-writable
|
||||||
#define FLASH_START (FLASH_START_ADDR+FLASH_OFFSET)
|
when protected. */
|
||||||
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
|
#if defined(__ARM_ARCH_6M__)
|
||||||
|
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7cc)
|
||||||
|
#define CHIP_ID_REG ((uint32_t *)0x40015800)
|
||||||
|
#else
|
||||||
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
|
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
|
||||||
|
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
|
||||||
|
#endif
|
||||||
|
#define FLASH_START (FLASH_START_ADDR+FLASH_OFFSET)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
||||||
@@ -330,12 +337,33 @@ nvic_system_reset (void)
|
|||||||
static void __attribute__ ((naked))
|
static void __attribute__ ((naked))
|
||||||
reset (void)
|
reset (void)
|
||||||
{
|
{
|
||||||
extern const unsigned long *FT0, *FT1, *FT2;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This code may not be at the start of flash ROM, because of DFU.
|
* This code may not be at the start of flash ROM, because of DFU.
|
||||||
* So, we take the address from PC.
|
* So, we take the address from PC.
|
||||||
*/
|
*/
|
||||||
|
#if defined(__ARM_ARCH_6M__)
|
||||||
|
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
||||||
|
"ldr r0, 1f\n\t" /* r0 = RAM start */
|
||||||
|
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
||||||
|
"mov r2, #0x10\n\t"
|
||||||
|
"lsl r2, #8\n\t"
|
||||||
|
"add r1, r1, r2\n\t"
|
||||||
|
"sub r2, r2, #1\n\t"
|
||||||
|
"bic r1, r1, r2\n\t"
|
||||||
|
"mov r2, #188\n"
|
||||||
|
"2:\n\t" /* Copy vectors. It will be enabled later by clock_init. */
|
||||||
|
"ldr r3, [r1, r2]\n\t"
|
||||||
|
"str r3, [r0, r2]\n\t"
|
||||||
|
"sub r2, #4\n\t"
|
||||||
|
"bcs 2b\n\t"
|
||||||
|
"msr MSP, r3\n\t" /* Main (exception handler) stack. */
|
||||||
|
"ldr r0, [r1, #4]\n\t" /* Reset handler. */
|
||||||
|
"bx r0\n\t"
|
||||||
|
".align 2\n"
|
||||||
|
"1: .word 0x20000000"
|
||||||
|
: /* no output */ : /* no input */ : "memory");
|
||||||
|
#else
|
||||||
|
extern const uint32_t FT0[256], FT1[256], FT2[256];
|
||||||
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
||||||
"ldr r0, 1f\n\t" /* r0 = SCR */
|
"ldr r0, 1f\n\t" /* r0 = SCR */
|
||||||
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
||||||
@@ -351,11 +379,11 @@ reset (void)
|
|||||||
".align 2\n"
|
".align 2\n"
|
||||||
"1: .word 0xe000ed00"
|
"1: .word 0xe000ed00"
|
||||||
: /* no output */ : /* no input */ : "memory");
|
: /* no output */ : /* no input */ : "memory");
|
||||||
|
|
||||||
/* Never reach here. */
|
|
||||||
/* Artificial entry to refer FT0, FT1, and FT2. */
|
/* Artificial entry to refer FT0, FT1, and FT2. */
|
||||||
asm volatile (""
|
asm volatile (""
|
||||||
: : "r" (FT0), "r" (FT1), "r" (FT2));
|
: : "r" (FT0), "r" (FT1), "r" (FT2));
|
||||||
|
#endif
|
||||||
|
/* Never reach here. */
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*handler)(void);
|
typedef void (*handler)(void);
|
||||||
@@ -16,8 +16,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const uint8_t sys_version[8];
|
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 uint32_t sys_board_id;
|
||||||
extern const uint8_t sys_board_name[];
|
extern const uint8_t sys_board_name[];
|
||||||
|
#else
|
||||||
|
# define SYS_BOARD_ID BOARD_ID
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef void (*handler)(void);
|
typedef void (*handler)(void);
|
||||||
extern handler vector[16];
|
extern handler vector[16];
|
||||||
@@ -113,22 +117,18 @@ nvic_system_reset (void)
|
|||||||
(*vector[12]) ();
|
(*vector[12]) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#ifdef REQUIRE_CLOCK_GPIO_SETTING_IN_SYS
|
||||||
* Users can override INLINE by 'attribute((used))' to have an
|
/* Provide the function entries. */
|
||||||
* implementation defined.
|
|
||||||
*/
|
|
||||||
#if !defined(INLINE)
|
|
||||||
#define INLINE __inline__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static INLINE void
|
static void __attribute__ ((used))
|
||||||
clock_init (void)
|
clock_init (void)
|
||||||
{
|
{
|
||||||
(*vector[13]) ();
|
(*vector[13]) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE void
|
static void __attribute__ ((used))
|
||||||
gpio_init (void)
|
gpio_init (void)
|
||||||
{
|
{
|
||||||
(*vector[14]) ();
|
(*vector[14]) ();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* sys.c - system routines for the initial page for STM32F030 / STM32F103.
|
* sys.c - system routines for the initial page for STM32F103.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013, 2014, 2015 Flying Stone Technology
|
* Copyright (C) 2013, 2014, 2015, 2016 Flying Stone Technology
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
*
|
*
|
||||||
* Copying and distribution of this file, with or without modification,
|
* Copying and distribution of this file, with or without modification,
|
||||||
@@ -17,41 +17,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
|
||||||
#include "clk_gpio_init-stm32.c"
|
#include "mcu/clk_gpio_init-stm32.c"
|
||||||
|
|
||||||
#define CORTEX_PRIORITY_BITS 4
|
|
||||||
#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS))
|
|
||||||
#define USB_LP_CAN1_RX0_IRQn 20
|
|
||||||
#define STM32_USB_IRQ_PRIORITY 11
|
|
||||||
|
|
||||||
struct NVIC {
|
|
||||||
volatile uint32_t ISER[8];
|
|
||||||
volatile uint32_t unused1[24];
|
|
||||||
volatile uint32_t ICER[8];
|
|
||||||
volatile uint32_t unused2[24];
|
|
||||||
volatile uint32_t ISPR[8];
|
|
||||||
volatile uint32_t unused3[24];
|
|
||||||
volatile uint32_t ICPR[8];
|
|
||||||
volatile uint32_t unused4[24];
|
|
||||||
volatile uint32_t IABR[8];
|
|
||||||
volatile uint32_t unused5[56];
|
|
||||||
volatile uint32_t IPR[60];
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct NVIC *const NVICBase = ((struct NVIC *const)0xE000E100);
|
|
||||||
#define NVIC_ISER(n) (NVICBase->ISER[n >> 5])
|
|
||||||
#define NVIC_ICPR(n) (NVICBase->ICPR[n >> 5])
|
|
||||||
#define NVIC_IPR(n) (NVICBase->IPR[n >> 2])
|
|
||||||
|
|
||||||
static void
|
|
||||||
nvic_enable_vector (uint32_t n, uint32_t prio)
|
|
||||||
{
|
|
||||||
unsigned int sh = (n & 3) << 3;
|
|
||||||
|
|
||||||
NVIC_IPR (n) = (NVIC_IPR(n) & ~(0xFF << sh)) | (prio << sh);
|
|
||||||
NVIC_ICPR (n) = 1 << (n & 0x1F);
|
|
||||||
NVIC_ISER (n) = 1 << (n & 0x1F);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usb_cable_config (int enable)
|
usb_cable_config (int enable)
|
||||||
@@ -118,13 +85,6 @@ usb_lld_sys_init (void)
|
|||||||
|
|
||||||
usb_cable_config (1);
|
usb_cable_config (1);
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
|
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
|
||||||
nvic_enable_vector (USB_LP_CAN1_RX0_IRQn,
|
|
||||||
CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY));
|
|
||||||
/*
|
|
||||||
* Note that we also have other IRQ(s):
|
|
||||||
* USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous)
|
|
||||||
* USBWakeUp_IRQn (suspend/resume)
|
|
||||||
*/
|
|
||||||
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
|
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
|
||||||
RCC->APB1RSTR = 0;
|
RCC->APB1RSTR = 0;
|
||||||
}
|
}
|
||||||
@@ -243,17 +203,11 @@ flash_check_blank (const uint8_t *p_start, size_t size)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FLASH_START_ADDR 0x08000000 /* Fixed for all STM32F0/F1. */
|
#define FLASH_START_ADDR 0x08000000 /* Fixed for all STM32F1. */
|
||||||
#define FLASH_OFFSET 0x1000 /* First pages are not-writable
|
#define FLASH_OFFSET 0x1000 /* First pages are not-writable. */
|
||||||
when protected. */
|
|
||||||
#if defined(__ARM_ARCH_6M__)
|
|
||||||
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7cc)
|
|
||||||
#define CHIP_ID_REG ((uint32_t *)0x40015800)
|
|
||||||
#else
|
|
||||||
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
|
|
||||||
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
|
|
||||||
#endif
|
|
||||||
#define FLASH_START (FLASH_START_ADDR+FLASH_OFFSET)
|
#define FLASH_START (FLASH_START_ADDR+FLASH_OFFSET)
|
||||||
|
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
|
||||||
|
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
||||||
@@ -376,33 +330,12 @@ nvic_system_reset (void)
|
|||||||
static void __attribute__ ((naked))
|
static void __attribute__ ((naked))
|
||||||
reset (void)
|
reset (void)
|
||||||
{
|
{
|
||||||
|
extern const uint32_t FT0[256], FT1[256], FT2[256];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This code may not be at the start of flash ROM, because of DFU.
|
* This code may not be at the start of flash ROM, because of DFU.
|
||||||
* So, we take the address from PC.
|
* So, we take the address from PC.
|
||||||
*/
|
*/
|
||||||
#if defined(__ARM_ARCH_6M__)
|
|
||||||
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
|
||||||
"ldr r0, 1f\n\t" /* r0 = RAM start */
|
|
||||||
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
|
||||||
"mov r2, #0x10\n\t"
|
|
||||||
"lsl r2, #8\n\t"
|
|
||||||
"add r1, r1, r2\n\t"
|
|
||||||
"sub r2, r2, #1\n\t"
|
|
||||||
"bic r1, r1, r2\n\t"
|
|
||||||
"mov r2, #188\n"
|
|
||||||
"2:\n\t" /* Copy vectors. It will be enabled later by clock_init. */
|
|
||||||
"ldr r3, [r1, r2]\n\t"
|
|
||||||
"str r3, [r0, r2]\n\t"
|
|
||||||
"sub r2, #4\n\t"
|
|
||||||
"bcs 2b\n\t"
|
|
||||||
"msr MSP, r3\n\t" /* Main (exception handler) stack. */
|
|
||||||
"ldr r0, [r1, #4]\n\t" /* Reset handler. */
|
|
||||||
"bx r0\n\t"
|
|
||||||
".align 2\n"
|
|
||||||
"1: .word 0x20000000"
|
|
||||||
: /* no output */ : /* no input */ : "memory");
|
|
||||||
#else
|
|
||||||
extern const unsigned long *FT0, *FT1, *FT2;
|
|
||||||
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
||||||
"ldr r0, 1f\n\t" /* r0 = SCR */
|
"ldr r0, 1f\n\t" /* r0 = SCR */
|
||||||
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
||||||
@@ -418,11 +351,11 @@ reset (void)
|
|||||||
".align 2\n"
|
".align 2\n"
|
||||||
"1: .word 0xe000ed00"
|
"1: .word 0xe000ed00"
|
||||||
: /* no output */ : /* no input */ : "memory");
|
: /* no output */ : /* no input */ : "memory");
|
||||||
|
|
||||||
|
/* Never reach here. */
|
||||||
/* Artificial entry to refer FT0, FT1, and FT2. */
|
/* Artificial entry to refer FT0, FT1, and FT2. */
|
||||||
asm volatile (""
|
asm volatile (""
|
||||||
: : "r" (FT0), "r" (FT1), "r" (FT2));
|
: : "r" (FT0), "r" (FT1), "r" (FT2));
|
||||||
#endif
|
|
||||||
/* Never reach here. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*handler)(void);
|
typedef void (*handler)(void);
|
||||||
@@ -450,8 +383,8 @@ handler vector[] __attribute__ ((section(".vectors"))) = {
|
|||||||
const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
|
const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
|
||||||
3*2+2, /* bLength */
|
3*2+2, /* bLength */
|
||||||
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */
|
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */
|
||||||
/* sys version: "2.1" */
|
/* sys version: "3.0" */
|
||||||
'2', 0, '.', 0, '1', 0,
|
'3', 0, '.', 0, '0', 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32_t __attribute__((section(".sys.board_id")))
|
const uint32_t __attribute__((section(".sys.board_id")))
|
||||||
@@ -459,3 +392,149 @@ sys_board_id = BOARD_ID;
|
|||||||
|
|
||||||
const uint8_t __attribute__((section(".sys.board_name")))
|
const uint8_t __attribute__((section(".sys.board_name")))
|
||||||
sys_board_name[] = BOARD_NAME;
|
sys_board_name[] = BOARD_NAME;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* aes-constant-ft.c - AES forward tables.
|
||||||
|
*
|
||||||
|
* We need something useful for the initial flash ROM page (4 Ki
|
||||||
|
* bytes), which cannot be modified after installation. Even after
|
||||||
|
* upgrade of the firmware, it stays intact.
|
||||||
|
*
|
||||||
|
* We decide to put 3/4 of AES forward tables to fill 3 Ki bytes, as
|
||||||
|
* its useful and it won't change.
|
||||||
|
*
|
||||||
|
* The code was taken from aes.c of PolarSSL version 0.14, and then,
|
||||||
|
* modified to add section names.
|
||||||
|
*
|
||||||
|
* Since this is just a data, it wouldn't be copyright-able, but the
|
||||||
|
* original auther would claim so. Thus, we put original copyright
|
||||||
|
* notice here. It is highly likely that there will be no such a
|
||||||
|
* thing for copyright. Nevertheless, we think that PolarSSL is good
|
||||||
|
* software to address here, and encourage people using it.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Original copyright notice is below:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIPS-197 compliant AES implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||||
|
*
|
||||||
|
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||||
|
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
||||||
|
*
|
||||||
|
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
|
||||||
|
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forward tables
|
||||||
|
*/
|
||||||
|
#define FT \
|
||||||
|
\
|
||||||
|
V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
|
||||||
|
V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
|
||||||
|
V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
|
||||||
|
V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
|
||||||
|
V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
|
||||||
|
V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
|
||||||
|
V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
|
||||||
|
V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
|
||||||
|
V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
|
||||||
|
V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
|
||||||
|
V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
|
||||||
|
V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
|
||||||
|
V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
|
||||||
|
V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
|
||||||
|
V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
|
||||||
|
V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
|
||||||
|
V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
|
||||||
|
V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
|
||||||
|
V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
|
||||||
|
V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
|
||||||
|
V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
|
||||||
|
V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
|
||||||
|
V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
|
||||||
|
V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
|
||||||
|
V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
|
||||||
|
V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
|
||||||
|
V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
|
||||||
|
V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
|
||||||
|
V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
|
||||||
|
V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
|
||||||
|
V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
|
||||||
|
V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
|
||||||
|
V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
|
||||||
|
V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
|
||||||
|
V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
|
||||||
|
V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
|
||||||
|
V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
|
||||||
|
V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
|
||||||
|
V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
|
||||||
|
V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
|
||||||
|
V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
|
||||||
|
V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
|
||||||
|
V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
|
||||||
|
V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
|
||||||
|
V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
|
||||||
|
V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
|
||||||
|
V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
|
||||||
|
V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
|
||||||
|
V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
|
||||||
|
V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
|
||||||
|
V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
|
||||||
|
V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
|
||||||
|
V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
|
||||||
|
V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
|
||||||
|
V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
|
||||||
|
V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
|
||||||
|
V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
|
||||||
|
V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
|
||||||
|
V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
|
||||||
|
V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
|
||||||
|
V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
|
||||||
|
V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
|
||||||
|
V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
|
||||||
|
V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
|
||||||
|
|
||||||
|
#define V(a,b,c,d) 0x##a##b##c##d
|
||||||
|
const uint32_t FT0[256] __attribute__((section(".sys.0"))) = { FT };
|
||||||
|
#undef V
|
||||||
|
|
||||||
|
#define V(a,b,c,d) 0x##b##c##d##a
|
||||||
|
const uint32_t FT1[256] __attribute__((section(".sys.1"))) = { FT };
|
||||||
|
#undef V
|
||||||
|
|
||||||
|
#define V(a,b,c,d) 0x##c##d##a##b
|
||||||
|
const uint32_t FT2[256] __attribute__((section(".sys.2"))) = { FT };
|
||||||
|
#undef V
|
||||||
|
|
||||||
|
#ifdef ORIGINAL_IMPLEMENTATION
|
||||||
|
#define V(a,b,c,d) 0x##d##a##b##c
|
||||||
|
const uint32_t FT3[256] = { FT };
|
||||||
|
#undef V
|
||||||
|
#endif
|
||||||
@@ -12,8 +12,13 @@
|
|||||||
#define BOARD_ID_NITROKEY_START 0xad1e7ebd
|
#define BOARD_ID_NITROKEY_START 0xad1e7ebd
|
||||||
|
|
||||||
extern const uint8_t sys_version[8];
|
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 uint32_t sys_board_id;
|
||||||
extern const uint8_t sys_board_name[];
|
extern const uint8_t sys_board_name[];
|
||||||
|
# define SYS_BOARD_ID sys_board_id
|
||||||
|
#else
|
||||||
|
# define SYS_BOARD_ID BOARD_ID
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef void (*handler)(void);
|
typedef void (*handler)(void);
|
||||||
extern handler vector[16];
|
extern handler vector[16];
|
||||||
@@ -109,22 +114,18 @@ nvic_system_reset (void)
|
|||||||
(*vector[12]) ();
|
(*vector[12]) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#ifdef REQUIRE_CLOCK_GPIO_SETTING_IN_SYS
|
||||||
* Users can override INLINE by 'attribute((used))' to have an
|
/* Provide the function entries. */
|
||||||
* implementation defined.
|
|
||||||
*/
|
|
||||||
#if !defined(INLINE)
|
|
||||||
#define INLINE __inline__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static INLINE void
|
static void __attribute__ ((used))
|
||||||
clock_init (void)
|
clock_init (void)
|
||||||
{
|
{
|
||||||
(*vector[13]) ();
|
(*vector[13]) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE void
|
static void __attribute__ ((used))
|
||||||
gpio_init (void)
|
gpio_init (void)
|
||||||
{
|
{
|
||||||
(*vector[14]) ();
|
(*vector[14]) ();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* usb_kl27z.c - USB driver for KL27Z
|
* usb-mkl27z.c - USB driver for MKL27Z
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016 Flying Stone Technology
|
* Copyright (C) 2016 Flying Stone Technology
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
@@ -32,6 +32,9 @@
|
|||||||
|
|
||||||
#include "usb_lld.h"
|
#include "usb_lld.h"
|
||||||
|
|
||||||
|
#define DATA0 0
|
||||||
|
#define DATA1 1
|
||||||
|
|
||||||
struct endpoint_ctl {
|
struct endpoint_ctl {
|
||||||
uint32_t rx_odd: 1;
|
uint32_t rx_odd: 1;
|
||||||
uint32_t tx_odd: 1;
|
uint32_t tx_odd: 1;
|
||||||
@@ -135,19 +138,13 @@ extern uint8_t __usb_bdt__;
|
|||||||
|
|
||||||
static struct BD *const BD_table = (struct BD *const)&__usb_bdt__;
|
static struct BD *const BD_table = (struct BD *const)&__usb_bdt__;
|
||||||
|
|
||||||
static uint8_t setup[8];
|
|
||||||
/* bmRequestType, bRequest */
|
|
||||||
/* Value: 2-byte */
|
|
||||||
/* Index: 2-byte */
|
|
||||||
/* Length: 2-byte */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kl27z_usb_init (void)
|
kl27z_usb_init (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset (ep, 0, sizeof (ep));
|
memset (ep, 0, sizeof (ep));
|
||||||
memset (BD_table, 0, 10 * sizeof (struct BD));
|
memset (BD_table, 0, 16 * 2 * 2 * sizeof (struct BD));
|
||||||
|
|
||||||
/* D+ pull up */
|
/* D+ pull up */
|
||||||
USB_CTRL0->OTGCTL = 0x80;
|
USB_CTRL0->OTGCTL = 0x80;
|
||||||
@@ -183,11 +180,11 @@ kl27z_set_daddr (uint8_t daddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kl27z_prepare_ep0_setup (void)
|
kl27z_prepare_ep0_setup (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
/* Endpoint 0, TX=0. */
|
/* Endpoint 0, TX=0. */
|
||||||
BD_table[ep[0].rx_odd].ctrl = 0x00080088; /* Len=8, OWN=1, DATA01=0, DTS=1 */
|
BD_table[ep[0].rx_odd].ctrl = 0x00080088; /* Len=8, OWN=1, DATA01=0, DTS=1 */
|
||||||
BD_table[ep[0].rx_odd].buf = setup;
|
BD_table[ep[0].rx_odd].buf = &dev->dev_req;
|
||||||
|
|
||||||
BD_table[!ep[0].rx_odd].ctrl = 0x0000; /* OWN=0 */
|
BD_table[!ep[0].rx_odd].ctrl = 0x0000; /* OWN=0 */
|
||||||
BD_table[!ep[0].rx_odd].buf = NULL;
|
BD_table[!ep[0].rx_odd].buf = NULL;
|
||||||
@@ -296,17 +293,11 @@ enum STANDARD_REQUESTS {
|
|||||||
|
|
||||||
|
|
||||||
enum FEATURE_SELECTOR {
|
enum FEATURE_SELECTOR {
|
||||||
ENDPOINT_STALL,
|
FEATURE_ENDPOINT_HALT=0,
|
||||||
DEVICE_REMOTE_WAKEUP
|
FEATURE_DEVICE_REMOTE_WAKEUP=1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct data_ctl {
|
|
||||||
uint8_t *addr;
|
|
||||||
uint16_t len;
|
|
||||||
uint8_t require_zlp;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The state machine states of a control pipe */
|
/* The state machine states of a control pipe */
|
||||||
enum {
|
enum {
|
||||||
WAIT_SETUP,
|
WAIT_SETUP,
|
||||||
@@ -319,30 +310,7 @@ enum {
|
|||||||
PAUSE
|
PAUSE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device_ctl {
|
static int handle_transaction (struct usb_dev *dev, uint8_t stat);
|
||||||
/* control pipe state */
|
|
||||||
uint8_t state;
|
|
||||||
|
|
||||||
uint32_t tkdone;
|
|
||||||
uint32_t reset;
|
|
||||||
uint32_t error;
|
|
||||||
uint32_t stall;
|
|
||||||
|
|
||||||
uint32_t send;
|
|
||||||
uint32_t recv;
|
|
||||||
|
|
||||||
/* Device specific settings */
|
|
||||||
uint8_t configuration;
|
|
||||||
uint8_t feature;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct device_ctl device_ctl;
|
|
||||||
static struct data_ctl data_ctl;
|
|
||||||
|
|
||||||
static struct device_ctl *const dev_p = &device_ctl;
|
|
||||||
static struct data_ctl *const data_p = &data_ctl;
|
|
||||||
|
|
||||||
static void handle_transaction (uint8_t stat);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_lld_stall (int n)
|
usb_lld_stall (int n)
|
||||||
@@ -352,16 +320,28 @@ usb_lld_stall (int n)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_lld_init (uint8_t feature)
|
usb_lld_ctrl_error (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
dev_p->state = WAIT_SETUP;
|
dev->state = STALLED;
|
||||||
dev_p->tkdone = 0;
|
kl27z_ep_stall (ENDP0);
|
||||||
dev_p->reset = 0;
|
}
|
||||||
dev_p->error = 0;
|
|
||||||
dev_p->stall = 0;
|
|
||||||
|
|
||||||
usb_lld_set_configuration (0);
|
int
|
||||||
dev_p->feature = feature;
|
usb_lld_ctrl_ack (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
/* Zero length packet for ACK. */
|
||||||
|
dev->state = WAIT_STATUS_IN;
|
||||||
|
kl27z_prepare_ep0_in (&dev->dev_req, 0, DATA1);
|
||||||
|
return USB_EVENT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
usb_lld_init (struct usb_dev *dev, uint8_t feature)
|
||||||
|
{
|
||||||
|
usb_lld_set_configuration (dev, 0);
|
||||||
|
dev->feature = feature;
|
||||||
|
dev->state = WAIT_SETUP;
|
||||||
|
|
||||||
kl27z_set_daddr (0);
|
kl27z_set_daddr (0);
|
||||||
kl27z_usb_init ();
|
kl27z_usb_init ();
|
||||||
@@ -376,8 +356,12 @@ usb_lld_init (uint8_t feature)
|
|||||||
| USB_IS_ERROR | USB_IS_USBRST;
|
| USB_IS_ERROR | USB_IS_USBRST;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
usb_interrupt_handler (void)
|
#define USB_MAKE_EV(event) (event<<24)
|
||||||
|
#define USB_MAKE_TXRX(ep_num,txrx,len) ((txrx? (1<<23):0)|(ep_num<<16)|len)
|
||||||
|
|
||||||
|
int
|
||||||
|
usb_lld_event_handler (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t istat_value = USB_CTRL1->ISTAT;
|
uint8_t istat_value = USB_CTRL1->ISTAT;
|
||||||
uint8_t stat = USB_CTRL1->STAT;
|
uint8_t stat = USB_CTRL1->STAT;
|
||||||
@@ -385,43 +369,37 @@ usb_interrupt_handler (void)
|
|||||||
if ((istat_value & USB_IS_USBRST))
|
if ((istat_value & USB_IS_USBRST))
|
||||||
{
|
{
|
||||||
USB_CTRL1->ISTAT = USB_IS_USBRST;
|
USB_CTRL1->ISTAT = USB_IS_USBRST;
|
||||||
usb_cb_device_reset ();
|
return USB_MAKE_EV (USB_EVENT_DEVICE_RESET);
|
||||||
dev_p->reset++;
|
|
||||||
}
|
}
|
||||||
|
else if ((istat_value & USB_IS_TOKDNE))
|
||||||
|
return handle_transaction (dev, stat);
|
||||||
else if ((istat_value & USB_IS_ERROR))
|
else if ((istat_value & USB_IS_ERROR))
|
||||||
{ /* Clear Errors. */
|
{ /* Clear Errors. */
|
||||||
USB_CTRL1->ERRSTAT = USB_CTRL1->ERRSTAT;
|
USB_CTRL1->ERRSTAT = USB_CTRL1->ERRSTAT;
|
||||||
USB_CTRL1->ISTAT = USB_IS_ERROR;
|
USB_CTRL1->ISTAT = USB_IS_ERROR;
|
||||||
/*reset???*/
|
|
||||||
dev_p->error++;
|
|
||||||
}
|
|
||||||
else if ((istat_value & USB_IS_TOKDNE))
|
|
||||||
{
|
|
||||||
handle_transaction (stat);
|
|
||||||
dev_p->tkdone++;
|
|
||||||
}
|
}
|
||||||
else if ((istat_value & USB_IS_STALL))
|
else if ((istat_value & USB_IS_STALL))
|
||||||
{
|
{
|
||||||
/* ??? stat includes ep_num in this case ???: No, it doesn't */
|
/* Does STAT have ENDPOINT info in this case?: No, it doesn't. */
|
||||||
|
|
||||||
if (kl27z_ep_is_stall (0))
|
if (kl27z_ep_is_stall (0))
|
||||||
{ /* It's endpoint 0, recover from erorr. */
|
{ /* It's endpoint 0, recover from erorr. */
|
||||||
dev_p->state = WAIT_SETUP;
|
dev->state = WAIT_SETUP;
|
||||||
kl27z_ep_clear_stall (0);
|
kl27z_ep_clear_stall (0);
|
||||||
kl27z_prepare_ep0_setup ();
|
kl27z_prepare_ep0_setup (dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_CTRL1->ISTAT = USB_IS_STALL;
|
USB_CTRL1->ISTAT = USB_IS_STALL;
|
||||||
dev_p->stall++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return USB_EVENT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DATA0 0
|
|
||||||
#define DATA1 1
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_datastage_out (uint8_t stat)
|
handle_datastage_out (struct usb_dev *dev, uint8_t stat)
|
||||||
{
|
{
|
||||||
|
struct ctrl_data *data_p = &dev->ctrl_data;
|
||||||
int odd = (stat >> 2)&1;
|
int odd = (stat >> 2)&1;
|
||||||
int data01 = !((BD_table[odd].ctrl >> 6)&1);
|
int data01 = !((BD_table[odd].ctrl >> 6)&1);
|
||||||
uint32_t len = (BD_table[odd].ctrl >> 16)&0x3ff;
|
uint32_t len = (BD_table[odd].ctrl >> 16)&0x3ff;
|
||||||
@@ -436,43 +414,44 @@ handle_datastage_out (uint8_t stat)
|
|||||||
if (data_p->len == 0)
|
if (data_p->len == 0)
|
||||||
{
|
{
|
||||||
/* No more data to receive, proceed to send acknowledge for IN. */
|
/* No more data to receive, proceed to send acknowledge for IN. */
|
||||||
dev_p->state = WAIT_STATUS_IN;
|
dev->state = WAIT_STATUS_IN;
|
||||||
kl27z_prepare_ep0_in (setup, 0, DATA1);
|
kl27z_prepare_ep0_in (&dev->dev_req, 0, DATA1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dev_p->state = OUT_DATA;
|
dev->state = OUT_DATA;
|
||||||
kl27z_prepare_ep0_out (data_p->addr, len, data01);
|
kl27z_prepare_ep0_out (data_p->addr, len, data01);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_datastage_in (uint8_t stat)
|
handle_datastage_in (struct usb_dev *dev, uint8_t stat)
|
||||||
{
|
{
|
||||||
|
struct ctrl_data *data_p = &dev->ctrl_data;
|
||||||
int odd = (stat >> 2)&1;
|
int odd = (stat >> 2)&1;
|
||||||
int data01 = !((BD_table[2+odd].ctrl >> 6)&1);
|
int data01 = !((BD_table[2+odd].ctrl >> 6)&1);
|
||||||
uint32_t len = USB_MAX_PACKET_SIZE;
|
uint32_t len = USB_MAX_PACKET_SIZE;
|
||||||
|
|
||||||
if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA))
|
if ((data_p->len == 0) && (dev->state == LAST_IN_DATA))
|
||||||
{
|
{
|
||||||
if (data_p->require_zlp)
|
if (data_p->require_zlp)
|
||||||
{
|
{
|
||||||
data_p->require_zlp = 0;
|
data_p->require_zlp = 0;
|
||||||
|
|
||||||
/* No more data to send. Send empty packet */
|
/* No more data to send. Send empty packet */
|
||||||
kl27z_prepare_ep0_in (setup, 0, data01);
|
kl27z_prepare_ep0_in (&dev->dev_req, 0, data01);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No more data to send, proceed to receive OUT acknowledge. */
|
/* No more data to send, proceed to receive OUT acknowledge. */
|
||||||
dev_p->state = WAIT_STATUS_OUT;
|
dev->state = WAIT_STATUS_OUT;
|
||||||
kl27z_prepare_ep0_out (setup, 8, DATA1);
|
kl27z_prepare_ep0_out (&dev->dev_req, 8, DATA1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_p->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
|
dev->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
|
||||||
|
|
||||||
if (len > data_p->len)
|
if (len > data_p->len)
|
||||||
len = data_p->len;
|
len = data_p->len;
|
||||||
@@ -482,31 +461,32 @@ handle_datastage_in (uint8_t stat)
|
|||||||
data_p->addr += len;
|
data_p->addr += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef int (*HANDLER) (uint8_t req, struct req_args *arg);
|
typedef int (*HANDLER) (struct usb_dev *dev);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_none (uint8_t req, struct req_args *arg)
|
std_none (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
(void)req; (void)arg;
|
(void)dev;
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_get_status (uint8_t req, struct req_args *arg)
|
std_get_status (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
uint16_t status_info = 0;
|
uint16_t status_info = 0;
|
||||||
|
|
||||||
if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
|
if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
|
||||||
|| USB_SETUP_SET (req))
|
|| USB_SETUP_SET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT)
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
{
|
{
|
||||||
if (arg->index == 0)
|
if (arg->index == 0)
|
||||||
{
|
{
|
||||||
/* Get Device Status */
|
/* Get Device Status */
|
||||||
uint8_t feature = dev_p->feature;
|
uint8_t feature = dev->feature;
|
||||||
|
|
||||||
/* Remote Wakeup enabled */
|
/* Remote Wakeup enabled */
|
||||||
if ((feature & (1 << 5)))
|
if ((feature & (1 << 5)))
|
||||||
@@ -520,380 +500,405 @@ std_get_status (uint8_t req, struct req_args *arg)
|
|||||||
else /* Self-powered */
|
else /* Self-powered */
|
||||||
status_info &= ~1;
|
status_info &= ~1;
|
||||||
|
|
||||||
return usb_lld_reply_request (&status_info, 2, arg);
|
return usb_lld_ctrl_send (dev, &status_info, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rcp == INTERFACE_RECIPIENT)
|
else if (rcp == INTERFACE_RECIPIENT)
|
||||||
{
|
{
|
||||||
int r;
|
if (dev->configuration == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (dev_p->configuration == 0)
|
return USB_EVENT_GET_STATUS_INTERFACE;
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
r = usb_cb_interface (USB_QUERY_INTERFACE, arg);
|
|
||||||
if (r != USB_SUCCESS)
|
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
return usb_lld_reply_request (&status_info, 2, arg);
|
|
||||||
}
|
}
|
||||||
else if (rcp == ENDPOINT_RECIPIENT)
|
else if (rcp == ENDPOINT_RECIPIENT)
|
||||||
{
|
{
|
||||||
uint8_t n = (arg->index & 0x0f);
|
uint8_t n = (arg->index & 0x0f);
|
||||||
|
|
||||||
if ((arg->index & 0x70) || n == ENDP0)
|
if ((arg->index & 0x70) || n == ENDP0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (kl27z_ep_is_disabled (n))
|
if (kl27z_ep_is_disabled (n))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
status_info = kl27z_ep_is_stall (n);
|
status_info = kl27z_ep_is_stall (n);
|
||||||
return usb_lld_reply_request (&status_info, 2, arg);
|
return usb_lld_ctrl_send (dev, &status_info, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_clear_feature (uint8_t req, struct req_args *arg)
|
std_clear_feature (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req))
|
if (USB_SETUP_GET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT)
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
{
|
{
|
||||||
if (arg->len != 0 || arg->index != 0)
|
if (arg->len != 0 || arg->index != 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->value == DEVICE_REMOTE_WAKEUP)
|
if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||||
{
|
{
|
||||||
dev_p->feature &= ~(1 << 5);
|
dev->feature &= ~(1 << 5);
|
||||||
return USB_SUCCESS;
|
return USB_EVENT_CLEAR_FEATURE_DEVICE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rcp == ENDPOINT_RECIPIENT)
|
else if (rcp == ENDPOINT_RECIPIENT)
|
||||||
{
|
{
|
||||||
uint8_t n = (arg->index & 0x0f);
|
uint8_t n = (arg->index & 0x0f);
|
||||||
|
|
||||||
if (dev_p->configuration == 0)
|
if (dev->configuration == 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->len != 0 || (arg->index >> 8) != 0
|
if (arg->len != 0 || (arg->index >> 8) != 0
|
||||||
|| arg->value != ENDPOINT_STALL || n == ENDP0)
|
|| arg->value != FEATURE_ENDPOINT_HALT || n == ENDP0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (kl27z_ep_is_disabled (n))
|
if (kl27z_ep_is_disabled (n))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
kl27z_ep_clear_dtog ((arg->index & 0x80) == 0, n);
|
kl27z_ep_clear_dtog ((arg->index & 0x80) == 0, n);
|
||||||
|
|
||||||
// event??
|
return USB_EVENT_CLEAR_FEATURE_ENDPOINT;
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_set_feature (uint8_t req, struct req_args *arg)
|
std_set_feature (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req))
|
if (USB_SETUP_GET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT)
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
{
|
{
|
||||||
if (arg->len != 0 || arg->index != 0)
|
if (arg->len != 0 || arg->index != 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->value == DEVICE_REMOTE_WAKEUP)
|
if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||||
{
|
{
|
||||||
dev_p->feature |= 1 << 5;
|
dev->feature |= 1 << 5;
|
||||||
// event??
|
return USB_EVENT_SET_FEATURE_DEVICE;
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rcp == ENDPOINT_RECIPIENT)
|
else if (rcp == ENDPOINT_RECIPIENT)
|
||||||
{
|
{
|
||||||
uint8_t n = (arg->index & 0x0f);
|
uint8_t n = (arg->index & 0x0f);
|
||||||
|
|
||||||
if (dev_p->configuration == 0)
|
if (dev->configuration == 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->len != 0 || (arg->index >> 8) != 0
|
if (arg->len != 0 || (arg->index >> 8) != 0
|
||||||
|| arg->value != 0 || n == ENDP0)
|
|| arg->value != FEATURE_ENDPOINT_HALT || n == ENDP0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (kl27z_ep_is_disabled (n))
|
if (kl27z_ep_is_disabled (n))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
kl27z_ep_stall (n);
|
kl27z_ep_stall (n);
|
||||||
|
|
||||||
// event??
|
return USB_EVENT_SET_FEATURE_ENDPOINT;
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_set_address (uint8_t req, struct req_args *arg)
|
std_set_address (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req))
|
if (USB_SETUP_GET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
|
if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
|
||||||
&& arg->index == 0 && dev_p->configuration == 0)
|
&& arg->index == 0 && dev->configuration == 0)
|
||||||
return USB_SUCCESS;
|
return usb_lld_ctrl_ack (dev);
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_get_descriptor (uint8_t req, struct req_args *arg)
|
std_get_descriptor (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
if (USB_SETUP_SET (arg->type))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (USB_SETUP_SET (req))
|
return USB_EVENT_GET_DESCRIPTOR;
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
return usb_cb_get_descriptor (rcp, (arg->value >> 8),
|
|
||||||
(arg->value & 0xff), arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_get_configuration (uint8_t req, struct req_args *arg)
|
std_get_configuration (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
(void)arg;
|
if (USB_SETUP_SET (arg->type))
|
||||||
if (USB_SETUP_SET (req))
|
return -1;
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
if (arg->value != 0 || arg->index != 0 || arg->len != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT)
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
return usb_lld_reply_request (&dev_p->configuration, 1, arg);
|
return usb_lld_ctrl_send (dev, &dev->configuration, 1);
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_set_configuration (uint8_t req, struct req_args *arg)
|
std_set_configuration (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req))
|
if (USB_SETUP_GET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0)
|
if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0)
|
||||||
return usb_cb_handle_event (USB_EVENT_CONFIG, arg->value);
|
return USB_EVENT_SET_CONFIGURATION;
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_get_interface (uint8_t req, struct req_args *arg)
|
std_get_interface (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_SET (req))
|
if (USB_SETUP_SET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
|
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (dev->configuration == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (rcp == INTERFACE_RECIPIENT)
|
if (rcp == INTERFACE_RECIPIENT)
|
||||||
{
|
return USB_EVENT_GET_INTERFACE;
|
||||||
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
|
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
if (dev_p->configuration == 0)
|
return -1;
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
return usb_cb_interface (USB_GET_INTERFACE, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_set_interface (uint8_t req, struct req_args *arg)
|
std_set_interface (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req) || rcp != INTERFACE_RECIPIENT
|
if (USB_SETUP_GET (arg->type) || rcp != INTERFACE_RECIPIENT
|
||||||
|| arg->len != 0 || (arg->index >> 8) != 0
|
|| arg->len != 0 || (arg->index >> 8) != 0
|
||||||
|| (arg->value >> 8) != 0 || dev_p->configuration == 0)
|
|| (arg->value >> 8) != 0 || dev->configuration == 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
return usb_cb_interface (USB_SET_INTERFACE, arg);
|
return USB_EVENT_SET_INTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static int
|
||||||
handle_setup0 (void)
|
handle_setup0 (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
struct req_args *arg = (struct req_args *)&setup[2];
|
struct ctrl_data *data_p = &dev->ctrl_data;
|
||||||
int r = USB_UNSUPPORT;
|
int r = -1;
|
||||||
HANDLER handler;
|
HANDLER handler;
|
||||||
|
|
||||||
data_p->addr = NULL;
|
data_p->addr = NULL;
|
||||||
data_p->len = 0;
|
data_p->len = 0;
|
||||||
data_p->require_zlp = 0;
|
data_p->require_zlp = 0;
|
||||||
|
|
||||||
if ((setup[0] & REQUEST_TYPE) == STANDARD_REQUEST)
|
if ((dev->dev_req.type & REQUEST_TYPE) == STANDARD_REQUEST)
|
||||||
{
|
{
|
||||||
if (setup[1] < TOTAL_REQUEST)
|
switch (dev->dev_req.request)
|
||||||
{
|
{
|
||||||
switch (setup[1])
|
case 0: handler = std_get_status; break;
|
||||||
{
|
case 1: handler = std_clear_feature; break;
|
||||||
case 0: handler = std_get_status; break;
|
case 3: handler = std_set_feature; break;
|
||||||
case 1: handler = std_clear_feature; break;
|
case 5: handler = std_set_address; break;
|
||||||
case 3: handler = std_set_feature; break;
|
case 6: handler = std_get_descriptor; break;
|
||||||
case 5: handler = std_set_address; break;
|
case 8: handler = std_get_configuration; break;
|
||||||
case 6: handler = std_get_descriptor; break;
|
case 9: handler = std_set_configuration; break;
|
||||||
case 8: handler = std_get_configuration; break;
|
case 10: handler = std_get_interface; break;
|
||||||
case 9: handler = std_set_configuration; break;
|
case 11: handler = std_set_interface; break;
|
||||||
case 10: handler = std_get_interface; break;
|
default: handler = std_none; break;
|
||||||
case 11: handler = std_set_interface; break;
|
|
||||||
default: handler = std_none; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = (*handler) (setup[0], arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((r = (*handler) (dev)) < 0)
|
||||||
|
{
|
||||||
|
usb_lld_ctrl_error (dev);
|
||||||
|
return USB_EVENT_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
r = usb_cb_setup (setup[0], setup[1], arg);
|
return USB_EVENT_CTRL_REQUEST;
|
||||||
|
|
||||||
if (r != USB_SUCCESS)
|
|
||||||
dev_p->state = STALLED;
|
|
||||||
else if (USB_SETUP_SET (setup[0]))
|
|
||||||
{
|
|
||||||
if (arg->len == 0)
|
|
||||||
{
|
|
||||||
/* Zero length packet for ACK. */
|
|
||||||
kl27z_prepare_ep0_in (setup, 0, DATA1);
|
|
||||||
dev_p->state = WAIT_STATUS_IN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
handle_in0 (uint8_t stat)
|
handle_in0 (struct usb_dev *dev, uint8_t stat)
|
||||||
{
|
{
|
||||||
if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
|
int r = 0;
|
||||||
handle_datastage_in (stat);
|
|
||||||
else if (dev_p->state == WAIT_STATUS_IN)
|
|
||||||
{ /* Control WRITE transfer done successfully. */
|
|
||||||
uint16_t value = (setup[3]<<8) | setup[2];
|
|
||||||
|
|
||||||
if ((setup[1] == SET_ADDRESS) &&
|
if (dev->state == IN_DATA || dev->state == LAST_IN_DATA)
|
||||||
((setup[0] & (REQUEST_TYPE | RECIPIENT))
|
handle_datastage_in (dev, stat);
|
||||||
|
else if (dev->state == WAIT_STATUS_IN)
|
||||||
|
{ /* Control WRITE transfer done successfully. */
|
||||||
|
uint16_t value = dev->dev_req.value;
|
||||||
|
|
||||||
|
if ((dev->dev_req.request == SET_ADDRESS) &&
|
||||||
|
((dev->dev_req.type & (REQUEST_TYPE | RECIPIENT))
|
||||||
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
|
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
|
||||||
{
|
{
|
||||||
kl27z_set_daddr (value);
|
kl27z_set_daddr (value);
|
||||||
usb_cb_handle_event (USB_EVENT_ADDRESS, value);
|
|
||||||
ep[0].rx_odd = 0;
|
ep[0].rx_odd = 0;
|
||||||
|
r = USB_EVENT_DEVICE_ADDRESSED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
usb_cb_ctrl_write_finish (setup[0], setup[1],
|
r = USB_EVENT_CTRL_WRITE_FINISH;
|
||||||
(struct req_args *)&setup[2]);
|
dev->state = WAIT_SETUP;
|
||||||
|
kl27z_prepare_ep0_setup (dev);
|
||||||
dev_p->state = WAIT_SETUP;
|
|
||||||
kl27z_prepare_ep0_setup ();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dev_p->state = STALLED;
|
{
|
||||||
|
dev->state = STALLED;
|
||||||
|
kl27z_ep_stall (ENDP0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_out0 (uint8_t stat)
|
handle_out0 (struct usb_dev *dev, uint8_t stat)
|
||||||
{
|
{
|
||||||
if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
|
if (dev->state == OUT_DATA)
|
||||||
/* Host aborts the control READ transfer before finish. */
|
|
||||||
dev_p->state = STALLED;
|
|
||||||
else if (dev_p->state == OUT_DATA)
|
|
||||||
/* It's normal control WRITE transfer. */
|
/* It's normal control WRITE transfer. */
|
||||||
handle_datastage_out (stat);
|
handle_datastage_out (dev, stat);
|
||||||
else if (dev_p->state == WAIT_STATUS_OUT)
|
else if (dev->state == WAIT_STATUS_OUT)
|
||||||
{ /* Control READ transfer done successfully. */
|
{ /* Control READ transfer done successfully. */
|
||||||
dev_p->state = WAIT_SETUP;
|
dev->state = WAIT_SETUP;
|
||||||
kl27z_prepare_ep0_setup ();
|
kl27z_prepare_ep0_setup (dev);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dev_p->state = STALLED;
|
{
|
||||||
|
/*
|
||||||
|
* dev->state == IN_DATA || dev->state == LAST_IN_DATA
|
||||||
|
* (Host aborts the transfer before finish)
|
||||||
|
* Or else, unexpected state.
|
||||||
|
* STALL the endpoint, until we receive the next SETUP token.
|
||||||
|
*/
|
||||||
|
dev->state = STALLED;
|
||||||
|
kl27z_ep_stall (ENDP0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
#define USB_TOKEN_ACK 0x02
|
||||||
handle_transaction (uint8_t stat)
|
#define USB_TOKEN_IN 0x09
|
||||||
|
#define USB_TOKEN_SETUP 0x0d
|
||||||
|
|
||||||
|
static int
|
||||||
|
handle_transaction (struct usb_dev *dev, uint8_t stat)
|
||||||
{
|
{
|
||||||
int odd = (stat >> 2)&1;
|
int odd = (stat >> 2)&1;
|
||||||
uint8_t ep_num = (stat >> 4);
|
uint8_t ep_num = (stat >> 4);
|
||||||
|
int r;
|
||||||
|
|
||||||
if (ep_num == 0)
|
if (ep_num == 0)
|
||||||
{
|
{
|
||||||
if ((stat & 0x08) == 0)
|
if ((stat & 0x08) == 0)
|
||||||
{
|
{
|
||||||
ep[0].rx_odd ^= 1;
|
ep[0].rx_odd ^= 1;
|
||||||
if (TOK_PID (BD_table[odd].ctrl) == 0x0d)
|
if (TOK_PID (BD_table[odd].ctrl) == USB_TOKEN_SETUP)
|
||||||
{
|
{
|
||||||
handle_setup0 ();
|
r = handle_setup0 (dev);
|
||||||
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
||||||
USB_CTRL1->CTL = 0x01; /* Clear TXSUSPENDTOKENBUSY. */
|
USB_CTRL1->CTL = 0x01; /* Clear TXSUSPENDTOKENBUSY. */
|
||||||
|
return USB_MAKE_EV (r);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
handle_out0 (dev, stat);
|
||||||
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
||||||
handle_out0 (stat);
|
return USB_EVENT_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ep[0].tx_odd ^= 1;
|
ep[0].tx_odd ^= 1;
|
||||||
|
r = handle_in0 (dev, stat);
|
||||||
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
||||||
handle_in0 (stat);
|
return USB_MAKE_EV (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev_p->state == STALLED)
|
|
||||||
kl27z_ep_stall (0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
uint16_t len;
|
||||||
|
|
||||||
if ((stat & 0x08) == 0)
|
if ((stat & 0x08) == 0)
|
||||||
{
|
{
|
||||||
dev_p->recv++;
|
len = (BD_table[4*ep_num+odd].ctrl >> 16)&0x3ff;
|
||||||
ep[ep_num].rx_odd ^= 1;
|
ep[ep_num].rx_odd ^= 1;
|
||||||
usb_cb_rx_ready (ep_num);
|
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
||||||
|
return USB_MAKE_TXRX (ep_num, 0, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* XXX: Can be NAK. Check BDT if it's NAK or not. */
|
/*
|
||||||
|
* IN transaction is usually in a sequence like:
|
||||||
|
*
|
||||||
|
* -----time------>
|
||||||
|
* host: IN ACK
|
||||||
|
* device: DATA0/1
|
||||||
|
*
|
||||||
|
* Although it is not described in the specification (it's
|
||||||
|
* ambiguous), it is actually possible for some host
|
||||||
|
* implementation to send back a NAK on erroneous case like
|
||||||
|
* a device sent oversized data.
|
||||||
|
*
|
||||||
|
* -----time------>
|
||||||
|
* host: IN NAK
|
||||||
|
* device: DATA0/1
|
||||||
|
*
|
||||||
|
* We do our best to distinguish successful tx and tx with
|
||||||
|
* failure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint32_t dmaerr = (USB_CTRL1->ERRSTAT & (1 << 5));
|
||||||
|
int success = (dmaerr == 0);
|
||||||
|
|
||||||
|
len = (BD_table[4*ep_num+2+odd].ctrl >> 16)&0x3ff;
|
||||||
|
if (!success)
|
||||||
|
USB_CTRL1->ERRSTAT = dmaerr; /* Clear error. */
|
||||||
|
|
||||||
dev_p->send++;
|
|
||||||
ep[ep_num].tx_odd ^= 1;
|
ep[ep_num].tx_odd ^= 1;
|
||||||
usb_cb_tx_done (ep_num);
|
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
||||||
|
return USB_MAKE_TXRX (ep_num, 1, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_CTRL1->ISTAT = USB_IS_TOKDNE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_lld_reset (uint8_t feature)
|
usb_lld_reset (struct usb_dev *dev, uint8_t feature)
|
||||||
{
|
{
|
||||||
dev_p->feature = feature;
|
usb_lld_set_configuration (dev, 0);
|
||||||
usb_lld_set_configuration (0);
|
dev->feature = feature;
|
||||||
|
dev->state = WAIT_SETUP;
|
||||||
|
|
||||||
/* Reset USB */
|
/* Reset USB */
|
||||||
USB_CTRL2->USBTRC0 = 0xc0;
|
USB_CTRL2->USBTRC0 = 0xc0;
|
||||||
|
|
||||||
USB_CTRL1->CTL = 0x00; /* Disable USB FS communication module */
|
USB_CTRL1->CTL = 0x00; /* Disable USB FS communication module */
|
||||||
|
|
||||||
dev_p->state = WAIT_SETUP;
|
|
||||||
dev_p->tkdone = 0;
|
|
||||||
dev_p->error = 0;
|
|
||||||
dev_p->stall = 0;
|
|
||||||
|
|
||||||
kl27z_set_daddr (0);
|
kl27z_set_daddr (0);
|
||||||
kl27z_usb_init ();
|
kl27z_usb_init ();
|
||||||
|
|
||||||
@@ -905,13 +910,13 @@ usb_lld_reset (uint8_t feature)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_lld_setup_endpoint (int n, int rx_en, int tx_en)
|
usb_lld_setup_endp (struct usb_dev *dev, int n, int rx_en, int tx_en)
|
||||||
{
|
{
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
/* Enable the endpoint 0. */
|
/* Enable the endpoint 0. */
|
||||||
USB_ENDPT[0].EP = 0x0d;
|
USB_ENDPT[0].EP = 0x0d;
|
||||||
kl27z_prepare_ep0_setup ();
|
kl27z_prepare_ep0_setup (dev);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -936,27 +941,29 @@ usb_lld_setup_endpoint (int n, int rx_en, int tx_en)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_lld_set_configuration (uint8_t config)
|
usb_lld_set_configuration (struct usb_dev *dev, uint8_t config)
|
||||||
{
|
{
|
||||||
dev_p->configuration = config;
|
dev->configuration = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
usb_lld_current_configuration (void)
|
usb_lld_current_configuration (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
return dev_p->configuration;
|
return dev->configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
usb_lld_set_data_to_recv (void *p, size_t len)
|
usb_lld_ctrl_recv (struct usb_dev *dev, void *p, size_t len)
|
||||||
{
|
{
|
||||||
|
struct ctrl_data *data_p = &dev->ctrl_data;
|
||||||
data_p->addr = (uint8_t *)p;
|
data_p->addr = (uint8_t *)p;
|
||||||
data_p->len = len;
|
data_p->len = len;
|
||||||
if (len > USB_MAX_PACKET_SIZE)
|
if (len > USB_MAX_PACKET_SIZE)
|
||||||
len = USB_MAX_PACKET_SIZE;
|
len = USB_MAX_PACKET_SIZE;
|
||||||
|
|
||||||
kl27z_prepare_ep0_out (p, len, DATA1);
|
kl27z_prepare_ep0_out (p, len, DATA1);
|
||||||
dev_p->state = OUT_DATA;
|
dev->state = OUT_DATA;
|
||||||
|
return USB_EVENT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -966,9 +973,10 @@ usb_lld_set_data_to_recv (void *p, size_t len)
|
|||||||
* BUFLEN: size of the data.
|
* BUFLEN: size of the data.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *a)
|
usb_lld_ctrl_send (struct usb_dev *dev, const void *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
uint32_t len_asked = a->len;
|
struct ctrl_data *data_p = &dev->ctrl_data;
|
||||||
|
uint32_t len_asked = dev->dev_req.len;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|
||||||
data_p->addr = (void *)buf;
|
data_p->addr = (void *)buf;
|
||||||
@@ -984,12 +992,12 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *a)
|
|||||||
if (data_p->len < USB_MAX_PACKET_SIZE)
|
if (data_p->len < USB_MAX_PACKET_SIZE)
|
||||||
{
|
{
|
||||||
len = data_p->len;
|
len = data_p->len;
|
||||||
dev_p->state = LAST_IN_DATA;
|
dev->state = LAST_IN_DATA;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
len = USB_MAX_PACKET_SIZE;
|
len = USB_MAX_PACKET_SIZE;
|
||||||
dev_p->state = IN_DATA;
|
dev->state = IN_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
@@ -998,11 +1006,11 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *a)
|
|||||||
data_p->len -= len;
|
data_p->len -= len;
|
||||||
data_p->addr += len;
|
data_p->addr += len;
|
||||||
|
|
||||||
return USB_SUCCESS;
|
return USB_EVENT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_lld_rx_enable (int n, void *buf, size_t len)
|
usb_lld_rx_enable_buf (int n, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
int data01 = !((BD_table[4*n+!ep[n].rx_odd].ctrl >> 6)&1);
|
int data01 = !((BD_table[4*n+!ep[n].rx_odd].ctrl >> 6)&1);
|
||||||
|
|
||||||
@@ -1010,25 +1018,12 @@ usb_lld_rx_enable (int n, void *buf, size_t len)
|
|||||||
BD_table[4*n+ep[n].rx_odd].buf = buf;
|
BD_table[4*n+ep[n].rx_odd].buf = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
usb_lld_rx_data_len (int n)
|
|
||||||
{
|
|
||||||
return (BD_table[4*n+!ep[n].rx_odd].ctrl >> 16)&0x3ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_lld_tx_enable (uint8_t n, const void *buf, size_t len)
|
usb_lld_tx_enable_buf (int n, const void *buf, size_t len)
|
||||||
{
|
{
|
||||||
int data01 = !((BD_table[4*n+2+!ep[n].tx_odd].ctrl >> 6)&1);
|
int data01 = !((BD_table[4*n+2+!ep[n].tx_odd].ctrl >> 6)&1);
|
||||||
|
|
||||||
BD_table[4*n+2+ep[n].tx_odd].ctrl = (len << 16) | 0x0088 | (data01 << 6);
|
BD_table[4*n+2+ep[n].tx_odd].ctrl = (len << 16) | 0x0088 | (data01 << 6);
|
||||||
BD_table[4*n+2+ep[n].tx_odd].buf = (void *)buf;
|
BD_table[4*n+2+ep[n].tx_odd].buf = (void *)buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
usb_lld_tx_result (int ep_num)
|
|
||||||
{
|
|
||||||
(void)ep_num;
|
|
||||||
return 0; /* XXX: return -1 when NAK */
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* usb-stm32f103.c - USB driver for STM32F103
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Flying Stone Technology
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* This file is a part of Chopstx, a thread library for embedded.
|
||||||
|
*
|
||||||
|
* Chopstx is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Chopstx is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As additional permission under GNU GPL version 3 section 7, you may
|
||||||
|
* distribute non-source form of the Program without the copy of the
|
||||||
|
* GNU GPL normally required by section 4, provided you inform the
|
||||||
|
* receipents of GNU GPL by a written offer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "sys.h"
|
#include "sys-stm32f103.h"
|
||||||
#include "usb_lld.h"
|
#include "usb_lld.h"
|
||||||
|
|
||||||
#define USB_MAX_PACKET_SIZE 64 /* For FS device */
|
#define USB_MAX_PACKET_SIZE 64 /* For FS device */
|
||||||
@@ -28,50 +56,20 @@ enum STANDARD_REQUESTS
|
|||||||
enum CONTROL_STATE
|
enum CONTROL_STATE
|
||||||
{
|
{
|
||||||
WAIT_SETUP,
|
WAIT_SETUP,
|
||||||
SETTING_UP,
|
|
||||||
IN_DATA,
|
IN_DATA,
|
||||||
OUT_DATA,
|
OUT_DATA,
|
||||||
LAST_IN_DATA,
|
LAST_IN_DATA,
|
||||||
WAIT_STATUS_IN,
|
WAIT_STATUS_IN,
|
||||||
WAIT_STATUS_OUT,
|
WAIT_STATUS_OUT,
|
||||||
STALLED,
|
STALLED,
|
||||||
PAUSE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FEATURE_SELECTOR
|
enum FEATURE_SELECTOR
|
||||||
{
|
{
|
||||||
ENDPOINT_STALL,
|
FEATURE_ENDPOINT_HALT=0,
|
||||||
DEVICE_REMOTE_WAKEUP
|
FEATURE_DEVICE_REMOTE_WAKEUP=1
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DATA_INFO
|
|
||||||
{
|
|
||||||
uint8_t *addr;
|
|
||||||
uint16_t len;
|
|
||||||
uint8_t require_zlp;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct DEVICE_INFO
|
|
||||||
{
|
|
||||||
uint8_t current_configuration;
|
|
||||||
uint8_t current_feature;
|
|
||||||
uint8_t state;
|
|
||||||
/**/
|
|
||||||
uint8_t bmRequestType;
|
|
||||||
uint8_t bRequest;
|
|
||||||
/**/
|
|
||||||
uint16_t value;
|
|
||||||
uint16_t index;
|
|
||||||
uint16_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct DEVICE_INFO device_info;
|
|
||||||
static struct DATA_INFO data_info;
|
|
||||||
|
|
||||||
static struct DEVICE_INFO *const dev_p = &device_info;
|
|
||||||
static struct DATA_INFO *const data_p = &data_info;
|
|
||||||
|
|
||||||
#define REG_BASE (0x40005C00UL) /* USB_IP Peripheral Registers base address */
|
#define REG_BASE (0x40005C00UL) /* USB_IP Peripheral Registers base address */
|
||||||
#define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */
|
#define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */
|
||||||
|
|
||||||
@@ -153,7 +151,7 @@ static struct DATA_INFO *const data_p = &data_info;
|
|||||||
#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */
|
#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */
|
||||||
#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */
|
#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */
|
||||||
|
|
||||||
static void usb_handle_transfer (uint16_t istr_value);
|
static int usb_handle_transfer (struct usb_dev *dev, uint16_t istr_value);
|
||||||
|
|
||||||
static void st103_set_btable (void)
|
static void st103_set_btable (void)
|
||||||
{
|
{
|
||||||
@@ -348,14 +346,29 @@ static void st103_ep_clear_dtog_tx (uint8_t ep_num)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_lld_init (uint8_t feature)
|
void
|
||||||
|
usb_lld_ctrl_error (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
dev->state = STALLED;
|
||||||
|
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
usb_lld_ctrl_ack (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
dev->state = WAIT_STATUS_IN;
|
||||||
|
st103_set_tx_count (ENDP0, 0);
|
||||||
|
st103_ep_set_rxtx_status (ENDP0, EP_RX_NAK, EP_TX_VALID);
|
||||||
|
return USB_EVENT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_lld_init (struct usb_dev *dev, uint8_t feature)
|
||||||
{
|
{
|
||||||
usb_lld_sys_init ();
|
usb_lld_sys_init ();
|
||||||
|
|
||||||
dev_p->state = IN_DATA;
|
dev->configuration = 0;
|
||||||
|
dev->feature = feature;
|
||||||
usb_lld_set_configuration (0);
|
dev->state = WAIT_SETUP;
|
||||||
dev_p->current_feature = feature;
|
|
||||||
|
|
||||||
/* Reset USB */
|
/* Reset USB */
|
||||||
st103_set_cntr (CNTR_FRES);
|
st103_set_cntr (CNTR_FRES);
|
||||||
@@ -378,15 +391,18 @@ void usb_lld_shutdown (void)
|
|||||||
usb_lld_sys_shutdown ();
|
usb_lld_sys_shutdown ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
#define USB_MAKE_EV(event) (event<<24)
|
||||||
usb_interrupt_handler (void)
|
#define USB_MAKE_TXRX(ep_num,txrx,len) ((txrx? (1<<23):0)|(ep_num<<16)|len)
|
||||||
|
|
||||||
|
int
|
||||||
|
usb_lld_event_handler (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint16_t istr_value = st103_get_istr ();
|
uint16_t istr_value = st103_get_istr ();
|
||||||
|
|
||||||
if ((istr_value & ISTR_RESET))
|
if ((istr_value & ISTR_RESET))
|
||||||
{
|
{
|
||||||
st103_set_istr (CLR_RESET);
|
st103_set_istr (CLR_RESET);
|
||||||
usb_cb_device_reset ();
|
return USB_MAKE_EV (USB_EVENT_DEVICE_RESET);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -397,42 +413,45 @@ usb_interrupt_handler (void)
|
|||||||
st103_set_istr (CLR_ERR);
|
st103_set_istr (CLR_ERR);
|
||||||
|
|
||||||
if ((istr_value & ISTR_CTR))
|
if ((istr_value & ISTR_CTR))
|
||||||
usb_handle_transfer (istr_value);
|
return usb_handle_transfer (dev, istr_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return USB_EVENT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_datastage_out (void)
|
static void handle_datastage_out (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
if (data_p->addr && data_p->len)
|
if (dev->ctrl_data.addr && dev->ctrl_data.len)
|
||||||
{
|
{
|
||||||
uint32_t len = st103_get_rx_count (ENDP0);
|
uint32_t len = st103_get_rx_count (ENDP0);
|
||||||
|
|
||||||
if (len > data_p->len)
|
if (len > dev->ctrl_data.len)
|
||||||
len = data_p->len;
|
len = dev->ctrl_data.len;
|
||||||
|
|
||||||
usb_lld_from_pmabuf (data_p->addr, st103_get_rx_addr (ENDP0), len);
|
usb_lld_from_pmabuf (dev->ctrl_data.addr, st103_get_rx_addr (ENDP0), len);
|
||||||
data_p->len -= len;
|
dev->ctrl_data.len -= len;
|
||||||
data_p->addr += len;
|
dev->ctrl_data.addr += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_p->len == 0)
|
if (dev->ctrl_data.len == 0)
|
||||||
{
|
{
|
||||||
dev_p->state = WAIT_STATUS_IN;
|
dev->state = WAIT_STATUS_IN;
|
||||||
st103_set_tx_count (ENDP0, 0);
|
st103_set_tx_count (ENDP0, 0);
|
||||||
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
|
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dev_p->state = OUT_DATA;
|
dev->state = OUT_DATA;
|
||||||
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
|
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_datastage_in (void)
|
static void handle_datastage_in (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint32_t len = USB_MAX_PACKET_SIZE;;
|
uint32_t len = USB_MAX_PACKET_SIZE;;
|
||||||
|
struct ctrl_data *data_p = &dev->ctrl_data;
|
||||||
|
|
||||||
if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA))
|
if ((data_p->len == 0) && (dev->state == LAST_IN_DATA))
|
||||||
{
|
{
|
||||||
if (data_p->require_zlp)
|
if (data_p->require_zlp)
|
||||||
{
|
{
|
||||||
@@ -440,19 +459,19 @@ static void handle_datastage_in (void)
|
|||||||
|
|
||||||
/* No more data to send. Send empty packet */
|
/* No more data to send. Send empty packet */
|
||||||
st103_set_tx_count (ENDP0, 0);
|
st103_set_tx_count (ENDP0, 0);
|
||||||
st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_VALID);
|
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No more data to send, proceed to receive OUT acknowledge.*/
|
/* No more data to send, proceed to receive OUT acknowledge. */
|
||||||
dev_p->state = WAIT_STATUS_OUT;
|
dev->state = WAIT_STATUS_OUT;
|
||||||
st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_STALL);
|
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_p->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
|
dev->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
|
||||||
|
|
||||||
if (len > data_p->len)
|
if (len > data_p->len)
|
||||||
len = data_p->len;
|
len = data_p->len;
|
||||||
@@ -464,29 +483,30 @@ static void handle_datastage_in (void)
|
|||||||
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
|
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef int (*HANDLER) (uint8_t req, struct req_args *arg);
|
typedef int (*HANDLER) (struct usb_dev *dev);
|
||||||
|
|
||||||
static int std_none (uint8_t req, struct req_args *arg)
|
static int std_none (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
(void)req; (void)arg;
|
(void)dev;
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_get_status (uint8_t req, struct req_args *arg)
|
static int std_get_status (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = (arg->type & RECIPIENT);
|
||||||
uint16_t status_info = 0;
|
uint16_t status_info = 0;
|
||||||
|
|
||||||
if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
|
if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
|
||||||
|| USB_SETUP_SET (req))
|
|| USB_SETUP_SET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT)
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
{
|
{
|
||||||
if (arg->index == 0)
|
if (arg->index == 0)
|
||||||
{
|
{
|
||||||
/* Get Device Status */
|
/* Get Device Status */
|
||||||
uint8_t feature = dev_p->current_feature;
|
uint8_t feature = dev->feature;
|
||||||
|
|
||||||
/* Remote Wakeup enabled */
|
/* Remote Wakeup enabled */
|
||||||
if ((feature & (1 << 5)))
|
if ((feature & (1 << 5)))
|
||||||
@@ -500,21 +520,15 @@ static int std_get_status (uint8_t req, struct req_args *arg)
|
|||||||
else /* Self-powered */
|
else /* Self-powered */
|
||||||
status_info &= ~1;
|
status_info &= ~1;
|
||||||
|
|
||||||
return usb_lld_reply_request (&status_info, 2, arg);
|
return usb_lld_ctrl_send (dev, &status_info, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rcp == INTERFACE_RECIPIENT)
|
else if (rcp == INTERFACE_RECIPIENT)
|
||||||
{
|
{
|
||||||
int r;
|
if (dev->configuration == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (dev_p->current_configuration == 0)
|
return USB_EVENT_GET_STATUS_INTERFACE;
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
r = usb_cb_interface (USB_QUERY_INTERFACE, arg);
|
|
||||||
if (r != USB_SUCCESS)
|
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
return usb_lld_reply_request (&status_info, 2, arg);
|
|
||||||
}
|
}
|
||||||
else if (rcp == ENDPOINT_RECIPIENT)
|
else if (rcp == ENDPOINT_RECIPIENT)
|
||||||
{
|
{
|
||||||
@@ -522,13 +536,13 @@ static int std_get_status (uint8_t req, struct req_args *arg)
|
|||||||
uint16_t status;
|
uint16_t status;
|
||||||
|
|
||||||
if ((arg->index & 0x70) || endpoint == ENDP0)
|
if ((arg->index & 0x70) || endpoint == ENDP0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if ((arg->index & 0x80))
|
if ((arg->index & 0x80))
|
||||||
{
|
{
|
||||||
status = st103_ep_get_tx_status (endpoint);
|
status = st103_ep_get_tx_status (endpoint);
|
||||||
if (status == 0) /* Disabled */
|
if (status == 0) /* Disabled */
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
else if (status == EP_TX_STALL)
|
else if (status == EP_TX_STALL)
|
||||||
status_info |= 1; /* IN Endpoint stalled */
|
status_info |= 1; /* IN Endpoint stalled */
|
||||||
}
|
}
|
||||||
@@ -536,33 +550,34 @@ static int std_get_status (uint8_t req, struct req_args *arg)
|
|||||||
{
|
{
|
||||||
status = st103_ep_get_rx_status (endpoint);
|
status = st103_ep_get_rx_status (endpoint);
|
||||||
if (status == 0) /* Disabled */
|
if (status == 0) /* Disabled */
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
else if (status == EP_RX_STALL)
|
else if (status == EP_RX_STALL)
|
||||||
status_info |= 1; /* OUT Endpoint stalled */
|
status_info |= 1; /* OUT Endpoint stalled */
|
||||||
}
|
}
|
||||||
|
|
||||||
return usb_lld_reply_request (&status_info, 2, arg);
|
return usb_lld_ctrl_send (dev, &status_info, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_clear_feature (uint8_t req, struct req_args *arg)
|
static int std_clear_feature (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req))
|
if (USB_SETUP_GET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT)
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
{
|
{
|
||||||
if (arg->len != 0 || arg->index != 0)
|
if (arg->len != 0 || arg->index != 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->value == DEVICE_REMOTE_WAKEUP)
|
if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||||
{
|
{
|
||||||
dev_p->current_feature &= ~(1 << 5);
|
dev->feature &= ~(1 << 5);
|
||||||
return USB_SUCCESS;
|
return USB_EVENT_CLEAR_FEATURE_DEVICE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rcp == ENDPOINT_RECIPIENT)
|
else if (rcp == ENDPOINT_RECIPIENT)
|
||||||
@@ -570,50 +585,49 @@ static int std_clear_feature (uint8_t req, struct req_args *arg)
|
|||||||
uint8_t endpoint = (arg->index & 0x0f);
|
uint8_t endpoint = (arg->index & 0x0f);
|
||||||
uint16_t status;
|
uint16_t status;
|
||||||
|
|
||||||
if (dev_p->current_configuration == 0)
|
if (dev->configuration == 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->len != 0 || (arg->index >> 8) != 0
|
if (arg->len != 0 || (arg->index >> 8) != 0
|
||||||
|| arg->value != ENDPOINT_STALL || endpoint == ENDP0)
|
|| arg->value != FEATURE_ENDPOINT_HALT || endpoint == ENDP0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if ((arg->index & 0x80))
|
if ((arg->index & 0x80))
|
||||||
status = st103_ep_get_tx_status (endpoint);
|
status = st103_ep_get_tx_status (endpoint);
|
||||||
else
|
else
|
||||||
status = st103_ep_get_rx_status (endpoint);
|
status = st103_ep_get_rx_status (endpoint);
|
||||||
|
|
||||||
if (status == 0) /* Disabled */
|
if (status == 0) /* It's disabled endpoint. */
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->index & 0x80) /* IN endpoint */
|
if (arg->index & 0x80) /* IN endpoint */
|
||||||
st103_ep_clear_dtog_tx (endpoint);
|
st103_ep_clear_dtog_tx (endpoint);
|
||||||
else /* OUT endpoint */
|
else /* OUT endpoint */
|
||||||
st103_ep_clear_dtog_rx (endpoint);
|
st103_ep_clear_dtog_rx (endpoint);
|
||||||
|
|
||||||
// event??
|
return USB_EVENT_CLEAR_FEATURE_ENDPOINT;
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_set_feature (uint8_t req, struct req_args *arg)
|
static int std_set_feature (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req))
|
if (USB_SETUP_GET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT)
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
{
|
{
|
||||||
if (arg->len != 0 || arg->index != 0)
|
if (arg->len != 0 || arg->index != 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->value == DEVICE_REMOTE_WAKEUP)
|
if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP)
|
||||||
{
|
{
|
||||||
dev_p->current_feature |= 1 << 5;
|
dev->feature |= 1 << 5;
|
||||||
// event??
|
return USB_EVENT_SET_FEATURE_DEVICE;
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rcp == ENDPOINT_RECIPIENT)
|
else if (rcp == ENDPOINT_RECIPIENT)
|
||||||
@@ -621,280 +635,286 @@ static int std_set_feature (uint8_t req, struct req_args *arg)
|
|||||||
uint8_t endpoint = (arg->index & 0x0f);
|
uint8_t endpoint = (arg->index & 0x0f);
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
if (dev_p->current_configuration == 0)
|
if (dev->configuration == 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->len != 0 || (arg->index >> 8) != 0
|
if (arg->len != 0 || (arg->index >> 8) != 0
|
||||||
|| arg->value != 0 || endpoint == ENDP0)
|
|| arg->value != FEATURE_ENDPOINT_HALT || endpoint == ENDP0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if ((arg->index & 0x80))
|
if ((arg->index & 0x80))
|
||||||
status = st103_ep_get_tx_status (endpoint);
|
status = st103_ep_get_tx_status (endpoint);
|
||||||
else
|
else
|
||||||
status = st103_ep_get_rx_status (endpoint);
|
status = st103_ep_get_rx_status (endpoint);
|
||||||
|
|
||||||
if (status == 0) /* Disabled */
|
if (status == 0) /* It's disabled endpoint. */
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (arg->index & 0x80)
|
if (arg->index & 0x80) /* IN endpoint */
|
||||||
/* IN endpoint */
|
|
||||||
st103_ep_set_tx_status (endpoint, EP_TX_STALL);
|
st103_ep_set_tx_status (endpoint, EP_TX_STALL);
|
||||||
else
|
else /* OUT endpoint */
|
||||||
/* OUT endpoint */
|
|
||||||
st103_ep_set_rx_status (endpoint, EP_RX_STALL);
|
st103_ep_set_rx_status (endpoint, EP_RX_STALL);
|
||||||
|
|
||||||
// event??
|
return USB_EVENT_SET_FEATURE_ENDPOINT;
|
||||||
return USB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_set_address (uint8_t req, struct req_args *arg)
|
static int std_set_address (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req))
|
if (USB_SETUP_GET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
|
if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
|
||||||
&& arg->index == 0 && dev_p->current_configuration == 0)
|
&& arg->index == 0 && dev->configuration == 0)
|
||||||
return USB_SUCCESS;
|
return usb_lld_ctrl_ack (dev);
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_get_descriptor (uint8_t req, struct req_args *arg)
|
static int std_get_descriptor (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
if (USB_SETUP_SET (arg->type))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (USB_SETUP_SET (req))
|
return USB_EVENT_GET_DESCRIPTOR;
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
return usb_cb_get_descriptor (rcp, (arg->value >> 8),
|
|
||||||
(arg->value & 0xff), arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_get_configuration (uint8_t req, struct req_args *arg)
|
static int std_get_configuration (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_SET (req))
|
if (USB_SETUP_SET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
|
if (arg->value != 0 || arg->index != 0 || arg->len != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT)
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
return usb_lld_reply_request (&dev_p->current_configuration, 1, arg);
|
return usb_lld_ctrl_send (dev, &dev->configuration, 1);
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_set_configuration (uint8_t req, struct req_args *arg)
|
static int std_set_configuration (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req))
|
if (USB_SETUP_GET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0)
|
if (arg->index != 0 || arg->len != 0)
|
||||||
return usb_cb_handle_event (USB_EVENT_CONFIG, arg->value);
|
return -1;
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
if (rcp == DEVICE_RECIPIENT)
|
||||||
|
return USB_EVENT_SET_CONFIGURATION;
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_get_interface (uint8_t req, struct req_args *arg)
|
static int std_get_interface (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_SET (req))
|
if (USB_SETUP_SET (arg->type))
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
|
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (dev->configuration == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (rcp == INTERFACE_RECIPIENT)
|
if (rcp == INTERFACE_RECIPIENT)
|
||||||
{
|
return USB_EVENT_GET_INTERFACE;
|
||||||
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
|
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
if (dev_p->current_configuration == 0)
|
return -1;
|
||||||
return USB_UNSUPPORT;
|
|
||||||
|
|
||||||
return usb_cb_interface (USB_GET_INTERFACE, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return USB_UNSUPPORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_set_interface (uint8_t req, struct req_args *arg)
|
static int std_set_interface (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
uint8_t rcp = req & RECIPIENT;
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
|
||||||
if (USB_SETUP_GET (req) || rcp != INTERFACE_RECIPIENT
|
if (USB_SETUP_GET (arg->type) || rcp != INTERFACE_RECIPIENT
|
||||||
|| arg->len != 0 || (arg->index >> 8) != 0
|
|| arg->len != 0 || (arg->index >> 8) != 0
|
||||||
|| (arg->value >> 8) != 0 || dev_p->current_configuration == 0)
|
|| (arg->value >> 8) != 0 || dev->configuration == 0)
|
||||||
return USB_UNSUPPORT;
|
return -1;
|
||||||
|
|
||||||
return usb_cb_interface (USB_SET_INTERFACE, arg);
|
return USB_EVENT_SET_INTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void handle_setup0 (void)
|
static int handle_setup0 (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
const uint16_t *pw;
|
const uint16_t *pw;
|
||||||
uint16_t w;
|
uint16_t w;
|
||||||
uint8_t req_no;
|
uint8_t req_no;
|
||||||
int r = USB_UNSUPPORT;
|
|
||||||
HANDLER handler;
|
HANDLER handler;
|
||||||
|
|
||||||
pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2));
|
pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2));
|
||||||
w = *pw++;
|
w = *pw++;
|
||||||
|
|
||||||
dev_p->bmRequestType = w & 0xff;
|
dev->dev_req.type = (w & 0xff);
|
||||||
dev_p->bRequest = req_no = w >> 8;
|
dev->dev_req.request = req_no = (w >> 8);
|
||||||
pw++;
|
pw++;
|
||||||
dev_p->value = *pw++;
|
dev->dev_req.value = *pw++;
|
||||||
pw++;
|
pw++;
|
||||||
dev_p->index = *pw++;
|
dev->dev_req.index = *pw++;
|
||||||
pw++;
|
pw++;
|
||||||
dev_p->len = *pw;
|
dev->dev_req.len = *pw;
|
||||||
|
|
||||||
data_p->addr = NULL;
|
dev->ctrl_data.addr = NULL;
|
||||||
data_p->len = 0;
|
dev->ctrl_data.len = 0;
|
||||||
data_p->require_zlp = 0;
|
dev->ctrl_data.require_zlp = 0;
|
||||||
|
|
||||||
if ((dev_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST)
|
if ((dev->dev_req.type & REQUEST_TYPE) == STANDARD_REQUEST)
|
||||||
{
|
{
|
||||||
if (req_no < TOTAL_REQUEST)
|
int r;
|
||||||
{
|
|
||||||
switch (req_no)
|
|
||||||
{
|
|
||||||
case 0: handler = std_get_status; break;
|
|
||||||
case 1: handler = std_clear_feature; break;
|
|
||||||
case 3: handler = std_set_feature; break;
|
|
||||||
case 5: handler = std_set_address; break;
|
|
||||||
case 6: handler = std_get_descriptor; break;
|
|
||||||
case 8: handler = std_get_configuration; break;
|
|
||||||
case 9: handler = std_set_configuration; break;
|
|
||||||
case 10: handler = std_get_interface; break;
|
|
||||||
case 11: handler = std_set_interface; break;
|
|
||||||
default: handler = std_none; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = (*handler) (dev_p->bmRequestType,
|
switch (req_no)
|
||||||
(struct req_args *)&dev_p->value);
|
{
|
||||||
|
case 0: handler = std_get_status; break;
|
||||||
|
case 1: handler = std_clear_feature; break;
|
||||||
|
case 3: handler = std_set_feature; break;
|
||||||
|
case 5: handler = std_set_address; break;
|
||||||
|
case 6: handler = std_get_descriptor; break;
|
||||||
|
case 8: handler = std_get_configuration; break;
|
||||||
|
case 9: handler = std_set_configuration; break;
|
||||||
|
case 10: handler = std_get_interface; break;
|
||||||
|
case 11: handler = std_set_interface; break;
|
||||||
|
default: handler = std_none; break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
r = usb_cb_setup (dev_p->bmRequestType, req_no,
|
|
||||||
(struct req_args *)&dev_p->value);
|
|
||||||
|
|
||||||
if (r != USB_SUCCESS)
|
if ((r = (*handler) (dev)) < 0)
|
||||||
dev_p->state = STALLED;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (USB_SETUP_SET (dev_p->bmRequestType))
|
|
||||||
{
|
{
|
||||||
if (dev_p->len == 0)
|
usb_lld_ctrl_error (dev);
|
||||||
{
|
return USB_EVENT_OK;
|
||||||
dev_p->state = WAIT_STATUS_IN;
|
|
||||||
st103_set_tx_count (ENDP0, 0);
|
|
||||||
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dev_p->state = OUT_DATA;
|
|
||||||
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_in0 (void)
|
|
||||||
{
|
|
||||||
if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
|
|
||||||
handle_datastage_in ();
|
|
||||||
else if (dev_p->state == WAIT_STATUS_IN)
|
|
||||||
{
|
|
||||||
if ((dev_p->bRequest == SET_ADDRESS) &&
|
|
||||||
((dev_p->bmRequestType & (REQUEST_TYPE | RECIPIENT))
|
|
||||||
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
|
|
||||||
{
|
|
||||||
st103_set_daddr (dev_p->value);
|
|
||||||
usb_cb_handle_event (USB_EVENT_ADDRESS, dev_p->value);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
usb_cb_ctrl_write_finish (dev_p->bmRequestType, dev_p->bRequest,
|
return r;
|
||||||
(struct req_args *)&dev_p->value);
|
|
||||||
|
|
||||||
dev_p->state = STALLED;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dev_p->state = STALLED;
|
return USB_EVENT_CTRL_REQUEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_out0 (void)
|
static int handle_in0 (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
|
int r = 0;
|
||||||
/* host aborts the transfer before finish */
|
|
||||||
dev_p->state = STALLED;
|
if (dev->state == IN_DATA || dev->state == LAST_IN_DATA)
|
||||||
else if (dev_p->state == OUT_DATA)
|
handle_datastage_in (dev);
|
||||||
handle_datastage_out ();
|
else if (dev->state == WAIT_STATUS_IN)
|
||||||
else if (dev_p->state == WAIT_STATUS_OUT)
|
{
|
||||||
dev_p->state = STALLED;
|
dev->state = WAIT_SETUP;
|
||||||
/* Unexpect state, STALL the endpoint */
|
|
||||||
|
if ((dev->dev_req.request == SET_ADDRESS) &&
|
||||||
|
((dev->dev_req.type & (REQUEST_TYPE | RECIPIENT))
|
||||||
|
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
|
||||||
|
{
|
||||||
|
st103_set_daddr (dev->dev_req.value);
|
||||||
|
r = USB_EVENT_DEVICE_ADDRESSED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
r = USB_EVENT_CTRL_WRITE_FINISH;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
dev_p->state = STALLED;
|
{
|
||||||
|
dev->state = STALLED;
|
||||||
|
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void handle_out0 (struct usb_dev *dev)
|
||||||
usb_handle_transfer (uint16_t istr_value)
|
{
|
||||||
|
if (dev->state == OUT_DATA)
|
||||||
|
/* Usual case. */
|
||||||
|
handle_datastage_out (dev);
|
||||||
|
else if (dev->state == WAIT_STATUS_OUT)
|
||||||
|
/*
|
||||||
|
* Control READ transfer finished by ZLP.
|
||||||
|
* Leave ENDP0 status RX_NAK, TX_NAK.
|
||||||
|
*/
|
||||||
|
dev->state = WAIT_SETUP;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* dev->state == IN_DATA || dev->state == LAST_IN_DATA
|
||||||
|
* (Host aborts the transfer before finish)
|
||||||
|
* Or else, unexpected state.
|
||||||
|
* STALL the endpoint, until we receive the next SETUP token.
|
||||||
|
*/
|
||||||
|
dev->state = STALLED;
|
||||||
|
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_handle_transfer (struct usb_dev *dev, uint16_t istr_value)
|
||||||
{
|
{
|
||||||
uint16_t ep_value = 0;
|
uint16_t ep_value = 0;
|
||||||
uint8_t ep_index;
|
uint8_t ep_num = (istr_value & ISTR_EP_ID);
|
||||||
|
|
||||||
ep_index = (istr_value & ISTR_EP_ID);
|
ep_value = st103_get_epreg (ep_num);
|
||||||
/* Decode and service non control endpoints interrupt */
|
|
||||||
/* process related endpoint register */
|
|
||||||
ep_value = st103_get_epreg (ep_index);
|
|
||||||
|
|
||||||
if (ep_index == 0)
|
if (ep_num == 0)
|
||||||
{
|
{
|
||||||
if ((ep_value & EP_CTR_TX))
|
if ((ep_value & EP_CTR_TX))
|
||||||
{
|
{
|
||||||
st103_ep_clear_ctr_tx (ep_index);
|
st103_ep_clear_ctr_tx (ep_num);
|
||||||
handle_in0 ();
|
return USB_MAKE_EV (handle_in0 (dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ep_value & EP_CTR_RX))
|
if ((ep_value & EP_CTR_RX))
|
||||||
{
|
{
|
||||||
st103_ep_clear_ctr_rx (ep_index);
|
st103_ep_clear_ctr_rx (ep_num);
|
||||||
|
|
||||||
if ((ep_value & EP_SETUP))
|
if ((ep_value & EP_SETUP))
|
||||||
handle_setup0 ();
|
return USB_MAKE_EV (handle_setup0 (dev));
|
||||||
else
|
else
|
||||||
handle_out0 ();
|
{
|
||||||
|
handle_out0 (dev);
|
||||||
|
return USB_EVENT_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev_p->state == STALLED)
|
|
||||||
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
uint16_t len;
|
||||||
|
|
||||||
if ((ep_value & EP_CTR_RX))
|
if ((ep_value & EP_CTR_RX))
|
||||||
{
|
{
|
||||||
st103_ep_clear_ctr_rx (ep_index);
|
len = st103_get_rx_count (ep_num);
|
||||||
usb_cb_rx_ready (ep_index);
|
st103_ep_clear_ctr_rx (ep_num);
|
||||||
|
return USB_MAKE_TXRX (ep_num, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ep_value & EP_CTR_TX))
|
if ((ep_value & EP_CTR_TX))
|
||||||
{
|
{
|
||||||
st103_ep_clear_ctr_tx (ep_index);
|
len = st103_get_tx_count (ep_num);
|
||||||
usb_cb_tx_done (ep_index);
|
st103_ep_clear_ctr_tx (ep_num);
|
||||||
|
return USB_MAKE_TXRX (ep_num, 1, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return USB_EVENT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_lld_reset (uint8_t feature)
|
void usb_lld_reset (struct usb_dev *dev, uint8_t feature)
|
||||||
{
|
{
|
||||||
usb_lld_set_configuration (0);
|
usb_lld_set_configuration (dev, 0);
|
||||||
dev_p->current_feature = feature;
|
dev->feature = feature;
|
||||||
st103_set_btable ();
|
st103_set_btable ();
|
||||||
st103_set_daddr (0);
|
st103_set_daddr (0);
|
||||||
}
|
}
|
||||||
@@ -924,16 +944,6 @@ void usb_lld_tx_enable (int ep_num, size_t len)
|
|||||||
st103_ep_set_tx_status (ep_num, EP_TX_VALID);
|
st103_ep_set_tx_status (ep_num, EP_TX_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_lld_tx_data_len (int ep_num)
|
|
||||||
{
|
|
||||||
return st103_get_tx_count (ep_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
int usb_lld_rx_data_len (int ep_num)
|
|
||||||
{
|
|
||||||
return st103_get_rx_count (ep_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usb_lld_stall_tx (int ep_num)
|
void usb_lld_stall_tx (int ep_num)
|
||||||
{
|
{
|
||||||
st103_ep_set_tx_status (ep_num, EP_TX_STALL);
|
st103_ep_set_tx_status (ep_num, EP_TX_STALL);
|
||||||
@@ -972,7 +982,7 @@ void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
|
|||||||
|
|
||||||
if (ep_rx_addr)
|
if (ep_rx_addr)
|
||||||
{
|
{
|
||||||
ep_rxtx_status |= EP_RX_VALID;
|
ep_rxtx_status |= EP_RX_NAK;
|
||||||
st103_set_rx_addr (ep_num, ep_rx_addr);
|
st103_set_rx_addr (ep_num, ep_rx_addr);
|
||||||
st103_set_rx_buf_size (ep_num, ep_rx_buf_size);
|
st103_set_rx_buf_size (ep_num, ep_rx_buf_size);
|
||||||
}
|
}
|
||||||
@@ -991,20 +1001,24 @@ void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
|
|||||||
st103_set_epreg (ep_num, epreg_value);
|
st103_set_epreg (ep_num, epreg_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_lld_set_configuration (uint8_t config)
|
void usb_lld_set_configuration (struct usb_dev *dev, uint8_t config)
|
||||||
{
|
{
|
||||||
dev_p->current_configuration = config;
|
dev->configuration = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t usb_lld_current_configuration (void)
|
uint8_t usb_lld_current_configuration (struct usb_dev *dev)
|
||||||
{
|
{
|
||||||
return dev_p->current_configuration;
|
return dev->configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_lld_set_data_to_recv (void *p, size_t len)
|
int usb_lld_ctrl_recv (struct usb_dev *dev, void *p, size_t len)
|
||||||
{
|
{
|
||||||
|
struct ctrl_data *data_p = &dev->ctrl_data;
|
||||||
data_p->addr = p;
|
data_p->addr = p;
|
||||||
data_p->len = len;
|
data_p->len = len;
|
||||||
|
dev->state = OUT_DATA;
|
||||||
|
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
|
||||||
|
return USB_EVENT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n)
|
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n)
|
||||||
@@ -1088,9 +1102,10 @@ void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n)
|
|||||||
* BUFLEN: size of the data.
|
* BUFLEN: size of the data.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl)
|
usb_lld_ctrl_send (struct usb_dev *dev, const void *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
uint32_t len_asked = ctl->len;
|
struct ctrl_data *data_p = &dev->ctrl_data;
|
||||||
|
uint32_t len_asked = dev->dev_req.len;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|
||||||
data_p->addr = (void *)buf;
|
data_p->addr = (void *)buf;
|
||||||
@@ -1106,12 +1121,12 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl)
|
|||||||
if (data_p->len < USB_MAX_PACKET_SIZE)
|
if (data_p->len < USB_MAX_PACKET_SIZE)
|
||||||
{
|
{
|
||||||
len = data_p->len;
|
len = data_p->len;
|
||||||
dev_p->state = LAST_IN_DATA;
|
dev->state = LAST_IN_DATA;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
len = USB_MAX_PACKET_SIZE;
|
len = USB_MAX_PACKET_SIZE;
|
||||||
dev_p->state = IN_DATA;
|
dev->state = IN_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
@@ -1122,6 +1137,6 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
st103_set_tx_count (ENDP0, len);
|
st103_set_tx_count (ENDP0, len);
|
||||||
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
|
st103_ep_set_rxtx_status (ENDP0, EP_RX_NAK, EP_TX_VALID);
|
||||||
return USB_SUCCESS;
|
return USB_EVENT_OK;
|
||||||
}
|
}
|
||||||
10
rules.mk
10
rules.mk
@@ -6,6 +6,16 @@ ifneq ($(USE_EVENTFLAG),)
|
|||||||
CSRC += $(CHOPSTX)/eventflag.c
|
CSRC += $(CHOPSTX)/eventflag.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(USE_SYS),)
|
||||||
|
CSRC += $(CHOPSTX)/mcu/sys-$(CHIP).c
|
||||||
|
endif
|
||||||
|
ifneq ($(USE_USB),)
|
||||||
|
CSRC += $(CHOPSTX)/mcu/usb-$(CHIP).c
|
||||||
|
endif
|
||||||
|
ifneq ($(USE_ADC),)
|
||||||
|
CSRC += $(CHOPSTX)/contrib/adc-$(CHIP).c
|
||||||
|
endif
|
||||||
|
|
||||||
INCDIR += $(CHOPSTX)
|
INCDIR += $(CHOPSTX)
|
||||||
|
|
||||||
BUILDDIR = build
|
BUILDDIR = build
|
||||||
|
|||||||
7
sys.h
Normal file
7
sys.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#if defined(MCU_KINETIS_L)
|
||||||
|
#include "mcu/sys-mkl27z.h"
|
||||||
|
#elif defined(MCU_STM32F0)
|
||||||
|
#include "mcu/sys-stm32f0.h"
|
||||||
|
#else
|
||||||
|
#include "mcu/sys-stm32f103.h"
|
||||||
|
#endif
|
||||||
164
usb_lld.h
Normal file
164
usb_lld.h
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
#define STANDARD_ENDPOINT_DESC_SIZE 0x09
|
||||||
|
|
||||||
|
/* endpoints enumeration */
|
||||||
|
#define ENDP0 ((uint8_t)0)
|
||||||
|
#define ENDP1 ((uint8_t)1)
|
||||||
|
#define ENDP2 ((uint8_t)2)
|
||||||
|
#define ENDP3 ((uint8_t)3)
|
||||||
|
#define ENDP4 ((uint8_t)4)
|
||||||
|
#define ENDP5 ((uint8_t)5)
|
||||||
|
#define ENDP6 ((uint8_t)6)
|
||||||
|
#define ENDP7 ((uint8_t)7)
|
||||||
|
|
||||||
|
enum RECIPIENT_TYPE
|
||||||
|
{
|
||||||
|
DEVICE_RECIPIENT = 0, /* Recipient device */
|
||||||
|
INTERFACE_RECIPIENT, /* Recipient interface */
|
||||||
|
ENDPOINT_RECIPIENT, /* Recipient endpoint */
|
||||||
|
OTHER_RECIPIENT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DESCRIPTOR_TYPE
|
||||||
|
{
|
||||||
|
DEVICE_DESCRIPTOR = 1,
|
||||||
|
CONFIG_DESCRIPTOR,
|
||||||
|
STRING_DESCRIPTOR,
|
||||||
|
INTERFACE_DESCRIPTOR,
|
||||||
|
ENDPOINT_DESCRIPTOR
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REQUEST_DIR 0x80 /* Mask to get request dir */
|
||||||
|
#define REQUEST_TYPE 0x60 /* Mask to get request type */
|
||||||
|
#define STANDARD_REQUEST 0x00 /* Standard request */
|
||||||
|
#define CLASS_REQUEST 0x20 /* Class request */
|
||||||
|
#define VENDOR_REQUEST 0x40 /* Vendor request */
|
||||||
|
#define RECIPIENT 0x1F /* Mask to get recipient */
|
||||||
|
|
||||||
|
#define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0)
|
||||||
|
#define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0)
|
||||||
|
|
||||||
|
struct device_req {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t request;
|
||||||
|
uint16_t value;
|
||||||
|
uint16_t index;
|
||||||
|
uint16_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ctrl_data {
|
||||||
|
uint8_t *addr;
|
||||||
|
uint16_t len;
|
||||||
|
uint8_t require_zlp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usb_dev {
|
||||||
|
uint8_t configuration;
|
||||||
|
uint8_t feature;
|
||||||
|
uint8_t state;
|
||||||
|
struct device_req dev_req;
|
||||||
|
struct ctrl_data ctrl_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
USB_EVENT_OK=0, /* Processed in lower layer. */
|
||||||
|
/* Device reset and suspend. */
|
||||||
|
USB_EVENT_DEVICE_RESET,
|
||||||
|
USB_EVENT_DEVICE_SUSPEND,
|
||||||
|
/* Device Requests (Control WRITE Transfer): Standard */
|
||||||
|
USB_EVENT_SET_CONFIGURATION,
|
||||||
|
USB_EVENT_SET_INTERFACE,
|
||||||
|
USB_EVENT_SET_FEATURE_DEVICE,
|
||||||
|
USB_EVENT_SET_FEATURE_ENDPOINT,
|
||||||
|
USB_EVENT_CLEAR_FEATURE_DEVICE,
|
||||||
|
USB_EVENT_CLEAR_FEATURE_ENDPOINT,
|
||||||
|
/* Device Requests (Control READ Transfer): Standard */
|
||||||
|
USB_EVENT_GET_STATUS_INTERFACE,
|
||||||
|
USB_EVENT_GET_DESCRIPTOR,
|
||||||
|
USB_EVENT_GET_INTERFACE,
|
||||||
|
/* Device Requests (Control READ/WRITE Transfer): Non-Standard */
|
||||||
|
USB_EVENT_CTRL_REQUEST,
|
||||||
|
USB_EVENT_CTRL_WRITE_FINISH,
|
||||||
|
/* Device addressed. */
|
||||||
|
USB_EVENT_DEVICE_ADDRESSED,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DEVICE_STATE {
|
||||||
|
UNCONNECTED,
|
||||||
|
ATTACHED,
|
||||||
|
POWERED,
|
||||||
|
SUSPENDED,
|
||||||
|
ADDRESSED,
|
||||||
|
CONFIGURED
|
||||||
|
};
|
||||||
|
|
||||||
|
void usb_lld_init (struct usb_dev *dev, uint8_t feature);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return value is encoded integer:
|
||||||
|
* event-no: 8-bit, 0 if TX/RX
|
||||||
|
* tx/rx-flag: 1-bit, 0 if rx, 1 if tx
|
||||||
|
* endpoint no: 7-bit
|
||||||
|
* length: 16-bit
|
||||||
|
*/
|
||||||
|
#define USB_EVENT_TXRX(e) ((e >> 23) & 1)
|
||||||
|
#define USB_EVENT_LEN(e) (e & 0xffff)
|
||||||
|
#define USB_EVENT_ENDP(e) ((e >> 16) & 0x7f)
|
||||||
|
#define USB_EVENT_ID(e) ((e >> 24))
|
||||||
|
int usb_lld_event_handler (struct usb_dev *dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control Endpoint ENDP0 does device requests handling.
|
||||||
|
* In response to an event of
|
||||||
|
* USB_EVENT_SET_CONFIGURATION
|
||||||
|
* USB_EVENT_SET_INTERFACE
|
||||||
|
* USB_EVENT_SET_FEATURE_DEVICE
|
||||||
|
* USB_EVENT_SET_FEATURE_ENDPOINT
|
||||||
|
* USB_EVENT_CLEAR_FEATURE_DEVICE
|
||||||
|
* USB_EVENT_CLEAR_FEATURE_ENDPOINT
|
||||||
|
* USB_EVENT_GET_STATUS_INTERFACE
|
||||||
|
* USB_EVENT_GET_DESCRIPTOR
|
||||||
|
* USB_EVENT_GET_INTERFACE
|
||||||
|
* USB_EVENT_CTRL_REQUEST
|
||||||
|
* a single action should be done, which is SEND, RECV, or,
|
||||||
|
* ACKNOWLEDGE (no data to be sent, or to be received).
|
||||||
|
* Otherwise, it's an error.
|
||||||
|
*/
|
||||||
|
int usb_lld_ctrl_send (struct usb_dev *dev, const void *buf, size_t buflen);
|
||||||
|
int usb_lld_ctrl_recv (struct usb_dev *dev, void *p, size_t len);
|
||||||
|
int usb_lld_ctrl_ack (struct usb_dev *dev);
|
||||||
|
void usb_lld_ctrl_error (struct usb_dev *dev);
|
||||||
|
|
||||||
|
void usb_lld_reset (struct usb_dev *dev, uint8_t feature);
|
||||||
|
void usb_lld_set_configuration (struct usb_dev *dev, uint8_t config);
|
||||||
|
uint8_t usb_lld_current_configuration (struct usb_dev *dev);
|
||||||
|
void usb_lld_prepare_shutdown (void);
|
||||||
|
void usb_lld_shutdown (void);
|
||||||
|
|
||||||
|
#ifdef MCU_KINETIS_L
|
||||||
|
void usb_lld_tx_enable_buf (int ep_num, const void *buf, size_t len);
|
||||||
|
void usb_lld_rx_enable_buf (int ep_num, void *buf, size_t len);
|
||||||
|
|
||||||
|
void usb_lld_setup_endp (struct usb_dev *dev, int ep_num, int rx_en, int tx_en);
|
||||||
|
void usb_lld_stall (int ep_num);
|
||||||
|
#else
|
||||||
|
/* EP_TYPE[1:0] EndPoint TYPE */
|
||||||
|
#define EP_BULK (0x0000) /* EndPoint BULK */
|
||||||
|
#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
|
||||||
|
#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
|
||||||
|
#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */
|
||||||
|
|
||||||
|
void usb_lld_tx_enable (int ep_num, size_t len);
|
||||||
|
void usb_lld_rx_enable (int ep_num);
|
||||||
|
|
||||||
|
void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
|
||||||
|
int ep_rx_addr, int ep_tx_addr,
|
||||||
|
int ep_rx_memory_size);
|
||||||
|
void usb_lld_stall_tx (int ep_num);
|
||||||
|
void usb_lld_stall_rx (int ep_num);
|
||||||
|
|
||||||
|
void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len);
|
||||||
|
void usb_lld_write (uint8_t ep_num, const void *buf, size_t len);
|
||||||
|
void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
|
||||||
|
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
|
||||||
|
void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user