Lianshengde HLK-W806 (Part 3): Automatic download and reset without buttons

Publisher:chwwdchLatest update time:2022-06-21 Source: eefocusKeywords:reset Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

No-button automatic reset download

If you just want to know how to use it, just read this part. Update the SDK to the latest version in the project, find this file include/arch/xt804/csi_config.h in the SDK, and change the value of the following line from 0 to 1


#define USE_UART0_AUTO_DL          0 // Auto download, 0:OFF, 1:ON


Then compile and burn it to the development board according to the normal operation process. After that, the burning can be automatically downloaded without pressing buttons. It will automatically reset before downloading and after downloading.


Notice:


This feature is only suitable for development and testing stages and cannot be used in production environments.

This function (and the default printf printing) will occupy UART0. If your project needs to use UART0 to communicate with other devices, you must turn off this function.

Functional analysis of keyless downloading

Analysis of the instructions for burning and downloading

In tools/W806/rules.mk


flash:all

    @$(WM_TOOL) -c $(DL_PORT) -rs at -ds $(DL_BAUD) -dl $(FIRMWAREDIR)/$(TARGET)/$(TARGET).fls


You can see that make flash will first compile, then call wm_tool to download the fls file to the device according to the preset download port and download baud rate. In the normal download process, you need to reset the development board to enter the download mode first, then the actual download will start. After the download is completed, the development board will still be in the download mode. At this time, you need to reset the development board to enter the normal mode and run the user program. Now these two steps are completed manually by pressing the Reset key.


Burn download reset code

In the above command, there is a parameter -rs at, the description of this parameter is


-rs reset_action, set device reset method, default is manual control

         none - manual control device reset

         at   - use the at command to control the device reset

         rts  - use the serial port rts pin to control the device reset


The option corresponding to at is to use AT command to restart the device. There are two places corresponding to the restart action, which are the two time points where you need to press the Reset button manually.


Reset before downloading

For the reset before downloading, the processing in wm_tool is


if (WM_TOOL_DL_ACTION_AT == wm_tool_dl_action)

{

    if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate)

        wm_tool_uart_set_speed(wm_tool_normal_serial_rate);


#if 0 /* use erase option */

    if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type)

    {

        ret = wm_tool_uart_write("AT+&FLSW=8002000,0rn", strlen("AT+&FLSW=8002000,0rn"));

        if (ret <= 0)

        {

            wm_tool_printf("destroy secboot failed.rn");

            wm_tool_uart_close();

            return -3;

        }

        wm_tool_delay_ms(300);

    }

#endif


    ret = wm_tool_uart_write("AT+Zrn", strlen("AT+Zrn"));

    if (ret <= 0)

    {

        wm_tool_printf("reset error.rn");

        wm_tool_uart_close();

        return -4;

    }


    if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate)

        wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE);

}


...


wm_tool_printf("wait serial sync...");

wm_tool_send_esc2uart(500);/* used for delay */


It can be seen that the actual operation of wm_tool is to send the AT+Zrn command through the serial port, and then wait for 500ms to detect whether it is reset.


Reset after download

For the reset after download, only the rts option is processed in the code, and the at option is used here without any action.


...


if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type)

{

    if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action)/* auto reset */

    {

        wm_tool_uart_set_dtr(0);

        wm_tool_uart_set_rts(1);

        wm_tool_delay_ms(50);

        wm_tool_uart_set_dtr(1);

        wm_tool_uart_set_rts(0);

        wm_tool_delay_ms(50);

        wm_tool_uart_set_dtr(0);

    }

    else

    {

        wm_tool_printf("please manually reset the device.rn");

    }

}

...


Implementation of automatic reset during burning of W806

According to the above analysis, the automatic reset of W806 needs to be implemented in two places, one before downloading and one after downloading.


Reset implementation before downloading

Before downloading, the development board is still running in normal mode. At this time, the serial port is controlled by the user program. If you need to respond to serial port commands, you need to add the RX interrupt and command judgment of serial port 0 in the user program. For this step, you can refer to the implementation of UART0 as printf print output in SDK.


Add UART0 initialization


Add initialization code in platform/arch/xt804/bsp/board_init.c, and enable UART0 receive interrupt when configured as enabled


...

static void uart0Init (int bandrate)

{

    unsigned int bd;


#if USE_UART0_AUTO_DL

    WRITE_REG(UART0->INTM, ~UART_RX_INT_FLAG);

    NVIC_ClearPendingIRQ(UART0_IRQn);

    NVIC_EnableIRQ(UART0_IRQn);

#else

    NVIC_DisableIRQ(UART0_IRQn);

    NVIC_ClearPendingIRQ(UART0_IRQn);

#endif

...

}


Add UART0 receive interrupt response and command detection


Add a new component under platform/component and implement interrupt response and command detection in the component


/******************************************************************************

** 

 * file        auto_dl.c

 * author Xu Ruijun | 1687701765@qq.com

 * date        

 * brief       Reset device with UART0 AT+Z command

 * note        Set USE_UART0_AUTO_DL = 1 to enable this feature

 * version     

 * ingroup     

 * remarks     

 *

******************************************************************************/


