From f5a3edc4c66e674f72a44f2baf6b523ebe636559 Mon Sep 17 00:00:00 2001 From: Julien Peeters Date: Thu, 10 Nov 2016 22:33:27 +0100 Subject: [PATCH] mutekh/boards: merge brain --- software/library/boards/board.build | 6 + software/library/boards/brain.c | 340 ++++++++++++++++++++++++++++ software/tests/brain_relay/Makefile | 2 + software/tests/brain_relay/config | 9 + software/tests/brain_relay/main.c | 30 +++ 5 files changed, 387 insertions(+) create mode 100644 software/library/boards/brain.c create mode 100644 software/tests/brain_relay/Makefile create mode 100644 software/tests/brain_relay/config create mode 100644 software/tests/brain_relay/main.c diff --git a/software/library/boards/board.build b/software/library/boards/board.build index 1d50ddf..d90d242 100644 --- a/software/library/boards/board.build +++ b/software/library/boards/board.build @@ -1,3 +1,9 @@ +%section bmaaa-brain + %inherit stm32-f107vc + + CONFIG_BMAAA + CONFIG_BMAAA_BOARD brain + %section bmaaa-pinky %inherit nrf51-xxac diff --git a/software/library/boards/brain.c b/software/library/boards/brain.c new file mode 100644 index 0000000..af6c0da --- /dev/null +++ b/software/library/boards/brain.c @@ -0,0 +1,340 @@ +/* + This file is part of MutekH. + + MutekH is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; version 2.1 of the + License. + + MutekH is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + . + + Copyright Julien Peeters (c) 2016 +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +/* CPU */ + +DEV_DECLARE_STATIC(cpu_dev, "cpu", DEVICE_FLAG_CPU, arm32m_drv, + DEV_STATIC_RES_ID(0, 0), + + DEV_STATIC_RES_FREQ(72000000, 1) +); + +/* GPIO A..E. */ +DEV_DECLARE_STATIC(gpio_dev, "gpio", 0, stm32_gpio_drv, + DEV_STATIC_RES_DEV_ICU("/cpu"), + DEV_STATIC_RES_IRQ(0, STM32_IRQ_EXTI0, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), + DEV_STATIC_RES_IRQ(1, STM32_IRQ_EXTI1, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), + DEV_STATIC_RES_IRQ(2, STM32_IRQ_EXTI2, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), + DEV_STATIC_RES_IRQ(3, STM32_IRQ_EXTI3, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), + DEV_STATIC_RES_IRQ(4, STM32_IRQ_EXTI4, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), + DEV_STATIC_RES_IRQ(5, STM32_IRQ_EXTI9_5, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), + DEV_STATIC_RES_IRQ(6, STM32_IRQ_EXTI15_10, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1) +); + +/* UART 4 */ +DEV_DECLARE_STATIC(uart2_dev, "uart4", 0, stm32_usart_drv, + DEV_STATIC_RES_MEM(STM32_UART4_ADDR, STM32_UART4_ADDR + STM32_UART4_SIZE), + + DEV_STATIC_RES_FREQ(72000000, 1), + + DEV_STATIC_RES_DEV_ICU("/cpu"), + DEV_STATIC_RES_IRQ(0, STM32_IRQ_UART4, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), + + DEV_STATIC_RES_DEV_PARAM("iomux", "/gpio"), + DEV_STATIC_RES_IOMUX("tx", 0, STM32_PC10, 0, 0), + DEV_STATIC_RES_IOMUX("rx", 0, STM32_PC11, 0, 0), + + DEV_STATIC_RES_UART(19200, 8, DEV_UART_PARITY_NONE, 1, 0, 0) +); + +/* UART 4 */ +DEV_DECLARE_STATIC(timer4_dev, "timer4", 0, stm32_timer_drv, + DEV_STATIC_RES_MEM(STM32_TIM4_ADDR, STM32_TIM4_ADDR + STM32_TIM4_SIZE), + + DEV_STATIC_RES_FREQ(72000000, 1), + + DEV_STATIC_RES_DEV_ICU("/cpu"), + DEV_STATIC_RES_IRQ(0, STM32_IRQ_TIM4, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), +); + +#include +#include +#include +#include + +#define __IO volatile + +struct stm32f1xx_flash_dev_s +{ + __IO uint32_t FLASH_ACR; + __IO uint32_t FLASH_KEYR; + __IO uint32_t FLASH_OPTKEYR; + __IO uint32_t FLASH_SR; + __IO uint32_t FLASH_CR; + __IO uint32_t FLASH_AR; + __IO uint32_t __reserved0; + __IO uint32_t FLASH_OBR; + __IO uint32_t FLASH_WRPR; +} __attribute__ ((packed)); + +#define STM32_FLASH_LAT_WS(n) ((n) & 0x7) + +void stm32_clock_init(void) +{ + uintptr_t a; + uint32_t x; + + __IO struct stm32f1xx_flash_dev_s *flash_dev = + (struct stm32f1xx_flash_dev_s *) 0x40022000; + + /* Disable interrupts. */ + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CIR_ADDR, 0); + + /* PLL OFF, PLLI2S OFF, HSE ON, HSI OFF. */ + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CR_ADDR, + endian_le32(STM32_RCC_CR_HSEON)); + + /* Wait for hse to stabilize. */ + do + { + x = endian_le32(cpu_mem_read_32(STM32_RCC_ADDR + STM32_RCC_CR_ADDR)); + } + while (!(x & STM32_RCC_CR_HSERDY)); + + /* Set PLL2 @ 40MHz and PLL3 @ 50MHz */ + x = 0; + STM32_RCC_CFGR2_PREDIV2_SET(x, 0x4 /* / 5 */); + STM32_RCC_CFGR2_PLL2MUL_SET(x, 0x6 /* x 8 */); + STM32_RCC_CFGR2_PLL3MUL_SET(x, 0x8 /* x 10 */); + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CFGR2_ADDR, endian_le32(x)); + + /* Enable PLL2 @ 40MHz */ + a = STM32_RCC_ADDR + STM32_RCC_CR_ADDR; + x = endian_le32(cpu_mem_read_32(a)); + STM32_RCC_CR_PLL2ON_SET(x, 1); + cpu_mem_write_32(a, endian_le32(x)); + + /* Wait for PLL2 to lock */ + do + { + x = endian_le32(cpu_mem_read_32(a)); + } + while (!(x & STM32_RCC_CR_PLL2RDY)); + + /* Enable PLL3 @ 50MHz */ + STM32_RCC_CR_PLL3ON_SET(x, 1); + cpu_mem_write_32(a, endian_le32(x)); + + /* Wait for PLL2 to lock */ + do + { + x = endian_le32(cpu_mem_read_32(a)); + } + while (!(x & STM32_RCC_CR_PLL3RDY)); + + /* Set PLL @ 72MHz as sink of PLL2 */ + x = endian_le32(cpu_mem_read_32(STM32_RCC_ADDR + STM32_RCC_CFGR2_ADDR)); + STM32_RCC_CFGR2_PREDIV1SRC_SET(x, 0x1 /* PLL2 */); + STM32_RCC_CFGR2_PREDIV1_SET(x, 0x4 /* / 5 */); + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CFGR2_ADDR, endian_le32(x)); + + x = endian_le32(cpu_mem_read_32(STM32_RCC_ADDR + STM32_RCC_CFGR_ADDR)); + STM32_RCC_CFGR_PLLSRC_SET(x, 0x1 /* PREDIV1 */); + STM32_RCC_CFGR_PLLMUL_SET(x, 0x7 /* x 9 */); + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CFGR_ADDR, endian_le32(x)); + + /* Enable PLL */ + a = STM32_RCC_ADDR + STM32_RCC_CR_ADDR; + x = endian_le32(cpu_mem_read_32(a)); + STM32_RCC_CR_PLLON_SET(x, 1); + cpu_mem_write_32(a, endian_le32(x)); + + /* Wait for PLL to lock */ + do + { + x = endian_le32(cpu_mem_read_32(a)); + } + while (!(x & STM32_RCC_CR_PLLRDY)); + + /* set wait cycles for the flash. */ + flash_dev->FLASH_ACR = STM32_FLASH_LAT_WS(2); + + /* Configure prescalers. */ + a = STM32_RCC_ADDR + STM32_RCC_CFGR_ADDR; + x = endian_le32(cpu_mem_read_32(a)); + STM32_RCC_CFGR_HPRE_SET(x, 0x0 /* / 1 */); /* 72MHZ */ + STM32_RCC_CFGR_PPRE1_SET(x, 0x1 /* / 2 */); /* 36MHZ */ + STM32_RCC_CFGR_PPRE2_SET(x, 0x0 /* / 1 */); /* 72MHz */ + + /* Use PLL-based clock path for the system clock. */ + STM32_RCC_CFGR_SW_SET(x, 0x2 /* PLL */); + + /* Set MCO clock source */ + STM32_RCC_CFGR_MCO_SET(x, 0x6 /* HSE */); + cpu_mem_write_32(a, endian_le32(x)); + + /* Wait for system clock to be sourced by the PLL. */ + do + { + x = endian_le32(cpu_mem_read_32(a)); + } + while (!(x & STM32_RCC_CFGR_SWS_PLL)); + + /* Enable all clock gates. */ + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_AHBENR_ADDR, -1); + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_APB1ENR_ADDR, -1); + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_APB2ENR_ADDR, -1); + + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_AHBRSTR_ADDR, -1); + cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_AHBRSTR_ADDR, 0); +} + +#include +#include + +enum shell_otoroshi_opts_e +{ + OTOROSHI_OPT_RELAY = 0x1, + OTOROSHI_OPT_STATE = 0x2, + OTOROSHI_OPT_CLOSED = 0x4, + OTOROSHI_OPT_OPEN = 0x8, + OTOROSHI_OPT_PULSE = 0x10, + OTOROSHI_OPT_DELAY = 0x20, +}; + +struct termui_optctx_otoroshi_opts +{ + uint8_t relay; + bool_t state; + size_t delay; +}; + +static TERMUI_CON_COMMAND_PROTOTYPE(shell_otoroshi_relay) +{ + struct termui_optctx_otoroshi_opts * c = ctx; + + struct device_timer_s timer; + dev_timer_delay_t msec; + + struct device_gpio_s gpio; + + error_t err = 0; + + err = device_get_accessor_by_path(&gpio.base, NULL, "/gpio", DRIVER_CLASS_GPIO); + if (err) + return err; + + err = device_get_accessor_by_path(&timer.base, NULL, "/timer*", DRIVER_CLASS_TIMER); + if (err) + goto gpio_cleanup; + + err = dev_timer_init_sec(&timer, &msec, 0, 1, 1000); + if (err) + goto timer_cleanup; + + DEVICE_OP(&gpio, set_output, STM32_PE8, STM32_PE15, dev_gpio_mask0, dev_gpio_mask0); + DEVICE_OP(&gpio, set_mode, STM32_PE8, STM32_PE15, dev_gpio_mask1, DEV_PIN_PUSHPULL); + + if (used & OTOROSHI_OPT_PULSE) + { + uint8_t id = STM32_PE8 + c->relay * 2; + + static uint8_t door_open_mask[1] = { 0x2 }; + static uint8_t door_close_mask[1] = { 0x1 }; + + DEVICE_OP(&gpio, set_output, id, id + 1, door_open_mask, door_open_mask); + dev_timer_wait_delay(&timer, msec * 100, 0); + DEVICE_OP(&gpio, set_output, id, id, dev_gpio_mask0, dev_gpio_mask0); + + dev_timer_wait_delay(&timer, msec * c->delay, 0); + + DEVICE_OP(&gpio, set_output, id, id + 1, door_close_mask, door_close_mask); + dev_timer_wait_delay(&timer, msec * 100, 0); + DEVICE_OP(&gpio, set_output, id, id, dev_gpio_mask0, dev_gpio_mask0); + } + else + { + bool_t state = 0; + + if (used & OTOROSHI_OPT_STATE) + state = c->state; + else if (used & OTOROSHI_OPT_CLOSED) + state = 0; + else if (used & OTOROSHI_OPT_OPEN) + state = 1; + + uint8_t id = STM32_PE8 + c->relay * 2 + state; + DEVICE_OP(&gpio, set_output, id, id, dev_gpio_mask1, dev_gpio_mask1); + dev_timer_wait_delay(&timer, msec * 100, 0); + DEVICE_OP(&gpio, set_output, id, id, dev_gpio_mask0, dev_gpio_mask0); + } + +timer_cleanup: + device_put_accessor(&timer.base); +gpio_cleanup: + device_put_accessor(&gpio.base); + return err; +} + +static TERMUI_CON_OPT_DECL(otoroshi_opts) = +{ + TERMUI_CON_OPT_INTEGER_RANGE_ENTRY("-r", "--relay", OTOROSHI_OPT_RELAY, + struct termui_optctx_otoroshi_opts, relay, 1, 0, 3, + TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_RELAY, 0)) + + TERMUI_CON_OPT_INTEGER_RANGE_ENTRY("-s", "--state", OTOROSHI_OPT_STATE, + struct termui_optctx_otoroshi_opts, state, 1, 0, 1, + TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_STATE, OTOROSHI_OPT_RELAY)) + + TERMUI_CON_OPT_ENTRY("-c", "--closed", OTOROSHI_OPT_CLOSED, + TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN | OTOROSHI_OPT_STATE, + OTOROSHI_OPT_RELAY)) + + TERMUI_CON_OPT_ENTRY("-o", "--open", OTOROSHI_OPT_OPEN, + TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN | OTOROSHI_OPT_STATE, + OTOROSHI_OPT_RELAY)) + + TERMUI_CON_OPT_ENTRY("-p", "--pulse", OTOROSHI_OPT_PULSE, + TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN | OTOROSHI_OPT_STATE | OTOROSHI_OPT_PULSE, + OTOROSHI_OPT_RELAY)) + + TERMUI_CON_OPT_INTEGER_ENTRY("-d", "--delay", OTOROSHI_OPT_DELAY, + struct termui_optctx_otoroshi_opts, delay, 1, + TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN | OTOROSHI_OPT_STATE | OTOROSHI_OPT_DELAY, + OTOROSHI_OPT_RELAY | OTOROSHI_OPT_PULSE)) + + TERMUI_CON_LIST_END +}; + +static TERMUI_CON_GROUP_DECL(shell_otoroshi_subgroup) = +{ + TERMUI_CON_ENTRY(shell_otoroshi_relay, "relay", + TERMUI_CON_OPTS_CTX(otoroshi_opts, OTOROSHI_OPT_RELAY, + OTOROSHI_OPT_STATE | OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN + | OTOROSHI_OPT_PULSE | OTOROSHI_OPT_DELAY, NULL)) + + TERMUI_CON_LIST_END +}; + +MUTEK_SHELL_ROOT_GROUP(shell_otoroshi_subgroup, "otoroshi"); diff --git a/software/tests/brain_relay/Makefile b/software/tests/brain_relay/Makefile new file mode 100644 index 0000000..5e5dfd3 --- /dev/null +++ b/software/tests/brain_relay/Makefile @@ -0,0 +1,2 @@ + +objs += main.o diff --git a/software/tests/brain_relay/config b/software/tests/brain_relay/config new file mode 100644 index 0000000..e201545 --- /dev/null +++ b/software/tests/brain_relay/config @@ -0,0 +1,9 @@ + %set OUTPUT_NAME bmaaa-brain + %append MODULES $(OUTPUT_NAME):$(CONFIGPATH) + + CONFIG_LICENSE_APP_BSD + + %include bmaaa.build + + CONFIG_PTHREAD + CONFIG_PTHREAD_MAIN diff --git a/software/tests/brain_relay/main.c b/software/tests/brain_relay/main.c new file mode 100644 index 0000000..789286b --- /dev/null +++ b/software/tests/brain_relay/main.c @@ -0,0 +1,30 @@ +#include +#include + +#include + +#define FIRST STM32_PE8 +#define LAST STM32_PE15 + +static struct device_gpio_s gpio; +static struct device_timer_s timer; + +static dev_timer_delay_t msec; + +static uint8_t brain_gpio_init_mask[] = { 0x55, 0x55 }; + +void main() +{ + printk("bmaaa: brain firmware started!\n"); + + ensure(!device_get_accessor_by_path(&gpio.base, NULL, "/gpio", DRIVER_CLASS_GPIO)); + ensure(!device_get_accessor_by_path(&timer.base, NULL, "/timer4", DRIVER_CLASS_TIMER)); + + ensure(!dev_timer_init_sec(&timer, &msec, 0, 1, 1000)); + + DEVICE_OP(&gpio, set_output, FIRST, LAST, brain_gpio_init_mask, dev_gpio_mask0); + DEVICE_OP(&gpio, set_mode, FIRST, LAST, dev_gpio_mask1, DEV_PIN_PUSHPULL); + dev_timer_wait_delay(&timer, msec * 100, 0); + DEVICE_OP(&gpio, set_output, FIRST, LAST, dev_gpio_mask0, dev_gpio_mask0); +} + -- GitLab