Browse Source

Add to STM code timer functionality to call Python on interrupt.

pull/3/head
Damien 11 years ago
parent
commit
bd8e110207
  1. 1
      stm/Makefile
  2. 4
      stm/audio.c
  3. 12
      stm/main.c
  4. 15
      stm/stm32fxxx_it.c
  5. 90
      stm/timer.c
  6. 1
      stm/timer.h

1
stm/Makefile

@ -26,6 +26,7 @@ SRC_C = \
usart.c \ usart.c \
usb.c \ usb.c \
sdio.c \ sdio.c \
timer.c \
audio.c \ audio.c \
lexerstm.c \ lexerstm.c \

4
stm/audio.c

@ -6,13 +6,13 @@
#include "nlr.h" #include "nlr.h"
#include "misc.h" #include "misc.h"
//#include "lexer.h"
//#include "lexerstm.h"
#include "mpyconfig.h" #include "mpyconfig.h"
#include "parse.h" #include "parse.h"
#include "compile.h" #include "compile.h"
#include "runtime.h" #include "runtime.h"
#include "audio.h"
#define SAMPLE_BUF_SIZE (32) #define SAMPLE_BUF_SIZE (32)
// sample_buf_in is always the same or ahead of sample_buf_out // sample_buf_in is always the same or ahead of sample_buf_out

12
stm/main.c

@ -20,6 +20,7 @@
#include "usart.h" #include "usart.h"
#include "usb.h" #include "usb.h"
#include "ff.h" #include "ff.h"
#include "timer.h"
#include "audio.h" #include "audio.h"
static FATFS fatfs0; static FATFS fatfs0;
@ -525,7 +526,7 @@ py_obj_t pyb_pwm_set(py_obj_t period, py_obj_t pulse) {
#define MMA_ADDR (0x4c) #define MMA_ADDR (0x4c)
py_obj_t pyb_mma_read() { py_obj_t pyb_mma_read(void) {
mma_start(MMA_ADDR, 1); mma_start(MMA_ADDR, 1);
mma_send_byte(0); mma_send_byte(0);
mma_restart(MMA_ADDR, 0); mma_restart(MMA_ADDR, 0);
@ -731,6 +732,8 @@ int main(void) {
storage_init(); storage_init();
usart_init(); usart_init();
int first_soft_reset = true;
soft_reset: soft_reset:
// LCD init // LCD init
@ -749,6 +752,9 @@ soft_reset:
// audio // audio
audio_init(); audio_init();
// timer
timer_init();
// add some functions to the python namespace // add some functions to the python namespace
{ {
py_obj_t m = py_module_new(); py_obj_t m = py_module_new();
@ -846,7 +852,7 @@ soft_reset:
usb_init(); usb_init();
// MMA // MMA
{ if (first_soft_reset) {
// init and reset address to zero // init and reset address to zero
mma_init(); mma_init();
mma_start(MMA_ADDR, 1); mma_start(MMA_ADDR, 1);
@ -1123,6 +1129,8 @@ soft_reset:
pyb_sync(); pyb_sync();
printf("PYB: soft reboot\n"); printf("PYB: soft reboot\n");
first_soft_reset = false;
goto soft_reset; goto soft_reset;
} }

15
stm/stm32fxxx_it.c

@ -251,4 +251,19 @@ void SDIO_IRQHandler(void)
{ {
}*/ }*/
// TIM6 Update event
#include "stm32f4xx_tim.h"
void TIM6_DAC_IRQHandler(void) {
// work out if it's TIM6 that had the interrupt
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) {
extern void timer_interrupt(void);
timer_interrupt();
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
} else {
// it seems we get 2 calls to this interrupt handler, and only 1 is the TIM_IT_Update...
// TODO work out what the other one is, and if we can disable it
//printf("unhandled TIM6_DAC\n");
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

90
stm/timer.c

@ -0,0 +1,90 @@
#include <stdint.h>
#include <stdio.h>
#include "stm_misc.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "parse.h"
#include "compile.h"
#include "runtime.h"
#include "timer.h"
// TIM6 is used as an internal interrup to schedule something at a specific rate
py_obj_t timer_py_callback;
py_obj_t timer_py_set_callback(py_obj_t f) {
timer_py_callback = f;
return py_const_none;
}
py_obj_t timer_py_set_period(py_obj_t period) {
TIM6->ARR = py_obj_get_int(period) & 0xffff;
//TIM6->PSC = prescaler & 0xffff;
return py_const_none;
}
py_obj_t timer_py_get_value(void) {
return py_obj_new_int(TIM6->CNT & 0xfffff);
}
void timer_init(void) {
timer_py_callback = py_const_none;
// TIM6 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
// Compute the prescaler value so TIM6 runs at 10kHz
uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 10000) - 1;
// Time base configuration
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 10000; // timer cycles at 1Hz
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // unused for TIM6
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // unused for TIM6
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
// enable perhipheral preload register
TIM_ARRPreloadConfig(TIM6, ENABLE);
// enable interrupt when counter overflows
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
// set up interrupt
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0f; // lowest priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0f; // lowest priority
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// TIM6 enable counter
TIM_Cmd(TIM6, ENABLE);
// Python interface
py_obj_t m = py_module_new();
rt_store_attr(m, qstr_from_str_static("callback"), rt_make_function_1(timer_py_set_callback));
rt_store_attr(m, qstr_from_str_static("period"), rt_make_function_1(timer_py_set_period));
rt_store_attr(m, qstr_from_str_static("value"), rt_make_function_0(timer_py_get_value));
rt_store_name(qstr_from_str_static("timer"), m);
}
void timer_interrupt(void) {
if (timer_py_callback != py_const_none) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
rt_call_function_0(timer_py_callback);
nlr_pop();
} else {
// uncaught exception
printf("exception in timer interrupt\n");
py_obj_print((py_obj_t)nlr.ret_val);
printf("\n");
}
}
}

1
stm/timer.h

@ -0,0 +1 @@
void timer_init(void);
Loading…
Cancel
Save