Update sources to new HAL

This commit is contained in:
iabdalkader 2014-06-18 17:28:46 +02:00
parent 0e69ebad74
commit 1e4b6fa8fd
13 changed files with 334 additions and 644 deletions

View File

@ -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 \
)
###################################################

View File

@ -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))

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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__ */