K1Guitar/AT32F403ARCT7_BOOT/project/src/main.c

367 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* add user code begin Header */
/**
**************************************************************************
* @file main.c
* @brief main program
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* add user code end Header */
/* Includes ------------------------------------------------------------------*/
#include "at32f403a_407_wk_config.h"
#include "wk_acc.h"
#include "wk_debug.h"
#include "wk_spi.h"
#include "wk_usbfs.h"
#include "usb_app.h"
#include "wk_system.h"
#include "includes.h"
#include <string.h>
#include "W25Q128.h"
#include "Drv_TM1617_RGB.h"
#include "UI0902_Res_Addr.h"
#include "drv_nvm.h"
#include "boot_flash_mode_ink.h"
/* private includes ----------------------------------------------------------*/
/* add user code begin private includes */
/* add user code end private includes */
/* private typedef -----------------------------------------------------------*/
/* add user code begin private typedef */
/* add user code end private typedef */
/* private define ------------------------------------------------------------*/
/* add user code begin private define */
//
// Power Button
//
#define POWER_BUTTON_PIN GPIO_PINS_2
#define POWER_BUTTON_PORT GPIOD
//
// Main Power
//
#define S_PWR_ON_OFF_Pin GPIO_PINS_2
#define S_PWR_ON_OFF_GPIO_Port GPIOB
#define FIRMWARE_START_ADDR 0x08008000
/* add user code end private define */
/* private macro -------------------------------------------------------------*/
/* add user code begin private macro */
/* add user code end private macro */
/* private variables ---------------------------------------------------------*/
/* add user code begin private variables */
/* add user code end private variables */
/* private function prototypes --------------------------------------------*/
/* add user code begin function prototypes */
/* add user code end function prototypes */
/* private user code ---------------------------------------------------------*/
/* add user code begin 0 */
void wk_gpio_config(void);
void JumpToApplication(void);
uint8_t TM1617KeyValue = 0;
static uint32_t PowerKeyCount = 0;
static uint8_t long_press_locked = 0; // ???????????????????
/* add user code end 0 */
static uint16_t Boot_NvmSum(const uint8_t *p, uint16_t len)
{
uint16_t sum = 0;
while (len > 0) {
sum = (uint16_t)(sum + *p++);
len--;
}
return sum;
}
static uint8_t Boot_NvmUsbUpdateRequested(void)
{
const NvmData_Type *nvm = (const NvmData_Type *)INNER_FLASH_SAVE_ADDRESS;
uint16_t s0 = Boot_NvmSum((const uint8_t *)&nvm->data, sizeof(NvmParam_Type));
if (s0 != nvm->sum[0] || (uint16_t)(~s0) != nvm->sum[1])
return 0;
if (nvm->data.nvm_version != NVM_VERSION)
return 0;
return (nvm->data.param.UsbMode == NVM_USB_UPDATE) ? 1 : 0;
}
/* 外部图把字画成了页面底色,铺出来是黑屏。字行中间有接近白色的像素才采用它。 */
static uint8_t Boot_FlashModeHasLight(void)
{
uint8_t row[172];
uint16_t i;
W25Q128_Read(row,
UI0902_FLASH_MODE_ADDR + (158ul * 240ul + 78ul) * 2ul,
(uint16_t)sizeof(row));
for (i = 0; i + 1u < sizeof(row); i += 2)
{
uint16_t c = (uint16_t)(((uint16_t)row[i] << 8) | row[i + 1]);
if (c >= 0xC618)
return 1;
}
return 0;
}
static void Boot_DrawFlashModeInk(void)
{
uint16_t row, col, stride;
LCD_FillByColor(0, 0, 240, 320, 0x0042);
stride = (uint16_t)((BOOT_FLASH_INK_W + 7u) >> 3);
for (row = 0; row < BOOT_FLASH_INK_H; row++)
{
const uint8_t *p = boot_flash_ink + (uint32_t)row * stride;
for (col = 0; col < BOOT_FLASH_INK_W; col++)
{
if (p[col >> 3] & (uint8_t)(0x80u >> (col & 7)))
LCD_DrawPoint((uint16_t)(BOOT_FLASH_INK_X + col),
(uint16_t)(BOOT_FLASH_INK_Y + row), WHITE);
}
}
}
static void Boot_NvmClearUsbUpdate(void)
{
NvmData_Type tmp;
uint16_t s0;
uint32_t i;
uint32_t words;
uint32_t buf[(sizeof(NvmData_Type) + 3) / 4];
memcpy(&tmp, (const void *)INNER_FLASH_SAVE_ADDRESS, sizeof(tmp));
if (tmp.data.param.UsbMode != NVM_USB_UPDATE)
return;
tmp.data.param.UsbMode = NVM_USB_MIDI;
s0 = Boot_NvmSum((const uint8_t *)&tmp.data, sizeof(NvmParam_Type));
tmp.sum[0] = s0;
tmp.sum[1] = (uint16_t)(~s0);
memset(buf, 0xFF, sizeof(buf));
memcpy(buf, &tmp, sizeof(tmp));
words = (sizeof(tmp) + 3) / 4;
flash_unlock();
flash_sector_erase(INNER_FLASH_SECTOR_ADDRESS);
for (i = 0; i < words; i++)
flash_word_program(INNER_FLASH_SAVE_ADDRESS + i * 4, buf[i]);
flash_lock();
}
flag_status BSP_GetPowerKey (void)
{
return gpio_input_data_bit_read(POWER_BUTTON_PORT, POWER_BUTTON_PIN);
}
void BSP_MainPowerEnable (uint8_t Enable)
{
if (Enable) gpio_bits_set(S_PWR_ON_OFF_GPIO_Port, S_PWR_ON_OFF_Pin);
else gpio_bits_reset(S_PWR_ON_OFF_GPIO_Port, S_PWR_ON_OFF_Pin);
}
/**
* @brief main function.
* @param none
* @retval none
*/
int main(void)
{
/* add user code begin 1 */
/* add user code end 1 */
/* system clock config. */
wk_system_clock_config();
/* config periph clock. */
wk_periph_clock_config();
/* gpio config */
wk_gpio_config();
/* init debug function. */
wk_debug_config();
/* nvic config. */
wk_nvic_config();
/* timebase config. */
wk_timebase_init();
TM1617_GPIO_Init();
/* 按住圆键 4(KEY_MAIN_A),或 App 确认了 USB 更新,都停在烧录。
* USB 更新有两处标志:Flash 里的 UsbMode,以及复位后仍在的备份寄存器。
* 没按键且两处都没有标志才跳进 App。 */
wk_delay_ms(50);
TM1617KeyValue = TM1617_ScanFkey();
if (TM1617KeyValue != KEY_MAIN_A &&
!Boot_NvmUsbUpdateRequested() &&
!drv_nvm_usb_boot_armed())
{
JumpToApplication();
}
/* init spi1 function. */
BSP_MainPowerEnable(1);
wk_spi1_init();
/* init spi2 function. */
/* init acc function. */
wk_acc_init();
/* add user code begin 2 */
W25Q128_Init();
LCD_Init();
wk_delay_ms(10);
/* USER CODE BEGIN 2 */
LCD_BLK_Set();
/* <20><><EFBFBD>???<3F><>?<3F><>UI0902_FLASH_MODE @ <20><><EFBFBD><EFBFBD> Flash<73><68>?<3F><><EFBFBD><EFBFBD>??<3F>??<3F><><EFBFBD> */
{
uint8_t peek[4];
W25Q128_Read(peek, UI0902_FLASH_MODE_ADDR, 4);
if (!(peek[0] == 0xFF && peek[1] == 0xFF && peek[2] == 0xFF && peek[3] == 0xFF) &&
Boot_FlashModeHasLight())
{
LCD_WR_PIC_FROM_FLASH(0, 0, UI0902_FLASH_MODE_W, UI0902_FLASH_MODE_H,
UI0902_FLASH_MODE_ADDR);
}
else
{
Boot_DrawFlashModeInk();
}
}
/* 画面出来后再清标志,避免还没进烧录就被下一次复位跳回 App。
* 擦写与 Boot 同在 Flash Bank1,期间关掉中断。 */
if (Boot_NvmUsbUpdateRequested() || drv_nvm_usb_boot_armed())
{
__disable_irq();
if (Boot_NvmUsbUpdateRequested())
Boot_NvmClearUsbUpdate();
drv_nvm_clear_usb_boot_arm();
__enable_irq();
}
wk_usbfs_init();
wk_usb_app_init();
/* add user code end 2 */
while(1)
{
/* add user code begin 3 */
if(BSP_GetPowerKey() == 0)
{
// ????????
if (PowerKeyCount < 200 && long_press_locked == 0)
{
PowerKeyCount++;
}
if (PowerKeyCount >= 150 && long_press_locked == 0)
{
LCD_BLK_Clr();
BSP_MainPowerEnable(0);
wk_delay_ms(3000);
}
wk_delay_ms(10);
}
/* add user code end 3 */
}
}
/* add user code begin 4 */
void wk_gpio_config(void)
{
/* add user code begin gpio_config 0 */
/* add user code end gpio_config 0 */
gpio_init_type gpio_init_struct;
gpio_default_para_init(&gpio_init_struct);
/* add user code begin gpio_config 1 */
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
/* add user code end gpio_config 1 */
/* gpio input config */
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_2;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOD, &gpio_init_struct);
/* gpio output config */
gpio_bits_reset(GPIOB, GPIO_PINS_9 | GPIO_PINS_2);
gpio_bits_set(GPIOC, GPIO_PINS_13);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_13;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOC, &gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_2 | GPIO_PINS_9;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOB, &gpio_init_struct);
/* gpio analog config */
/* add user code begin gpio_config 2 */
/* add user code end gpio_config 2 */
}
/* add user code end 4 */
void JumpToApplication(void)
{
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
if (((*(__IO uint32_t*)FIRMWARE_START_ADDR) & 0x2FFE0000 ) == 0x20000000)
{
/* ???????????????? */
JumpAddress = *(__IO uint32_t*) (FIRMWARE_START_ADDR + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* ??????????<3F><>????????? */
__set_MSP(*(__IO uint32_t*) FIRMWARE_START_ADDR);
SCB->VTOR = FIRMWARE_START_ADDR;
Jump_To_Application();
}
}