Skip to content
Snippets Groups Projects
Commit 0f654513 authored by Damien's avatar Damien
Browse files

Implement simple servo control using PWM.

parent 8b3a7c22
No related branches found
No related tags found
No related merge requests found
...@@ -62,6 +62,7 @@ SRC_STM = \ ...@@ -62,6 +62,7 @@ SRC_STM = \
stm32f4xx_dma.c \ stm32f4xx_dma.c \
stm32f4xx_exti.c \ stm32f4xx_exti.c \
stm32f4xx_gpio.c \ stm32f4xx_gpio.c \
stm32f4xx_tim.c \
stm_misc.c \ stm_misc.c \
usb_core.c \ usb_core.c \
usb_dcd.c \ usb_dcd.c \
......
...@@ -88,7 +88,7 @@ int lcd_line; ...@@ -88,7 +88,7 @@ int lcd_line;
int lcd_column; int lcd_column;
int lcd_next_line; int lcd_next_line;
void lcd_init() { void lcd_init(void) {
// set the outputs high // set the outputs high
PYB_LCD_PORT->BSRRL = PYB_LCD_CS1_PIN; PYB_LCD_PORT->BSRRL = PYB_LCD_CS1_PIN;
PYB_LCD_PORT->BSRRL = PYB_LCD_RST_PIN; PYB_LCD_PORT->BSRRL = PYB_LCD_RST_PIN;
......
void lcd_init(); void lcd_init(void);
void lcd_print_str(const char *str); void lcd_print_str(const char *str);
void lcd_print_strn(const char *str, unsigned int len); void lcd_print_strn(const char *str, unsigned int len);
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#define PYB_LED_G1_PIN (GPIO_Pin_4) #define PYB_LED_G1_PIN (GPIO_Pin_4)
#define PYB_LED_G2_PIN (GPIO_Pin_5) #define PYB_LED_G2_PIN (GPIO_Pin_5)
void led_init() { void led_init(void) {
// set the output high (so LED is off) // set the output high (so LED is off)
PYB_LED_R_PORT->BSRRL = PYB_LED_R1_PIN; PYB_LED_R_PORT->BSRRL = PYB_LED_R1_PIN;
PYB_LED_R_PORT->BSRRL = PYB_LED_R2_PIN; PYB_LED_R_PORT->BSRRL = PYB_LED_R2_PIN;
......
...@@ -5,6 +5,6 @@ typedef enum { ...@@ -5,6 +5,6 @@ typedef enum {
PYB_LED_G2 = 3, PYB_LED_G2 = 3,
} pyb_led_t; } pyb_led_t;
void led_init(); void led_init(void);
void led_state(pyb_led_t led, int state); void led_state(pyb_led_t led, int state);
void led_toggle(pyb_led_t led); void led_toggle(pyb_led_t led);
This diff is collapsed.
This diff is collapsed.
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <stm32f4xx.h> #include <stm32f4xx.h>
#include <stm32f4xx_rcc.h> #include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h> #include <stm32f4xx_gpio.h>
#include <stm32f4xx_tim.h>
#include <stm_misc.h> #include <stm_misc.h>
#include "std.h" #include "std.h"
...@@ -32,7 +33,7 @@ void flash_error(int n) { ...@@ -32,7 +33,7 @@ void flash_error(int n) {
led_state(PYB_LED_R2, 0); led_state(PYB_LED_R2, 0);
} }
static void impl02_c_version() { static void impl02_c_version(void) {
int x = 0; int x = 0;
while (x < 400) { while (x < 400) {
int y = 0; int y = 0;
...@@ -50,7 +51,7 @@ static void impl02_c_version() { ...@@ -50,7 +51,7 @@ static void impl02_c_version() {
#define PYB_USRSW_PORT (GPIOA) #define PYB_USRSW_PORT (GPIOA)
#define PYB_USRSW_PIN (GPIO_Pin_13) #define PYB_USRSW_PIN (GPIO_Pin_13)
void sw_init() { void sw_init(void) {
// make it an input with pull-up // make it an input with pull-up
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = PYB_USRSW_PIN; GPIO_InitStructure.GPIO_Pin = PYB_USRSW_PIN;
...@@ -59,7 +60,7 @@ void sw_init() { ...@@ -59,7 +60,7 @@ void sw_init() {
GPIO_Init(PYB_USRSW_PORT, &GPIO_InitStructure); GPIO_Init(PYB_USRSW_PORT, &GPIO_InitStructure);
} }
int sw_get() { int sw_get(void) {
if (PYB_USRSW_PORT->IDR & PYB_USRSW_PIN) { if (PYB_USRSW_PORT->IDR & PYB_USRSW_PIN) {
// pulled high, so switch is not pressed // pulled high, so switch is not pressed
return 0; return 0;
...@@ -101,7 +102,7 @@ py_obj_t pyb_main(py_obj_t main) { ...@@ -101,7 +102,7 @@ py_obj_t pyb_main(py_obj_t main) {
} }
// sync all file systems // sync all file systems
py_obj_t pyb_sync() { py_obj_t pyb_sync(void) {
storage_flush(); storage_flush();
return py_const_none; return py_const_none;
} }
...@@ -116,7 +117,7 @@ py_obj_t pyb_led(py_obj_t state) { ...@@ -116,7 +117,7 @@ py_obj_t pyb_led(py_obj_t state) {
return state; return state;
} }
py_obj_t pyb_sw() { py_obj_t pyb_sw(void) {
if (sw_get()) { if (sw_get()) {
return py_const_true; return py_const_true;
} else { } else {
...@@ -131,7 +132,7 @@ void g(uint i) { ...@@ -131,7 +132,7 @@ void g(uint i) {
nlr_jump((void*)(42 + i)); nlr_jump((void*)(42 + i));
} }
} }
void f() { void f(void) {
nlr_buf_t nlr; nlr_buf_t nlr;
int i; int i;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
...@@ -149,12 +150,12 @@ void f() { ...@@ -149,12 +150,12 @@ void f() {
} }
} }
} }
void nlr_test() { void nlr_test(void) {
f(1); f(1);
} }
*/ */
void fatality() { void fatality(void) {
led_state(PYB_LED_R1, 1); led_state(PYB_LED_R1, 1);
led_state(PYB_LED_G1, 1); led_state(PYB_LED_G1, 1);
led_state(PYB_LED_R2, 1); led_state(PYB_LED_R2, 1);
...@@ -174,7 +175,7 @@ static const char fresh_boot_py[] = ...@@ -174,7 +175,7 @@ static const char fresh_boot_py[] =
; ;
// get lots of info about the board // get lots of info about the board
static py_obj_t pyb_info() { static py_obj_t pyb_info(void) {
// get and print clock speeds // get and print clock speeds
// SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
{ {
...@@ -249,7 +250,7 @@ int readline(vstr_t *line, const char *prompt) { ...@@ -249,7 +250,7 @@ int readline(vstr_t *line, const char *prompt) {
} }
} }
void do_repl() { void do_repl(void) {
usb_vcp_send_str("Micro Python 0.5; STM32F405RG; PYBv2\r\n"); usb_vcp_send_str("Micro Python 0.5; STM32F405RG; PYBv2\r\n");
usb_vcp_send_str("Type \"help\" for more information.\r\n"); usb_vcp_send_str("Type \"help\" for more information.\r\n");
...@@ -352,7 +353,7 @@ bool do_file(const char *filename) { ...@@ -352,7 +353,7 @@ bool do_file(const char *filename) {
void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end); void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
void gc_collect() { void gc_collect(void) {
uint32_t start = sys_tick_counter; uint32_t start = sys_tick_counter;
gc_collect_start(); gc_collect_start();
gc_collect_root((void**)RAM_START, (((uint32_t)&_heap_start) - RAM_START) / 4); gc_collect_root((void**)RAM_START, (((uint32_t)&_heap_start) - RAM_START) / 4);
...@@ -369,12 +370,70 @@ void gc_collect() { ...@@ -369,12 +370,70 @@ void gc_collect() {
printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block); printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
} }
py_obj_t pyb_gc() { py_obj_t pyb_gc(void) {
gc_collect(); gc_collect();
return py_const_none; return py_const_none;
} }
int main() { // PWM
// TIM2 and TIM5 have CH1, CH2, CH3, CH4 on PA0-PA3 respectively
// they are both 32-bit counters
// 16-bit prescaler
// TIM2_CH3 also on PB10 (used below)
void servo_init(void) {
// TIM2 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// GPIOC Configuration: TIM2_CH3 (PB10)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Connect TIM2 pins to AF1
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2);
// Compute the prescaler value so TIM2 runs at 100kHz
uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 100000) - 1;
// Time base configuration
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 2000; // timer cycles at 50Hz
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// PWM1 Mode configuration: Channel1
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 150; // units of 10us
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
// ?
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
// ?
TIM_ARRPreloadConfig(TIM2, ENABLE);
// TIM2 enable counter
TIM_Cmd(TIM2, ENABLE);
}
py_obj_t pyb_servo_set(py_obj_t value) {
int v = py_get_int(value);
if (v < 100) { v = 100; }
if (v > 200) { v = 200; }
TIM2->CCR3 = v;
return py_const_none;
}
int main(void) {
// TODO disable JTAG // TODO disable JTAG
// set interrupt priority config to use all 4 bits for pre-empting // set interrupt priority config to use all 4 bits for pre-empting
...@@ -406,6 +465,9 @@ soft_reset: ...@@ -406,6 +465,9 @@ soft_reset:
qstr_init(); qstr_init();
rt_init(); rt_init();
// servo
servo_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();
...@@ -417,6 +479,7 @@ soft_reset: ...@@ -417,6 +479,7 @@ soft_reset:
rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay)); rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay));
rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led)); rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led));
rt_store_attr(m, qstr_from_str_static("sw"), rt_make_function_0(pyb_sw)); rt_store_attr(m, qstr_from_str_static("sw"), rt_make_function_0(pyb_sw));
rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_1(pyb_servo_set));
rt_store_name(qstr_from_str_static("pyb"), m); rt_store_name(qstr_from_str_static("pyb"), m);
} }
......
...@@ -49,7 +49,7 @@ void *realloc(void *ptr, size_t n) { ...@@ -49,7 +49,7 @@ void *realloc(void *ptr, size_t n) {
return gc_realloc(ptr, n); return gc_realloc(ptr, n);
} }
void __assert_func() { void __assert_func(void) {
printf("\nASSERT FAIL!"); printf("\nASSERT FAIL!");
for (;;) { for (;;) {
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include "mma.h" #include "mma.h"
void mma_init() { void mma_init(void) {
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1
//gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */); //gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
//gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */); //gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
...@@ -46,7 +46,7 @@ void mma_init() { ...@@ -46,7 +46,7 @@ void mma_init() {
// set START bit in CR1 to generate a start cond! // set START bit in CR1 to generate a start cond!
} }
static uint32_t i2c_get_sr() { static uint32_t i2c_get_sr(void) {
// must read SR1 first, then SR2, as the read can clear some flags // must read SR1 first, then SR2, as the read can clear some flags
uint32_t sr1 = I2C1->SR1; uint32_t sr1 = I2C1->SR1;
uint32_t sr2 = I2C1->SR2; uint32_t sr2 = I2C1->SR2;
...@@ -98,7 +98,7 @@ void mma_send_byte(uint8_t data) { ...@@ -98,7 +98,7 @@ void mma_send_byte(uint8_t data) {
} }
} }
uint8_t mma_read_ack() { uint8_t mma_read_ack(void) {
// enable ACK of received byte // enable ACK of received byte
I2C1->CR1 |= I2C_CR1_ACK; I2C1->CR1 |= I2C_CR1_ACK;
// wait for BUSY, MSL and RXNE (byte received) // wait for BUSY, MSL and RXNE (byte received)
...@@ -109,7 +109,7 @@ uint8_t mma_read_ack() { ...@@ -109,7 +109,7 @@ uint8_t mma_read_ack() {
return data; return data;
} }
uint8_t mma_read_nack() { uint8_t mma_read_nack(void) {
// disable ACK of received byte (to indicate end of receiving) // disable ACK of received byte (to indicate end of receiving)
I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK); I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
// last byte should apparently also generate a stop condition // last byte should apparently also generate a stop condition
...@@ -122,7 +122,7 @@ uint8_t mma_read_nack() { ...@@ -122,7 +122,7 @@ uint8_t mma_read_nack() {
return data; return data;
} }
void mma_stop() { void mma_stop(void) {
// send stop condition // send stop condition
I2C1->CR1 |= I2C_CR1_STOP; I2C1->CR1 |= I2C_CR1_STOP;
} }
void mma_init(); void mma_init(void);
void mma_restart(uint8_t addr, int write); void mma_restart(uint8_t addr, int write);
void mma_start(uint8_t addr, int write); void mma_start(uint8_t addr, int write);
void mma_send_byte(uint8_t data); void mma_send_byte(uint8_t data);
uint8_t mma_read_ack(); uint8_t mma_read_ack(void);
uint8_t mma_read_nack(); uint8_t mma_read_nack(void);
void mma_stop(); void mma_stop(void);
typedef unsigned int size_t; typedef unsigned int size_t;
void __assert_func(); void __assert_func(void);
void *malloc(size_t n); void *malloc(size_t n);
void free(void *ptr); void free(void *ptr);
......
...@@ -18,7 +18,7 @@ static uint32_t cache_flash_sector_start; ...@@ -18,7 +18,7 @@ static uint32_t cache_flash_sector_start;
static uint32_t cache_flash_sector_size; static uint32_t cache_flash_sector_size;
static bool cache_dirty; static bool cache_dirty;
static void cache_flush() { static void cache_flush(void) {
if (cache_dirty) { if (cache_dirty) {
// sync the cache RAM buffer by writing it to the flash page // sync the cache RAM buffer by writing it to the flash page
flash_write(cache_flash_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, cache_flash_sector_size / 4); flash_write(cache_flash_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, cache_flash_sector_size / 4);
...@@ -45,7 +45,7 @@ static uint8_t *cache_get_addr_for_write(uint32_t flash_addr) { ...@@ -45,7 +45,7 @@ static uint8_t *cache_get_addr_for_write(uint32_t flash_addr) {
return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start; return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start;
} }
void storage_init() { void storage_init(void) {
if (!is_initialised) { if (!is_initialised) {
cache_flash_sector_id = 0; cache_flash_sector_id = 0;
cache_dirty = false; cache_dirty = false;
...@@ -53,15 +53,15 @@ void storage_init() { ...@@ -53,15 +53,15 @@ void storage_init() {
} }
} }
uint32_t storage_get_block_size() { uint32_t storage_get_block_size(void) {
return BLOCK_SIZE; return BLOCK_SIZE;
} }
uint32_t storage_get_block_count() { uint32_t storage_get_block_count(void) {
return FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS; return FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS;
} }
void storage_flush() { void storage_flush(void) {
cache_flush(); cache_flush();
} }
......
void storage_init(); void storage_init(void);
uint32_t storage_get_block_size(); uint32_t storage_get_block_size(void);
uint32_t storage_get_block_count(); uint32_t storage_get_block_count(void);
void storage_flush(); void storage_flush(void);
bool storage_read_block(uint8_t *dest, uint32_t block); bool storage_read_block(uint8_t *dest, uint32_t block);
bool storage_write_block(const uint8_t *src, uint32_t block); bool storage_write_block(const uint8_t *src, uint32_t block);
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
volatile uint32_t sys_tick_counter; volatile uint32_t sys_tick_counter;
void sys_tick_init() { void sys_tick_init(void) {
// sys-tick interrupt called at 1ms intervals // sys-tick interrupt called at 1ms intervals
sys_tick_counter = 0; sys_tick_counter = 0;
SysTick_Config(SystemCoreClock / 1000); SysTick_Config(SystemCoreClock / 1000);
...@@ -12,7 +12,7 @@ void sys_tick_init() { ...@@ -12,7 +12,7 @@ void sys_tick_init() {
} }
// called on SysTick interrupt // called on SysTick interrupt
void SysTick_Handler() { void SysTick_Handler(void) {
sys_tick_counter++; sys_tick_counter++;
} }
......
extern volatile uint32_t sys_tick_counter; extern volatile uint32_t sys_tick_counter;
void sys_tick_init(); void sys_tick_init(void);
void SysTick_Handler(); void SysTick_Handler(void);
void sys_tick_delay_ms(uint32_t delay_ms); void sys_tick_delay_ms(uint32_t delay_ms);
void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms); void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms);
bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms); bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms);
...@@ -19,7 +19,7 @@ static char rx_buf[64]; ...@@ -19,7 +19,7 @@ static char rx_buf[64];
static int rx_buf_in; static int rx_buf_in;
static int rx_buf_out; static int rx_buf_out;
void usb_init() { void usb_init(void) {
if (!is_enabled) { if (!is_enabled) {
// only init USB once in the device's power-lifetime // only init USB once in the device's power-lifetime
USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb); USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb);
...@@ -29,7 +29,7 @@ void usb_init() { ...@@ -29,7 +29,7 @@ void usb_init() {
is_enabled = 1; is_enabled = 1;
} }
bool usb_vcp_is_enabled() { bool usb_vcp_is_enabled(void) {
return is_enabled; return is_enabled;
} }
...@@ -50,7 +50,7 @@ void usb_vcp_receive(const char *buf, uint32_t len) { ...@@ -50,7 +50,7 @@ void usb_vcp_receive(const char *buf, uint32_t len) {
} }
} }
int usb_vcp_rx_any() { int usb_vcp_rx_any(void) {
if (rx_buf_in >= rx_buf_out) { if (rx_buf_in >= rx_buf_out) {
return rx_buf_in - rx_buf_out; return rx_buf_in - rx_buf_out;
} else { } else {
...@@ -58,7 +58,7 @@ int usb_vcp_rx_any() { ...@@ -58,7 +58,7 @@ int usb_vcp_rx_any() {
} }
} }
char usb_vcp_rx_get() { char usb_vcp_rx_get(void) {
while (rx_buf_out == rx_buf_in) { while (rx_buf_out == rx_buf_in) {
} }
char c = rx_buf[rx_buf_out]; char c = rx_buf[rx_buf_out];
......
void usb_init(); void usb_init(void);
bool usb_vcp_is_enabled(); bool usb_vcp_is_enabled(void);
int usb_vcp_rx_any(); int usb_vcp_rx_any(void);
char usb_vcp_rx_get(); char usb_vcp_rx_get(void);
void usb_vcp_send_str(const char* str); void usb_vcp_send_str(const char* str);
void usb_vcp_send_strn(const char* str, int len); void usb_vcp_send_strn(const char* str, int len);
void usb_vcp_send_strn_cooked(const char *str, int len); void usb_vcp_send_strn_cooked(const char *str, int len);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment