diff options
Diffstat (limited to 'libmaple')
-rw-r--r-- | libmaple/adc.c | 1 | ||||
-rw-r--r-- | libmaple/exti.c | 106 | ||||
-rw-r--r-- | libmaple/flash.c | 1 | ||||
-rw-r--r-- | libmaple/gpio.c | 1 | ||||
-rw-r--r-- | libmaple/include/libmaple/exti.h | 5 | ||||
-rw-r--r-- | libmaple/include/libmaple/libmaple_types.h | 1 | ||||
-rw-r--r-- | libmaple/include/libmaple/usb.h | 1 | ||||
-rw-r--r-- | libmaple/include/libmaple/usb_cdcacm.h | 22 | ||||
-rw-r--r-- | libmaple/nvic.c | 1 | ||||
-rw-r--r-- | libmaple/stm32f1/bkp.c | 4 | ||||
-rw-r--r-- | libmaple/stm32f1/dma.c | 1 | ||||
-rw-r--r-- | libmaple/stm32f1/include/series/dma.h | 10 | ||||
-rw-r--r-- | libmaple/stm32f1/performance/isrs.S | 2 | ||||
-rw-r--r-- | libmaple/stm32f1/performance/vector_table.S | 2 | ||||
-rw-r--r-- | libmaple/stm32f1/rules.mk | 3 | ||||
-rw-r--r-- | libmaple/systick.c | 1 | ||||
-rw-r--r-- | libmaple/timer.c | 2 | ||||
-rw-r--r-- | libmaple/usart.c | 1 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb.c | 196 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb_cdcacm.c | 64 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb_reg_map.c | 13 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb_reg_map.h | 230 | ||||
-rw-r--r-- | libmaple/util.c | 1 |
23 files changed, 487 insertions, 182 deletions
diff --git a/libmaple/adc.c b/libmaple/adc.c index e108332..7ea85dd 100644 --- a/libmaple/adc.c +++ b/libmaple/adc.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/libmaple/exti.c b/libmaple/exti.c index 9023782..f8ee8c3 100644 --- a/libmaple/exti.c +++ b/libmaple/exti.c @@ -43,27 +43,27 @@ static inline void dispatch_extis(uint32 start, uint32 stop); */ typedef struct exti_channel { - void (*handler)(void); - uint32 irq_line; + void (*handler)(void *); + void *arg; } exti_channel; static exti_channel exti_channels[] = { - { .handler = NULL, .irq_line = NVIC_EXTI0 }, // EXTI0 - { .handler = NULL, .irq_line = NVIC_EXTI1 }, // EXTI1 - { .handler = NULL, .irq_line = NVIC_EXTI2 }, // EXTI2 - { .handler = NULL, .irq_line = NVIC_EXTI3 }, // EXTI3 - { .handler = NULL, .irq_line = NVIC_EXTI4 }, // EXTI4 - { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI5 - { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI6 - { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI7 - { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI8 - { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI9 - { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI10 - { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI11 - { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI12 - { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI13 - { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI14 - { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI15 + { .handler = NULL, .arg = NULL }, // EXTI0 + { .handler = NULL, .arg = NULL }, // EXTI1 + { .handler = NULL, .arg = NULL }, // EXTI2 + { .handler = NULL, .arg = NULL }, // EXTI3 + { .handler = NULL, .arg = NULL }, // EXTI4 + { .handler = NULL, .arg = NULL }, // EXTI5 + { .handler = NULL, .arg = NULL }, // EXTI6 + { .handler = NULL, .arg = NULL }, // EXTI7 + { .handler = NULL, .arg = NULL }, // EXTI8 + { .handler = NULL, .arg = NULL }, // EXTI9 + { .handler = NULL, .arg = NULL }, // EXTI10 + { .handler = NULL, .arg = NULL }, // EXTI11 + { .handler = NULL, .arg = NULL }, // EXTI12 + { .handler = NULL, .arg = NULL }, // EXTI13 + { .handler = NULL, .arg = NULL }, // EXTI14 + { .handler = NULL, .arg = NULL }, // EXTI15 }; /* @@ -90,10 +90,37 @@ void exti_attach_interrupt(exti_num num, exti_cfg port, voidFuncPtr handler, exti_trigger_mode mode) { + // Call callback version with arg being null + exti_attach_callback(num, port, (voidArgumentFuncPtr)handler, NULL, mode); +} + +/** + * @brief Register a handler with an argument to run upon external interrupt. + * + * This function assumes that the interrupt request corresponding to + * the given external interrupt is masked. + * + * @param num External interrupt line number. + * @param port Port to use as source input for external interrupt. + * @param handler Function handler to execute when interrupt is triggered. + * @param arg Argument to pass to the interrupt handler. + * @param mode Type of transition to trigger on, one of: + * EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING. + * @see exti_num + * @see exti_cfg + * @see voidFuncPtr + * @see exti_trigger_mode + */ +void exti_attach_callback(exti_num num, + exti_cfg port, + voidArgumentFuncPtr handler, + void *arg, + exti_trigger_mode mode) { ASSERT(handler); /* Register the handler */ exti_channels[num].handler = handler; + exti_channels[num].arg = arg; /* Set trigger mode */ switch (mode) { @@ -116,7 +143,39 @@ void exti_attach_interrupt(exti_num num, bb_peri_set_bit(&EXTI_BASE->IMR, num, 1); /* Enable the interrupt line */ - nvic_irq_enable(exti_channels[num].irq_line); + switch(num) + { + case EXTI0: + nvic_irq_enable(NVIC_EXTI0); + break; + case EXTI1: + nvic_irq_enable(NVIC_EXTI1); + break; + case EXTI2: + nvic_irq_enable(NVIC_EXTI2); + break; + case EXTI3: + nvic_irq_enable(NVIC_EXTI3); + break; + case EXTI4: + nvic_irq_enable(NVIC_EXTI4); + break; + case EXTI5: + case EXTI6: + case EXTI7: + case EXTI8: + case EXTI9: + nvic_irq_enable(NVIC_EXTI_9_5); + break; + case EXTI10: + case EXTI11: + case EXTI12: + case EXTI13: + case EXTI14: + case EXTI15: + nvic_irq_enable(NVIC_EXTI_15_10); + break; + } } /** @@ -134,6 +193,7 @@ void exti_detach_interrupt(exti_num num) { /* Finally, unregister the user's handler */ exti_channels[num].handler = NULL; + exti_channels[num].arg = NULL; } /* @@ -199,13 +259,13 @@ static __always_inline void clear_pending_msk(uint32 exti_msk) { /* This dispatch routine is for non-multiplexed EXTI lines only; i.e., * it doesn't check EXTI_PR. */ static __always_inline void dispatch_single_exti(uint32 exti) { - voidFuncPtr handler = exti_channels[exti].handler; + voidArgumentFuncPtr handler = exti_channels[exti].handler; if (!handler) { return; } - handler(); + handler(exti_channels[exti].arg); clear_pending_msk(1U << exti); } @@ -219,9 +279,9 @@ static __always_inline void dispatch_extis(uint32 start, uint32 stop) { for (exti = start; exti <= stop; exti++) { uint32 eb = (1U << exti); if (pr & eb) { - voidFuncPtr handler = exti_channels[exti].handler; + voidArgumentFuncPtr handler = exti_channels[exti].handler; if (handler) { - handler(); + handler(exti_channels[exti].arg); handled_msk |= eb; } } diff --git a/libmaple/flash.c b/libmaple/flash.c index 0cdff59..c57bbbf 100644 --- a/libmaple/flash.c +++ b/libmaple/flash.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/libmaple/gpio.c b/libmaple/gpio.c index 898007a..6e63d2f 100644 --- a/libmaple/gpio.c +++ b/libmaple/gpio.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/libmaple/include/libmaple/exti.h b/libmaple/include/libmaple/exti.h index 3800b4a..1d201ac 100644 --- a/libmaple/include/libmaple/exti.h +++ b/libmaple/include/libmaple/exti.h @@ -115,6 +115,11 @@ void exti_attach_interrupt(exti_num num, exti_cfg port, voidFuncPtr handler, exti_trigger_mode mode); +void exti_attach_callback(exti_num num, + exti_cfg port, + voidArgumentFuncPtr handler, + void *arg, + exti_trigger_mode mode); void exti_detach_interrupt(exti_num num); /** diff --git a/libmaple/include/libmaple/libmaple_types.h b/libmaple/include/libmaple/libmaple_types.h index 9e1fbb3..60dd2ff 100644 --- a/libmaple/include/libmaple/libmaple_types.h +++ b/libmaple/include/libmaple/libmaple_types.h @@ -48,6 +48,7 @@ typedef int int32; typedef long long int64; typedef void (*voidFuncPtr)(void); +typedef void (*voidArgumentFuncPtr)(void *); #define __io volatile #define __attr_flash __attribute__((section (".USER_FLASH"))) diff --git a/libmaple/include/libmaple/usb.h b/libmaple/include/libmaple/usb.h index 2be5971..ea24030 100644 --- a/libmaple/include/libmaple/usb.h +++ b/libmaple/include/libmaple/usb.h @@ -151,6 +151,7 @@ typedef struct usblib_dev { void (**ep_int_in)(void); void (**ep_int_out)(void); usb_dev_state state; + usb_dev_state prevState; rcc_clk_id clk_id; } usblib_dev; diff --git a/libmaple/include/libmaple/usb_cdcacm.h b/libmaple/include/libmaple/usb_cdcacm.h index 8b3c1fe..5fe832c 100644 --- a/libmaple/include/libmaple/usb_cdcacm.h +++ b/libmaple/include/libmaple/usb_cdcacm.h @@ -72,6 +72,27 @@ extern "C" { #define USB_INTERFACE_SUBCLASS_CDC_ACM 0x02 #define USB_INTERFACE_CLASS_DIC 0x0A +/* + * Endpoint configuration + */ + +#define USB_CDCACM_CTRL_ENDP 0 +#define USB_CDCACM_CTRL_RX_ADDR 0x40 +#define USB_CDCACM_CTRL_TX_ADDR 0x80 +#define USB_CDCACM_CTRL_EPSIZE 0x40 + +#define USB_CDCACM_TX_ENDP 1 +#define USB_CDCACM_TX_ADDR 0xC0 +#define USB_CDCACM_TX_EPSIZE 0x40 + +#define USB_CDCACM_MANAGEMENT_ENDP 2 +#define USB_CDCACM_MANAGEMENT_ADDR 0x100 +#define USB_CDCACM_MANAGEMENT_EPSIZE 0x40 + +#define USB_CDCACM_RX_ENDP 3 +#define USB_CDCACM_RX_ADDR 0x110 +#define USB_CDCACM_RX_EPSIZE 0x40 + #ifndef __cplusplus #define USB_CDCACM_DECLARE_DEV_DESC(vid, pid) \ { \ @@ -106,6 +127,7 @@ uint32 usb_cdcacm_peek(uint8* buf, uint32 len); uint32 usb_cdcacm_data_available(void); /* in RX buffer */ uint16 usb_cdcacm_get_pending(void); +uint8 usb_cdcacm_is_transmitting(void); uint8 usb_cdcacm_get_dtr(void); uint8 usb_cdcacm_get_rts(void); diff --git a/libmaple/nvic.c b/libmaple/nvic.c index fe7c7bc..149e780 100644 --- a/libmaple/nvic.c +++ b/libmaple/nvic.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/libmaple/stm32f1/bkp.c b/libmaple/stm32f1/bkp.c index f435ff1..01ad419 100644 --- a/libmaple/stm32f1/bkp.c +++ b/libmaple/stm32f1/bkp.c @@ -62,14 +62,14 @@ void bkp_init(void) { * @see bkp_init() */ void bkp_enable_writes(void) { - *bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 1; + *bb_perip(&PWR_BASE->CR, PWR_CR_DBP_BIT) = 1; } /** * Disable write access to the backup registers. */ void bkp_disable_writes(void) { - *bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 0; + *bb_perip(&PWR_BASE->CR, PWR_CR_DBP_BIT) = 0; } /** diff --git a/libmaple/stm32f1/dma.c b/libmaple/stm32f1/dma.c index 5364a04..6400d15 100644 --- a/libmaple/stm32f1/dma.c +++ b/libmaple/stm32f1/dma.c @@ -145,6 +145,7 @@ static int config_to_per(dma_tube_reg_map *chregs, dma_tube_config *cfg) { cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC, cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC, (cfg_ccr_flags(cfg->tube_flags) | DMA_CCR_DIR_FROM_MEM)); + chregs->CNDTR = cfg->tube_nr_xfers; chregs->CMAR = (uint32)cfg->tube_src; chregs->CPAR = (uint32)cfg->tube_dst; return DMA_TUBE_CFG_SUCCESS; diff --git a/libmaple/stm32f1/include/series/dma.h b/libmaple/stm32f1/include/series/dma.h index 3b19e2b..bedb602 100644 --- a/libmaple/stm32f1/include/series/dma.h +++ b/libmaple/stm32f1/include/series/dma.h @@ -145,6 +145,16 @@ typedef struct dma_tube_reg_map { /* Interrupt status register */ +#define DMA_ISR_TEIF_BIT 3 +#define DMA_ISR_HTIF_BIT 2 +#define DMA_ISR_TCIF_BIT 1 +#define DMA_ISR_GIF_BIT 0 + +#define DMA_ISR_TEIF (1 << DMA_ISR_TEIF_BIT) +#define DMA_ISR_HTIF (1 << DMA_ISR_HTIF_BIT) +#define DMA_ISR_TCID (1 << DMA_ISR_TCIF_BIT) +#define DMA_ISR_GIF (1 << DMA_ISR_GIF_BIT) + #define DMA_ISR_TEIF7_BIT 27 #define DMA_ISR_HTIF7_BIT 26 #define DMA_ISR_TCIF7_BIT 25 diff --git a/libmaple/stm32f1/performance/isrs.S b/libmaple/stm32f1/performance/isrs.S index a8f0709..c638078 100644 --- a/libmaple/stm32f1/performance/isrs.S +++ b/libmaple/stm32f1/performance/isrs.S @@ -26,6 +26,8 @@ /* STM32F1 performance line ISR weak declarations */ +#include <libmaple/stm32.h> + .thumb /* Default handler for all non-overridden interrupts and exceptions */ diff --git a/libmaple/stm32f1/performance/vector_table.S b/libmaple/stm32f1/performance/vector_table.S index b489b94..8be3fa6 100644 --- a/libmaple/stm32f1/performance/vector_table.S +++ b/libmaple/stm32f1/performance/vector_table.S @@ -26,6 +26,8 @@ /* STM32F1 performance line vector table */ +#include <libmaple/stm32.h> + .section ".stm32.interrupt_vector" .globl __stm32_vector_table diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 3ca0813..f1cc23e 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -6,6 +6,7 @@ BUILDDIRS += $(BUILD_PATH)/$(d) # Local flags CFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror +ASFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Extra BUILDDIRS BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_F1_LINE) @@ -33,7 +34,7 @@ OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) DEPS_$(d) := $(OBJS_$(d):%.o=%.d) -$(OBJS_$(d)): TGT_ASFLAGS := +$(OBJS_$(d)): TGT_ASFLAGS := $(ASFLAGS_$(d)) $(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) TGT_BIN += $(OBJS_$(d)) diff --git a/libmaple/systick.c b/libmaple/systick.c index 80c0c47..7568abe 100644 --- a/libmaple/systick.c +++ b/libmaple/systick.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2010, 2011 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/libmaple/timer.c b/libmaple/timer.c index 24ae7fa..c22fe9d 100644 --- a/libmaple/timer.c +++ b/libmaple/timer.c @@ -38,7 +38,7 @@ static void disable_channel(timer_dev *dev, uint8 channel); static void pwm_mode(timer_dev *dev, uint8 channel); static void output_compare_mode(timer_dev *dev, uint8 channel); -static inline void enable_irq(timer_dev *dev, uint8 interrupt); +static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid); /* * Devices diff --git a/libmaple/usart.c b/libmaple/usart.c index 253cf9f..1d88234 100644 --- a/libmaple/usart.c +++ b/libmaple/usart.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/libmaple/usb/stm32f1/usb.c b/libmaple/usb/stm32f1/usb.c index c20cc71..f694f04 100644 --- a/libmaple/usb/stm32f1/usb.c +++ b/libmaple/usb/stm32f1/usb.c @@ -28,7 +28,7 @@ * @file libmaple/usb/stm32f1/usb.c * @brief USB support. * - * This is a mess. What we need almost amounts to a ground-up rewrite. + * This is a mess. */ #include <libmaple/usb.h> @@ -69,13 +69,14 @@ typedef enum { } RESUME_STATE; struct { - volatile RESUME_STATE eState; - volatile uint8 bESOFcnt; + volatile RESUME_STATE eState; + volatile uint8 bESOFcnt; } ResumeS; static usblib_dev usblib = { .irq_mask = USB_ISR_MSK, .state = USB_UNCONNECTED, + .prevState = USB_UNCONNECTED, .clk_id = RCC_USB, }; usblib_dev *USBLIB = &usblib; @@ -105,147 +106,151 @@ void usb_init_usblib(usblib_dev *dev, } static void usb_suspend(void) { - uint16 cntr; - - /* TODO decide if read/modify/write is really what we want - * (e.g. usb_resume_init() reconfigures CNTR). */ - cntr = USB_BASE->CNTR; - cntr |= USB_CNTR_FSUSP; - USB_BASE->CNTR = cntr; - cntr |= USB_CNTR_LP_MODE; - USB_BASE->CNTR = cntr; - - USBLIB->state = USB_SUSPENDED; + uint16 cntr; + + /* TODO decide if read/modify/write is really what we want + * (e.g. usb_resume_init() reconfigures CNTR). */ + cntr = USB_BASE->CNTR; + cntr |= USB_CNTR_FSUSP; + USB_BASE->CNTR = cntr; + cntr |= USB_CNTR_LP_MODE; + USB_BASE->CNTR = cntr; + + USBLIB->prevState = USBLIB->state; + USBLIB->state = USB_SUSPENDED; } static void usb_resume_init(void) { - uint16 cntr; + uint16 cntr; - cntr = USB_BASE->CNTR; - cntr &= ~USB_CNTR_LP_MODE; - USB_BASE->CNTR = cntr; + cntr = USB_BASE->CNTR; + cntr &= ~USB_CNTR_LP_MODE; + USB_BASE->CNTR = cntr; - /* Enable interrupt lines */ - USB_BASE->CNTR = USB_ISR_MSK; + /* Enable interrupt lines */ + USB_BASE->CNTR = USB_ISR_MSK; } static void usb_resume(RESUME_STATE eResumeSetVal) { - uint16 cntr; + uint16 cntr; - if (eResumeSetVal != RESUME_ESOF) - ResumeS.eState = eResumeSetVal; + if (eResumeSetVal != RESUME_ESOF) { + ResumeS.eState = eResumeSetVal; + } - switch (ResumeS.eState) - { + switch (ResumeS.eState) { case RESUME_EXTERNAL: - usb_resume_init(); - ResumeS.eState = RESUME_OFF; - break; + usb_resume_init(); + ResumeS.eState = RESUME_OFF; + USBLIB->state = USBLIB->prevState; + break; case RESUME_INTERNAL: - usb_resume_init(); - ResumeS.eState = RESUME_START; - break; + usb_resume_init(); + ResumeS.eState = RESUME_START; + break; case RESUME_LATER: - ResumeS.bESOFcnt = 2; - ResumeS.eState = RESUME_WAIT; - break; + ResumeS.bESOFcnt = 2; + ResumeS.eState = RESUME_WAIT; + break; case RESUME_WAIT: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) - ResumeS.eState = RESUME_START; - break; + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) { + ResumeS.eState = RESUME_START; + } + break; case RESUME_START: - cntr = USB_BASE->CNTR; - cntr |= USB_CNTR_RESUME; - USB_BASE->CNTR = cntr; - ResumeS.eState = RESUME_ON; - ResumeS.bESOFcnt = 10; - break; + cntr = USB_BASE->CNTR; + cntr |= USB_CNTR_RESUME; + USB_BASE->CNTR = cntr; + ResumeS.eState = RESUME_ON; + ResumeS.bESOFcnt = 10; + break; case RESUME_ON: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) { - cntr = USB_BASE->CNTR; - cntr &= ~USB_CNTR_RESUME; - USB_BASE->CNTR = cntr; - ResumeS.eState = RESUME_OFF; - } - break; + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) { + cntr = USB_BASE->CNTR; + cntr &= ~USB_CNTR_RESUME; + USB_BASE->CNTR = cntr; + USBLIB->state = USBLIB->prevState; + ResumeS.eState = RESUME_OFF; + } + break; case RESUME_OFF: case RESUME_ESOF: default: - ResumeS.eState = RESUME_OFF; - break; + ResumeS.eState = RESUME_OFF; + break; } } #define SUSPEND_ENABLED 1 void __irq_usb_lp_can_rx0(void) { - uint16 istr = USB_BASE->ISTR; + uint16 istr = USB_BASE->ISTR; - /* Use USB_ISR_MSK to only include code for bits we care about. */ + /* Use USB_ISR_MSK to only include code for bits we care about. */ #if (USB_ISR_MSK & USB_ISTR_RESET) - if (istr & USB_ISTR_RESET & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_RESET; - pProperty->Reset(); - } + if (istr & USB_ISTR_RESET & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_RESET; + pProperty->Reset(); + } #endif #if (USB_ISR_MSK & USB_ISTR_PMAOVR) - if (istr & ISTR_PMAOVR & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_PMAOVR; - } + if (istr & ISTR_PMAOVR & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_PMAOVR; + } #endif #if (USB_ISR_MSK & USB_ISTR_ERR) - if (istr & USB_ISTR_ERR & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_ERR; - } + if (istr & USB_ISTR_ERR & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_ERR; + } #endif #if (USB_ISR_MSK & USB_ISTR_WKUP) - if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_WKUP; - usb_resume(RESUME_EXTERNAL); - } + if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_WKUP; + usb_resume(RESUME_EXTERNAL); + } #endif #if (USB_ISR_MSK & USB_ISTR_SUSP) - if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) { - /* check if SUSPEND is possible */ - if (SUSPEND_ENABLED) { - usb_suspend(); - } else { - /* if not possible then resume after xx ms */ - usb_resume(RESUME_LATER); + if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) { + /* check if SUSPEND is possible */ + if (SUSPEND_ENABLED) { + usb_suspend(); + } else { + /* if not possible then resume after xx ms */ + usb_resume(RESUME_LATER); + } + /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ + USB_BASE->ISTR = ~USB_ISTR_SUSP; } - /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - USB_BASE->ISTR = ~USB_ISTR_SUSP; -} #endif #if (USB_ISR_MSK & USB_ISTR_SOF) - if (istr & USB_ISTR_SOF & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_SOF; - } + if (istr & USB_ISTR_SOF & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_SOF; + } #endif #if (USB_ISR_MSK & USB_ISTR_ESOF) - if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_ESOF; - /* resume handling timing is made with ESOFs */ - usb_resume(RESUME_ESOF); /* request without change of the machine state */ - } + if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_ESOF; + /* resume handling timing is made with ESOFs */ + usb_resume(RESUME_ESOF); /* request without change of the machine state */ + } #endif - /* - * Service the correct transfer interrupt. - */ + /* + * Service the correct transfer interrupt. + */ #if (USB_ISR_MSK & USB_ISTR_CTR) - if (istr & USB_ISTR_CTR & USBLIB->irq_mask) { - dispatch_ctr_lp(); - } + if (istr & USB_ISTR_CTR & USBLIB->irq_mask) { + dispatch_ctr_lp(); + } #endif } @@ -274,8 +279,9 @@ static void dispatch_ctr_lp() { * once we're done serving endpoint zero, but not okay if * there are multiple nonzero endpoint transfers to * handle. */ - if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) + if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) { return; + } } else { dispatch_endpt(ep_id); } diff --git a/libmaple/usb/stm32f1/usb_cdcacm.c b/libmaple/usb/stm32f1/usb_cdcacm.c index fc70e39..d4d4262 100644 --- a/libmaple/usb/stm32f1/usb_cdcacm.c +++ b/libmaple/usb/stm32f1/usb_cdcacm.c @@ -82,27 +82,6 @@ static void usbSetConfiguration(void); static void usbSetDeviceAddress(void); /* - * Endpoint configuration - */ - -#define USB_CDCACM_CTRL_ENDP 0 -#define USB_CDCACM_CTRL_RX_ADDR 0x40 -#define USB_CDCACM_CTRL_TX_ADDR 0x80 -#define USB_CDCACM_CTRL_EPSIZE 0x40 - -#define USB_CDCACM_TX_ENDP 1 -#define USB_CDCACM_TX_ADDR 0xC0 -#define USB_CDCACM_TX_EPSIZE 0x40 - -#define USB_CDCACM_MANAGEMENT_ENDP 2 -#define USB_CDCACM_MANAGEMENT_ADDR 0x100 -#define USB_CDCACM_MANAGEMENT_EPSIZE 0x40 - -#define USB_CDCACM_RX_ENDP 3 -#define USB_CDCACM_RX_ADDR 0x110 -#define USB_CDCACM_RX_EPSIZE 0x40 - -/* * Descriptors */ @@ -288,6 +267,8 @@ static volatile uint8 vcomBufferRx[USB_CDCACM_RX_EPSIZE]; static volatile uint32 rx_offset = 0; /* Number of bytes left to transmit */ static volatile uint32 n_unsent_bytes = 0; +/* Are we currently sending an IN packet? */ +static volatile uint8 transmitting = 0; /* Number of unread bytes */ static volatile uint32 n_unread_bytes = 0; @@ -328,16 +309,19 @@ static void (*ep_int_out[7])(void) = /* * Globals required by usb_lib/ + * + * Mark these weak so they can be overriden to implement other USB + * functionality. */ #define NUM_ENDPTS 0x04 -DEVICE Device_Table = { +__weak DEVICE Device_Table = { .Total_Endpoint = NUM_ENDPTS, .Total_Configuration = 1 }; #define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ -DEVICE_PROP Device_Property = { +__weak DEVICE_PROP Device_Property = { .Init = usbInit, .Reset = usbReset, .Process_Status_IN = NOP_Process, @@ -352,7 +336,7 @@ DEVICE_PROP Device_Property = { .MaxPacketSize = MAX_PACKET_SIZE }; -USER_STANDARD_REQUESTS User_Standard_Requests = { +__weak USER_STANDARD_REQUESTS User_Standard_Requests = { .User_GetConfiguration = NOP_Process, .User_SetConfiguration = usbSetConfiguration, .User_GetInterface = NOP_Process, @@ -413,7 +397,7 @@ void usb_cdcacm_putc(char ch) { * buffer, and returns the number of bytes copied. */ uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) { /* Last transmission hasn't finished, so abort. */ - if (n_unsent_bytes) { + if (usb_cdcacm_is_transmitting()) { return 0; } @@ -425,10 +409,14 @@ uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) { /* Queue bytes for sending. */ if (len) { usb_copy_to_pma(buf, len, USB_CDCACM_TX_ADDR); - usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, len); - n_unsent_bytes = len; - usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID); } + // We still need to wait for the interrupt, even if we're sending + // zero bytes. (Sending zero-size packets is useful for flushing + // host-side buffers.) + usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, len); + n_unsent_bytes = len; + transmitting = 1; + usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID); return len; } @@ -437,7 +425,11 @@ uint32 usb_cdcacm_data_available(void) { return n_unread_bytes; } -uint16 usb_cdcacm_get_pending() { +uint8 usb_cdcacm_is_transmitting(void) { + return transmitting; +} + +uint16 usb_cdcacm_get_pending(void) { return n_unsent_bytes; } @@ -518,12 +510,8 @@ int usb_cdcacm_get_n_data_bits(void) { */ static void vcomDataTxCb(void) { - /* The following assumes that all of the bytes we copied during - * the last call to usb_cdcacm_tx were sent during the IN - * transaction (this seems to be the case). */ - /* TODO find out why this is broken: - * n_unsent_bytes = usb_get_ep_tx_count(USB_CDCACM_TX_ENDP); */ n_unsent_bytes = 0; + transmitting = 0; } static void vcomDataRxCb(void) { @@ -535,6 +523,13 @@ static void vcomDataRxCb(void) { usb_copy_from_pma((uint8*)vcomBufferRx, n_unread_bytes, USB_CDCACM_RX_ADDR); + + if (n_unread_bytes == 0) { + usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + rx_offset = 0; + } + if (rx_hook) { rx_hook(USB_CDCACM_HOOK_RX, 0); } @@ -614,6 +609,7 @@ static void usbReset(void) { n_unread_bytes = 0; n_unsent_bytes = 0; rx_offset = 0; + transmitting = 0; } static RESULT usbDataSetup(uint8 request) { diff --git a/libmaple/usb/stm32f1/usb_reg_map.c b/libmaple/usb/stm32f1/usb_reg_map.c index 75562e1..ea60cb3 100644 --- a/libmaple/usb/stm32f1/usb_reg_map.c +++ b/libmaple/usb/stm32f1/usb_reg_map.c @@ -58,8 +58,7 @@ void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) { } } -void usb_set_ep_rx_count(uint8 ep, uint16 count) { - uint32 *rxc = usb_ep_rx_count_ptr(ep); +static void usb_set_ep_rx_count_common(uint32 *rxc, uint16 count) { uint16 nblocks; if (count > 62) { /* use 32-byte memory block size */ @@ -77,3 +76,13 @@ void usb_set_ep_rx_count(uint8 ep, uint16 count) { *rxc = nblocks << 10; } } + +void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count) { + uint32 *rxc = usb_ep_rx_buf0_count_ptr(ep); + usb_set_ep_rx_count_common(rxc, count); +} + +void usb_set_ep_rx_count(uint8 ep, uint16 count) { + uint32 *rxc = usb_ep_rx_count_ptr(ep); + usb_set_ep_rx_count_common(rxc, count); +} diff --git a/libmaple/usb/stm32f1/usb_reg_map.h b/libmaple/usb/stm32f1/usb_reg_map.h index ea483d2..2e3f6bc 100644 --- a/libmaple/usb/stm32f1/usb_reg_map.h +++ b/libmaple/usb/stm32f1/usb_reg_map.h @@ -88,6 +88,7 @@ typedef struct usb_reg_map { #define USB_EP_EP_TYPE_ISO (0x2 << 9) #define USB_EP_EP_TYPE_INTERRUPT (0x3 << 9) #define USB_EP_EP_KIND BIT(USB_EP_EP_KIND_BIT) +#define USB_EP_EP_KIND_DBL_BUF (0x1 << USB_EP_EP_KIND_BIT) #define USB_EP_CTR_TX BIT(USB_EP_CTR_TX_BIT) #define USB_EP_DTOG_TX BIT(USB_EP_DTOG_TX_BIT) #define USB_EP_STAT_TX (0x3 << 4) @@ -205,6 +206,86 @@ static inline void usb_clear_ctr_tx(uint8 ep) { USB_BASE->EP[ep] = epr & ~USB_EP_CTR_TX & __EP_NONTOGGLE; } +static inline uint32 usb_get_ep_dtog_tx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_DTOG_TX; +} + +static inline uint32 usb_get_ep_dtog_rx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_DTOG_RX; +} + +static inline uint32 usb_get_ep_tx_sw_buf(uint8 ep) { + return usb_get_ep_dtog_rx(ep); +} + +static inline uint32 usb_get_ep_rx_sw_buf(uint8 ep) { + return usb_get_ep_dtog_tx(ep); +} + +static inline void usb_toggle_ep_dtog_tx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + epr &= __EP_NONTOGGLE; + epr |= USB_EP_DTOG_TX; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_toggle_ep_dtog_rx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + epr &= __EP_NONTOGGLE; + epr |= USB_EP_DTOG_RX; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_clear_ep_dtog_tx(uint8 ep) { + if (usb_get_ep_dtog_tx(ep) != 0) { + usb_toggle_ep_dtog_tx(ep); + } +} + +static inline void usb_clear_ep_dtog_rx(uint8 ep) { + if (usb_get_ep_dtog_rx(ep) != 0) { + usb_toggle_ep_dtog_rx(ep); + } +} + +static inline void usb_set_ep_dtog_tx(uint8 ep) { + if (usb_get_ep_dtog_tx(ep) == 0) { + usb_toggle_ep_dtog_tx(ep); + } +} + +static inline void usb_set_ep_dtog_rx(uint8 ep) { + if (usb_get_ep_dtog_rx(ep) == 0) { + usb_toggle_ep_dtog_rx(ep); + } +} + +static inline void usb_toggle_ep_rx_sw_buf(uint8 ep) { + usb_toggle_ep_dtog_tx(ep); +} + +static inline void usb_toggle_ep_tx_sw_buf(uint8 ep) { + usb_toggle_ep_dtog_rx(ep); +} + +static inline void usb_clear_ep_rx_sw_buf(uint8 ep) { + usb_clear_ep_dtog_tx(ep); +} + +static inline void usb_clear_ep_tx_sw_buf(uint8 ep) { + usb_clear_ep_dtog_rx(ep); +} + +static inline void usb_set_ep_rx_sw_buf(uint8 ep) { + usb_set_ep_dtog_tx(ep); +} + +static inline void usb_set_ep_tx_sw_buf(uint8 ep) { + usb_set_ep_dtog_rx(ep); +} + static inline void usb_set_ep_rx_stat(uint8 ep, uint32 status) { uint32 epr = USB_BASE->EP[ep]; epr &= ~(USB_EP_STAT_TX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); @@ -235,6 +316,17 @@ static inline void usb_set_ep_kind(uint8 ep, uint32 kind) { USB_BASE->EP[ep] = epr; } +static inline uint32 usb_get_ep_type(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_EP_TYPE; +} + +static inline uint32 usb_get_ep_kind(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_EP_TYPE; +} + + static inline void usb_clear_status_out(uint8 ep) { usb_set_ep_kind(ep, 0); } @@ -275,42 +367,42 @@ union usb_btable_ent; /* Bidirectional endpoint BTABLE entry */ typedef struct usb_btable_bidi { - __io uint16 addr_tx; const uint16 PAD1; - __io uint16 count_tx; const uint16 PAD2; - __io uint16 addr_rx; const uint16 PAD3; - __io uint16 count_rx; const uint16 PAD4; + __io uint16 addr_tx; const uint16 PAD1; + __io uint16 count_tx; const uint16 PAD2; + __io uint16 addr_rx; const uint16 PAD3; + __io uint16 count_rx; const uint16 PAD4; } usb_btable_bidi; /* Unidirectional receive-only endpoint BTABLE entry */ typedef struct usb_btable_uni_rx { - __io uint16 empty1; const uint16 PAD1; - __io uint16 empty2; const uint16 PAD2; - __io uint16 addr_rx; const uint16 PAD3; - __io uint16 count_rx; const uint16 PAD4; + __io uint16 empty1; const uint16 PAD1; + __io uint16 empty2; const uint16 PAD2; + __io uint16 addr_rx; const uint16 PAD3; + __io uint16 count_rx; const uint16 PAD4; } usb_btable_uni_rx; /* Unidirectional transmit-only endpoint BTABLE entry */ typedef struct usb_btable_uni_tx { - __io uint16 addr_tx; const uint16 PAD1; - __io uint16 count_tx; const uint16 PAD2; - __io uint16 empty1; const uint16 PAD3; - __io uint16 empty2; const uint16 PAD4; + __io uint16 addr_tx; const uint16 PAD1; + __io uint16 count_tx; const uint16 PAD2; + __io uint16 empty1; const uint16 PAD3; + __io uint16 empty2; const uint16 PAD4; } usb_btable_uni_tx; /* Double-buffered transmission endpoint BTABLE entry */ typedef struct usb_btable_dbl_tx { - __io uint16 addr_tx0; const uint16 PAD1; - __io uint16 count_tx0; const uint16 PAD2; - __io uint16 addr_tx1; const uint16 PAD3; - __io uint16 count_tx1; const uint16 PAD4; + __io uint16 addr_tx0; const uint16 PAD1; + __io uint16 count_tx0; const uint16 PAD2; + __io uint16 addr_tx1; const uint16 PAD3; + __io uint16 count_tx1; const uint16 PAD4; } usb_btable_dbl_tx; /* Double-buffered reception endpoint BTABLE entry */ typedef struct usb_btable_dbl_rx { - __io uint16 addr_rx0; const uint16 PAD1; - __io uint16 count_rx0; const uint16 PAD2; - __io uint16 addr_rx1; const uint16 PAD3; - __io uint16 count_rx1; const uint16 PAD4; + __io uint16 addr_rx0; const uint16 PAD1; + __io uint16 count_rx0; const uint16 PAD2; + __io uint16 addr_rx1; const uint16 PAD3; + __io uint16 count_rx1; const uint16 PAD4; } usb_btable_dbl_rx; /* TODO isochronous endpoint entries */ @@ -336,10 +428,6 @@ static inline uint32* usb_btable_ptr(uint32 offset) { return (uint32*)usb_pma_ptr(USB_BASE->BTABLE + offset); } -static inline usb_btable_ent *usb_btable(void) { - return (usb_btable_ent*)usb_btable_ptr(0); -} - /* TX address */ static inline uint32* usb_ep_tx_addr_ptr(uint8 ep) { @@ -399,6 +487,100 @@ static inline uint16 usb_get_ep_rx_count(uint8 ep) { void usb_set_ep_rx_count(uint8 ep, uint16 count); +/* double buffer definitions */ +static inline uint32* usb_get_ep_tx_buf0_addr_ptr(uint8 ep) { + return usb_ep_tx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf0_addr(uint8 ep) { + return usb_get_ep_tx_addr(ep); +} + +static inline void usb_set_ep_tx_buf0_addr(uint8 ep, uint16 addr) { + usb_set_ep_tx_addr(ep, addr); +} + +static inline uint32* usb_get_ep_tx_buf1_addr_ptr(uint8 ep) { + return usb_ep_rx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf1_addr(uint8 ep) { + return usb_get_ep_rx_addr(ep); +} + +static inline void usb_set_ep_tx_buf1_addr(uint8 ep, uint16 addr) { + usb_set_ep_rx_addr(ep, addr); +} + +static inline uint32* usb_ep_tx_buf0_count_ptr(uint8 ep) { + return usb_ep_tx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf0_count(uint8 ep) { + return usb_get_ep_tx_count(ep); +} + +static inline void usb_set_ep_tx_buf0_count(uint8 ep, uint16 count) { + usb_set_ep_tx_count(ep, count); +} + +static inline uint32* usb_ep_tx_buf1_count_ptr(uint8 ep) { + return usb_ep_rx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf1_count(uint8 ep) { + return usb_get_ep_rx_count(ep); +} + +static inline void usb_set_ep_tx_buf1_count(uint8 ep, uint16 count) { + usb_set_ep_rx_count(ep, count); +} +static inline uint32* usb_get_ep_rx_buf0_addr_ptr(uint8 ep) { + return usb_ep_tx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf0_addr(uint8 ep) { + return usb_get_ep_tx_addr(ep); +} + +static inline void usb_set_ep_rx_buf0_addr(uint8 ep, uint16 addr) { + usb_set_ep_tx_addr(ep, addr); +} + +static inline uint32* usb_get_ep_rx_buf1_addr_ptr(uint8 ep) { + return usb_ep_rx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf1_addr(uint8 ep) { + return usb_get_ep_rx_addr(ep); +} + +static inline void usb_set_ep_rx_buf1_addr(uint8 ep, uint16 addr) { + usb_set_ep_rx_addr(ep, addr); +} + +static inline uint32* usb_ep_rx_buf0_count_ptr(uint8 ep) { + return usb_ep_tx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf0_count(uint8 ep) { + return usb_get_ep_tx_count(ep); +} + +void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count); + +static inline uint32* usb_ep_rx_buf1_count_ptr(uint8 ep) { + return usb_ep_rx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf1_count(uint8 ep) { + return usb_get_ep_rx_count(ep); +} + +static inline void usb_set_ep_rx_buf1_count(uint8 ep, uint16 count) { + usb_set_ep_rx_count(ep, count); +} + /* * Misc. types */ diff --git a/libmaple/util.c b/libmaple/util.c index 2ee5ede..4c0b2c8 100644 --- a/libmaple/util.c +++ b/libmaple/util.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation |