Commit 0f654513 authored by Damien's avatar Damien
Browse files

Implement simple servo control using PWM.

parent 8b3a7c22
......@@ -62,6 +62,7 @@ SRC_STM = \
stm32f4xx_dma.c \
stm32f4xx_exti.c \
stm32f4xx_gpio.c \
stm32f4xx_tim.c \
stm_misc.c \
usb_core.c \
usb_dcd.c \
......
......@@ -88,7 +88,7 @@ int lcd_line;
int lcd_column;
int lcd_next_line;
void lcd_init() {
void lcd_init(void) {
// set the outputs high
PYB_LCD_PORT->BSRRL = PYB_LCD_CS1_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_strn(const char *str, unsigned int len);
......@@ -9,7 +9,7 @@
#define PYB_LED_G1_PIN (GPIO_Pin_4)
#define PYB_LED_G2_PIN (GPIO_Pin_5)
void led_init() {
void led_init(void) {
// set the output high (so LED is off)
PYB_LED_R_PORT->BSRRL = PYB_LED_R1_PIN;
PYB_LED_R_PORT->BSRRL = PYB_LED_R2_PIN;
......
......@@ -5,6 +5,6 @@ typedef enum {
PYB_LED_G2 = 3,
} pyb_led_t;
void led_init();
void led_init(void);
void led_state(pyb_led_t led, int state);
void led_toggle(pyb_led_t led);
This diff is collapsed.
This diff is collapsed.
......@@ -2,6 +2,7 @@
#include <stm32f4xx.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_tim.h>
#include <stm_misc.h>
#include "std.h"
......@@ -32,7 +33,7 @@ void flash_error(int n) {
led_state(PYB_LED_R2, 0);
}
static void impl02_c_version() {
static void impl02_c_version(void) {
int x = 0;
while (x < 400) {
int y = 0;
......@@ -50,7 +51,7 @@ static void impl02_c_version() {
#define PYB_USRSW_PORT (GPIOA)
#define PYB_USRSW_PIN (GPIO_Pin_13)
void sw_init() {
void sw_init(void) {
// make it an input with pull-up
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = PYB_USRSW_PIN;
......@@ -59,7 +60,7 @@ void sw_init() {
GPIO_Init(PYB_USRSW_PORT, &GPIO_InitStructure);
}
int sw_get() {
int sw_get(void) {
if (PYB_USRSW_PORT->IDR & PYB_USRSW_PIN) {
// pulled high, so switch is not pressed
return 0;
......@@ -101,7 +102,7 @@ py_obj_t pyb_main(py_obj_t main) {
}
// sync all file systems
py_obj_t pyb_sync() {
py_obj_t pyb_sync(void) {
storage_flush();
return py_const_none;
}
......@@ -116,7 +117,7 @@ py_obj_t pyb_led(py_obj_t state) {
return state;
}
py_obj_t pyb_sw() {
py_obj_t pyb_sw(void) {
if (sw_get()) {
return py_const_true;
} else {
......@@ -131,7 +132,7 @@ void g(uint i) {
nlr_jump((void*)(42 + i));
}
}
void f() {
void f(void) {
nlr_buf_t nlr;
int i;
for (i = 0; i < 4; i++) {
......@@ -149,12 +150,12 @@ void f() {
}
}
}
void nlr_test() {
void nlr_test(void) {
f(1);
}
*/
void fatality() {
void fatality(void) {
led_state(PYB_LED_R1, 1);
led_state(PYB_LED_G1, 1);
led_state(PYB_LED_R2, 1);
......@@ -174,7 +175,7 @@ static const char fresh_boot_py[] =
;
// 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
// SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
{
......@@ -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("Type \"help\" for more information.\r\n");
......@@ -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_collect() {
void gc_collect(void) {
uint32_t start = sys_tick_counter;
gc_collect_start();
gc_collect_root((void**)RAM_START, (((uint32_t)&_heap_start) - RAM_START) / 4);
......@@ -369,12 +370,70 @@ void gc_collect() {
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();
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
// set interrupt priority config to use all 4 bits for pre-empting
......@@ -406,6 +465,9 @@ soft_reset:
qstr_init();
rt_init();
// servo
servo_init();
// add some functions to the python namespace
{
py_obj_t m = py_module_new();
......@@ -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("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("servo"), rt_make_function_1(pyb_servo_set));
rt_store_name(qstr_from_str_static("pyb"), m);
}
......
......@@ -49,7 +49,7 @@ void *realloc(void *ptr, size_t n) {
return gc_realloc(ptr, n);
}
void __assert_func() {
void __assert_func(void) {
printf("\nASSERT FAIL!");
for (;;) {
}
......
......@@ -6,7 +6,7 @@
#include "mma.h"
void mma_init() {
void mma_init(void) {
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, 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() {
// 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
uint32_t sr1 = I2C1->SR1;
uint32_t sr2 = I2C1->SR2;
......@@ -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
I2C1->CR1 |= I2C_CR1_ACK;
// wait for BUSY, MSL and RXNE (byte received)
......@@ -109,7 +109,7 @@ uint8_t mma_read_ack() {
return data;
}
uint8_t mma_read_nack() {
uint8_t mma_read_nack(void) {
// disable ACK of received byte (to indicate end of receiving)
I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
// last byte should apparently also generate a stop condition
......@@ -122,7 +122,7 @@ uint8_t mma_read_nack() {
return data;
}
void mma_stop() {
void mma_stop(void) {
// send stop condition
I2C1->CR1 |= I2C_CR1_STOP;
}
void mma_init();
void mma_init(void);
void mma_restart(uint8_t addr, int write);
void mma_start(uint8_t addr, int write);
void mma_send_byte(uint8_t data);
uint8_t mma_read_ack();
uint8_t mma_read_nack();
void mma_stop();
uint8_t mma_read_ack(void);
uint8_t mma_read_nack(void);
void mma_stop(void);
typedef unsigned int size_t;
void __assert_func();
void __assert_func(void);
void *malloc(size_t n);
void free(void *ptr);
......
......@@ -18,7 +18,7 @@ static uint32_t cache_flash_sector_start;
static uint32_t cache_flash_sector_size;
static bool cache_dirty;
static void cache_flush() {
static void cache_flush(void) {
if (cache_dirty) {
// 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);
......@@ -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;
}
void storage_init() {
void storage_init(void) {
if (!is_initialised) {
cache_flash_sector_id = 0;
cache_dirty = false;
......@@ -53,15 +53,15 @@ void storage_init() {
}
}
uint32_t storage_get_block_size() {
uint32_t storage_get_block_size(void) {
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;
}
void storage_flush() {
void storage_flush(void) {
cache_flush();
}
......
void storage_init();
uint32_t storage_get_block_size();
uint32_t storage_get_block_count();
void storage_flush();
void storage_init(void);
uint32_t storage_get_block_size(void);
uint32_t storage_get_block_count(void);
void storage_flush(void);
bool storage_read_block(uint8_t *dest, uint32_t block);
bool storage_write_block(const uint8_t *src, uint32_t block);
......@@ -4,7 +4,7 @@
volatile uint32_t sys_tick_counter;
void sys_tick_init() {
void sys_tick_init(void) {
// sys-tick interrupt called at 1ms intervals
sys_tick_counter = 0;
SysTick_Config(SystemCoreClock / 1000);
......@@ -12,7 +12,7 @@ void sys_tick_init() {
}
// called on SysTick interrupt
void SysTick_Handler() {
void SysTick_Handler(void) {
sys_tick_counter++;
}
......
extern volatile uint32_t sys_tick_counter;
void sys_tick_init();
void SysTick_Handler();
void sys_tick_init(void);
void SysTick_Handler(void);
void sys_tick_delay_ms(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);
......@@ -19,7 +19,7 @@ static char rx_buf[64];
static int rx_buf_in;
static int rx_buf_out;
void usb_init() {
void usb_init(void) {
if (!is_enabled) {
// 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);
......@@ -29,7 +29,7 @@ void usb_init() {
is_enabled = 1;
}
bool usb_vcp_is_enabled() {
bool usb_vcp_is_enabled(void) {
return is_enabled;
}
......@@ -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) {
return rx_buf_in - rx_buf_out;
} else {
......@@ -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) {
}
char c = rx_buf[rx_buf_out];
......
void usb_init();
bool usb_vcp_is_enabled();
int usb_vcp_rx_any();
char usb_vcp_rx_get();
void usb_init(void);
bool usb_vcp_is_enabled(void);
int usb_vcp_rx_any(void);
char usb_vcp_rx_get(void);
void usb_vcp_send_str(const char* str);
void usb_vcp_send_strn(const char* str, int len);
void usb_vcp_send_strn_cooked(const char *str, int len);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment