/* Reflow Oven Controller * * Copyright (C) 2020 Mario Hüttel * * This file is part of the Reflow Oven Controller Project. * * The reflow oven controller is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * The Reflow Oven Control Firmware 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the reflow oven controller project. * If not, see . */ /** * @file main.c * @brief Main file for firmware */ #include #include #include #include /* #include */ #include #include #include #include #include #include #include #include "fatfs/shimatta_sdio_driver/shimatta_sdio.h" #include #include #include #include #include #include #include #include bool global_error_state; static void setup_nvic_priorities(void) { /* No sub priorities */ NVIC_SetPriorityGrouping(2); /* Setup Priorities */ NVIC_SetPriority(ADC_IRQn, 2); NVIC_SetPriority(DMA2_Stream0_IRQn, 1); NVIC_SetPriority(DMA2_Stream7_IRQn, 3); } FATFS fs; FATFS * const fs_ptr = &fs; static inline void uart_gpio_config(void) { /* * In case the application is build in debug mode, use the TX/RX Pins on the debug header * else the Pins on the DIGIO header are configured in the digio module */ #ifdef DEBUGBUILD rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(SHELL_UART_PORT_RCC_MASK)); SHELL_UART_PORT->MODER &= MODER_DELETE(SHELL_UART_TX_PIN) & MODER_DELETE(SHELL_UART_RX_PIN); SHELL_UART_PORT->MODER |= ALTFUNC(SHELL_UART_RX_PIN) | ALTFUNC(SHELL_UART_TX_PIN); SETAF(SHELL_UART_PORT, SHELL_UART_RX_PIN, SHELL_UART_RX_PIN_ALTFUNC); SETAF(SHELL_UART_PORT, SHELL_UART_TX_PIN, SHELL_UART_TX_PIN_ALTFUNC); /* Setup Pullup resistor at UART RX */ SHELL_UART_PORT->PUPDR |= PULLUP(SHELL_UART_RX_PIN); #endif } static char shell_uart_tx_buff[128]; static char shell_uart_rx_buff[48]; struct stm_uart shell_uart; static shellmatta_retCode_t write_shell_callback(const char *data, uint32_t len) { uart_send_array_with_dma(&shell_uart, data, len); return SHELLMATTA_OK; } static inline void setup_shell_uart(struct stm_uart *uart) { uart->rx = 1; uart->tx = 1; uart->brr_val = SHELL_UART_BRR_REG_VALUE; uart->rcc_reg = &SHELL_UART_RCC_REG; uart->rcc_bit_no = BITMASK_TO_BITNO(SHELL_UART_RCC_MASK); uart->uart_dev = SHELL_UART_PERIPH; uart->dma_rx_buff = shell_uart_rx_buff; uart->dma_tx_buff = shell_uart_tx_buff; uart->rx_buff_count = sizeof(shell_uart_rx_buff); uart->tx_buff_count = sizeof(shell_uart_tx_buff); uart->base_dma_num = 2; uart->dma_rx_stream = SHELL_UART_RECEIVE_DMA_STREAM; uart->dma_tx_stream = SHELL_UART_SEND_DMA_STREAM; uart->dma_rx_trigger_channel = SHELL_UART_RX_DMA_TRIGGER; uart->dma_tx_trigger_channel = SHELL_UART_TX_DMA_TRIGGER; uart_init(uart); NVIC_EnableIRQ(DMA2_Stream7_IRQn); } static bool mount_sd_card_if_avail(bool mounted) { FRESULT res; if (sdio_check_inserted() && mounted) { memset(fs_ptr, 0, sizeof(FATFS)); return false; } if (!sdio_check_inserted() && !mounted) { res = f_mount(fs_ptr, "0:/", 1); if (res == FR_OK) return true; else return false; } return mounted; } static void setup_unused_pins(void) { int i; rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_GPIOEEN)); GPIOE->MODER = 0UL; for (i = 0; i < 16; i++) GPIOE->PUPDR |= PULLDOWN(i); } static inline void setup_system(void) { setup_nvic_priorities(); systick_setup(); oven_driver_init(); digio_setup_default_all(); led_setup(); loudspeaker_setup(); reflow_menu_init(); uart_gpio_config(); setup_shell_uart(&shell_uart); setup_unused_pins(); safety_controller_init(); adc_pt1000_setup_meas(); } static void handle_shell_uart_input(shellmatta_handle_t shell_handle) { int uart_receive_status; const char *uart_input; size_t uart_input_len; /* Handle UART input for shell */ uart_receive_status = uart_receive_data_with_dma(&shell_uart, &uart_input, &uart_input_len); if (uart_receive_status >= 0) shell_handle_input(shell_handle, uart_input, uart_input_len); } static void zero_ccm_ram(void) { /* These extern variables are placed in the linker script */ extern char _sccmram; extern char _eccmram; uint32_t len; uint32_t i; uint32_t *ptr = (uint32_t *)&_sccmram; len = (uint32_t)&_eccmram - (uint32_t)&_sccmram; for (i = 0; i < len; i++) ptr[i] = 0UL; } int main(void) { bool sd_card_mounted = false; shellmatta_handle_t shell_handle; int menu_wait_request; uint64_t quarter_sec_timestamp = 0ULL; zero_ccm_ram(); setup_system(); global_error_state = false; shell_handle = shell_init(write_shell_callback); shell_print_motd(shell_handle); while (1) { sd_card_mounted = mount_sd_card_if_avail(sd_card_mounted); if (systick_ticks_have_passed(quarter_sec_timestamp, 250)) { quarter_sec_timestamp = systick_get_global_tick(); } menu_wait_request = reflow_menu_handle(); handle_shell_uart_input(shell_handle); safety_controller_handle(); oven_driver_apply_power_level(); if (menu_wait_request) __WFI(); else __NOP(); } return 0; } void sdio_wait_ms(uint32_t ms) { systick_wait_ms(ms); } void DMA2_Stream7_IRQHandler(void) { uint32_t hisr = DMA2->HISR; DMA2->HIFCR = hisr; if (hisr & DMA_HISR_TCIF7) uart_tx_dma_complete_int_callback(&shell_uart); }