/* 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 #include 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; static uint8_t IN_SECTION(.ccm.bss) inserted_counter = 0; if (sdio_check_inserted() && mounted) { memset(fs_ptr, 0, sizeof(FATFS)); sdio_stop_clk(); inserted_counter = 0; return false; } if (!sdio_check_inserted() && inserted_counter < 255) inserted_counter++; if (!sdio_check_inserted() && !mounted && inserted_counter > 4) { inserted_counter = 0; res = f_mount(fs_ptr, "0:/", 1); if (res == FR_OK) { led_set(1, 1); 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); } int main(void) { bool cal_active; float offset; float sens; int status; bool sd_card_mounted = false; bool sd_old; shellmatta_handle_t shell_handle; int menu_wait_request; uint64_t quarter_sec_timestamp = 0ULL; setup_system(); shell_handle = shell_init(write_shell_callback); shell_print_motd(shell_handle); while (1) { if (systick_ticks_have_passed(quarter_sec_timestamp, 250)) { led_set(1, 0); sd_old = sd_card_mounted; sd_card_mounted = mount_sd_card_if_avail(sd_card_mounted); if (sd_card_mounted && !sd_old) { adc_pt1000_get_resistance_calibration(NULL, NULL, &cal_active); if (!cal_active) { status = settings_load_calibration(&sens, &offset); if (!status) { adc_pt1000_set_resistance_calibration(offset, sens, true); } } } quarter_sec_timestamp = systick_get_global_tick(); } menu_wait_request = reflow_menu_handle(); handle_shell_uart_input(shell_handle); safety_controller_handle(); oven_driver_set_power(0); oven_driver_apply_power_level(); safety_controller_report_timing(ERR_TIMING_MAIN_LOOP); 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); }