#include "wm_hal.h"


#if USE_UART0_AUTO_DL


#define __AUTO_DL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->INTS |= __FLAG__)

#define __AUTO_DL_TIMEOUT 5

#define __AUTO_DL_BUF_SIZE 32


const static uint8_t auto_dl_cmd[] = {'A', 'T', '+', 'Z', 'r', 'n'};

uint8_t auto_dl_buf[__AUTO_DL_BUF_SIZE] = {0}, auto_dl_buf_pt = 0, auto_dl_cmd_pt = 0;

uint32_t auto_dl_act_ts = 0;


void AUTO_DL_Reset(void)

{

    CLEAR_REG(RCC->RST);                     // reset all peripherals

    uint32_t rv = *(uint32_t*)(0x00000000U); // get reset vector

    ((void (*)())(rv))();                    // go to ROM

}


__attribute__((weak)) void USER_UART0_RX(uint8_t ch)

{

    UNUSED(ch);

}


void AUTO_DL_UART_IRQHandler(USART_TypeDef* huart)

{

    uint8_t ch, count;

    uint32_t ts, isrflags = READ_REG(huart->INTS), isrmasks = READ_REG(huart->INTM);

    // Clear interrupts

    __AUTO_DL_UART_CLEAR_FLAG(huart, isrflags);


    if (((isrflags & UART_RX_INT_FLAG) != RESET) && ((isrmasks & UART_RX_INT_FLAG) == RESET))

    {

        /**

         *   1) Data always comes in as single bytes, so the count is always 1(or 0);

         *   2) Each byte will comes in twice, the second time with count=0 will be ignored;

         */

        count = ((READ_REG(huart->FIFOS) & UART_FIFOS_RFC) >> UART_FIFOS_RFC_Pos);

        while (count-- > 0)

        {

            // Write ch to ring buffer

            ch = (uint8_t)(huart->RDW);

            auto_dl_buf[auto_dl_buf_pt++] = ch;

            if (auto_dl_buf_pt == __AUTO_DL_BUF_SIZE) auto_dl_buf_pt = 0;


            // Command detection

            ts = HAL_GetTick();

            if ((ts - auto_dl_act_ts) > __AUTO_DL_TIMEOUT)

            {

                // Restart the comparison if timeout

                auto_dl_cmd_pt = 0;

                if (auto_dl_cmd[auto_dl_cmd_pt] == ch)

                {

                    auto_dl_cmd_pt++;

                }

            }

            else

            {

                // Avoid starting new comparison in the middle of RX

                if ((auto_dl_cmd[auto_dl_cmd_pt] == ch) && (auto_dl_cmd_pt > 0))

                {

                    auto_dl_cmd_pt++;

                    if (auto_dl_cmd_pt == sizeof(auto_dl_cmd))

                    {

                        AUTO_DL_Reset();

                    }

                }

                else

                {

                    // Restart the comparison

                    auto_dl_cmd_pt = 0;

                }

            }

            // Record last active timestamp

            auto_dl_act_ts = ts;

            USER_UART0_RX(ch);

        }

    }


    if (((isrflags & UART_INTS_TL) != RESET) && ((isrmasks & UART_INTM_RL) == RESET))

    {

        //UART_Transmit_IT(huart);

    }


    if (((isrflags & UART_INTS_TEMPT) != RESET) && ((isrmasks & UART_INTM_TEMPT) == RESET))

    {

        //UART_EndTransmit_IT(huart);

    }

}


__attribute__((isr)) void UART0_IRQHandler(void)

{

    AUTO_DL_UART_IRQHandler(UART0);

}


#endif


Reset after successful download

After the download is successful, the development board is still running in download mode, so just find the corresponding reset command in download mode. This command is


0x21, 0x06, 0x00, 0xc7, 0x7c, 0x3f, 0x00, 0x00, 0x00


Correspondingly, add this command constant in wm_tool.c


const static unsigned char wm_tool_chip_cmd_reset[]    = {0x21, 0x06, 0x00, 0xc7, 0x7c, 0x3f, 0x00, 0x00, 0x00};


And the processing logic for AT mode


if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type)

{

    if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action) // Use UART RTS pin to control the device reset

    {

        ...

    }

    else if(WM_TOOL_DL_ACTION_AT == wm_tool_dl_action) // Use AT command to reset the device

    {

        wm_tool_delay_ms(500);

        ret = wm_tool_uart_write(wm_tool_chip_cmd_reset, sizeof(wm_tool_chip_cmd_reset));

        wm_tool_delay_ms(30);

        if(ret > 0){

            wm_tool_printf("reset command has been sent.rn");

        }else{

            wm_tool_printf("reset command sending failed.rn");

        }

        right = 0;

    }

    ...

}

Keywords:reset Reference address:Lianshengde HLK-W806 (Part 3): Automatic download and reset without buttons

Previous article:HLK-W806 (IV): Software SPI and hardware SPI driver for ST7735 LCD
Next article:Lianshengde HLK-W806 (Part 2): Development environment configuration, compilation and burning instructions under Win10

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号