mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Update sources to new HAL
This commit is contained in:
parent
0e69ebad74
commit
1e4b6fa8fd
11
src/Makefile
11
src/Makefile
@ -54,10 +54,11 @@ CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/stmhal/boards/$(TARGET)/
|
||||
|
||||
CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/
|
||||
CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/py/
|
||||
CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/img/
|
||||
|
||||
# Linker Flags
|
||||
|
||||
LDFLAGS = -mcpu=cortex-m4 -mabi=aapcs-linux -mthumb -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostdlib -Wl,-Tstm32f407.ld
|
||||
LDFLAGS = -mcpu=cortex-m4 -mabi=aapcs-linux -mthumb -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostdlib -Wl,-T$(OMV_DIR)/stm32f407.ld
|
||||
|
||||
# Sources
|
||||
#SRC_C = $(addprefix $(CMSIS_DIR)/src/st/,\
|
||||
@ -79,7 +80,6 @@ OBJ += $(addprefix $(BUILD)/$(MICROPY_DIR)/,\
|
||||
usbd_desc_cdc_msc.o \
|
||||
usbd_cdc_interface.o \
|
||||
usbd_msc_storage.o \
|
||||
systick.o \
|
||||
pendsv.o \
|
||||
bufhelper.o \
|
||||
usb.o \
|
||||
@ -128,11 +128,18 @@ OBJ += $(addprefix $(BUILD)/$(MICROPY_DIR)/usbdev/,\
|
||||
|
||||
OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/,\
|
||||
main.o \
|
||||
systick.o\
|
||||
usbdbg.o\
|
||||
sccb.o\
|
||||
ov9650.o\
|
||||
ov2640.o\
|
||||
sensor.o\
|
||||
led.o \
|
||||
)
|
||||
|
||||
OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/py/,\
|
||||
py_led.o \
|
||||
py_sensor.o \
|
||||
)
|
||||
|
||||
###################################################
|
||||
|
||||
@ -1,11 +1,21 @@
|
||||
# Sources
|
||||
SRCS += $(addprefix ./,\
|
||||
SRCS += $(addprefix ,\
|
||||
main.c\
|
||||
systick.c\
|
||||
usbdbg.c\
|
||||
sccb.c\
|
||||
ov9650.c\
|
||||
ov2640.c\
|
||||
sensor.c\
|
||||
led.c\
|
||||
)
|
||||
|
||||
SRCS += $(addprefix ./py/,\
|
||||
SRCS += $(addprefix img/,\
|
||||
)
|
||||
|
||||
SRCS += $(addprefix py/,\
|
||||
py_led.c\
|
||||
py_sensor.c\
|
||||
)
|
||||
|
||||
OBJS = $(addprefix $(BUILD)/, $(SRCS:.c=.o))
|
||||
|
||||
@ -1,38 +1,27 @@
|
||||
#include <stm32f4xx_hal.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
#include "timer.h"
|
||||
#include "pincfg.h"
|
||||
#include "led.h"
|
||||
#include "pin.h"
|
||||
#include "genhdr/pins.h"
|
||||
|
||||
STATIC const pin_obj_t *led_objs[] = {
|
||||
&MICROPY_HW_LED1,
|
||||
&MICROPY_HW_LED2,
|
||||
&MICROPY_HW_LED3,
|
||||
/* LED GPIOs */
|
||||
static const gpio_t led_pincfg[] = {
|
||||
{PINCFG_LED_PORT, PINCFG_LED_RED_PIN},
|
||||
{PINCFG_LED_PORT, PINCFG_LED_GREEN_PIN},
|
||||
{PINCFG_LED_PORT, PINCFG_LED_BLUE_PIN},
|
||||
};
|
||||
#define NUM_LEDS ARRAY_SIZE(led_objs)
|
||||
#define NUM_LEDS (sizeof(led_pincfg)/sizeof(led_pincfg[0]))
|
||||
|
||||
void led_init()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* Configure LED pins in output mode */
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
|
||||
|
||||
/* Initialize LEDS */
|
||||
for (int led = 0; led<NUM_LEDS; led++) {
|
||||
const pin_obj_t *led_pin = led_objs[led];
|
||||
MICROPY_HW_LED_OFF(led_pin);
|
||||
GPIO_InitStructure.Pin = led_pin->pin_mask;
|
||||
HAL_GPIO_Init(led_pin->gpio, &GPIO_InitStructure);
|
||||
for (int i=0; i<NUM_LEDS; i++) {
|
||||
PINCFG_LED_OFF(led_pincfg[i]);
|
||||
GPIO_InitStructure.Pin = led_pincfg[i].pin;
|
||||
HAL_GPIO_Init(led_pincfg[i].port, &GPIO_InitStructure);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,10 +30,10 @@ void led_state(enum led_id id, int state)
|
||||
if (id < NUM_LEDS) {
|
||||
if (state) {
|
||||
/* turn on LED */
|
||||
MICROPY_HW_LED_ON(led_objs[id]);
|
||||
PINCFG_LED_ON(led_pincfg[id]);
|
||||
} else {
|
||||
/* turn off LED */
|
||||
MICROPY_HW_LED_OFF(led_objs[id]);
|
||||
PINCFG_LED_OFF(led_pincfg[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,5 +41,5 @@ void led_state(enum led_id id, int state)
|
||||
void led_toggle(enum led_id id)
|
||||
{
|
||||
/* Invert LED state */
|
||||
HAL_GPIO_TogglePin(led_objs[id]->gpio, led_objs[id]->pin_mask);
|
||||
HAL_GPIO_TogglePin(led_pincfg[id].port, led_pincfg[id].pin);
|
||||
}
|
||||
|
||||
@ -29,10 +29,16 @@
|
||||
#include "sdcard.h"
|
||||
#include "ff.h"
|
||||
#include "lcd.h"
|
||||
#include "mdefs.h"
|
||||
|
||||
#include "usbdbg.h"
|
||||
|
||||
#include "led.h"
|
||||
#include "py_led.h"
|
||||
|
||||
#include "sensor.h"
|
||||
#include "py_sensor.h"
|
||||
|
||||
int errno;
|
||||
static FATFS fatfs0;
|
||||
//static FATFS fatfs1;
|
||||
@ -53,12 +59,8 @@ void __fatal_error(const char *msg) {
|
||||
stdout_tx_strn("\nFATAL ERROR:\n", 14);
|
||||
stdout_tx_strn(msg, strlen(msg));
|
||||
for (uint i = 0;;) {
|
||||
led_toggle(((i++) & 3) + 1);
|
||||
for (volatile uint delay = 0; delay < 10000000; delay++) {
|
||||
}
|
||||
if (i >= 16) {
|
||||
// to conserve power
|
||||
__WFI();
|
||||
led_toggle(((i++) & 3));
|
||||
for (volatile uint delay = 0; delay < 500000; delay++) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -110,8 +112,11 @@ MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode);
|
||||
|
||||
static const char fresh_main_py[] =
|
||||
"# main.py -- put your code here!\n"
|
||||
"import led\n"
|
||||
"import led, sensor\n"
|
||||
"led.on(led.BLUE)\n"
|
||||
"sensor.set_pixformat(sensor.RGB565)\n"
|
||||
"while (True):\n"
|
||||
" image = sensor.snapshot()\n"
|
||||
;
|
||||
|
||||
static const char fresh_pybcdc_inf[] =
|
||||
@ -139,7 +144,7 @@ typedef struct {
|
||||
} module_t;
|
||||
|
||||
static const module_t exported_modules[] ={
|
||||
//{MP_QSTR_sensor,py_sensor_init},
|
||||
{MP_QSTR_sensor,py_sensor_init},
|
||||
{MP_QSTR_led, py_led_init},
|
||||
// {MP_QSTR_time, py_time_init},
|
||||
// {MP_QSTR_gpio, py_gpio_init},
|
||||
@ -164,6 +169,7 @@ int main(void) {
|
||||
__GPIOB_CLK_ENABLE();
|
||||
__GPIOC_CLK_ENABLE();
|
||||
__GPIOD_CLK_ENABLE();
|
||||
__GPIOE_CLK_ENABLE();
|
||||
|
||||
// enable the CCM RAM
|
||||
__CCMDATARAMEN_CLK_ENABLE();
|
||||
@ -227,24 +233,6 @@ soft_reset:
|
||||
pin_init();
|
||||
extint_init();
|
||||
|
||||
/* Add functions to the global python namespace */
|
||||
// mp_store_global(qstr_from_str("open"), mp_make_function_n(2, py_file_open));
|
||||
// mp_store_global(qstr_from_str("vcp_connected"), mp_make_function_n(0, py_vcp_connected));
|
||||
// mp_store_global(qstr_from_str("info"), mp_make_function_n(0, py_info));
|
||||
// mp_store_global(qstr_from_str("gc_collect"), mp_make_function_n(0, py_gc_collect));
|
||||
// mp_store_global(qstr_from_str("Image"), mp_make_function_n(1, py_image_load_image));
|
||||
// mp_store_global(qstr_from_str("HaarCascade"), mp_make_function_n(1, py_image_load_cascade));
|
||||
|
||||
/* Export Python modules to the global python namespace */
|
||||
for (const module_t *p = exported_modules; p->name; p++) {
|
||||
const mp_obj_module_t *module = p->init();
|
||||
if (module == NULL) {
|
||||
__fatal_error("failed to init module");
|
||||
} else {
|
||||
mp_module_register(p->name, (mp_obj_t)module);
|
||||
}
|
||||
}
|
||||
|
||||
// local filesystem init
|
||||
// try to mount the flash
|
||||
FRESULT res = f_mount(&fatfs0, "0:", 1);
|
||||
@ -345,10 +333,31 @@ soft_reset:
|
||||
|
||||
timer_init0();
|
||||
|
||||
usbdbg_init();
|
||||
|
||||
#if MICROPY_HW_ENABLE_RNG
|
||||
//rng_init0();
|
||||
#endif
|
||||
|
||||
/* Add functions to the global python namespace */
|
||||
// mp_store_global(qstr_from_str("open"), mp_make_function_n(2, py_file_open));
|
||||
// mp_store_global(qstr_from_str("vcp_connected"), mp_make_function_n(0, py_vcp_connected));
|
||||
// mp_store_global(qstr_from_str("info"), mp_make_function_n(0, py_info));
|
||||
// mp_store_global(qstr_from_str("gc_collect"), mp_make_function_n(0, py_gc_collect));
|
||||
// mp_store_global(qstr_from_str("Image"), mp_make_function_n(1, py_image_load_image));
|
||||
// mp_store_global(qstr_from_str("HaarCascade"), mp_make_function_n(1, py_image_load_cascade));
|
||||
|
||||
/* Export Python modules to the global python namespace */
|
||||
for (const module_t *p = exported_modules; p->name; p++) {
|
||||
const mp_obj_module_t *module = p->init();
|
||||
if (module == NULL) {
|
||||
__fatal_error("failed to init module");
|
||||
} else {
|
||||
mp_module_register(p->name, (mp_obj_t)module);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now that everything is initialised, run main script
|
||||
if (reset_mode == 1 && pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
|
||||
vstr_t *vstr = vstr_new();
|
||||
@ -367,17 +376,21 @@ soft_reset:
|
||||
vstr_free(vstr);
|
||||
}
|
||||
|
||||
// enter REPL
|
||||
// Enter REPL
|
||||
// REPL mode can change, or it can request a soft reset
|
||||
nlr_buf_t nlr;
|
||||
for (;;) {
|
||||
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
|
||||
if (pyexec_raw_repl() != 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (pyexec_friendly_repl() != 0) {
|
||||
break;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
if (usbdbg_script_ready()) {
|
||||
pyexec_push_scope();
|
||||
pyexec_str(usbdbg_get_script());
|
||||
pyexec_pop_scope();
|
||||
}
|
||||
usbdbg_clr_script();
|
||||
|
||||
// no script run repl
|
||||
pyexec_friendly_repl();
|
||||
nlr_pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,17 +1,12 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stm32f4xx_tim.h>
|
||||
#include <stm32f4xx_i2c.h>
|
||||
#include <stm32f4xx_gpio.h>
|
||||
#include <stm32f4xx_rcc.h>
|
||||
#include <stm32f4xx_dma.h>
|
||||
#include <stm32f4xx_misc.h>
|
||||
#include <stm32f4xx_dcmi.h>
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "sccb.h"
|
||||
#include "ov2640.h"
|
||||
#include "systick.h"
|
||||
#include "ov2640_regs.h"
|
||||
|
||||
#define DSP_FRAME_W (800)
|
||||
#define DSP_FRAME_H (600)
|
||||
|
||||
@ -405,9 +400,9 @@ static int set_gainceiling(enum sensor_gainceiling gainceiling)
|
||||
int ov2640_init(struct sensor_dev *sensor)
|
||||
{
|
||||
/* set HSYNC/VSYNC/PCLK polarity */
|
||||
sensor->vsync_pol = DCMI_VSPolarity_Low;
|
||||
sensor->hsync_pol = DCMI_HSPolarity_Low;
|
||||
sensor->pixck_pol = DCMI_PCKPolarity_Rising;
|
||||
sensor->vsync_pol = DCMI_VSPOLARITY_LOW;
|
||||
sensor->hsync_pol = DCMI_HSPOLARITY_LOW;
|
||||
sensor->pixck_pol = DCMI_PCKPOLARITY_RISING;
|
||||
|
||||
/* set function pointers */
|
||||
sensor->reset = reset;
|
||||
|
||||
@ -1,13 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stm32f4xx_tim.h>
|
||||
#include <stm32f4xx_i2c.h>
|
||||
#include <stm32f4xx_gpio.h>
|
||||
#include <stm32f4xx_rcc.h>
|
||||
#include <stm32f4xx_dma.h>
|
||||
#include <stm32f4xx_misc.h>
|
||||
#include <stm32f4xx_dcmi.h>
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "sccb.h"
|
||||
#include "ov9650.h"
|
||||
#include "systick.h"
|
||||
@ -35,7 +29,7 @@ static const uint8_t default_regs[][2] = {
|
||||
{REG_COM15, 0xD0}, /* Output range 0x00-0xFF/RGB565*/
|
||||
|
||||
/* YUV fmt /Special Effects Controls */
|
||||
{REG_TSLB, 0x01}, /* YUVU/DBLC Enable/Bitwise reverse*/
|
||||
{REG_TSLB, 0x01}, /* YUYV/DBLC Enable/Bitwise reverse*/
|
||||
{REG_MANU, 0x80}, /* Manual U */
|
||||
{REG_MANV, 0x80}, /* Manual V */
|
||||
|
||||
@ -345,9 +339,9 @@ static int set_gainceiling(enum sensor_gainceiling gainceiling)
|
||||
int ov9650_init(struct sensor_dev *sensor)
|
||||
{
|
||||
/* set HSYNC/VSYNC/PCLK polarity */
|
||||
sensor->vsync_pol = DCMI_VSPolarity_High;
|
||||
sensor->hsync_pol = DCMI_HSPolarity_Low;
|
||||
sensor->pixck_pol = DCMI_PCKPolarity_Rising;
|
||||
sensor->vsync_pol = DCMI_VSPOLARITY_HIGH;
|
||||
sensor->hsync_pol = DCMI_HSPOLARITY_LOW;
|
||||
sensor->pixck_pol = DCMI_PCKPOLARITY_RISING;
|
||||
|
||||
/* set function pointers */
|
||||
sensor->reset = reset;
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
#include <libmp.h>
|
||||
#include "xalloc.h"
|
||||
#include "mp.h"
|
||||
#include "imlib.h"
|
||||
#include "array.h"
|
||||
#include "sensor.h"
|
||||
#include "py_image.h"
|
||||
#include "py_assert.h"
|
||||
#include "py_file.h"
|
||||
#include "py_image.h"
|
||||
|
||||
extern struct sensor_dev sensor;
|
||||
static const mp_obj_type_t py_cascade_type;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#include <libmp.h>
|
||||
#include "mp.h"
|
||||
#include "sensor.h"
|
||||
#include "sccb.h"
|
||||
#include "py_sensor.h"
|
||||
#include "py_image.h"
|
||||
#include "py_sensor.h"
|
||||
|
||||
static mp_obj_t py_sensor_reset() {
|
||||
sensor_reset();
|
||||
@ -15,9 +15,11 @@ static mp_obj_t py_sensor_reset() {
|
||||
}
|
||||
|
||||
static mp_obj_t py_sensor_snapshot() {
|
||||
mp_obj_t image = py_image(0, 0, 0, 0);
|
||||
sensor_snapshot((struct image*) py_image_cobj(image));
|
||||
return image;
|
||||
// mp_obj_t image = py_image(0, 0, 0, 0);
|
||||
// sensor_snapshot((struct image*) py_image_cobj(image));
|
||||
// return image;
|
||||
sensor_snapshot(0);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
static mp_obj_t py_sensor_set_pixformat(mp_obj_t pixformat) {
|
||||
|
||||
230
src/omv/sccb.c
230
src/omv/sccb.c
@ -1,215 +1,77 @@
|
||||
#include "sccb.h"
|
||||
#include <stm32f4xx_rcc.h>
|
||||
#include <stm32f4xx_gpio.h>
|
||||
#include <stm32f4xx_syscfg.h>
|
||||
#include <stm32f4xx_misc.h>
|
||||
#include <stm32f4xx_i2c.h>
|
||||
#include "pincfg.h"
|
||||
#include "mdefs.h"
|
||||
|
||||
/* I2C defs */
|
||||
#define I2Cx I2C1
|
||||
#define I2C_CLOCK RCC_APB1Periph_I2C1
|
||||
#define I2C_FREQ (30000)
|
||||
#define I2C_SLAVE_ADDR (0x60)
|
||||
#define I2C_MAX_TIMEOUT (10000)
|
||||
|
||||
/* I2C GPIO defs */
|
||||
#define I2C_GPIO_PORT GPIOB
|
||||
#define I2C_GPIO_CLOCK RCC_AHB1Periph_GPIOB
|
||||
#define I2C_GPIO_AF GPIO_AF_I2C1
|
||||
#define I2C_GPIO_SCL_PIN GPIO_Pin_8
|
||||
#define I2C_GPIO_SDA_PIN GPIO_Pin_9
|
||||
#define I2C_GPIO_SCL_SRC GPIO_PinSource8
|
||||
#define I2C_GPIO_SDA_SRC GPIO_PinSource9
|
||||
#define SCCB_FREQ (30000)
|
||||
#define SLAVE_ADDR (0x60)
|
||||
#define TIMEOUT (100000)
|
||||
static I2C_HandleTypeDef I2CHandle;
|
||||
|
||||
void SCCB_Init()
|
||||
{
|
||||
I2C_InitTypeDef I2C_InitStruct;
|
||||
/* Enable I2C clock */
|
||||
PINCFG_SCCB_CLK_ENABLE();
|
||||
|
||||
/* Configure SCCB GPIOs */
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStructure.Alternate = PINCFG_SCCB_AF;
|
||||
|
||||
/* Enable I2C/GPIO clocks */
|
||||
RCC_APB1PeriphClockCmd(I2C_CLOCK, ENABLE);
|
||||
RCC_AHB1PeriphClockCmd(I2C_GPIO_CLOCK, ENABLE);
|
||||
GPIO_InitStructure.Pin = PINCFG_SCCB_SCL_PIN;
|
||||
HAL_GPIO_Init(PINCFG_SCCB_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Connect I2C GPIOs to AF4 */
|
||||
GPIO_PinAFConfig(I2C_GPIO_PORT, I2C_GPIO_SCL_SRC, I2C_GPIO_AF);
|
||||
GPIO_PinAFConfig(I2C_GPIO_PORT, I2C_GPIO_SDA_SRC, I2C_GPIO_AF);
|
||||
GPIO_InitStructure.Pin = PINCFG_SCCB_SDA_PIN;
|
||||
HAL_GPIO_Init(PINCFG_SCCB_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Configure I2C GPIOs */
|
||||
GPIO_InitStructure.GPIO_Pin = I2C_GPIO_SCL_PIN|I2C_GPIO_SDA_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(I2C_GPIO_PORT, &GPIO_InitStructure);
|
||||
/* Configure I2C */
|
||||
I2CHandle.Instance = PINCFG_SCCB_I2C;
|
||||
I2CHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
I2CHandle.Init.ClockSpeed = SCCB_FREQ;
|
||||
I2CHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
|
||||
I2CHandle.Init.DutyCycle = I2C_DUTYCYCLE_2;
|
||||
I2CHandle.Init.GeneralCallMode = I2C_GENERALCALL_ENABLED;
|
||||
I2CHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
|
||||
I2CHandle.Init.OwnAddress1 = 0xFE;
|
||||
I2CHandle.Init.OwnAddress2 = 0xFE;
|
||||
|
||||
/* Configure I2Cx */
|
||||
I2C_DeInit(I2Cx);
|
||||
|
||||
/* Set the I2C structure parameters */
|
||||
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
|
||||
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
|
||||
I2C_InitStruct.I2C_OwnAddress1 = 0xFE;
|
||||
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
|
||||
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
||||
I2C_InitStruct.I2C_ClockSpeed = 30000;
|
||||
|
||||
/* Initialize the I2C peripheral w/ selected parameters */
|
||||
I2C_Init(I2Cx, &I2C_InitStruct);
|
||||
|
||||
/* Enable the I2C peripheral */
|
||||
I2C_Cmd(I2Cx, ENABLE);
|
||||
if (HAL_I2C_Init(&I2CHandle) != HAL_OK) {
|
||||
/* Initialization Error */
|
||||
BREAK();
|
||||
}
|
||||
}
|
||||
|
||||
void SCCB_DeInit()
|
||||
{
|
||||
/* Disable the I2C peripheral */
|
||||
I2C_Cmd(I2Cx, DISABLE);
|
||||
|
||||
/* DeInit I2C registers */
|
||||
I2C_DeInit(I2Cx);
|
||||
|
||||
/* Disable I2C clock */
|
||||
RCC_APB1PeriphClockCmd(I2C_CLOCK, ENABLE);
|
||||
HAL_I2C_DeInit(&I2CHandle);
|
||||
PINCFG_SCCB_CLK_DISABLE();
|
||||
}
|
||||
|
||||
uint8_t SCCB_Write(uint8_t addr, uint8_t data)
|
||||
{
|
||||
volatile uint32_t timeout = I2C_MAX_TIMEOUT;
|
||||
|
||||
/* Generate the Start Condition */
|
||||
I2C_GenerateSTART(I2Cx, ENABLE);
|
||||
|
||||
/* Test on I2Cx EV5 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
uint8_t buf[] = {addr, data};
|
||||
while (HAL_I2C_GetState(&I2CHandle) != HAL_I2C_STATE_READY);
|
||||
if (HAL_I2C_Master_Transmit(&I2CHandle, SLAVE_ADDR, buf, 2, TIMEOUT) != HAL_OK) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
/* Send DCMI selcted device slave Address for write */
|
||||
I2C_Send7bitAddress(I2Cx, I2C_SLAVE_ADDR, I2C_Direction_Transmitter);
|
||||
|
||||
/* Test on I2Cx EV6 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
}
|
||||
|
||||
/* Send I2Cx location address LSB */
|
||||
I2C_SendData(I2Cx, (uint8_t)(addr));
|
||||
|
||||
/* Test on I2Cx EV8 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
}
|
||||
|
||||
/* Send Data */
|
||||
I2C_SendData(I2Cx, data);
|
||||
|
||||
/* Test on I2Cx EV8 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
}
|
||||
|
||||
/* Send I2Cx STOP Condition */
|
||||
I2C_GenerateSTOP(I2Cx, ENABLE);
|
||||
|
||||
/* If operation is OK, return 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t SCCB_Read(uint8_t addr)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
volatile uint32_t timeout = I2C_MAX_TIMEOUT;
|
||||
uint8_t data=0;
|
||||
HAL_StatusTypeDef st;
|
||||
|
||||
/* Generate the Start Condition */
|
||||
I2C_GenerateSTART(I2Cx, ENABLE);
|
||||
|
||||
/* Test on I2Cx EV5 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
while (HAL_I2C_GetState(&I2CHandle) != HAL_I2C_STATE_READY);
|
||||
if (HAL_I2C_Master_Transmit(&I2CHandle, SLAVE_ADDR, &addr, 1, TIMEOUT) != HAL_OK) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
/* Send DCMI selcted device slave Address for write */
|
||||
I2C_Send7bitAddress(I2Cx, I2C_SLAVE_ADDR, I2C_Direction_Transmitter);
|
||||
|
||||
/* Test on I2Cx EV6 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
while (HAL_I2C_GetState(&I2CHandle) != HAL_I2C_STATE_READY);
|
||||
if (HAL_I2C_Master_Receive(&I2CHandle, SLAVE_ADDR, &data, 1, TIMEOUT) != HAL_OK) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
/* Send I2Cx location address LSB */
|
||||
I2C_SendData(I2Cx, (uint8_t)(addr));
|
||||
|
||||
/* Test on I2Cx EV8 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
}
|
||||
|
||||
/* Prepare Stop after receiving data */
|
||||
I2C_GenerateSTOP(I2Cx, ENABLE);
|
||||
|
||||
/* Clear AF flag if arised */
|
||||
I2Cx->SR1 |= (uint16_t)0x0400;
|
||||
|
||||
/* Generate the Start Condition */
|
||||
I2C_GenerateSTART(I2Cx, ENABLE);
|
||||
|
||||
/* Test on I2Cx EV6 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
}
|
||||
|
||||
/* Send DCMI selcted device slave Address for write */
|
||||
I2C_Send7bitAddress(I2Cx, I2C_SLAVE_ADDR, I2C_Direction_Receiver);
|
||||
|
||||
/* Test on I2Cx EV6 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
}
|
||||
|
||||
/* Prepare an NACK for the next data received */
|
||||
I2C_AcknowledgeConfig(I2Cx, DISABLE);
|
||||
|
||||
/* Test on I2Cx EV7 and clear it */
|
||||
timeout = I2C_MAX_TIMEOUT; /* Initialize timeout value */
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
|
||||
{
|
||||
/* If the timeout delay is exeeded, exit with error code */
|
||||
if ((timeout--) == 0) return 0xFF;
|
||||
}
|
||||
|
||||
/* Prepare Stop after receiving data */
|
||||
I2C_GenerateSTOP(I2Cx, ENABLE);
|
||||
|
||||
/* Receive the Data */
|
||||
data = I2C_ReceiveData(I2Cx);
|
||||
|
||||
/* return the read data */
|
||||
return data;
|
||||
}
|
||||
|
||||
472
src/omv/sensor.c
472
src/omv/sensor.c
@ -1,17 +1,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stm32f4xx_tim.h>
|
||||
#include <stm32f4xx_i2c.h>
|
||||
#include <stm32f4xx_gpio.h>
|
||||
#include <stm32f4xx_rcc.h>
|
||||
#include <stm32f4xx_dma.h>
|
||||
#include <stm32f4xx_misc.h>
|
||||
#include <stm32f4xx_dcmi.h>
|
||||
#include "sccb.h"
|
||||
#include "ov9650.h"
|
||||
#include "ov2640.h"
|
||||
#include "systick.h"
|
||||
#include "sensor.h"
|
||||
#include "pincfg.h"
|
||||
#include "framebuffer.h"
|
||||
|
||||
#define REG_PID 0x0A
|
||||
@ -22,11 +16,34 @@
|
||||
|
||||
#define OV9650_PID 0x96
|
||||
#define OV2640_PID 0x26
|
||||
#define BREAK() __asm__ volatile ("BKPT")
|
||||
#define DCMI_DR_ADDRESS (DCMI_BASE + 0x28)
|
||||
#define BREAK() __asm__ volatile ("BKPT")
|
||||
|
||||
struct sensor_dev sensor;
|
||||
static volatile int frame_ready = 0;
|
||||
TIM_HandleTypeDef TIMHandle;
|
||||
DMA_HandleTypeDef DMAHandle;
|
||||
DCMI_HandleTypeDef DCMIHandle;
|
||||
|
||||
/* DCMI GPIOs */
|
||||
static const gpio_t dcmi_pins[] = {
|
||||
{DCMI_D0_PORT, DCMI_D0_PIN},
|
||||
{DCMI_D1_PORT, DCMI_D1_PIN},
|
||||
{DCMI_D2_PORT, DCMI_D2_PIN},
|
||||
{DCMI_D3_PORT, DCMI_D3_PIN},
|
||||
{DCMI_D4_PORT, DCMI_D4_PIN},
|
||||
{DCMI_D5_PORT, DCMI_D5_PIN},
|
||||
{DCMI_D6_PORT, DCMI_D6_PIN},
|
||||
{DCMI_D7_PORT, DCMI_D7_PIN},
|
||||
{DCMI_HSYNC_PORT, DCMI_HSYNC_PIN},
|
||||
{DCMI_VSYNC_PORT, DCMI_VSYNC_PIN},
|
||||
{DCMI_PXCLK_PORT, DCMI_PXCLK_PIN},
|
||||
};
|
||||
|
||||
#define NUM_PINS (sizeof(dcmi_pins)/sizeof(dcmi_pins[0]))
|
||||
#define RESET_LOW() HAL_GPIO_WritePin(DCMI_RESET_PORT, DCMI_RESET_PIN, GPIO_PIN_RESET)
|
||||
#define RESET_HIGH() HAL_GPIO_WritePin(DCMI_RESET_PORT, DCMI_RESET_PIN, GPIO_PIN_SET)
|
||||
|
||||
#define PWDN_LOW() HAL_GPIO_WritePin(DCMI_PWDN_PORT, DCMI_PWDN_PIN, GPIO_PIN_RESET)
|
||||
#define PWDN_HIGH() HAL_GPIO_WritePin(DCMI_PWDN_PORT, DCMI_PWDN_PIN, GPIO_PIN_SET)
|
||||
|
||||
const int res_width[] = {
|
||||
88, /* QQCIF */
|
||||
@ -48,47 +65,6 @@ const int res_height[]= {
|
||||
1024, /* SXGA */
|
||||
};
|
||||
|
||||
/* IRQ Handlers */
|
||||
void DCMI_IRQHandler(void)
|
||||
{
|
||||
if (DCMI_GetITStatus(DCMI_IT_VSYNC)) {
|
||||
DCMI_ClearITPendingBit(DCMI_IT_VSYNC);
|
||||
} else if (DCMI_GetITStatus(DCMI_IT_LINE)) {
|
||||
DCMI_ClearITPendingBit(DCMI_IT_LINE);
|
||||
} else if (DCMI_GetITStatus(DCMI_IT_FRAME)) {
|
||||
DCMI_ClearITPendingBit(DCMI_IT_FRAME);
|
||||
BREAK();
|
||||
} else if (DCMI_GetITStatus(DCMI_IT_OVF)) {
|
||||
DCMI_ClearITPendingBit(DCMI_IT_OVF);
|
||||
BREAK();
|
||||
} else if (DCMI_GetITStatus(DCMI_IT_ERR)) {
|
||||
DCMI_ClearITPendingBit(DCMI_IT_ERR);
|
||||
BREAK();
|
||||
}
|
||||
}
|
||||
|
||||
void DMA2_Stream1_IRQHandler(void)
|
||||
{
|
||||
/* DMA Transfer Complete Interrupt */
|
||||
if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1)) {
|
||||
/* clear DMA TCIF pending interrupt */
|
||||
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
|
||||
/* set frame ready flag */
|
||||
frame_ready = 1;
|
||||
} else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_HTIF1)) {
|
||||
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_HTIF1);
|
||||
} else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TEIF1)) {
|
||||
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TEIF1);
|
||||
BREAK();
|
||||
} else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_DMEIF1)) {
|
||||
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_DMEIF1);
|
||||
BREAK();
|
||||
} else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_FEIF1)) {
|
||||
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_FEIF1);
|
||||
BREAK();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TIM1 input clock (TIM1CLK) is set to 2 * APB2 clock (PCLK2)
|
||||
TIM1CLK = 2 * PCLK2 (PCLK2 = HCLK / 2)
|
||||
@ -107,251 +83,157 @@ void DMA2_Stream1_IRQHandler(void)
|
||||
*/
|
||||
static void extclk_config(int frequency)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
RCC_ClocksTypeDef RCC_Clocks;
|
||||
/* TCLK (PCLK2 * 2) */
|
||||
int tclk = HAL_RCC_GetPCLK2Freq() * 2;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
|
||||
|
||||
/* TIM channel GPIO configuration */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
|
||||
/* Connect TIM pins to AF */
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_TIM1);
|
||||
|
||||
/* Read Core Clocks */
|
||||
RCC_GetClocksFreq(&RCC_Clocks);
|
||||
|
||||
/* set TCLK to HCLK (PCLK2 * 2) */
|
||||
int tclk = RCC_Clocks.PCLK2_Frequency * 2;
|
||||
|
||||
/* No prescalar */
|
||||
int prescaler = (uint16_t) (RCC_Clocks.SYSCLK_Frequency / tclk) - 1;
|
||||
/* SYSCLK/TCLK = No prescaler */
|
||||
int prescaler = (uint16_t) (HAL_RCC_GetSysClockFreq()/ tclk) - 1;
|
||||
|
||||
/* Period should be even */
|
||||
int period = (tclk / frequency)-1;
|
||||
|
||||
/* Time base configuration */
|
||||
TIM_TimeBaseStructure.TIM_Period = period;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
|
||||
//TODO move to MSP
|
||||
/* Timer GPIO configuration */
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.Pin = DCMI_TIM_PIN;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStructure.Alternate = DCMI_TIM_AF;
|
||||
HAL_GPIO_Init(DCMI_TIM_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* PWM1 Mode configuration: Channel2 */
|
||||
TIM_OCInitStructure.TIM_Pulse = period/2;
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
|
||||
/* Enable DCMI timer clock */
|
||||
DCMI_TIM_CLK_ENABLE();
|
||||
|
||||
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
|
||||
TIM_ARRPreloadConfig(TIM1, ENABLE);
|
||||
/* Timer base configuration */
|
||||
TIMHandle.Instance = DCMI_TIM;
|
||||
TIMHandle.Init.Period = period;
|
||||
TIMHandle.Init.Prescaler = prescaler;
|
||||
TIMHandle.Init.ClockDivision = 0;
|
||||
TIMHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
|
||||
/* TIM1 enable counter */
|
||||
TIM_Cmd(TIM1, ENABLE);
|
||||
TIM_CtrlPWMOutputs(TIM1, ENABLE);
|
||||
/* Timer channel configuration */
|
||||
TIM_OC_InitTypeDef TIMOCHandle;
|
||||
TIMOCHandle.Pulse = period/2;
|
||||
TIMOCHandle.OCMode = TIM_OCMODE_PWM1;
|
||||
TIMOCHandle.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||
TIMOCHandle.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
TIMOCHandle.OCIdleState = TIM_OCIDLESTATE_RESET;
|
||||
if (HAL_TIM_PWM_Init(&TIMHandle) != HAL_OK) {
|
||||
/* Initialization Error */
|
||||
BREAK();
|
||||
}
|
||||
|
||||
if (HAL_TIM_PWM_ConfigChannel(&TIMHandle, &TIMOCHandle, DCMI_TIM_CHANNEL) != HAL_OK) {
|
||||
BREAK();
|
||||
}
|
||||
if (HAL_TIM_PWM_Start(&TIMHandle, DCMI_TIM_CHANNEL) != HAL_OK) {
|
||||
BREAK();
|
||||
}
|
||||
}
|
||||
|
||||
static int dcmi_config()
|
||||
{
|
||||
DCMI_InitTypeDef DCMI_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
/* DCMI clock enable */
|
||||
__DCMI_CLK_ENABLE();
|
||||
|
||||
/*** DCMI GPIO configuration ***/
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE |
|
||||
RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE);
|
||||
/* Connect DCMI pins to AF13 */
|
||||
/* D0..D7 */
|
||||
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
|
||||
/* DCMI GPIOs configuration */
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStructure.Alternate = GPIO_AF13_DCMI;
|
||||
|
||||
/* VSYNC, HSYNC, PCLK */
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);
|
||||
for (int i=0; i<NUM_PINS; i++) {
|
||||
GPIO_InitStructure.Pin = dcmi_pins[i].pin;
|
||||
HAL_GPIO_Init(dcmi_pins[i].port, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
/* DCMI GPIO configuration */
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
|
||||
//GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
|
||||
/* DCMI configuration */
|
||||
DCMIHandle.Instance = DCMI;
|
||||
DCMIHandle.Init.VSPolarity = sensor.vsync_pol; /* VSYNC clock polarity */
|
||||
DCMIHandle.Init.HSPolarity = sensor.hsync_pol; /* HSYNC clock polarity */
|
||||
DCMIHandle.Init.PCKPolarity = sensor.pixck_pol; /* PXCLK clock polarity */
|
||||
DCMIHandle.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE; /* Enable Hardware synchronization */
|
||||
DCMIHandle.Init.CaptureRate = DCMI_CR_ALL_FRAME; /* Capture rate all frames */
|
||||
DCMIHandle.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B; /* Capture 8 bits on every pixel clock */
|
||||
DCMIHandle.Init.JPEGMode = DCMI_JPEG_DISABLE; /* Disable JPEG Mode */
|
||||
|
||||
/* D0,D1 (PC6/7) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
/* Associate the DMA handle to the DCMI handle */
|
||||
__HAL_LINKDMA(&DCMIHandle, DMA_Handle, DMAHandle);
|
||||
|
||||
/* D2,D3,D4,D6,D7 (E0/1/4/5/6) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |
|
||||
GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
|
||||
GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
/* Configure and enable DCMI IRQ Channel */
|
||||
HAL_NVIC_SetPriority(DCMI_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(DCMI_IRQn);
|
||||
|
||||
/* D5,VSYNC (PB6/7) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
/* HSYNC,PCLK (PA4/6) */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/*** DCMI Configuration ***/
|
||||
DCMI_DeInit();
|
||||
DCMI_Cmd(DISABLE);
|
||||
|
||||
/* Enable DCMI clock */
|
||||
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
|
||||
|
||||
/* Configure capture mode SnapShot/Continuous */
|
||||
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot;
|
||||
|
||||
/* Hardware synchronization via VSYNC/HSYNC/PCLK lines */
|
||||
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
|
||||
|
||||
/* Active VS/HS clocks*/
|
||||
DCMI_InitStructure.DCMI_VSPolarity = sensor.vsync_pol;
|
||||
DCMI_InitStructure.DCMI_HSPolarity = sensor.hsync_pol;
|
||||
|
||||
/* Sample data on rising edge of PCK */
|
||||
DCMI_InitStructure.DCMI_PCKPolarity = sensor.pixck_pol;
|
||||
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
|
||||
|
||||
/* Capture 8 bits on every pixel clock */
|
||||
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
|
||||
/* Init DCMI */
|
||||
DCMI_Init(&DCMI_InitStructure);
|
||||
|
||||
#if 0
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
|
||||
/* Configure DCMI Interrupts */
|
||||
DCMI_ITConfig(DCMI_IT_OVF, ENABLE);
|
||||
DCMI_ITConfig(DCMI_IT_ERR, ENABLE);
|
||||
//DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);
|
||||
//DCMI_ITConfig(DCMI_IT_LINE, ENABLE);
|
||||
//DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE);
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
#endif
|
||||
|
||||
/* Enable DCMI Perphieral */
|
||||
DCMI_Cmd(ENABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dma_config(uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
|
||||
/* Enable DMA2 clock */
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
|
||||
|
||||
DMA_DeInit(DMA2_Stream1);
|
||||
DMA_Cmd(DMA2_Stream1, DISABLE);
|
||||
|
||||
/* DMA2 Stream1 Configuration */
|
||||
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
|
||||
|
||||
/* DMA direction peripheral to memory */
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
|
||||
/* Number of data items to be transferred in multiples of (Mburst beat*(Msize)/(Psize))*/
|
||||
DMA_InitStructure.DMA_BufferSize = size/4;
|
||||
|
||||
/* Base memory and peripheral addresses */
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) buffer;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
|
||||
|
||||
/* Memory and peripheral address increments */
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
|
||||
/* Set Msize and Psize to one word */
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
|
||||
|
||||
/* Configure circular mode for DMA buffer */
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||
|
||||
/* Enable FIFO with threshold of 16 bytes */
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
|
||||
/* Set burst mode, Mburst is 4 beats (16 bytes each) */
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
|
||||
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
|
||||
|
||||
/* Enable DMA interrupts */
|
||||
DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE);
|
||||
// DMA_ITConfig(DMA2_Stream1, DMA_IT_HT, ENABLE);
|
||||
// DMA_ITConfig(DMA2_Stream1, DMA_IT_TE, ENABLE);
|
||||
// DMA_ITConfig(DMA2_Stream1, DMA_IT_FE, ENABLE);
|
||||
|
||||
/* DMA Stream enable */
|
||||
DMA_Cmd(DMA2_Stream1, ENABLE);
|
||||
|
||||
int dma_timeout = 10000;
|
||||
while ((DMA_GetCmdStatus(DMA2_Stream1) != ENABLE) && (--dma_timeout > 0));
|
||||
|
||||
if (dma_timeout == 0) {
|
||||
if (HAL_DCMI_Init(&DCMIHandle) != HAL_OK) {
|
||||
/* Initialization Error */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Enable the DMA Stream IRQ Channel */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
__HAL_DCMI_DISABLE_IT(&DCMIHandle, DCMI_IT_LINE);
|
||||
__HAL_DCMI_DISABLE_IT(&DCMIHandle, DCMI_IT_VSYNC);
|
||||
__HAL_DCMI_DISABLE_IT(&DCMIHandle, DCMI_IT_ERR);
|
||||
__HAL_DCMI_DISABLE_IT(&DCMIHandle, DCMI_IT_OVF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dma_config()
|
||||
{
|
||||
/* Enable DMA2 clock */
|
||||
__DMA2_CLK_ENABLE();
|
||||
|
||||
/* DMA Stream configuration */
|
||||
DMAHandle.Instance = DMA2_Stream1; /* Select the DMA instance */
|
||||
DMAHandle.Init.Channel = DMA_CHANNEL_1; /* DMA Channel */
|
||||
DMAHandle.Init.Direction = DMA_PERIPH_TO_MEMORY; /* Peripheral to memory transfer */
|
||||
DMAHandle.Init.MemInc = DMA_MINC_ENABLE; /* Memory increment mode Enable */
|
||||
DMAHandle.Init.PeriphInc = DMA_PINC_DISABLE; /* Peripheral increment mode Enable */
|
||||
DMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; /* Peripheral data alignment : Word */
|
||||
DMAHandle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; /* Memory data alignment : Word */
|
||||
DMAHandle.Init.Mode = DMA_CIRCULAR; /* Circular DMA mode */
|
||||
DMAHandle.Init.Priority = DMA_PRIORITY_HIGH; /* Priority level : high */
|
||||
DMAHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; /* FIFO mode enabled */
|
||||
DMAHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; /* FIFO threshold full */
|
||||
DMAHandle.Init.MemBurst = DMA_MBURST_SINGLE; /* Memory burst */
|
||||
DMAHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; /* Peripheral burst */
|
||||
|
||||
/* Configure and enable DMA IRQ Channel */
|
||||
HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
|
||||
|
||||
/* Initialize the DMA stream */
|
||||
if (HAL_DMA_Init(&DMAHandle) != HAL_OK) {
|
||||
/* Initialization Error */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sensor_init()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
|
||||
|
||||
/* RESET/PWDN GPIO configuration */
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStructure.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
|
||||
|
||||
/* Configure the RESET GPIO pin */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
/* RESET */
|
||||
GPIO_InitStructure.Pin = DCMI_RESET_PIN;
|
||||
HAL_GPIO_Init(DCMI_RESET_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Configure the PWDN GPIO pin */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
/* PWDN */
|
||||
GPIO_InitStructure.Pin = DCMI_PWDN_PIN;
|
||||
HAL_GPIO_Init(DCMI_PWDN_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Do a power cycle */
|
||||
GPIO_SetBits(GPIOB, GPIO_Pin_5);
|
||||
systick_sleep(100);
|
||||
PWDN_HIGH();
|
||||
systick_sleep(10);
|
||||
|
||||
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
|
||||
PWDN_LOW();
|
||||
systick_sleep(100);
|
||||
|
||||
/* Initialize the SCCB interface */
|
||||
@ -371,10 +253,10 @@ int sensor_init()
|
||||
register with both polarities to determine line state. */
|
||||
sensor.reset_pol = ACTIVE_HIGH;
|
||||
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
RESET_HIGH();
|
||||
systick_sleep(10);
|
||||
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
RESET_LOW();
|
||||
systick_sleep(10);
|
||||
|
||||
/* Check if we can read PID */
|
||||
@ -382,10 +264,10 @@ int sensor_init()
|
||||
/* Sensor is held in reset, so reset is active high */
|
||||
sensor.reset_pol = ACTIVE_LOW;
|
||||
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
RESET_LOW();
|
||||
systick_sleep(10);
|
||||
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
RESET_HIGH();
|
||||
systick_sleep(10);
|
||||
}
|
||||
|
||||
@ -408,9 +290,16 @@ int sensor_init()
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure the DCMI DMA Stream */
|
||||
if (dma_config() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure the DCMI interface. This should be called
|
||||
after ovxxx_init to set VSYNC/HSYNC/PCLK polarities */
|
||||
dcmi_config();
|
||||
if (dcmi_config() != 0){
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -425,17 +314,17 @@ int sensor_reset()
|
||||
/* Hard reset the sensor */
|
||||
switch (sensor.reset_pol) {
|
||||
case ACTIVE_HIGH:
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
RESET_HIGH();
|
||||
systick_sleep(10);
|
||||
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
RESET_LOW();
|
||||
systick_sleep(10);
|
||||
break;
|
||||
case ACTIVE_LOW:
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
RESET_LOW();
|
||||
systick_sleep(10);
|
||||
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
RESET_HIGH();
|
||||
systick_sleep(10);
|
||||
break;
|
||||
}
|
||||
@ -457,30 +346,25 @@ int sensor_write_reg(uint8_t reg, uint8_t val)
|
||||
|
||||
int sensor_snapshot(struct image *image)
|
||||
{
|
||||
/* clear frame_ready flag */
|
||||
frame_ready = 0;
|
||||
/* Enable the Frame capture complete interrupt */
|
||||
__HAL_DCMI_ENABLE_IT(&DCMIHandle, DCMI_IT_FRAME);
|
||||
|
||||
/* re-enable DCMI interface */
|
||||
DCMI_CaptureCmd(ENABLE);
|
||||
HAL_DCMI_Start_DMA(&DCMIHandle, DCMI_MODE_SNAPSHOT, (uint32_t) fb->pixels, (fb->w * fb->h * 2)/4);
|
||||
|
||||
/* wait for dma transfer to finish */
|
||||
while (!frame_ready);
|
||||
|
||||
/* wait for DCMI to be disabled */
|
||||
while (DCMI->CR & DCMI_CR_CAPTURE);
|
||||
/* Wait for frame */
|
||||
while (HAL_DCMI_GetState(&DCMIHandle) == HAL_DCMI_STATE_BUSY);
|
||||
|
||||
if (sensor.pixformat == PIXFORMAT_GRAYSCALE) {
|
||||
int i;
|
||||
/* extract Y channel */
|
||||
for (i=0; i<(fb->w * fb->h); i++) {
|
||||
fb->pixels[i] = fb->pixels[i*2+(fb->w * fb->h)];
|
||||
/* Extract Y channel from YUYV */
|
||||
for (int i=0; i<(fb->w * fb->h); i++) {
|
||||
fb->pixels[i] = fb->pixels[i*2];
|
||||
}
|
||||
}
|
||||
|
||||
image->w = fb->w;
|
||||
image->h = fb->h;
|
||||
image->bpp = fb->bpp;
|
||||
image->pixels = fb->pixels;
|
||||
// image->w = fb->w;
|
||||
// image->h = fb->h;
|
||||
// image->bpp = fb->bpp;
|
||||
// image->pixels = fb->pixels;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -514,12 +398,6 @@ int sensor_set_pixformat(enum sensor_pixformat pixformat)
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pixformat==PIXFORMAT_GRAYSCALE) {
|
||||
dma_config(fb->pixels+(fb->w * fb->h), fb->w * fb->h * 2);
|
||||
} else {
|
||||
dma_config(fb->pixels, fb->w * fb->h * 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -558,9 +436,6 @@ int sensor_set_framesize(enum sensor_framesize framesize)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Reconfigure the DMA stream */
|
||||
dma_config(fb->pixels, fb->w * fb->h * 2);
|
||||
|
||||
#if 0
|
||||
/* This enables croping use it to test bigger frames */
|
||||
DCMI_CROPCmd(DISABLE);
|
||||
@ -628,5 +503,6 @@ int sensor_set_gainceiling(enum sensor_gainceiling gainceiling)
|
||||
|
||||
int get_bytes()
|
||||
{
|
||||
return DMA_GetCurrDataCounter(DMA2_Stream1);
|
||||
// return DMA_GetCurrDataCounter(DMA2_Stream1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -74,9 +74,9 @@ extern const int res_height[];
|
||||
|
||||
struct sensor_dev {
|
||||
struct sensor_id id;
|
||||
uint16_t vsync_pol;
|
||||
uint16_t hsync_pol;
|
||||
uint16_t pixck_pol;
|
||||
uint32_t vsync_pol;
|
||||
uint32_t hsync_pol;
|
||||
uint32_t pixck_pol;
|
||||
enum reset_polarity reset_pol;
|
||||
enum sensor_pixformat pixformat;
|
||||
enum sensor_framesize framesize;
|
||||
|
||||
@ -1,82 +1,26 @@
|
||||
#include <stdlib.h>
|
||||
#include <stm32f4xx_hal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stm32f4xx.h>
|
||||
#include <stm32f4xx_misc.h>
|
||||
#include "xalloc.h"
|
||||
#include "systick.h"
|
||||
#include "array.h"
|
||||
static volatile uint32_t sys_ticks;
|
||||
//static struct array *task_list;
|
||||
|
||||
struct systick_task {
|
||||
task_cb cb;
|
||||
uint32_t period;
|
||||
};
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
// int i;
|
||||
// struct systick_task *task;
|
||||
|
||||
++sys_ticks;
|
||||
|
||||
#if 0
|
||||
for (i=0; i<array_length(task_list); i++) {
|
||||
task = array_at(task_list, i);
|
||||
if ((sys_ticks % task->period)==0) {
|
||||
task->cb();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int systick_init()
|
||||
{
|
||||
/* Allocate task_list array */
|
||||
//array_alloc(&task_list, xfree);
|
||||
|
||||
/* Configure systick to interrupt every 1ms */
|
||||
if (SysTick_Config(SystemCoreClock / 1000)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set SysTick IRQ to the highest priority */
|
||||
NVIC_SetPriority(SysTick_IRQn, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void systick_sleep(volatile uint32_t ms)
|
||||
{
|
||||
volatile uint32_t curr_ticks = sys_ticks;
|
||||
while ((sys_ticks - curr_ticks) < ms);
|
||||
volatile uint32_t curr_ticks = HAL_GetTick();
|
||||
while ((HAL_GetTick() - curr_ticks) < ms) {
|
||||
//__WFI();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t systick_current_millis()
|
||||
{
|
||||
return sys_ticks;
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
void systick_sched_task(task_cb cb, uint32_t period)
|
||||
bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms)
|
||||
{
|
||||
#if 0
|
||||
struct systick_task *task;
|
||||
|
||||
task = xalloc(sizeof(struct systick_task));
|
||||
task->cb = cb;
|
||||
task->period = period;
|
||||
array_push_back(task_list, task);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool systick_has_passed(uint32_t stc, uint32_t delay_ms) {
|
||||
// stc_wait is the value of sys_ticks that we wait for
|
||||
uint32_t stc_wait = stc + delay_ms;
|
||||
if (stc_wait < stc) {
|
||||
// stc_wait wrapped around
|
||||
return !(stc <= sys_ticks || sys_ticks < stc_wait);
|
||||
} else {
|
||||
// stc_wait did not wrap around
|
||||
return !(stc <= sys_ticks && sys_ticks < stc_wait);
|
||||
}
|
||||
systick_sleep(delay_ms);
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#ifndef __SYSTICK_H__
|
||||
#define __SYSTICK_H__
|
||||
typedef void (*task_cb) ();
|
||||
#include <stdint.h>
|
||||
int systick_init();
|
||||
void systick_sleep(uint32_t ms);
|
||||
uint32_t systick_current_millis();
|
||||
void systick_sched_task(task_cb cb, uint32_t period);
|
||||
bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms);
|
||||
#endif /* __SYSTICK_H__ */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user