first commit

This commit is contained in:
2022-11-08 16:13:55 +01:00
commit f838fa66c4
2500 changed files with 2237507 additions and 0 deletions
@@ -0,0 +1,481 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#include <unistd.h>
#include "dma.h"
#include "spi.h"
#include "gpio.h"
#include "uhsdr_board.h"
#include "flash_if.h"
#include "uhsdr_boot_hw.h"
#include "command.h"
#include "fatfs.h"
#include "usb_host.h"
#include "bootloader_main.h"
#include "ui_lcd_hy28.h"
FATFS USBDISKFatFs; /* File system object for USB disk logical drive */
FIL MyFile; /* File object */
char USBDISKPath[4]; /* USB Host logical drive path */
bool boot_failed;
static FIL fileR;
extern USBH_HandleTypeDef hUsbHostHS;
static uint8_t Bootloader_USBConnected(void)
{
return hUsbHostHS.device.is_connected;
}
static const char* bl_help[] =
{
TRX_NAME " Bootloader",
"Firmware Name: " BASE_FILE,
"USB Drive Mode",
// "Release Band- to skip firmware update",
"Release Band- to skip fw/config update",
"",
"DFU Update Mode",
"Keep Power pressed until finish.",
"Release Band+ to start DFU Mode.",
"Screen may go white. This is ok.",
"PC should recognize new USB device.",
};
static void Bootloader_DisplayInit(void)
{
MX_DMA_Init();
MX_SPI2_Init();
MX_GPIO_Init();
// we need to set the touch screen CS signal to high, otherwise SPI displays
// will not be detectable
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pin = TP_CS;
HAL_GPIO_Init(TP_CS_PIO, &GPIO_InitStructure);
GPIO_SetBits(TP_CS_PIO, TP_CS);
UiLcdHy28_Init();
UiLcdHy28_LcdClear(Black);
mchfBl_PinOn(BACKLIGHT);
}
// bin rw: 0 1 2 3 4
// dfu 0 1 5 4 6 7 8 9
static void Bootloader_InfoScreen(void)
{
Bootloader_DisplayInit();
Bootloader_PrintLine(bl_help[0]);
Bootloader_PrintLine(bl_help[1]);
Bootloader_PrintLine(bl_help[2]);
Bootloader_PrintLine(bl_help[4]);
Bootloader_PrintLine(bl_help[3]);
Bootloader_PrintLine(bl_help[4]);
}
static void Bootloader_InfoScreenDFU(void)
{
Bootloader_DisplayInit();
Bootloader_PrintLine(bl_help[0]);
Bootloader_PrintLine(bl_help[1]);
Bootloader_PrintLine(bl_help[5]);
Bootloader_PrintLine(bl_help[4]);
Bootloader_PrintLine(bl_help[6]);
Bootloader_PrintLine(bl_help[7]);
Bootloader_PrintLine(bl_help[8]);
Bootloader_PrintLine(bl_help[9]);
}
static void Bootloader_UsbHost_Idle(void)
{
static bool power_was_up = false;
static uint32_t tick;
uint32_t now = HAL_GetTick();
if (now >= tick)
{
mchfBl_PinToggle(LEDGREEN);
tick = now + 1024;
}
if(mchfBl_ButtonGetState(BUTTON_POWER) == 0)
{
// we only switch off, if power button was at least once seen as being released and pressed in the idle loop
if (power_was_up == true)
{
mcHF_PowerOff();
}
}
else
{
// okay, power button is not pressed currently
power_was_up = true;
}
}
static int Bootloader_UsbMSCDevice_Application(void)
{
Bootloader_PowerHoldOn(); // make sure we have uninterrupted power
Bootloader_PrintLine("USB Drive detected.");
/* Register the file system object to the FatFs module */
if(f_mount(&USBDISKFatFs, (TCHAR const*)USBDISKPath, 0) != FR_OK)
{
/* FatFs Initialization Error */
FlashFail_Handler(BL_ERR_USBPROBLEM);
}
else
{
// just before we start, we check the BANDM button.
// If still pressed, we will also flash the memory afer reading it
__IO uint32_t was_download = (mchfBl_ButtonGetState(BUTTON_BANDM) == 0);
/* Reads all flash memory */
if(was_download)
{
// Bootloader_PrintLine("Firmware will be updated...");
Bootloader_PrintLine("Firmware/config will be updated...");
}
Bootloader_PrintLine("Saving Flash to \"" UPLOAD_FILE "\"...");
COMMAND_UPLOAD();
Bootloader_PrintLine("Saving Flash to \"" UPLOAD_FILE_CONF "\"...");
COMMAND_UPLOAD_CONF();
/* Check if BAND- Button was pressed */
if (was_download)
{
/* Writes Flash memory */
// Bootloader_PrintLine("Updating firmware using \"" DOWNLOAD_FILE "\"...");
// COMMAND_DOWNLOAD();
bool FilesAreHere = false;
if (f_open(&fileR, DOWNLOAD_FILENAME, FA_READ) == FR_OK)
{
f_close (&fileR);
FilesAreHere = true;
Bootloader_PrintLine("Updating firmware using \"" DOWNLOAD_FILE "\"...");
COMMAND_DOWNLOAD();
}
if (f_open(&fileR, DOWNLOAD_FILENAME_CONF, FA_READ) == FR_OK)
{
f_close (&fileR);
FilesAreHere = true;
Bootloader_PrintLine("Updating config using \"" DOWNLOAD_FILE_CONF "\"...");
COMMAND_DOWNLOAD_CONF();
}
if(FilesAreHere == false)
{
Bootloader_PrintLine("No files for update.");
}
}
else
{
// Bootloader_PrintLine("Skipping firmware update.");
Bootloader_PrintLine("Skipping firmware/conf update.");
}
Bootloader_PrintLine("");
Bootloader_PrintLine("Finished.");
Bootloader_PrintLine("");
Bootloader_PrintLine("Remove drive or press Band- to reboot.");
Bootloader_PrintLine("Press Power to switch off.");
// if we don't have a display, turn off backlight
if (mchf_display.DeviceCode == 0x0000)
{
mchfBl_PinOff(BACKLIGHT);
}
/* Waiting User Button Released */
while ((mchfBl_ButtonGetState(BUTTON_BANDM) == 0))
{}
/* Waiting User Button Pressed or usb drive removed. If drive is removed, we go straight to reboot */
while ((mchfBl_ButtonGetState(BUTTON_BANDM) == 1) && Bootloader_USBConnected() != 0)
{
/* switch off if power button is pressed */
if(mchfBl_ButtonGetState(BUTTON_POWER) == 0)
{
mcHF_PowerOff();
}
}
/* Waiting User Button Released or usb drive removed. If drive is removed, we go straight to reboot */
while ((mchfBl_ButtonGetState(BUTTON_BANDM) == 0) && Bootloader_USBConnected() != 0)
{}
/* Jumps to user application code located in the internal Flash memory */
COMMAND_ResetMCU(BOOT_REBOOT);
}
// this below is a trick to get sbrk() linked in at the right time so that
// we don't get a link error
sbrk(0);
return(0);
}
void BSP_Init(void)
{
// we assume that the clock for all required GPIO Ports has been turn on!!
/* Initialize LEDs and User_Button on mchf --------------------*/
mchfBl_ButtonInit(BUTTON_BANDM, BUTTON_MODE_GPIO);
mchfBl_ButtonInit(BUTTON_POWER, BUTTON_MODE_GPIO);
mchfBl_ButtonInit(BUTTON_BANDP, BUTTON_MODE_GPIO);
mchfBl_LEDInit(LEDGREEN);
mchfBl_LEDInit(LEDRED);
mchfBl_LEDInit(PWR_HOLD);
mchfBl_LEDInit(BACKLIGHT);
}
/**
* @brief jump to a STM32 Application by giving the start address of the ISR Vector structure of that application
*/
// __attribute__ ( ( naked ) )
extern const uint32_t* _linker_ram_start; // we get this from the linker script
static const uint32_t linker_ram_start_addr = (uint32_t)&_linker_ram_start;
/**
* We check whether the supplied address is pointing to a valid vector table
* Checks are simple (right now we just look if the stack pointer points in the region of RAM)
*
* @param ApplicationAddress an 32 bit value pointing to the start of a vector table
* @return true we should try to use this address
*/
bool uhsdrBl_IsValidApplication(uint32_t ApplicationAddress)
{
// TODO: Better checks
// check if the stackpointer points into a likely ram area (normal RAM start + 1MB)
uint32_t* const APPLICATION_PTR = (uint32_t*)ApplicationAddress;
return APPLICATION_PTR[0] <= (linker_ram_start_addr + (1024 * 1024)) && ( APPLICATION_PTR[0] >= linker_ram_start_addr);
}
/**
* Jumps to new code using a reset vector,
* brings processor into the default state (almost like in reset state, except for peripherals and their clocks)
* set stackpointer and then jumps to the specific address. This function normally never returns unless
* the IsValidApplication check fails.
*
* @param ApplicationAddress the start address of the reset vector (not the start of the code itself!)
*/
void UhsdrBl_JumpToApplication(uint32_t ApplicationAddress)
{
if (uhsdrBl_IsValidApplication(ApplicationAddress))
{
uint32_t* const APPLICATION_PTR = (uint32_t*)ApplicationAddress;
// disable all interrupts
__disable_irq();
// disable systick irq
HAL_SuspendTick();
// set clocks to default state
HAL_RCC_DeInit();
// clear Interrupt Enable Register & Interrupt Pending Register
const size_t icer_count = sizeof(NVIC->ICER)/sizeof(NVIC->ICER[0]);
for (size_t i = 0; i <icer_count; i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
// enable all interrupts
__enable_irq();
__set_MSP(APPLICATION_PTR[0]);
/* Jump to user application */
((pFunction) APPLICATION_PTR[1])();
}
}
int Bootloader_Main()
{
double i,border;
/* prevention of erratical boot loop */
if( *(__IO uint32_t*)(SRAM2_BASE) != BOOT_REBOOT)
{
border = 300000; // long delay if firmware was not running before or at powerdown
}
else
{
border = 10; // short delay if reboot is requested
}
for (i = 0; i < border; i++)
{
;
}
// #ifdef SBLA
// *(uint32_t*)(SRAM2_BASE+5) = 0x29; // signature for DF8OE development features
// #endif
// #ifdef SBLS
// *(uint32_t*)(SRAM2_BASE+10) = 0x29; // signature for special beta-testing features
// #endif
/* initialization */
BSP_Init();
//#if 0
// mcHF_PowerHoldOff();
//
//
// if( *(uint32_t*)(SRAM2_BASE) != 0x55) // no reboot requested?
// {
// // we wait for a longer time
// HAL_Delay(300);
// }
//#else
//#endif
Bootloader_PowerHoldOn();
HAL_Delay(50);
if (boot_failed == true)
{
BootFail_Handler(3);
}
else if (mchfBl_ButtonGetState(BUTTON_BANDP) == 0)
{
Bootloader_InfoScreenDFU();
// BANDP pressed, DFU boot requested
while (mchfBl_ButtonGetState(BUTTON_BANDP) == 0) {};
COMMAND_ResetMCU(BOOT_DFU);
}
/* Test if BAND- button on mchf is NOT pressed */
else if (mchfBl_ButtonGetState(BUTTON_BANDM) == 1)
{
/* Check Vector Table: Test if user code is programmed starting from address
"APPLICATION_ADDRESS"
We do that be reading the stack pointer value stored at APPLICATION_ADDRESS
and roughly check if it points to a RAM SPACE address
*/
// we go through restart here to have all interrupts turned off and everything as
// pristine as it gets after reset, avoids issues with enabled interrupts etc.
// we had that and it is pain to debug, see #1610 in GitHub!
if (uhsdrBl_IsValidApplication(APPLICATION_ADDRESS))
{
UhsdrBl_JumpToApplication(APPLICATION_ADDRESS);
}
else
{
BootFail_Handler(2);
}
// never reached, is endless loop
}
/* Init upgrade mode display */
Bootloader_InfoScreen();
mchfBl_PinOn(BACKLIGHT);
// now give user a chance to let go off the BAND- button
HAL_Delay(3000);
return 0;
}
extern ApplicationTypeDef Appli_state;
void Bootloader_UsbHostApplication()
{
switch(Appli_state)
{
case APPLICATION_READY:
Bootloader_UsbMSCDevice_Application();
Appli_state = APPLICATION_IDLE;
break;
case APPLICATION_DISCONNECT:
f_mount(NULL, (TCHAR const*)"", 0);
Appli_state = APPLICATION_IDLE;
break;
case APPLICATION_IDLE:
default:
break;
}
Bootloader_UsbHost_Idle();
}
/*
* This does not work if data cache is enabled, since we then need to flush the SRAM2_BASE write
* but here flash should not be enabled anyway!
*/
void Bootloader_CheckAndGoForBootTarget()
{
if(*(uint32_t*)(SRAM2_BASE) == BOOT_DFU)
{
*(uint32_t*)(SRAM2_BASE) = BOOT_CLEARED;
#if defined(STM32F4)
__HAL_REMAPMEMORY_SYSTEMFLASH();
const uint32_t dfu_boot_start = 0x00000000;
#elif defined(STM32F7)
const uint32_t dfu_boot_start = 0x1FF00000;
// if in dual boot mode (which is required for proper operation
// we need to fix the setup
#if defined (FLASH_OPTCR_nDBANK)
if ((FLASH->OPTCR & (FLASH_OPTCR_nDBANK_Msk|FLASH_OPTCR_nDBOOT_Msk)) != FLASH_OPTCR_nDBOOT)
{
if (HAL_FLASH_OB_Unlock() == HAL_OK)
{
FLASH->OPTCR |= FLASH_OPTCR_nDBOOT; // set == disable dual boot
FLASH->OPTCR &= ~FLASH_OPTCR_nDBANK; // unset == enabled dual bank mode
HAL_FLASH_OB_Launch();
HAL_FLASH_OB_Lock();
}
}
#endif
#elif defined(STM32H7)
const uint32_t dfu_boot_start = 0x1FF09800;
#endif
UhsdrBl_JumpToApplication(dfu_boot_start);
// start the STM32Fxxx bootloader at address dfu_boot_start;
}
if(*(uint32_t*)(SRAM2_BASE) == BOOT_FIRMWARE)
{
*(uint32_t*)(SRAM2_BASE) = BOOT_CLEARED;
UhsdrBl_JumpToApplication(APPLICATION_ADDRESS);
// start the STM32Fxxx bootloader at address dfu_boot_start;
boot_failed = true;
}
}
#include "uhsdr_board_config.h"
static uint8_t current_line;
void Bootloader_PrintLine(const char* txt)
{
UiLcdHy28_PrintText(4,4+current_line*16,txt,Yellow,Black,0);
current_line++;
}
@@ -0,0 +1,44 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _BOOTLOADER_MAIN_H
#define _BOOTLOADER_MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
void Bootloader_UsbHostApplication(void);
int Bootloader_Main(void);
void Bootloader_CheckAndGoForBootTarget(void);
void Bootloader_PrintLine(const char* txt);
enum
{
BOOT_CLEARED = 0,
BOOT_REBOOT = 0x55, // this command can be issue also by the firmware indicate immediate start
BOOT_DFU = 0x99,
BOOT_FIRMWARE = 0x66993300,
};
#ifdef __cplusplus
}
#endif
#endif /* _BOOTLOADER_MAIN */
@@ -0,0 +1,394 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/**
******************************************************************************
* @author MCD Application Team
* @version V1.0.0
* @date 28-October-2011
* @brief This file provides all the IAP command functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "command.h"
#include "uhsdr_mcu.h"
#include "fatfs.h"
#include "uhsdr_boot_hw.h"
#include "bootloader_main.h"
#include "ui_lcd_hy28.h"
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#define BUFFER_SIZE ((uint16_t)512*64)
// 64k flash are in use for bootloader and config memory
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static uint8_t RAM_Buf[BUFFER_SIZE] __attribute__ ((aligned (4)));
static FIL file;
static FIL fileR;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void Wait(int time)
{
HAL_Delay(time);
// we show the error message until user presses power...
if(mchfBl_ButtonGetState(BUTTON_POWER) == 0)
{
mcHF_PowerOff();
}
}
static const char* error_help[] =
{
"No error",
"USB problem",
DOWNLOAD_FILE " not found",
"Flash memory too small",
"Problem writing " UPLOAD_FILE,
"Problem reading" DOWNLOAD_FILE,
"Flash programming problem",
"Flash erase problem",
"Flash write protected",
};
// USB error handling
void FlashFail_Handler(mchf_bootloader_error_t redCount)
{
mchfBl_PinOff(LEDGREEN);
mchfBl_PinOff(LEDRED);
char txt[16] = "Error Code X";
txt[12] = redCount + '0';
Bootloader_PrintLine("");
Bootloader_PrintLine(txt);
Bootloader_PrintLine(error_help[redCount]);
while(1)
{
if (mchf_display.DeviceCode == 0x0000)
{
mchfBl_PinOff(BACKLIGHT);
}
Wait(600);
for(int i = 0; i < redCount; i++)
{
mchfBl_PinOff(LEDRED);
Wait(300);
mchfBl_PinOn(LEDRED);
Wait(300);
mchfBl_PinOff(LEDRED);
Wait(300);
}
Wait(600);
mchfBl_PinOn(BACKLIGHT);
Wait(900);
}
}
// USB error handling
void BootFail_Handler(uint8_t count)
{
mchfBl_PinOff(BACKLIGHT);
Wait(700);
while(1)
{
for(uint8_t i = 0; i < count; i++)
{
Wait(300);
mchfBl_PinOn(BACKLIGHT);
Wait(300);
mchfBl_PinOff(BACKLIGHT);
Wait(700);
}
Wait(700);
}
}
/**
* @brief Programs the internal Flash memory
*/
//mchf_bootloader_error_t COMMAND_ProgramFlashMemory()
mchf_bootloader_error_t COMMAND_ProgramFlashMemory(uint32_t LastPGAddress)
{
mchf_bootloader_error_t retval = BL_ERR_NONE;
uint8_t readflag = TRUE;
// uint32_t LastPGAddress = APPLICATION_ADDRESS;
do
{
UINT BytesRead;
/* Read maximum 32 Kbyte from the selected file */
if(f_read (&fileR, RAM_Buf, BUFFER_SIZE, &BytesRead) != FR_OK)
{
retval = BL_ERR_READDISK;
}
else
{
/* The read data < "BUFFER_SIZE" Kbyte */
if (BytesRead < BUFFER_SIZE)
{
readflag = FALSE;
}
/* Program flash memory */
for ( uint32_t programcounter = 0;
programcounter < BytesRead;
programcounter+=32,LastPGAddress += 32)
{
uint32_t* RAM_Address = (uint32_t*)&RAM_Buf[programcounter];
if (flashIf_Program256Bit(LastPGAddress, RAM_Address) != HAL_OK)
{
/* Flash programming error */
retval = BL_ERR_FLASHPROG;
}
}
}
} while ((readflag == TRUE) && retval == BL_ERR_NONE);
return retval;
}
/**
* @brief read flash and write to image on disk
*/
void COMMAND_UPLOAD(void)
{
UINT bytesWritten;
FRESULT res = FR_OK;
f_unlink(VERSION);
f_unlink(AUTHOR);
/* green LED on command upload */
mchfBl_PinOn(LEDGREEN);
/* Get the read out protection status */
FlagStatus readoutstatus = flashIf_ReadOutProtectionStatus();
if (readoutstatus == 0)
{
/* Remove UPLOAD file if exist on flash disk */
f_unlink (UPLOAD_FILENAME);
/* Init written byte counter */
uint32_t offset = 0;
uint8_t* address = (uint8_t*)CONFIG_START_ADDRESS;//APPLICATION_ADDRESS;
/* Open binary file to write on it */
res = f_open(&file, UPLOAD_FILENAME, FA_CREATE_ALWAYS | FA_WRITE);
if (res == FR_OK)
{
uint32_t counterread = 0;
uint32_t fw_leight = flashIf_userFlashSize();
/* Read flash memory */
// while ((offset != flashIf_userFlashSize() && res == FR_OK))
while ((offset != fw_leight && res == FR_OK))
{
// for (counterread = 0; counterread < BUFFER_SIZE && offset != flashIf_userFlashSize(); counterread++,offset++)
for (counterread = 0; counterread < BUFFER_SIZE && offset != fw_leight; counterread++,offset++)
{
RAM_Buf[counterread] = address[offset];
}
/* Write buffer to file */
res = f_write (&file, RAM_Buf, counterread, &bytesWritten);
}
/* Close file and filesystem */
f_close (&file);
}
if (res != FR_OK)
{
FlashFail_Handler(BL_ERR_WRITEDISK);
}
}
else
{
FlashFail_Handler(BL_ERR_FLASHPROTECT);
}
}
/**
* @brief read flash and write config on disk
*/
void COMMAND_UPLOAD_CONF(void)
{
UINT bytesWritten;
FRESULT res = FR_OK;
/* green LED on command upload */
mchfBl_PinOn(LEDGREEN);
/* Get the read out protection status */
FlagStatus readoutstatus = flashIf_ReadOutProtectionStatus();
if (readoutstatus == 0)
{
/* Remove UPLOAD file if exist on flash disk */
f_unlink (UPLOAD_FILENAME_CONF);
/* Init written byte counter */
uint32_t offset = 0;
uint8_t* address = (uint8_t*)CONFIG_START_ADDRESS;
/* Open binary file to write on it */
res = f_open(&file, UPLOAD_FILENAME_CONF, FA_CREATE_ALWAYS | FA_WRITE);
if (res == FR_OK)
{
uint32_t counterread = 0;
/* Read flash memory */
while ((offset != CONFIG_LEIGHT && res == FR_OK))
{
for (counterread = 0; counterread < BUFFER_SIZE && offset != CONFIG_LEIGHT; counterread++,offset++)
{
RAM_Buf[counterread] = address[offset];
}
/* Write buffer to file */
res = f_write (&file, RAM_Buf, counterread, &bytesWritten);
}
/* Close file and filesystem */
f_close (&file);
}
if (res != FR_OK)
{
Bootloader_PrintLine("Problem writing " UPLOAD_FILE_CONF);
}
}
else
{
FlashFail_Handler(BL_ERR_FLASHPROTECT);
}
}
/**
* @brief read file and flash it
*/
void COMMAND_DOWNLOAD(void)
{
mchf_bootloader_error_t retval = BL_ERR_NONE;
/* Flash unlock */
flashIf_FlashUnlock();
/* Reading for flash active: Red LED on */
mchfBl_PinOn(LEDRED);
/* Open the binary file to be downloaded */
if (f_open(&fileR, DOWNLOAD_FILENAME, FA_READ) == FR_OK)
{
/* Erase FLASH sectors to download image */
if (f_size(&fileR) > flashIf_userFlashSize())
{
retval = BL_ERR_FLASHTOOSMALL;
} else if ( flashIf_EraseSectors(APPLICATION_ADDRESS,f_size(&fileR)) != HAL_OK)
{
/* Flash erase error */
retval = BL_ERR_FLASHERASE;
} else
{
/* Program flash memory */
// retval = COMMAND_ProgramFlashMemory();
retval = COMMAND_ProgramFlashMemory(APPLICATION_ADDRESS);
}
/* Close file and filesystem */
f_close (&fileR);
///f_mount(0, NULL);
}
else
{
/* the binary file is not available */
retval = BL_ERR_NOIMAGE;
}
flashIf_FlashLock();
if (retval != BL_ERR_NONE)
{
FlashFail_Handler(retval);
}
}
/**
* @brief flash file
*/
void COMMAND_DOWNLOAD_CONF(void)
{
mchf_bootloader_error_t retval = BL_ERR_NONE;
/* Flash unlock */
flashIf_FlashUnlock();
/* Reading for flash active: Red LED on */
mchfBl_PinOn(LEDRED);
/* Open the binary file to be downloaded */
if (f_open(&fileR, DOWNLOAD_FILENAME_CONF, FA_READ) == FR_OK)
{
/* Erase FLASH sectors to download image */
if (f_size(&fileR) > CONFIG_LEIGHT)
{
retval = BL_ERR_FLASHTOOSMALL;
} else if ( flashIf_EraseSectors(CONFIG_START_ADDRESS, CONFIG_LEIGHT) != HAL_OK)
{
/* Flash erase error */
retval = BL_ERR_FLASHERASE;
} else
{
/* Program flash memory */
// retval = COMMAND_ProgramFlashMemory();
retval = COMMAND_ProgramFlashMemory(CONFIG_START_ADDRESS);
}
/* Close file and filesystem */
f_close (&fileR);
}
else
{
/* the binary file is not available */
retval = BL_ERR_NOIMAGE;
}
flashIf_FlashLock();
if (retval != BL_ERR_NONE)
{
FlashFail_Handler(retval);
}
}
/**
* @brief reset to restart mchf
*/
void COMMAND_ResetMCU(uint32_t code)
{
*(__IO uint32_t*)(SRAM2_BASE) = code;
__DSB();
#if defined(STM32F7)
// || defined(STM32H7) H7 crashes here if we would call SCB_CleanDCache since we do not enable it in the first place in main.c!
SCB_CleanDCache();
#endif
/* Software reset */
NVIC_SystemReset();
}
@@ -0,0 +1,88 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/**
******************************************************************************
* @author MCD Application Team
* @version V1.0.0
* @date 28-October-2011
* @brief Header file for command.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _COMMAND_H
#define _COMMAND_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "gpio.h" // dummy include for HAL
#include "flash_if.h"
#include "uhsdr_version.h"
/* Exported types ------------------------------------------------------------*/
typedef enum {
BL_ERR_NONE = 0,
BL_ERR_USBPROBLEM = 1,
BL_ERR_NOIMAGE = 2,
BL_ERR_FLASHTOOSMALL = 3,
BL_ERR_WRITEDISK = 4,
BL_ERR_READDISK = 5,
BL_ERR_FLASHPROG = 6,
BL_ERR_FLASHERASE = 7,
BL_ERR_FLASHPROTECT = 8,
} mchf_bootloader_error_t;
/* Exported constants --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
#define BASE_PREFIX "fw-"
#define BASE_FILE BASE_PREFIX TRX_ID
#define UPLOAD_FILE BASE_FILE ".old"
#define DOWNLOAD_FILE BASE_FILE ".bin"
#define UPLOAD_FILENAME "0:" UPLOAD_FILE
#define DOWNLOAD_FILENAME "0:" DOWNLOAD_FILE
#define VERSION "Version: "UHSDR_BOOT_VER
#define AUTHOR "Author: DF8OE"
#define UPLOAD_FILE_CONF "cf-mchf.old"
#define UPLOAD_FILENAME_CONF "0:" UPLOAD_FILE_CONF
#define DOWNLOAD_FILE_CONF "cf-mchf.bin"
#define DOWNLOAD_FILENAME_CONF "0:" DOWNLOAD_FILE_CONF
#if defined(STM32F4) || defined(STM32F7)
#define CONFIG_START_ADDRESS ((uint32_t)0x08008000)
#define CONFIG_LEIGHT ((uint32_t)0x00008000)
#elif defined(STM32H7)
#define CONFIG_START_ADDRESS ((uint32_t)0x08020000)
#define CONFIG_LEIGHT ((uint32_t)0x00040000)
#endif
/* Exported functions ------------------------------------------------------- */
void COMMAND_UPLOAD(void);
void COMMAND_UPLOAD_CONF(void);
void COMMAND_DOWNLOAD(void);
void COMMAND_DOWNLOAD_CONF(void);
void COMMAND_ResetMCU(uint32_t code);
void BootFail_Handler(uint8_t count);
void FlashFail_Handler(mchf_bootloader_error_t errcode);
#ifdef __cplusplus
}
#endif
#endif /* _COMMAND_H */
@@ -0,0 +1,226 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#include "uhsdr_board_config.h"
#if defined(STM32F7)
#include "stm32f7xx_hal_flash.h"
#elif defined(STM32H7)
#include "stm32h7xx_hal_flash.h"
#elif defined(STM32F4)
#include "stm32f4xx_hal_flash.h"
#else
#error Unknown processor
#endif
#include "flash_if.h"
#define FLASH_NO_SECTOR (0xFFFFFFFF)
/* Base address of the Flash sectors */
typedef struct
{
uint32_t addr;
} flash_sectorinfo_t;
// this struct can be used to store more information
// such as bank numbers, sector numbers etc. if flash layout gets more complex
// right now not yet used
static const flash_sectorinfo_t flash_sector_addr[] = {
#if defined(STM32F4) || defined(STM32F7)
{ 0x08000000 }, /* Base @ of Sector 0, 16 Kbyte */
{ 0x08004000 }, /* Base @ of Sector 1, 16 Kbyte */
{ 0x08008000 }, /* Base @ of Sector 2, 16 Kbyte */
{ 0x0800C000 }, /* Base @ of Sector 3, 16 Kbyte */
{ 0x08010000 }, /* Base @ of Sector 4, 64 Kbyte */
{ 0x08020000 }, /* Base @ of Sector 5, 128 Kbyte */
{ 0x08040000 }, /* Base @ of Sector 6, 128 Kbyte */
{ 0x08060000 }, /* Base @ of Sector 7, 128 Kbyte */
{ 0x08080000 }, /* Base @ of Sector 8, 128 Kbyte */
{ 0x080A0000 }, /* Base @ of Sector 9, 128 Kbyte */
{ 0x080C0000 }, /* Base @ of Sector 10, 128 Kbyte */
{ 0x080E0000 }, /* Base @ of Sector 11, 128 Kbyte */
{ 0x08100000 }, /* Base @ of Sector 12, 128 Kbyte */
{ 0x08104000 }, /* Base @ of Sector 13, 16 Kbyte */
{ 0x08108000 }, /* Base @ of Sector 14, 16 Kbyte */
{ 0x0810C000 }, /* Base @ of Sector 15, 16 Kbyte */
{ 0x08110000 }, /* Base @ of Sector 16, 64 Kbyte */
{ 0x08120000 }, /* Base @ of Sector 17, 128 Kbyte */
{ 0x08140000 }, /* Base @ of Sector 18, 128 Kbyte */
{ 0x08160000 }, /* Base @ of Sector 19, 128 Kbyte */
{ 0x08180000 }, /* Base @ of Sector 20, 128 Kbyte */
{ 0x081A0000 }, /* Base @ of Sector 21, 128 Kbyte */
{ 0x081C0000 }, /* Base @ of Sector 22, 128 Kbyte */
{ 0x081E0000 }, /* Base @ of Sector 23, 128 Kbyte */
{ 0x08200000 }, /* End+1@ of Sector 23, 128 Kbyte */
#elif defined(STM32H7)
{ 0x08000000 }, /* Base @ of Sector 0, bank 1, 128 Kbyte */
{ 0x08020000 }, /* Base @ of Sector 1, 128 Kbyte */
{ 0x08040000 }, /* Base @ of Sector 2, 128 Kbyte */
{ 0x08060000 }, /* Base @ of Sector 3, 128 Kbyte */
{ 0x08080000 }, /* Base @ of Sector 4, 128 Kbyte */
{ 0x080A0000 }, /* Base @ of Sector 5, 128 Kbyte */
{ 0x080C0000 }, /* Base @ of Sector 6, 128 Kbyte */
{ 0x080E0000 }, /* Base @ of Sector 7, 128 Kbyte */
{ 0x08100000 }, /* Base @ of Sector 0, bank 2, 128 Kbyte */
{ 0x08120000 }, /* Base @ of Sector 1, 128 Kbyte */
{ 0x08140000 }, /* Base @ of Sector 2, 128 Kbyte */
{ 0x08160000 }, /* Base @ of Sector 3, 128 Kbyte */
{ 0x08180000 }, /* Base @ of Sector 4, 128 Kbyte */
{ 0x081A0000 }, /* Base @ of Sector 5, 128 Kbyte */
{ 0x081C0000 }, /* Base @ of Sector 6, 128 Kbyte */
{ 0x081E0000 }, /* Base @ of Sector 7, 128 Kbyte */
{ 0x08200000 }, /* End+1@ of Sector 7, 128 Kbyte */
#endif
};
static const uint32_t flash_sector_max = sizeof(flash_sector_addr)/sizeof(flash_sectorinfo_t)-1;
// we have one extra entry at the end, hence we need to reduce number of sectors by one
#define RESET 0
#define SET 1
/**
* Return the Flash sector Number of the address
* retval The Flash sector Number of the address
*/
static uint32_t flashIf_GetSectorInfoIndex(uint32_t Address)
{
uint32_t sector = FLASH_NO_SECTOR; // index of invalid sector, returned if address not in flash
for (int idx = 0; idx < flash_sector_max; idx++)
{
if (Address >= flash_sector_addr[idx].addr && Address < flash_sector_addr[idx+1].addr)
{
sector = idx;
break;
}
}
return sector;
}
static uint32_t flashIf_GetSectorNumber(uint32_t idx)
{
uint32_t retval = FLASH_NO_SECTOR;
if (idx < flash_sector_max)
{
#if defined(STM32F4) || defined(STM32F7)
retval = idx; // idx == sector number
#elif defined(STM32H7)
retval = idx % 8; // 2x8 sectors
#endif
}
return retval;
}
#if defined(STM32H7)
static uint32_t flashIf_GetSectorBank(uint32_t idx)
{
uint32_t retval = FLASH_NO_SECTOR;
if (idx < flash_sector_max)
{
retval = idx < 8? FLASH_BANK_1:FLASH_BANK_2; // 2x8 sectors
}
return retval;
}
#endif
void flashIf_FlashUnlock()
{
HAL_FLASH_Unlock();
}
void flashIf_FlashLock()
{
HAL_FLASH_Lock();
}
FlagStatus flashIf_ReadOutProtectionStatus()
{
FLASH_OBProgramInitTypeDef OBInit;
HAL_FLASHEx_OBGetConfig(&OBInit);
FlagStatus readoutstatus = RESET;
if (OBInit.RDPLevel != OB_RDP_LEVEL0)
{
readoutstatus = SET;
}
else
{
readoutstatus = RESET;
}
return readoutstatus;
}
/**
* Erases the required FLASH Sectors.
* retval Sectors erase status:
* HAL_OK: Erase sectors done with success
* Anything else: Erase error
*/
uint32_t flashIf_EraseSectors(uint32_t Address, uint32_t Length)
{
FLASH_EraseInitTypeDef flashEraseOp;
uint32_t sectorError = 0;
uint32_t retval = HAL_ERROR;
/* Erase Flash sectors */
uint32_t startsector = flashIf_GetSectorInfoIndex(Address);
uint32_t endsector = flashIf_GetSectorInfoIndex(Address+Length-1);
if (startsector != FLASH_NO_SECTOR && endsector != FLASH_NO_SECTOR)
{
retval = HAL_OK;
for (int idx = startsector; retval == HAL_OK && idx <= endsector; idx++)
{
/* Erase FLASH sectors to download image */
flashEraseOp.Sector = flashIf_GetSectorNumber(idx);
flashEraseOp.NbSectors = 1;
flashEraseOp.VoltageRange = VOLTAGE_RANGE_3;
flashEraseOp.TypeErase = FLASH_TYPEERASE_SECTORS;
#if defined(STM32H7)
flashEraseOp.Banks = flashIf_GetSectorBank(idx);
#endif
retval = HAL_FLASHEx_Erase(&flashEraseOp, &sectorError);
}
}
return retval;
}
/**
* Programs a word at a specified address.
* Address: specifies the address to be programmed.
* Data: specifies the data to be programmed.
* retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, HAL_OK or FLASH_TIMEOUT.
*/
HAL_StatusTypeDef flashIf_Program256Bit(uint32_t Address, uint32_t Data[8])
{
HAL_StatusTypeDef retval = HAL_OK;
#ifndef STM32H7
for (int i=0; retval == HAL_OK && i < 8; i++)
{
retval = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,Address+(i*4), Data[i]);
}
#else
retval = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD,Address, (uint32_t)&Data[0]);
#endif
return retval;
}
@@ -0,0 +1,85 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/**
******************************************************************************
* @author MCD Application Team
* @version V1.0.0
* @date 28-October-2011
* @brief Header file for flash_layer.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _FLASH_ACCESS_LAYER_H
#define _FLASH_ACCESS_LAYER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "uhsdr_mcu.h"
/* Exported types ------------------------------------------------------------*/
typedef void (*pFunction)(void);
/* Exported constants --------------------------------------------------------*/
/* extern const char* version;
extern const char* author; */
#ifndef STM32H7
/* Define the flash memory start address */
#define USER_FLASH_STARTADDRESS ((uint32_t)0x08000000) /* Flash Start Address */
/* End of the Flash address for the largest device, dynamically sized down based on real processor flash */
#define USER_FLASH_END_ADDRESS ((uint32_t)0x081FFFFF)
#define MCHF_FLASHRESERVED (64)
#else
/* Define the flash memory start address */
#define USER_FLASH_STARTADDRESS ((uint32_t)0x08000000) /* Flash Start Address */
/* End of the Flash address for the largest device, dynamically sized down based on real processor flash */
#define USER_FLASH_END_ADDRESS ((uint32_t)0x081FFFFF)
#define MCHF_FLASHRESERVED (384)
#endif
/* Define the address from where user application will be loaded. */
#define APPLICATION_ADDRESS (USER_FLASH_STARTADDRESS + (MCHF_FLASHRESERVED * 1024))
/**
* @brief real user flash size of microprocessor (flash size - bootloader/config flash size)
* @returns size of user flash in bytes
*/
static inline uint32_t flashIf_userFlashSize() { return ((STM32_GetFlashSize() - MCHF_FLASHRESERVED)*1024); }
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void flashIf_FlashUnlock(void);
void flashIf_FlashLock(void);
FlagStatus flashIf_ReadOutProtectionStatus(void);
uint32_t flashIf_EraseSectors(uint32_t Address, uint32_t Length);
HAL_StatusTypeDef flashIf_Program256Bit(uint32_t Address, uint32_t Data[8]);
#ifdef __cplusplus
}
#endif
#endif /* _FLASH_IF_H */
/*******************(C)COPYRIGHT 2011 STMicroelectronics *****END OF FILE******/
@@ -0,0 +1,139 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#include "uhsdr_boot_hw.h"
static GPIO_TypeDef* GPIO_PORT[LEDn] = {LEDGREEN_GPIO_PORT, LEDRED_GPIO_PORT, POWER_ON_GPIO_PORT, BACKLIGHT_ON_GPIO_PORT, TP_CS_PIO};
static const uint16_t GPIO_PIN[LEDn] = {LEDGREEN_PIN, LEDRED_PIN, POWER_ON_PIN, BACKLIGHT_ON_PIN, TP_CS};
static GPIO_TypeDef* BUTTON_PORT[BUTTONn] = {BANDM_BUTTON_GPIO_PORT,POWER_BUTTON_GPIO_PORT, BANDP_BUTTON_GPIO_PORT};
static const uint16_t BUTTON_PIN[BUTTONn] = {BANDM_BUTTON_PIN,POWER_BUTTON_PIN, BANDP_BUTTON_PIN};
static const uint8_t BUTTON_IRQn[BUTTONn] = {BANDM_BUTTON_EXTI_IRQn,POWER_BUTTON_EXTI_IRQn,BANDP_BUTTON_EXTI_IRQn};
void mchfBl_PortClock(uint32_t port)
{
/* Enable the BUTTON Clock */
switch(port)
{
case (uint32_t)GPIOA:
__HAL_RCC_GPIOA_CLK_ENABLE();
break;
case (uint32_t)GPIOB:
__HAL_RCC_GPIOB_CLK_ENABLE();
break;
case (uint32_t)GPIOC:
__HAL_RCC_GPIOC_CLK_ENABLE();
break;
case (uint32_t)GPIOD:
__HAL_RCC_GPIOD_CLK_ENABLE();
break;
#if 0
case (uint32_t)GPIOE:
__HAL_RCC_GPIOE_CLK_ENABLE();
break;
case (uint32_t)GPIOF:
__HAL_RCC_GPIOF_CLK_ENABLE();
break;
case (uint32_t)GPIOG:
__HAL_RCC_GPIOG_CLK_ENABLE();
break;
case (uint32_t)GPIOH:
__HAL_RCC_GPIOH_CLK_ENABLE();
break;
case (uint32_t)GPIOI:
__HAL_RCC_GPIOI_CLK_ENABLE();
break;
#endif
}
}
void mchfBl_LEDInit(Led_TypeDef Led)
{
GPIO_InitTypeDef GPIO_InitStructure;
mchfBl_PortClock((uint32_t)GPIO_PORT[Led]);
/* Enable the GPIO_LED Clock */
/* Configure the GPIO_LED pin */
GPIO_InitStructure.Pin = GPIO_PIN[Led];
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIO_PORT[Led], &GPIO_InitStructure);
}
void mchfBl_PinOn(Led_TypeDef Led)
{
GPIO_SetBits(GPIO_PORT[Led],GPIO_PIN[Led])
}
void mchfBl_PinOff(Led_TypeDef Led)
{
GPIO_ResetBits(GPIO_PORT[Led],GPIO_PIN[Led])
}
void mchfBl_PinToggle(Led_TypeDef Led)
{
GPIO_PORT[Led]->ODR ^= GPIO_PIN[Led];
}
void mchfBl_ButtonInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
mchfBl_PortClock((uint32_t)BUTTON_PORT[Button]);
/* Configure Button pin as input */
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Pin = BUTTON_PIN[Button];
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
if (Button_Mode == BUTTON_MODE_EXTI)
{
/* Configure Button EXTI line */
GPIO_InitStructure.Mode = GPIO_MODE_EVT_FALLING;
/* Enable and set Button EXTI Interrupt to the lowest priority */
HAL_NVIC_EnableIRQ(BUTTON_IRQn[Button]);
HAL_NVIC_SetPriority(BUTTON_IRQn[Button],15,0);
}
HAL_GPIO_Init(BUTTON_PORT[Button], &GPIO_InitStructure);
}
uint32_t mchfBl_ButtonGetState(Button_TypeDef Button)
{
return HAL_GPIO_ReadPin(BUTTON_PORT[Button], BUTTON_PIN[Button]);
}
void mcHF_PowerOff()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Pin = GPIO_PIN[PWR_HOLD];
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIO_PORT[PWR_HOLD], &GPIO_InitStructure);
while(1) { asm("nop"); }
// never reached
}
@@ -0,0 +1,105 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#ifndef __MCHF_H
#define __MCHF_H
/* Includes ------------------------------------------------------------------*/
#include "uhsdr_board_config.h"
#include "uhsdr_board.h"
#include "gpio.h"
typedef enum
{
LEDGREEN = 0,
LEDRED = 1,
PWR_HOLD = 2,
BACKLIGHT = 3,
TPCS_PIN = 4
} Led_TypeDef;
typedef enum
{
BUTTON_BANDM = 0,
BUTTON_POWER = 1,
BUTTON_BANDP = 2
} Button_TypeDef;
typedef enum
{
BUTTON_MODE_GPIO = 0,
BUTTON_MODE_EXTI = 1
} ButtonMode_TypeDef;
#define LEDn 5
#define LEDGREEN_PIN GPIO_PIN_9
#define LEDGREEN_GPIO_PORT GPIOB
#define LEDRED_PIN GPIO_PIN_12
#define LEDRED_GPIO_PORT GPIOB
#define POWER_ON_PIN GPIO_PIN_8
#define POWER_ON_GPIO_PORT GPIOC
#define BACKLIGHT_ON_PIN GPIO_PIN_2
#define BACKLIGHT_ON_GPIO_PORT GPIOD
#define BUTTONn 3
#define BANDM_BUTTON_PIN GPIO_PIN_0
#define BANDM_BUTTON_GPIO_PORT GPIOB
#define BANDM_BUTTON_EXTI_IRQn EXTI0_IRQn
#define BANDP_BUTTON_PIN GPIO_PIN_2
#define BANDP_BUTTON_GPIO_PORT GPIOB
#define BANDP_BUTTON_EXTI_IRQn EXTI0_IRQn
#if defined(UI_BRD_MCHF)
#define POWER_BUTTON_PIN GPIO_PIN_13
#define POWER_BUTTON_GPIO_PORT GPIOC
#define POWER_BUTTON_EXTI_LINE EXTI_Line0
#define POWER_BUTTON_EXTI_IRQn EXTI0_IRQn
#elif defined(UI_BRD_OVI40)
#define POWER_BUTTON_PIN GPIO_PIN_2
#define POWER_BUTTON_GPIO_PORT GPIOG
#define POWER_BUTTON_EXTI_LINE EXTI_Line0
#define POWER_BUTTON_EXTI_IRQn EXTI0_IRQn
#endif
void mchfBl_LEDInit(Led_TypeDef Led);
void mchfBl_PinOn(Led_TypeDef Led);
void mchfBl_PinOff(Led_TypeDef Led);
void mchfBl_PinToggle(Led_TypeDef Led);
void mchfBl_ButtonInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode);
uint32_t mchfBl_ButtonGetState(Button_TypeDef Button);
void mcHF_PowerOff(void);
/*
* Just toggles the PowerHold Pin, but does not stop execution
*/
static inline void Bootloader_PowerHoldOff(void)
{
mchfBl_PinOn(PWR_HOLD);
}
static inline void Bootloader_PowerHoldOn(void)
{
mchfBl_PinOff(PWR_HOLD);
}
#endif /* __MCHF_H */
@@ -0,0 +1,555 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
// Common
#include "uhsdr_board.h"
#include <stdio.h>
#include "uhsdr_rtc.h"
#include "ui_spectrum.h"
#include "ui_configuration.h"
#include "config_storage.h"
// serial EEPROM driver
#include "uhsdr_hw_i2c.h"
#include "uhsdr_hw_i2s.h"
#include "uhsdr_hmc1023.h"
// Audio Driver
#include "drivers/audio/audio_driver.h"
#include "drivers/audio/audio_management.h"
#include "drivers/audio/cw/cw_gen.h"
#include "drivers/audio/freedv_uhsdr.h"
#include "drivers/audio/audio_nr.h"
//cat
#include "drivers/cat/cat_driver.h"
// UI Driver
#include "drivers/ui/ui_driver.h"
#include "drivers/ui/lcd/ui_lcd_hy28.h"
#include "drivers/ui/menu/ui_menu.h"
#include "drivers/ui/oscillator/osc_interface.h"
#include "drivers/ui/oscillator/osc_si5351a.h"
#include "drivers/ui/oscillator/osc_si570.h"
#include "drivers/audio/codec/codec.h"
#include "misc/profiling.h"
#include "uhsdr_canary.h"
#include "audio_agc.h"
// Keyboard Driver
// #include "keyb_driver.h"
// Misc
#include "drivers/audio/softdds/softdds.h"
#include "uhsdr_flash.h" // only for EEPROM_START_ADDRESS
#include "drivers/ui/radio_management.h"
//
#include "misc/TestCPlusPlusInterface.h"
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
{
if (ts.paddles_active != false)
{
switch(GPIO_Pin)
{
case BUTTON_PWR:
break;
case PADDLE_DAH:
// Call handler
if (Board_PttDahLinePressed() && RadioManagement_IsTxDisabledBy(TX_DISABLE_RXMODE) == false)
{ // was PTT line low? Is it not a RX only mode
RadioManagement_Request_TxOn(); // yes - ONLY then do we activate PTT! (e.g. prevent hardware bug from keying PTT!)
if(ts.dmod_mode == DEMOD_CW || is_demod_rtty() || is_demod_psk() || ts.cw_text_entry)
{
CwGen_DahIRQ(); // Yes - go to CW state machine
}
}
break;
case PADDLE_DIT:
if((ts.dmod_mode == DEMOD_CW || is_demod_rtty() || is_demod_psk() || ts.cw_text_entry) && Board_DitLinePressed())
{
if (ts.cw_keyer_mode != CW_KEYER_MODE_STRAIGHT)
{
RadioManagement_Request_TxOn();
}
CwGen_DitIRQ();
}
break;
}
}
}
/**
* Detects if a special bootloader is used and configures some settings
* Used for debugging and testing purposes only
*/
void Main_DetectSpecialBootloader()
{
// detection routine for special bootloader version strings which do enable debug or development functions
char out[14];
for(uint8_t* begin = (uint8_t*)0x8000000; begin < (uint8_t*)EEPROM_START_ADDRESS-8; begin++)
{
if (memcmp("Version: ",begin,9) == 0)
{
snprintf(out,13, "%s", &begin[9]);
for (uint8_t i=1; i<13; i++)
{
if (out[i] == '\0')
{
if (out[i-1] == 'a')
{
ts.special_functions_enabled = 1;
}
if (out[i-1] == 's')
{
ts.special_functions_enabled = 2;
}
break;
}
}
break;
}
}
}
/**
* All data inside the ts data structure which needs a non-zero value set at startup AND
* is either used before the configuration has been loaded OR which is not loaded from the persistent configuration
* should be initialized here.
* Values which are initialized by other init functions before use should not be initialized here.
* We try to initialize a single variable only once, to avoid confusion.
*
*/
void TransceiverStateInit(void)
{
// Defaults always
ts.txrx_mode = TRX_MODE_RX; // start in RX
ts.samp_rate = IQ_SAMPLE_RATE; // set sampling rate
//CONFIG LOADED: ts.band = BAND_MODE_20; // band from eeprom
ts.rx_temp_mute = false; // used in muting audio during band change
ts.filter_band = FILTER_BAND_UNKNOWN; // used to indicate the bpf filter selection for power detector coefficient selection
ts.dmod_mode = DEMOD_USB; // demodulator mode
//CONFIG LOADED: ts.rx_gain[RX_AUDIO_SPKR].value = AUDIO_GAIN_DEFAULT;
ts.rx_gain[RX_AUDIO_DIG].value = DIG_GAIN_DEFAULT;
//CONFIG LOADED:ts.rx_gain[RX_AUDIO_SPKR].max = MAX_VOLUME_DEFAULT; // Set max volume default
ts.rx_gain[RX_AUDIO_DIG].max = DIG_GAIN_MAX; // Set max volume default
ts.rx_gain[RX_AUDIO_SPKR].active_value = 1; // this variable is used in the active RX audio processing function
ts.rx_gain[RX_AUDIO_DIG].active_value = 1; // this variable is used in the active RX audio processing function
//CONFIG LOADED:ts.lineout_gain = LINEOUT_GAIN_DEFAULT;
//CONFIG LOADED:ts.rf_codec_gain = DEFAULT_RF_CODEC_GAIN_VAL; // Set default RF gain (0 = lowest, 8 = highest, 9 = "Auto")
ts.rit_value = 0; // RIT value
//CONFIG LOADED:ts.cw_sidetone_gain = DEFAULT_SIDETONE_GAIN; // Sidetone gain
//CONFIG LOADED:ts.cw_keyer_mode = CW_KEYER_MODE_IAM_B; // CW keyer mode
//CONFIG LOADED:ts.cw_keyer_speed = CW_KEYER_SPEED_DEFAULT; // CW keyer speed
//CONFIG LOADED:ts.cw_sidetone_freq = CW_SIDETONE_FREQ_DEFAULT; // CW sidetone and TX offset frequency
//CONFIG LOADED:ts.cw_paddle_reverse = 0; // Paddle defaults to NOT reversed
//CONFIG LOADED:ts.cw_rx_delay = CW_TX2RX_DELAY_DEFAULT; // Delay of TX->RX turnaround
//CONFIG LOADED:ts.cw_keyer_weight = CW_KEYER_WEIGHT_DEFAULT;
ts.audio_spkr_unmute_delay_count = VOICE_TX2RX_DELAY_DEFAULT; // TX->RX delay turnaround
ts.tune_freq = 0;
ts.menu_mode = 0; // menu mode
ts.menu_item = 0; // menu item selection
ts.menu_var = 0; // menu item change variable
ts.menu_var_changed = 0; // TRUE if a menu variable was changed and that an EEPROM save should be done
//NO INIT NEEDED? SET BEFORE USE? ts.tx_mic_boost = MIC_BOOST_DEFAULT; // no extra gain. electret element assumed
//CONFIG LOADED:ts.tx_audio_source = TX_AUDIO_MIC; // default source is microphone
//NO INIT NEEDED, SET BEFORE USE: ts.tx_mic_gain_mult = MIC_GAIN_DEFAULT; // actual operating value for microphone gain
//CONFIG LOADED:ts.tx_gain[TX_AUDIO_MIC] = MIC_GAIN_DEFAULT; // default line gain
//CONFIG LOADED:ts.tx_gain[TX_AUDIO_LINEIN_L] = LINE_GAIN_DEFAULT; // default line gain
ts.tx_gain[TX_AUDIO_LINEIN_R] = LINE_GAIN_DEFAULT; // default line gain
ts.tx_gain[TX_AUDIO_DIG] = LINE_GAIN_DEFAULT; // default line gain
ts.tx_gain[TX_AUDIO_DIGIQ] = LINE_GAIN_DEFAULT; // default line gain
ts.tune = false; // reset tuning flag
//NO INIT NEEDED, SET BEFORE USE:ts.tx_power_factor = 0.50; // TX power factor
//CONFIG LOADED:ts.pa_bias = PA_BIAS_DEFAULT; // Use lowest possible voltage as default
//CONFIG LOADED:ts.pa_cw_bias = PA_BIAS_DEFAULT; // Use lowest possible voltage as default (nonzero sets separate bias for CW mode)
//CONFIG LOADED:ts.freq_cal = 0; // Initial setting for frequency calibration
//CONFIG LOADED:ts.power_level = PA_LEVEL_DEFAULT; // See uhsdr_board.h for setting
ts.powering_down = 0; // TRUE if powering down
//CONFIG LOADED:ts.xverter_mode = 0; // TRUE if transverter mode is active (e.g. offset of display)
//CONFIG LOADED:ts.xverter_offset = 0; // Frequency offset in transverter mode (added to frequency display)
// This is NOT reset by the LCD function, but must be enabled/disabled externally
//CONFIG LOADED:ts.demod_mode_disable = 0; // TRUE if a specific mode is to be disabled
//CONFIG LOADED:ts.tx_meter_mode = METER_SWR;
//CONFIG LOADED:ts.alc_decay = ALC_DECAY_DEFAULT; // ALC Decay (release) default value
//NO INIT NEEDED, SET BEFORE USE:ts.alc_decay_var = ALC_DECAY_DEFAULT; // ALC Decay (release) default value
//CONFIG LOADED:ts.alc_tx_postfilt_gain = ALC_POSTFILT_GAIN_DEFAULT; // Post-filter added gain default (used for speech processor/ALC)
//NO INIT NEEDED, SET BEFORE USEts.alc_tx_postfilt_gain_var = ALC_POSTFILT_GAIN_DEFAULT; // Post-filter added gain default (used for speech processor/ALC)
//CONFIG LOADED:ts.tx_comp_level = 0; // 0=Release Time/Pre-ALC gain manually adjusted, >=1: Value calculated by this parameter
ts.freq_step_config = 0; // disabled both marker line under frequency and swapping of STEP buttons
ts.lcd_backlight_brightness = 0; // = 0 full brightness
ts.lcd_backlight_blanking = 0; // MSB = 1 for auto-off of backlight, lower nybble holds time for auto-off in seconds
//CONFIG LOADED:ts.low_power_config = LOW_POWER_THRESHOLD_DEFAULT; // add LOW_POWER_THRESHOLD_OFFSET for voltage value
ts.tune_step = 0; // Used for press-and-hold step size changing mode
ts.frequency_lock = 0; // TRUE if frequency knob is locked
//CONFIG LOADED:ts.tx_disable = TX_DISABLE_OFF; // > 0 if transmitter is to be disabled
//CONFIG LOADED:ts.flags1 = 0; // Used to hold individual status flags, stored in EEPROM location "EEPROM_FLAGS1"
//CONFIG LOADED:ts.flags2 = 0; // Used to hold individual status flags, stored in EEPROM location "EEPROM_FLAGS2"
ts.sysclock = 0; // This counts up from zero when the unit is powered up at precisely 100 Hz over the long term. This
// is NEVER reset and is used for timing certain events.
ts.version_number_release = 0; // version release - used to detect firmware change
ts.version_number_major = 0; // version build - used to detect firmware change
//CONFIG LOADED:ts.cw_offset_mode = CW_OFFSET_USB_RX; // CW offset mode (USB, LSB, etc.)
ts.cw_lsb = false; // Flag that indicates CW operates in LSB mode when TRUE
//CONFIG LOADED:ts.iq_freq_mode = FREQ_IQ_CONV_MODE_DEFAULT; // used to set/configure the I/Q frequency/conversion mode
//CONFIG LOADED:ts.lsb_usb_auto_select = 0; // holds setting of LSB/USB auto-select above/below 10 MHz
ts.last_tuning = 0; // this is a timer used to hold off updates of the spectrum scope when an SPI LCD display interface is used
ts.lcd_blanking_time = 0; // this holds the system time after which the LCD is blanked - if blanking is enabled
ts.lcd_blanking_flag = 0; // if TRUE, the LCD is blanked completely (e.g. backlight is off)
ts.xvtr_adjust_flag = 0; // set TRUE if transverter offset adjustment is in process
//CONFIG LOADED:ts.vfo_mem_mode = 0; // this is used to record the VFO/memory mode (0 = VFO "A" = backwards compatibility)
//CONFIG LOADED:ts.voltmeter_calibrate = POWER_VOLTMETER_CALIBRATE_DEFAULT; // Voltmeter calibration constant
// spectrum general settings
//CONFIG LOADED:ts.spectrum_filter = SPECTRUM_FILTER_DEFAULT; // default filter strength for spectrum scope
//CONFIG LOADED:ts.spectrum_centre_line_colour = SPEC_COLOUR_GRID_DEFAULT; // color of center line of scope grid
//CONFIG LOADED:ts.spectrum_freqscale_colour = SPEC_COLOUR_SCALE_DEFAULT; // default colour for the spectrum scope frequency scale at the bottom
//CONFIG LOADED:ts.spectrum_db_scale = DB_DIV_10; // default to 10dB/division
//CONFIG LOADED:ts.spectrum_size = SPECTRUM_SIZE_DEFAULT; // adjustment for waterfall size
//CONFIG LOADED:ts.spectrum_agc_rate = SPECTRUM_SCOPE_AGC_DEFAULT; // load default spectrum scope AGC rate
// scope ui settings
//CONFIG LOADED:ts.scope_trace_colour = SPEC_COLOUR_TRACE_DEFAULT; // default colour for the spectrum scope trace
//CONFIG LOADED:ts.scope_grid_colour = SPEC_COLOUR_GRID_DEFAULT; // default colour for the spectrum scope grid
//CONFIG LOADED:ts.scope_speed = SPECTRUM_SCOPE_SPEED_DEFAULT; // default rate of spectrum scope update
ts.scope_scheduler = 0; // timer for scheduling the next update of the spectrum update
//CONFIG LOADED:ts.waterfall.speed = WATERFALL_SPEED_DEFAULT; // default speed of update of the waterfall
//CONFIG LOADED:ts.waterfall.color_scheme = WATERFALL_COLOR_DEFAULT; // color scheme for waterfall display
//CONFIG LOADED:ts.waterfall.vert_step_size = WATERFALL_STEP_SIZE_DEFAULT; // step size in waterfall display
//CONFIG LOADED:ts.waterfall.contrast = WATERFALL_CONTRAST_DEFAULT; // contrast setting for waterfall display
ts.waterfall.scheduler=0;
// ts.fft_window_type = FFT_WINDOW_DEFAULT; // FFT Windowing type
ts.dvmode = false; // disable "DV" mode RX/TX functions by default
ts.txrx_switch_audio_muting_timing = 0; // timing value used for muting TX audio when keying PTT to suppress "click" or "thump"
ts.audio_dac_muting_timer = 0; // timer used for muting TX audio when keying PTT to suppress "click" or "thump"
ts.audio_dac_muting_flag = 0; // when TRUE, audio is to be muted after PTT/keyup
//CONFIG LOADED:ts.filter_disp_colour = FILTER_DISP_COLOUR_DEFAULT;
ts.vfo_mem_flag = 0; // when TRUE, memory mode is enabled
ts.mem_disp = 0; // when TRUE, memory list is enabled
ts.xvtr_disp = false; // when TRUE, XVTR list is enabled
//CONFIG LOADED:ts.fm_subaudible_tone_gen_select = 0; // lookup ("tone number") used to index the table generation (0 corresponds to "tone disabled")
//CONFIG LOADED:ts.fm_tone_burst_mode = 0; // this is the setting for the tone burst generator
ts.fm_tone_burst_timing = 0; // used to time the duration of the tone burst
//CONFIG LOADED:ts.fm_sql_threshold = FM_SQUELCH_DEFAULT; // squelch threshold
//CONFIG LOADED:ts.fm_subaudible_tone_det_select = 0; // lookup ("tone number") used to index the table for tone detection (0 corresponds to "tone disabled")
ts.ser_eeprom_type = 0; // serial eeprom not present
ts.configstore_in_use = CONFIGSTORE_IN_USE_FLASH; // serial eeprom not in use
ts.tp = &mchf_touchscreen;
ts.display = &mchf_display;
ts.show_debug_info = false; // dont show coordinates on LCD
ts.show_wide_spectrum = false; // default mode of spectrum wide on screen
//CONFIG LOADED:ts.tune_power_level = 0; // Tune with FULL POWER
ts.power_scale_gen = 100; // power scale for Gen, %
ts.power_scale_gen_full = 100; // power scale for Gen, FULL POWER, %
//CONFIG LOADED:ts.xlat = 0; // 0 = report base frequency, 1 = report xlat-frequency;
ts.audio_int_counter = 0; // test DL2FW
ts.cat_band_index =255; // no CAT command arrived
ts.s_meter = 1; // S-Meter configuration, 0 = old school, 1 = dBm-based, 2=dBm/Hz-based
//CONFIG LOADED:ts.display_dbm = 0; // style of dBm display, 0=OFF, 1= dbm, 2= dbm/Hz
// ts.dBm_count = 0; // timer start
//CONFIG LOADED:ts.tx_filter = 0; // which TX filter has been chosen by the user
//CONFIG LOADED: ts.iq_auto_correction = 1; // disable/enable automatic IQ correction
ts.twinpeaks_tested = TWINPEAKS_WAIT;
//CONFIG LOADED:ts.dbm_constant = 0;
ts.i2c_speed[I2C_BUS_1] = I2C1_SPEED_DEFAULT; // Si570, MCP9801
ts.i2c_speed[I2C_BUS_2] = I2C2_SPEED_DEFAULT; // Codec, EEPROM
ts.keyer_mode.active = false;
ts.keyer_mode.button_recording = KEYER_BUTTON_NONE;
for (int idx = 0; idx<KEYER_BUTTONS; idx++)
{
ts.keyer_mode.macro[idx][0] = '\0';
// strcpy((char *) ts.keyer_mode.cap[idx], "BTN");
strcpy((char *) ts.keyer_mode.cap[idx], "EMPTY");
}
// ts.buffered_tx = false;
ts.keyer_mode_tx = 0;
ts.keyer_cycled_tx_active = false;
ts.keyer_cycled_tx_timer = 0;
ts.keyer_cycled_tx_button = 1;
ts.keyer_cycled_interval = 3; // 3 sec.
ts.cw_beacon_interval = 18000; // 3 min
ts.swbi = BEACON_INTERVAL_3M; // cw beacon interval numerator
ts.peak_ind_tune = 3; // timer 0.75 sec
ts.cw_text_entry = false;
ts.ExtFMenuActive = false;
ts.XvtrFMenuActive = false;
ts.MenuOfFMenusActive = false;
ts.debug_si5351a_pllreset = 2; //start with "reset on IQ Divider"
ts.debug_vswr_protection_threshold = 1; // OFF
//CONFIG LOADED:ts.expflags1 = 0; // Used to hold flags for options in Debug/Expert menu, stored in EEPROM location "EEPROM_EXPFLAGS1"
ts.lotx_dacs_present = false; // TX LO Supression DACs MCP4725 (x096/x097) is not present
for (int idx = 0; idx < 15; idx++) // Band calibrated values for DACs MCP4725
{
ts.cal_lo_tx_supr0[idx] = 2048; // Half of +5V for each
ts.cal_lo_tx_supr1[idx] = 2048; // Half of +5V for each
}
ts.band_index = 255; // Index of current band in table (by tune freq) - invalid for start
ts.HereIsEnableCB26Mc = false; // Tune on enable CB band 26 Mc
ts.HereIsEnableCB27Mc = false; // Tune on enable CB band 27 Mc
ts.band_lo_tx_supr = 255; // Invalid band number (the band of currently selected frequency (CB band 27 MHz == 28 MHz))
ts.band_lo_tx_supr_old = 255; // Invalid band number - old value bla-bla-bla
ts.band_effective = NULL; // this is an invalid band number, which will trigger a redisplay of the band name and the effective power
//#ifdef SDR_AMBER
ts.amber_input_state = 0; // Amber - state of RX input group, - PRE(amp)
#ifdef SDR_AMBER
ts.amber_io8_present = false; // I/Ox8 PCF8574A
ts.amber_io8_state = 255;
ts.amber_io4_present = false; // I/Ox4 PCA9536
ts.amber_io4_state = 0;
ts.amber_dac_pwr_tx_present = false; // DAC MCP4725 for TX PWR reg.
ts.amber_dac_pwr_tx_state = 2048;
ts.amber_pa_bandcode_mode = 0;
#endif
ts.box_colour = 2; // =Blue - screen boxes colour
ts.txtline_colour = 9; // =Yellow - ticker colour
ts.cw_smooth = 1; // smooth of CW signal edges == 5 ms
ts.cw_smooth_len = 2; // duration of CW signal edges
ts.cw_smooth_steps = 9; // duration steps of CW signal edges
ts.anr_n_taps = 64;
ts.anr_delay = 12; //16;
ts.anr_two_mu_int = 100;
ts.anr_gamma_int = 100;
ts.dummy = 0;
ts.disabled_tp = false;
#ifdef FAST_FREQ_ENC
ts.freq_enc_timer = 0;
#endif
// ts.iq_freq_delta = 10;//0; //Hz
ts.it_is_band = true;
#ifdef HELP_MENU
ts.menu_selected_item = 280; // MENU_DEBUG_SHOW_GREETING, No comment
ts.help_showing = false;
#endif
ts.maxi_pos_contest = 23;
ts.maxi_pos_contesttry = 23;
ts.cmem_colour = White;
}
// #include "Trace.h"
#if 0
void timeTest1()
{
static uint32_t time = 0;
if (time != RTC->TR)
{
Board_RedLed(LED_STATE_TOGGLE);
time = RTC->TR;
}
}
void timeTest()
{
MchfRtc_Start();
while (1)
{
timeTest1();
}
}
#endif
// Power on
int mchfMain(void)
{
///trace_puts("Hello mcHF World!");
// trace_printf(" %u\n", 1u);
// *(__IO uint32_t*)(SRAM2_BASE) = 0x0; // clearing delay prevent for bootloader
// Set default transceiver state
TransceiverStateInit();
Board_RamSizeDetection();
#ifdef TESTCPLUSPLUS
test_call_cpp();
#endif
// HW init
Board_InitMinimal();
// Show logo & HW Info
UiDriver_StartUpScreenInit(2000);
if (ts.display != DISPLAY_NONE)
{
// TODO: Better indication of non-detected display
Board_GreenLed(LED_STATE_ON);
}
Board_InitFull();
ConfigStorage_Init();
// init mchf_touchscreen to see if it is present
// we don't care about the screen being reverse or not
// here, so we simply set reverse to false
UiLcdHy28_TouchscreenInit(0);
Main_DetectSpecialBootloader();
UiDriver_Init();
#ifdef STM32F4
// we now re-init the I2C buses with the configured speed settings. Loading the EEPROM always uses the default speed!
// we can do this only on the STM32F4 as we are not able to change
// the speed on the STM32F7/H7 easily via HAL in a portable way
UhsdrHw_I2C_ChangeSpeed(&hi2c1);
UhsdrHw_I2C_ChangeSpeed(&hi2c2);
#endif
profileTimedEventInit();
#ifdef USE_HMC1023
hmc1023_init();
#endif
// Audio Software Init
AudioDriver_Init();
// Audio Driver Hardware Init
ts.codecCS4270_present = false;
ts.rf_gain_codecCS4270 = 1.0;
ts.codec_present = Codec_Reset(ts.samp_rate) == HAL_OK;
#ifndef SDR_AMBER
UiDriver_StartupScreen_LogIfProblem(ts.codec_present == false,
"Audiocodec WM8731 NOT detected!");
#else
#ifdef UI_BRD_MCHF
UiDriver_StartupScreen_LogIfProblem(ts.codec_present == false,
"Audiocodec WM8731 NOT detected!");
#else // OVI40 or Amber
UiDriver_StartupScreen_LogIfProblem(ts.codecWM8731_Audio_present == false,
"Audio codec WM8731 NOT detected!");
if(ts.codecCS4270_present)
{
// Amber-UI board
}
else if(!(ts.codec_present) && ts.codecWM8731_Audio_present)
{
UiDriver_StartupScreen_LogIfProblem(true,
"IQ codec WM8731/AS4270 NOT detected!");
}
// Test
GPIO_ResetBits(BAND1_PIO,BAND1);
#endif
#endif
const char* bl_version = Board_BootloaderVersion();
UiDriver_StartupScreen_LogIfProblem(
(bl_version[0] == '1' || bl_version[0] == '2' || bl_version[0] == '3' || bl_version[0] == '4') && bl_version[1] == '.',
"Upgrade bootloader to 5.0.1 or newer");
AudioFilter_SetDefaultMemories();
ts.rx_gain[RX_AUDIO_SPKR].value_old = 0; // Force update of volume control
// TX LO Supression DACs MCP4725 (x096/x097) is present?
ts.lotx_dacs_present = (UhsdrHw_I2C_DeviceReady(SERIALEEPROM_I2C,LO_TX_SUPR_DAC0_WRITE) == HAL_OK) && (UhsdrHw_I2C_DeviceReady(SERIALEEPROM_I2C,LO_TX_SUPR_DAC1_WRITE) == HAL_OK);
#ifdef SDR_AMBER
ts.amber_io8_present = UhsdrHw_I2C_DeviceReady(SERIALEEPROM_I2C,AMBER_IO8_WRITE) == HAL_OK;
ts.amber_io4_present = UhsdrHw_I2C_DeviceReady(SERIALEEPROM_I2C,AMBER_IO4_WRITE) == HAL_OK;
ts.amber_dac_pwr_tx_present = UhsdrHw_I2C_DeviceReady(SI5351A_I2C,AMBER_DAC_PWR_TX_WRITE) == HAL_OK;
#endif
#ifdef USE_FREEDV
FreeDV_Init();
// we now try to place a marker after last dynamically
// allocated memory
Canary_Create();
#endif
UiDriver_StartUpScreenFinish(2000);
// We initialize the requested demodulation mode
// and update the screen accordingly
UiDriver_SetDemodMode(ts.dmod_mode);
// Finally, start DMA transfers to get everything going
UhsdrHwI2s_Codec_StartDMA();
// now enable paddles/ptt, i.e. external input
ts.paddles_active = true;
Board_RedLed(LED_STATE_OFF);
// Eliminate sound blocking on boot in RX-slide mode
if(ts.iq_freq_delta == 0)
{
ts.iq_freq_delta = 10; // Hz
}
// Transceiver main loop
for(;;)
{
// UI events processing
UiDriver_TaskHandler_MainTasks();
}
return 0;
}
@@ -0,0 +1,35 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _MCHF_MAIN_H
#define _MCHF_MAIN_H
#include "uhsdr_board.h"
#ifdef __cplusplus
extern "C" {
#endif
int mchfMain(void);
#ifdef __cplusplus
}
#endif
#endif /* _MCHF_MAIN */
@@ -0,0 +1,35 @@
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
/************************************************************************************
** **
** UHSDR **
** a powerful firmware for STM32 based SDR transceivers **
** **
**---------------------------------------------------------------------------------**
** **
** File name: **
** Description: **
** Last Modified: **
** Licence: GNU GPLv3 **
************************************************************************************/
#define UHSDR_VER_MAJOR "2"
#define UHSDR_VER_MINOR "12"
#define UHSDR_VER_RELEASE "2m10"
#define UHSDR_BOOT_VERS "5.0.4m"
#ifdef SBLA // Bootloader enables additional rf bands PCB
#define UHSDR_BOOT_VER UHSDR_BOOT_VERS"a"
#elif SBLS // Bootloader enables special debug capabilities
#define UHSDR_BOOT_VER UHSDR_BOOT_VERS"s"
#else // Standard Bootloader
#define UHSDR_BOOT_VER UHSDR_BOOT_VERS
#endif
// trailing characters are needed for identifying version and building date+time in binary
#define UHSDR_VERSION "fwv-"UHSDR_VER_MAJOR"."UHSDR_VER_MINOR"."UHSDR_VER_RELEASE
#define UHSDR_BUILD_DAT "fwt-"__DATE__ " - " __TIME__
#define UHSDR_LICENCE "GNU GPLv3"
#define UHSDR_REPO "github.com/df8oe/UHSDR"