diff options
-rw-r--r-- | stmhal/Makefile | 2 | ||||
-rw-r--r-- | stmhal/led.c | 5 | ||||
-rw-r--r-- | stmhal/main.c | 15 | ||||
-rw-r--r-- | stmhal/servo.c | 50 | ||||
-rw-r--r-- | stmhal/servo.h | 2 | ||||
-rw-r--r-- | stmhal/stm32f4xx_hal_msp.c | 31 | ||||
-rw-r--r-- | stmhal/stm32f4xx_it.c | 12 | ||||
-rw-r--r-- | stmhal/timer.c | 189 | ||||
-rw-r--r-- | stmhal/timer.h | 10 | ||||
-rw-r--r-- | stmhal/usbd_cdc_interface.h | 4 |
10 files changed, 233 insertions, 87 deletions
diff --git a/stmhal/Makefile b/stmhal/Makefile index 0f3fe46cfa..fff966934a 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -61,6 +61,7 @@ SRC_C = \ usbd_msc_storage.c \ pendsv.c \ systick.c \ + timer.c \ led.c \ pin.c \ pin_map.c \ @@ -98,7 +99,6 @@ SRC_C = \ adc.c \ i2c.c \ -# timer.c \ # pybwlan.c \ SRC_S = \ diff --git a/stmhal/led.c b/stmhal/led.c index b7afdd40c5..3108ee7792 100644 --- a/stmhal/led.c +++ b/stmhal/led.c @@ -1,7 +1,5 @@ #include <stdio.h> #include <stm32f4xx_hal.h> -#include "usbd_cdc_msc_hid.h" -#include "usbd_cdc_interface.h" #include "nlr.h" #include "misc.h" @@ -9,6 +7,7 @@ #include "qstr.h" #include "obj.h" #include "runtime.h" +#include "timer.h" #include "led.h" #include "pin.h" #include "build/pins.h" @@ -54,6 +53,8 @@ void led_init(void) { // LED4 (blue) is on PB4 which is TIM3_CH1 // we use PWM on this channel to fade the LED + // LED3 (yellow) is on PA15 which has TIM2_CH1, so we could PWM that as well + // GPIO configuration GPIO_InitStructure.Pin = MICROPY_HW_LED4.pin_mask; GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; diff --git a/stmhal/main.c b/stmhal/main.c index d6d9b9ed7e..afef84e290 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -22,6 +22,7 @@ #include "readline.h" #include "pyexec.h" #include "usart.h" +#include "timer.h" #include "led.h" #include "exti.h" #include "usrsw.h" @@ -38,7 +39,6 @@ #include "dac.h" #include "pin.h" #if 0 -#include "timer.h" #include "pybwlan.h" #endif @@ -177,6 +177,7 @@ int main(void) { // basic sub-system init pendsv_init(); + timer_tim3_init(); led_init(); switch_init0(); @@ -409,6 +410,11 @@ soft_reset: rng_init(); #endif +#if MICROPY_HW_ENABLE_TIMER + // timer + //timer_init(); +#endif + // I2C i2c_init(); @@ -422,13 +428,6 @@ soft_reset: servo_init(); #endif -#if 0 -#if MICROPY_HW_ENABLE_TIMER - // timer - timer_init(); -#endif -#endif - #if MICROPY_HW_ENABLE_DAC // DAC dac_init(); diff --git a/stmhal/servo.c b/stmhal/servo.c index 15ba35165c..9c757c5659 100644 --- a/stmhal/servo.c +++ b/stmhal/servo.c @@ -8,12 +8,13 @@ #include "qstr.h" #include "obj.h" #include "runtime.h" +#include "timer.h" #include "servo.h" // this servo driver uses hardware PWM to drive servos on PA0, PA1, PA2, PA3 = X1, X2, X3, X4 // TIM2 and TIM5 have CH1, CH2, CH3, CH4 on PA0-PA3 respectively // they are both 32-bit counters with 16-bit prescaler -// we use TIM2 +// we use TIM5 #define PYB_SERVO_NUM (4) @@ -30,23 +31,8 @@ STATIC const mp_obj_type_t servo_obj_type; STATIC pyb_servo_obj_t pyb_servo_obj[PYB_SERVO_NUM]; -TIM_HandleTypeDef TIM2_Handle; - void servo_init(void) { - // TIM2 clock enable - __TIM2_CLK_ENABLE(); - - // set up and enable interrupt - HAL_NVIC_SetPriority(TIM2_IRQn, 6, 0); - HAL_NVIC_EnableIRQ(TIM2_IRQn); - - // PWM clock configuration - TIM2_Handle.Instance = TIM2; - TIM2_Handle.Init.Period = 2000; // timer cycles at 50Hz - TIM2_Handle.Init.Prescaler = ((SystemCoreClock / 2) / 100000) - 1; // timer runs at 100kHz - TIM2_Handle.Init.ClockDivision = 0; - TIM2_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; - HAL_TIM_PWM_Init(&TIM2_Handle); + timer_tim5_init(); // reset servo objects for (int i = 0; i < PYB_SERVO_NUM; i++) { @@ -74,17 +60,17 @@ void servo_timer_irq_callback(void) { need_it = true; } switch (s->servo_id) { - case 1: TIM2->CCR1 = s->pulse_cur; break; - case 2: TIM2->CCR2 = s->pulse_cur; break; - case 3: TIM2->CCR3 = s->pulse_cur; break; - case 4: TIM2->CCR4 = s->pulse_cur; break; + case 1: TIM5->CCR1 = s->pulse_cur; break; + case 2: TIM5->CCR2 = s->pulse_cur; break; + case 3: TIM5->CCR3 = s->pulse_cur; break; + case 4: TIM5->CCR4 = s->pulse_cur; break; } } } if (need_it) { - __HAL_TIM_ENABLE_IT(&TIM2_Handle, TIM_IT_UPDATE); + __HAL_TIM_ENABLE_IT(&TIM5_Handle, TIM_IT_UPDATE); } else { - __HAL_TIM_DISABLE_IT(&TIM2_Handle, TIM_IT_UPDATE); + __HAL_TIM_DISABLE_IT(&TIM5_Handle, TIM_IT_UPDATE); } } @@ -105,7 +91,7 @@ STATIC void servo_init_channel(pyb_servo_obj_t *s) { GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF1_TIM2; + GPIO_InitStructure.Alternate = GPIO_AF2_TIM5; HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); // PWM mode configuration @@ -114,10 +100,10 @@ STATIC void servo_init_channel(pyb_servo_obj_t *s) { oc_init.Pulse = s->pulse_cur; // units of 10us oc_init.OCPolarity = TIM_OCPOLARITY_HIGH; oc_init.OCFastMode = TIM_OCFAST_DISABLE; - HAL_TIM_PWM_ConfigChannel(&TIM2_Handle, &oc_init, channel); + HAL_TIM_PWM_ConfigChannel(&TIM5_Handle, &oc_init, channel); // start PWM - HAL_TIM_PWM_Start(&TIM2_Handle, channel); + HAL_TIM_PWM_Start(&TIM5_Handle, channel); } /******************************************************************************/ @@ -129,10 +115,10 @@ STATIC mp_obj_t pyb_servo_set(mp_obj_t port, mp_obj_t value) { if (v < 50) { v = 50; } if (v > 250) { v = 250; } switch (p) { - case 1: TIM2->CCR1 = v; break; - case 2: TIM2->CCR2 = v; break; - case 3: TIM2->CCR3 = v; break; - case 4: TIM2->CCR4 = v; break; + case 1: TIM5->CCR1 = v; break; + case 2: TIM5->CCR2 = v; break; + case 3: TIM5->CCR3 = v; break; + case 4: TIM5->CCR4 = v; break; } return mp_const_none; } @@ -142,8 +128,8 @@ MP_DEFINE_CONST_FUN_OBJ_2(pyb_servo_set_obj, pyb_servo_set); STATIC mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse) { int pe = mp_obj_get_int(period); int pu = mp_obj_get_int(pulse); - TIM2->ARR = pe; - TIM2->CCR3 = pu; + TIM5->ARR = pe; + TIM5->CCR3 = pu; return mp_const_none; } diff --git a/stmhal/servo.h b/stmhal/servo.h index d5fb6a8505..865b0fc9f5 100644 --- a/stmhal/servo.h +++ b/stmhal/servo.h @@ -1,5 +1,3 @@ -extern TIM_HandleTypeDef TIM2_Handle; - void servo_init(void); void servo_timer_irq_callback(void); diff --git a/stmhal/stm32f4xx_hal_msp.c b/stmhal/stm32f4xx_hal_msp.c index 1cf78336f8..7004912e14 100644 --- a/stmhal/stm32f4xx_hal_msp.c +++ b/stmhal/stm32f4xx_hal_msp.c @@ -38,8 +38,6 @@ /* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
-#include "usbd_cdc_msc_hid.h"
-#include "usbd_cdc_interface.h"
#include "misc.h"
#include "mpconfig.h"
@@ -47,30 +45,12 @@ #include "obj.h"
#include "servo.h"
-TIM_HandleTypeDef TIM3_Handle;
-
/**
* @brief Initializes the Global MSP.
* @param None
* @retval None
*/
void HAL_MspInit(void) {
- // set up the timer for USBD CDC
- __TIM3_CLK_ENABLE();
-
- TIM3_Handle.Instance = TIM3;
- TIM3_Handle.Init.Period = (USBD_CDC_POLLING_INTERVAL*1000) - 1;
- TIM3_Handle.Init.Prescaler = 84-1;
- TIM3_Handle.Init.ClockDivision = 0;
- TIM3_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
- HAL_TIM_Base_Init(&TIM3_Handle);
-
- HAL_NVIC_SetPriority(TIM3_IRQn, 6, 0);
- HAL_NVIC_EnableIRQ(TIM3_IRQn);
-
- if (HAL_TIM_Base_Start(&TIM3_Handle) != HAL_OK) {
- /* Starting Error */
- }
}
/**
@@ -79,9 +59,6 @@ void HAL_MspInit(void) { * @retval None
*/
void HAL_MspDeInit(void) {
- // reset TIM3 timer
- __TIM3_FORCE_RESET();
- __TIM3_RELEASE_RESET();
}
/**
@@ -146,14 +123,6 @@ void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc) __HAL_RCC_RTC_DISABLE();
}
-void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
- if (htim == &TIM3_Handle) {
- USBD_CDC_HAL_TIM_PeriodElapsedCallback();
- } else if (htim == &TIM2_Handle) {
- servo_timer_irq_callback();
- }
-}
-
/**
* @}
*/
diff --git a/stmhal/stm32f4xx_it.c b/stmhal/stm32f4xx_it.c index e74b1c6c75..aee689d7e2 100644 --- a/stmhal/stm32f4xx_it.c +++ b/stmhal/stm32f4xx_it.c @@ -42,15 +42,13 @@ #include "stm32f4xx_it.h"
#include "stm32f4xx_hal.h"
-#include "usbd_cdc_msc_hid.h"
-#include "usbd_cdc_interface.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "exti.h"
-#include "servo.h"
+#include "timer.h"
/** @addtogroup STM32F4xx_HAL_Examples
* @{
@@ -351,12 +349,12 @@ void RTC_WKUP_IRQHandler(void) { Handle_EXTI_Irq(EXTI_RTC_WAKEUP);
}
-void TIM2_IRQHandler(void) {
- HAL_TIM_IRQHandler(&TIM2_Handle);
-}
-
void TIM3_IRQHandler(void) {
HAL_TIM_IRQHandler(&TIM3_Handle);
}
+void TIM5_IRQHandler(void) {
+ HAL_TIM_IRQHandler(&TIM5_Handle);
+}
+
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/timer.c b/stmhal/timer.c new file mode 100644 index 0000000000..cfdb93587f --- /dev/null +++ b/stmhal/timer.c @@ -0,0 +1,189 @@ +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include <stm32f4xx_hal.h> +#include "usbd_cdc_msc_hid.h" +#include "usbd_cdc_interface.h" + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" +#include "timer.h" +#include "servo.h" + +// The timers can be used by multiple drivers, and need a common point for +// the interrupts to be dispatched, so they are all collected here. +// +// TIM3: +// - USB CDC interface, interval, to check for new data +// - LED 4, PWM to set the LED intensity +// +// TIM5: +// - servo controller, PWM + +TIM_HandleTypeDef TIM3_Handle; +TIM_HandleTypeDef TIM5_Handle; + +// TIM3 is set-up for the USB CDC interface +void timer_tim3_init(void) { + // set up the timer for USBD CDC + __TIM3_CLK_ENABLE(); + + TIM3_Handle.Instance = TIM3; + TIM3_Handle.Init.Period = (USBD_CDC_POLLING_INTERVAL*1000) - 1; + TIM3_Handle.Init.Prescaler = 84-1; + TIM3_Handle.Init.ClockDivision = 0; + TIM3_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; + HAL_TIM_Base_Init(&TIM3_Handle); + + HAL_NVIC_SetPriority(TIM3_IRQn, 6, 0); + HAL_NVIC_EnableIRQ(TIM3_IRQn); + + if (HAL_TIM_Base_Start(&TIM3_Handle) != HAL_OK) { + /* Starting Error */ + } +} + +/* unused +void timer_tim3_deinit(void) { + // reset TIM3 timer + __TIM3_FORCE_RESET(); + __TIM3_RELEASE_RESET(); +} +*/ + +// TIM5 is set-up for the servo controller +void timer_tim5_init(void) { + // TIM5 clock enable + __TIM5_CLK_ENABLE(); + + // set up and enable interrupt + HAL_NVIC_SetPriority(TIM5_IRQn, 6, 0); + HAL_NVIC_EnableIRQ(TIM5_IRQn); + + // PWM clock configuration + TIM5_Handle.Instance = TIM5; + TIM5_Handle.Init.Period = 2000; // timer cycles at 50Hz + TIM5_Handle.Init.Prescaler = ((SystemCoreClock / 2) / 100000) - 1; // timer runs at 100kHz + TIM5_Handle.Init.ClockDivision = 0; + TIM5_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; + HAL_TIM_PWM_Init(&TIM5_Handle); +} + +// Interrupt dispatch +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { + if (htim == &TIM3_Handle) { + USBD_CDC_HAL_TIM_PeriodElapsedCallback(); + } else if (htim == &TIM5_Handle) { + servo_timer_irq_callback(); + } +} + +// below is old code from stm/ which has not yet been fully ported to stmhal/ +#if 0 +typedef struct _pyb_hal_tim_t { + mp_obj_base_t base; + TIM_HandleTypeDef htim; +} pyb_hal_tim_t; + +pyb_hal_tim_t pyb_hal_tim_6; + + pyb_hal_tim_6 = { + .base = {&pyb_type_hal_tim}; + .htim = {TIM6 + +// TIM6 is used as an internal interrup to schedule something at a specific rate +mp_obj_t timer_py_callback; + +mp_obj_t timer_py_set_callback(mp_obj_t f) { + timer_py_callback = f; + return mp_const_none; +} + +mp_obj_t timer_py_set_period(mp_obj_t period) { + TIM6->ARR = mp_obj_get_int(period) & 0xffff; + return mp_const_none; +} + +mp_obj_t timer_py_set_prescaler(mp_obj_t prescaler) { + TIM6->PSC = mp_obj_get_int(prescaler) & 0xffff; + return mp_const_none; +} + +mp_obj_t timer_py_get_value(void) { + return mp_obj_new_int(TIM6->CNT & 0xfffff); +} + +void timer_init(void) { + timer_py_callback = mp_const_none; + + // TIM6 clock enable + __TIM6_CLK_ENABLE(); + + // Compute the prescaler value so TIM6 runs at 20kHz + uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 20000) - 1; + + // Time base configuration + tim_handle.Instance = TIM6; + tim_handle.Init.Prescaler = PrescalerValue; + tim_handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6 + tim_handle.Init.Period = 20000; // timer cycles at 1Hz + tim_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // unused for TIM6 + tim_handle.Init.RepetitionCounter = 0; // unused for TIM6 + HAL_TIM_Base_Init(&tim_handle); + + // enable perhipheral preload register + //TIM_ARRPreloadConfig(TIM6, ENABLE); ?? + + // set up interrupt + HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0xf, 0xf); // lowest priority + HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); + + // start timer, so that it interrupts on overflow + HAL_TIM_Base_Start_IT(&tim_handle); + + // Python interface + mp_obj_t m = mp_obj_new_module(QSTR_FROM_STR_STATIC("timer")); + rt_store_attr(m, QSTR_FROM_STR_STATIC("callback"), rt_make_function_n(1, timer_py_set_callback)); + rt_store_attr(m, QSTR_FROM_STR_STATIC("period"), rt_make_function_n(1, timer_py_set_period)); + rt_store_attr(m, QSTR_FROM_STR_STATIC("prescaler"), rt_make_function_n(1, timer_py_set_prescaler)); + rt_store_attr(m, QSTR_FROM_STR_STATIC("value"), rt_make_function_n(0, timer_py_get_value)); + rt_store_name(QSTR_FROM_STR_STATIC("timer"), m); +} + +void timer_interrupt(void) { + if (timer_py_callback != mp_const_none) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + // XXX what to do if the GC is in the middle of running?? + rt_call_function_0(timer_py_callback); + nlr_pop(); + } else { + // uncaught exception + printf("exception in timer interrupt\n"); + mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR); + printf("\n"); + } + } +} + +mp_obj_t pyb_Timer(mp_obj_t timx_in) { + TIM_TypeDef *TIMx = (TIM_TypeDef*)mp_obj_get_int(timx_in); + if (!IS_TIM_INSTANCE(TIMx)) { + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "argument 1 is not a TIM instance")); + } + pyb_hal_tim_t *tim = m_new_obj(pyb_hal_tim_t); + tim->htim.Instance = TIMx; + tim->htim.Instance.Init.Prescaler = x; + tim->htim.Instance.Init.CounterMode = y; + tim->htim.Instance.Init.Period = y; + tim->htim.Instance.Init.ClockDivision = y; + tim->htim.Instance.Init.RepetitionCounter = y; + HAL_TIM_Base_Init(&tim->htim); + return tim; +} +#endif diff --git a/stmhal/timer.h b/stmhal/timer.h new file mode 100644 index 0000000000..317b39b3f7 --- /dev/null +++ b/stmhal/timer.h @@ -0,0 +1,10 @@ +// Periodically, the state of the buffer "UserTxBuffer" is checked. +// The period depends on USBD_CDC_POLLING_INTERVAL +// The value is in ms. The max is 65 and the min is 1. +#define USBD_CDC_POLLING_INTERVAL (10) + +extern TIM_HandleTypeDef TIM3_Handle; +extern TIM_HandleTypeDef TIM5_Handle; + +void timer_tim3_init(void); +void timer_tim5_init(void); diff --git a/stmhal/usbd_cdc_interface.h b/stmhal/usbd_cdc_interface.h index 5ed5ecef46..88ea7e5afc 100644 --- a/stmhal/usbd_cdc_interface.h +++ b/stmhal/usbd_cdc_interface.h @@ -33,10 +33,6 @@ /* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
-/* Periodically, the state of the buffer "UserTxBuffer" is checked.
- The period depends on USBD_CDC_POLLING_INTERVAL */
-#define USBD_CDC_POLLING_INTERVAL 10 /* in ms. The max is 65 and the min is 1 */
-
extern TIM_HandleTypeDef TIM3_Handle;
extern const USBD_CDC_ItfTypeDef USBD_CDC_fops;
|