Commit aa7cf6f7 authored by Damien George's avatar Damien George
Browse files

stm: Remove long-obsolete stm/ port.

parent 63436ce2
......@@ -29,15 +29,13 @@ Major components in this repository:
- py/ -- the core Python implementation, including compiler and runtime.
- unix/ -- a version of Micro Python that runs on Unix.
- stmhal/ -- a version of Micro Python that runs on the Micro Python board
with an STM32F405RG (using ST's new Cube HAL drivers).
with an STM32F405RG (using ST's Cube HAL drivers).
- teensy/ -- a version of Micro Python that runs on the Teensy 3.1
(preliminary but functional).
Additional components:
- bare-arm/ -- a bare minimum version of Micro Python for ARM MCUs. Start
with this if you want to port Micro Python to another microcontroller.
- stm/ -- obsolete version of Micro Python for the Micro Python board
that uses ST's old peripheral drivers.
- unix-cpy/ -- a version of Micro Python that outputs bytecode (for testing).
- tests/ -- test framework and test scripts.
- tools/ -- various tools, including the pyboard.py module.
......
include ../py/mkenv.mk
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
# include py core make definitions
include ../py/py.mk
CMSIS_DIR=cmsis
STMPERIPH_DIR=stmperiph
STMUSB_DIR=stmusb
STMUSBD_DIR=stmusbd
STMUSBH_DIR=stmusbh
FATFS_DIR=fatfs
CC3K_DIR=cc3k
DFU=../tools/dfu.py
CROSS_COMPILE = arm-none-eabi-
INC = -I.
INC += -I$(PY_SRC)
INC += -I$(BUILD)
INC += -I$(CMSIS_DIR)
INC += -I$(STMPERIPH_DIR)
INC += -I$(STMUSB_DIR)
INC += -I$(STMUSBD_DIR)
INC += -I$(STMUSBH_DIR)
INC += -I$(FATFS_DIR)
#INC += -I$(CC3K_DIR)
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) $(COPT)
BOARD ?= PYBOARD4
ifeq ($(wildcard boards/$(BOARD)/.),)
$(error Invalid BOARD specified)
endif
CFLAGS += -Iboards/$(BOARD)
#Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -g -DPENDSV_DEBUG
COPT = -O0
else
COPT += -Os -DNDEBUG
endif
LDFLAGS = --nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref
LIBS =
# uncomment this if you want libgcc
#LIBS += $(shell $(CC) -print-libgcc-file-name)
SRC_C = \
main.c \
printf.c \
math.c \
system_stm32f4xx.c \
stm32fxxx_it.c \
string0.c \
malloc0.c \
systick.c \
pendsv.c \
gccollect.c \
lexerfatfs.c \
import.c \
pyexec.c \
led.c \
gpio.c \
lcd.c \
servo.c \
flash.c \
storage.c \
accel.c \
usart.c \
usb.c \
timer.c \
audio.c \
sdcard.c \
i2c.c \
adc.c \
rtc.c \
file.c \
pin.c \
pin_named_pins.c \
pin_map.c \
exti.c \
usrsw.c \
pybmodule.c \
# pybwlan.c \
SRC_S = \
startup_stm32f40xx.s \
gchelper.s \
SRC_STMPERIPH = $(addprefix $(STMPERIPH_DIR)/,\
stm_misc.c \
stm32f4xx_rcc.c \
stm32f4xx_syscfg.c \
stm32f4xx_flash.c \
stm32f4xx_dma.c \
stm32f4xx_gpio.c \
stm32f4xx_exti.c \
stm32f4xx_tim.c \
stm32f4xx_sdio.c \
stm32f4xx_pwr.c \
stm32f4xx_rtc.c \
stm32f4xx_usart.c \
stm32f4xx_spi.c \
stm32f4xx_dac.c \
stm32f4xx_rng.c \
stm32f4xx_i2c.c \
stm32f4xx_adc.c \
stm324x7i_eval.c \
stm324x7i_eval_sdio_sd.c \
)
SRC_STMUSB = $(addprefix $(STMUSB_DIR)/,\
usb_core.c \
usb_bsp.c \
usb_dcd.c \
usb_dcd_int.c \
usb_hcd.c \
usb_hcd_int.c \
)
# usb_otg.c \
SRC_STMUSBD = $(addprefix $(STMUSBD_DIR)/,\
usbd_core.c \
usbd_ioreq.c \
usbd_req.c \
usbd_usr.c \
usbd_desc.c \
usbd_pyb_core.c \
usbd_pyb_core2.c \
usbd_cdc_vcp.c \
usbd_msc_bot.c \
usbd_msc_data.c \
usbd_msc_scsi.c \
usbd_storage_msd.c \
)
SRC_STMUSBH = $(addprefix $(STMUSBH_DIR)/,\
usbh_core.c \
usbh_hcs.c \
usbh_stdreq.c \
usbh_ioreq.c \
usbh_usr.c \
usbh_hid_core.c \
usbh_hid_mouse.c \
usbh_hid_keybd.c \
)
SRC_FATFS = $(addprefix $(FATFS_DIR)/,\
ff.c \
diskio.c \
ccsbcs.c \
)
SRC_CC3K = $(addprefix $(CC3K_DIR)/,\
cc3000_common.c \
evnt_handler.c \
hci.c \
netapp.c \
nvmem.c \
security.c \
socket.c \
wlan.c \
ccspi.c \
pybcc3k.c \
)
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o) $(SRC_STMPERIPH:.c=.o) $(SRC_STMUSB:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_STMUSBD:.c=.o))
#OBJ += $(addprefix $(BUILD)/, $(SRC_STMUSBH:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_FATFS:.c=.o))
#OBJ += $(addprefix $(BUILD)/, $(SRC_CC3K:.c=.o))
OBJ += $(BUILD)/pins_$(BOARD).o
all: $(BUILD)/flash.dfu
$(BUILD)/flash.dfu: $(BUILD)/flash0.bin $(BUILD)/flash1.bin
$(ECHO) "Create $@"
$(Q)$(PYTHON) $(DFU) -b 0x08000000:$(BUILD)/flash0.bin -b 0x08020000:$(BUILD)/flash1.bin $@
$(BUILD)/flash0.bin: $(BUILD)/flash.elf
$(Q)$(OBJCOPY) -O binary -j .isr_vector $^ $@
$(BUILD)/flash1.bin: $(BUILD)/flash.elf
$(Q)$(OBJCOPY) -O binary -j .text -j .data $^ $@
$(BUILD)/flash.elf: $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
$(Q)$(SIZE) $@
MAKE_PINS = boards/make-pins.py
BOARD_PINS = boards/$(BOARD)/pins.csv
AF_FILE = boards/stm32f4xx-af.csv
PREFIX_FILE = boards/stm32f4xx-prefix.c
GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c
GEN_PINS_HDR = $(BUILD)/pins.h
# Making OBJ use an order-only depenedency on the generated pins.h file
# has the side effect of making the pins.h file before we actually compile
# any of the objects. The normal dependency generation will deal with the
# case when pins.h is modified. But when it doesn't exist, we don't know
# which source files might need it.
$(OBJ): | $(BUILD)/pins.h
# Use a pattern rule here so that make will only call make-pins.py once to make
# both pins_$(BOARD).c and pins.h
$(BUILD)/%_$(BOARD).c $(BUILD)/%.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE)
$(ECHO) "Create $@"
$(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) > $(GEN_PINS_SRC)
$(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c
$(call compile_c)
include ../py/mkrules.mk
#include <stdio.h>
#include <stm32f4xx.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "systick.h"
#include "obj.h"
#include "runtime.h"
#include "accel.h"
#define ACCEL_ADDR (0x4c)
void accel_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 */);
//gpio_pin_af(GPIOB, 6, 4 /* AF 4 for I2C1 */);
//gpio_pin_af(GPIOB, 7, 4 /* AF 4 for I2C1 */);
// XXX untested GPIO init! (was above code)
GPIO_InitTypeDef GPIO_InitStructure;
// PB5 is connected to AVDD; pull high to enable MMA accel device
GPIOB->BSRRH = GPIO_Pin_5; // PB5 low to start with
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// PB6=SCL, PB7=SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// alternate functions for SCL and SDA
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
// get clock speeds
RCC_ClocksTypeDef rcc_clocks;
RCC_GetClocksFreq(&rcc_clocks);
// disable the I2C peripheral before we configure it
I2C1->CR1 &= ~I2C_CR1_PE;
// program peripheral input clock
I2C1->CR2 = 4; // no interrupts; 4 MHz (hopefully!) (could go up to 42MHz)
// configure clock control reg
uint32_t freq = rcc_clocks.PCLK1_Frequency / (100000 << 1); // want 100kHz, this is the formula for freq
I2C1->CCR = freq; // standard mode (speed), freq calculated as above
// configure rise time reg
I2C1->TRISE = (rcc_clocks.PCLK1_Frequency / 1000000) + 1; // formula for trise, gives maximum rise time
// enable the I2C peripheral
I2C1->CR1 |= I2C_CR1_PE;
// wait 20ms, then turn on AVDD, then wait 20ms again; this seems to work, but maybe can decrease delays
// doesn't work for soft reboot; 50ms doesn't work either...
sys_tick_delay_ms(20);
GPIOB->BSRRL = GPIO_Pin_5;
sys_tick_delay_ms(20);
// set START bit in CR1 to generate a start cond!
// init the chip via I2C commands
accel_start(ACCEL_ADDR, 1);
accel_send_byte(0);
accel_stop();
/*
// read and print all 11 registers
accel_start(ACCEL_ADDR, 1);
accel_send_byte(0);
accel_restart(ACCEL_ADDR, 0);
for (int i = 0; i <= 0xa; i++) {
int data;
if (i == 0xa) {
data = accel_read_nack();
} else {
data = accel_read_ack();
}
printf(" %02x", data);
}
printf("\n");
*/
// put into active mode
accel_start(ACCEL_ADDR, 1);
accel_send_byte(7); // mode
accel_send_byte(1); // active mode
accel_stop();
/*
// infinite loop to read values
for (;;) {
sys_tick_delay_ms(500);
accel_start(ACCEL_ADDR, 1);
accel_send_byte(0);
accel_restart(ACCEL_ADDR, 0);
for (int i = 0; i <= 3; i++) {
int data;
if (i == 3) {
data = accel_read_nack();
printf(" %02x\n", data);
} else {
data = accel_read_ack() & 0x3f;
if (data & 0x20) {
data |= ~0x1f;
}
printf(" % 2d", data);
}
}
}
*/
}
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;
return (sr2 << 16) | sr1;
}
void accel_restart(uint8_t addr, int write) {
// send start condition
I2C1->CR1 |= I2C_CR1_START;
// wait for BUSY, MSL and SB --> Slave has acknowledged start condition
uint32_t timeout = 1000000;
while ((i2c_get_sr() & 0x00030001) != 0x00030001) {
if (--timeout == 0) {
printf("timeout in accel_restart\n");
return;
}
}
if (write) {
// send address and write bit
I2C1->DR = (addr << 1) | 0;
// wait for BUSY, MSL, ADDR, TXE and TRA
timeout = 1000000;
while ((i2c_get_sr() & 0x00070082) != 0x00070082) {
if (--timeout == 0) {
printf("timeout in accel_restart write\n");
return;
}
}
} else {
// send address and read bit
I2C1->DR = (addr << 1) | 1;
// wait for BUSY, MSL and ADDR flags
timeout = 1000000;
while ((i2c_get_sr() & 0x00030002) != 0x00030002) {
if (--timeout == 0) {
printf("timeout in accel_restart read\n");
return;
}
}
}
}
void accel_start(uint8_t addr, int write) {
// wait until I2C is not busy
uint32_t timeout = 1000000;
while (I2C1->SR2 & I2C_SR2_BUSY) {
if (--timeout == 0) {
printf("timeout in accel_start\n");
return;
}
}
// do rest of start
accel_restart(addr, write);
}
void accel_send_byte(uint8_t data) {
// send byte
I2C1->DR = data;
// wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted)
uint32_t timeout = 1000000;
while ((i2c_get_sr() & 0x00070084) != 0x00070084) {
if (--timeout == 0) {
printf("timeout in accel_send_byte\n");
return;
}
}
}
uint8_t accel_read_ack(void) {
// enable ACK of received byte
I2C1->CR1 |= I2C_CR1_ACK;
// wait for BUSY, MSL and RXNE (byte received)
uint32_t timeout = 1000000;
while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
if (--timeout == 0) {
printf("timeout in accel_read_ack\n");
break;
}
}
// read and return data
uint8_t data = I2C1->DR;
return data;
}
uint8_t accel_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
I2C1->CR1 |= I2C_CR1_STOP;
// wait for BUSY, MSL and RXNE (byte received)
uint32_t timeout = 1000000;
while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
if (--timeout == 0) {
printf("timeout in accel_read_nack\n");
break;
}
}
// read and return data
uint8_t data = I2C1->DR;
return data;
}
void accel_stop(void) {
// send stop condition
I2C1->CR1 |= I2C_CR1_STOP;
}
/******************************************************************************/
/* Micro Python bindings */
int accel_buf[12];
mp_obj_t pyb_accel_read(void) {
for (int i = 0; i <= 6; i += 3) {
accel_buf[0 + i] = accel_buf[0 + i + 3];
accel_buf[1 + i] = accel_buf[1 + i + 3];
accel_buf[2 + i] = accel_buf[2 + i + 3];
}
accel_start(ACCEL_ADDR, 1);
accel_send_byte(0);
accel_restart(ACCEL_ADDR, 0);
for (int i = 0; i <= 2; i++) {
int v = accel_read_ack() & 0x3f;
if (v & 0x20) {
v |= ~0x1f;
}
accel_buf[9 + i] = v;
}
int jolt_info = accel_read_nack();
mp_obj_t data[4];
data[0] = mp_obj_new_int(accel_buf[0] + accel_buf[3] + accel_buf[6] + accel_buf[9]);
data[1] = mp_obj_new_int(accel_buf[1] + accel_buf[4] + accel_buf[7] + accel_buf[10]);
data[2] = mp_obj_new_int(accel_buf[2] + accel_buf[5] + accel_buf[8] + accel_buf[11]);
data[3] = mp_obj_new_int(jolt_info);
return mp_obj_new_tuple(4, data);
}
MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_obj, pyb_accel_read);
mp_obj_t pyb_accel_read_all(void) {
mp_obj_t data[11];
accel_start(ACCEL_ADDR, 1);
accel_send_byte(0);
accel_restart(ACCEL_ADDR, 0);
for (int i = 0; i <= 9; i++) {
data[i] = mp_obj_new_int(accel_read_ack());
}
data[10] = mp_obj_new_int(accel_read_nack());
return mp_obj_new_tuple(11, data);
}
MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_all_obj, pyb_accel_read_all);
mp_obj_t pyb_accel_write_mode(mp_obj_t o_int, mp_obj_t o_mode) {
accel_start(ACCEL_ADDR, 1);
accel_send_byte(6); // start at int
accel_send_byte(mp_obj_get_int(o_int));
accel_send_byte(mp_obj_get_int(o_mode));
accel_stop();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_write_mode_obj, pyb_accel_write_mode);
void accel_init(void);
void accel_restart(uint8_t addr, int write);
void accel_start(uint8_t addr, int write);
void accel_send_byte(uint8_t data);
uint8_t accel_read_ack(void);
uint8_t accel_read_nack(void);
void accel_stop(void);
MP_DECLARE_CONST_FUN_OBJ(pyb_accel_read_obj);
MP_DECLARE_CONST_FUN_OBJ(pyb_accel_read_all_obj);
MP_DECLARE_CONST_FUN_OBJ(pyb_accel_write_mode_obj);
#include <stdio.h>
#include <stm32f4xx.h>
#include "mpconfig.h"
#include "misc.h"
#include "nlr.h"
#include "qstr.h"
#include "obj.h"
#include "adc.h"
/* ADC defintions */
#define ADCx (ADC1)
#define ADCx_CLK (RCC_APB2Periph_ADC1)
#define ADC_NUM_CHANNELS (16)
/* Internally connected ADC channels Temp/VBAT/VREF*/
#if defined (STM32F40XX) || defined(STM32F41XX) || defined(STM32F40_41xxx)
#define ADC_TEMP_CHANNEL (16)
#define ADC_VBAT_CHANNEL (18)
#define ADC_VREF_CHANNEL (17)
#elif defined (STM32F42XX) || defined(STM32F43XX)
#define ADC_TEMP_CHANNEL (18)
#define ADC_VBAT_CHANNEL (18) /* same channel as TEMP */
#define ADC_VREF_CHANNEL (17)
#endif
/* Core temperature sensor definitions */
#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */
#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */
/* VBAT divider */
#if defined (STM32F40XX) || defined(STM32F41XX) || defined(STM32F40_41xxx)
#define VBAT_DIV (2)
#elif defined (STM32F42XX) || defined(STM32F43XX)
#define VBAT_DIV (4)
#endif
/* GPIO struct */
typedef struct {
GPIO_TypeDef* port;
uint32_t pin;
} gpio_t;
/* ADC GPIOs */
static const gpio_t adc_gpio[] = {
{GPIOA, GPIO_Pin_0}, /* ADC123_IN0 */
{GPIOA, GPIO_Pin_1}, /* ADC123_IN1 */
{GPIOA, GPIO_Pin_2}, /* ADC123_IN2 */
{GPIOA, GPIO_Pin_3}, /* ADC123_IN3 */
{GPIOA, GPIO_Pin_4}, /* ADC12_IN4 */
{GPIOA, GPIO_Pin_5}, /* ADC12_IN5 */
{GPIOA, GPIO_Pin_6}, /* ADC12_IN6 */
{GPIOA, GPIO_Pin_7}, /* ADC12_IN7 */
{GPIOB, GPIO_Pin_0}, /* ADC12_IN8 */
{GPIOB, GPIO_Pin_1}, /* ADC12_IN9 */
{GPIOC, GPIO_Pin_0}, /* ADC123_IN10 */
{GPIOC, GPIO_Pin_1}, /* ADC123_IN11 */
{GPIOC, GPIO_Pin_2}, /* ADC123_IN12 */
{GPIOC, GPIO_Pin_3}, /* ADC123_IN13 */
{GPIOC, GPIO_Pin_4}, /* ADC12_IN14 */
{GPIOC, GPIO_Pin_5}, /* ADC12_IN15 */
};
void adc_init_all(uint32_t resolution) {
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
/* Enable ADCx, DMA and GPIO clocks */
#if 0
/* GPIO clocks enabled in main */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
RCC_AHB1Periph_GPIOB |
RCC_AHB1Periph_GPIOC, ENABLE);
#endif
RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);
/* ADC Common Init */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;