#include #include /* * LED1 = GPIO_PIN_8 OUTPUT PUSH-PULL * LED CNF: 10 (3:1 2:0) * LED MODE: 00 (1:0 0:0) * * BTN * Input, PullDown, 10Mhz * MODE: 00 * CNF: 10 * * PORT GPIOC * RCC = 0x4002 1000 - 0x4002 13FF * GPIOC = 0x4001 1000 - 0x4001 13FF * GPIO PORT C RCC_APB2ENR 4 */ //inline constexpr uint32_t RCC_BASE = 0x40021000UL; //inline constexpr uint32_t RCC_CR_OFFSET = 0x000; //inline constexpr uint32_t RCC_CFGR_OFFSET = 0x004; inline constexpr uint32_t RCC_APB2ENR_OFFSET = 0x018; inline constexpr uint32_t RCC_APB1ENR_OFFSET = 0x01C; inline constexpr uint32_t RCC_APB2ENR_ADDR = (RCC_BASE + RCC_APB2ENR_OFFSET); inline constexpr uint32_t RCC_APB1ENR_ADDR = (RCC_BASE + RCC_APB1ENR_OFFSET); inline constexpr uint32_t RCC_CR_ADDR = (RCC_BASE + RCC_CR_OFFSET); inline constexpr uint32_t RCC_CFGR_ADDR = (RCC_BASE + RCC_CFGR_OFFSET); //inline constexpr uint32_t GPIOA_BASE = 0x40010800; //inline constexpr uint32_t GPIOC_BASE = 0x40011000; inline constexpr uint32_t GPIOX_CRL_OFFSET = 0x00; inline constexpr uint32_t GPIOX_CRH_OFFSET = 0x04; inline constexpr uint32_t GPIOX_IDR_OFFSET = 0x08; inline constexpr uint32_t GPIOX_ODR_OFFSET = 0x0C; inline constexpr uint32_t GPIOA_CRL = (GPIOA_BASE + GPIOX_CRL_OFFSET); inline constexpr uint32_t GPIOA_CRH = (GPIOA_BASE + GPIOX_CRH_OFFSET); inline constexpr uint32_t GPIOA_ODR = (GPIOA_BASE + GPIOX_ODR_OFFSET); inline constexpr uint32_t GPIOA_IDR = (GPIOA_BASE + GPIOX_IDR_OFFSET); inline constexpr uint32_t GPIOC_CRH = (GPIOC_BASE + GPIOX_CRH_OFFSET); inline constexpr uint32_t GPIOC_ODR = (GPIOC_BASE + GPIOX_ODR_OFFSET); inline constexpr unsigned long PC8 = 8; inline constexpr unsigned long PC9 = 9; inline constexpr unsigned long PA0 = 0; void SetBit(uint32_t value, uint32_t bit) { uint32_t* ptr_value = (uint32_t*)value; *ptr_value |= (1 << bit); } void UnsetBit(uint32_t value, uint32_t bit) { uint32_t* ptr_value = (uint32_t*)value; *ptr_value &= ~(1 << bit); } bool GetBit(uint32_t value, uint32_t bit) { uint32_t* ptr_value = (uint32_t*)value; return static_cast((*ptr_value >> bit) & 1); } void SetBit(uint32_t* value, uint32_t bit) { *value |= (1 << bit); } void UnsetBit(uint32_t* value, uint32_t bit) { *value &= ~(1 << bit); } bool GetBit(uint32_t* value, uint32_t bit) { return static_cast((*value >> bit) & 1); } // Clock /* * We wanna set PLL to 16Mhz (minimum). Maximum would be 24Mhz * For that we use HSI Clock divided by two (4 Mhz) as input * 16Mhz = (8Mhz / 2) * 4 * */ // INTERRUPTS /* * Setps: * - Configure GPIO to Input mode * - Use SYSCFG register to connect GPIO to an EXTI lin * - Confiure EXTI for a specific trigger (rising, falling, ...) * * Common Mistakes to Avoid: * - Forgetting enable SYSFG CLK * - Mapping Multiple Pins to same EXTI Line (for example PA1 and PB1) * - Not unmasking the line in EXTI Register * - Forgetting to do enable in NVIC * - Not clearing the pending bit in ISR -> infinite loop * * BTN is on GPIOA0 (PA0) * PA0 -> EXTI0 * EXTI_IMR Bit 0 auf 1 Setzen */ //inline constexpr uint32_t EXTI_BASE = 0x40010400; inline constexpr uint32_t EXTI_IMR = (EXTI_BASE + 0x00); inline constexpr uint32_t EXTI_EMR = (EXTI_BASE + 0x04); inline constexpr uint32_t EXTI_RTSR = (EXTI_BASE + 0x08); inline constexpr uint32_t EXTI_FTSR = (EXTI_BASE + 0x0C); inline constexpr uint32_t EXTI_SWIER = (EXTI_BASE + 0x10); inline constexpr uint32_t EXTI_PR = (EXTI_BASE + 0x14); extern "C" { static int ActiveBlink = 0; /* * Handles EXTI line interrupt for a given GPIO pin. */ void GPIO_IRQHandling(uint8_t PinNumber) { // clear the exti pr register corresponding to the pin number if (EXTI->PR & (1UL << PinNumber)) { // clear EXTI->PR |= (1UL << PinNumber); uint32_t *pGpioCOdr = (uint32_t*) GPIOC_ODR; GPIOC->ODR ^= (1 << PC9); if (ActiveBlink == 0) { ActiveBlink = 1; TIM2->ARR = 100; } else { ActiveBlink = 0; TIM2->ARR = 1000; } } } void EXTI0_IRQHandler(void) { GPIO_IRQHandling(PA0); } void TIM2_IRQHandler(void) { // Handle a timer 'update' interrupt event if (TIM2->SR & TIM_SR_UIF) { TIM2->SR &= ~(TIM_SR_UIF); // Toggle the LED output pin. GPIOC->ODR ^= (1 << PC8); } } } int main(void) { // Init system Clock uint32_t *pRccCfgr = (uint32_t*) RCC_CFGR_ADDR; //set PLLMUL to x4 UnsetBit(pRccCfgr, 18); SetBit(pRccCfgr, 19); UnsetBit(pRccCfgr, 20); UnsetBit(pRccCfgr, 21); //set PLLSRC to HSI oscillator / 2 UnsetBit(pRccCfgr, 16); uint32_t *pRccCr = (uint32_t*) RCC_CR_ADDR; //enable PLL clock SetBit(pRccCr, 24); //wait till PLL clock is ready while (!GetBit(pRccCr, 25)) {}; //Set PLL clock as system clock UnsetBit(pRccCfgr, 0); SetBit(pRccCfgr, 1); //wait till PLL clock is set as system clock while (!(GetBit(pRccCfgr, 3) && !GetBit(pRccCfgr, 2))) {} const auto coreClockHz = 16000000; // BUTTON INTERRUPT CFG //enable interrupt requests for interrupt line 0 uint32_t *pExtiIMR = (uint32_t*) EXTI_IMR; SetBit(pExtiIMR, 0); //enable rising trigger on interrupt line uint32_t *pExtiRTSR = (uint32_t*) EXTI_RTSR; SetBit(pExtiRTSR, 0); uint32_t *pExtiFTSR = (uint32_t*) EXTI_FTSR; UnsetBit(pExtiFTSR, 0); NVIC_SetPriority(EXTI0_IRQn, 0); NVIC_EnableIRQ(EXTI0_IRQn); // TIMER INTERRUPT CFG uint32_t *pRccApb1Enr = (uint32_t*) RCC_APB1ENR_ADDR; //Enable TIM2 SetBit(pRccApb1Enr, 0); //Disable TIM2 Counter TIM2->CR1 &= ~(TIM_CR1_CEN); //Reset TIM2 //SetBit(RCC->APB1RSTR, 0); //UnsetBit(RCC->APB1RSTR, 0); RCC->APB1RSTR |= (RCC_APB1RSTR_TIM2RST); RCC->APB1RSTR &= ~(RCC_APB1RSTR_TIM2RST); //Set TIM2 to count every millisecond TIM2->PSC = coreClockHz / 1000; // Reset timmer counter every 1000 counts (1 second) TIM2->ARR = 1000; // enable ARR register buffering, needed to change ARR counter on the fly TIM2->CR1 |= TIM_CR1_ARPE; // Send an update event to reset the timer and apply settings TIM2->EGR |= TIM_EGR_UG; // Enable interrupts on timer updates TIM2->DIER |= TIM_DIER_UIE; //SetBit(TIM2->DIER, TIM_DIER_UIE); //Enable TIM2 Counter TIM2->CR1 |= TIM_CR1_CEN; //SetBit(TIM2->CR1, TIM_CR1_CEN); //Activate Interrupts for TIM2 NVIC_SetPriority(TIM2_IRQn, 3); NVIC_EnableIRQ(TIM2_IRQn); uint32_t *pRccApb2Enr = (uint32_t*) RCC_APB2ENR_ADDR; // enalbe clock for GPIO Port A on APB2 *pRccApb2Enr |= (1 << 2); // enalbe clock for GPIO Port C on APB2 *pRccApb2Enr |= (1 << 4); //Configure LED 8 Pin as Output with Push-Pull Resistor uint32_t *pGpioCCrh = (uint32_t*) GPIOC_CRH; //Set LED MODE SetBit(pGpioCCrh, 0); UnsetBit(pGpioCCrh, 1); ////Set LED CNF UnsetBit(pGpioCCrh, 2); UnsetBit(pGpioCCrh, 3); //Configure LED 9 Pin as Output with Push-Pull Resistor //Set LED MODE SetBit(pGpioCCrh, 4); UnsetBit(pGpioCCrh, 5); ////Set LED CNF UnsetBit(pGpioCCrh, 6); UnsetBit(pGpioCCrh, 7); //Configure BTN Pin as Input with PullDown Resistor uint32_t *pGpioACrl = (uint32_t*) GPIOA_CRL; //Set BTN MODE UnsetBit(pGpioACrl, 0); UnsetBit(pGpioACrl, 1); //Set BTN CNF UnsetBit(pGpioACrl, 2); SetBit(pGpioACrl, 3); uint32_t *pGpioAIdr = (uint32_t*) GPIOA_IDR; uint32_t *pGpioCOdr = (uint32_t*) GPIOC_ODR; while(1) { //const auto buttonIsSet = GetBit(pGpioAIdr, 0); //auto DoBlink = static_cast(ActiveBlink); //SetBit(pGpioCOdr, PC8); //if (DoBlink) { // SetBit(pGpioCOdr, PC9); //} for (uint32_t i = 0; i < 500000; i++); //DoBlink = static_cast(ActiveBlink); //UnsetBit(pGpioCOdr, PC8); //if (DoBlink) { // UnsetBit(pGpioCOdr, PC9); //} for (uint32_t i = 0; i < 500000; i++); } return 0; } //#include //#include //#include //#include // //#include // ///* // * reserve PB11-PB15 for SPI2 // */ // //// STM32VL-Discovery green led - PC9 //#define BTN_PORT GPIOA //#define LED_PORT GPIOC //#define LED1_PIN GPIO_PIN_8 //#define LED2_PIN GPIO_PIN_9 //#define BTN_PIN GPIO_PIN_0 //#define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE // //#define LoRa_RESET_Pin GPIO_PIN_4 //#define LoRa_RESET_GPIO_Port GPIOC //#define LoRa_CS_Pin GPIO_PIN_5 //#define LoRa_CS_GPIO_Port GPIOC // //#include "commons.hpp" //#include "logging.hpp" //#include "rfm95.hpp" //#include "spi.hpp" // //extern uint8_t LoRa_buff[RH_RF95_FIFO_SIZE]; //extern SPI_HandleTypeDef hspi1; // //void print_version(void) { log::info("running PentaTrack v0.2.0"); } //void print_help(void); // //void loglevel_error(void) { log::set_loglevel(LogLevel::ERROR); } //void loglevel_info(void) { log::set_loglevel(LogLevel::INFO); } //void loglevel_debug(void) { log::set_loglevel(LogLevel::DEBUG); } // //template //class cmd_holder { // public: // typedef void (*functionPointerType)(void); // // using command_t = // std::tuple; // template // using command_array_t = std::array; // // template // constexpr cmd_holder(Args... command_list) // : commands{std::forward(command_list)...} {} // // constexpr functionPointerType get_func(std::string_view message) const { // for (const auto &[cmd_name, cmd_help, func] : commands) { // if (message == cmd_name) { // return func; // } // } // // return nullptr; // } // // void print_help() const { // log::info("Listing available commands:"); // for (const auto &[cmd_name, cmd_help, func] : commands) { // log::info("\t", cmd_name, " - ", cmd_help); // } // } // // private: // std::array commands; //}; // //static bool updated_main_buf = false; //static bool print_main_buf = false; //static buffer main_buffer{}; //static gps_data gps; // //void print_buf(void) { main_buffer.print(); } //void print_gps(void) { gps.print(); } //void print_buf_toggle(void) { print_main_buf = !print_main_buf; } // //class cmd_handler { // public: // static constexpr auto MaxCmdLength = 24; // using array_t = std::array; // using iterator_t = array_t::iterator; // using const_iterator_t = array_t::const_iterator; // // constexpr cmd_handler() : symbols{}, iterator{symbols.begin()} {} // // static cmd_handler &get() { // static auto c = cmd_handler{}; // return c; // }; // // void add_symbol(uint8_t symbol) { // *iterator = symbol; // iterator++; // if (iterator == symbols.end()) { // iterator = symbols.begin(); // } // } // // std::string_view get_current_cmd() const { // return {reinterpret_cast(symbols.data()), // static_cast( // std::distance(symbols.begin(), const_iterator_t{iterator}))}; // } // // bool exists() const { // return commands.get_func(get_current_cmd()) != nullptr; // } // // void execute() { // const auto current_cmd = get_current_cmd(); // log::debug("Try executing command: ", current_cmd); // const auto func = commands.get_func(current_cmd); // iterator = symbols.begin(); // // if (func == nullptr) { // log::info("Unknown Command: ", current_cmd); // log::info("Type 'help' to show available commands."); // return; // } // // func(); // } // // void queue_execution() { ShouldExecute = true; } // // void run() { // if (ShouldExecute) { // execute(); // ShouldExecute = false; // } // } // // void print_help_() const { commands.print_help(); } // // private: // static constexpr cmd_holder<8> commands{ // std::make_tuple("ver", "Prints current version.", &print_version), // std::make_tuple("error", "Set LogLevel to Error.", &loglevel_error), // std::make_tuple("info", "Set LogLevel to Info.", &loglevel_info), // std::make_tuple("debug", "Set LogLevel to Debug.", &loglevel_debug), // std::make_tuple("gps", "Prints captured gps data", &print_gps), // std::make_tuple("buf", "Prints uart2 buffer", &print_buf), // std::make_tuple("buft", "toggles continous printing of uart2 buffer", // &print_buf_toggle), // std::make_tuple("help", "Prints available commands", &print_help)}; // // array_t symbols; // iterator_t iterator; // bool ShouldExecute = false; //}; // //void print_help(void) { cmd_handler::get().print_help_(); } // //// This prevent name mangling for functions used in C/assembly files. //extern "C" { //void SysTick_Handler(void) { // HAL_IncTick(); // HAL_SYSTICK_IRQHandler(); //} // //void EXTI0_IRQHandler(void) //{ // /* USER CODE BEGIN EXTI0_IRQn 0 */ // // /* USER CODE END EXTI0_IRQn 0 */ // HAL_GPIO_EXTI_IRQHandler(BTN_PIN); // /* USER CODE BEGIN EXTI0_IRQn 1 */ // // /* USER CODE END EXTI0_IRQn 1 */ //} // //void USART2_IRQHandler(void) { // HAL_UART_IRQHandler(&gps_interface::s_UARTHandle); // HAL_UART_Receive_IT(&gps_interface::s_UARTHandle, uart_interface::get_buf(), // 1); //} // //void USART1_IRQHandler(void) { // HAL_UART_IRQHandler(&uart_interface::s_UARTHandle); // HAL_UART_Receive_IT(&uart_interface::s_UARTHandle, uart_interface::get_buf(), // 1); //} // //void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // if (huart == &gps_interface::s_UARTHandle) { // return; // } // // const uint8_t value = *uart_interface::get_buf(); // // if (value == '\r') { // cmd_handler::get().queue_execution(); // return; // } // // cmd_handler::get().add_symbol(value); //} // //void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { // // const uint8_t value = *gps_interface::get_buf(); // // gps_interface::write({reinterpret_cast(&value), 1}); //} // //void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { // // log::debug("DMA Callback"); // // HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); // if (main_buffer.copy_from(gps_interface::new_rx_buf, Size)) { // updated_main_buf = true; // } // HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); // // HAL_UARTEx_ReceiveToIdle_DMA(&gps_interface::s_UARTHandle, // gps_interface::new_rx_buf.data(), // gps_interface::new_rx_buf.size()); // __HAL_DMA_DISABLE_IT(&gps_interface::s_DMAHandle, DMA_IT_HT); //} // ///** // * @brief This function handles DMA1 channel6 global interrupt. // */ //void DMA1_Channel6_IRQHandler(void) { // /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */ // // /* USER CODE END DMA1_Channel6_IRQn 0 */ // HAL_DMA_IRQHandler(&gps_interface::s_DMAHandle); // // /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */ // // /* USER CODE END DMA1_Channel6_IRQn 1 */ //} //} // //void initGPIO() { // __HAL_RCC_GPIOC_CLK_ENABLE(); // __HAL_RCC_GPIOA_CLK_ENABLE(); // // //GPIO_InitTypeDef GPIO_Config2; // //GPIO_Config2.Mode = GPIO_MODE_INPUT; // //GPIO_Config2.Pull = GPIO_PULLDOWN; // //GPIO_Config2.Speed = GPIO_SPEED_FREQ_HIGH; // //GPIO_Config2.Pin = BTN_PIN; // // GPIO_InitTypeDef GPIO_Config2; // GPIO_Config2.Mode = GPIO_MODE_IT_FALLING; // GPIO_Config2.Pull = GPIO_PULLUP; // GPIO_Config2.Pin = BTN_PIN; // // GPIO_InitTypeDef GPIO_Config; // GPIO_Config.Mode = GPIO_MODE_OUTPUT_PP; // GPIO_Config.Pull = GPIO_NOPULL; // GPIO_Config.Speed = GPIO_SPEED_FREQ_HIGH; // GPIO_Config.Pin = LED1_PIN | LED2_PIN; // // GPIO_InitTypeDef GPIO_ConfigSPI; // GPIO_ConfigSPI.Mode = GPIO_MODE_OUTPUT_PP; // // GPIO_ConfigSPI.Pull = GPIO_NOPULL; // GPIO_ConfigSPI.Speed = GPIO_SPEED_FREQ_HIGH; // GPIO_ConfigSPI.Pin = LoRa_CS_Pin | LoRa_RESET_Pin; // // // bare metal init of led1: // // volatile uint32_t* CRH = reinterpret_cast(0x40011000 + // // 0x04); // //*CRH |= 0x3; // //*CRH &= (~0xC); // // HAL_GPIO_Init(LED_PORT, &GPIO_Config); // HAL_GPIO_Init(BTN_PORT, &GPIO_Config2); // HAL_GPIO_Init(LoRa_CS_GPIO_Port, &GPIO_ConfigSPI); // // HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); // // HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, // // GPIO_PIN_SET); //} // //extern "C" { //#include // //void start_interrupt() { // HAL_UARTEx_ReceiveToIdle_DMA(&gps_interface::s_UARTHandle, // gps_interface::new_rx_buf.data(), // gps_interface::new_rx_buf.size()); // __HAL_DMA_DISABLE_IT(&gps_interface::s_DMAHandle, DMA_IT_HT); // HAL_GPIOEx_EnableEventout(); //} // //void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { // if (GPIO_Pin == BTN_PIN) { // // Your interrupt handling code goes here // // For example, toggle an LED // HAL_GPIO_TogglePin(LED_PORT, LED1_PIN); // } //} // //} // //int main(void) { // HAL_Init(); // HAL_SYSTICK_Config(1); // initGPIO(); // // if (!log::init()) { // // toggle status led or something // } // log::set_loglevel(LogLevel::DEBUG); // log::info("logging Initialized"); // // //if (!MX_SPI1_Init()) { // // // toggle status led or something // //} // //HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); // //HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); // // HAL_NVIC_SetPriority(EXTI0_IRQn, 0 ,0); // HAL_NVIC_EnableIRQ(EXTI0_IRQn); // // while(1) { // HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_SET); // HAL_Delay(100); // HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET); // HAL_Delay(100); // } // // HAL_Delay(10); // // // log::debug("SPI1 Initialized."); // // log::debug("SPI1 Initialized."); // // // if (!gps_interface::init()) { // // log::error("UART2 Initialization failed, needed for GPS"); // // } else { // // log::debug("Uart2 Initialized"); // // } // // // log::debug("Initialization done."); // // // char OP_Mode = 0x01; // // char buff = 0x7F & OP_Mode; // // char res = 0; // // // HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET); // // [[maybe_unused]] auto result = // // HAL_SPI_Transmit(&hspi1, (uint8_t *)&buff, 1, 100); // // HAL_SPI_Receive(&hspi1, (uint8_t *)&res, 1, 100); // // HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); // // // // RF95_Init(); // // // HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET); // // // while (1) { // // cmd_handler::get().run(); // // // // gps_interface::write("TEST"); // // // RF95_setModeRx_Continuous(); // // // HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); // // // RF95_receive(LoRa_buff); // // // HAL_Delay(100); // // // HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); // // // HAL_Delay(100); // // // if (gps.is_valid()) { // // HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_SET); // // } // // // if (updated_main_buf) { // // updated_main_buf = false; // // gps.extract_gps_data(main_buffer); // // // if (print_main_buf) { // // updated_main_buf = !main_buffer.print(); // // } // // } // // // // std::string_view msg{reinterpret_cast(LoRa_buff)}; // // // log::info("Received Message"); // // // log::debug("Received Message"); // // // log::debug(msg); // // // // std::string_view foo{"Das ist ein test"}; // // // strcpy((char *)LoRa_buff, foo.data()); // // // // RF95_send(LoRa_buff); // // } // // return 0; //} //