⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bl_autobaud.c

📁 ARM-CORTEX LM3S系列远程下载更新程序
💻 C
字号:
//*****************************************************************************
//
// bl_autobaud.c - Automatic baud rate detection code.
//
// Copyright (c) 2006-2007 Luminary Micro, Inc.  All rights reserved.
// 
// Software License Agreement
// 
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
// 
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  You may not combine
// this software with "viral" open-source software in order to form a larger
// program.  Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
// 
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 1928 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************

#include "../hw_gpio.h"
#include "../hw_memmap.h"
#include "../hw_nvic.h"
#include "../hw_types.h"
#include "bl_config.h"
#include "bl_uart.h"

//*****************************************************************************
//
// If using auto-baud, make sure that the data buffer is large enough.
//
//*****************************************************************************
#if defined(UART_ENABLE_UPDATE) && defined(UART_AUTOBAUD) && (BUFFER_SIZE < 20)
#error ERROR: BUFFER_SIZE must be >= 20!
#endif

//*****************************************************************************
//
//! \addtogroup boot_loader_api
//! @{
//
//*****************************************************************************
#if defined(UART_ENABLE_UPDATE) && defined(UART_AUTOBAUD) || defined(DOXYGEN)

//*****************************************************************************
//
// This define holds the multiplier for the pulse detection algorithm.  The
// value is used to generate a fractional difference detection of
// 1 / PULSE_DETECTION_MULT.
//
//*****************************************************************************
#define PULSE_DETECTION_MULT    3

//*****************************************************************************
//
// This define holds the minimum number of edges to successfully sync to a
// pattern of 2 bytes.
//
//*****************************************************************************
#define MIN_EDGE_COUNT          18

//*****************************************************************************
//
// This global holds the number of edges that have been stored in the global
// buffer g_pulDataBuffer.
//
//*****************************************************************************
static volatile unsigned long g_ulTickIndex;

//*****************************************************************************
//
// The data buffer that is used for receiving packets is used to hold the edge
// times during auto-baud.  The buffer is not used for receiving packets while
// auto-baud is in progress, so this does not present problems.
//
//*****************************************************************************
extern unsigned long g_pulDataBuffer[];

//*****************************************************************************
//
//! Handles the UART Rx GPIO interrupt.
//!
//! When an edge is detected on the UART Rx pin, this function is called to
//! save the time of the edge.  These times are later used to determine the
//! ratio of the UART baud rate to the processor clock rate.
//!
//! This function is contained in <tt>bl_autobaud.c</tt>.
//!
//! \return None.
//
//*****************************************************************************
void
GPIOIntHandler(void)
{
    unsigned long ulTemp;

    //
    // Clear the GPIO interrupt source.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_ICR) = UART_RX;

    //
    // While we still have space in our buffer, store the current system tick
    // count and return from interrupt.
    //
    if(g_ulTickIndex < 20)
    {
        ulTemp = HWREG(NVIC_ST_CURRENT);
        g_pulDataBuffer[g_ulTickIndex++] = ulTemp;
    }
}

//*****************************************************************************
//
//! Performs auto-baud on the UART port.
//!
//! \param pulRatio is the ratio of the processor's crystal frequency to the
//! baud rate being used by the UART port for communications.
//!
//! This function attempts to synchronize to the updater program that is trying
//! to communicate with the boot loader.  The UART port is monitored for edges
//! using interrupts.  Once enough edges are detected, the boot loader
//! determines the ratio of baud rate and crystal frequency needed to program
//! the UART.
//!
//! This function is contained in <tt>bl_autobaud.c</tt>.
//!
//! \return Returns a value of 0 to indicate that this call successfully
//! synchronized with the other device communicating over the UART, and a
//! negative value to indicate that this function did not successfully
//! synchronize with the other UART device.
//
//*****************************************************************************
int
UARTAutoBaud(unsigned long *pulRatio)
{
    long lPulse, lValidPulses, lTemp, lTotal;
    volatile long lDelay;

    //
    // Configure and enable SysTick.  Set the reload value to the maximum;
    // there are only 24 bits in the register but loading 32 bits of ones is
    // more efficient.
    //
    HWREG(NVIC_ST_RELOAD) = 0xffffffff;
    HWREG(NVIC_ST_CTRL) = NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_ENABLE;

    //
    // Reset the counters that control the pulse detection.
    //
    lValidPulses = 0;
    lTotal = 0;
    g_ulTickIndex = 0;

    //
    // Set the pad(s) for standard push-pull operation.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_PUR) |= UART_RX;
    HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= UART_RX;

    //
    // Interrupt on both edges.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_IBE) = UART_RX;

    //
    // Clear out all of the gpio interrupts in this register.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_ICR) = UART_RX;

    //
    // Enable the GPIO pin corresponding to the UART RX pin.
    //
    HWREG(GPIO_PORTA_BASE + GPIO_O_IM) = UART_RX;

    //
    // Enable GPIOA Interrupt.
    //
    HWREG(NVIC_EN0) = 1;

    //
    // Wait for MIN_EDGE_COUNT to pass to collect enough edges.
    //
    while(g_ulTickIndex < MIN_EDGE_COUNT)
    {
    }

    //
    // Disable GPIOA Interrupt.
    //
    HWREG(NVIC_DIS0) = 1;

    //
    // Calculate the pulse widths from the array of tick times.
    //
    for(lPulse = 0; lPulse < (MIN_EDGE_COUNT - 1); lPulse++)
    {
        lTemp = (((long)g_pulDataBuffer[lPulse] -
                  (long)g_pulDataBuffer[lPulse + 1]) & 0x00ffffff);
        g_pulDataBuffer[lPulse] = lTemp;
    }

    //
    // This loops handles checking for consecutive pulses that have pulse
    // widths that are within an acceptable margin.
    //
    for(lPulse = 0; lPulse < (MIN_EDGE_COUNT - 1); lPulse++)
    {
        //
        // Calculate the absolute difference between two consecutive pulses.
        //
        lTemp = (long)g_pulDataBuffer[lPulse];
        lTemp -= (long)g_pulDataBuffer[lPulse + 1];
        if(lTemp < 0)
        {
            lTemp *= -1;
        }

        //
        // This pulse detection code uses the following algorithm:
        // If the following is true then we have consecutive acceptable pulses
        // abs(Pulse[n] - Pulse[n + 1]) < Pulse[n + 1] / PULSE_DETECTION_MULT
        // or
        // PULSE_DETECTION_MULT * abs(Pulse[n] - Pulse[n + 1]) < Pulse[n + 1]
        //
        if((lTemp * PULSE_DETECTION_MULT) < (long)g_pulDataBuffer[lPulse + 1])
        {
            lTotal += (long)g_pulDataBuffer[lPulse];
            lValidPulses++;
        }
        else
        {
            lValidPulses = 0;
            lTotal = 0;
        }

        //
        // Once we have 7 pulses calculate the ratio needed to program the
        // UART.
        //
        if(lValidPulses == 7)
        {
            //
            // Add in the last pulse and calculate the ratio.
            //
            lTotal += (long)g_pulDataBuffer[lPulse];
            *pulRatio = lTotal >> 1;

            //
            // Wait for at least 2 UART clocks since we only wait for 18 of 20
            // that are coming from the host.  If we don't wait, we can turn
            // on the UART while the last two pulses come down.
            //
            for(lDelay = lTotal; lDelay; lDelay--)
            {
            }

            //
            // Indicate a successful auto baud operation.
            //
            return(0);
        }
    }

    //
    // Automatic baud rate detection failed.
    //
    return(-1);
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -