You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dvmfirmware-hs/SerialSTM.cpp

321 lines
8.1 KiB

// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2016 Jim McLaughlin, KI6ZUM
* Copyright (C) 2016,2017,2018,2019 Andy Uribe, CA6JAU
* Copyright (C) 2021,2022,2024 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "SerialPort.h"
#include "STM_UART.h"
#if defined(STM32F10X_MD)
#include <stm32f10x_flash.h>
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
#define STM32_CNF_PAGE_ADDR (uint32_t)0x0800FC00
#define STM32_CNF_PAGE ((uint32_t *)0x0800FC00)
/*
Pin definitions:
- Host communication:
1) USART1 - TXD PA9 - RXD PA10
2) USB VCOM
- Serial repeater
USART2 - TXD PA2 - RXD PA3
*/
#if defined(STM32_USART1_HOST) || defined(SERIAL_REPEATER_USART1)
// ---------------------------------------------------------------------------
// Global Functions and Variables
// ---------------------------------------------------------------------------
extern "C" {
void USART1_IRQHandler();
void USART2_IRQHandler();
}
// ---------------------------------------------------------------------------
// UART1
// ---------------------------------------------------------------------------
static STM_UART m_USART1;
/**
* @brief Helper to handle the USART1 IRQ.
*/
void USART1_IRQHandler()
{
m_USART1.handleIRQ();
}
/**
* @brief Initializes the USART1.
* @param speed Port speed.
*/
void InitUSART1(int speed)
{
// USART1 - TXD PA9 - RXD PA10
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// USART IRQ init
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 15;
NVIC_Init(&NVIC_InitStructure);
// Configure USART as alternate function
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // Tx
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // Rx
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Configure USART baud rate
USART_StructInit(&USART_InitStructure);
USART_InitStructure.USART_BaudRate = speed;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
m_USART1.init(USART1);
}
#endif
// ---------------------------------------------------------------------------
// UART2
// ---------------------------------------------------------------------------
static STM_UART m_USART2;
/**
* @brief Helper to handle the USART5 IRQ.
*/
void USART2_IRQHandler()
{
m_USART2.handleIRQ();
}
/**
* @brief Initializes the USART5.
* @param speed Port speed.
*/
void InitUSART2(int speed)
{
// USART2 - TXD PA2 - RXD PA3
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// USART IRQ init
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 15;
NVIC_Init(&NVIC_InitStructure);
// Configure USART as alternate function
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // Tx
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // Rx
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Configure USART baud rate
USART_StructInit(&USART_InitStructure);
USART_InitStructure.USART_BaudRate = speed;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
m_USART2.init(USART2);
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/* Reads data from the modem flash parititon. */
void SerialPort::flashRead()
{
uint8_t reply[249U];
reply[0U] = DVM_SHORT_FRAME_START;
reply[1U] = 249U;
reply[2U] = CMD_FLSH_READ;
::memcpy(reply + 3U, (void*)STM32_CNF_PAGE, 246U);
writeInt(1U, reply, 249U);
}
/* Writes data to the modem flash partition. */
uint8_t SerialPort::flashWrite(const uint8_t* data, uint8_t length)
{
if (length > 249U) {
return RSN_FLASH_WRITE_TOO_BIG;
}
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
#if defined(STM32F4XX)
if (FLASH_EraseSector(STM32_CNF_SECTOR, VoltageRange_3) != FLASH_COMPLETE) {
FLASH_Lock();
return RSN_FAILED_ERASE_FLASH;
}
#elif defined(STM32F10X_MD)
if (FLASH_ErasePage(STM32_CNF_PAGE_ADDR) != FLASH_COMPLETE) {
FLASH_Lock();
return RSN_FAILED_ERASE_FLASH;
}
#endif
// write data to the user flash area
uint32_t address = STM32_CNF_PAGE_ADDR;
uint8_t i = 0U;
while (i < length) {
uint32_t word =
(data[i + 3] << 24) +
(data[i + 2] << 16) +
(data[i + 1] << 8) +
(data[i + 0] << 0);
if (FLASH_ProgramWord(address, word) == FLASH_COMPLETE) {
address += 4;
i += 4;
}
else {
FLASH_Lock();
return RSN_FAILED_WRITE_FLASH;
}
}
FLASH_Lock();
return RSN_OK;
}
/* */
void SerialPort::beginInt(uint8_t n, int speed)
{
switch (n) {
case 1U:
InitUSART1(speed);
break;
case 3U:
InitUSART2(speed);
break;
default:
break;
}
}
/* */
int SerialPort::availableInt(uint8_t n)
{
switch (n) {
case 1U:
return m_USART1.available();
case 3U:
m_USART2.available();
default:
return 0;
}
}
/* */
int SerialPort::availableForWriteInt(uint8_t n)
{
switch (n) {
case 1U:
return m_USART1.availableForWrite();
case 3U:
return m_USART2.availableForWrite();
default:
return 0;
}
}
/* */
uint8_t SerialPort::readInt(uint8_t n)
{
switch (n) {
case 1U:
return m_USART1.read();
case 3U:
return m_USART2.read();
default:
return 0U;
}
}
/* */
void SerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush)
{
switch (n) {
case 1U:
m_USART1.write(data, length);
if (flush)
m_USART1.flush();
break;
case 3U:
m_USART2.write(data, length);
if (flush)
m_USART2.flush();
break;
default:
break;
}
}
#endif

Powered by TurnKey Linux.