vos/ambiq-hal-sys/ambiq-sparkfun-sdk/devices/am_devices_da14581.c
2022-10-23 23:45:43 -07:00

200 lines
6.9 KiB
C

//*****************************************************************************
//
//! @file am_devices_da14581.c
//!
//! @brief Support functions for the Dialog Semiconductor DA14581 BTLE radio.
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2020, Ambiq Micro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// Third party software included in this distribution is subject to the
// additional license terms as defined in the /docs/licenses directory.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include "am_bsp.h"
#include "am_devices_da14581.h"
//*****************************************************************************
//
// Macro definitions
//
//*****************************************************************************
#define DIALOG_BOOT_STX 0x02
#define DIALOG_BOOT_SOH 0x01
#define DIALOG_BOOT_ACK 0x06
#define DIALOG_BOOT_NACK 0x15
//*****************************************************************************
//
// BLE MAC address for the Dialog radio.
//
//*****************************************************************************
static uint8_t g_BLEMacAddress[6] =
{0x01, 0x00, 0x00, 0xCA, 0xEA, 0x80};
//*****************************************************************************
//
// Location in the Diaog binary where the MAC address is stored.
//
//*****************************************************************************
static const uint32_t g_ui32MacIndex = 1000;
//*****************************************************************************
//
// Sets the MAC address to send to the dialog radio on the next boot up.
//
//*****************************************************************************
void
am_devices_da14581_mac_set(const uint8_t *pui8MacAddress)
{
uint32_t i;
//
// Copy the 6-byte MAC address into our global variable.
//
for ( i = 0; i < 6; i++ )
{
g_BLEMacAddress[i] = *pui8MacAddress++;
}
}
//*****************************************************************************
//
//! @brief Runs a UART based boot sequence for a Dialog radio device.
//!
//! @param pui8BinData - pointer to an array of bytes containing the firmware
//! for the DA14581
//!
//! @param ui32NumBytes - length of the DA14581 firmware image.
//!
//! This function allows the Ambiq device to program a "blank" DA14581 device
//! on startup. It will handle all of the necessary UART negotiation for the
//! Dialog boot procedure, and will verify that the CRC value for the
//! downloaded firmware image is correct.
//!
//! @return true if successful.
//
//*****************************************************************************
bool
am_devices_da14581_uart_boot(const uint8_t *pui8BinData, uint32_t ui32NumBytes,
uint32_t ui32UartModule)
{
uint32_t ui32Index;
uint8_t ui8CRCValue;
uint8_t ui8TxData;
char ui8RxChar;
//
// Poll the RX lines until we get some indication that the dialog radio is
// present and ready to receive data.
//
do
{
am_hal_uart_char_receive_polled(ui32UartModule, &ui8RxChar);
}
while (ui8RxChar != DIALOG_BOOT_STX);
//
// Send the Start-of-Header signal and the length of the data download.
//
am_hal_uart_char_transmit_polled(ui32UartModule, DIALOG_BOOT_SOH);
am_hal_uart_char_transmit_polled(ui32UartModule, ui32NumBytes & 0xFF);
am_hal_uart_char_transmit_polled(ui32UartModule, (ui32NumBytes & 0xFF00) >> 8);
//
// Poll for the 'ACK' from the dialog device that signifies that the header
// was recieved correctly.
//
do
{
am_hal_uart_char_receive_polled(ui32UartModule, &ui8RxChar);
}
while (ui8RxChar != DIALOG_BOOT_ACK);
//
// Initialize the CRC value to zero.
//
ui8CRCValue = 0;
//
// Send the binary image over to the dialog device one byte at a time,
// keeping track of the CRC as we go.
//
for (ui32Index = 0; ui32Index < ui32NumBytes; ui32Index++)
{
if ((ui32Index >= g_ui32MacIndex) && (ui32Index < g_ui32MacIndex + 6))
{
ui8TxData = g_BLEMacAddress[ui32Index - g_ui32MacIndex];
}
else
{
ui8TxData = pui8BinData[ui32Index];
}
ui8CRCValue ^= ui8TxData;
am_hal_uart_char_transmit_polled(ui32UartModule, ui8TxData);
}
//
// The Dialog device should respond back with a CRC value at the end of the
// programming cycle. We should check here to make sure that they got the
// same CRC result that we did. If it doesn't match, return with an error.
//
am_hal_uart_char_receive_polled(ui32UartModule, &ui8RxChar);
if ( ui8RxChar != ui8CRCValue )
{
return 1;
}
//
// If all is well, send the final 'ACK' to tell the dialog device that its
// new image is correct. After this point, the dialog device should start
// running the downloaded firmware.
//
am_hal_uart_char_transmit_polled(ui32UartModule, DIALOG_BOOT_ACK);
//
// Wait until the FIFO is actually empty and the UART is no-longer busy.
//
while (!AM_BFR(UART, FR, TXFE) || AM_BFR(UART, FR, BUSY));
return 0;
}