652 lines
21 KiB
C
652 lines
21 KiB
C
|
//*****************************************************************************
|
||
|
//
|
||
|
//! @file am_ios_boot_handlers.c
|
||
|
//!
|
||
|
//! @brief Boot related functions for the IOS interface.
|
||
|
//!
|
||
|
//! This file contains the main state machine for handling boot commands via
|
||
|
//! the I2C interface.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// 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 "am_mcu_apollo.h"
|
||
|
#include "am_bsp.h"
|
||
|
#include "am_util.h"
|
||
|
#include "am_multi_boot_private.h"
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// SPI Slave Configuration
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
static am_hal_ios_config_t g_sIOSConfig =
|
||
|
{
|
||
|
// Configure the IOS in SPI mode.
|
||
|
.ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
|
||
|
|
||
|
// Eliminate the "read-only" section, so an external host can use the
|
||
|
// entire "direct write" section.
|
||
|
.ui32ROBase = 0x78,
|
||
|
|
||
|
// Set the FIFO base to the maximum value, making the "direct write"
|
||
|
// section as big as possible.
|
||
|
.ui32FIFOBase = 0x78,
|
||
|
|
||
|
// We don't need any RAM space, so extend the FIFO all the way to the end
|
||
|
// of the LRAM.
|
||
|
.ui32RAMBase = 0x100,
|
||
|
};
|
||
|
static uint32_t g_iosIntPin;
|
||
|
|
||
|
static volatile bool g_bIosImageValid = false;
|
||
|
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
void *g_IOSHandle;
|
||
|
|
||
|
#define TEST_ACC_INT 1
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// GPIO Configuration
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
const am_hal_gpio_pincfg_t g_AM_BOOT_GPIO_IOS_SCL =
|
||
|
{
|
||
|
.uFuncSel = AM_HAL_PIN_0_SLSCL,
|
||
|
.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA,
|
||
|
.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE
|
||
|
};
|
||
|
|
||
|
const am_hal_gpio_pincfg_t g_AM_BOOT_GPIO_IOS_SDA =
|
||
|
{
|
||
|
.uFuncSel = AM_HAL_PIN_1_SLSDAWIR3,
|
||
|
.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K,
|
||
|
.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA,
|
||
|
.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN
|
||
|
};
|
||
|
|
||
|
const am_hal_gpio_pincfg_t g_AM_BOOT_GPIO_IOS_SCK =
|
||
|
{
|
||
|
.uFuncSel = AM_HAL_PIN_0_SLSCK,
|
||
|
.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA,
|
||
|
.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE
|
||
|
};
|
||
|
|
||
|
const am_hal_gpio_pincfg_t g_AM_BOOT_GPIO_IOS_CE =
|
||
|
{
|
||
|
.uFuncSel = AM_HAL_PIN_3_SLnCE,
|
||
|
.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA,
|
||
|
.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE,
|
||
|
.uNCE = 0,
|
||
|
.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW
|
||
|
};
|
||
|
|
||
|
const am_hal_gpio_pincfg_t g_AM_BOOT_GPIO_IOS_MISO =
|
||
|
{
|
||
|
.uFuncSel = AM_HAL_PIN_2_SLMISO
|
||
|
};
|
||
|
|
||
|
const am_hal_gpio_pincfg_t g_AM_BOOT_GPIO_IOS_MOSI =
|
||
|
{
|
||
|
.uFuncSel = AM_HAL_PIN_1_SLMOSI,
|
||
|
.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA,
|
||
|
.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE
|
||
|
};
|
||
|
|
||
|
const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_ENABLE =
|
||
|
{
|
||
|
.uFuncSel = AM_HAL_PIN_0_GPIO,
|
||
|
.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE,
|
||
|
};
|
||
|
|
||
|
const am_hal_gpio_pincfg_t g_AM_BOOT_GPIO_ENABLE =
|
||
|
{
|
||
|
.uFuncSel = 3,
|
||
|
.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL
|
||
|
};
|
||
|
|
||
|
const am_hal_gpio_pincfg_t g_AM_BOOT_GPIO_DISABLE =
|
||
|
{
|
||
|
.uFuncSel = 3,
|
||
|
.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
//! @brief Multiboot protocol handler for IOS implemented in IOS-ACC ISR
|
||
|
//!
|
||
|
//! This function should be invoked from respective IOS-ACC ISR
|
||
|
//!
|
||
|
//! @return none.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
am_multiboot_ios_acc_isr_handler(void)
|
||
|
{
|
||
|
uint32_t ui32Status;
|
||
|
uint32_t *pui32Packet;
|
||
|
|
||
|
//
|
||
|
// Check to see what caused this interrupt, then clear the bit from the
|
||
|
// interrupt register.
|
||
|
//
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_ios_control(g_IOSHandle, AM_HAL_IOS_REQ_ACC_INTGET, &ui32Status);
|
||
|
am_hal_ios_control(g_IOSHandle, AM_HAL_IOS_REQ_ACC_INTCLR, &ui32Status);
|
||
|
#else
|
||
|
ui32Status = am_hal_ios_access_int_status_get(false);
|
||
|
am_hal_ios_access_int_clear(ui32Status);
|
||
|
#endif
|
||
|
//
|
||
|
// Set up a pointer for writing 32-bit aligned packets through the IO slave
|
||
|
// interface.
|
||
|
//
|
||
|
pui32Packet = (uint32_t *) am_hal_ios_pui8LRAM;
|
||
|
|
||
|
if ( ui32Status & AM_HAL_IOS_ACCESS_INT_03 )
|
||
|
{
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_SET);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_set(g_iosIntPin);
|
||
|
#endif
|
||
|
//
|
||
|
// Figure out what to do next based on the packet header.
|
||
|
//
|
||
|
switch(pui32Packet[0])
|
||
|
{
|
||
|
case AM_BOOTLOADER_NEW_IMAGE:
|
||
|
|
||
|
//
|
||
|
// Parse the image packet, and store the result to the global
|
||
|
// image structure.
|
||
|
//
|
||
|
g_bIosImageValid = image_start_packet_read(&g_sImage,
|
||
|
(uint32_t *) am_hal_ios_pui8LRAM);
|
||
|
|
||
|
//
|
||
|
// Make sure the image packet had reasonable contents. If it
|
||
|
// didn't, we need to let the host know.
|
||
|
//
|
||
|
if ( g_bIosImageValid )
|
||
|
{
|
||
|
//
|
||
|
// Good image; Send back a "READY" packet.
|
||
|
//
|
||
|
pui32Packet[0] = AM_BOOTLOADER_READY;
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Bad image; Send back an error.
|
||
|
//
|
||
|
pui32Packet[0] = AM_BOOTLOADER_ERROR;
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case AM_BOOTLOADER_SET_OVERRIDE_CMD:
|
||
|
//
|
||
|
// Set the override GPIO settings based on the packet
|
||
|
// information.
|
||
|
//
|
||
|
g_sImage.ui32OverrideGPIO = pui32Packet[1];
|
||
|
g_sImage.ui32OverridePolarity = pui32Packet[2];
|
||
|
|
||
|
//
|
||
|
// Send back a "READY" packet.
|
||
|
//
|
||
|
pui32Packet[0] = AM_BOOTLOADER_READY;
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case AM_BOOTLOADER_NEW_PACKET:
|
||
|
//
|
||
|
// Only take new packets if our image structure is valid.
|
||
|
//
|
||
|
if ( !g_bIosImageValid )
|
||
|
{
|
||
|
pui32Packet[0] = AM_BOOTLOADER_ERROR;
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the size information from the packet header, and set the src pointer
|
||
|
// to the beginning of the actual data.
|
||
|
//
|
||
|
//
|
||
|
// Parse the reset of the packet sitting in the IOS LRAM.
|
||
|
//
|
||
|
image_data_packet_read((uint8_t *)(am_hal_ios_pui8LRAM + 8),
|
||
|
*((uint32_t *) (am_hal_ios_pui8LRAM + 4)));
|
||
|
|
||
|
//
|
||
|
// If this packet completed the image...
|
||
|
//
|
||
|
if ( g_ui32BytesReceived == g_sImage.ui32NumBytes )
|
||
|
{
|
||
|
#ifdef MULTIBOOT_SECURE
|
||
|
if ( (g_ui32CRC != g_sImage.ui32CRC) || multiboot_secure_verify(&g_sImage.ui32CRC) )
|
||
|
{
|
||
|
pui32Packet[0] = AM_BOOTLOADER_BAD_CRC;
|
||
|
}
|
||
|
#else
|
||
|
if ( g_ui32CRC != g_sImage.ui32CRC )
|
||
|
{
|
||
|
pui32Packet[0] = AM_BOOTLOADER_BAD_CRC;
|
||
|
}
|
||
|
#endif
|
||
|
else
|
||
|
{
|
||
|
// Protect (and optionally write if stored in SRAM)
|
||
|
// image in flash now as it has been validated now
|
||
|
program_image(g_sImage.bEncrypted);
|
||
|
// Validate the flash contents of a boot image to make
|
||
|
// sure it's safe to run
|
||
|
if ( am_bootloader_flash_check(&g_sImage) )
|
||
|
{
|
||
|
pui32Packet[0] = AM_BOOTLOADER_IMAGE_COMPLETE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pui32Packet[0] = AM_BOOTLOADER_ERROR;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// If this wasn't the end of the image, just send back a
|
||
|
// "READY" packet.
|
||
|
//
|
||
|
pui32Packet[0] = AM_BOOTLOADER_READY;
|
||
|
}
|
||
|
//
|
||
|
// Assert the interrupt line so the host knows we have a
|
||
|
// message.
|
||
|
//
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case AM_BOOTLOADER_RESET:
|
||
|
if ( USE_FLAG_PAGE )
|
||
|
{
|
||
|
//
|
||
|
// Write the flag page.
|
||
|
//
|
||
|
am_bootloader_flag_page_update(&g_sImage, (uint32_t *)FLAG_PAGE_LOCATION);
|
||
|
}
|
||
|
#ifdef MULTIBOOT_SECURE
|
||
|
wipe_sram();
|
||
|
#endif
|
||
|
|
||
|
case AM_BOOTLOADER_RESTART:
|
||
|
//
|
||
|
// Perform a software reset.
|
||
|
//
|
||
|
#if AM_APOLLO3_RESET
|
||
|
am_hal_reset_control(AM_HAL_RESET_CONTROL_SWPOI, 0);
|
||
|
#else // AM_APOLLO3_RESET
|
||
|
am_hal_reset_poi();
|
||
|
#endif // AM_APOLLO3_RESET
|
||
|
|
||
|
//
|
||
|
// Wait for the reset to take effect.
|
||
|
//
|
||
|
while (1);
|
||
|
|
||
|
case AM_BOOTLOADER_BL_VERSION_CMD:
|
||
|
//
|
||
|
// Respond with the version number.
|
||
|
//
|
||
|
pui32Packet[0] = AM_BOOTLOADER_BL_VERSION;
|
||
|
pui32Packet[1] = AM_BOOTLOADER_VERSION_NUM;
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case AM_BOOTLOADER_ACK_CMD:
|
||
|
case AM_BOOTLOADER_NAK_CMD:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
// Error
|
||
|
pui32Packet[0] = AM_BOOTLOADER_ERROR;
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
//! @brief Configure the IOS for IOS boot
|
||
|
//!
|
||
|
//! @param interruptPin is the handshake pin to use for interrupting host.
|
||
|
//!
|
||
|
//! This function configures the IOS for bootloader
|
||
|
//!
|
||
|
//! @return none
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
am_multiboot_setup_ios_interface(uint32_t interruptPin)
|
||
|
{
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
uint32_t ui32Arg = 0;
|
||
|
//
|
||
|
// Check pin 0 to see if we should be using SPI or I2C
|
||
|
//
|
||
|
am_hal_gpio_pinconfig(0, g_AM_HAL_GPIO_INPUT_ENABLE);
|
||
|
am_hal_gpio_state_read(0, AM_HAL_GPIO_INPUT_READ, &ui32Arg);
|
||
|
if ( ui32Arg )
|
||
|
{
|
||
|
//
|
||
|
// If the clock line is high, we'll assume I2C.
|
||
|
//
|
||
|
am_hal_gpio_pinconfig(0, g_AM_BOOT_GPIO_IOS_SCL);
|
||
|
am_hal_gpio_pinconfig(1, g_AM_BOOT_GPIO_IOS_SDA);
|
||
|
|
||
|
g_sIOSConfig.ui32InterfaceSelect = (AM_HAL_IOS_USE_I2C |
|
||
|
AM_HAL_IOS_I2C_ADDRESS(I2C_SLAVE_ADDR << 1));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// If the clock line is low, we'll assume SPI.
|
||
|
//
|
||
|
am_hal_gpio_pinconfig(0, g_AM_BOOT_GPIO_IOS_SCK);
|
||
|
am_hal_gpio_pinconfig(1, g_AM_BOOT_GPIO_IOS_MISO);
|
||
|
am_hal_gpio_pinconfig(2, g_AM_BOOT_GPIO_IOS_MOSI);
|
||
|
am_hal_gpio_pinconfig(3, g_AM_BOOT_GPIO_IOS_CE);
|
||
|
|
||
|
g_sIOSConfig.ui32InterfaceSelect = AM_HAL_IOS_USE_SPI;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Configure the IOS interface and LRAM structure.
|
||
|
//
|
||
|
am_hal_ios_initialize(0, &g_IOSHandle);
|
||
|
am_hal_ios_power_ctrl(g_IOSHandle, AM_HAL_SYSCTRL_WAKE, false);
|
||
|
am_hal_ios_configure(g_IOSHandle, &g_sIOSConfig);
|
||
|
g_iosIntPin = interruptPin;
|
||
|
|
||
|
//
|
||
|
// Make sure the interrupt pin is set up correctly
|
||
|
//
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_SET);
|
||
|
am_hal_gpio_pinconfig(g_iosIntPin, g_AM_BOOT_GPIO_ENABLE);
|
||
|
|
||
|
//
|
||
|
// Clear out any IOS register-access interrupts that may be active, and
|
||
|
// enable interrupts for the registers we're interested in.
|
||
|
//
|
||
|
#ifdef TEST_ACC_INT
|
||
|
ui32Arg = AM_HAL_IOS_ACCESS_INT_ALL;
|
||
|
am_hal_ios_control(g_IOSHandle, AM_HAL_IOS_REQ_ACC_INTCLR, &ui32Arg);
|
||
|
ui32Arg = AM_HAL_IOS_ACCESS_INT_03;
|
||
|
am_hal_ios_control(g_IOSHandle, AM_HAL_IOS_REQ_ACC_INTEN, &ui32Arg);
|
||
|
#endif
|
||
|
am_hal_ios_interrupt_clear(g_IOSHandle, AM_HAL_IOS_INT_ALL);
|
||
|
am_hal_ios_interrupt_enable(g_IOSHandle, AM_HAL_IOS_INT_FSIZE);
|
||
|
|
||
|
//
|
||
|
// Set the bit in the NVIC to accept access interrupts from the IO Slave.
|
||
|
//
|
||
|
#if AM_CMSIS_REGS
|
||
|
NVIC_EnableIRQ(IOSLAVEACC_IRQn);
|
||
|
// NVIC_EnableIRQ(IOSLAVE_IRQn);
|
||
|
#else // AM_CMSIS_REGS
|
||
|
am_hal_interrupt_enable(AM_HAL_INTERRUPT_IOSACC);
|
||
|
// am_hal_interrupt_enable(AM_HAL_INTERRUPT_IOSLAVE);
|
||
|
#endif // AM_CMSIS_REGS
|
||
|
|
||
|
//
|
||
|
// Notify the host that we're ready to receive data.
|
||
|
//
|
||
|
*((uint32_t *) am_hal_ios_pui8LRAM) = AM_BOOTLOADER_READY;
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
//
|
||
|
// Check pin 0 to see if we should be using SPI or I2C
|
||
|
//
|
||
|
am_hal_gpio_pin_config(0, AM_HAL_GPIO_INPUT);
|
||
|
if ( am_hal_gpio_input_bit_read(0) )
|
||
|
{
|
||
|
//
|
||
|
// If the clock line is high, we'll assume I2C.
|
||
|
//
|
||
|
am_hal_gpio_pin_config(0, AM_HAL_PIN_0_SLSCL);
|
||
|
am_hal_gpio_pin_config(1, AM_HAL_PIN_1_SLSDA);
|
||
|
|
||
|
g_sIOSConfig.ui32InterfaceSelect = (AM_HAL_IOS_USE_I2C |
|
||
|
AM_HAL_IOS_I2C_ADDRESS(I2C_SLAVE_ADDR << 1));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// If the clock line is low, we'll assume SPI.
|
||
|
//
|
||
|
am_hal_gpio_pin_config(0, AM_HAL_PIN_0_SLSCK);
|
||
|
am_hal_gpio_pin_config(1, AM_HAL_PIN_1_SLMISO);
|
||
|
am_hal_gpio_pin_config(2, AM_HAL_PIN_2_SLMOSI);
|
||
|
am_hal_gpio_pin_config(3, AM_HAL_PIN_3_SLnCE);
|
||
|
|
||
|
g_sIOSConfig.ui32InterfaceSelect = AM_HAL_IOS_USE_SPI;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Configure the IOS interface and LRAM structure.
|
||
|
//
|
||
|
am_hal_ios_config(&g_sIOSConfig);
|
||
|
g_iosIntPin = interruptPin;
|
||
|
|
||
|
//
|
||
|
// Make sure the interrupt pin is set up correctly
|
||
|
//
|
||
|
am_hal_gpio_out_bit_set(g_iosIntPin);
|
||
|
am_hal_gpio_pin_config(g_iosIntPin, AM_HAL_PIN_OUTPUT);
|
||
|
|
||
|
//
|
||
|
// Clear out any IOS register-access interrupts that may be active, and
|
||
|
// enable interrupts for the registers we're interested in.
|
||
|
//
|
||
|
am_hal_ios_access_int_clear(AM_HAL_IOS_ACCESS_INT_ALL);
|
||
|
am_hal_ios_access_int_enable(AM_HAL_IOS_ACCESS_INT_03);
|
||
|
|
||
|
am_hal_ios_int_clear(AM_HAL_IOS_INT_ALL);
|
||
|
am_hal_ios_int_enable(AM_HAL_IOS_INT_FSIZE);
|
||
|
|
||
|
//
|
||
|
// Set the bit in the NVIC to accept access interrupts from the IO Slave.
|
||
|
//
|
||
|
am_hal_interrupt_enable(AM_HAL_INTERRUPT_IOSACC);
|
||
|
// am_hal_interrupt_enable(AM_HAL_INTERRUPT_IOSLAVE);
|
||
|
|
||
|
//
|
||
|
// Notify the host that we're ready to receive data.
|
||
|
//
|
||
|
*((uint32_t *) am_hal_ios_pui8LRAM) = AM_BOOTLOADER_READY;
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
//! @brief Cleanup the IOS
|
||
|
//!
|
||
|
//! This function un-configures the IOS
|
||
|
//!
|
||
|
//! @return none
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
am_multiboot_cleanup_ios_interface(void)
|
||
|
{
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_pinconfig(0, g_AM_BOOT_GPIO_DISABLE);
|
||
|
am_hal_gpio_pinconfig(1, g_AM_BOOT_GPIO_DISABLE);
|
||
|
am_hal_gpio_pinconfig(2, g_AM_BOOT_GPIO_DISABLE);
|
||
|
am_hal_gpio_pinconfig(3, g_AM_BOOT_GPIO_DISABLE);
|
||
|
#else
|
||
|
am_hal_gpio_pin_config(0, AM_HAL_PIN_DISABLE);
|
||
|
am_hal_gpio_pin_config(1, AM_HAL_PIN_DISABLE);
|
||
|
am_hal_gpio_pin_config(2, AM_HAL_PIN_DISABLE);
|
||
|
am_hal_gpio_pin_config(3, AM_HAL_PIN_DISABLE);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// IO Slave Main ISR.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
void
|
||
|
am_ioslave_ios_isr(void)
|
||
|
{
|
||
|
uint32_t ui32Status;
|
||
|
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
//
|
||
|
// Check to see what caused this interrupt, then clear the bit from the
|
||
|
// interrupt register.
|
||
|
//
|
||
|
am_hal_ios_interrupt_status_get(g_IOSHandle, false, &ui32Status);
|
||
|
am_hal_ios_interrupt_clear(g_IOSHandle, ui32Status);
|
||
|
|
||
|
//
|
||
|
// Service the I2C slave FIFO if necessary.
|
||
|
//
|
||
|
am_hal_ios_interrupt_service(g_IOSHandle, ui32Status);
|
||
|
#else
|
||
|
//
|
||
|
// Check to see what caused this interrupt, then clear the bit from the
|
||
|
// interrupt register.
|
||
|
//
|
||
|
ui32Status = am_hal_ios_int_status_get(false);
|
||
|
am_hal_ios_int_clear(ui32Status);
|
||
|
|
||
|
//
|
||
|
// Service the I2C slave FIFO if necessary.
|
||
|
//
|
||
|
am_hal_ios_fifo_service(ui32Status);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// IO Slave handshake
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
bool
|
||
|
am_ioslave_handshake(uint32_t ui32Timeout)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
uint32_t *pui32Packet;
|
||
|
bool bReturnVal = false;
|
||
|
|
||
|
//
|
||
|
// Set up a pointer for writing 32-bit aligned packets through the IO slave
|
||
|
// interface.
|
||
|
//
|
||
|
pui32Packet = (uint32_t *) am_hal_ios_pui8LRAM;
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_SET);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_set(g_iosIntPin);
|
||
|
#endif
|
||
|
|
||
|
for ( i = 0; i < ui32Timeout; i++ )
|
||
|
{
|
||
|
if ( pui32Packet[0] == 0x5A )
|
||
|
{
|
||
|
bReturnVal = true;
|
||
|
|
||
|
//
|
||
|
// Notify the host that we're ready to receive data.
|
||
|
//
|
||
|
*((uint32_t *) am_hal_ios_pui8LRAM) = AM_BOOTLOADER_READY;
|
||
|
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||
|
am_hal_gpio_state_write(g_iosIntPin, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||
|
#else
|
||
|
am_hal_gpio_out_bit_clear(g_iosIntPin);
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
am_util_delay_us(1);
|
||
|
}
|
||
|
return bReturnVal;
|
||
|
}
|
||
|
#endif
|