44 Commits

Author SHA1 Message Date
Niibe Yutaka
40adf95c24 Version 1.0 2016-06-16 11:46:38 +09:00
Niibe Yutaka
5a7381ece6 Add FST-01G 2016-06-16 11:31:10 +09:00
Niibe Yutaka
52626a3368 chopstx_exit change 2016-06-15 12:41:12 +09:00
Niibe Yutaka
440188c373 Fix USB for STM32 2016-06-14 15:10:07 +09:00
NIIBE Yutaka
a6541cbcc6 NONE sounds bad, use OK instead 2016-06-10 08:25:00 +09:00
NIIBE Yutaka
74c7b5bcb3 minor comment change 2016-06-09 10:07:31 +09:00
NIIBE Yutaka
4d7e97028e More update of USB API 2016-06-09 09:53:15 +09:00
NIIBE Yutaka
d061e6f931 USB for FS-BB48 2016-06-08 15:43:11 +09:00
NIIBE Yutaka
5f1c26ff17 USB API major change 2016-06-08 15:40:55 +09:00
NIIBE Yutaka
78718e57df Move files 2016-06-02 11:01:11 +09:00
NIIBE Yutaka
a756987d2a Fix chx_fatal 2016-06-01 07:47:58 +09:00
NIIBE Yutaka
b6e3a1aba1 Relicense ADC driver with GPLv3+ plus EXCEPTION 2016-05-31 21:41:40 +09:00
NIIBE Yutaka
c79a41870a Version 0.12 2016-05-31 15:18:10 +09:00
NIIBE Yutaka
4889a5386b STM32F030: Fix use of vector on RAM 2016-05-31 15:12:55 +09:00
NIIBE Yutaka
e02f2e71e6 Fix f2a8b01607 2016-05-31 14:18:12 +09:00
NIIBE Yutaka
1fa89d1754 Change USB API a bit 2016-05-31 13:13:14 +09:00
NIIBE Yutaka
03a1d46c08 Fix sys-stm32f103.h 2016-05-31 12:00:25 +09:00
NIIBE Yutaka
3a4e1f2bd5 Cleanup of sys and its macro 2016-05-31 11:49:01 +09:00
NIIBE Yutaka
421fd8019b ; ABOUT-SYS 2016-05-30 20:34:06 +09:00
NIIBE Yutaka
e8eaeced77 Update USB for stm32f103 2016-05-30 20:11:18 +09:00
NIIBE Yutaka
1ae3caf7fc USB cleanup 2016-05-30 20:06:43 +09:00
NIIBE Yutaka
a933eebfd5 Update for STM32F103 2016-05-30 15:13:55 +09:00
NIIBE Yutaka
fae4c58d99 AES table is included in sys-stm32f103.c 2016-05-30 14:57:51 +09:00
NIIBE Yutaka
9f16e5e051 consolidate mcu-chip specific code 2016-05-30 14:57:10 +09:00
NIIBE Yutaka
b90e58f763 Move CHIP specific things to mcu/ 2016-05-30 14:39:02 +09:00
NIIBE Yutaka
8209f38755 example-fs-bb48: Add flash ROM handling 2016-05-30 14:06:18 +09:00
NIIBE Yutaka
781ad1847c example-fs-bb48: rm crc32.h 2016-05-27 17:29:36 +09:00
NIIBE Yutaka
8eb2130664 example-fs-bb48: rm crc32.h 2016-05-27 17:29:08 +09:00
NIIBE Yutaka
960921f537 example-fs-bb48: SYS implementation 2016-05-27 17:17:44 +09:00
NIIBE Yutaka
f2a8b01607 Fix IDLE thread 2016-05-27 16:19:02 +09:00
NIIBE Yutaka
890d108114 Add document for ABOUT-SYS 2016-05-27 11:22:29 +09:00
NIIBE Yutaka
5f57222b73 Move clk_gpio_init to mcu/ 2016-05-26 17:40:47 +09:00
NIIBE Yutaka
d81767b7c7 example-fs-bb48: Only use LS-8-bit 2016-05-26 17:29:06 +09:00
NIIBE Yutaka
91823d0fc1 Move kl_sim.h 2016-05-26 10:21:30 +09:00
NIIBE Yutaka
51cd47c3b7 example-fs-bb48: ADC use DIV1 2016-05-26 09:54:44 +09:00
NIIBE Yutaka
cf81e7a6dc example-fs-bb48: ADC added 2016-05-26 09:50:07 +09:00
NIIBE Yutaka
2578fc0f30 Update example-fs-bb48 2016-05-24 17:34:20 +09:00
NIIBE Yutaka
2704416c38 Fix PSR handling (ORRS instruction changes PSR) 2016-05-23 20:15:47 +09:00
NIIBE Yutaka
77255b0c1d Fix chopstx_poll 2016-05-23 17:45:10 +09:00
NIIBE Yutaka
eeb354119c Change example-cdc 2016-05-23 17:42:21 +09:00
NIIBE Yutaka
72c3d59555 Change example-fs-bb48 2016-05-23 17:42:01 +09:00
NIIBE Yutaka
8ba91f5db6 Fix example-fs-bb48 to support 16 endpoints 2016-05-23 17:36:31 +09:00
NIIBE Yutaka
b6603f6771 Update example-fs-bb48 2016-05-23 13:48:24 +09:00
NIIBE Yutaka
ee92bb15b3 Remove deprecated API 2016-05-23 13:00:33 +09:00
64 changed files with 4389 additions and 3052 deletions

15
AUTHORS
View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -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

View File

@@ -1 +1 @@
release/0.11 release/1.0

View File

@@ -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
View File

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

View File

@@ -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.
* *

View File

@@ -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);

View File

@@ -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
View 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
View 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;
}
}
}

View File

@@ -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})

View File

@@ -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
View File

@@ -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

View File

@@ -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 =

View File

@@ -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

View File

@@ -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] = ':';

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 =

View File

@@ -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
View 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));
}
}

View File

@@ -0,0 +1 @@
void cmd_dispatch (struct tty *tty, const char *line);

2
example-fs-bb48/config.h Normal file
View File

@@ -0,0 +1,2 @@
#define CRC32_SUPPORT
#define ADC_SUPPORT

22
example-fs-bb48/crc32.c Normal file
View 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);
}

View File

@@ -1,5 +0,0 @@
void crc32_init (void);
void crc32_u8 (unsigned char);
void crc32_u32 (unsigned int);
unsigned int crc32_value (void);

View File

@@ -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);
}

View File

@@ -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;
} }
} }

View File

@@ -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.*)

View File

@@ -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
View 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

View File

@@ -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);

View File

@@ -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

View File

@@ -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
{ {

View File

@@ -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 */

View File

@@ -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 =

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 =

View File

@@ -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

View File

@@ -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 */

View File

@@ -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,
};

View File

@@ -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
View 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.
--

View File

@@ -1,5 +1,5 @@
/* /*
* clk_gpio_init-kl.c - Clock and GPIO initialization for Kinetis L. * clk_gpio_init-mkl27z.c - Clock and GPIO initialization for Kinetis L.
* *
* Copyright (C) 2016 Flying Stone Technology * 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 */

View File

@@ -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
View 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
View 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
View 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

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 */
}

View File

@@ -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;
} }

View File

@@ -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
View 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
View 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