/* 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 #include static void setup_nvic_priorities() { /* 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() { /* * 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); #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 inline int32_t handle_pid_controller(struct pid_controller *pid, float target_temperature, float current_temperature) { int32_t pid_out; pid_out = (int32_t)pid_sample(pid, target_temperature - current_temperature); /* Blink green LED */ led_set(1, !led_get(1)); return pid_out; } static void setup_unused_pins() { 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() { setup_nvic_priorities(); systick_setup(); adc_pt1000_setup_meas(); oven_driver_init(); digio_setup_default_all(); led_setup(); loudspeaker_setup(); reflow_menu_init(); safety_adc_init(); uart_gpio_config(); setup_shell_uart(&shell_uart); setup_unused_pins(); } 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); } extern char _sccmram; extern char _eccmram; static void zero_ccm_ram(void) { 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() { bool sd_card_mounted = false; shellmatta_handle_t shell_handle; int menu_wait_request; uint64_t quarter_sec_timestamp = 0ULL; enum safety_adc_check_result safety_adc_status; zero_ccm_ram(); setup_system(); 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)) { safety_adc_status = handle_safety_adc(); quarter_sec_timestamp = systick_get_global_tick(); } handle_shell_uart_input(shell_handle); menu_wait_request = reflow_menu_handle(); if (menu_wait_request) __WFI(); } } void sdio_wait_ms(uint32_t ms) { systick_wait_ms(ms); } void DMA2_Stream7_IRQHandler() { uint32_t hisr = DMA2->HISR; DMA2->HIFCR = hisr; if (hisr & DMA_HISR_TCIF7) { uart_tx_dma_complete_int_callback(&shell_uart); } }