initial commit

This commit is contained in:
2022-10-23 23:45:43 -07:00
commit e190fa5193
6450 changed files with 8626944 additions and 0 deletions
@@ -0,0 +1,225 @@
How to Regenerate Existing BSPs
===============================
After making changes to the BSP source files (```am_bsp.h```, ```am_bsp.c```, and ```bsp_pins.src```) you will still need to ensure that the ```libam_bsp.a``` archive is updated to reflect this (if this file exists then the build process simply uses it instead of compiling BSP sources). The simplest way is to navigate to the root of this repo and run ```./common/tools_sfe/scripts/regen_bsps.sh```
**all these automated methods rely on this repo being placed in the root directory of the AmbiqSuite SDK (alternately you may employ an environment variable {$AMSDK} pointing at the root) and having the prerequisite tools available**
How to Generate New BSP Files
=============================
A Board Support Package is designed to provide a uniform interface to the hardware capabilities across boards, thus enabling users to easily identify what hardware is being used and increasing the compatibility of example applications.
To do so the BSP provides a listing of pin names and corresponding pin configurations, as well as several uniform API calls.
am_bsp_pins.h + am_bsp_pins.c
=============================
These files are used to create named configurations (and pins numbers) that represent what's on the board. The files are automatically generated by the ```pinconfig.py``` script. This uses pin definitions that the user sets up in the ```bsp_pins.src``` file which helps reduce maintenance effort. An example usage is (from the root directory of this repo):
```bash
python common/bsp_pinconfig/pinconfig.py ${board}/bsp/bsp_pins.src ${selector} > ${board}/bsp/am_bsp_pins.${selector}
```
Where ```${board}``` is the directory for the board whose BSP is being generated and ```${selector}``` is one of ```c``` or ```h``` (which tells the script which file to generate)
am_bsp.h + am_bsp.c
===================
This compilation unit uses the pin definitions (above) to describe the common interface. It has a standard structure and contents, but it is also possible to add additional board-specific macros.
**The Header**
The header is standardized and changes to it should be minimal
Includes:
- License + Copyright
- Include guards (opening)
- Includes
- stdint
- stdbool
- am_mcu_apollo
- am_bsp_pins
- am_devices_led
- am_devices_button
- C++ guards (opening)
``` c
//*****************************************************************************
//
// am_bsp.h
//! @file
//!
//! @brief Functions to aid with configuring the GPIOs.
//!
//! @addtogroup BSP Board Support Package (BSP)
//! @addtogroup apollo3_fpga_bsp BSP for the Apollo3 Hotshot FPGA
//! @ingroup BSP
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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 v2.0.0 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#ifndef AM_BSP_H
#define AM_BSP_H
#include <stdint.h>
#include <stdbool.h>
#include "am_mcu_apollo.h"
#include "am_bsp_pins.h"
//
// Make individual includes to not require full port before usage.
//#include "am_devices.h"
//
#include "am_devices_led.h"
#include "am_devices_button.h"
#ifdef __cplusplus
extern "C"
{
#endif
//*****************************************************************************
//
// Begin User Modifiable Area
//
//*****************************************************************************
```
**The User Modifiable Area**
Contents of this section are free reign. Nothing is required. Possible elements include:
- Aliases for pin names
- Definitions for HW not captured by the bsp_pins.src file
**Print Interface Area**
Todo: explain what this area is about
```c
//*****************************************************************************
//
// End User Modifiable Area
//
//*****************************************************************************
//*****************************************************************************
//
// Print interface type
//
//*****************************************************************************
#define AM_BSP_PRINT_INFC_NONE 0
#define AM_BSP_PRINT_INFC_SWO 1
#define AM_BSP_PRINT_INFC_UART0 2
#define AM_BSP_PRINT_INFC_BUFFERED_UART0 3
//*****************************************************************************
//
//! Structure containing UART configuration information while it is powered down.
//
//*****************************************************************************
typedef struct
{
bool bSaved;
uint32_t ui32TxPinNum;
uint32_t ui32TxPinCfg;
}
am_bsp_uart_pwrsave_t;
//*****************************************************************************
//
// External data definitions.
//
//*****************************************************************************
extern am_bsp_uart_pwrsave_t am_bsp_uart_pwrsave[AM_REG_UART_NUM_MODULES];
```
**The API Area**
This area declares standard bsp functions that are used across AmbiqSuite examples. It is best to attempt to implement these functions in ```am_bsp.c```.
```c
//*****************************************************************************
//
// External function definitions.
//
//*****************************************************************************
extern void am_bsp_low_power_init(void);
extern void am_bsp_iom_pins_enable(uint32_t ui32Module, am_hal_iom_mode_e eIOMMode);
extern void am_bsp_iom_pins_disable(uint32_t ui32Module, am_hal_iom_mode_e eIOMMode);
extern void am_bsp_mspi_pins_enable(am_hal_mspi_device_e eMSPIDevice);
extern void am_bsp_mspi_pins_disable(am_hal_mspi_device_e eMSPIDevice);
extern void am_bsp_ios_pins_enable(uint32_t ui32Module, uint32_t ui32IOSMode); // SparkFun Edge does not expose IO Slave Clock signal, so hiding these functions
extern void am_bsp_ios_pins_disable(uint32_t ui32Module, uint32_t ui32IOSMode);
extern void am_bsp_debug_printf_enable(void);
extern void am_bsp_debug_printf_disable(void);
#ifdef AM_BSP_GPIO_ITM_SWO
extern void am_bsp_itm_printf_enable(void);
#else
extern void am_bsp_itm_printf_enable(uint32_t ui32Pin, am_hal_gpio_pincfg_t sPincfg);
#endif
extern void am_bsp_itm_string_print(char *pcString);
extern void am_bsp_itm_printf_disable(void);
extern void am_bsp_uart_string_print(char *pcString);
extern void am_bsp_uart_printf_enable(void);
extern void am_bsp_uart_printf_enable_custom(const am_hal_uart_config_t* p_config);
extern void am_bsp_uart_printf_disable(void);
extern void am_bsp_buffered_uart_printf_enable(void);
extern void am_bsp_buffered_uart_service(void);
extern uint32_t am_bsp_com_uart_transfer(const am_hal_uart_transfer_t *psTransfer);
```
**The Footer**
The footer just wraps it all up
```c
#ifdef __cplusplus
}
#endif
#endif // AM_BSP_H
//*****************************************************************************
//
// End Doxygen group.
//! @}
//
//*****************************************************************************
```
@@ -0,0 +1,653 @@
#!/usr/bin/env python3
# *****************************************************************************
#
# pinconfig.py
#
# @brief Script for generating a BSP pin file.
# *****************************************************************************
# *****************************************************************************
#
# Copyright (c) 2019, 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.2.0-hotfix-2.2.1 of the AmbiqSuite Development Package.
#
# *****************************************************************************
# *****************************************************************************
# Imported modules
# *****************************************************************************
import argparse
import textwrap
import os.path
import rsonlite
# *****************************************************************************
# Templates
# *****************************************************************************
filetemplateC = '''
//*****************************************************************************
//
// {filename}
//! @file
//!
//! @brief BSP pin configuration definitions.
//!
//! @addtogroup BSP Board Support Package (BSP)
//! @addtogroup apollo3_evb_bsp BSP for the Apollo3 Engineering Board
//! @ingroup BSP
//! @{{
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.2.0-hotfix-2.2.1 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include "am_bsp.h"
{pin_defs}
//*****************************************************************************
//
// End Doxygen group.
//! @}}
//
//*****************************************************************************
'''.strip()
filetemplateH = '''
//*****************************************************************************
//
// {filename}
//! @file
//!
//! @brief BSP pin configuration definitions.
//!
//! @addtogroup BSP Board Support Package (BSP)
//! @addtogroup apollo3_bsp BSP for the Apollo3 EVB.
//! @ingroup BSP
//! @{{
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.2.0-hotfix-2.2.1 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#ifndef {headerdef}
#define {headerdef}
#include <stdint.h>
#include <stdbool.h>
#include "am_mcu_apollo.h"
#ifdef __cplusplus
extern "C"
{{
#endif
{pin_defs}
#ifdef __cplusplus
}}
#endif
#endif // {headerdef}
//*****************************************************************************
//
// End Doxygen group.
//! @}}
//
//*****************************************************************************
'''.strip()
sectiontemplate = '''
//*****************************************************************************
//
// {pin_descr}
//
//*****************************************************************************
'''.strip()
# *****************************************************************************
#
# Globals
#
# *****************************************************************************
# *****************************************************************************
#
# Command line support.
#
# *****************************************************************************
def read_arguments():
parser = argparse.ArgumentParser()
parser.add_argument('input', help='input src file name')
parser.add_argument('CorH', help='C to create C file, H to create H file',
choices=['C','H','c','h'])
parser.add_argument('-g', '--guard', dest='headerdef', required=False, default='AM_BSP_PINS_H', help='optional string to use for header include guards - defaults to AM_BSP_PINS_H')
parser.add_argument('-p', '--prefix', dest='prefix', required=False, default='AM_BSP_GPIO', help='optional string with which to prefix names - defaults to AM_BSP')
parser.add_argument('-b', '--bgaguard', dest='bgaguard', required=False, default=None, help='if provided this script will place preprocessor guards around pins that only exist on the BGA package using the provided string as the check value')
return parser.parse_args()
# *****************************************************************************
# parse_input()
# *****************************************************************************
def parse_input(filename):
'''
Simple wrapper to pull an rsonlite list from given file.
'''
with open(filename) as f:
data = f.read()
return rsonlite.loads(data)
# *****************************************************************************
# list_to_dict()
# *****************************************************************************
def list_to_dict(L):
'''
rsonlite loads data from the rson files as a very-nested list. This
function converts that list to a set of nested dictionaries. At each level,
the dictionary keys correspond to the "headings", and the dictionary values
are a list of the items under that "heading". Values assigned by
equals-sign statements are (unfortunately) also converted to (key, list)
pairs, the same way that subheadings are.
'''
if len(L) == 1:
return L[0]
else:
D = dict()
for x in L:
if x[0] in D:
D[x[0]] = D[x[0]] + [list_to_dict(x[1])]
else:
D[x[0]] = [list_to_dict(x[1])]
return D
# *****************************************************************************
# get_val()
# *****************************************************************************
def get_val(name, D):
'''
get_val is just a helper to make it more obvious when you are trying to get
at an equals-sign-assigned value from the rson file dictionary.
'''
if name not in D:
return "ERROR: {} VALUE MISSING".format(name)
else:
return D[name][0]
# *****************************************************************************
# get_pinobj()
# *****************************************************************************
def get_pinobj(filename):
'''
Given the filename of an 'src' file, this function will return a 'pin'
object corresponding to the fields described in the src file.
'''
# Set the location for the supplementary files (infoblock, base addresses, etc.)
srcdir = os.path.dirname(filename)
# Read in the contents of the src file, and use the rsonlite library to
# parse them into a list.
rson_data = parse_input(filename)
# Convert the list to a dictionary.
rson_dict = list_to_dict(rson_data)
# Convert the dictionary to a block object, which will create field
# objects as necessary. Return this object to the caller.
return pinobj(rson_dict)
# *****************************************************************************
# pinfields
# *****************************************************************************
class pinfields:
def __init__(self, pindict):
self.name = ''
self.desc = ''
self.pinnum = 0
self.powersw = ''
self.pullup = ''
self.func_sel = ''
self.drvstrength = 0
self.intdir = 0
self.GPOutcfg = ''
self.GPinput = ''
self.GPRdZero = ''
self.IOMnum = ''
self.CEnum = ''
self.CEpol = ''
self.bIomMSPIn = ''
intnotgiven = 65535
strnotgiven = 'none_given'
if 'name' in pindict:
self.name = get_val('name', pindict)
else:
self.name = strnotgiven
if 'desc' in pindict:
self.desc = get_val('desc', pindict)
else:
self.desc = strnotgiven
if 'pinnum' in pindict:
self.pinnum = int(get_val('pinnum', pindict))
else:
self.pinnum = intnotgiven
if 'powersw' in pindict:
self.powersw = get_val('powersw', pindict)
else:
self.powersw = strnotgiven
if 'pullup' in pindict:
self.pullup = get_val('pullup', pindict)
else:
self.pullup = strnotgiven
if 'func_sel' in pindict:
self.func_sel = get_val('func_sel', pindict)
else:
self.func_sel = strnotgiven
if 'drvstrength' in pindict:
self.drvstrength = int(get_val('drvstrength', pindict))
else:
self.drvstrength = intnotgiven
if 'intdir' in pindict:
self.intdir = get_val('intdir', pindict)
else:
self.intdir = strnotgiven
if 'GPOutcfg' in pindict:
self.GPOutcfg = get_val('GPOutcfg', pindict)
else:
self.GPOutcfg = strnotgiven
if 'GPinput' in pindict:
self.GPinput = get_val('GPinput', pindict)
else:
self.GPinput = strnotgiven
if 'GPRdZero' in pindict:
self.GPRdZero = get_val('GPRdZero', pindict)
else:
self.GPRdZero = strnotgiven
if 'IOMnum' in pindict:
self.IOMnum = get_val('IOMnum', pindict)
else:
self.IOMnum = strnotgiven
if 'CEnum' in pindict:
self.CEnum = get_val('CEnum', pindict)
else:
self.CEnum = strnotgiven
if 'CEpol' in pindict:
self.CEpol = get_val('CEpol', pindict)
else:
self.CEpol = strnotgiven
if 'bIomMSPIn' in pindict:
self.bIomMSPIn = get_val('bIomMSPIn', pindict)
else:
self.bIomMSPIn = strnotgiven
#
# Check for an invalid field in the src file. If so, report it.
#
for fld in pindict:
if fld != 'name' and \
fld != 'desc' and \
fld != 'pinnum' and \
fld != 'powersw' and \
fld != 'pullup' and \
fld != 'func_sel' and \
fld != 'drvstrength' and \
fld != 'intdir' and \
fld != 'GPOutcfg' and \
fld != 'GPinput' and \
fld != 'GPRdZero' and \
fld != 'IOMnum' and \
fld != 'CEnum' and \
fld != 'CEpol' and \
fld != 'bIomMSPIn':
print("Invalid field: '%s.%s'" % (self.name, fld))
# *****************************************************************************
# pinobj
# *****************************************************************************
class pinobj:
def __init__(self, pindict):
self.name = 'name'
self.srcver=0x0000
self.pins = []
if 'pinsrc_ver' in pindict:
# Convert rson list object to int
ssrcver = pindict["pinsrc_ver"][0]
if ssrcver[0:2].lower() == "0x":
self.srcver = int(ssrcver,16)
else:
self.srcver = int(ssrcver,10)
else:
# If no src file version given, assume version for Apollo3
self.srcver = 0x0003
# Run through all the pins given in the src file
if 'pin' in pindict:
#
# Run through the 'pin' list.
#
for pin in pindict['pin']:
self.pins.append(pinfields(pin))
# *****************************************************************************
# write_Cfiles()
# *****************************************************************************
def write_Cfiles(pinobj, bCreateC):
#
# Initializations
#
intnotgiven = 65535
strnotgiven = 'none_given'
strCfile = ''
strHfile = ''
for pin in pinobj.pins:
sectiondesc = pin.name.strip() + ' pin'
if pin.desc == strnotgiven:
sectiondesc += '.'
else:
sectiondesc += ': ' + pin.desc.strip()
if sectiondesc[-1] != '.':
sectiondesc += '.'
strCfile += '\n'
strCfile += sectiontemplate.format(pin_descr=sectiondesc)
strCfile += '\n'
strHfile += '\n'
strHfile += sectiontemplate.format(pin_descr=sectiondesc)
strHfile += '\n'
bga = False
if ( 30 <= pin.pinnum <=38 ) or ( 42 <= pin.pinnum <= 43 ) or ( 45 <= pin.pinnum <= 46 ):
bga = True
if pin.pinnum != intnotgiven:
if bga and args.bgaguard:
strHfile += '#if defined (' + args.bgaguard + ')\n'
strHfile += '#define ' + args.prefix + '_%-20s\t' % pin.name + '%d\n' % pin.pinnum
strHfile += 'extern const am_hal_gpio_pincfg_t g_' + args.prefix + '_%s;\n' % pin.name
if bga and args.bgaguard:
strHfile += '#endif // ' + args.bgaguard + '\n'
#strHfile += '\n'
if bga and args.bgaguard:
strCfile += '#if defined (' + args.bgaguard + ')\n'
strCfile += 'const am_hal_gpio_pincfg_t g_' + args.prefix + '_%s =\n' % pin.name
strCfile += '{\n'
strCfile += '%-25s' % ' .uFuncSel' + '= %s,\n' % pin.func_sel
if pin.powersw != strnotgiven:
if (pin.powersw.lower() == "vdd") or \
(pin.powersw.lower() == "vss") or \
(pin.powersw.lower() == "none"):
strCfile += '%-25s' % ' .ePowerSw' + '= AM_HAL_GPIO_PIN_POWERSW_%s,\n' % pin.powersw.upper()
else:
strCfile += '%-25s' % ' .ePowerSw' + '= %s,\n' % pin.powersw
if pin.pullup != strnotgiven:
if (pin.pullup.lower() == "none") or \
(pin.pullup.lower() == "weak") or \
(pin.pullup.lower() == "pulldown") or \
(pin.pullup.lower() == "1_5k") or \
(pin.pullup.lower() == "6k") or \
(pin.pullup.lower() == "12k") or \
(pin.pullup.lower() == "24k"):
strCfile += '%-25s' % ' .ePullup' + '= AM_HAL_GPIO_PIN_PULLUP_%s,\n' % pin.pullup.upper()
elif (pin.pullup == "1_5") or \
(pin.pullup == "6") or \
(pin.pullup == "12") or \
(pin.pullup == "24"):
strCfile += '%-25s' % ' .ePullup' + '= AM_HAL_GPIO_PIN_PULLUP_%sK,\n' % pin.pullup
else:
strCfile += '%-25s' % ' .ePullup' + '= %s,\n' % pin.pullup
if pin.drvstrength != intnotgiven:
if (pin.drvstrength != 2) and (pin.drvstrength != 4) and \
(pin.drvstrength != 8) and (pin.drvstrength != 12):
pin.drvstrength = 2
strCfile += '%-25s' % ' .eDriveStrength' + '= AM_HAL_GPIO_PIN_DRIVESTRENGTH_%dMA,\n' % pin.drvstrength
if pin.GPOutcfg != strnotgiven:
if (pin.GPOutcfg.lower() == "disable") or \
(pin.GPOutcfg.lower() == "pushpull") or \
(pin.GPOutcfg.lower() == "opendrain") or \
(pin.GPOutcfg.lower() == "tristate"):
strCfile += '%-25s' % ' .eGPOutcfg' + '= AM_HAL_GPIO_PIN_OUTCFG_%s,\n' % pin.GPOutcfg.upper()
else:
strCfile += '%-25s' % ' .eGPOutcfg' + '= %s,\n' % pin.GPOutcfg
if pin.GPinput != strnotgiven:
if (pin.GPinput.lower() == "true"):
strCfile += '%-25s' % ' .eGPInput' + '= AM_HAL_GPIO_PIN_INPUT_ENABLE,\n'
elif (pin.GPinput.lower() == "false"):
strCfile += '%-25s' % ' .eGPInput' + '= AM_HAL_GPIO_PIN_INPUT_NONE,\n'
else:
strCfile += '%-25s' % ' .eGPInput' + '= %s,\n' % pin.GPinput
if pin.GPRdZero != strnotgiven:
if (pin.GPRdZero.lower() == "true") or \
(pin.GPRdZero.lower() == "zero"):
strCfile += '%-25s' % ' .eGPRdZero' + '= AM_HAL_GPIO_PIN_RDZERO_ZERO,\n'
elif (pin.GPRdZero.lower() == "false") or \
(pin.GPRdZero.lower() == "readpin"):
strCfile += '%-25s' % ' .eGPRdZero' + '= AM_HAL_GPIO_PIN_RDZERO_READPIN,\n'
else:
strCfile += '%-25s' % ' .eGPRdZero' + '= %s,\n' % pin.GPRdZero
if pin.intdir != strnotgiven:
if (pin.intdir.lower() == "none") or \
(pin.intdir.lower() == "lo2hi") or \
(pin.intdir.lower() == "hi2lo") or \
(pin.intdir.lower() == "either"):
strCfile += '%-25s' % ' .eIntDir' + '= AM_HAL_GPIO_PIN_INTDIR_%s,\n' % pin.intdir.upper()
else:
strCfile += '%-25s' % ' .eIntDir' + '= %s,\n' % pin.intdir
if (pin.bIomMSPIn != strnotgiven):
if pinobj.srcver >= 0x0003:
if ((pin.bIomMSPIn[0:1].lower() != "m") and (pin.bIomMSPIn != "0")):
bIom = 1
else:
bIom = 0
strCfile += '%-25s' % ' .bIomMSPIn' + '= %d,\n' % bIom
if pin.IOMnum != strnotgiven:
strCfile += '%-25s' % ' .uIOMnum' + '= %s,\n' % str(pin.IOMnum)
if pin.CEnum != strnotgiven:
strCfile += '%-25s' % ' .uNCE' + '= %s,\n' % str(pin.CEnum)
# Create the define
strtmp = '#define ' + args.prefix + '_%s_CHNL' % (pin.name)
strHfile += '%-40s' % strtmp + '%s\n' % str((pin.CEnum))
if pin.CEpol != strnotgiven:
if (pin.CEpol.lower() == "low") or \
(pin.CEpol.lower() == "high"):
strCfile += '%-25s' % ' .eCEpol' + '= AM_HAL_GPIO_PIN_CEPOL_ACTIVE%s,\n' % pin.CEpol.upper()
elif (pin.CEpol.lower() == "activelow") or \
(pin.CEpol.lower() == "activehigh"):
strCfile += '%-25s' % ' .eCEpol' + '= AM_HAL_GPIO_PIN_CEPOL_%s,\n' % pin.CEpol.upper()
else:
strCfile += '%-25s' % ' .eCEpol' + '= %s,\n' % pin.CEpol
# Eliminate the last comma from the last structure member
strCfile = strCfile[:-2]
# Terminate the structure
strCfile += '\n};\n'
if bga and args.bgaguard:
strCfile += '#endif // ' + args.bgaguard + '\n'
if bCreateC:
#
# Develop and print the C file
#
S = filetemplateC.format(filename='am_bsp_pins.c', pin_defs=strCfile);
print(S)
else:
#
# Develop and print the H file
#
S = filetemplateH.format(filename='am_bsp_pins.h',
pin_defs=strHfile,
headerdef=args.headerdef)
print(S)
# *****************************************************************************
#
# main
#
# *****************************************************************************
if __name__ == '__main__':
#
# Get arguments.
# First arg is a string for the input .src file.
# Second arg must be a C or H.
#
args = read_arguments()
if args.CorH.upper() == 'C':
bCreateC = True
else:
bCreateC = False
pinobj = get_pinobj(args.input)
#
# pinobj.pins is a list of the pins
#
write_Cfiles(pinobj, bCreateC)
@@ -0,0 +1,294 @@
'''
rsonlite -- an extremely lightweight version of rson.
Copyright (c) 2012, Patrick Maupin
License :: MIT
http://pypi.python.org/pypi/rsonlite
http://code.google.com/p/rson/
rsonlite makes it easy to build a file parser for
declarative hierarchical data structures using indentation.
(Spaces only, tabs not considered indentation.)
The only special characters are '#', '=', and indentation:
- Indentation denotes a key/value relationship. The
value is indented from the key.
- = Denotes the start of a free-format string. These
strings can contain '=' and '#' characters, and
even be multi-line, but every line in the string
must be indented past the initial equal sign.
Note that, for multi-line strings, indentation is
preserved but normalized such that at least one
line starts in the left column. This allows for
restructuredText or Python code to exist inside
multi-line strings.
- # Denotes the start of a line comment, when not
inside a free-format string.
The only Python objects resulting from parsing a file
with rsonlite are:
- strings:
free-format strings (described above) can
contain any character, but the whitespace
before/after the string may be stripped.
Regular strings must fit on a single line and
cannot contain '=' or '#' characters.
Regular strings may be used as keys in key/value
pairs, but free-format strings may not.
- tuple:
A key/value pair is a two-element tuple. The key is always
a string. The value is always a list.
- list:
The top level is a list, and the value element of every
key/value pair tuple is also a list. Lists can contain
strings and key/value pair tuples.
'''
import re
version = __version__ = '0.1.0'
# Our attempt at rationalizing differences between Python 2 and Python 3.
try:
basestring
except NameError:
basestring = str
class unicode: pass
# Use OrderedDict if it's available
try:
from collections import OrderedDict as stddict
except ImportError:
stddict = dict
# Splits the entire file into probable tokens.
splitter = re.compile('(\n *|=[^\n]*|#[^\n]*|[^\n#=]+)').findall
class RsonToken(str):
''' A string that may be annotated with location information
'''
def __new__(cls, s, line, col):
self = str.__new__(cls, s)
self.line = line
self.col = col
return self
def __add__(self, other):
return RsonToken(str(self) + other, self.line, self.col)
def gettoks(source):
''' Convert string into (probable) tokens
(some tokens may be recombined later, e.g. if they
contain # or = but were already inside a string)
'''
# Use "regular" strings, whatever that means for the given Python
if isinstance(source, unicode):
source = source.encode('utf-8', 'replace')
elif not isinstance(source, basestring):
source = source.decode('utf-8', 'replace')
# Convert MS-DOS or Mac line endings to the one true way, and
# prefix the source with a linefeed to simplify the tokenization.
source = '\n' + source.replace('\r\n', '\n').replace('\r', '\n')
line = 0
for tok in splitter(source):
if tok.startswith('\n'):
line += 1
col = len(tok)
else:
yield RsonToken(tok, line, col)
col += len(tok)
def multiline(lineinfo, dedent):
''' Returns one string for each line,
properly dedented.
'''
linenum = lineinfo[0].line
for tok in lineinfo:
while linenum < tok.line:
yield ''
linenum += 1
yield (tok.col - dedent) * ' ' + tok.rstrip()
linenum += 1
def getfreeformat(toklist, firsttok, firstcol):
''' Returns a free-formatted string.
'''
curline = firsttok.line
firstpart = firsttok[1:].strip() # Get past = sign
lineinfo = []
while toklist and toklist[-1].col > firstcol:
tok = toklist.pop()
if tok.line == curline:
lineinfo[-1] += tok
else:
lineinfo.append(tok)
curline = tok.line
if lineinfo:
dedent = min(tok.col for tok in lineinfo)
if firstpart:
lineinfo.insert(0, RsonToken(firstpart, firsttok.line, dedent))
firstpart = '\n'.join(multiline(lineinfo, dedent))
return RsonToken(firstpart, firsttok.line, firsttok.col)
def loads(source):
''' load a string into an rsonlite datastructure.
If the source is not a string instance, then
loads will attempt to convert it into a string
instance, by encoding to UTF-8 on Python 2,
or decoding from UTF-8 on Python 3.
'''
toklist = list(gettoks(source))
toklist.reverse()
result = [None]
stack = []
curcol = -1
curlist = result
while toklist:
tok = toklist.pop()
if tok.startswith('#'):
continue
col = tok.col
if col > curcol:
stack.append((curcol, curlist))
oldlist = curlist
curcol, curlist = col, []
oldlist[-1] = oldlist[-1], curlist
while col < curcol:
curcol, curlist = stack.pop()
if col != curcol:
err = IndentationError('unindent does not match any outer indentation level')
err.filename = '<rsonlite>'
err.lineno = tok.line
raise err
if tok.startswith('='):
curlist.append(getfreeformat(toklist, tok, col))
else:
curlist.append(RsonToken(tok.rstrip(), tok.line, tok.col))
if toklist and toklist[-1].line == tok.line:
tok = toklist.pop()
if tok.startswith('='):
curlist[-1] = curlist[-1], [getfreeformat(toklist, tok, col)]
else:
assert tok.startswith('#') # else problem in regex...
result, = result
return [] if result is None else result[1]
def dumps(data, indent=' ', initial_indent=''):
''' Dump a string loaded with loads back out.
'''
def getstring(data, indent2):
if '\n' in data:
data = ('\n'+indent2).join([''] + data.split('\n'))
return data
def recurse(data, indent2):
assert isinstance(data, list), repr(data)
for data in data:
if isinstance(data, tuple):
key, value = data
if len(value) == 1 and isinstance(value[0], basestring):
append('%s%s = %s' % (indent2, key, getstring(value[0], indent2+indent)))
else:
append('%s%s' % (indent2, key))
recurse(value, indent2 + indent)
else:
assert isinstance(data, basestring)
if '\n' in data or '=' in data or '#' in data:
append(indent2 + '=')
append(getstring(data, indent2 + ' '))
else:
append('%s%s' % (indent2, data))
result = []
append = result.append
recurse(data, initial_indent)
append('')
return '\n'.join(result)
def pretty(data, indent=' '):
''' Pretty-print a string loaded by loads into
something that makes it easy to see the actual
structure of the data. The return value of
this should be parseable by eval()
'''
def recurse(data, indent2):
assert isinstance(data, list)
for data in data:
assert isinstance(data, (tuple, basestring))
if isinstance(data, tuple) and (
len(data[1]) != 1 or not isinstance(data[1][0], basestring)):
append('%s(%s, [' % (indent2, repr(data[0])))
recurse(data[1], indent2 + indent)
append('%s])' % (indent2))
else:
append('%s%s,' % (indent2, repr(data)))
result = []
append = result.append
append('[')
recurse(data, indent)
append(']')
append('')
return '\n'.join(result)
##########################################################################
# These higher-level functions might suffice for simple data, and also
# provide a template for designing similar functions.
def stringparse(s, special=dict(true=True, false=False, null=None)):
''' This gives an example of handling the JSON special identifiers
true, false and null, and also of handling simple arrays.
'''
if s in special:
return special[s]
if s.startswith('[') and s.endswith(']'):
t = s[1:-1]
for ch in '"\'[]{}\n':
if ch in t:
return s
return [x.strip() for x in t.split(',')]
return s
def simpleparse(source, stringparse=stringparse, stddict=stddict):
''' Return the simplest structure that uses dicts instead
of tuples, and doesn't lose any source information.
Use ordered dicts if they are available.
'''
def recurse(mylist):
if len(mylist) == 1 and isinstance(mylist[0], basestring):
return stringparse(mylist[0])
keys = [x[0] for x in mylist if isinstance(x, tuple)]
if not keys:
return mylist # simple list
if len(set(keys)) == len(mylist):
return stddict((x, recurse(y)) for (x, y) in mylist)
# Complicated. Make a list that might have multiple dicts
result = []
curdict = None
for item in mylist:
if not isinstance(item, tuple):
result.append(stringparse(item))
curdict = None
continue
key, value = item
if curdict is None or key in curdict:
curdict = stddict()
result.append(curdict)
curdict[key] = recurse(value)
return result
return recurse(source if isinstance(source, list) else loads(source))
@@ -0,0 +1,6 @@
Common Examples README
======================
The beauty of the Ambiq BSP system is that it can be used to create common example code. For example if we define the proper UART instance and TX/RX pads as part of the BSP then a single source file can be used to demonstrate UART functionality across all capable boards. To utilize this capability to the fullest the common examples source code should be isolated from specific boards. This reduces redundancy in maintenance.
This directory contains common source files that may be referred to by any of the boards included in this repo. For board-specific source code look beneath the respective board's directory.
@@ -0,0 +1,21 @@
Name:
=====
ble_freertos_tag
Description:
============
ARM Cordio BLE - Proximity Tag Example
Purpose:
========
This is a standard BLE Proximity Profile example.
Printing takes place over the ITM at 1M Baud.
******************************************************************************
@@ -0,0 +1,574 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := ble_freertos_tag
COMPILERNAME := gcc
PROJECT := $(TARGET)_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_FREERTOS
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+= -DSEC_ECC_CFG=SEC_ECC_CFG_UECC
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -Dgcc
DEFINES+=
INCLUDES = -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/stack/l2c
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/hid
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/fmpl
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/stack/att
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/uribeacon
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/apps
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/gap
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/include
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/hci/include
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/third_party/exactle/wsf/sources
INCLUDES+= -I$(SDKPATH)/third_party/FreeRTOSv10.1.1/Source/portable/GCC/AMapollo2
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/sec/common
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/bas
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/apps/app
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/include
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/third_party/exactle/wsf/include
INCLUDES+= -I$(COMMONPATH)/examples/ble_freertos_tag/src
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+= -I$(SDKPATH)/third_party/exactle/wsf/sources/port/freertos
INCLUDES+= -I$(SDKPATH)/third_party/FreeRTOSv10.1.1/Source/include
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/hci/ambiq/apollo3
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/stack/dm
INCLUDES+= -I$(SDKPATH)/third_party/exactle/wsf/sources/util
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/wdxs
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/gatt
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/include/app
INCLUDES+= -I$(SDKPATH)/third_party/uecc
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/services
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/apps/tag
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/stack/smp
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/stack/hci
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/stack/cfg
INCLUDES+= -I$(SDKPATH)/third_party/exactle/ble-host/sources/hci/ambiq
VPATH = $(SDKPATH)/utils
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/stack/l2c
VPATH+=:$(COMMONPATH)/examples/ble_freertos_tag/src
VPATH+=:$(SDKPATH)/third_party/exactle/wsf/sources/port/freertos
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/hid
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/fmpl
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/stack/att
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/sec/uecc
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/apps/app/common
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/hci/ambiq/apollo3
VPATH+=:$(SDKPATH)/third_party/exactle/wsf/sources/util
VPATH+=:$(SDKPATH)/third_party/FreeRTOSv10.1.1/Source
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/stack/dm
VPATH+=:$(SDKPATH)/third_party/FreeRTOSv10.1.1/Source/portable/MemMang
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/wdxs
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/gatt
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/gap
VPATH+=:$(SDKPATH)/third_party/uecc
VPATH+=:$(SDKPATH)/devices
VPATH+=:$(SDKPATH)/third_party/FreeRTOSv10.1.1/Source/portable/GCC/AMapollo2
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/services
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/apps/tag
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/sec/common
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/profiles/bas
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/stack/smp
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/apps/app
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/stack/hci
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/stack/cfg
VPATH+=:$(SDKPATH)/third_party/exactle/ble-host/sources/hci/ambiq
VPATH+=:$(SDKPATH)/third_party/exactle/ble-profiles/sources/apps/hidapp
LIBS = $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS += $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
SRC = l2c_coc.c
SRC += l2c_main.c
SRC += l2c_master.c
SRC += l2c_slave.c
SRC += ble_freertos_tag.c
SRC += radio_task.c
SRC += rtos.c
SRC += wsf_assert.c
SRC += wsf_buf.c
SRC += wsf_efs.c
SRC += wsf_math.c
SRC += wsf_msg.c
SRC += wsf_os.c
SRC += wsf_queue.c
SRC += wsf_timer.c
SRC += wsf_trace.c
SRC += hid_main.c
SRC += fmpl_main.c
SRC += attc_disc.c
SRC += attc_main.c
SRC += attc_proc.c
SRC += attc_read.c
SRC += attc_sign.c
SRC += attc_write.c
SRC += atts_ccc.c
SRC += atts_csf.c
SRC += atts_dyn.c
SRC += atts_ind.c
SRC += atts_main.c
SRC += atts_proc.c
SRC += atts_read.c
SRC += atts_sign.c
SRC += atts_write.c
SRC += att_main.c
SRC += att_uuid.c
SRC += sec_ecc.c
SRC += app_db.c
SRC += app_hw.c
SRC += app_ui.c
SRC += ui_console.c
SRC += ui_lcd.c
SRC += ui_main.c
SRC += ui_platform.c
SRC += ui_timer.c
SRC += hci_drv_apollo3.c
SRC += bda.c
SRC += bstream.c
SRC += calc128.c
SRC += crc32.c
SRC += print.c
SRC += terminal.c
SRC += wstr.c
SRC += dm_adv.c
SRC += dm_adv_ae.c
SRC += dm_adv_leg.c
SRC += dm_conn.c
SRC += dm_conn_cte.c
SRC += dm_conn_master.c
SRC += dm_conn_master_ae.c
SRC += dm_conn_master_leg.c
SRC += dm_conn_slave.c
SRC += dm_conn_slave_ae.c
SRC += dm_conn_slave_leg.c
SRC += dm_conn_sm.c
SRC += dm_dev.c
SRC += dm_dev_priv.c
SRC += dm_main.c
SRC += dm_past.c
SRC += dm_phy.c
SRC += dm_priv.c
SRC += dm_scan.c
SRC += dm_scan_ae.c
SRC += dm_scan_leg.c
SRC += dm_sec.c
SRC += dm_sec_lesc.c
SRC += dm_sec_master.c
SRC += dm_sec_slave.c
SRC += dm_sync_ae.c
SRC += wdxs_au.c
SRC += wdxs_dc.c
SRC += wdxs_ft.c
SRC += wdxs_main.c
SRC += wdxs_phy.c
SRC += wdxs_stream.c
SRC += gatt_main.c
SRC += gap_main.c
SRC += uECC.c
SRC += uECC_ll.c
SRC += port.c
SRC += sec_aes.c
SRC += sec_aes_rev.c
SRC += sec_ccm_hci.c
SRC += sec_cmac_hci.c
SRC += sec_ecc_debug.c
SRC += sec_ecc_hci.c
SRC += sec_main.c
SRC += bas_main.c
SRC += smpi_act.c
SRC += smpi_sc_act.c
SRC += smpi_sc_sm.c
SRC += smpi_sm.c
SRC += smpr_act.c
SRC += smpr_sc_act.c
SRC += smpr_sc_sm.c
SRC += smpr_sm.c
SRC += smp_act.c
SRC += smp_db.c
SRC += smp_main.c
SRC += smp_non.c
SRC += smp_sc_act.c
SRC += smp_sc_main.c
SRC += hci_main.c
SRC += cfg_stack.c
SRC += hci_cmd.c
SRC += hci_cmd_ae.c
SRC += hci_cmd_cte.c
SRC += hci_cmd_past.c
SRC += hci_cmd_phy.c
SRC += hci_core.c
SRC += hci_core_ps.c
SRC += hci_evt.c
SRC += hci_tr.c
SRC += hci_vs.c
SRC += hci_vs_ae.c
SRC += hidapp_main.c
SRC += am_util_ble.c
SRC += am_util_debug.c
SRC += am_util_delay.c
SRC += am_util_faultisr.c
SRC += am_util_id.c
SRC += am_util_stdio.c
SRC += event_groups.c
SRC += list.c
SRC += queue.c
SRC += tasks.c
SRC += timers.c
SRC += heap_2.c
SRC += am_devices_button.c
SRC += am_devices_led.c
SRC += svc_batt.c
SRC += svc_bps.c
SRC += svc_core.c
SRC += svc_cps.c
SRC += svc_cscs.c
SRC += svc_dis.c
SRC += svc_gls.c
SRC += svc_gyro.c
SRC += svc_hid.c
SRC += svc_hrs.c
SRC += svc_hts.c
SRC += svc_ipss.c
SRC += svc_plxs.c
SRC += svc_px.c
SRC += svc_rscs.c
SRC += svc_scpss.c
SRC += svc_temp.c
SRC += svc_uricfg.c
SRC += svc_wdxs.c
SRC += svc_wp.c
SRC += svc_wss.c
SRC += tag_main.c
SRC += app_disc.c
SRC += app_main.c
SRC += app_master.c
SRC += app_master_leg.c
SRC += app_server.c
SRC += app_slave.c
SRC += app_slave_leg.c
SRC += app_terminal.c
SRC += startup_gcc.c
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := $(COMMONPATH)/examples/ble_freertos_tag/gcc/startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections -fomit-frame-pointer
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories: $(CONFIG)
$(CONFIG):
@mkdir -p $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE := $(COMMONPATH)/examples/ble_freertos_tag/gcc/ble_freertos_tag_asb.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE := $(COMMONPATH)/examples/ble_freertos_tag/gcc/ble_freertos_tag_svl.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
@echo "Uploading using the Ambiq Secure Bootloader"
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
@echo "Uploading using the SparkFun Variable Loader"
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories
@@ -0,0 +1,63 @@
/******************************************************************************
*
* ble_freertos_tag.ld - Linker script for applications using startup_gnu.c
*
*****************************************************************************/
ENTRY(Reset_Handler)
MEMORY
{
ROMEM (rx) : ORIGIN = 0x0000C000, LENGTH = 960K
RWMEM (rwx) : ORIGIN = 0x10000000, LENGTH = 384K
}
SECTIONS
{
.text :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
KEEP(*(.patch))
*(.text)
*(.text*)
*(.rodata)
*(.rodata*)
. = ALIGN(4);
_etext = .;
} > ROMEM
/* User stack section initialized by startup code. */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack)
*(.stack*)
. = ALIGN(8);
} > RWMEM
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} > RWMEM AT>ROMEM
/* used by startup to initialize data */
_init_data = LOADADDR(.data);
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} > RWMEM
.ARM.attributes 0 : { *(.ARM.attributes) }
}
@@ -0,0 +1,63 @@
/******************************************************************************
*
* ble_freertos_tag.ld - Linker script for applications using startup_gnu.c
*
*****************************************************************************/
ENTRY(Reset_Handler)
MEMORY
{
ROMEM (rx) : ORIGIN = 0x00010000, LENGTH = 960K
RWMEM (rwx) : ORIGIN = 0x10000000, LENGTH = 384K
}
SECTIONS
{
.text :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
KEEP(*(.patch))
*(.text)
*(.text*)
*(.rodata)
*(.rodata*)
. = ALIGN(4);
_etext = .;
} > ROMEM
/* User stack section initialized by startup code. */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack)
*(.stack*)
. = ALIGN(8);
} > RWMEM
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} > RWMEM AT>ROMEM
/* used by startup to initialize data */
_init_data = LOADADDR(.data);
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} > RWMEM
.ARM.attributes 0 : { *(.ARM.attributes) }
}
@@ -0,0 +1,354 @@
//*****************************************************************************
//
//! @file startup_gcc.c
//!
//! @brief Definitions for interrupt handlers, the vector table, and the stack.
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include <stdint.h>
//*****************************************************************************
//
// Forward declaration of interrupt handlers.
//
//*****************************************************************************
extern void Reset_Handler(void) __attribute ((naked));
extern void NMI_Handler(void) __attribute ((weak));
extern void HardFault_Handler(void) __attribute ((weak));
extern void MemManage_Handler(void) __attribute ((weak, alias ("HardFault_Handler")));
extern void BusFault_Handler(void) __attribute ((weak, alias ("HardFault_Handler")));
extern void UsageFault_Handler(void) __attribute ((weak, alias ("HardFault_Handler")));
extern void SecureFault_Handler(void) __attribute ((weak));
extern void SVC_Handler(void) __attribute ((weak, alias ("am_default_isr")));
extern void DebugMon_Handler(void) __attribute ((weak, alias ("am_default_isr")));
extern void PendSV_Handler(void) __attribute ((weak, alias ("am_default_isr")));
extern void SysTick_Handler(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_brownout_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_watchdog_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_rtc_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_vcomp_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_ioslave_ios_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_ioslave_acc_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_iomaster0_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_iomaster1_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_iomaster2_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_iomaster3_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_iomaster4_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_iomaster5_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_ble_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_gpio_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_ctimer_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_uart_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_uart1_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_scard_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_adc_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_pdm0_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_mspi0_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_software0_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_cmpr0_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_cmpr1_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_cmpr2_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_cmpr3_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_cmpr4_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_cmpr5_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_cmpr6_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_stimer_cmpr7_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_clkgen_isr(void) __attribute ((weak, alias ("am_default_isr")));
extern void am_default_isr(void) __attribute ((weak));
//*****************************************************************************
//
// The entry point for the application.
//
//*****************************************************************************
extern int main(void);
//*****************************************************************************
//
// Reserve space for the system stack.
//
//*****************************************************************************
__attribute__ ((section(".stack")))
static uint32_t g_pui32Stack[0xac0];
//*****************************************************************************
//
// The vector table. Note that the proper constructs must be placed on this to
// ensure that it ends up at physical address 0x0000.0000.
//
// Note: Aliasing and weakly exporting am_mpufault_isr, am_busfault_isr, and
// am_usagefault_isr does not work if am_fault_isr is defined externally.
// Therefore, we'll explicitly use am_fault_isr in the table for those vectors.
//
//*****************************************************************************
__attribute__ ((section(".isr_vector")))
void (* const g_am_pfnVectors[])(void) =
{
(void (*)(void))((uint32_t)g_pui32Stack + sizeof(g_pui32Stack)),
// The initial stack pointer
Reset_Handler, // The reset handler
NMI_Handler, // The NMI handler
HardFault_Handler, // The hard fault handler
MemManage_Handler, // The MemManage_Handler
BusFault_Handler, // The BusFault_Handler
UsageFault_Handler, // The UsageFault_Handler
SecureFault_Handler, // The SecureFault_Handler
0, // Reserved
0, // Reserved
0, // Reserved
SVC_Handler, // SVCall handler
DebugMon_Handler, // Debug monitor handler
0, // Reserved
PendSV_Handler, // The PendSV handler
SysTick_Handler, // The SysTick handler
//
// Peripheral Interrupts
//
am_brownout_isr, // 0: Brownout (rstgen)
am_watchdog_isr, // 1: Watchdog
am_rtc_isr, // 2: RTC
am_vcomp_isr, // 3: Voltage Comparator
am_ioslave_ios_isr, // 4: I/O Slave general
am_ioslave_acc_isr, // 5: I/O Slave access
am_iomaster0_isr, // 6: I/O Master 0
am_iomaster1_isr, // 7: I/O Master 1
am_iomaster2_isr, // 8: I/O Master 2
am_iomaster3_isr, // 9: I/O Master 3
am_iomaster4_isr, // 10: I/O Master 4
am_iomaster5_isr, // 11: I/O Master 5
am_ble_isr, // 12: BLEIF
am_gpio_isr, // 13: GPIO
am_ctimer_isr, // 14: CTIMER
am_uart_isr, // 15: UART0
am_uart1_isr, // 16: UART1
am_scard_isr, // 17: SCARD
am_adc_isr, // 18: ADC
am_pdm0_isr, // 19: PDM
am_mspi0_isr, // 20: MSPI0
am_software0_isr, // 21: SOFTWARE0
am_stimer_isr, // 22: SYSTEM TIMER
am_stimer_cmpr0_isr, // 23: SYSTEM TIMER COMPARE0
am_stimer_cmpr1_isr, // 24: SYSTEM TIMER COMPARE1
am_stimer_cmpr2_isr, // 25: SYSTEM TIMER COMPARE2
am_stimer_cmpr3_isr, // 26: SYSTEM TIMER COMPARE3
am_stimer_cmpr4_isr, // 27: SYSTEM TIMER COMPARE4
am_stimer_cmpr5_isr, // 28: SYSTEM TIMER COMPARE5
am_stimer_cmpr6_isr, // 29: SYSTEM TIMER COMPARE6
am_stimer_cmpr7_isr, // 30: SYSTEM TIMER COMPARE7
am_clkgen_isr, // 31: CLKGEN
};
//******************************************************************************
//
// Place code immediately following vector table.
//
//******************************************************************************
//******************************************************************************
//
// The Patch table.
//
// The patch table should pad the vector table size to a total of 64 entries
// (16 core + 48 periph) such that code begins at offset 0x100.
//
//******************************************************************************
__attribute__ ((section(".patch")))
uint32_t const __Patchable[] =
{
0, // 32
0, // 33
0, // 34
0, // 35
0, // 36
0, // 37
0, // 38
0, // 39
0, // 40
0, // 41
0, // 42
0, // 43
0, // 44
0, // 45
0, // 46
0, // 47
};
//*****************************************************************************
//
// The following are constructs created by the linker, indicating where the
// the "data" and "bss" segments reside in memory. The initializers for the
// "data" segment resides immediately following the "text" segment.
//
//*****************************************************************************
extern uint32_t _etext;
extern uint32_t _sdata;
extern uint32_t _edata;
extern uint32_t _sbss;
extern uint32_t _ebss;
//*****************************************************************************
//
// This is the code that gets called when the processor first starts execution
// following a reset event. Only the absolutely necessary set is performed,
// after which the application supplied entry() routine is called.
//
//*****************************************************************************
#if defined(__GNUC_STDC_INLINE__)
void
Reset_Handler(void)
{
//
// Set the vector table pointer.
//
__asm(" ldr r0, =0xE000ED08\n"
" ldr r1, =g_am_pfnVectors\n"
" str r1, [r0]");
//
// Set the stack pointer.
//
__asm(" ldr sp, [r1]");
#ifndef NOFPU
//
// Enable the FPU.
//
__asm("ldr r0, =0xE000ED88\n"
"ldr r1,[r0]\n"
"orr r1,#(0xF << 20)\n"
"str r1,[r0]\n"
"dsb\n"
"isb\n");
#endif
//
// Copy the data segment initializers from flash to SRAM.
//
__asm(" ldr r0, =_init_data\n"
" ldr r1, =_sdata\n"
" ldr r2, =_edata\n"
"copy_loop:\n"
" ldr r3, [r0], #4\n"
" str r3, [r1], #4\n"
" cmp r1, r2\n"
" blt copy_loop\n");
//
// Zero fill the bss segment.
//
__asm(" ldr r0, =_sbss\n"
" ldr r1, =_ebss\n"
" mov r2, #0\n"
"zero_loop:\n"
" cmp r0, r1\n"
" it lt\n"
" strlt r2, [r0], #4\n"
" blt zero_loop");
//
// Call the application's entry point.
//
main();
//
// If main returns then execute a break point instruction
//
__asm(" bkpt ");
}
#else
#error GNU STDC inline not supported.
#endif
//*****************************************************************************
//
// This is the code that gets called when the processor receives a NMI. This
// simply enters an infinite loop, preserving the system state for examination
// by a debugger.
//
//*****************************************************************************
void
NMI_Handler(void)
{
//
// Go into an infinite loop.
//
while(1)
{
}
}
//*****************************************************************************
//
// This is the code that gets called when the processor receives a fault
// interrupt. This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
void
HardFault_Handler(void)
{
//
// Go into an infinite loop.
//
while(1)
{
}
}
//*****************************************************************************
//
// This is the code that gets called when the processor receives an unexpected
// interrupt. This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
void
am_default_isr(void)
{
//
// Go into an infinite loop.
//
while(1)
{
}
}
@@ -0,0 +1,161 @@
//*****************************************************************************
//
//! @file FreeRTOSConfig.h
//!
//! @brief Configuration options for FreeRTOS
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#ifdef __cplusplus
extern "C"
{
#endif
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#ifdef AM_PART_APOLLO
#define configCPU_CLOCK_HZ 24000000UL
#else
#define configCPU_CLOCK_HZ 48000000UL
#endif
#define configTICK_RATE_HZ 1000
#define configMAX_PRIORITIES 4
#define configMINIMAL_STACK_SIZE (256)
#define configTOTAL_HEAP_SIZE (16 * 1024)
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_COUNTING_SEMAPHORES 0
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE 0
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_MALLOC_FAILED_HOOK 1
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 3
#define configTIMER_QUEUE_LENGTH 5
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Interrupt nesting behaviour configuration. */
#define configKERNEL_INTERRUPT_PRIORITY (0x7 << 5)
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (0x4 << 5)
#define NVIC_configKERNEL_INTERRUPT_PRIORITY (0x7)
#define NVIC_configMAX_SYSCALL_INTERRUPT_PRIORITY (0x4)
/* Define to trap errors during development. */
#define configASSERT(x) if (( x ) == 0) while(1);
/* FreeRTOS MPU specific definitions. */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 0
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 0
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 1 // Enable non-SysTick based Tick
#define configUSE_TICKLESS_IDLE 2 // Ambiq specific implementation for Tickless
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
extern uint32_t am_freertos_sleep(uint32_t);
extern void am_freertos_wakeup(uint32_t);
#define configPRE_SLEEP_PROCESSING( time ) \
do { \
(time) = am_freertos_sleep(time); \
} while (0);
#define configPOST_SLEEP_PROCESSING(time) am_freertos_wakeup(time)
#endif
/*-----------------------------------------------------------*/
#ifndef AM_PART_APOLLO
#define AM_FREERTOS_USE_STIMER_FOR_TICK
#endif
#ifdef AM_FREERTOS_USE_STIMER_FOR_TICK
#define configSTIMER_CLOCK_HZ 32768
#else // Use CTimer
#define configCTIMER_CLOCK_HZ 32768
#endif
#ifdef __cplusplus
}
#endif
#endif // FREERTOS_CONFIG_H
@@ -0,0 +1,166 @@
//*****************************************************************************
//
//! @file ble_freertos_tag.c
//!
//! @brief ARM Cordio BLE - Proximity Tag Example
//!
//! Purpose: This is a standard BLE Proximity Profile example.
//!
//! Printing takes place over the ITM at 1M Baud.
//!
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
//*****************************************************************************
//
// This application has a large number of common include files. For
// convenience, we'll collect them all together in a single header and include
// that everywhere.
//
//*****************************************************************************
#include "ble_freertos_tag.h"
#include "rtos.h"
//*****************************************************************************
//
// Enable printing to the console.
//
//*****************************************************************************
void
enable_print_interface(void)
{
//
// Initialize a debug printing interface.
//
am_bsp_itm_printf_enable();
}
//*****************************************************************************
//
// Main Function
//
//*****************************************************************************
int
main(void)
{
//
// Set the clock frequency
//
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
//
// Set the default cache configuration
//
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
#ifndef NOFPU
//
// Enable the floating point module, and configure the core for lazy
// stacking.
//
am_hal_sysctrl_fpu_enable();
am_hal_sysctrl_fpu_stacking_enable(true);
#else
am_hal_sysctrl_fpu_disable();
#endif
//
// Configure the board for low power.
//
am_bsp_low_power_init();
// Turn off unused Flash & SRAM
#ifdef AM_PART_APOLLO
//
// SRAM bank power setting.
// Need to match up with actual SRAM usage for the program
// Current usage is between 32K and 40K - so disabling upper 3 banks
//
am_hal_mcuctrl_sram_power_set(AM_HAL_MCUCTRL_SRAM_POWER_DOWN_5 |
AM_HAL_MCUCTRL_SRAM_POWER_DOWN_6 |
AM_HAL_MCUCTRL_SRAM_POWER_DOWN_7,
AM_HAL_MCUCTRL_SRAM_POWER_DOWN_5 |
AM_HAL_MCUCTRL_SRAM_POWER_DOWN_6 |
AM_HAL_MCUCTRL_SRAM_POWER_DOWN_7);
#if 0 // Not turning off the Flash as it may be needed to download the image
//
// Flash bank power set.
//
am_hal_mcuctrl_flash_power_set(AM_HAL_MCUCTRL_FLASH_POWER_DOWN_1);
#endif
#endif // AM_PART_APOLLO
#ifdef AM_PART_APOLLO2
#if 0 // Not turning off the Flash as it may be needed to download the image
am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEMEN_FLASH512K);
#endif
am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEMEN_SRAM64K);
#endif // AM_PART_APOLLO2
//
// Enable printing to the console.
//
#ifdef AM_DEBUG_PRINTF
enable_print_interface();
#endif
//
// Initialize plotting interface.
//
am_util_debug_printf("FreeRTOS Tag Example\n");
//
// Run the application.
//
run_tasks();
//
// We shouldn't ever get here.
//
while (1)
{
}
}
@@ -0,0 +1,89 @@
//*****************************************************************************
//
//! @file ble_freertos_tag.h
//!
//! @brief Global includes for the ble_freertos_tag app.
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#ifndef BLE_FREERTOS_TAG_H
#define BLE_FREERTOS_TAG_H
//*****************************************************************************
//
// Required built-ins.
//
//*****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
//*****************************************************************************
//
// Standard AmbiqSuite includes.
//
//*****************************************************************************
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
//*****************************************************************************
//
// FreeRTOS include files.
//
//*****************************************************************************
#include "FreeRTOS.h"
#include "task.h"
#include "portmacro.h"
#include "portable.h"
#include "semphr.h"
#include "event_groups.h"
//#include "rtos.h"
//*****************************************************************************
//
// Task include files.
//
//*****************************************************************************
#include "radio_task.h"
#endif // FREERTOS_FIT_H
@@ -0,0 +1,77 @@
//*****************************************************************************
//
//! @file hci_apollo_config.h
//!
//! @brief This file describes the physical aspects of the HCI conection.
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include <stdint.h>
#include "am_bsp.h"
#ifndef HCI_APOLLO_CONFIG_H
#define HCI_APOLLO_CONFIG_H
//*****************************************************************************
//
// Pin numbers and configuration.
//
// NOTE: RTS, CTS, and RESET are implemented as GPIOs, so no "CFG" field is
// needed.
//
//*****************************************************************************
//#define HCI_APOLLO_POWER_PIN AM_BSP_GPIO_EM9304_POWER
//#define HCI_APOLLO_POWER_CFG AM_BSP_GPIO_CFG_EM9304_POWER
#define HCI_APOLLO_RESET_PIN AM_BSP_GPIO_EM9304_RESET
//*****************************************************************************
//
// Other options.
//
// These options are provided in case your board setup is a little more
// unusual. Most boards shouldn't need these features. If in doubt, leave all
// of these features disabled.
//
//*****************************************************************************
#define HCI_APOLLO_CFG_OVERRIDE_ISR 1 // Override the exactle UART ISR
#endif // HCI_APOLLO_CONFIG_H
@@ -0,0 +1,401 @@
//*****************************************************************************
//
//! @file radio_task.c
//!
//! @brief Task to handle radio operation.
//!
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
//*****************************************************************************
//
// Global includes for this project.
//
//*****************************************************************************
#include "ble_freertos_tag.h"
//*****************************************************************************
//
// WSF standard includes.
//
//*****************************************************************************
#include "wsf_types.h"
#include "wsf_trace.h"
#include "wsf_buf.h"
#include "wsf_timer.h"
//*****************************************************************************
//
// Includes for operating the ExactLE stack.
//
//*****************************************************************************
#include "hci_handler.h"
#include "dm_handler.h"
#include "l2c_handler.h"
#include "att_handler.h"
#include "smp_handler.h"
#include "l2c_api.h"
#include "att_api.h"
#include "smp_api.h"
#include "app_api.h"
#include "hci_core.h"
#include "hci_drv.h"
#include "hci_drv_apollo.h"
#include "hci_drv_apollo3.h"
#include "hci_apollo_config.h"
#include "wsf_msg.h"
//*****************************************************************************
//
//
//*****************************************************************************
#include "tag_api.h"
#include "app_ui.h"
//*****************************************************************************
//
// Radio task handle.
//
//*****************************************************************************
TaskHandle_t radio_task_handle;
//*****************************************************************************
//
// Function prototypes
//
//*****************************************************************************
void exactle_stack_init(void);
void button_handler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
void setup_buttons(void);
//*****************************************************************************
//
// Timer for buttons.
//
//*****************************************************************************
wsfHandlerId_t ButtonHandlerId;
wsfTimer_t ButtonTimer;
//*****************************************************************************
//
// WSF buffer pools.
//
//*****************************************************************************
#define WSF_BUF_POOLS 4
// Important note: the size of g_pui32BufMem should includes both overhead of internal
// buffer management structure, wsfBufPool_t (up to 16 bytes for each pool), and pool
// description (e.g. g_psPoolDescriptors below).
// Memory for the buffer pool
// extra AMOTA_PACKET_SIZE bytes for OTA handling
static uint32_t g_pui32BufMem[
(WSF_BUF_POOLS*16
+ 16*8 + 32*4 + 64*6 + 280*8) / sizeof(uint32_t)];
// Default pool descriptor.
static wsfBufPoolDesc_t g_psPoolDescriptors[WSF_BUF_POOLS] =
{
{ 16, 8 },
{ 32, 4 },
{ 64, 6 },
{ 280, 8 }
};
//*****************************************************************************
//
// Tracking variable for the scheduler timer.
//
//*****************************************************************************
void radio_timer_handler(void);
//*****************************************************************************
//
// Poll the buttons.
//
//*****************************************************************************
void
button_handler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
{
//
// Restart the button timer.
//
WsfTimerStartMs(&ButtonTimer, 10);
#ifdef AM_BSP_NUM_BUTTONS
//
// Every time we get a button timer tick, check all of our buttons.
//
am_devices_button_array_tick(am_bsp_psButtons, AM_BSP_NUM_BUTTONS);
//
// If we got a a press, do something with it.
//
if ( am_devices_button_released(am_bsp_psButtons[0]) )
{
am_util_debug_printf("Got Button 0 Press\n");
AppUiBtnTest(APP_UI_BTN_1_SHORT);
}
if ( am_devices_button_released(am_bsp_psButtons[1]) )
{
am_util_debug_printf("Got Button 1 Press\n");
AppUiBtnTest(APP_UI_BTN_1_SHORT);
}
if ( am_devices_button_released(am_bsp_psButtons[2]) )
{
am_util_debug_printf("Got Button 2 Press\n");
}
#endif // AM_BSP_NUM_BUTTONS
}
//*****************************************************************************
//
// Sets up a button interface.
//
//*****************************************************************************
void
setup_buttons(void)
{
#ifdef AM_BSP_NUM_BUTTONS
//
// Enable the buttons for user interaction.
//
am_devices_button_array_init(am_bsp_psButtons, AM_BSP_NUM_BUTTONS);
//
// Start a timer.
//
ButtonTimer.handlerId = ButtonHandlerId;
WsfTimerStartSec(&ButtonTimer, 2);
#endif // AM_BSP_NUM_BUTTONS
}
//*****************************************************************************
//
// Initialization for the ExactLE stack.
//
//*****************************************************************************
void
exactle_stack_init(void)
{
wsfHandlerId_t handlerId;
uint16_t wsfBufMemLen;
//
// Set up timers for the WSF scheduler.
//
WsfOsInit();
WsfTimerInit();
//
// Initialize a buffer pool for WSF dynamic memory needs.
//
wsfBufMemLen = WsfBufInit(sizeof(g_pui32BufMem), (uint8_t *)g_pui32BufMem, WSF_BUF_POOLS,
g_psPoolDescriptors);
if (wsfBufMemLen > sizeof(g_pui32BufMem))
{
am_util_debug_printf("Memory pool is too small by %d\r\n",
wsfBufMemLen - sizeof(g_pui32BufMem));
}
//
// Initialize the WSF security service.
//
SecInit();
SecAesInit();
SecCmacInit();
SecEccInit();
//
// Set up callback functions for the various layers of the ExactLE stack.
//
handlerId = WsfOsSetNextHandler(HciHandler);
HciHandlerInit(handlerId);
handlerId = WsfOsSetNextHandler(DmHandler);
DmDevVsInit(0);
DmAdvInit();
DmConnInit();
DmConnSlaveInit();
DmSecInit();
DmSecLescInit();
DmPrivInit();
DmHandlerInit(handlerId);
handlerId = WsfOsSetNextHandler(L2cSlaveHandler);
L2cSlaveHandlerInit(handlerId);
L2cInit();
L2cSlaveInit();
handlerId = WsfOsSetNextHandler(AttHandler);
AttHandlerInit(handlerId);
AttsInit();
AttsIndInit();
AttcInit();
handlerId = WsfOsSetNextHandler(SmpHandler);
SmpHandlerInit(handlerId);
SmprInit();
SmprScInit();
HciSetMaxRxAclLen(251);
handlerId = WsfOsSetNextHandler(AppHandler);
AppHandlerInit(handlerId);
handlerId = WsfOsSetNextHandler(TagHandler);
TagHandlerInit(handlerId);
ButtonHandlerId = WsfOsSetNextHandler(button_handler);
handlerId = WsfOsSetNextHandler(HciDrvHandler);
HciDrvHandlerInit(handlerId);
}
//*****************************************************************************
//
// UART interrupt handler.
//
//*****************************************************************************
void
am_uart_isr(void)
{
uint32_t ui32Status;
//
// Read and save the interrupt status, but clear out the status register.
//
ui32Status = UARTn(0)->MIS;
UARTn(0)->IEC = ui32Status;
//
// Allow the HCI driver to respond to the interrupt.
//
//HciDrvUartISR(ui32Status);
// Signal radio task to run
WsfTaskSetReady(0, 0);
}
//*****************************************************************************
//
// Interrupt handler for BLE
//
//*****************************************************************************
void
am_ble_isr(void)
{
HciDrvIntService();
// Signal radio task to run
WsfTaskSetReady(0, 0);
}
//*****************************************************************************
//
// Perform initial setup for the radio task.
//
//*****************************************************************************
void
RadioTaskSetup(void)
{
am_util_debug_printf("RadioTask: setup\r\n");
NVIC_SetPriority(BLE_IRQn, NVIC_configMAX_SYSCALL_INTERRUPT_PRIORITY);
//
// Boot the radio.
//
HciDrvRadioBoot(1);
}
//*****************************************************************************
//
// Short Description.
//
//*****************************************************************************
void
RadioTask(void *pvParameters)
{
#if WSF_TRACE_ENABLED == TRUE
//
// Enable ITM
//
am_util_debug_printf("Starting wicentric trace:\n\n");
#endif
//
// Initialize the main ExactLE stack.
//
exactle_stack_init();
//
// Prep the buttons for use
//
setup_buttons();
//
// Start the "Tag" profile.
//
TagStart();
while (1)
{
//
// Calculate the elapsed time from our free-running timer, and update
// the software timers in the WSF scheduler.
//
wsfOsDispatcher();
}
}
@@ -0,0 +1,65 @@
//*****************************************************************************
//
//! @file radio_task.h
//!
//! @brief Functions and variables related to the radio task.
//!
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#ifndef RADIO_TASK_H
#define RADIO_TASK_H
//*****************************************************************************
//
// Radio task handle.
//
//*****************************************************************************
extern TaskHandle_t radio_task_handle;
//*****************************************************************************
//
// External function definitions.
//
//*****************************************************************************
extern void RadioTaskSetup(void);
extern void RadioTask(void *pvParameters);
#endif // RADIO_TASK_H
@@ -0,0 +1,214 @@
//*****************************************************************************
//
//! @file rtos.c
//!
//! @brief Essential functions to make the RTOS run correctly.
//!
//! These functions are required by the RTOS for ticking, sleeping, and basic
//! error checking.
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "portmacro.h"
#include "portable.h"
#include "ble_freertos_tag.h"
//*****************************************************************************
//
// Task handle for the initial setup task.
//
//*****************************************************************************
TaskHandle_t xSetupTask;
//*****************************************************************************
//
// Interrupt handler for the CTIMER module.
//
//*****************************************************************************
void
am_ctimer_isr(void)
{
uint32_t ui32Status;
//
// Check the timer interrupt status.
//
ui32Status = am_hal_ctimer_int_status_get(false);
am_hal_ctimer_int_clear(ui32Status);
//
// Run handlers for the various possible timer events.
//
am_hal_ctimer_int_service(ui32Status);
}
//*****************************************************************************
//
// Sleep function called from FreeRTOS IDLE task.
// Do necessary application specific Power down operations here
// Return 0 if this function also incorporates the WFI, else return value same
// as idleTime
//
//*****************************************************************************
uint32_t am_freertos_sleep(uint32_t idleTime)
{
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
return 0;
}
//*****************************************************************************
//
// Recovery function called from FreeRTOS IDLE task, after waking up from Sleep
// Do necessary 'wakeup' operations here, e.g. to power up/enable peripherals etc.
//
//*****************************************************************************
void am_freertos_wakeup(uint32_t idleTime)
{
return;
}
//*****************************************************************************
//
// FreeRTOS debugging functions.
//
//*****************************************************************************
void
vApplicationMallocFailedHook(void)
{
//
// Called if a call to pvPortMalloc() fails because there is insufficient
// free memory available in the FreeRTOS heap. pvPortMalloc() is called
// internally by FreeRTOS API functions that create tasks, queues, software
// timers, and semaphores. The size of the FreeRTOS heap is set by the
// configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h.
//
while (1);
}
void
vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName)
{
(void) pcTaskName;
(void) pxTask;
//
// Run time stack overflow checking is performed if
// configconfigCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
// function is called if a stack overflow is detected.
//
while (1)
{
__asm("BKPT #0\n") ; // Break into the debugger
}
}
//*****************************************************************************
//
// High priority task to run immediately after the scheduler starts.
//
// This task is used for any global initialization that must occur after the
// scheduler starts, but before any functional tasks are running. This can be
// useful for enabling events, semaphores, and other global, RTOS-specific
// features.
//
//*****************************************************************************
void
setup_task(void *pvParameters)
{
//
// Print a debug message.
//
am_util_debug_printf("Running setup tasks...\r\n");
//
// Run setup functions.
//
RadioTaskSetup();
//
// Create the functional tasks
//
xTaskCreate(RadioTask, "RadioTask", 512, 0, 3, &radio_task_handle);
//
// The setup operations are complete, so suspend the setup task now.
//
vTaskSuspend(NULL);
while (1);
}
//*****************************************************************************
//
// Initializes all tasks
//
//*****************************************************************************
void
run_tasks(void)
{
//
// Set some interrupt priorities before we create tasks or start the scheduler.
//
// Note: Timer priority is handled by the FreeRTOS kernel, so we won't
// touch it here.
//
//
// Create essential tasks.
//
xTaskCreate(setup_task, "Setup", 512, 0, 3, &xSetupTask);
//
// Start the scheduler.
//
vTaskStartScheduler();
}
@@ -0,0 +1,75 @@
//*****************************************************************************
//
//! @file rtos.h
//!
//! @brief Essential functions to make the RTOS run
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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.3.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#ifndef RTOS_H
#define RTOS_H
#ifdef __cplusplus
extern "C"
{
#endif
//*****************************************************************************
//
// Macro definitions
//
//*****************************************************************************
// External variable definitions
//
//*****************************************************************************
//*****************************************************************************
//
// External function definitions
//
//*****************************************************************************
void run_tasks(void);
#ifdef __cplusplus
}
#endif
#endif // RTOS_H
@@ -0,0 +1,401 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := blinky
COMPILERNAME := gcc
PROJECT := blinky_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.c
SRC+= startup_gcc.c
SRC+= am_util_delay.c
SRC+= am_util_faultisr.c
SRC+= am_util_stdio.c
SRC+= am_devices_led.c
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(SDKPATH)/devices
VPATH+= $(COMMONPATH)/examples/blinky
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,84 @@
//*****************************************************************************
//
//! @file main.c
//!
//! @brief A simple LED blinking example.
//!
//
//*****************************************************************************
/*
Copyright (c) 2019 SparkFun Electronics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#define BLINK_PERIOD 500
//*****************************************************************************
//
// Main
//
//*****************************************************************************
int
main(void)
{
// Set the clock frequency.
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
// Set the default cache configuration
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
// Configure the board for low power operation.
am_bsp_low_power_init();
// Set up BSP leds
#ifdef AM_BSP_NUM_LEDS
uint32_t ux, ui32GPIONumber;
for (ux = 0; ux < AM_BSP_NUM_LEDS; ux++) {
ui32GPIONumber = am_bsp_psLEDs[ux].ui32GPIONumber;
am_hal_gpio_pinconfig(ui32GPIONumber, g_AM_HAL_GPIO_OUTPUT);
am_devices_led_off(am_bsp_psLEDs, ux);
}
#endif // AM_BSP_NUM_LEDS
bool led_state = false;
// Blink forever
while (1)
{
// Toggle LEDs
#ifdef AM_BSP_NUM_LEDS
led_state = !led_state;
uint32_t ux;
for (ux = 0; ux < AM_BSP_NUM_LEDS; ux++) {
ui32GPIONumber = am_bsp_psLEDs[ux].ui32GPIONumber;
(led_state) ? am_devices_led_on(am_bsp_psLEDs, ux) : am_devices_led_off(am_bsp_psLEDs, ux);
}
#endif // AM_BSP_NUM_LEDS
// Delay
am_util_delay_ms(BLINK_PERIOD);
}
}
@@ -0,0 +1,401 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := hello_world_uart
COMPILERNAME := gcc
PROJECT := $(TARGET)_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.c
SRC+= startup_gcc.c
SRC+= am_util_delay.c
SRC+= am_util_faultisr.c
SRC+= am_util_id.c
SRC+= am_util_stdio.c
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/examples/hello_world_uart
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,332 @@
//*****************************************************************************
//
//! @file hello_world_uart.c
//!
//! @brief A simple "Hello World" example using the UART peripheral.
//!
//! Purpose: This example prints a "Hello World" message with some device info
//! over UART at 115200 baud. To see the output of this program, run AMFlash,
//! and configure the console for UART. The example sleeps after it is done
//! printing.
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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 v2.2.0-7-g63f7c2ba1 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
//*****************************************************************************
//
// UART handle.
//
//*****************************************************************************
void *phUART;
#define CHECK_ERRORS(x) \
if ((x) != AM_HAL_STATUS_SUCCESS) \
{ \
error_handler(x); \
}
volatile uint32_t ui32LastError;
//*****************************************************************************
//
// Catch HAL errors.
//
//*****************************************************************************
void
error_handler(uint32_t ui32ErrorStatus)
{
ui32LastError = ui32ErrorStatus;
while (1);
}
//*****************************************************************************
//
// UART buffers.
//
//*****************************************************************************
uint8_t g_pui8TxBuffer[256];
uint8_t g_pui8RxBuffer[2];
//*****************************************************************************
//
// UART configuration.
//
//*****************************************************************************
const am_hal_uart_config_t g_sUartConfig =
{
//
// Standard UART settings: 115200-8-N-1
//
.ui32BaudRate = 115200,
.ui32DataBits = AM_HAL_UART_DATA_BITS_8,
.ui32Parity = AM_HAL_UART_PARITY_NONE,
.ui32StopBits = AM_HAL_UART_ONE_STOP_BIT,
.ui32FlowControl = AM_HAL_UART_FLOW_CTRL_NONE,
//
// Set TX and RX FIFOs to interrupt at half-full.
//
.ui32FifoLevels = (AM_HAL_UART_TX_FIFO_1_2 |
AM_HAL_UART_RX_FIFO_1_2),
//
// Buffers
//
.pui8TxBuffer = g_pui8TxBuffer,
.ui32TxBufferSize = sizeof(g_pui8TxBuffer),
.pui8RxBuffer = g_pui8RxBuffer,
.ui32RxBufferSize = sizeof(g_pui8RxBuffer),
};
//*****************************************************************************
//
// UART0 interrupt handler.
//
//*****************************************************************************
void
am_uart_isr(void)
{
//
// Service the FIFOs as necessary, and clear the interrupts.
//
uint32_t ui32Status, ui32Idle;
am_hal_uart_interrupt_status_get(phUART, &ui32Status, true);
am_hal_uart_interrupt_clear(phUART, ui32Status);
am_hal_uart_interrupt_service(phUART, ui32Status, &ui32Idle);
}
//*****************************************************************************
//
// UART print string
//
//*****************************************************************************
void
uart_print(char *pcStr)
{
uint32_t ui32StrLen = 0;
uint32_t ui32BytesWritten = 0;
//
// Measure the length of the string.
//
while (pcStr[ui32StrLen] != 0)
{
ui32StrLen++;
}
//
// Print the string via the UART.
//
const am_hal_uart_transfer_t sUartWrite =
{
.ui32Direction = AM_HAL_UART_WRITE,
.pui8Data = (uint8_t *) pcStr,
.ui32NumBytes = ui32StrLen,
.ui32TimeoutMs = 0,
.pui32BytesTransferred = &ui32BytesWritten,
};
CHECK_ERRORS(am_hal_uart_transfer(phUART, &sUartWrite));
if (ui32BytesWritten != ui32StrLen)
{
//
// Couldn't send the whole string!!
//
while(1);
}
}
//*****************************************************************************
//
// Main
//
//*****************************************************************************
int
main(void)
{
am_util_id_t sIdDevice;
uint32_t ui32StrBuf;
//
// Set the clock frequency.
//
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
//
// Set the default cache configuration
//
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
//
// Configure the board for low power operation.
//
am_bsp_low_power_init();
//
// Initialize the printf interface for UART output.
//
CHECK_ERRORS(am_hal_uart_initialize(0, &phUART));
CHECK_ERRORS(am_hal_uart_power_control(phUART, AM_HAL_SYSCTRL_WAKE, false));
CHECK_ERRORS(am_hal_uart_configure(phUART, &g_sUartConfig));
//
// Enable the UART pins.
//
am_hal_gpio_pinconfig(AM_BSP_GPIO_COM_UART_TX, g_AM_BSP_GPIO_COM_UART_TX);
am_hal_gpio_pinconfig(AM_BSP_GPIO_COM_UART_RX, g_AM_BSP_GPIO_COM_UART_RX);
//
// Enable interrupts.
//
NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + AM_BSP_UART_PRINT_INST));
am_hal_interrupt_master_enable();
//
// Set the main print interface to use the UART print function we defined.
//
am_util_stdio_printf_init(uart_print);
//
// Print the banner.
//
am_util_stdio_terminal_clear();
am_util_stdio_printf("Hello World!\n\n");
//
// Print the device info.
//
am_util_id_device(&sIdDevice);
am_util_stdio_printf("Vendor Name: %s\n", sIdDevice.pui8VendorName);
am_util_stdio_printf("Device type: %s\n", sIdDevice.pui8DeviceName);
am_util_stdio_printf("Qualified: %s\n",
sIdDevice.sMcuCtrlDevice.ui32Qualified ?
"Yes" : "No");
am_util_stdio_printf("Device Info:\n"
"\tPart number: 0x%08X\n"
"\tChip ID0: 0x%08X\n"
"\tChip ID1: 0x%08X\n"
"\tRevision: 0x%08X (Rev%c%c)\n",
sIdDevice.sMcuCtrlDevice.ui32ChipPN,
sIdDevice.sMcuCtrlDevice.ui32ChipID0,
sIdDevice.sMcuCtrlDevice.ui32ChipID1,
sIdDevice.sMcuCtrlDevice.ui32ChipRev,
sIdDevice.ui8ChipRevMaj, sIdDevice.ui8ChipRevMin );
//
// If not a multiple of 1024 bytes, append a plus sign to the KB.
//
ui32StrBuf = ( sIdDevice.sMcuCtrlDevice.ui32FlashSize % 1024 ) ? '+' : 0;
am_util_stdio_printf("\tFlash size: %7d (%d KB%s)\n",
sIdDevice.sMcuCtrlDevice.ui32FlashSize,
sIdDevice.sMcuCtrlDevice.ui32FlashSize / 1024,
&ui32StrBuf);
ui32StrBuf = ( sIdDevice.sMcuCtrlDevice.ui32SRAMSize % 1024 ) ? '+' : 0;
am_util_stdio_printf("\tSRAM size: %7d (%d KB%s)\n\n",
sIdDevice.sMcuCtrlDevice.ui32SRAMSize,
sIdDevice.sMcuCtrlDevice.ui32SRAMSize / 1024,
&ui32StrBuf);
//
// Print the compiler version.
//
am_hal_uart_tx_flush(phUART);
am_util_stdio_printf("App Compiler: %s\n", COMPILER_VERSION);
#ifdef AM_PART_APOLLO3
am_util_stdio_printf("HAL Compiler: %s\n", g_ui8HALcompiler);
am_util_stdio_printf("HAL SDK version: %d.%d.%d\n",
g_ui32HALversion.s.Major,
g_ui32HALversion.s.Minor,
g_ui32HALversion.s.Revision);
am_util_stdio_printf("HAL compiled with %s-style registers\n",
g_ui32HALversion.s.bAMREGS ? "AM_REG" : "CMSIS");
am_hal_security_info_t secInfo;
char sINFO[32];
uint32_t ui32Status;
ui32Status = am_hal_security_get_info(&secInfo);
if (ui32Status == AM_HAL_STATUS_SUCCESS)
{
if ( secInfo.bInfo0Valid )
{
am_util_stdio_sprintf(sINFO, "INFO0 valid, ver 0x%X", secInfo.info0Version);
}
else
{
am_util_stdio_sprintf(sINFO, "INFO0 invalid");
}
am_util_stdio_printf("SBL ver: 0x%x - 0x%x, %s\n",
secInfo.sblVersion, secInfo.sblVersionAddInfo, sINFO);
}
else
{
am_util_stdio_printf("am_hal_security_get_info failed 0x%X\n", ui32Status);
}
#endif // AM_PART_APOLLO3
//
// We are done printing.
// Disable the UART and interrupts
//
am_hal_uart_tx_flush(phUART);
CHECK_ERRORS(am_hal_uart_power_control(phUART, AM_HAL_SYSCTRL_DEEPSLEEP, false));
//
// Loop forever while sleeping.
//
while (1)
{
//
// Go to Deep Sleep.
//
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
}
@@ -0,0 +1,401 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := hello_world_uart_cpp
COMPILERNAME := gcc
PROJECT := $(TARGET)_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.cpp
SRC+= startup_gcc.c
SRC+= am_util_delay.c
SRC+= am_util_faultisr.c
SRC+= am_util_id.c
SRC+= am_util_stdio.c
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/examples/hello_world_uart_cpp
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,345 @@
//*****************************************************************************
//
//! @file hello_world_uart.cpp
//!
//! @brief A simple "Hello World" example using the UART peripheral.
//!
//! Purpose: This example prints a "Hello World" message with some device info
//! over UART at 115200 baud. To see the output of this program, run AMFlash,
//! and configure the console for UART. The example sleeps after it is done
//! printing.
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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 v2.2.0-7-g63f7c2ba1 of the AmbiqSuite Development Package.
//
//*****************************************************************************
extern "C" { // extern "C" is required because Release 2.2.0 of the
#include "am_mcu_apollo.h" // AmbiqSuite SDK still has some HAL headers without
} // this CPP guard built in
#include "am_bsp.h"
#include "am_util.h"
//*****************************************************************************
//
// C++ Functionality demonstration
//
//*****************************************************************************
class CPPPrinter {
private:
protected:
public:
uint8_t value;
CPPPrinter( uint8_t _value ) : value(_value) {};
void printValue( void ){
am_util_stdio_printf("I am a CPPPrinter and my value is %d\n\n", value);
}
};
CPPPrinter myCPPPrinter(12);
//*****************************************************************************
//
// UART handle.
//
//*****************************************************************************
void *phUART;
#define CHECK_ERRORS(x) \
if ((x) != AM_HAL_STATUS_SUCCESS) \
{ \
error_handler(x); \
}
volatile uint32_t ui32LastError;
//*****************************************************************************
//
// Catch HAL errors.
//
//*****************************************************************************
void
error_handler(uint32_t ui32ErrorStatus)
{
ui32LastError = ui32ErrorStatus;
while (1);
}
//*****************************************************************************
//
// UART buffers.
//
//*****************************************************************************
uint8_t g_pui8TxBuffer[256];
uint8_t g_pui8RxBuffer[2];
//*****************************************************************************
//
// UART configuration.
//
//*****************************************************************************
am_hal_uart_config_t g_sUartConfig = {0};
//*****************************************************************************
//
// UART0 interrupt handler.
//
//*****************************************************************************
extern "C" void am_uart_isr(void)
{
//
// Service the FIFOs as necessary, and clear the interrupts.
//
uint32_t ui32Status, ui32Idle;
am_hal_uart_interrupt_status_get(phUART, &ui32Status, true);
am_hal_uart_interrupt_clear(phUART, ui32Status);
am_hal_uart_interrupt_service(phUART, ui32Status, &ui32Idle);
}
//*****************************************************************************
//
// UART print string
//
//*****************************************************************************
void
uart_print(char *pcStr)
{
uint32_t ui32StrLen = 0;
uint32_t ui32BytesWritten = 0;
//
// Measure the length of the string.
//
while (pcStr[ui32StrLen] != 0)
{
ui32StrLen++;
}
//
// Print the string via the UART.
//
const am_hal_uart_transfer_t sUartWrite =
{
.ui32Direction = AM_HAL_UART_WRITE,
.pui8Data = (uint8_t *) pcStr,
.ui32NumBytes = ui32StrLen,
.ui32TimeoutMs = 0,
.pui32BytesTransferred = &ui32BytesWritten,
};
CHECK_ERRORS(am_hal_uart_transfer(phUART, &sUartWrite));
if (ui32BytesWritten != ui32StrLen)
{
//
// Couldn't send the whole string!!
//
while(1);
}
}
//*****************************************************************************
//
// Main
//
//*****************************************************************************
extern "C" int main(void)
{
am_util_id_t sIdDevice;
uint32_t ui32StrBuf;
// Initialize Uart Configuration Structure
g_sUartConfig.ui32BaudRate = 115200;
g_sUartConfig.ui32DataBits = AM_HAL_UART_DATA_BITS_8;
g_sUartConfig.ui32Parity = AM_HAL_UART_PARITY_NONE;
g_sUartConfig.ui32StopBits = AM_HAL_UART_ONE_STOP_BIT;
g_sUartConfig.ui32FlowControl = AM_HAL_UART_FLOW_CTRL_NONE;
g_sUartConfig.ui32FifoLevels = (AM_HAL_UART_TX_FIFO_1_2 | AM_HAL_UART_RX_FIFO_1_2);
g_sUartConfig.pui8TxBuffer = g_pui8TxBuffer;
g_sUartConfig.ui32TxBufferSize = sizeof(g_pui8TxBuffer);
g_sUartConfig.pui8RxBuffer = g_pui8RxBuffer;
g_sUartConfig.ui32RxBufferSize = sizeof(g_pui8RxBuffer);
//
// Set the clock frequency.
//
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
//
// Set the default cache configuration
//
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
//
// Configure the board for low power operation.
//
am_bsp_low_power_init();
//
// Initialize the printf interface for UART output.
//
CHECK_ERRORS(am_hal_uart_initialize(0, &phUART));
CHECK_ERRORS(am_hal_uart_power_control(phUART, AM_HAL_SYSCTRL_WAKE, false));
CHECK_ERRORS(am_hal_uart_configure(phUART, &g_sUartConfig));
//
// Enable the UART pins.
//
am_hal_gpio_pinconfig(AM_BSP_GPIO_COM_UART_TX, g_AM_BSP_GPIO_COM_UART_TX);
am_hal_gpio_pinconfig(AM_BSP_GPIO_COM_UART_RX, g_AM_BSP_GPIO_COM_UART_RX);
//
// Enable interrupts.
//
NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + AM_BSP_UART_PRINT_INST));
am_hal_interrupt_master_enable();
//
// Set the main print interface to use the UART print function we defined.
//
am_util_stdio_printf_init(uart_print);
//
// Print the banner.
//
am_util_stdio_terminal_clear();
am_util_stdio_printf("Hello World!\n\n");
//
// Test CPPPrinter
//
myCPPPrinter.printValue();
//
// Print the device info.
//
am_util_id_device(&sIdDevice);
am_util_stdio_printf("Vendor Name: %s\n", sIdDevice.pui8VendorName);
am_util_stdio_printf("Device type: %s\n", sIdDevice.pui8DeviceName);
am_util_stdio_printf("Qualified: %s\n",
sIdDevice.sMcuCtrlDevice.ui32Qualified ?
"Yes" : "No");
am_util_stdio_printf("Device Info:\n"
"\tPart number: 0x%08X\n"
"\tChip ID0: 0x%08X\n"
"\tChip ID1: 0x%08X\n"
"\tRevision: 0x%08X (Rev%c%c)\n",
sIdDevice.sMcuCtrlDevice.ui32ChipPN,
sIdDevice.sMcuCtrlDevice.ui32ChipID0,
sIdDevice.sMcuCtrlDevice.ui32ChipID1,
sIdDevice.sMcuCtrlDevice.ui32ChipRev,
sIdDevice.ui8ChipRevMaj, sIdDevice.ui8ChipRevMin );
//
// If not a multiple of 1024 bytes, append a plus sign to the KB.
//
ui32StrBuf = ( sIdDevice.sMcuCtrlDevice.ui32FlashSize % 1024 ) ? '+' : 0;
am_util_stdio_printf("\tFlash size: %7d (%d KB%s)\n",
sIdDevice.sMcuCtrlDevice.ui32FlashSize,
sIdDevice.sMcuCtrlDevice.ui32FlashSize / 1024,
&ui32StrBuf);
ui32StrBuf = ( sIdDevice.sMcuCtrlDevice.ui32SRAMSize % 1024 ) ? '+' : 0;
am_util_stdio_printf("\tSRAM size: %7d (%d KB%s)\n\n",
sIdDevice.sMcuCtrlDevice.ui32SRAMSize,
sIdDevice.sMcuCtrlDevice.ui32SRAMSize / 1024,
&ui32StrBuf);
//
// Print the compiler version.
//
am_hal_uart_tx_flush(phUART);
am_util_stdio_printf("App Compiler: %s\n", COMPILER_VERSION);
#ifdef AM_PART_APOLLO3
am_util_stdio_printf("HAL Compiler: %s\n", g_ui8HALcompiler);
am_util_stdio_printf("HAL SDK version: %d.%d.%d\n",
g_ui32HALversion.s.Major,
g_ui32HALversion.s.Minor,
g_ui32HALversion.s.Revision);
am_util_stdio_printf("HAL compiled with %s-style registers\n",
g_ui32HALversion.s.bAMREGS ? "AM_REG" : "CMSIS");
am_hal_security_info_t secInfo;
char sINFO[32];
uint32_t ui32Status;
ui32Status = am_hal_security_get_info(&secInfo);
if (ui32Status == AM_HAL_STATUS_SUCCESS)
{
if ( secInfo.bInfo0Valid )
{
am_util_stdio_sprintf(sINFO, "INFO0 valid, ver 0x%X", secInfo.info0Version);
}
else
{
am_util_stdio_sprintf(sINFO, "INFO0 invalid");
}
am_util_stdio_printf("SBL ver: 0x%x - 0x%x, %s\n",
secInfo.sblVersion, secInfo.sblVersionAddInfo, sINFO);
}
else
{
am_util_stdio_printf("am_hal_security_get_info failed 0x%X\n", ui32Status);
}
#endif // AM_PART_APOLLO3
//
// We are done printing.
// Disable the UART and interrupts
//
am_hal_uart_tx_flush(phUART);
CHECK_ERRORS(am_hal_uart_power_control(phUART, AM_HAL_SYSCTRL_DEEPSLEEP, false));
//
// Loop forever while sleeping.
//
while (1)
{
//
// Go to Deep Sleep.
//
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
}
@@ -0,0 +1,404 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := hm01b0_camera_uart
COMPILERNAME := gcc
PROJECT := $(TARGET)_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+= -I$(COMMONPATH)/third_party/hm01b0
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.cpp
SRC+= startup_gcc.c
SRC+= am_util_delay.c
SRC+= am_util_faultisr.c
SRC+= am_util_id.c
SRC+= am_util_stdio.c
SRC+= HM01B0.c
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/examples/hm01b0_camera_uart
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+= $(COMMONPATH)/third_party/hm01b0
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,356 @@
// based on demo from Himax
/*
Copyright (c) 2019 SparkFun Electronics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#include "HM01B0.h"
#include "HM01B0_RAW8_QVGA_8bits_lsb_5fps.h"
#include "platform.h"
//#define DEMO_HM01B0_TEST_MODE_ENABLE
#define DEMO_HM01B0_FRAMEBUFFER_DUMP_ENABLE
//*****************************************************************************
//
// HM01B0 Configuration
//
//*****************************************************************************
static hm01b0_cfg_t s_HM01B0Cfg =
{
// i2c settings
.ui16SlvAddr = HM01B0_DEFAULT_ADDRESS,
.eIOMMode = HM01B0_IOM_MODE,
.ui32IOMModule = HM01B0_IOM_MODULE,
.sIOMCfg =
{
.eInterfaceMode = HM01B0_IOM_MODE,
.ui32ClockFreq = HM01B0_I2C_CLOCK_FREQ,
},
.pIOMHandle = NULL,
.ui8PinSCL = HM01B0_PIN_SCL,
.ui8PinSDA = HM01B0_PIN_SDA,
// MCLK settings
.ui32CTimerModule = HM01B0_MCLK_GENERATOR_MOD,
.ui32CTimerSegment = HM01B0_MCLK_GENERATOR_SEG,
.ui32CTimerOutputPin = HM01B0_PIN_MCLK,
// data interface
.ui8PinD0 = HM01B0_PIN_D0,
.ui8PinD1 = HM01B0_PIN_D1,
.ui8PinD2 = HM01B0_PIN_D2,
.ui8PinD3 = HM01B0_PIN_D3,
.ui8PinD4 = HM01B0_PIN_D4,
.ui8PinD5 = HM01B0_PIN_D5,
.ui8PinD6 = HM01B0_PIN_D6,
.ui8PinD7 = HM01B0_PIN_D7,
.ui8PinVSYNC = HM01B0_PIN_VSYNC,
.ui8PinHSYNC = HM01B0_PIN_HSYNC,
.ui8PinPCLK = HM01B0_PIN_PCLK,
#ifdef HM01B0_PIN_TRIG
.ui8PinTrig = HM01B0_PIN_TRIG,
#endif // HM01B0_PIN_TRIG
#ifdef HM01B0_PIN_INT
.ui8PinInt = HM01B0_PIN_INT,
#endif // HM01B0_PIN_INT
.pfnGpioIsr = NULL,
};
static uint8_t s_ui8FrameBuffer[HM01B0_PIXEL_X_NUM * HM01B0_PIXEL_Y_NUM];
//*****************************************************************************
//
// Forward declarations
//
//*****************************************************************************
void boost_mode_enable(bool bEnable);
void am_gpio_isr(void);
void framebuffer_dump(uint8_t *pui8Buffer, uint32_t ui32BufferLen);
//*****************************************************************************
//
// High Speed UART Configuration
//
//*****************************************************************************
static const am_hal_uart_config_t g_sBspUartConfigHS =
{
//
// Standard UART settings: 115200-8-N-1
//
.ui32BaudRate = 115200,
.ui32DataBits = AM_HAL_UART_DATA_BITS_8,
.ui32Parity = AM_HAL_UART_PARITY_NONE,
.ui32StopBits = AM_HAL_UART_ONE_STOP_BIT,
.ui32FlowControl = AM_HAL_UART_FLOW_CTRL_NONE,
//
// Set TX and RX FIFOs to interrupt at half-full.
//
.ui32FifoLevels = (AM_HAL_UART_TX_FIFO_1_2 |
AM_HAL_UART_RX_FIFO_1_2),
//
// The default interface will just use polling instead of buffers.
//
.pui8TxBuffer = 0,
.ui32TxBufferSize = 0,
.pui8RxBuffer = 0,
.ui32RxBufferSize = 0,
};
//*****************************************************************************
//
// Main function.
//
//*****************************************************************************
int main(void)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint16_t ui16ModelId = 0x0000;
uint8_t ui8Mode = 0xFF;
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
//
// Set the default cache configuration
//
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
//
// Configure the board for low power operation.
//
am_bsp_low_power_init();
#ifdef AM_BSP_GPIO_CAMERA_HM01B0_DVDDEN
//
// Turn on the camera regulator
//
am_hal_gpio_pinconfig(AM_BSP_GPIO_CAMERA_HM01B0_DVDDEN, g_AM_HAL_GPIO_OUTPUT_12);
am_hal_gpio_output_set(AM_BSP_GPIO_CAMERA_HM01B0_DVDDEN);
#endif // AM_BSP_GPIO_CAMERA_HM01B0_DVDDEN
//
// Enable the UART print interface at high speed
//
am_bsp_uart_printf_enable_custom(&g_sBspUartConfigHS);
//
// Clear the terminal and print the banner.
//
am_util_stdio_terminal_clear();
am_util_stdio_printf("HM01B0 Demo\n");
am_util_stdio_printf(" SCL:\tPin %d\n", s_HM01B0Cfg.ui8PinSCL);
am_util_stdio_printf(" SDA:\tPin %d\n", s_HM01B0Cfg.ui8PinSDA);
am_util_stdio_printf(" MCLK:\tPin %d\n", s_HM01B0Cfg.ui32CTimerOutputPin);
am_util_stdio_printf(" VSYNC:\tPin %d\n", s_HM01B0Cfg.ui8PinVSYNC);
am_util_stdio_printf(" HSYNC\tPin %d\n", s_HM01B0Cfg.ui8PinHSYNC);
am_util_stdio_printf(" PCLK:\tPin %d\n", s_HM01B0Cfg.ui8PinPCLK);
am_util_stdio_printf(" D0:\tPin %d\n", s_HM01B0Cfg.ui8PinD0);
am_util_stdio_printf(" D1:\tPin %d\n", s_HM01B0Cfg.ui8PinD1);
am_util_stdio_printf(" D2:\tPin %d\n", s_HM01B0Cfg.ui8PinD2);
am_util_stdio_printf(" D3:\tPin %d\n", s_HM01B0Cfg.ui8PinD3);
am_util_stdio_printf(" D4:\tPin %d\n", s_HM01B0Cfg.ui8PinD4);
am_util_stdio_printf(" D5:\tPin %d\n", s_HM01B0Cfg.ui8PinD5);
am_util_stdio_printf(" D6:\tPin %d\n", s_HM01B0Cfg.ui8PinD6);
am_util_stdio_printf(" D7:\tPin %d\n", s_HM01B0Cfg.ui8PinD7);
//
// Enable interrupts so we can receive messages from the boot host.
//
am_hal_interrupt_master_enable();
boost_mode_enable(true);
hm01b0_power_up(&s_HM01B0Cfg);
// todo: check the delay time to just fit the spec.
am_util_delay_ms(1);
hm01b0_mclk_enable(&s_HM01B0Cfg);
// todo: check the delay time to just fit the spec.
am_util_delay_ms(1);
hm01b0_init_if(&s_HM01B0Cfg);
hm01b0_get_modelid(&s_HM01B0Cfg, &ui16ModelId);
am_util_stdio_printf("HM01B0 Model ID 0x%04X\n", ui16ModelId);
hm01b0_init_system(&s_HM01B0Cfg, (hm_script_t *)sHM01B0InitScript, sizeof(sHM01B0InitScript)/sizeof(hm_script_t));
#ifdef DEMO_HM01B0_TEST_MODE_ENABLE
am_util_stdio_printf("HM01B0 Enable walking 1s test mode\n");
hm01b0_test_walking1s(&s_HM01B0Cfg);
#else
hm01b0_cal_ae(&s_HM01B0Cfg, 10, s_ui8FrameBuffer, sizeof(s_ui8FrameBuffer));
#endif
while(1)
{
hm01b0_ae_cfg_t sAECfg;
hm01b0_get_mode(&s_HM01B0Cfg, &ui8Mode);
am_util_stdio_printf("HM01B0 current mode %d\n", ui8Mode);
ui32Err = hm01b0_get_ae(&s_HM01B0Cfg, &sAECfg);
am_util_stdio_printf("AE convergance(0x%02X) TargetMean 0x%02X, ConvergeInTh 0x%02X, AEMean 0x%02X\n", ui32Err, sAECfg.ui8AETargetMean, sAECfg.ui8ConvergeInTh, sAECfg.ui8AEMean);
hm01b0_cmd_update(&s_HM01B0Cfg);
hm01b0_set_mode(&s_HM01B0Cfg, HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES, 1);
hm01b0_blocking_read_oneframe(&s_HM01B0Cfg, s_ui8FrameBuffer, sizeof(s_ui8FrameBuffer));
#ifdef DEMO_HM01B0_TEST_MODE_ENABLE
hm01b0_test_walking1s_check_data_sanity(s_ui8FrameBuffer, sizeof(s_ui8FrameBuffer), 10);
am_util_delay_ms(3000);
#endif
#ifdef DEMO_HM01B0_FRAMEBUFFER_DUMP_ENABLE
framebuffer_dump(s_ui8FrameBuffer, sizeof(s_ui8FrameBuffer));
#endif
memset(s_ui8FrameBuffer, 0x00, sizeof(s_ui8FrameBuffer));
// give some time for user to stop the external itm logging.
am_util_delay_ms(5000);
}
hm01b0_deinit_if(&s_HM01B0Cfg);
hm01b0_mclk_disable(&s_HM01B0Cfg);
hm01b0_power_down(&s_HM01B0Cfg);
boost_mode_enable(false);
//
// Loop forever.
//
while (1)
{
//
// Go to Deep Sleep.
//
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
}
//*****************************************************************************
//
// Helper Functions
//
//*****************************************************************************
// GPIO ISR
void
am_gpio_isr(void)
{
if (s_HM01B0Cfg.pfnGpioIsr)
s_HM01B0Cfg.pfnGpioIsr();
}
// frame buffer dump
void framebuffer_dump(uint8_t *pui8Buffer, uint32_t ui32BufferLen)
{
am_util_stdio_printf("+++ frame +++");
for (uint32_t ui32Idx = 0; ui32Idx < ui32BufferLen; ui32Idx++)
{
if ((ui32Idx & 0xF) == 0x00)
{
am_util_stdio_printf("\n0x%08X ", ui32Idx);
// this delay is to let itm have time to flush out data.
am_util_delay_ms(1);
}
am_util_stdio_printf("%02X ", *(pui8Buffer + ui32Idx));
}
am_util_stdio_printf("\n--- frame ---\n");
am_util_delay_ms(1);
}
// burst mode enable
void boost_mode_enable(bool bEnable){
am_hal_burst_avail_e eBurstModeAvailable;
am_hal_burst_mode_e eBurstMode;
// Check that the Burst Feature is available.
if (AM_HAL_STATUS_SUCCESS == am_hal_burst_mode_initialize(&eBurstModeAvailable)){
if (AM_HAL_BURST_AVAIL == eBurstModeAvailable){
am_util_stdio_printf("Apollo3 Burst Mode is Available\n");
}
else{
am_util_stdio_printf("Apollo3 Burst Mode is Not Available\n");
while(1){};
}
}
else{
am_util_stdio_printf("Failed to Initialize for Burst Mode operation\n");
}
// Make sure we are in "Normal" mode.
if (AM_HAL_STATUS_SUCCESS == am_hal_burst_mode_disable(&eBurstMode)){
if (AM_HAL_NORMAL_MODE == eBurstMode){
am_util_stdio_printf("Apollo3 operating in Normal Mode (48MHz)\n");
}
}
else{
am_util_stdio_printf("Failed to Disable Burst Mode operation\n");
}
// Put the MCU into "Burst" mode.
if (bEnable)
{
if (AM_HAL_STATUS_SUCCESS == am_hal_burst_mode_enable(&eBurstMode)){
if (AM_HAL_BURST_MODE == eBurstMode){
am_util_stdio_printf("Apollo3 operating in Burst Mode (96MHz)\n");
}
}
else{
am_util_stdio_printf("Failed to Enable Burst Mode operation\n");
}
}
}
@@ -0,0 +1,95 @@
#!/usr/bin/python
import os
import sys
import argparse
import os.path
from array import *
VERSION = 0
SUBVERSION = 1
HIMAX_CMD_OFFSET_OP = 0
HIMAX_CMD_OFFSET_ADDR = 1
HIMAX_CMD_OFFSET_REGADDR = 2
HIMAX_CMD_OFFSET_REGVALUE = 3
dict_DeviceDefaultAddress = {
'HM01B0': '24',
}
def check_file_existence(x):
if not os.path.isfile(x):
# Argparse uses the ArgumentTypeError to give a rejection message like:
# error: argument input: x does not exist
raise argparse.ArgumentTypeError("{0} does not exist".format(x))
return x
def create_outputfile(args):
path = os.path.dirname(os.path.abspath(args.ifile))
basename = os.path.split(os.path.splitext(args.ifile)[0])[-1]
outputfile = os.path.join(path, basename + '.h')
return outputfile
def do_convert(args, ofilename):
ofile = open(ofilename, 'w')
ofile.write("\n")
ofile.write("#include \"%s.h\"\n" % args.model)
ofile.write("\n")
ofile.write("const hm_script_t s%sInitScript[] =\n" % args.model)
ofile.write("{\n")
with open(args.ifile, 'r') as ifile:
for line in ifile:
items = line.split()
ofile.write("// %s\n" % (' '.join(items)))
print("// %s" % (' '.join(items)))
if len(items) > 1:
if items[HIMAX_CMD_OFFSET_OP] == 'W' and items[HIMAX_CMD_OFFSET_ADDR] == dict_DeviceDefaultAddress.get(args.model):
print(" {0x%s, 0x%s,}," % (items[HIMAX_CMD_OFFSET_REGADDR], items[HIMAX_CMD_OFFSET_REGVALUE]))
ofile.write(" {0x%s, 0x%s,},\n" % (items[HIMAX_CMD_OFFSET_REGADDR], items[HIMAX_CMD_OFFSET_REGVALUE]))
ofile.write("};\n")
ofile.close()
def main():
parser = argparse.ArgumentParser(
description = 'This program converts a given Himax Script into a c header file.')
parser.add_argument('-i', '--input',
dest = 'ifile',
required = True,
help = 'input file',
metavar = 'FILE',
type = check_file_existence)
parser.add_argument('-m', '--model',
dest = 'model',
required = True,
help = 'Himax Sensor Model',
choices = ['HM01B0'],
default = 'HM01B0',
)
parser.add_argument('-v', '--version',
help = 'show the program version',
action = 'version',
version = '%(prog)s {ver}'.format(ver = 'v%d.%d' %\
(VERSION, SUBVERSION)))
args = parser.parse_args()
ofilename = create_outputfile(args)
# print('%s' % ofile)
do_convert(args, ofilename)
print "done!"
if __name__ == "__main__":
main()
@@ -0,0 +1,177 @@
#!/usr/bin/python3
import os
import sys
import argparse
import os.path
from array import *
from PIL import Image
import numpy as np
import re
dict_Resolutions = {
'QVGA': (324, 244),
}
# height = 244
# width = 324
VERSION = 0
SUBVERSION = 1
class RawData:
ui8Array = None
def __init__(self):
self.ui8Array = array('B')
def check_file_existence(x):
if not os.path.isfile(x):
# Argparse uses the ArgumentTypeError to give a rejection message like:
# error: argument input: x does not exist
raise argparse.ArgumentTypeError("{0} does not exist".format(x))
return x
def create_bmp(args, framelist):
(width, height) = dict_Resolutions.get(args.resolution, ("Resolution not supported", 0, 0))
for idx, frame in enumerate(framelist):
bitmap = np.zeros((height, width), dtype=np.uint8)
h_idx = height - 1
w_idx = 0
# fill up bitmap array
for pixel in frame.ui8Array:
bitmap[h_idx, w_idx] = pixel
if w_idx == width - 1:
w_idx = 0
h_idx -= 1
else:
w_idx += 1
# h_idx = height - 1
# w_idx = width - 1
# # fill up bitmap array
# for pixel in frame.ui8Array:
# bitmap[h_idx, w_idx] = pixel
# if w_idx == 0:
# w_idx = width - 1
# h_idx -= 1
# else:
# w_idx -= 1
# h_idx = 0
# w_idx = 0
# # fill up bitmap array
# for pixel in frame.ui8Array:
# bitmap[h_idx, w_idx] = pixel
# if w_idx == width - 1:
# w_idx = 0
# h_idx += 1
# else:
# w_idx += 1
path = os.path.dirname(os.path.abspath(args.inputfile))
basename = os.path.split(os.path.splitext(args.inputfile)[0])[-1]
outputfile = os.path.join(path, basename + '_' + str(idx) + '.bmp')
# print (bitmap)
img = Image.fromarray(bitmap, 'L')
img.save(outputfile)
img.show()
print ("%s created" % (basename + '_' + str(idx) + '.bmp'))
def do_convert(args):
(width, height) = dict_Resolutions.get(args.resolution, ("Resolution not supported", 0, 0))
with open(args.inputfile) as f:
h_idx = 0
w_idx = 0
rawdata = None
framestart = False
framestop = False
framelist = list()
# collect all pixel data into an int array
for line in f:
if line == "+++ frame +++\n":
framestart = True
rawdata = RawData()
continue
elif line == '--- frame ---\n':
framestop = True
if framestart == True and framestop == False:
linelist = re.findall(r"[\w']+", line)
if len(linelist) != 17:
# drop this frame
framestart = False
continue
for item in linelist[1 : ]:
rawdata.ui8Array.append(int(item, base=16))
elif framestart == True and framestop == True:
(address, length) = rawdata.ui8Array.buffer_info()
if (length * rawdata.ui8Array.itemsize) != (height * width):
print ("Incorrect total data length %d" % length * rawdata.ui8Array.itemsize)
else:
framelist.append(rawdata)
framestart = False
framestop = False
create_bmp(args, framelist)
def main():
parser = argparse.ArgumentParser(
description = 'This program converts raw data from HM01B0 to a bmp file.')
parser.add_argument('-i', '--input',
dest = 'inputfile',
required = True,
help = 'input file',
metavar = 'FILE',
type = check_file_existence
)
parser.add_argument('-r', '--resolution',
dest = 'resolution',
required = False,
help = 'Resolution',
choices = ['QVGA'],
default = 'QVGA',
)
parser.add_argument('-v', '--version',
help = 'Program version',
action = 'version',
version = '%(prog)s {ver}'.format(ver = 'v%d.%d' %\
(VERSION, SUBVERSION))
)
args = parser.parse_args()
do_convert(args)
print ("done!")
if __name__ == "__main__":
main()
@@ -0,0 +1,439 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := i2c
COMPILERNAME := gcc
PROJECT := i2c_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+= -DAM_UTIL_FAULTISR_PRINT
DEFINES+= -DUNITY_INCLUDE_CONFIG_H
DEFINES+= -D__FPU_PRESENT
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.c
SRC+= startup_gcc.c
SRC+= am_util_delay.c
SRC+= am_util_faultisr.c
SRC+= am_util_stdio.c
SRC+= am_hal_ble_patch.c
SRC+= am_hal_ble.c
SRC+= am_hal_ble_patch_b0.c
SRC+= am_hal_burst.c
SRC+= am_hal_cachectrl.c
SRC+= am_hal_adc.c
SRC+= am_hal_clkgen.c
SRC+= am_hal_cmdq.c
SRC+= am_hal_ctimer.c
SRC+= am_hal_debug.c
SRC+= am_hal_flash.c
SRC+= am_hal_global.c
SRC+= am_hal_gpio.c
SRC+= am_hal_interrupt.c
SRC+= am_hal_iom.c
SRC+= am_hal_ios.c
SRC+= am_hal_itm.c
SRC+= am_hal_mcuctrl.c
SRC+= am_hal_mspi.c
SRC+= am_hal_pdm.c
SRC+= am_hal_pwrctrl.c
SRC+= am_hal_queue.c
SRC+= am_hal_reset.c
SRC+= am_hal_rtc.c
SRC+= am_hal_scard.c
SRC+= am_hal_secure_ota.c
SRC+= am_hal_security.c
SRC+= am_hal_stimer.c
SRC+= am_hal_sysctrl.c
SRC+= am_hal_systick.c
SRC+= am_hal_tpiu.c
SRC+= am_hal_uart.c
SRC+= am_hal_wdt.c
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/examples/i2c
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+= $(SDKPATH)/mcu/apollo3/hal
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
# LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+= $(SDKPATH)/CMSIS/ARM/Lib/ARM/libarm_cortexM4lf_math.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,166 @@
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
// #define ASYNCH // comment out to use blocking methods
#define DEVICE_ADDR (0xEE)
#define DEVICE_ADDR_R (DEVICE_ADDR | 0x01)
#define DEVICE_ADDR_W (DEVICE_ADDR & 0xFE)
#define IOMN (2)
#define I2C_FREQ (AM_HAL_IOM_400KHZ)
void* iom_handle = NULL;
am_hal_iom_config_t iom_cfg = {0};
am_hal_iom_transfer_t xfer = {0};
#define report(s) am_util_stdio_printf("status: 0x%08X (function: %s, file: %s, line: %d)\n", s, __PRETTY_FUNCTION__, __FILE__, __LINE__)
volatile bool xfer_complete = false;
volatile uint32_t txn_stat = 0;
void xfer_complete_callback(void *pCallbackCtxt, uint32_t transactionStatus){
(void)pCallbackCtxt;
xfer_complete = true;
txn_stat = transactionStatus;
}
void init_iom( void ){
uint32_t status = AM_HAL_STATUS_SUCCESS;
iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
iom_cfg.ui32ClockFreq = I2C_FREQ;
iom_cfg.pNBTxnBuf = NULL;
iom_cfg.ui32NBTxnBufLength = 0;
#ifdef ASYNCH
// iom_cfg.pNMTxnBuf = ???
// iom_cfg.ui32NBTxnBufLength = ???
#endif // ASYNCH
status = am_hal_iom_initialize(IOMN, &iom_handle);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_iom_power_ctrl(iom_handle, AM_HAL_SYSCTRL_WAKE, false);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_iom_configure(iom_handle, &iom_cfg);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_iom_enable(iom_handle);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
// config pins
status = am_hal_gpio_pinconfig(AM_BSP_GPIO_IOM2_SCL, g_AM_BSP_GPIO_IOM2_SCL);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_gpio_pinconfig(AM_BSP_GPIO_IOM2_SDA, g_AM_BSP_GPIO_IOM2_SDA);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
}
//*****************************************************************************
//
// Main
//
//*****************************************************************************
int
main(void)
{
uint32_t status = AM_HAL_STATUS_SUCCESS;
//
// Perform the standard initialzation for clocks, cache settings, and
// board-level low-power operation.
//
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
am_bsp_low_power_init();
//
// Initialize the printf interface for UART output
//
am_bsp_uart_printf_enable();
//
// Print the banner.
//
am_util_stdio_terminal_clear();
am_util_stdio_printf("I2C Testing\n\n");
// do i2c stuff
init_iom();
char cmd[2];
cmd[0] = 0x01;
cmd[1] = 0x00;
// i2c.write(addr8bit, cmd, 2);
xfer.uPeerInfo.ui32I2CDevAddr = DEVICE_ADDR_W;
xfer.ui32InstrLen = 0;
xfer.ui32Instr = 0;
xfer.ui32NumBytes = 2;
xfer.eDirection = AM_HAL_IOM_TX;
xfer.pui32TxBuffer = (uint32_t*)cmd;
xfer.pui32RxBuffer = NULL;
xfer.bContinue = false;
xfer.ui8RepeatCount = 0;
xfer.ui8Priority = 1;
xfer.ui32PauseCondition = 0;
xfer.ui32StatusSetClr = 0;
#ifndef AM_HAL_DISABLE_API_VALIDATION
am_util_stdio_printf("API Validation is enabled\n");
#else
am_util_stdio_printf("API Validation DISabled\n");
#endif
#ifdef ASYNCH
status = am_hal_iom_nonblocking_transfer(iom_handle, &xfer, xfer_complete_callback, NULL);
report(status);
while(!xfer_complete){
static uint32_t count = 0;
am_util_stdio_printf("waiting for xfer to complete... %d\n", count++);
if(count > 0x0000FFFF){
am_util_stdio_printf("!TIME OUT!\n");
break;
}
}
#else
status = am_hal_iom_blocking_transfer(iom_handle, &xfer);
report(status);
#endif // ASYNCH
const char* stat_msg = NULL;
switch(status){
case AM_HAL_STATUS_SUCCESS : stat_msg = "success"; break;
case AM_HAL_IOM_ERR_I2C_NAK : stat_msg = "NAK"; break;
case AM_HAL_IOM_ERR_I2C_ARB : stat_msg = "ARB"; break;
default:
stat_msg = "UNKNOWN ERROR";
break;
}
am_util_stdio_printf("I2C write result: %s\n", stat_msg);
// cmd[0] = 0x00;
// i2c.write(addr8bit, cmd, 1);
// i2c.read(addr8bit, cmd, 2);
//
// Loop forever while sleeping.
//
while (1)
{
//
// Go to Deep Sleep.
//
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
}
@@ -0,0 +1,412 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := linker_tests
COMPILERNAME := gcc
PROJECT := $(TARGET)_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+= -I$(COMMONPATH)/examples/linker_tests
INCLUDES+= -I$(COMMONPATH)/examples/linker_tests/test_framework
INCLUDES+= -I$(COMMONPATH)/examples/linker_tests/tests
INCLUDES+= -I$(COMMONPATH)/examples/linker_tests/tests/heap
INCLUDES+= -I$(COMMONPATH)/examples/linker_tests/tests/stack
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.cpp
SRC+= am_util_stdio.c
SRC+= startup_gcc.c
SRC+= system.c
SRC+= test_framework.cpp
SRC+= tests.cpp
SRC+= test_heap.cpp
SRC+= test_stack.cpp
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+= $(COMMONPATH)/examples/linker_tests
VPATH+= $(COMMONPATH)/examples/linker_tests/test_framework
VPATH+= $(COMMONPATH)/examples/linker_tests/tests
VPATH+= $(COMMONPATH)/examples/linker_tests/tests/heap
VPATH+= $(COMMONPATH)/examples/linker_tests/tests/stack
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions -fno-threadsafe-statics # added -fno-threadsafe-statics to allow static local contructors
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,43 @@
/*
Tests / verifies linker
Checks:
- heap allocation
- stack allocation
*/
#include "main.h"
#include "test_framework.h"
#include "tests.h"
// main
int main()
{
// Setup system clocks
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
// Set the default cache configuration
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
// Configure the board for low power operation.
am_bsp_low_power_init();
// Enable the UART print interface.
am_bsp_uart_printf_enable();
// Clear the terminal and print the banner.
am_util_stdio_terminal_clear();
am_util_stdio_printf("Linker Tests\n");
am_util_stdio_printf("=============\n");
am_util_stdio_printf("\n");
// run tests
run_tests(tests);
// Loop forever while sleeping.
while (1){
// Go to Deep Sleep.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
}
@@ -0,0 +1,9 @@
#ifndef _MAIN_H_
#define _MAIN_H_
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#include <stdbool.h>
#endif // _MAIN_H_
@@ -0,0 +1,18 @@
#include "test_framework.h"
void print_test_info( test_info_t* info ){
am_util_stdio_printf("Test Name: %s\n", (info->name != NULL) ? info->name : "N/A");
am_util_stdio_printf("==========\n");
am_util_stdio_printf("metric: %s\n", (info->metric != NULL) ? info->metric : "N/A");
am_util_stdio_printf("value: %d\n", info->value);
am_util_stdio_printf("\n");
}
void run_tests(test_fn* tests){
test_info_t* info;
while(*tests != NULL){
(*tests)(&info);
print_test_info(info);
tests++;
}
am_util_stdio_printf("\n\nAll tests complete\n");
}
@@ -0,0 +1,16 @@
#ifndef _TEST_FRAMEWORK_H_
#define _TEST_FRAMEWORK_H_
#include "main.h"
#include <stdlib.h>
typedef struct _test_info_t {
char* name;
char* metric;
uint32_t value;
} test_info_t;
typedef void (*test_fn)( test_info_t** info );
void print_test_info( test_info_t* info );
void run_tests(test_fn* tests);
#endif // _TEST_FRAMEWORK_H_
@@ -0,0 +1,23 @@
#include "test_heap.h"
//
// test_heap
void test_heap( test_info_t** info ){
static test_info_t test_heap_info;
static char* test_heap_name = "Heap Allocation";
test_heap_info.name = test_heap_name;
*(info) = &test_heap_info;
void* mem = NULL;
size_t len = 0;
// boost_mode_enable(true);
do {
len++;
mem = (void*)malloc( len * sizeof(uint8_t));
free(mem);
} while (mem != NULL);
// boost_mode_enable(false);
test_heap_info.metric = "largest allocated space";
test_heap_info.value = len;
}
@@ -0,0 +1,8 @@
#ifndef _TEST_HEAP_H_
#define _TEST_HEAP_H_
#include "tests.h"
void test_heap( test_info_t** info );
#endif // _TEST_HEAP_H_
@@ -0,0 +1,58 @@
#include "test_stack.h"
#define MEMORY_HEADSPACE 4096
// Globals
uint32_t stack_pointer;
uint32_t min_stack_pointer = 0xFFFFFFFF;
uint32_t free_mem;
uint32_t min_free_mem = 0xFFFFFFFF;
bool go_deeper = true;
uint32_t max_depth = 0;
extern unsigned char _sheap;
uint32_t free_memory( void ){
// Without an implementation of _sbrk (heap management) we are assuming
// that the heap has zero size. If there was heap management then you
// would compute the distance to the program break (the end of the heap)
void* local;
return (((uint32_t)&local) - ((uint32_t)&_sheap));
}
void update_stack_info( void ){
void* local;
stack_pointer = (uint32_t)(&local);
free_mem = free_memory();
min_free_mem = (free_mem < min_free_mem) ? free_mem : min_free_mem;
min_stack_pointer = (stack_pointer < min_stack_pointer) ? stack_pointer : min_stack_pointer;
}
void deep_horizon( void ){
update_stack_info();
if(free_memory() < MEMORY_HEADSPACE){
go_deeper = false;
return;
}
if( go_deeper ){
deep_horizon();
}
max_depth++;
}
//
// test_stack
void test_stack( test_info_t** info ){
static test_info_t test_stack_info;
static char* test_stack_name = "Stack Allocation";
test_stack_info.name = test_stack_name;
*(info) = &test_stack_info;
go_deeper = true;
min_free_mem = 0xFFFFFFFF;
max_depth = 0;
deep_horizon();
test_stack_info.metric = "recursion depth";
test_stack_info.value = max_depth;
}
@@ -0,0 +1,8 @@
#ifndef _TEST_STACK_H_
#define _TEST_STACK_H_
#include "tests.h"
void test_stack( test_info_t** info );
#endif // _TEST_STACK_H_
@@ -0,0 +1,30 @@
#include "tests.h"
test_fn tests[] = {
test_stack,
test_heap,
// test_fail,
// test_pass,
NULL, // NULL terminates the list
};
// test definitions
void test_fail( test_info_t** info ){
static test_info_t test_fail_info;
static char* test_fail_name = "Fail Test";
test_fail_info.name = test_fail_name;
test_fail_info.metric = "success";
test_fail_info.value = 0;
*(info) = &test_fail_info;
}
void test_pass( test_info_t** info ){
static test_info_t test_pass_info;
static char* test_pass_name = "Pass Test";
test_pass_info.name = test_pass_name;
test_pass_info.metric = "success";
test_pass_info.value = 1;
*(info) = &test_pass_info;
}
@@ -0,0 +1,18 @@
// test definitions
#ifndef _TESTS_H_
#define _TESTS_H_
#include "test_framework.h"
// included tests
#include "test_stack.h"
#include "test_heap.h"
// simple tests
void test_fail( test_info_t** info );
void test_pass( test_info_t** info );
// list of tests to run
extern test_fn tests[];
#endif // _TESTS_H_
@@ -0,0 +1,405 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := lis2dh12_accelerometer_uart
COMPILERNAME := gcc
PROJECT := $(TARGET)_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+= -I$(COMMONPATH)/third_party/lis2dh12
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.c
SRC+= startup_gcc.c
SRC+= am_util_delay.c
SRC+= am_util_faultisr.c
SRC+= am_util_id.c
SRC+= am_util_stdio.c
SRC+= lis2dh12_reg.c
SRC+= lis2dh12_platform_apollo3.c
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/examples/lis2dh12_accelerometer_uart
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+= $(COMMONPATH)/third_party/lis2dh12
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,174 @@
/*
Copyright (c) 2019 SparkFun Electronics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#include "lis2dh12_platform_apollo3.h"
//
// Defines
#define LOOP_DELAY_MS 0
//
// Function Declarations
uint32_t initAccel( void );
//
// Global Variables
axis3bit16_t data_raw_acceleration;
axis1bit16_t data_raw_temperature;
float acceleration_mg[3];
float temperature_degC;
lis2dh12_platform_apollo3_if_t dev_if = {
.iomHandle = NULL, // Needs to be initialized later
.addCS = AM_BSP_ACCELEROMETER_I2C_ADDRESS, // Gets the accelerometer I2C address for the board
.useSPI = false, // Using I2C in this example
};
lis2dh12_ctx_t dev_ctx = {
.write_reg = lis2dh12_write_platform_apollo3, // write bytes function
.read_reg = lis2dh12_read_platform_apollo3, // read bytes function
.handle = (void*)&dev_if, // Apollo3-specific interface information
};
int main( void ){
uint32_t stat = AM_HAL_STATUS_SUCCESS;
// Board-agnostic setup
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
// Board-specific setup
am_bsp_low_power_init();
am_bsp_uart_printf_enable();
// Clear UART terminal
am_util_stdio_terminal_clear();
// Initialize accelerometer (uses board-specific code -- see function below)
stat = initAccel();
if( stat != 0 ){
am_util_stdio_printf("Accelerometer initialization failed with code: %d\n", stat);
}
am_util_stdio_printf("Accelerometer initialization successful");
while(1){
lis2dh12_reg_t reg;
// Check if accelerometer is ready with new temperature data
lis2dh12_temp_data_ready_get(&dev_ctx, &reg.byte);
if (reg.byte) {
/* Read temperature data */
lis2dh12_temperature_raw_get(&dev_ctx, data_raw_temperature.u8bit);
/* Convert to celsius */
temperature_degC = lis2dh12_from_lsb_hr_to_celsius(data_raw_temperature.i16bit);
}
// Check if accelerometer is ready with new acceleration data
lis2dh12_xl_data_ready_get(&dev_ctx, &reg.byte);
if (reg.byte){
/* Read acceleration data */
lis2dh12_acceleration_raw_get(&dev_ctx, data_raw_acceleration.u8bit);
/* convert to mg */
acceleration_mg[0] = lis2dh12_from_fs2_hr_to_mg(data_raw_acceleration.i16bit[0]);
acceleration_mg[1] = lis2dh12_from_fs2_hr_to_mg(data_raw_acceleration.i16bit[1]);
acceleration_mg[2] = lis2dh12_from_fs2_hr_to_mg(data_raw_acceleration.i16bit[2]);
// Print results if acceleration data was ready
am_util_stdio_printf("Acc [mg] %04.2f x, %04.2f y, %04.2f z, Temp [deg C] %04.2f,\r\n",
acceleration_mg[0], acceleration_mg[1], acceleration_mg[2], temperature_degC);
}
#ifdef LOOP_DELAY_MS
#if LOOP_DELAY_MS
am_util_delay_ms(LOOP_DELAY_MS);
#endif
#endif
}
// Disable debug
am_bsp_debug_printf_disable();
// Go to Deep Sleep.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
uint32_t initAccel( void ){
uint32_t retVal32 = 0;
static uint8_t whoamI = 0;
am_hal_iom_config_t i2cConfig = {
.eInterfaceMode = AM_HAL_IOM_I2C_MODE,
.ui32ClockFreq = AM_HAL_IOM_100KHZ,
};
// Initialize the IOM.
retVal32 = am_hal_iom_initialize(AM_BSP_ACCELEROMETER_I2C_IOM, &(dev_if.iomHandle)); // set the iomHandle of the device interface
if(retVal32 != AM_HAL_STATUS_SUCCESS){ return retVal32; }
retVal32 = am_hal_iom_power_ctrl((dev_if.iomHandle), AM_HAL_SYSCTRL_WAKE, false);
if(retVal32 != AM_HAL_STATUS_SUCCESS){ return retVal32; }
retVal32 = am_hal_iom_configure((dev_if.iomHandle), &i2cConfig);
if(retVal32 != AM_HAL_STATUS_SUCCESS){ return retVal32; }
//
// Configure the IOM pins.
am_hal_gpio_pinconfig(AM_BSP_ACCELEROMETER_I2C_SDA_PIN, g_AM_BSP_ACCELEROMETER_I2C_SDA);
am_hal_gpio_pinconfig(AM_BSP_ACCELEROMETER_I2C_SCL_PIN, g_AM_BSP_ACCELEROMETER_I2C_SCL);
//
// Enable the IOM.
//
retVal32 = am_hal_iom_enable((dev_if.iomHandle));
if(retVal32 != AM_HAL_STATUS_SUCCESS){ return retVal32; }
//
// Apply accelerometer configuration
lis2dh12_device_id_get(&dev_ctx, &whoamI);
if (whoamI != LIS2DH12_ID){
return AM_HAL_STATUS_FAIL;
}
am_util_stdio_printf("Whoami (should be 0x33): 0x%2x\n", whoamI);
lis2dh12_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
lis2dh12_temperature_meas_set(&dev_ctx, LIS2DH12_TEMP_ENABLE);
lis2dh12_data_rate_set(&dev_ctx, LIS2DH12_ODR_25Hz);
lis2dh12_full_scale_set(&dev_ctx, LIS2DH12_2g);
lis2dh12_temperature_meas_set(&dev_ctx, LIS2DH12_TEMP_ENABLE);
lis2dh12_operating_mode_set(&dev_ctx, LIS2DH12_HR_12bit);
return 0;
}
@@ -0,0 +1,24 @@
Name:
=====
pdm_fft
Description:
============
An example to show basic PDM operation.
Purpose:
========
This example enables the PDM interface to record audio signals from an
external microphone. The required pin connections are:
Printing takes place over the ITM at 1M Baud.
GPIO 10 - PDM DATA
GPIO 11 - PDM CLK
******************************************************************************
@@ -0,0 +1,403 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := pdm_fft
COMPILERNAME := gcc
PROJECT := pdm_fft_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+= -DAM_UTIL_FAULTISR_PRINT
DEFINES+= -DUNITY_INCLUDE_CONFIG_H
DEFINES+= -D__FPU_PRESENT
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.c
SRC+= startup_gcc.c
SRC+= am_util_delay.c
SRC+= am_util_faultisr.c
SRC+= am_util_stdio.c
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/examples/pdm_fft
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+= $(SDKPATH)/CMSIS/ARM/Lib/ARM/libarm_cortexM4lf_math.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,389 @@
//*****************************************************************************
//
//! @file pdm_fft.c
//!
//! @brief An example to show basic PDM operation.
//!
//! Purpose: This example enables the PDM interface to record audio signals from an
//! external microphone. The required pin connections are:
//!
//! Printing takes place over the ITM at 1M Baud.
//!
//! GPIO 10 - PDM DATA
//! GPIO 11 - PDM CLK
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2019, 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 v2.2.0-7-g63f7c2ba1 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#define ARM_MATH_CM4
#include <arm_math.h>
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
//*****************************************************************************
//
// Example parameters.
//
//*****************************************************************************
#define PDM_FFT_SIZE 4096
#define PDM_FFT_BYTES (PDM_FFT_SIZE * 2)
#define PRINT_PDM_DATA 0
#define PRINT_FFT_DATA 0
//*****************************************************************************
//
// Global variables.
//
//*****************************************************************************
volatile bool g_bPDMDataReady = false;
uint32_t g_ui32PDMDataBuffer[PDM_FFT_SIZE];
float g_fPDMTimeDomain[PDM_FFT_SIZE * 2];
float g_fPDMFrequencyDomain[PDM_FFT_SIZE * 2];
float g_fPDMMagnitudes[PDM_FFT_SIZE * 2];
uint32_t g_ui32SampleFreq;
//*****************************************************************************
//
// PDM configuration information.
//
//*****************************************************************************
void *PDMHandle;
am_hal_pdm_config_t g_sPdmConfig =
{
.eClkDivider = AM_HAL_PDM_MCLKDIV_1,
.eLeftGain = AM_HAL_PDM_GAIN_0DB,
.eRightGain = AM_HAL_PDM_GAIN_0DB,
.ui32DecimationRate = 64,
.bHighPassEnable = 0,
.ui32HighPassCutoff = 0xB,
.ePDMClkSpeed = AM_HAL_PDM_CLK_6MHZ,
.bInvertI2SBCLK = 0,
.ePDMClkSource = AM_HAL_PDM_INTERNAL_CLK,
.bPDMSampleDelay = 0,
.bDataPacking = 1,
.ePCMChannels = AM_BSP_PDM_CHANNEL,
.ui32GainChangeDelay = 1,
.bI2SEnable = 0,
.bSoftMute = 0,
.bLRSwap = 0,
};
//*****************************************************************************
//
// PDM initialization.
//
//*****************************************************************************
void
pdm_init(void)
{
//
// Initialize, power-up, and configure the PDM.
//
am_hal_pdm_initialize(0, &PDMHandle);
am_hal_pdm_power_control(PDMHandle, AM_HAL_PDM_POWER_ON, false);
am_hal_pdm_configure(PDMHandle, &g_sPdmConfig);
am_hal_pdm_enable(PDMHandle);
//
// Configure the necessary pins.
//
am_hal_gpio_pinconfig(AM_BSP_PDM_DATA_PIN, g_AM_BSP_PDM_DATA);
am_hal_gpio_pinconfig(AM_BSP_PDM_CLOCK_PIN, g_AM_BSP_PDM_CLOCK);
//
// Configure and enable PDM interrupts (set up to trigger on DMA
// completion).
//
am_hal_pdm_interrupt_enable(PDMHandle, (AM_HAL_PDM_INT_DERR
| AM_HAL_PDM_INT_DCMP
| AM_HAL_PDM_INT_UNDFL
| AM_HAL_PDM_INT_OVF));
NVIC_EnableIRQ(PDM_IRQn);
}
//*****************************************************************************
//
// Print PDM configuration data.
//
//*****************************************************************************
void
pdm_config_print(void)
{
uint32_t ui32PDMClk;
uint32_t ui32MClkDiv;
float fFrequencyUnits;
//
// Read the config structure to figure out what our internal clock is set
// to.
//
switch (g_sPdmConfig.eClkDivider)
{
case AM_HAL_PDM_MCLKDIV_4: ui32MClkDiv = 4; break;
case AM_HAL_PDM_MCLKDIV_3: ui32MClkDiv = 3; break;
case AM_HAL_PDM_MCLKDIV_2: ui32MClkDiv = 2; break;
case AM_HAL_PDM_MCLKDIV_1: ui32MClkDiv = 1; break;
default:
ui32MClkDiv = 0;
}
switch (g_sPdmConfig.ePDMClkSpeed)
{
case AM_HAL_PDM_CLK_12MHZ: ui32PDMClk = 12000000; break;
case AM_HAL_PDM_CLK_6MHZ: ui32PDMClk = 6000000; break;
case AM_HAL_PDM_CLK_3MHZ: ui32PDMClk = 3000000; break;
case AM_HAL_PDM_CLK_1_5MHZ: ui32PDMClk = 1500000; break;
case AM_HAL_PDM_CLK_750KHZ: ui32PDMClk = 750000; break;
case AM_HAL_PDM_CLK_375KHZ: ui32PDMClk = 375000; break;
case AM_HAL_PDM_CLK_187KHZ: ui32PDMClk = 187000; break;
default:
ui32PDMClk = 0;
}
//
// Record the effective sample frequency. We'll need it later to print the
// loudest frequency from the sample.
//
g_ui32SampleFreq = (ui32PDMClk /
(ui32MClkDiv * 2 * g_sPdmConfig.ui32DecimationRate));
fFrequencyUnits = (float) g_ui32SampleFreq / (float) PDM_FFT_SIZE;
am_util_stdio_printf("Settings:\n");
am_util_stdio_printf("PDM Clock (Hz): %12d\n", ui32PDMClk);
am_util_stdio_printf("Decimation Rate: %12d\n", g_sPdmConfig.ui32DecimationRate);
am_util_stdio_printf("Effective Sample Freq.: %12d\n", g_ui32SampleFreq);
am_util_stdio_printf("FFT Length: %12d\n\n", PDM_FFT_SIZE);
am_util_stdio_printf("FFT Resolution: %15.3f Hz\n", fFrequencyUnits);
}
//*****************************************************************************
//
// Start a transaction to get some number of bytes from the PDM interface.
//
//*****************************************************************************
void
pdm_data_get(void)
{
//
// Configure DMA and target address.
//
am_hal_pdm_transfer_t sTransfer;
sTransfer.ui32TargetAddr = (uint32_t ) g_ui32PDMDataBuffer;
sTransfer.ui32TotalCount = PDM_FFT_BYTES;
//
// Start the data transfer.
//
am_hal_pdm_enable(PDMHandle);
am_util_delay_ms(100);
am_hal_pdm_fifo_flush(PDMHandle);
am_hal_pdm_dma_start(PDMHandle, &sTransfer);
}
//*****************************************************************************
//
// PDM interrupt handler.
//
//*****************************************************************************
void
am_pdm0_isr(void)
{
uint32_t ui32Status;
//
// Read the interrupt status.
//
am_hal_pdm_interrupt_status_get(PDMHandle, &ui32Status, true);
am_hal_pdm_interrupt_clear(PDMHandle, ui32Status);
//
// Once our DMA transaction completes, we will disable the PDM and send a
// flag back down to the main routine. Disabling the PDM is only necessary
// because this example only implemented a single buffer for storing FFT
// data. More complex programs could use a system of multiple buffers to
// allow the CPU to run the FFT in one buffer while the DMA pulls PCM data
// into another buffer.
//
if (ui32Status & AM_HAL_PDM_INT_DCMP)
{
am_hal_pdm_disable(PDMHandle);
g_bPDMDataReady = true;
}
}
//*****************************************************************************
//
// Analyze and print frequency data.
//
//*****************************************************************************
void
pcm_fft_print(void)
{
float fMaxValue;
uint32_t ui32MaxIndex;
int16_t *pi16PDMData = (int16_t *) g_ui32PDMDataBuffer;
uint32_t ui32LoudestFrequency;
//
// Convert the PDM samples to floats, and arrange them in the format
// required by the FFT function.
//
for (uint32_t i = 0; i < PDM_FFT_SIZE; i++)
{
if (PRINT_PDM_DATA)
{
am_util_stdio_printf("%d\n", pi16PDMData[i]);
}
g_fPDMTimeDomain[2 * i] = pi16PDMData[i] / 1.0;
g_fPDMTimeDomain[2 * i + 1] = 0.0;
}
if (PRINT_PDM_DATA)
{
am_util_stdio_printf("END\n");
}
//
// Perform the FFT.
//
arm_cfft_radix4_instance_f32 S;
arm_cfft_radix4_init_f32(&S, PDM_FFT_SIZE, 0, 1);
arm_cfft_radix4_f32(&S, g_fPDMTimeDomain);
arm_cmplx_mag_f32(g_fPDMTimeDomain, g_fPDMMagnitudes, PDM_FFT_SIZE);
if (PRINT_FFT_DATA)
{
for (uint32_t i = 0; i < PDM_FFT_SIZE / 2; i++)
{
am_util_stdio_printf("%f\n", g_fPDMMagnitudes[i]);
}
am_util_stdio_printf("END\n");
}
//
// Find the frequency bin with the largest magnitude.
//
arm_max_f32(g_fPDMMagnitudes, PDM_FFT_SIZE / 2, &fMaxValue, &ui32MaxIndex);
ui32LoudestFrequency = (g_ui32SampleFreq * ui32MaxIndex) / PDM_FFT_SIZE;
if (PRINT_FFT_DATA)
{
am_util_stdio_printf("Loudest frequency bin: %d\n", ui32MaxIndex);
}
am_util_stdio_printf("Loudest frequency: %d \n", ui32LoudestFrequency);
}
//*****************************************************************************
//
// Main
//
//*****************************************************************************
int
main(void)
{
//
// Perform the standard initialzation for clocks, cache settings, and
// board-level low-power operation.
//
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
//am_bsp_low_power_init();
//
// Initialize the printf interface for UART output
//
am_bsp_uart_printf_enable();
//
// Print the banner.
//
am_util_stdio_terminal_clear();
am_util_stdio_printf("PDM FFT example.\n\n");
//
// Turn on the PDM, set it up for our chosen recording settings, and start
// the first DMA transaction.
//
pdm_init();
pdm_config_print();
am_hal_pdm_fifo_flush(PDMHandle);
pdm_data_get();
//
// Loop forever while sleeping.
//
while (1)
{
am_hal_interrupt_master_disable();
if (g_bPDMDataReady)
{
g_bPDMDataReady = false;
pcm_fft_print();
while (PRINT_PDM_DATA || PRINT_FFT_DATA);
//
// Start converting the next set of PCM samples.
//
pdm_data_get();
}
//
// Go to Deep Sleep.
//
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
am_hal_interrupt_master_enable();
}
}
@@ -0,0 +1,439 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := spi
COMPILERNAME := gcc
PROJECT := spi_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+= -DAM_UTIL_FAULTISR_PRINT
DEFINES+= -DUNITY_INCLUDE_CONFIG_H
DEFINES+= -D__FPU_PRESENT
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.c
SRC+= startup_gcc.c
SRC+= am_util_delay.c
SRC+= am_util_faultisr.c
SRC+= am_util_stdio.c
SRC+= am_hal_ble_patch.c
SRC+= am_hal_ble.c
SRC+= am_hal_ble_patch_b0.c
SRC+= am_hal_burst.c
SRC+= am_hal_cachectrl.c
SRC+= am_hal_adc.c
SRC+= am_hal_clkgen.c
SRC+= am_hal_cmdq.c
SRC+= am_hal_ctimer.c
SRC+= am_hal_debug.c
SRC+= am_hal_flash.c
SRC+= am_hal_global.c
SRC+= am_hal_gpio.c
SRC+= am_hal_interrupt.c
SRC+= am_hal_iom.c
SRC+= am_hal_ios.c
SRC+= am_hal_itm.c
SRC+= am_hal_mcuctrl.c
SRC+= am_hal_mspi.c
SRC+= am_hal_pdm.c
SRC+= am_hal_pwrctrl.c
SRC+= am_hal_queue.c
SRC+= am_hal_reset.c
SRC+= am_hal_rtc.c
SRC+= am_hal_scard.c
SRC+= am_hal_secure_ota.c
SRC+= am_hal_security.c
SRC+= am_hal_stimer.c
SRC+= am_hal_sysctrl.c
SRC+= am_hal_systick.c
SRC+= am_hal_tpiu.c
SRC+= am_hal_uart.c
SRC+= am_hal_wdt.c
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/examples/spi
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+= $(SDKPATH)/mcu/apollo3/hal
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+= $(SDKPATH)/CMSIS/ARM/Lib/ARM/libarm_cortexM4lf_math.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP $(CSTD) -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,144 @@
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
// #define ASYNCH // comment out to use blocking methods
#define IOMN (2)
#define SPI_MODE (3)
#define SPI_FREQ (AM_HAL_IOM_4MHZ)
void* iom_handle = NULL;
am_hal_iom_config_t iom_cfg = {0};
am_hal_iom_transfer_t xfer = {0};
#define CS_PIN (16)
#define report(s) am_util_stdio_printf("status: 0x%08X (function: %s, file: %s, line: %d)\n", s, __PRETTY_FUNCTION__, __FILE__, __LINE__)
volatile bool xfer_complete = false;
volatile uint32_t txn_stat = 0;
void xfer_complete_callback(void *pCallbackCtxt, uint32_t transactionStatus){
(void)pCallbackCtxt;
xfer_complete = true;
txn_stat = transactionStatus;
}
void init_iom( void ){
uint32_t status = AM_HAL_STATUS_SUCCESS;
iom_cfg.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
iom_cfg.ui32ClockFreq = SPI_FREQ;
iom_cfg.eSpiMode = SPI_MODE;
iom_cfg.pNBTxnBuf = NULL;
iom_cfg.ui32NBTxnBufLength = 0;
status = am_hal_iom_initialize(IOMN, &iom_handle);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_iom_power_ctrl(iom_handle, AM_HAL_SYSCTRL_WAKE, false);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_iom_configure(iom_handle, &iom_cfg);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_iom_enable(iom_handle);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
// config pins
status = am_hal_gpio_pinconfig(AM_BSP_GPIO_IOM2_MISO, g_AM_BSP_GPIO_IOM2_MISO);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_gpio_pinconfig(AM_BSP_GPIO_IOM2_MOSI, g_AM_BSP_GPIO_IOM2_MOSI);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }
status = am_hal_gpio_pinconfig(AM_BSP_GPIO_IOM2_SCK, g_AM_BSP_GPIO_IOM2_SCK);
if(status != AM_HAL_STATUS_SUCCESS){ report(status); }\
}
//*****************************************************************************
//
// Main
//
//*****************************************************************************
int
main(void)
{
uint32_t status = AM_HAL_STATUS_SUCCESS;
//
// Perform the standard initialzation for clocks, cache settings, and
// board-level low-power operation.
//
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
am_bsp_low_power_init();
//
// Initialize the printf interface for UART output
//
am_bsp_uart_printf_enable();
//
// Print the banner.
//
am_util_stdio_terminal_clear();
am_util_stdio_printf("PDM FFT example.\n\n");
// do spi stuff
init_iom();
char cmd[2];
cmd[0] = 0xEC;
cmd[1] = 0xC3;
xfer.uPeerInfo.ui32SpiChipSelect = 0;
xfer.ui32InstrLen = 0;
xfer.ui32Instr = 0;
xfer.ui32NumBytes = 1;
xfer.eDirection = AM_HAL_IOM_TX;
xfer.pui32TxBuffer = (uint32_t*)cmd;
xfer.pui32RxBuffer = NULL;
xfer.bContinue = false;
xfer.ui8RepeatCount = 0;
xfer.ui8Priority = 1;
xfer.ui32PauseCondition = 0;
xfer.ui32StatusSetClr = 0;
#ifdef ASYNCH
status = am_hal_iom_nonblocking_transfer(iom_handle, &xfer, xfer_complete_callback, NULL);
report(status);
#else
status = am_hal_iom_blocking_transfer(iom_handle, &xfer);
report(status);
#endif
char rx_buf[10];
xfer.eDirection = AM_HAL_IOM_FULLDUPLEX;
xfer.pui32TxBuffer = (uint32_t*)cmd;
xfer.pui32RxBuffer = (uint32_t*)rx_buf;
#ifdef ASYNCH
status = am_hal_iom_nonblocking_transfer(iom_handle, &xfer, xfer_complete_callback, NULL);
report(status);
#else
status = am_hal_iom_spi_blocking_fullduplex(iom_handle, &xfer);
report(status);
#endif
while (1)
{
#ifdef ASYNCH
status = am_hal_iom_nonblocking_transfer(iom_handle, &xfer, xfer_complete_callback, NULL);
#else
status = am_hal_iom_spi_blocking_fullduplex(iom_handle, &xfer);
#endif
if(status != AM_HAL_STATUS_SUCCESS){
report(status);
}
}
}
@@ -0,0 +1,417 @@
#******************************************************************************
#
# Makefile - Rules for building the libraries, examples and docs.
#
# Copyright (c) 2019, 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.1.0 of the AmbiqSuite Development Package.
#
#******************************************************************************
#******************************************************************************
#
# This is an example makefile for SparkFun Apollo3 boards as used in the
# AmbiqSuite SDK.
#
# Recommended usage
# make
# make bootload_svl (uses the SparkFun Variable Loader to upload code)
# make bootload_asb (uses the Ambiq Secure Bootlaoder to upload code)
# make clean
#
# Filepaths
# You can relocate this makefile easily by providing the path to the root of
# the AmbiqSuite SDK. If that path is not specified then this file will
# assume that it is located in
# <AmbiqSDKRoot>/boards/<your_board>/examples/<your_example>/gcc
# and use relative paths
#
# User Configuration
# You must also specify which COM_PORT to use if you want to use the
# 'bootlaoder' targets.
# Windows example: COM_PORT=COM4
# *nix example: COM_PORT=/dev/usbserialxxxx
#
# Python vs. Executable
# For simplicity the upload tools are called as Python scripts by default.
# Make sure PYTHON is set to the appropriate command to run Python3 from the
# command line.
#
#******************************************************************************
#******************************************************************************
#
# User Options
#
#******************************************************************************
# You can override these values on the command line e.g. make bootload COM_PORT=/dev/cu***
# COM_PORT is the serial port to use for uploading. For example COM#### on Windows or /dev/cu.usbserial-#### on *nix
COM_PORT ?=
# ASB_UPLOAD_BAUD is the baud rate setting of the Ambiq Secue Bootloader (ASB) as it is configured on the Apollo3. Defautls to 115200 if unset
ASB_UPLOAD_BAUD ?=
# SVL_UPLOAD_BAUD is the baud rate setting of the SparkFun Variable Loader (SVL). Defaults to 921600 if unset
SVL_UPLOAD_BAUD ?=
# PYTHON3 should evaluate to a call to the Python3 executable on your machine
PYTHON3 ?=
# *Optionally* specify absolute paths to the SDK and the BSP
# You can do this on the command line - e.g. make bootload SDKPATH=~/$AMBIQ_SDK_ROOT_PATH
# Make sure to use / instead of \ when on Windows
SDKPATH ?=# Set as the path to the SDK root if not located at ../../../../..
COMMONPATH ?=# Set as the path to the BSP common folder if not located at ../../../../common
BOARDPATH ?=# Set as the path to the board if not located at ../../..
PROJECTPATH ?=# Set as the path to the project if not located at ..
BOARD ?=# If using a SparkFun board you can simply provide the name e.g. redboard_artemis_atp
### Project Settings
TARGET := startup_tests
COMPILERNAME := gcc
PROJECT := $(TARGET)_gcc
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
ifeq ($(BOARD),)
$(warning warning: no BOARD specified, will fall back to BOARDPATH for arbitrary bsp locations)
else
BOARDPATH=../../../../$(BOARD)
$(warning Using BOARD=$(BOARD) at $(BOARDPATH))
endif
ifeq ($(COM_PORT),)
COM_PORT=COM4
$(warning warning: you have not defined COM_PORT. Assuming it is COM4)
endif
ifeq ($(PYTHON3),)
PYTHON3=python3
$(warning warning: you have not defined PYTHON3. assuming it is accessible by 'python3')
endif
ifeq ($(ASB_UPLOAD_BAUD),)
ASB_UPLOAD_BAUD=115200
$(warning defaulting to 115200 baud for ASB)
endif
ifeq ($(SVL_UPLOAD_BAUD),)
SVL_UPLOAD_BAUD=921600
$(warning defaulting to 921600 baud for SVL)
endif
ifeq ($(SDKPATH),)
SDKPATH =../../../../..
$(warning warning: you have not defined SDKPATH so will continue assuming that the SDK root is at $(SDKPATH))
else
# When the SDKPATH is given export it
export SDKPATH
endif
ifeq ($(COMMONPATH),)
COMMONPATH =../../../../common
$(warning warning: you have not defined COMMONPATH so will continue assuming that the COMMON root is at $(COMMONPATH))
else
# When the COMMONPATH is given export it
export COMMONPATH
endif
ifeq ($(BOARDPATH),)
$(error Error: BOARDPATH must be provided)
else
# Ensure that boardpath does not include a trailing '/'
ifeq ($(notdir $(BOARDPATH)),)
override BOARDPATH:=$(patsubst %/, %,$(BOARDPATH))
$(warning BOARDPATH had a trivial 'notdir' so we tried changing it to: $(BOARDPATH))
endif
BOARD=$(notdir $(BOARDPATH))
# When the BOARDPATH is given export it
export BOARDPATH
endif
ifeq ($(PROJECTPATH),)
PROJECTPATH =..
$(warning warning: you have not defined PROJECTPATH so will continue assuming that the PROJECT root is at $(PROJECTPATH))
else
# When the PROJECTPATH is given export it
export PROJECTPATH
endif
CONFIG := $(PROJECTPATH)/gcc/$(BOARD)/bin
$(warning CONFIG=$(CONFIG))
#******************************************************************************
#
# User Defines / Includes / Sources / Libraries
#
#******************************************************************************
# Global Defines
DEFINES= -DPART_$(PART)
DEFINES+= -DAM_CUSTOM_BDADDR
DEFINES+= -DAM_PACKAGE_BGA
DEFINES+= -DWSF_TRACE_ENABLED
DEFINES+= -DAM_DEBUG_PRINTF
DEFINES+= -DAM_PART_APOLLO3
DEFINES+=
# Includes (Add paths to where example header files are located)
INCLUDES=
INCLUDES+= -I$(PROJECTPATH)/src
INCLUDES+= -I$(BOARDPATH)/bsp
INCLUDES+= -I$(SDKPATH)
INCLUDES+= -I$(SDKPATH)/utils
INCLUDES+= -I$(SDKPATH)/devices
INCLUDES+= -I$(SDKPATH)/mcu/apollo3
INCLUDES+= -I$(SDKPATH)/CMSIS/AmbiqMicro/Include
INCLUDES+= -I$(SDKPATH)/CMSIS/ARM/Include
INCLUDES+= -I$(COMMONPATH)/examples/startup_tests
INCLUDES+= -I$(COMMONPATH)/examples/startup_tests/test_framework
INCLUDES+= -I$(COMMONPATH)/examples/startup_tests/tests
INCLUDES+= -I$(COMMONPATH)/examples/startup_tests/tests/data
INCLUDES+= -I$(COMMONPATH)/examples/startup_tests/tests/bss
INCLUDES+= -I$(COMMONPATH)/examples/startup_tests/tests/constructors
INCLUDES+= -I$(COMMONPATH)/examples/startup_tests/tests/fn_init
INCLUDES+=
# Compilation Units (Add all the .c files you need to compile)
SRC=
SRC+= main.cpp
SRC+= am_util_stdio.c
SRC+= startup_gcc.c
SRC+= test_framework.cpp
SRC+= tests.cpp
SRC+= test_data.cpp
SRC+= test_bss.cpp
SRC+= test_constructors.cpp
SRC+= test_fn_init.cpp
SRC+=
# VPATH (Add paths to where your source files are located)
VPATH=
VPATH+= $(PROJECTPATH)/src
VPATH+= $(SDKPATH)/utils
VPATH+= $(COMMONPATH)/tools_sfe/templates
VPATH+= $(COMMONPATH)/examples/startup_tests
VPATH+= $(COMMONPATH)/examples/startup_tests/test_framework
VPATH+= $(COMMONPATH)/examples/startup_tests/tests
VPATH+= $(COMMONPATH)/examples/startup_tests/tests/data
VPATH+= $(COMMONPATH)/examples/startup_tests/tests/bss
VPATH+= $(COMMONPATH)/examples/startup_tests/tests/constructors
VPATH+= $(COMMONPATH)/examples/startup_tests/tests/fn_init
VPATH+=
# LIBS (Precompiled libraries to include in the linker step)
LIBS=
LIBS+= $(BOARDPATH)/bsp/gcc/bin/libam_bsp.a
LIBS+= $(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a
LIBS+=
#******************************************************************************
#
# Warning Messages
#
#******************************************************************************
### Bootloader Tools
ASB_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/asb/asb.py
SVL_UPLOADER=$(PYTHON3) $(COMMONPATH)/tools_sfe/svl/svl.py
SHELL:=/bin/bash
#### Setup ####
TOOLCHAIN ?= arm-none-eabi
PART = apollo3
CPU = cortex-m4
FPU = fpv4-sp-d16
# Default to FPU hardware calling convention. However, some customers and/or
# applications may need the software calling convention.
#FABI = softfp
FABI = hard
STARTUP_FILE := ./startup_$(COMPILERNAME).c
#### Required Executables ####
CC = $(TOOLCHAIN)-gcc
GCC = $(TOOLCHAIN)-gcc
CPP = $(TOOLCHAIN)-cpp
CXX = $(TOOLCHAIN)-g++
LD = $(TOOLCHAIN)-ld
CP = $(TOOLCHAIN)-objcopy
OD = $(TOOLCHAIN)-objdump
RD = $(TOOLCHAIN)-readelf
AR = $(TOOLCHAIN)-ar
SIZE = $(TOOLCHAIN)-size
RM = $(shell which rm 2>/dev/null)
EXECUTABLES = CC LD CP OD AR RD SIZE GCC CXX
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $($(exec)) 2>/dev/null),,\
$(info $(exec) not found on PATH ($($(exec))).)$(exec)))
$(if $(strip $(value K)),$(info Required Program(s) $(strip $(value K)) not found))
ifneq ($(strip $(value K)),)
all clean:
$(info Tools $(TOOLCHAIN)-$(COMPILERNAME) not installed.)
$(RM) -rf bin
else
#******************************************************************************
#
# Machinery
#
#******************************************************************************
XSRC = $(filter %.cpp,$(SRC))
ZSRC = $(filter %.cc,$(SRC))
CSRC = $(filter %.c,$(SRC))
ASRC = $(filter %.s,$(SRC))
OBJS = $(XSRC:%.cpp=$(CONFIG)/%.o)
OBJS+= $(ZSRC:%.cc=$(CONFIG)/%.o)
OBJS+= $(CSRC:%.c=$(CONFIG)/%.o)
OBJS+= $(ASRC:%.s=$(CONFIG)/%.o)
DEPS = $(XSRC:%.cpp=$(CONFIG)/%.d)
DEPS+= $(ZSRC:%.cc=$(CONFIG)/%.d)
DEPS+= $(CSRC:%.c=$(CONFIG)/%.d)
DEPS+= $(ASRC:%.s=$(CONFIG)/%.d)
CSTD = -std=c99
CFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
CFLAGS+= -ffunction-sections -fdata-sections
CFLAGS+= -MMD -MP -Wall -g
CFLAGS+= -O0
CFLAGS+= $(DEFINES)
CFLAGS+= $(INCLUDES)
CFLAGS+=
XSTD = -std=gnu++11
XFLAGS = $(CFLAGS)
XFLAGS+= -fno-exceptions -fno-threadsafe-statics # added -fno-threadsafe-statics to allow static local contructors
LFLAGS = -mthumb -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FABI)
LFLAGS+= -nostartfiles -static
LFLAGS+= -Wl,--gc-sections,--entry,Reset_Handler,-Map,$(CONFIG)/$(TARGET).map
LFLAGS+= -Wl,--start-group -lm -lc -lgcc $(LIBS) -Wl,--end-group
LFLAGS+=
# Additional user specified CFLAGS
CFLAGS+=$(EXTRA_CFLAGS)
CPFLAGS = -Obinary
ODFLAGS = -S
#******************************************************************************
#
# Targets / Rules
#
#******************************************************************************
all: asb
asb: directories $(CONFIG)/$(TARGET)_asb.bin
svl: directories $(CONFIG)/$(TARGET)_svl.bin
directories:
@mkdir -p $(CONFIG)
$(CONFIG)/%.o: %.cpp $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.cc $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CXX) -c $(XSTD) $(XFLAGS) $< -o $@
$(CONFIG)/%.o: %.c $(CONFIG)/%.d
@echo " Compiling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/%.o: %.s $(CONFIG)/%.d
@echo " Assembling $(COMPILERNAME) $<" ;\
$(CC) -c $(CFLAGS) $< -o $@
$(CONFIG)/$(TARGET)_asb.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_linker.ld
$(CONFIG)/$(TARGET)_asb.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_svl.axf: LINKER_FILE = $(COMMONPATH)/tools_sfe/templates/asb_svl_linker.ld
$(CONFIG)/$(TARGET)_svl.axf: $(OBJS) $(LIBS)
@echo " Linking $(COMPILERNAME) $@ with script $(LINKER_FILE)";\
$(CC) -Wl,-T,$(LINKER_FILE) -o $@ $(OBJS) $(LFLAGS)
$(CONFIG)/$(TARGET)_%.bin: $(CONFIG)/$(TARGET)_%.axf
@echo " Copying $(COMPILERNAME) $@..." ;\
$(CP) $(CPFLAGS) $< $@ ;\
$(OD) $(ODFLAGS) $< > $(CONFIG)/$(TARGET).lst
bootload_asb: directories $(CONFIG)/$(TARGET)_asb.bin
$(ASB_UPLOADER) --bin $(CONFIG)/$(TARGET)_asb.bin --load-address-blob 0x20000 --magic-num 0xCB -o $(CONFIG)/$(TARGET) --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $(ASB_UPLOAD_BAUD) -port $(COM_PORT) -r 2 -v
bootload_svl: directories $(CONFIG)/$(TARGET)_svl.bin
$(SVL_UPLOADER) $(COM_PORT) -f $(CONFIG)/$(TARGET)_svl.bin -b $(SVL_UPLOAD_BAUD) -v
bootload: bootload_svl
clean:
@echo "Cleaning..." ;\
$(RM) -f $(OBJS) $(DEPS) \
$(CONFIG)/$(TARGET).bin $(CONFIG)/$(TARGET).axf \
$(CONFIG)/$(TARGET).lst $(CONFIG)/$(TARGET).map \
$(CONFIG)/$(TARGET)_svl.bin $(CONFIG)/$(TARGET)_svl.axf \
$(CONFIG)/$(TARGET)_svl.lst $(CONFIG)/$(TARGET)_svl.map \
$(CONFIG)/$(TARGET)_asb.bin $(CONFIG)/$(TARGET)_asb.axf \
$(CONFIG)/$(TARGET)_asb.lst $(CONFIG)/$(TARGET)_asb.map
$(CONFIG)/%.d: ;
$(SDKPATH)/mcu/apollo3/hal/gcc/bin/libam_hal.a:
$(MAKE) -C $(SDKPATH)/mcu/apollo3/hal/gcc
$(SDKPATH)/third_party/uecc/gcc/bin/lib_uecc.a:
$(MAKE) -C $(SDKPATH)/third_party/uecc
$(BOARDPATH)/bsp/gcc/bin/libam_bsp.a:
$(MAKE) -C $(BOARDPATH)/bsp/gcc
# Automatically include any generated dependencies
-include $(DEPS)
endif
.PHONY: all clean directories bootload bootload_asb bootload_svl
@@ -0,0 +1,44 @@
/*
Tests / verifies startup
Checks:
- data segment copy
- bss segment zero-fill
- C++ global static constructor initialization
*/
#include "main.h"
#include "test_framework.h"
#include "tests.h"
// main
int main()
{
// Setup system clocks
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
// Set the default cache configuration
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();
// Configure the board for low power operation.
am_bsp_low_power_init();
// Enable the UART print interface.
am_bsp_uart_printf_enable();
// Clear the terminal and print the banner.
am_util_stdio_terminal_clear();
am_util_stdio_printf("Startup Tests\n");
am_util_stdio_printf("=============\n");
am_util_stdio_printf("\n");
// run tests
run_tests(tests);
// Loop forever while sleeping.
while (1){
// Go to Deep Sleep.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
}
@@ -0,0 +1,9 @@
#ifndef _MAIN_H_
#define _MAIN_H_
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#include <stdbool.h>
#endif // _MAIN_H_
@@ -0,0 +1,17 @@
#include "test_framework.h"
void print_test_info( test_info_t* info ){
am_util_stdio_printf("Test Name: %s\n", (info->name != NULL) ? info->name : "N/A");
am_util_stdio_printf("==========\n");
am_util_stdio_printf("status: %s\n", (info->passed) ? "passed" : "failed" );
am_util_stdio_printf("\n");
}
void run_tests(test_fn* tests){
test_info_t* info;
while(*tests != NULL){
(*tests)(&info);
print_test_info(info);
tests++;
}
am_util_stdio_printf("\n\nAll tests complete\n");
}
@@ -0,0 +1,15 @@
#ifndef _TEST_FRAMEWORK_H_
#define _TEST_FRAMEWORK_H_
#include "main.h"
#include <stdlib.h>
typedef struct _test_info_t {
char* name;
bool passed;
} test_info_t;
typedef void (*test_fn)( test_info_t** info );
void print_test_info( test_info_t* info );
void run_tests(test_fn* tests);
#endif // _TEST_FRAMEWORK_H_
@@ -0,0 +1,21 @@
#include "test_bss.h"
#define BYTES_TO_FILL 64
char bss_1[BYTES_TO_FILL];
char bss_2[BYTES_TO_FILL] = {0};
//
// test_bss
void test_bss( test_info_t** info ){
static test_info_t test_bss_info;
static char* test_bss_name = "BSS Zereo Fill";
test_bss_info.name = test_bss_name;
test_bss_info.passed = true;
*(info) = &test_bss_info;
for(size_t ix = 0; ix < BYTES_TO_FILL; ix++){
if(bss_1[ix] != 0){ test_bss_info.passed = false; }
if(bss_2[ix] != 0){ test_bss_info.passed = false; }
}
}
@@ -0,0 +1,8 @@
#ifndef _TEST_BSS_H_
#define _TEST_BSS_H_
#include "tests.h"
void test_bss( test_info_t** info );
#endif // _TEST_BSS_H_
@@ -0,0 +1,41 @@
#include "test_constructors.h"
#define STATE1 0x00
#define STATE2 0x01
#define STATE3 0xDD
#define STATE4 0xCC
/* A very simple class to test constructor execution */
class LEDSTATE {
private:
protected:
public:
uint8_t state; // Trivial initialization is 0
LEDSTATE(uint8_t init);
};
LEDSTATE::LEDSTATE(uint8_t init){
state=init;
}
// This object should be initialized with a non-zero state
LEDSTATE state1(STATE1);
LEDSTATE state2(STATE2);
LEDSTATE state3(STATE3);
//
// test_constructors
void test_constructors( test_info_t** info ){
static LEDSTATE state4(STATE4);
static test_info_t test_constructors_info;
static char* test_constructors_name = "Global / Static Constructors";
test_constructors_info.name = test_constructors_name;
test_constructors_info.passed = true;
*(info) = &test_constructors_info;
if(state1.state != STATE1){ test_constructors_info.passed = false; }
if(state2.state != STATE2){ test_constructors_info.passed = false; }
if(state3.state != STATE3){ test_constructors_info.passed = false; }
if(state4.state != STATE4){ test_constructors_info.passed = false; }
}
@@ -0,0 +1,8 @@
#ifndef _TEST_CONSTRUCTORS_H_
#define _TEST_CONSTRUCTORS_H_
#include "tests.h"
void test_constructors( test_info_t** info );
#endif // _TEST_CONSTRUCTORS_H_
@@ -0,0 +1,99 @@
#include "test_data.h"
#define BYTES_TO_COPY 8
// Automatially add some variables that won't be optimized
// away to fill up the number of requested bytes
#ifdef BYTES_TO_COPY
#if BYTES_TO_COPY > 0
#define VAR11 0xDE
#endif
#if BYTES_TO_COPY > 1
#define VAR12 0xAD
#endif
#if BYTES_TO_COPY > 2
#define VAR13 0xBE
#endif
#if BYTES_TO_COPY > 3
#define VAR14 0xEF
#endif
#if BYTES_TO_COPY > 4
#define VAR21 0xC0
#endif
#if BYTES_TO_COPY > 5
#define VAR22 0xFE
#endif
#if BYTES_TO_COPY > 6
#define VAR23 0xE6
#endif
#if BYTES_TO_COPY > 7
#define VAR24 0x0D
#endif
#endif // BYTES_TO_COPY
#ifdef BYTES_TO_COPY
static volatile char data[] = {
#if BYTES_TO_COPY > 0
VAR11,
#endif
#if BYTES_TO_COPY > 1
VAR12,
#endif
#if BYTES_TO_COPY > 2
VAR13,
#endif
#if BYTES_TO_COPY > 3
VAR14,
#endif
#if BYTES_TO_COPY > 4
VAR21,
#endif
#if BYTES_TO_COPY > 5
VAR22,
#endif
#if BYTES_TO_COPY > 6
VAR23,
#endif
#if BYTES_TO_COPY > 7
VAR24,
#endif
};
#endif // BYTES_TO_COPY
//
// test_data
void test_data( test_info_t** info ){
static test_info_t test_data_info;
static char* test_data_name = "Data Segment Copy";
test_data_info.name = test_data_name;
test_data_info.passed = true;
*(info) = &test_data_info;
// Verify that all bytes were copied into RAM correctly
#ifdef BYTES_TO_COPY
#if BYTES_TO_COPY > 0
if( data[0] != VAR11 ){ test_data_info.passed = false; }
#endif
#if BYTES_TO_COPY > 1
if( data[1] != VAR12 ){ test_data_info.passed = false; }
#endif
#if BYTES_TO_COPY > 2
if( data[2] != VAR13 ){ test_data_info.passed = false; }
#endif
#if BYTES_TO_COPY > 3
if( data[3] != VAR14 ){ test_data_info.passed = false; }
#endif
#if BYTES_TO_COPY > 4
if( data[4] != VAR21 ){ test_data_info.passed = false; }
#endif
#if BYTES_TO_COPY > 5
if( data[5] != VAR22 ){ test_data_info.passed = false; }
#endif
#if BYTES_TO_COPY > 6
if( data[6] != VAR23 ){ test_data_info.passed = false; }
#endif
#if BYTES_TO_COPY > 7
if( data[7] != VAR24 ){ test_data_info.passed = false; }
#endif
#endif // BYTES_TO_COPY
}
@@ -0,0 +1,8 @@
#ifndef _TEST_DATA_H_
#define _TEST_DATA_H_
#include "tests.h"
void test_data( test_info_t** info );
#endif // _TEST_DATA_H_
@@ -0,0 +1,21 @@
#include "test_fn_init.h"
#define VAL 0xFA
char init_fn( void ){
return VAL;
}
char var = init_fn();
//
// test_fn_init
void test_fn_init( test_info_t** info ){
static test_info_t test_fn_init_info;
static char* test_fn_init_name = "Initialization of Global by Function";
test_fn_init_info.name = test_fn_init_name;
test_fn_init_info.passed = true;
*(info) = &test_fn_init_info;
if( var != VAL ){ test_fn_init_info.passed = false; }
}
@@ -0,0 +1,8 @@
#ifndef _TEST_FN_INIT_H_
#define _TEST_FN_INIT_H_
#include "tests.h"
void test_fn_init( test_info_t** info );
#endif // _TEST_FN_INIT_H_
@@ -0,0 +1,30 @@
#include "tests.h"
test_fn tests[] = {
test_data,
test_bss,
test_constructors,
test_fn_init,
// test_fail,
// test_pass,
NULL, // NULL terminates the list
};
// test definitions
void test_fail( test_info_t** info ){
static test_info_t test_fail_info;
static char* test_fail_name = "Fail Test";
test_fail_info.name = test_fail_name;
test_fail_info.passed = false;
*(info) = &test_fail_info;
}
void test_pass( test_info_t** info ){
static test_info_t test_pass_info;
static char* test_pass_name = "Pass Test";
test_pass_info.name = test_pass_name;
test_pass_info.passed = true;
*(info) = &test_pass_info;
}
@@ -0,0 +1,20 @@
// test definitions
#ifndef _TESTS_H_
#define _TESTS_H_
#include "test_framework.h"
// included tests
#include "test_data.h"
#include "test_bss.h"
#include "test_constructors.h"
#include "test_fn_init.h"
// simple tests
void test_fail( test_info_t** info );
void test_pass( test_info_t** info );
// list of tests to run
extern test_fn tests[];
#endif // _TESTS_H_
@@ -0,0 +1,938 @@
//*****************************************************************************
//
//! @file HM01B0.c
//!
//
//*****************************************************************************
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#include "HM01B0.h"
#include "HM01B0_Walking1s_01.h"
#include "platform.h"
#define read_vsync() (AM_REGVAL(AM_REGADDR(GPIO, RDA)) & (1 << HM01B0_PIN_VSYNC))
#define read_hsync() (AM_REGVAL(AM_REGADDR(GPIO, RDA)) & (1 << HM01B0_PIN_HSYNC))
#define read_pclk() (AM_REGVAL(AM_REGADDR(GPIO, RDA)) & (1 << HM01B0_PIN_PCLK))
#define read_byte() (APBDMA->BBINPUT)
const am_hal_gpio_pincfg_t g_HM01B0_pin_int =
{
.uFuncSel = 3,
.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI,
.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE,
.eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN
};
//*****************************************************************************
//
//! @brief Write HM01B0 registers
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui16Reg - Register address.
//! @param pui8Value - Pointer to the data to be written.
//! @param ui32NumBytes - Length of the data in bytes to be written.
//!
//! This function writes value to HM01B0 registers.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_write_reg(hm01b0_cfg_t *psCfg, \
uint16_t ui16Reg, uint8_t *pui8Value, uint32_t ui32NumBytes)
{
am_hal_iom_transfer_t Transaction;
//
// Create the transaction.
//
Transaction.ui32InstrLen = sizeof(uint16_t);
Transaction.ui32Instr = (ui16Reg & 0x0000FFFF);
Transaction.eDirection = AM_HAL_IOM_TX;
Transaction.ui32NumBytes = ui32NumBytes;
Transaction.pui32TxBuffer = (uint32_t *) pui8Value;
Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t) psCfg->ui16SlvAddr;
Transaction.bContinue = false;
Transaction.ui8RepeatCount = 0;
Transaction.ui32PauseCondition = 0;
Transaction.ui32StatusSetClr = 0;
//
// Execute the transction over IOM.
//
if (am_hal_iom_blocking_transfer(psCfg->pIOMHandle, &Transaction))
{
return HM01B0_ERR_I2C;
}
return HM01B0_ERR_OK;
}
//*****************************************************************************
//
//! @brief Read HM01B0 registers
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui16Reg - Register address.
//! @param pui8Value - Pointer to the buffer for read data to be put into.
//! @param ui32NumBytes - Length of the data to be read.
//!
//! This function reads value from HM01B0 registers.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_read_reg(hm01b0_cfg_t *psCfg, \
uint16_t ui16Reg, uint8_t *pui8Value, uint32_t ui32NumBytes)
{
am_hal_iom_transfer_t Transaction;
//
// Create the transaction.
//
Transaction.ui32InstrLen = sizeof(uint16_t);
Transaction.ui32Instr = (ui16Reg & 0x0000FFFF);
Transaction.eDirection = AM_HAL_IOM_RX;
Transaction.ui32NumBytes = ui32NumBytes;
Transaction.pui32RxBuffer = (uint32_t *) pui8Value;;
Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t) psCfg->ui16SlvAddr;
Transaction.bContinue = false;
Transaction.ui8RepeatCount = 0;
Transaction.ui32PauseCondition = 0;
Transaction.ui32StatusSetClr = 0;
//
// Execute the transction over IOM.
//
if (am_hal_iom_blocking_transfer(psCfg->pIOMHandle, &Transaction))
{
return HM01B0_ERR_I2C;
}
return HM01B0_ERR_OK;
}
//*****************************************************************************
//
//! @brief Load HM01B0 a given script
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psScrip - Pointer to the script to be loaded.
//! @param ui32ScriptCmdNum - Number of entries in a given script.
//!
//! This function loads HM01B0 a given script.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_load_script(hm01b0_cfg_t *psCfg, hm_script_t *psScript, uint32_t ui32ScriptCmdNum)
{
uint32_t ui32Err = HM01B0_ERR_OK;
for (uint32_t idx = 0; idx < ui32ScriptCmdNum; idx++)
{
ui32Err = hm01b0_write_reg(psCfg, \
(psScript + idx)->ui16Reg, \
&((psScript + idx)->ui8Val), \
sizeof(uint8_t));
if (ui32Err != HM01B0_ERR_OK)
{
break;
}
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Power up HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function powers up HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_power_up(hm01b0_cfg_t *psCfg)
{
// place holder
}
//*****************************************************************************
//
//! @brief Power down HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function powers up HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_power_down(hm01b0_cfg_t *psCfg)
{
// place holder
}
//*****************************************************************************
//
//! @brief Enable MCLK
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function utilizes CTimer to generate MCLK for HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_mclk_enable(hm01b0_cfg_t *psCfg)
{
#define MCLK_UI64PATTERN 0x55555555
#define MCLK_UI64PATTERNLEN 31
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
//
// Set up timer.
//
am_hal_ctimer_clear(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
am_hal_ctimer_config_single(psCfg->ui32CTimerModule,
psCfg->ui32CTimerSegment,
(
AM_HAL_CTIMER_FN_PTN_REPEAT |
AM_HAL_CTIMER_HFRC_12MHZ
)
);
//
// Set the pattern in the CMPR registers.
//
am_hal_ctimer_compare_set(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment, 0,
(uint32_t)(MCLK_UI64PATTERN & 0xFFFF));
am_hal_ctimer_compare_set(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment, 1,
(uint32_t)((MCLK_UI64PATTERN >> 16) & 0xFFFF));
//
// Set the timer trigger and pattern length.
//
am_hal_ctimer_config_trigger(psCfg->ui32CTimerModule,
psCfg->ui32CTimerSegment,
(
(MCLK_UI64PATTERNLEN << CTIMER_AUX0_TMRA0LMT_Pos) |
(CTIMER_AUX0_TMRB0TRIG_DIS << CTIMER_AUX0_TMRA0TRIG_Pos)
)
);
//
// Configure timer output pin.
//
am_hal_ctimer_output_config(psCfg->ui32CTimerModule,
psCfg->ui32CTimerSegment,
psCfg->ui32CTimerOutputPin,
AM_HAL_CTIMER_OUTPUT_NORMAL,
AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA);
//
// Start the timer.
//
am_hal_ctimer_start(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
}
//*****************************************************************************
//
//! @brief Disable MCLK
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function disable CTimer to stop MCLK for HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_mclk_disable(hm01b0_cfg_t *psCfg)
{
//
// Stop the timer.
//
am_hal_ctimer_stop(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
am_hal_gpio_pinconfig(psCfg->ui32CTimerOutputPin, g_AM_HAL_GPIO_DISABLE);
}
//*****************************************************************************
//
//! @brief Initialize interfaces
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function initializes interfaces.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_init_if(hm01b0_cfg_t *psCfg)
{
void *pIOMHandle = NULL;
if ( psCfg->ui32IOMModule > AM_REG_IOM_NUM_MODULES )
{
return HM01B0_ERR_I2C;
}
//
// Enable fault detection.
//
#if AM_APOLLO3_MCUCTRL
am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_FAULT_CAPTURE_ENABLE, 0);
#else // AM_APOLLO3_MCUCTRL
am_hal_mcuctrl_fault_capture_enable();
#endif // AM_APOLLO3_MCUCTRL
//
// Initialize the IOM instance.
// Enable power to the IOM instance.
// Configure the IOM for Serial operation during initialization.
// Enable the IOM.
//
if (am_hal_iom_initialize(psCfg->ui32IOMModule, &pIOMHandle) ||
am_hal_iom_power_ctrl(pIOMHandle, AM_HAL_SYSCTRL_WAKE, false) ||
am_hal_iom_configure(pIOMHandle, &(psCfg->sIOMCfg)) ||
am_hal_iom_enable(pIOMHandle))
{
return HM01B0_ERR_I2C;
}
else
{
//
// Configure the IOM pins.
//
am_bsp_iom_pins_enable(psCfg->ui32IOMModule, psCfg->eIOMMode);
psCfg->pIOMHandle = pIOMHandle;
}
// initialize pins for camera parallel interface.
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD0);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD1);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD2);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD3);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD4);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD5);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD6);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD7);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD0);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD1);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD2);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD3);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD4);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD5);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD6);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD7);
am_hal_gpio_fast_pinconfig((uint64_t)0x1 << psCfg->ui8PinD0 |
(uint64_t)0x1 << psCfg->ui8PinD1 |
(uint64_t)0x1 << psCfg->ui8PinD2 |
(uint64_t)0x1 << psCfg->ui8PinD3 |
(uint64_t)0x1 << psCfg->ui8PinD4 |
(uint64_t)0x1 << psCfg->ui8PinD5 |
(uint64_t)0x1 << psCfg->ui8PinD6 |
(uint64_t)0x1 << psCfg->ui8PinD7,
g_AM_HAL_GPIO_INPUT, 0);
am_hal_gpio_pinconfig(psCfg->ui8PinVSYNC, g_AM_HAL_GPIO_INPUT);
am_hal_gpio_pinconfig(psCfg->ui8PinHSYNC, g_AM_HAL_GPIO_INPUT);
am_hal_gpio_pinconfig(psCfg->ui8PinPCLK, g_AM_HAL_GPIO_INPUT);
am_hal_gpio_pinconfig(psCfg->ui8PinTrig, g_AM_HAL_GPIO_OUTPUT);
am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_AM_HAL_GPIO_DISABLE);
// am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_HM01B0_pin_int);
// am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(psCfg->ui8PinInt));
// am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(psCfg->ui8PinInt));
// NVIC_EnableIRQ(GPIO_IRQn);
return HM01B0_ERR_OK;
}
//*****************************************************************************
//
//! @brief Deinitialize interfaces
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function deinitializes interfaces.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_deinit_if(hm01b0_cfg_t *psCfg)
{
am_hal_iom_disable(psCfg->pIOMHandle);
am_hal_iom_uninitialize(psCfg->pIOMHandle);
am_hal_gpio_pinconfig(psCfg->ui8PinSCL, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinSDA, g_AM_HAL_GPIO_DISABLE);
// initialize pins for camera parallel interface.
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD0);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD1);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD2);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD3);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD4);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD5);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD6);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD7);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD0);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD1);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD2);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD3);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD4);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD5);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD6);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD7);
am_hal_gpio_pinconfig(psCfg->ui8PinVSYNC, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinHSYNC, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinPCLK, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinTrig, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_AM_HAL_GPIO_DISABLE);
return HM01B0_ERR_OK;
}
//*****************************************************************************
//
//! @brief Get HM01B0 Model ID
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui16MID - Pointer to buffer for the read back model ID.
//!
//! This function reads back HM01B0 model ID.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_modelid(hm01b0_cfg_t *psCfg, uint16_t *pui16MID)
{
uint8_t ui8Data[1];
uint32_t ui32Err;
*pui16MID = 0x0000;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_MODEL_ID_H, ui8Data, sizeof(ui8Data));
if (ui32Err == HM01B0_ERR_OK)
{
*pui16MID |= (ui8Data[0] << 8);
}
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_MODEL_ID_L, ui8Data, sizeof(ui8Data));
if (ui32Err == HM01B0_ERR_OK)
{
*pui16MID |= ui8Data[0];
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Initialize HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psScript - Pointer to HM01B0 initialization script.
//! @param ui32ScriptCmdNum - No. of commands in HM01B0 initialization script.
//!
//! This function initilizes HM01B0 with a given script.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_init_system(hm01b0_cfg_t *psCfg, hm_script_t *psScript, uint32_t ui32ScriptCmdNum)
{
return hm01b0_load_script(psCfg, psScript, ui32ScriptCmdNum);
}
//*****************************************************************************
//
//! @brief Set HM01B0 in the walking 1s test mode
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function sets HM01B0 in the walking 1s test mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_test_walking1s(hm01b0_cfg_t *psCfg)
{
uint32_t ui32ScriptCmdNum = sizeof(sHM01b0TestModeScript_Walking1s) / sizeof(hm_script_t);
hm_script_t *psScript = (hm_script_t *)sHM01b0TestModeScript_Walking1s;
return hm01b0_load_script(psCfg, psScript, ui32ScriptCmdNum);
}
//*****************************************************************************
//
//! @brief Check the data read from HM01B0 in the walking 1s test mode
//!
//! @param pui8Buffer - Pointer to data buffer.
//! @param ui32BufferLen - Buffer length
//! @param ui32PrintCnt - Number of mismatched data to be printed out
//!
//! This function sets HM01B0 in the walking 1s test mode.
//!
//! @return Error code.
//
//*****************************************************************************
void hm01b0_test_walking1s_check_data_sanity(uint8_t *pui8Buffer, uint32_t ui32BufferLen, uint32_t ui32PrintCnt)
{
uint8_t ui8ByteData = *pui8Buffer;
uint32_t ui32MismatchCnt = 0x00;
for (uint32_t ui32Idx = 0; ui32Idx < ui32BufferLen; ui32Idx++)
{
if (*(pui8Buffer + ui32Idx) != ui8ByteData)
{
if (ui32PrintCnt)
{
am_util_stdio_printf("[0x%08X] actual 0x%02X expected 0x%02X\n", ui32Idx, *(pui8Buffer + ui32Idx), ui8ByteData);
am_util_delay_ms(1);
ui32PrintCnt--;
}
ui32MismatchCnt++;
}
if (ui8ByteData)
ui8ByteData = ui8ByteData << 1;
else
ui8ByteData = 0x01;
}
am_util_stdio_printf("Mismatch Rate %d/%d\n", ui32MismatchCnt, ui32BufferLen);
}
//*****************************************************************************
//
//! @brief Software reset HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function resets HM01B0 by issuing a reset command.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_reset_sw(hm01b0_cfg_t *psCfg)
{
uint8_t ui8Data[1] = {0x00};
return hm01b0_write_reg(psCfg, HM01B0_REG_SW_RESET, ui8Data, sizeof(ui8Data));
}
//*****************************************************************************
//
//! @brief Get current HM01B0 operation mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui8Mode - Pointer to buffer
//! - for the read back operation mode to be put into
//!
//! This function get HM01B0 operation mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_mode(hm01b0_cfg_t *psCfg, uint8_t *pui8Mode)
{
uint8_t ui8Data[1] = {0x01};
uint32_t ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_MODE_SELECT, ui8Data, sizeof(ui8Data));
*pui8Mode = ui8Data[0];
return ui32Err;
}
//*****************************************************************************
//
//! @brief Set HM01B0 operation mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui8Mode - Operation mode. One of:
//! HM01B0_REG_MODE_SELECT_STANDBY
//! HM01B0_REG_MODE_SELECT_STREAMING
//! HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES
//! HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER
//! @param ui8FrameCnt - Frame count for HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES.
//! - Discarded if other modes.
//!
//! This function set HM01B0 operation mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_set_mode(hm01b0_cfg_t *psCfg, uint8_t ui8Mode, uint8_t ui8FrameCnt)
{
uint32_t ui32Err = HM01B0_ERR_OK;
if (ui8Mode == HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES)
{
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_PMU_PROGRAMMABLE_FRAMECNT, &ui8FrameCnt, sizeof(ui8FrameCnt));
}
if(ui32Err == HM01B0_ERR_OK)
{
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_MODE_SELECT, &ui8Mode, sizeof(ui8Mode));
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Activate the updated settings to HM01B0.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! Some settings updated to HM01B0 will only be affected after calling this function
//! 1. AE settings
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_cmd_update(hm01b0_cfg_t *psCfg)
{
uint8_t ui8Data = HM01B0_REG_GRP_PARAM_HOLD_HOLD;
return hm01b0_write_reg(psCfg, HM01B0_REG_GRP_PARAM_HOLD, &ui8Data, sizeof(ui8Data));
}
//*****************************************************************************
//
//! @brief Get HM01B0 AE convergance
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psAECfg - Pointer to the structure hm01b0_ae_cfg_t.
//!
//! This function checks if AE is converged or not and returns ui32Err accordingly.
//! If caller needs detailed AE settings, psAECfg has to be non NULL.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_ae(hm01b0_cfg_t *psCfg, hm01b0_ae_cfg_t *psAECfg)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint8_t ui8AETargetMean;
uint8_t ui8AEMinMean;
uint8_t ui8AEMean;
uint8_t ui8ConvergeInTh;
uint8_t ui8ConvergeOutTh;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_AE_TARGET_MEAN, &ui8AETargetMean, sizeof(ui8AETargetMean));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_AE_MIN_MEAN, &ui8AEMinMean, sizeof(ui8AEMinMean));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_CONVERGE_IN_TH, &ui8ConvergeInTh, sizeof(ui8ConvergeInTh));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_CONVERGE_OUT_TH, &ui8ConvergeOutTh, sizeof(ui8ConvergeOutTh));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, 0x2020, &ui8AEMean, sizeof(ui8AEMean));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
if ((ui8AEMean < (ui8AETargetMean - ui8ConvergeInTh)) || (ui8AEMean > (ui8AETargetMean + ui8ConvergeInTh)))
ui32Err = HM01B0_ERR_AE_NOT_CONVERGED;
if (psAECfg)
{
psAECfg->ui8AETargetMean = ui8AETargetMean;
psAECfg->ui8AEMinMean = ui8AEMinMean;
psAECfg->ui8ConvergeInTh = ui8ConvergeInTh;
psAECfg->ui8ConvergeOutTh = ui8ConvergeOutTh;
psAECfg->ui8AEMean = ui8AEMean;
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief AE calibration.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui8CalFrames - Frame counts for calibratoin.
//! @param pui8Buffer - Pointer to the frame buffer.
//! @param ui32BufferLen - Framebuffer size.
//!
//! This function lets HM01B0 AE settled as much as possible within a given frame counts.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_cal_ae(hm01b0_cfg_t *psCfg, uint8_t ui8CalFrames, uint8_t *pui8Buffer, uint32_t ui32BufferLen)
{
uint32_t ui32Err = HM01B0_ERR_OK;
hm01b0_ae_cfg_t sAECfg;
am_util_stdio_printf("[%s] +\n", __func__);
hm01b0_set_mode(psCfg, HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES, ui8CalFrames);
for (uint8_t i = 0; i < ui8CalFrames; i++)
{
hm01b0_blocking_read_oneframe(psCfg, pui8Buffer, ui32BufferLen);
ui32Err = hm01b0_get_ae(psCfg, &sAECfg);
am_util_stdio_printf("AE Calibration(0x%02X) TargetMean 0x%02X, ConvergeInTh 0x%02X, AEMean 0x%02X\n", \
ui32Err, sAECfg.ui8AETargetMean, sAECfg.ui8ConvergeInTh, sAECfg.ui8AEMean);
// if AE calibration is done in ui8CalFrames, just exit to save some time.
if (ui32Err == HM01B0_ERR_OK)
break;
}
hm01b0_set_mode(psCfg, HM01B0_REG_MODE_SELECT_STANDBY, 0);
am_util_stdio_printf("[%s] -\n", __func__);
return ui32Err;
}
//*****************************************************************************
//
//! @brief Save HM01B0 exposure gain settings.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psExpoGainCtrl - Pointer to the structure hm01b0_snr_expo_gain_ctrl_t
//!
//! This function saves HM01B0 exposure gain settings.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_save_exposure_gains(hm01b0_cfg_t *psCfg, hm01b0_snr_expo_gain_ctrl_t *psExpoGainCtrl)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint8_t ui8IntegrationH;
uint8_t ui8IntegrationL;
uint8_t ui8AGain;
uint8_t ui8DGain_H;
uint8_t ui8DGain_L;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_INTEGRATION_H, &ui8IntegrationH, sizeof(ui8IntegrationH));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_INTEGRATION_L, &ui8IntegrationL, sizeof(ui8IntegrationL));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_ANALOG_GAIN, &ui8AGain, sizeof(ui8AGain));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_H, &ui8DGain_H, sizeof(ui8DGain_H));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_L, &ui8DGain_L, sizeof(ui8DGain_L));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
if (psExpoGainCtrl)
{
psExpoGainCtrl->ui8IntegrationH = ui8IntegrationH;
psExpoGainCtrl->ui8IntegrationL = ui8IntegrationL;
psExpoGainCtrl->ui8AGain = ui8AGain;
psExpoGainCtrl->ui8DGain_H = ui8DGain_H;
psExpoGainCtrl->ui8DGain_L = ui8DGain_L;
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Restore HM01B0 exposure gain settings.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psExpoGainCtrl - Pointer to the structure hm01b0_snr_expo_gain_ctrl_t
//!
//! This function restores HM01B0 exposure gain settings. The call flow shall be
//! hm01b0_restore_exposure_gains() -> hm01b0_cmd_update() -> hm01b0_set_mode()
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_restore_exposure_gains(hm01b0_cfg_t *psCfg, hm01b0_snr_expo_gain_ctrl_t *psExpoGainCtrl)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint8_t ui8Tmp;
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_INTEGRATION_H, &(psExpoGainCtrl->ui8IntegrationH), sizeof(psExpoGainCtrl->ui8IntegrationH));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_INTEGRATION_L, &(psExpoGainCtrl->ui8IntegrationL), sizeof(psExpoGainCtrl->ui8IntegrationL));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_ANALOG_GAIN, &ui8Tmp, sizeof(ui8Tmp));
ui8Tmp = (ui8Tmp & ~(0x7 << 4)) | (psExpoGainCtrl->ui8AGain & (0x7 << 4));
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_ANALOG_GAIN, &ui8Tmp, sizeof(ui8Tmp));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_H, &ui8Tmp, sizeof(ui8Tmp));
ui8Tmp = (ui8Tmp & ~(0x3 << 0)) | (psExpoGainCtrl->ui8DGain_H & (0x3 << 0));
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_H, &ui8Tmp, sizeof(ui8Tmp));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_L, &ui8Tmp, sizeof(ui8Tmp));
ui8Tmp = (ui8Tmp & ~(0x3F << 2)) | (psExpoGainCtrl->ui8DGain_L & (0x3F << 2));
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_L, &ui8Tmp, sizeof(ui8Tmp));
return ui32Err;
}
//*****************************************************************************
//
//! @brief Hardware trigger HM01B0 to stream.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param bTrigger - True to start streaming
//! - False to stop streaming
//!
//! This function triggers HM01B0 to stream by toggling the TRIG pin.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_hardware_trigger_streaming(hm01b0_cfg_t *psCfg, bool bTrigger)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint8_t ui8Mode;
ui32Err = hm01b0_get_mode(psCfg, &ui8Mode);
if (ui32Err != HM01B0_ERR_OK)
goto end;
if (ui8Mode != HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER)
{
ui32Err = HM01B0_ERR_MODE;
goto end;
}
if (bTrigger)
{
am_hal_gpio_output_set(psCfg->ui8PinTrig);
}
else
{
am_hal_gpio_output_clear(psCfg->ui8PinTrig);
}
end:
return ui32Err;
}
//*****************************************************************************
//
//! @brief Set HM01B0 mirror mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param bHmirror - Horizontal mirror
//! @param bVmirror - Vertical mirror
//!
//! This function set HM01B0 mirror mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_set_mirror(hm01b0_cfg_t *psCfg, bool bHmirror, bool bVmirror)
{
uint8_t ui8Data = 0x00;
uint32_t ui32Err = HM01B0_ERR_OK;
if (bHmirror)
{
ui8Data |= HM01B0_REG_IMAGE_ORIENTATION_HMIRROR;
}
if (bVmirror)
{
ui8Data |= HM01B0_REG_IMAGE_ORIENTATION_VMIRROR;
}
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_IMAGE_ORIENTATION, &ui8Data, sizeof(ui8Data));
if (ui32Err == HM01B0_ERR_OK)
{
ui8Data = HM01B0_REG_GRP_PARAM_HOLD_HOLD;
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_GRP_PARAM_HOLD, &ui8Data, sizeof(ui8Data));
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Read data of one frame from HM01B0.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui8Buffer - Pointer to the frame buffer.
//! @param ui32BufferLen - Framebuffer size.
//!
//! This function read data of one frame from HM01B0.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_blocking_read_oneframe(hm01b0_cfg_t *psCfg, uint8_t *pui8Buffer, uint32_t ui32BufferLen)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint32_t ui32Idx = 0x00;
am_util_stdio_printf("[%s] +\n", __func__);
uint32_t ui32HsyncCnt = 0x00;
while((ui32HsyncCnt < HM01B0_PIXEL_Y_NUM))
{
while (0x00 == read_hsync());
// read one row
while(read_hsync())
{
while(0x00 == read_pclk());
*(pui8Buffer + ui32Idx++) = read_byte();
if (ui32Idx == ui32BufferLen) {
goto end;
}
while(read_pclk());
}
ui32HsyncCnt++;
}
end:
am_util_stdio_printf("[%s] - Byte Counts %d\n", __func__, ui32Idx);
return ui32Err;
}
@@ -0,0 +1,490 @@
//*****************************************************************************
//
//! @file HM01B0.h
//
//*****************************************************************************
#ifndef HM01B0_H
#define HM01B0_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#define HM01B0_DRV_VERSION (0)
#define HM01B0_DRV_SUBVERSION (5)
#define HM01B0_DEFAULT_ADDRESS (0x24)
#define HM01B0_PIXEL_X_NUM (324)
#define HM01B0_PIXEL_Y_NUM (244)
#define HM01B0_REG_MODEL_ID_H (0x0000)
#define HM01B0_REG_MODEL_ID_L (0x0001)
#define HM01B0_REG_SILICON_REV (0x0002)
#define HM01B0_REG_FRAME_COUNT (0x0005)
#define HM01B0_REG_PIXEL_ORDER (0x0006)
#define HM01B0_REG_MODE_SELECT (0x0100)
#define HM01B0_REG_IMAGE_ORIENTATION (0x0101)
#define HM01B0_REG_SW_RESET (0x0103)
#define HM01B0_REG_GRP_PARAM_HOLD (0x0104)
#define HM01B0_REG_INTEGRATION_H (0x0202)
#define HM01B0_REG_INTEGRATION_L (0x0203)
#define HM01B0_REG_ANALOG_GAIN (0x0205)
#define HM01B0_REG_DIGITAL_GAIN_H (0x020E)
#define HM01B0_REG_DIGITAL_GAIN_L (0x020F)
#define HM01B0_REG_AE_TARGET_MEAN (0x2101)
#define HM01B0_REG_AE_MIN_MEAN (0x2102)
#define HM01B0_REG_CONVERGE_IN_TH (0x2103)
#define HM01B0_REG_CONVERGE_OUT_TH (0x2104)
#define HM01B0_REG_I2C_ID_SEL (0x3400)
#define HM01B0_REG_I2C_ID_REG (0x3401)
#define HM01B0_REG_PMU_PROGRAMMABLE_FRAMECNT (0x3020)
// #define HM01B0_REG_MODE_SELECT (0x0100)
#define HM01B0_REG_MODE_SELECT_STANDBY (0x00)
#define HM01B0_REG_MODE_SELECT_STREAMING (0x01)
#define HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES (0x03)
#define HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER (0x05)
// #define HM01B0_REG_IMAGE_ORIENTATION (0x0101)
#define HM01B0_REG_IMAGE_ORIENTATION_DEFAULT (0x00)
#define HM01B0_REG_IMAGE_ORIENTATION_HMIRROR (0x01)
#define HM01B0_REG_IMAGE_ORIENTATION_VMIRROR (0x02)
#define HM01B0_REG_IMAGE_ORIENTATION_HVMIRROR (HM01B0_REG_IMAGE_ORIENTATION_HMIRROR | HM01B0_REG_IMAGE_ORIENTATION_HVMIRROR)
// #define HM01B0_REG_GRP_PARAM_HOLD (0x0104)
#define HM01B0_REG_GRP_PARAM_HOLD_CONSUME (0x00)
#define HM01B0_REG_GRP_PARAM_HOLD_HOLD (0x01)
enum
{
HM01B0_ERR_OK = 0x00,
HM01B0_ERR_I2C,
HM01B0_ERR_MODE,
HM01B0_ERR_AE_NOT_CONVERGED,
};
typedef struct
{
uint16_t ui16Reg;
uint8_t ui8Val;
} hm_script_t;
typedef struct
{
uint16_t ui16SlvAddr;
am_hal_iom_mode_e eIOMMode;
uint32_t ui32IOMModule;
am_hal_iom_config_t sIOMCfg;
void *pIOMHandle;
uint32_t ui32CTimerModule;
uint32_t ui32CTimerSegment;
uint32_t ui32CTimerOutputPin;
uint8_t ui8PinSCL;
uint8_t ui8PinSDA;
uint8_t ui8PinD0;
uint8_t ui8PinD1;
uint8_t ui8PinD2;
uint8_t ui8PinD3;
uint8_t ui8PinD4;
uint8_t ui8PinD5;
uint8_t ui8PinD6;
uint8_t ui8PinD7;
uint8_t ui8PinVSYNC;
uint8_t ui8PinHSYNC;
uint8_t ui8PinPCLK;
uint8_t ui8PinTrig;
uint8_t ui8PinInt;
void (*pfnGpioIsr)(void);
} hm01b0_cfg_t;
typedef struct
{
uint8_t ui8AETargetMean;
uint8_t ui8AEMinMean;
uint8_t ui8ConvergeInTh;
uint8_t ui8ConvergeOutTh;
uint8_t ui8AEMean;
} hm01b0_ae_cfg_t;
typedef struct
{
uint8_t ui8IntegrationH;
uint8_t ui8IntegrationL;
uint8_t ui8AGain;
uint8_t ui8DGain_H;
uint8_t ui8DGain_L;
} hm01b0_snr_expo_gain_ctrl_t;
//*****************************************************************************
//
//! @brief Write HM01B0 registers
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui16Reg - Register address.
//! @param pui8Value - Pointer to the data to be written.
//! @param ui32NumBytes - Length of the data in bytes to be written.
//!
//! This function writes value to HM01B0 registers.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_write_reg(hm01b0_cfg_t *psCfg, \
uint16_t ui16Reg, uint8_t *pui8Value, uint32_t ui32NumBytes);
//*****************************************************************************
//
//! @brief Read HM01B0 registers
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui16Reg - Register address.
//! @param pui8Value - Pointer to the buffer for read data to be put into.
//! @param ui32NumBytes - Length of the data to be read.
//!
//! This function reads value from HM01B0 registers.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_read_reg(hm01b0_cfg_t *psCfg, \
uint16_t ui16Reg, uint8_t *pui8Value, uint32_t ui32NumBytes);
//*****************************************************************************
//
//! @brief Load HM01B0 a given script
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psScrip - Pointer to the script to be loaded.
//! @param ui32ScriptCmdNum - Number of entries in a given script.
//!
//! This function loads HM01B0 a given script.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_load_script(hm01b0_cfg_t *psCfg, hm_script_t *psScript, uint32_t ui32ScriptCmdNum);
//*****************************************************************************
//
//! @brief Power up HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function powers up HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_power_up(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Power down HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function powers up HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_power_down(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Enable MCLK
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function utilizes CTimer to generate MCLK for HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_mclk_enable(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Disable MCLK
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function disable CTimer to stop MCLK for HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_mclk_disable(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Initialize interfaces
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function initializes interfaces.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_init_if(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Deinitialize interfaces
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function deinitializes interfaces.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_deinit_if(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Get HM01B0 Model ID
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui16MID - Pointer to buffer for the read back model ID.
//!
//! This function reads back HM01B0 model ID.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_modelid(hm01b0_cfg_t *psCfg, uint16_t *pui16MID);
//*****************************************************************************
//
//! @brief Initialize HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psScript - Pointer to HM01B0 initialization script.
//! @param ui32ScriptCmdNum - No. of commands in HM01B0 initialization script.
//!
//! This function initilizes HM01B0 with a given script.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_init_system(hm01b0_cfg_t *psCfg, hm_script_t *psScript, uint32_t ui32ScriptCmdNum);
//*****************************************************************************
//
//! @brief Set HM01B0 in the walking 1s test mode
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function sets HM01B0 in the walking 1s test mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_test_walking1s(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Check the data read from HM01B0 in the walking 1s test mode
//!
//! @param pui8Buffer - Pointer to data buffer.
//! @param ui32BufferLen - Buffer length
//! @param ui32PrintCnt - Number of mismatched data to be printed out
//!
//! This function sets HM01B0 in the walking 1s test mode.
//!
//! @return Error code.
//
//*****************************************************************************
void hm01b0_test_walking1s_check_data_sanity(uint8_t *pui8Buffer, uint32_t ui32BufferLen, uint32_t ui32PrintCnt);
//*****************************************************************************
//
//! @brief Software reset HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function resets HM01B0 by issuing a reset command.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_reset_sw(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Get current HM01B0 operation mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui8Mode - Pointer to buffer
//! - for the read back operation mode to be put into
//!
//! This function get HM01B0 operation mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_mode(hm01b0_cfg_t *psCfg, uint8_t *pui8Mode);
//*****************************************************************************
//
//! @brief Set HM01B0 operation mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui8Mode - Operation mode. One of:
//! HM01B0_REG_MODE_SELECT_STANDBY
//! HM01B0_REG_MODE_SELECT_STREAMING
//! HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES
//! HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER
//! @param framecnt - Frame count for HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES.
//! - Discarded if other modes.
//!
//! This function set HM01B0 operation mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_set_mode(hm01b0_cfg_t *psCfg, uint8_t ui8Mode, uint8_t framecnt);
//*****************************************************************************
//
//! @brief Activate the updated settings to HM01B0.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! Some settings updated to HM01B0 will only be affected after calling this function
//! 1. AE settings
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_cmd_update(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Get HM01B0 AE settings
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psAECfg - Pointer to the structure hm01b0_ae_cfg_t.
//!
//! This function checks if AE is converged or not and returns ui32Err accordingly.
//! If caller needs detailed AE settings, psAECfg has to be non NULL.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_ae(hm01b0_cfg_t *psCfg, hm01b0_ae_cfg_t *psAECfg);
//*****************************************************************************
//
//! @brief AE calibration.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui8CalFrames - Frame counts for calibratoin.
//! @param pui8Buffer - Pointer to the frame buffer.
//! @param ui32BufferLen - Framebuffer size.
//!
//! This function lets HM01B0 AE settled as much as possible within a given frame counts.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_cal_ae(hm01b0_cfg_t *psCfg, uint8_t ui8CalFrames, uint8_t *pui8Buffer, uint32_t ui32BufferLen);
//*****************************************************************************
//
//! @brief Save HM01B0 exposure gain settings.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psExpoGainCtrl - Pointer to the structure hm01b0_snr_expo_gain_ctrl_t
//!
//! This function saves HM01B0 exposure gain settings.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_save_exposure_gains(hm01b0_cfg_t *psCfg, hm01b0_snr_expo_gain_ctrl_t *psExpoGainCtrl);
//*****************************************************************************
//
//! @brief Restore HM01B0 exposure gain settings.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psExpoGainCtrl - Pointer to the structure hm01b0_snr_expo_gain_ctrl_t
//!
//! This function restores HM01B0 exposure gain settings. The call flow shall be
//! hm01b0_restore_exposure_gains() -> hm01b0_cmd_update() -> hm01b0_set_mode()
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_restore_exposure_gains(hm01b0_cfg_t *psCfg, hm01b0_snr_expo_gain_ctrl_t *psExpoGainCtrl);
//*****************************************************************************
//
//! @brief Hardware trigger HM01B0 to stream.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param bTrigger - True to start streaming
//! - False to stop streaming
//!
//! This function triggers HM01B0 to stream by toggling the TRIG pin.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_hardware_trigger_streaming(hm01b0_cfg_t *psCfg, bool bTrigger);
//*****************************************************************************
//
//! @brief Set HM01B0 mirror mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param bHmirror - Horizontal mirror
//! @param bVmirror - Vertical mirror
//!
//! This function set HM01B0 mirror mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_set_mirror(hm01b0_cfg_t *psCfg, bool bHmirror, bool bVmirror);
//*****************************************************************************
//
//! @brief Read data of one frame from HM01B0.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui8Buffer - Pointer to the frame buffer.
//! @param ui32BufferLen - Framebuffer size.
//!
//! This function read data of one frame from HM01B0.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_blocking_read_oneframe(hm01b0_cfg_t *psCfg, \
uint8_t *pui8Buffer, uint32_t ui32BufferLen);
#ifdef __cplusplus
}
#endif
#endif // AM_HAL_CTIMER_H
@@ -0,0 +1,233 @@
#include "HM01B0.h"
const hm_script_t sHM01B0InitScript[] =
{
// ;*************************************************************************
// ; Sensor: HM01B0
// ; I2C ID: 24
// ; Resolution: 324x244
// ; Lens:
// ; Flicker:
// ; Frequency:
// ; Description: AE control enable
// ; 8-bit mode, LSB first
// ;
// ;
// ; Note:
// ;
// ; $Revision: 1338 $
// ; $Date:: 2017-04-11 15:43:45 +0800#$
// ;*************************************************************************
//
// // ---------------------------------------------------
// // HUB system initial
// // ---------------------------------------------------
// W 20 8A04 01 2 1
// W 20 8A00 22 2 1
// W 20 8A01 00 2 1
// W 20 8A02 01 2 1
// W 20 0035 93 2 1 ; [3]&[1] hub616 20bits in, [5:4]=1 mclk=48/2=24mhz
// W 20 0036 00 2 1
// W 20 0011 09 2 1
// W 20 0012 B6 2 1
// W 20 0014 08 2 1
// W 20 0015 98 2 1
// ;W 20 0130 16 2 1 ; 3m soc, signal buffer control
// ;W 20 0100 44 2 1 ; [6] hub616 20bits in
// W 20 0100 04 2 1 ; [6] hub616 20bits in
// W 20 0121 01 2 1 ; [0] Q1 Intf enable, [1]:4bit mode, [2] msb first, [3] serial mode
// W 20 0150 00 2 1 ;
// W 20 0150 04 2 1 ;
//
//
// //---------------------------------------------------
// // Initial
// //---------------------------------------------------
// W 24 0103 00 2 1 ; software reset-> was 0x22
{0x0103, 0x00,},
// W 24 0100 00 2 1; power up
{0x0100, 0x00,},
//
//
//
// //---------------------------------------------------
// // Analog
// //---------------------------------------------------
// L HM01B0_analog_setting.txt
{0x1003, 0x08,},
{0x1007, 0x08,},
{0x3044, 0x0A,},
{0x3045, 0x00,},
{0x3047, 0x0A,},
{0x3050, 0xC0,},
{0x3051, 0x42,},
{0x3052, 0x50,},
{0x3053, 0x00,},
{0x3054, 0x03,},
{0x3055, 0xF7,},
{0x3056, 0xF8,},
{0x3057, 0x29,},
{0x3058, 0x1F,},
{0x3059, 0x1E,},
{0x3064, 0x00,},
{0x3065, 0x04,},
//
//
// //---------------------------------------------------
// // Digital function
// //---------------------------------------------------
//
// // BLC
// W 24 1000 43 2 1 ; BLC_on, IIR
{0x1000, 0x43,},
// W 24 1001 40 2 1 ; [6] : BLC dithering en
{0x1001, 0x40,},
// W 24 1002 32 2 1 ; // blc_darkpixel_thd
{0x1002, 0x32,},
//
// // Dgain
// W 24 0350 7F 2 1 ; Dgain Control
{0x0350, 0x7F,},
//
// // BLI
// W 24 1006 01 2 1 ; [0] : bli enable
{0x1006, 0x01,},
//
// // DPC
// W 24 1008 00 2 1 ; [2:0] : DPC option 0: DPC off 1 : mono 3 : bayer1 5 : bayer2
{0x1008, 0x00,},
// W 24 1009 A0 2 1 ; cluster hot pixel th
{0x1009, 0xA0,},
// W 24 100A 60 2 1 ; cluster cold pixel th
{0x100A, 0x60,},
// W 24 100B 90 2 1 ; single hot pixel th
{0x100B, 0x90,},
// W 24 100C 40 2 1 ; single cold pixel th
{0x100C, 0x40,},
// //
// advance VSYNC by 1 row
{0x3022, 0x01,},
// W 24 1012 00 2 1 ; Sync. enable VSYNC shift
{0x1012, 0x01,},
//
// // ROI Statistic
// W 24 2000 07 2 1 ; [0] : AE stat en [1] : MD LROI stat en [2] : MD GROI stat en [3] : RGB stat ratio en [4] : IIR selection (1 -> 16, 0 -> 8)
{0x2000, 0x07,},
// W 24 2003 00 2 1 ; MD GROI 0 y start HB
{0x2003, 0x00,},
// W 24 2004 1C 2 1 ; MD GROI 0 y start LB
{0x2004, 0x1C,},
// W 24 2007 00 2 1 ; MD GROI 1 y start HB
{0x2007, 0x00,},
// W 24 2008 58 2 1 ; MD GROI 1 y start LB
{0x2008, 0x58,},
// W 24 200B 00 2 1 ; MD GROI 2 y start HB
{0x200B, 0x00,},
// W 24 200C 7A 2 1 ; MD GROI 2 y start LB
{0x200C, 0x7A,},
// W 24 200F 00 2 1 ; MD GROI 3 y start HB
{0x200F, 0x00,},
// W 24 2010 B8 2 1 ; MD GROI 3 y start LB
{0x2010, 0xB8,},
//
// W 24 2013 00 2 1 ; MD LRIO y start HB
{0x2013, 0x00,},
// W 24 2014 58 2 1 ; MD LROI y start LB
{0x2014, 0x58,},
// W 24 2017 00 2 1 ; MD LROI y end HB
{0x2017, 0x00,},
// W 24 2018 9B 2 1 ; MD LROI y end LB
{0x2018, 0x9B,},
//
// // AE
// W 24 2100 01 2 1 ; [0]: AE control enable
{0x2100, 0x01,},
// W 24 2104 07 2 1 ; converge out th
{0x2104, 0x07,},
// W 24 2105 0C 2 1 ; max INTG Hb
{0x2105, 0x0C,},
// W 24 2106 78 2 1 ; max INTG Lb
{0x2106, 0x78,},
// W 24 2108 03 2 1 ; max AGain in full
{0x2108, 0x03,},
// W 24 2109 03 2 1 ; max AGain in bin2
{0x2109, 0x03,},
// W 24 210B 80 2 1 ; max DGain
{0x210B, 0x80,},
// W 24 210F 00 2 1 ; FS 60Hz Hb
{0x210F, 0x00,},
// W 24 2110 85 2 1 ; FS 60Hz Lb
{0x2110, 0x85,},
// W 24 2111 00 2 1 ; Fs 50Hz Hb
{0x2111, 0x00,},
// W 24 2112 A0 2 1 ; FS 50Hz Lb
{0x2112, 0xA0,},
//
//
// // MD
// W 24 2150 03 2 1 ; [0] : MD LROI en [1] : MD GROI en
{0x2150, 0x03,},
//
//
// //---------------------------------------------------
// // frame rate : 5 FPS
// //---------------------------------------------------
// W 24 0340 0C 2 1 ; smia frame length Hb
{0x0340, 0x0C,},
// W 24 0341 7A 2 1 ; smia frame length Lb 3192
{0x0341, 0x7A,},
//
// W 24 0342 01 2 1 ; smia line length Hb
{0x0342, 0x01,},
// W 24 0343 77 2 1 ; smia line length Lb 375
{0x0343, 0x77,},
//
// //---------------------------------------------------
// // Resolution : QVGA 324x244
// //---------------------------------------------------
// W 24 3010 01 2 1 ; [0] : window mode 0 : full frame 324x324 1 : QVGA
{0x3010, 0x01,},
//
//
// W 24 0383 01 2 1 ;
{0x0383, 0x01,},
// W 24 0387 01 2 1 ;
{0x0387, 0x01,},
// W 24 0390 00 2 1 ;
{0x0390, 0x00,},
//
// //---------------------------------------------------
// // bit width Selection
// //---------------------------------------------------
// W 24 3011 70 2 1 ; [0] : 6 bit mode enable
{0x3011, 0x70,},
//
//
// W 24 3059 02 2 1 ; [7]: Self OSC En, [6]: 4bit mode, [5]: serial mode, [4:0]: keep value as 0x02
{0x3059, 0x02,},
// W 24 3060 01 2 1 ; [5]: gated_clock, [4]: msb first,
{0x3060, 0x20,},
// ; [3:2]: vt_reg_div -> div by 4/8/1/2
// ; [1;0]: vt_sys_div -> div by 8/4/2/1
//
//
{0x0101, 0x01,},
// //---------------------------------------------------
// // CMU update
// //---------------------------------------------------
//
// W 24 0104 01 2 1 ; was 0100
{0x0104, 0x01,},
//
//
//
// //---------------------------------------------------
// // Turn on rolling shutter
// //---------------------------------------------------
// W 24 0100 01 2 1 ; was 0005 ; mode_select 00 : standby - wait fir I2C SW trigger 01 : streaming 03 : output "N" frame, then enter standby 04 : standby - wait for HW trigger (level), then continuous video out til HW TRIG goes off 06 : standby - wait for HW trigger (edge), then output "N" frames then enter standby
{0x0100, 0x00,},
//
// ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
};
@@ -0,0 +1,14 @@
#include "HM01B0.h"
const hm_script_t sHM01b0TestModeScript_Walking1s[] =
{
{0x2100, 0x00,}, //W 24 2100 00 2 1 ; AE
{0x1000, 0x00,}, //W 24 1000 00 2 1 ; BLC
{0x1008, 0x00,}, //W 24 1008 00 2 1 ; DPC
{0x0205, 0x00,}, //W 24 0205 00 2 1 ; AGain
{0x020E, 0x01,}, //W 24 020E 01 2 1 ; DGain
{0x020F, 0x00,}, //W 24 020F 00 2 1 ; DGain
{0x0601, 0x11,}, //W 24 0601 11 2 1 ; Test pattern
{0x0104, 0x01,}, //W 24 0104 01 2 1 ;
};
@@ -0,0 +1,73 @@
// based on demo from Himax
/*
Copyright (c) 2019 SparkFun Electronics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef HM01B0_PLATFORM_H
#define HM01B0_PLATFORM_H
#ifdef __cplusplus
extern "C"
{
#endif
#define HM01B0_PIN_D0 AM_BSP_GPIO_CAMERA_HM01B0_D0
#define HM01B0_PIN_D1 AM_BSP_GPIO_CAMERA_HM01B0_D1
#define HM01B0_PIN_D2 AM_BSP_GPIO_CAMERA_HM01B0_D2
#define HM01B0_PIN_D3 AM_BSP_GPIO_CAMERA_HM01B0_D3
#define HM01B0_PIN_D4 AM_BSP_GPIO_CAMERA_HM01B0_D4
#define HM01B0_PIN_D5 AM_BSP_GPIO_CAMERA_HM01B0_D5
#define HM01B0_PIN_D6 AM_BSP_GPIO_CAMERA_HM01B0_D6
#define HM01B0_PIN_D7 AM_BSP_GPIO_CAMERA_HM01B0_D7
#define HM01B0_PIN_VSYNC AM_BSP_GPIO_CAMERA_HM01B0_VSYNC
#define HM01B0_PIN_HSYNC AM_BSP_GPIO_CAMERA_HM01B0_HSYNC
#define HM01B0_PIN_PCLK AM_BSP_GPIO_CAMERA_HM01B0_PCLK
#define HM01B0_PIN_SCL AM_BSP_CAMERA_HM01B0_I2C_SCL_PIN
#define HM01B0_PIN_SDA AM_BSP_CAMERA_HM01B0_I2C_SDA_PIN
// Some boards do not support TRIG or INT pins
#ifdef AM_BSP_GPIO_CAMERA_HM01B0_TRIG
#define HM01B0_PIN_TRIG AM_BSP_GPIO_CAMERA_HM01B0_TRIG
#endif // AM_BSP_GPIO_CAMERA_HM01B0_TRIG
#ifdef AM_BSP_GPIO_CAMERA_HM01B0_INT
#define HM01B0_PIN_INT AM_BSP_GPIO_CAMERA_HM01B0_INT
#endif // AM_BSP_GPIO_CAMERA_HM01B0_INT
// Define AP3B's CTIMER and output pin for HM01B0 MCLK generation
#define HM01B0_MCLK_GENERATOR_MOD AM_BSP_CAMERA_HM01B0_MCLK_GEN_MOD
#define HM01B0_MCLK_GENERATOR_SEG AM_BSP_CAMERA_HM01B0_MCLK_GEN_SEG
#define HM01B0_PIN_MCLK AM_BSP_CAMERA_HM01B0_MCLK_PIN
// Deifne I2C controller and SCL(pin8)/SDA(pin9) are configured automatically.
#define HM01B0_IOM_MODE AM_HAL_IOM_I2C_MODE
#define HM01B0_IOM_MODULE AM_BSP_CAMERA_HM01B0_I2C_IOM
#define HM01B0_I2C_CLOCK_FREQ AM_HAL_IOM_100KHZ
#ifdef __cplusplus
}
#endif
#endif // HM01B0_PLATFORM_H
@@ -0,0 +1,119 @@
/*
Copyright (c) 2019 SparkFun Electronics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "lis2dh12_platform_apollo3.h"
/*
* @brief Write generic device register (platform dependent)
*
* @param handle customizable argument. In this examples is used in
* order to select the correct sensor bus handler.
* @param reg register to write
* @param bufp pointer to data to write in register reg
* @param len number of consecutive register to write
*
*/
int32_t lis2dh12_write_platform_apollo3(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
{
uint32_t retVal32 = 0;
lis2dh12_platform_apollo3_if_t* pif = (lis2dh12_platform_apollo3_if_t*)handle;
am_hal_iom_transfer_t iomTransfer = {0};
if( bufp == NULL ) { return AM_HAL_STATUS_FAIL; }
if( pif == NULL ) { return AM_HAL_STATUS_FAIL; }
if( pif->iomHandle == NULL) { return AM_HAL_STATUS_FAIL; }
// Set up transfer
iomTransfer.uPeerInfo.ui32I2CDevAddr = pif->addCS;
iomTransfer.ui32InstrLen = 1;
iomTransfer.ui32Instr = (reg | 0x80);
iomTransfer.ui32NumBytes = len;
iomTransfer.eDirection = AM_HAL_IOM_TX;
iomTransfer.pui32TxBuffer = (uint32_t*)bufp;
iomTransfer.pui32RxBuffer = NULL;
iomTransfer.bContinue = false;
if( pif->useSPI ){
// ToDo: Support SPI w/ CS assertion
}
// Send the transfer
retVal32 = am_hal_iom_blocking_transfer(pif->iomHandle, &iomTransfer);
if( pif->useSPI ){
// ToDo: Support SPI / CS de-assertion
}
if( retVal32 != AM_HAL_STATUS_SUCCESS ){ return retVal32; }
return 0;
}
/*
* @brief Read generic device register (platform dependent)
*
* @param handle customizable argument. In this examples is used in
* order to select the correct sensor bus handler.
* @param reg register to read
* @param bufp pointer to buffer that store the data read
* @param len number of consecutive register to read
*
*/
int32_t lis2dh12_read_platform_apollo3(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
{
uint32_t retVal32 = 0;
lis2dh12_platform_apollo3_if_t* pif = (lis2dh12_platform_apollo3_if_t*)handle;
am_hal_iom_transfer_t iomTransfer = {0};
if( bufp == NULL ) { return AM_HAL_STATUS_FAIL; }
if( pif == NULL ) { return AM_HAL_STATUS_FAIL; }
if( pif->iomHandle == NULL) { return AM_HAL_STATUS_FAIL; }
// Set up first transfer
iomTransfer.uPeerInfo.ui32I2CDevAddr = pif->addCS;
iomTransfer.ui32InstrLen = 1;
iomTransfer.ui32Instr = (reg | 0x80);
iomTransfer.ui32NumBytes = 0;
iomTransfer.eDirection = AM_HAL_IOM_TX;
iomTransfer.bContinue = true;
if( pif->useSPI ){
// ToDo: Support SPI w/ CS assertion
}
// Send the first transfer
retVal32 = am_hal_iom_blocking_transfer(pif->iomHandle, &iomTransfer);
if( retVal32 != AM_HAL_STATUS_SUCCESS ){ return retVal32; }
// Change direction, and add the rx buffer
iomTransfer.eDirection = AM_HAL_IOM_RX;
iomTransfer.pui32RxBuffer = (uint32_t*)bufp;
iomTransfer.ui32NumBytes = len;
iomTransfer.bContinue = false;
// Send the second transfer
retVal32 = am_hal_iom_blocking_transfer(pif->iomHandle, &iomTransfer);
if( retVal32 != AM_HAL_STATUS_SUCCESS ){ return retVal32; }
return 0;
}
@@ -0,0 +1,47 @@
/*
Copyright (c) 2019 SparkFun Electronics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _LIS2DH12_PLATFORM_APOLLO3_H_
#define _LIS2DH12_PLATFORM_APOLLO3_H_
#include "am_mcu_apollo.h"
#include "lis2dh12_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _lis2dh12_platform_apollo3_if_t {
void* iomHandle; // IO Master instance
uint8_t addCS; // I2C mode: the 7-bit I2C address (either 0x18 or 0x19 depeding on SA0 pin)
// SPI mode: the Apollo3 pad to use for chip select
bool useSPI; // Set 'true' if using SPI mode, else 'false'
}lis2dh12_platform_apollo3_if_t;
int32_t lis2dh12_write_platform_apollo3(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len);
int32_t lis2dh12_read_platform_apollo3(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len);
#ifdef __cplusplus
}
#endif
#endif // _LIS2DH12_PLATFORM_APOLLO3_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,763 @@
/*
******************************************************************************
* @file lis2dh12_reg.h
* @author Sensors Software Solution Team
* @brief This file contains all the functions prototypes for the
* lis2dh12_reg.c driver.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2018 STMicroelectronics</center></h2>
*
* 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 STMicroelectronics nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* 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.
*
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef LIS2DH12_REGS_H
#define LIS2DH12_REGS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <math.h>
/** @addtogroup LIS2DH12
* @{
*
*/
/** @defgroup LIS2DH12_sensors_common_types
* @{
*
*/
#ifndef MEMS_SHARED_TYPES
#define MEMS_SHARED_TYPES
/**
* @defgroup axisXbitXX_t
* @brief These unions are useful to represent different sensors data type.
* These unions are not need by the driver.
*
* REMOVING the unions you are compliant with:
* MISRA-C 2012 [Rule 19.2] -> " Union are not allowed "
*
* @{
*
*/
typedef union{
int16_t i16bit[3];
uint8_t u8bit[6];
} axis3bit16_t;
typedef union{
int16_t i16bit;
uint8_t u8bit[2];
} axis1bit16_t;
typedef union{
int32_t i32bit[3];
uint8_t u8bit[12];
} axis3bit32_t;
typedef union{
int32_t i32bit;
uint8_t u8bit[4];
} axis1bit32_t;
/**
* @}
*
*/
typedef struct{
uint8_t bit0 : 1;
uint8_t bit1 : 1;
uint8_t bit2 : 1;
uint8_t bit3 : 1;
uint8_t bit4 : 1;
uint8_t bit5 : 1;
uint8_t bit6 : 1;
uint8_t bit7 : 1;
} bitwise_t;
#define PROPERTY_DISABLE (0U)
#define PROPERTY_ENABLE (1U)
#endif /* MEMS_SHARED_TYPES */
/**
* @}
*
*/
/** @addtogroup LIS3MDL_Interfaces_Functions
* @brief This section provide a set of functions used to read and
* write a generic register of the device.
* MANDATORY: return 0 -> no Error.
* @{
*
*/
typedef int32_t (*lis2dh12_write_ptr)(void *, uint8_t, uint8_t*, uint16_t);
typedef int32_t (*lis2dh12_read_ptr) (void *, uint8_t, uint8_t*, uint16_t);
typedef struct {
/** Component mandatory fields **/
lis2dh12_write_ptr write_reg;
lis2dh12_read_ptr read_reg;
/** Customizable optional pointer **/
void *handle;
} lis2dh12_ctx_t;
/**
* @}
*
*/
/** @defgroup LIS2DH12_Infos
* @{
*
*/
/** I2C Device Address 8 bit format if SA0=0 -> 31 if SA0=1 -> 33 **/
#define LIS2DH12_I2C_ADD_L 0x31U
#define LIS2DH12_I2C_ADD_H 0x33U
/** Device Identification (Who am I) **/
#define LIS2DH12_ID 0x33U
/**
* @}
*
*/
#define LIS2DH12_STATUS_REG_AUX 0x07U
typedef struct {
uint8_t not_used_01 : 2;
uint8_t tda : 1;
uint8_t not_used_02 : 3;
uint8_t tor : 1;
uint8_t not_used_03 : 1;
} lis2dh12_status_reg_aux_t;
#define LIS2DH12_OUT_TEMP_L 0x0CU
#define LIS2DH12_OUT_TEMP_H 0x0DU
#define LIS2DH12_WHO_AM_I 0x0FU
#define LIS2DH12_CTRL_REG0 0x1EU
typedef struct {
uint8_t not_used_01 : 7;
uint8_t sdo_pu_disc : 1;
} lis2dh12_ctrl_reg0_t;
#define LIS2DH12_TEMP_CFG_REG 0x1FU
typedef struct {
uint8_t not_used_01 : 6;
uint8_t temp_en : 2;
} lis2dh12_temp_cfg_reg_t;
#define LIS2DH12_CTRL_REG1 0x20U
typedef struct {
uint8_t xen : 1;
uint8_t yen : 1;
uint8_t zen : 1;
uint8_t lpen : 1;
uint8_t odr : 4;
} lis2dh12_ctrl_reg1_t;
#define LIS2DH12_CTRL_REG2 0x21U
typedef struct {
uint8_t hp : 3; /* HPCLICK + HP_IA2 + HP_IA1 -> HP */
uint8_t fds : 1;
uint8_t hpcf : 2;
uint8_t hpm : 2;
} lis2dh12_ctrl_reg2_t;
#define LIS2DH12_CTRL_REG3 0x22U
typedef struct {
uint8_t not_used_01 : 1;
uint8_t i1_overrun : 1;
uint8_t i1_wtm : 1;
uint8_t not_used_02 : 1;
uint8_t i1_zyxda : 1;
uint8_t i1_ia2 : 1;
uint8_t i1_ia1 : 1;
uint8_t i1_click : 1;
} lis2dh12_ctrl_reg3_t;
#define LIS2DH12_CTRL_REG4 0x23U
typedef struct {
uint8_t sim : 1;
uint8_t st : 2;
uint8_t hr : 1;
uint8_t fs : 2;
uint8_t ble : 1;
uint8_t bdu : 1;
} lis2dh12_ctrl_reg4_t;
#define LIS2DH12_CTRL_REG5 0x24U
typedef struct {
uint8_t d4d_int2 : 1;
uint8_t lir_int2 : 1;
uint8_t d4d_int1 : 1;
uint8_t lir_int1 : 1;
uint8_t not_used_01 : 2;
uint8_t fifo_en : 1;
uint8_t boot : 1;
} lis2dh12_ctrl_reg5_t;
#define LIS2DH12_CTRL_REG6 0x25U
typedef struct {
uint8_t not_used_01 : 1;
uint8_t int_polarity : 1;
uint8_t not_used_02 : 1;
uint8_t i2_act : 1;
uint8_t i2_boot : 1;
uint8_t i2_ia2 : 1;
uint8_t i2_ia1 : 1;
uint8_t i2_click : 1;
} lis2dh12_ctrl_reg6_t;
#define LIS2DH12_REFERENCE 0x26U
#define LIS2DH12_STATUS_REG 0x27U
typedef struct {
uint8_t xda : 1;
uint8_t yda : 1;
uint8_t zda : 1;
uint8_t zyxda : 1;
uint8_t _xor : 1;
uint8_t yor : 1;
uint8_t zor : 1;
uint8_t zyxor : 1;
} lis2dh12_status_reg_t;
#define LIS2DH12_OUT_X_L 0x28U
#define LIS2DH12_OUT_X_H 0x29U
#define LIS2DH12_OUT_Y_L 0x2AU
#define LIS2DH12_OUT_Y_H 0x2BU
#define LIS2DH12_OUT_Z_L 0x2CU
#define LIS2DH12_OUT_Z_H 0x2DU
#define LIS2DH12_FIFO_CTRL_REG 0x2EU
typedef struct {
uint8_t fth : 5;
uint8_t tr : 1;
uint8_t fm : 2;
} lis2dh12_fifo_ctrl_reg_t;
#define LIS2DH12_FIFO_SRC_REG 0x2FU
typedef struct {
uint8_t fss : 5;
uint8_t empty : 1;
uint8_t ovrn_fifo : 1;
uint8_t wtm : 1;
} lis2dh12_fifo_src_reg_t;
#define LIS2DH12_INT1_CFG 0x30U
typedef struct {
uint8_t xlie : 1;
uint8_t xhie : 1;
uint8_t ylie : 1;
uint8_t yhie : 1;
uint8_t zlie : 1;
uint8_t zhie : 1;
uint8_t _6d : 1;
uint8_t aoi : 1;
} lis2dh12_int1_cfg_t;
#define LIS2DH12_INT1_SRC 0x31U
typedef struct {
uint8_t xl : 1;
uint8_t xh : 1;
uint8_t yl : 1;
uint8_t yh : 1;
uint8_t zl : 1;
uint8_t zh : 1;
uint8_t ia : 1;
uint8_t not_used_01 : 1;
} lis2dh12_int1_src_t;
#define LIS2DH12_INT1_THS 0x32U
typedef struct {
uint8_t ths : 7;
uint8_t not_used_01 : 1;
} lis2dh12_int1_ths_t;
#define LIS2DH12_INT1_DURATION 0x33U
typedef struct {
uint8_t d : 7;
uint8_t not_used_01 : 1;
} lis2dh12_int1_duration_t;
#define LIS2DH12_INT2_CFG 0x34U
typedef struct {
uint8_t xlie : 1;
uint8_t xhie : 1;
uint8_t ylie : 1;
uint8_t yhie : 1;
uint8_t zlie : 1;
uint8_t zhie : 1;
uint8_t _6d : 1;
uint8_t aoi : 1;
} lis2dh12_int2_cfg_t;
#define LIS2DH12_INT2_SRC 0x35U
typedef struct {
uint8_t xl : 1;
uint8_t xh : 1;
uint8_t yl : 1;
uint8_t yh : 1;
uint8_t zl : 1;
uint8_t zh : 1;
uint8_t ia : 1;
uint8_t not_used_01 : 1;
} lis2dh12_int2_src_t;
#define LIS2DH12_INT2_THS 0x36U
typedef struct {
uint8_t ths : 7;
uint8_t not_used_01 : 1;
} lis2dh12_int2_ths_t;
#define LIS2DH12_INT2_DURATION 0x37U
typedef struct {
uint8_t d : 7;
uint8_t not_used_01 : 1;
} lis2dh12_int2_duration_t;
#define LIS2DH12_CLICK_CFG 0x38U
typedef struct {
uint8_t xs : 1;
uint8_t xd : 1;
uint8_t ys : 1;
uint8_t yd : 1;
uint8_t zs : 1;
uint8_t zd : 1;
uint8_t not_used_01 : 2;
} lis2dh12_click_cfg_t;
#define LIS2DH12_CLICK_SRC 0x39U
typedef struct {
uint8_t x : 1;
uint8_t y : 1;
uint8_t z : 1;
uint8_t sign : 1;
uint8_t sclick : 1;
uint8_t dclick : 1;
uint8_t ia : 1;
uint8_t not_used_01 : 1;
} lis2dh12_click_src_t;
#define LIS2DH12_CLICK_THS 0x3AU
typedef struct {
uint8_t ths : 7;
uint8_t lir_click : 1;
} lis2dh12_click_ths_t;
#define LIS2DH12_TIME_LIMIT 0x3BU
typedef struct {
uint8_t tli : 7;
uint8_t not_used_01 : 1;
} lis2dh12_time_limit_t;
#define LIS2DH12_TIME_LATENCY 0x3CU
typedef struct {
uint8_t tla : 8;
} lis2dh12_time_latency_t;
#define LIS2DH12_TIME_WINDOW 0x3DU
typedef struct {
uint8_t tw : 8;
} lis2dh12_time_window_t;
#define LIS2DH12_ACT_THS 0x3EU
typedef struct {
uint8_t acth : 7;
uint8_t not_used_01 : 1;
} lis2dh12_act_ths_t;
#define LIS2DH12_ACT_DUR 0x3FU
typedef struct {
uint8_t actd : 8;
} lis2dh12_act_dur_t;
/**
* @defgroup LIS2DH12_Register_Union
* @brief This union group all the registers that has a bitfield
* description.
* This union is usefull but not need by the driver.
*
* REMOVING this union you are complient with:
* MISRA-C 2012 [Rule 19.2] -> " Union are not allowed "
*
* @{
*
*/
typedef union{
lis2dh12_status_reg_aux_t status_reg_aux;
lis2dh12_ctrl_reg0_t ctrl_reg0;
lis2dh12_temp_cfg_reg_t temp_cfg_reg;
lis2dh12_ctrl_reg1_t ctrl_reg1;
lis2dh12_ctrl_reg2_t ctrl_reg2;
lis2dh12_ctrl_reg3_t ctrl_reg3;
lis2dh12_ctrl_reg4_t ctrl_reg4;
lis2dh12_ctrl_reg5_t ctrl_reg5;
lis2dh12_ctrl_reg6_t ctrl_reg6;
lis2dh12_status_reg_t status_reg;
lis2dh12_fifo_ctrl_reg_t fifo_ctrl_reg;
lis2dh12_fifo_src_reg_t fifo_src_reg;
lis2dh12_int1_cfg_t int1_cfg;
lis2dh12_int1_src_t int1_src;
lis2dh12_int1_ths_t int1_ths;
lis2dh12_int1_duration_t int1_duration;
lis2dh12_int2_cfg_t int2_cfg;
lis2dh12_int2_src_t int2_src;
lis2dh12_int2_ths_t int2_ths;
lis2dh12_int2_duration_t int2_duration;
lis2dh12_click_cfg_t click_cfg;
lis2dh12_click_src_t click_src;
lis2dh12_click_ths_t click_ths;
lis2dh12_time_limit_t time_limit;
lis2dh12_time_latency_t time_latency;
lis2dh12_time_window_t time_window;
lis2dh12_act_ths_t act_ths;
lis2dh12_act_dur_t act_dur;
bitwise_t bitwise;
uint8_t byte;
} lis2dh12_reg_t;
/**
* @}
*
*/
int32_t lis2dh12_read_reg(lis2dh12_ctx_t *ctx, uint8_t reg, uint8_t* data,
uint16_t len);
int32_t lis2dh12_write_reg(lis2dh12_ctx_t *ctx, uint8_t reg, uint8_t* data,
uint16_t len);
extern float lis2dh12_from_fs2_hr_to_mg(int16_t lsb);
extern float lis2dh12_from_fs4_hr_to_mg(int16_t lsb);
extern float lis2dh12_from_fs8_hr_to_mg(int16_t lsb);
extern float lis2dh12_from_fs16_hr_to_mg(int16_t lsb);
extern float lis2dh12_from_lsb_hr_to_celsius(int16_t lsb);
extern float lis2dh12_from_fs2_nm_to_mg(int16_t lsb);
extern float lis2dh12_from_fs4_nm_to_mg(int16_t lsb);
extern float lis2dh12_from_fs8_nm_to_mg(int16_t lsb);
extern float lis2dh12_from_fs16_nm_to_mg(int16_t lsb);
extern float lis2dh12_from_lsb_nm_to_celsius(int16_t lsb);
extern float lis2dh12_from_fs2_lp_to_mg(int16_t lsb);
extern float lis2dh12_from_fs4_lp_to_mg(int16_t lsb);
extern float lis2dh12_from_fs8_lp_to_mg(int16_t lsb);
extern float lis2dh12_from_fs16_lp_to_mg(int16_t lsb);
extern float lis2dh12_from_lsb_lp_to_celsius(int16_t lsb);
int32_t lis2dh12_temp_status_reg_get(lis2dh12_ctx_t *ctx, uint8_t *buff);
int32_t lis2dh12_temp_data_ready_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_temp_data_ovr_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_temperature_raw_get(lis2dh12_ctx_t *ctx, uint8_t *buff);
typedef enum {
LIS2DH12_TEMP_DISABLE = 0,
LIS2DH12_TEMP_ENABLE = 3,
} lis2dh12_temp_en_t;
int32_t lis2dh12_temperature_meas_set(lis2dh12_ctx_t *ctx,
lis2dh12_temp_en_t val);
int32_t lis2dh12_temperature_meas_get(lis2dh12_ctx_t *ctx,
lis2dh12_temp_en_t *val);
typedef enum {
LIS2DH12_HR_12bit = 0,
LIS2DH12_NM_10bit = 1,
LIS2DH12_LP_8bit = 2,
} lis2dh12_op_md_t;
int32_t lis2dh12_operating_mode_set(lis2dh12_ctx_t *ctx,
lis2dh12_op_md_t val);
int32_t lis2dh12_operating_mode_get(lis2dh12_ctx_t *ctx,
lis2dh12_op_md_t *val);
typedef enum {
LIS2DH12_POWER_DOWN = 0x00,
LIS2DH12_ODR_1Hz = 0x01,
LIS2DH12_ODR_10Hz = 0x02,
LIS2DH12_ODR_25Hz = 0x03,
LIS2DH12_ODR_50Hz = 0x04,
LIS2DH12_ODR_100Hz = 0x05,
LIS2DH12_ODR_200Hz = 0x06,
LIS2DH12_ODR_400Hz = 0x07,
LIS2DH12_ODR_1kHz620_LP = 0x08,
LIS2DH12_ODR_5kHz376_LP_1kHz344_NM_HP = 0x09,
} lis2dh12_odr_t;
int32_t lis2dh12_data_rate_set(lis2dh12_ctx_t *ctx, lis2dh12_odr_t val);
int32_t lis2dh12_data_rate_get(lis2dh12_ctx_t *ctx, lis2dh12_odr_t *val);
int32_t lis2dh12_high_pass_on_outputs_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_high_pass_on_outputs_get(lis2dh12_ctx_t *ctx, uint8_t *val);
typedef enum {
LIS2DH12_AGGRESSIVE = 0,
LIS2DH12_STRONG = 1,
LIS2DH12_MEDIUM = 2,
LIS2DH12_LIGHT = 3,
} lis2dh12_hpcf_t;
int32_t lis2dh12_high_pass_bandwidth_set(lis2dh12_ctx_t *ctx,
lis2dh12_hpcf_t val);
int32_t lis2dh12_high_pass_bandwidth_get(lis2dh12_ctx_t *ctx,
lis2dh12_hpcf_t *val);
typedef enum {
LIS2DH12_NORMAL_WITH_RST = 0,
LIS2DH12_REFERENCE_MODE = 1,
LIS2DH12_NORMAL = 2,
LIS2DH12_AUTORST_ON_INT = 3,
} lis2dh12_hpm_t;
int32_t lis2dh12_high_pass_mode_set(lis2dh12_ctx_t *ctx, lis2dh12_hpm_t val);
int32_t lis2dh12_high_pass_mode_get(lis2dh12_ctx_t *ctx, lis2dh12_hpm_t *val);
typedef enum {
LIS2DH12_2g = 0,
LIS2DH12_4g = 1,
LIS2DH12_8g = 2,
LIS2DH12_16g = 3,
} lis2dh12_fs_t;
int32_t lis2dh12_full_scale_set(lis2dh12_ctx_t *ctx, lis2dh12_fs_t val);
int32_t lis2dh12_full_scale_get(lis2dh12_ctx_t *ctx, lis2dh12_fs_t *val);
int32_t lis2dh12_block_data_update_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_block_data_update_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_filter_reference_set(lis2dh12_ctx_t *ctx, uint8_t *buff);
int32_t lis2dh12_filter_reference_get(lis2dh12_ctx_t *ctx, uint8_t *buff);
int32_t lis2dh12_xl_data_ready_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_xl_data_ovr_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_acceleration_raw_get(lis2dh12_ctx_t *ctx, uint8_t *buff);
int32_t lis2dh12_device_id_get(lis2dh12_ctx_t *ctx, uint8_t *buff);
typedef enum {
LIS2DH12_ST_DISABLE = 0,
LIS2DH12_ST_POSITIVE = 1,
LIS2DH12_ST_NEGATIVE = 2,
} lis2dh12_st_t;
int32_t lis2dh12_self_test_set(lis2dh12_ctx_t *ctx, lis2dh12_st_t val);
int32_t lis2dh12_self_test_get(lis2dh12_ctx_t *ctx, lis2dh12_st_t *val);
typedef enum {
LIS2DH12_LSB_AT_LOW_ADD = 0,
LIS2DH12_MSB_AT_LOW_ADD = 1,
} lis2dh12_ble_t;
int32_t lis2dh12_data_format_set(lis2dh12_ctx_t *ctx, lis2dh12_ble_t val);
int32_t lis2dh12_data_format_get(lis2dh12_ctx_t *ctx, lis2dh12_ble_t *val);
int32_t lis2dh12_boot_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_boot_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_status_get(lis2dh12_ctx_t *ctx, lis2dh12_status_reg_t *val);
int32_t lis2dh12_int1_gen_conf_set(lis2dh12_ctx_t *ctx,
lis2dh12_int1_cfg_t *val);
int32_t lis2dh12_int1_gen_conf_get(lis2dh12_ctx_t *ctx,
lis2dh12_int1_cfg_t *val);
int32_t lis2dh12_int1_gen_source_get(lis2dh12_ctx_t *ctx,
lis2dh12_int1_src_t *val);
int32_t lis2dh12_int1_gen_threshold_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_int1_gen_threshold_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_int1_gen_duration_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_int1_gen_duration_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_int2_gen_conf_set(lis2dh12_ctx_t *ctx,
lis2dh12_int2_cfg_t *val);
int32_t lis2dh12_int2_gen_conf_get(lis2dh12_ctx_t *ctx,
lis2dh12_int2_cfg_t *val);
int32_t lis2dh12_int2_gen_source_get(lis2dh12_ctx_t *ctx,
lis2dh12_int2_src_t *val);
int32_t lis2dh12_int2_gen_threshold_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_int2_gen_threshold_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_int2_gen_duration_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_int2_gen_duration_get(lis2dh12_ctx_t *ctx, uint8_t *val);
typedef enum {
LIS2DH12_DISC_FROM_INT_GENERATOR = 0,
LIS2DH12_ON_INT1_GEN = 1,
LIS2DH12_ON_INT2_GEN = 2,
LIS2DH12_ON_TAP_GEN = 4,
LIS2DH12_ON_INT1_INT2_GEN = 3,
LIS2DH12_ON_INT1_TAP_GEN = 5,
LIS2DH12_ON_INT2_TAP_GEN = 6,
LIS2DH12_ON_INT1_INT2_TAP_GEN = 7,
} lis2dh12_hp_t;
int32_t lis2dh12_high_pass_int_conf_set(lis2dh12_ctx_t *ctx,
lis2dh12_hp_t val);
int32_t lis2dh12_high_pass_int_conf_get(lis2dh12_ctx_t *ctx,
lis2dh12_hp_t *val);
int32_t lis2dh12_pin_int1_config_set(lis2dh12_ctx_t *ctx,
lis2dh12_ctrl_reg3_t *val);
int32_t lis2dh12_pin_int1_config_get(lis2dh12_ctx_t *ctx,
lis2dh12_ctrl_reg3_t *val);
int32_t lis2dh12_int2_pin_detect_4d_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_int2_pin_detect_4d_get(lis2dh12_ctx_t *ctx, uint8_t *val);
typedef enum {
LIS2DH12_INT2_PULSED = 0,
LIS2DH12_INT2_LATCHED = 1,
} lis2dh12_lir_int2_t;
int32_t lis2dh12_int2_pin_notification_mode_set(lis2dh12_ctx_t *ctx,
lis2dh12_lir_int2_t val);
int32_t lis2dh12_int2_pin_notification_mode_get(lis2dh12_ctx_t *ctx,
lis2dh12_lir_int2_t *val);
int32_t lis2dh12_int1_pin_detect_4d_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_int1_pin_detect_4d_get(lis2dh12_ctx_t *ctx, uint8_t *val);
typedef enum {
LIS2DH12_INT1_PULSED = 0,
LIS2DH12_INT1_LATCHED = 1,
} lis2dh12_lir_int1_t;
int32_t lis2dh12_int1_pin_notification_mode_set(lis2dh12_ctx_t *ctx,
lis2dh12_lir_int1_t val);
int32_t lis2dh12_int1_pin_notification_mode_get(lis2dh12_ctx_t *ctx,
lis2dh12_lir_int1_t *val);
int32_t lis2dh12_pin_int2_config_set(lis2dh12_ctx_t *ctx,
lis2dh12_ctrl_reg6_t *val);
int32_t lis2dh12_pin_int2_config_get(lis2dh12_ctx_t *ctx,
lis2dh12_ctrl_reg6_t *val);
int32_t lis2dh12_fifo_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_fifo_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_fifo_watermark_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_fifo_watermark_get(lis2dh12_ctx_t *ctx, uint8_t *val);
typedef enum {
LIS2DH12_INT1_GEN = 0,
LIS2DH12_INT2_GEN = 1,
} lis2dh12_tr_t;
int32_t lis2dh12_fifo_trigger_event_set(lis2dh12_ctx_t *ctx,
lis2dh12_tr_t val);
int32_t lis2dh12_fifo_trigger_event_get(lis2dh12_ctx_t *ctx,
lis2dh12_tr_t *val);
typedef enum {
LIS2DH12_BYPASS_MODE = 0,
LIS2DH12_FIFO_MODE = 1,
LIS2DH12_DYNAMIC_STREAM_MODE = 2,
LIS2DH12_STREAM_TO_FIFO_MODE = 3,
} lis2dh12_fm_t;
int32_t lis2dh12_fifo_mode_set(lis2dh12_ctx_t *ctx, lis2dh12_fm_t val);
int32_t lis2dh12_fifo_mode_get(lis2dh12_ctx_t *ctx, lis2dh12_fm_t *val);
int32_t lis2dh12_fifo_status_get(lis2dh12_ctx_t *ctx,
lis2dh12_fifo_src_reg_t *val);
int32_t lis2dh12_fifo_data_level_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_fifo_empty_flag_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_fifo_ovr_flag_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_fifo_fth_flag_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_tap_conf_set(lis2dh12_ctx_t *ctx, lis2dh12_click_cfg_t *val);
int32_t lis2dh12_tap_conf_get(lis2dh12_ctx_t *ctx, lis2dh12_click_cfg_t *val);
int32_t lis2dh12_tap_source_get(lis2dh12_ctx_t *ctx,
lis2dh12_click_src_t *val);
int32_t lis2dh12_tap_threshold_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_tap_threshold_get(lis2dh12_ctx_t *ctx, uint8_t *val);
typedef enum {
LIS2DH12_TAP_PULSED = 0,
LIS2DH12_TAP_LATCHED = 1,
} lis2dh12_lir_click_t;
int32_t lis2dh12_tap_notification_mode_set(lis2dh12_ctx_t *ctx,
lis2dh12_lir_click_t val);
int32_t lis2dh12_tap_notification_mode_get(lis2dh12_ctx_t *ctx,
lis2dh12_lir_click_t *val);
int32_t lis2dh12_shock_dur_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_shock_dur_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_quiet_dur_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_quiet_dur_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_double_tap_timeout_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_double_tap_timeout_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_act_threshold_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_act_threshold_get(lis2dh12_ctx_t *ctx, uint8_t *val);
int32_t lis2dh12_act_timeout_set(lis2dh12_ctx_t *ctx, uint8_t val);
int32_t lis2dh12_act_timeout_get(lis2dh12_ctx_t *ctx, uint8_t *val);
typedef enum {
LIS2DH12_PULL_UP_DISCONNECT = 0,
LIS2DH12_PULL_UP_CONNECT = 1,
} lis2dh12_sdo_pu_disc_t;
int32_t lis2dh12_pin_sdo_sa0_mode_set(lis2dh12_ctx_t *ctx,
lis2dh12_sdo_pu_disc_t val);
int32_t lis2dh12_pin_sdo_sa0_mode_get(lis2dh12_ctx_t *ctx,
lis2dh12_sdo_pu_disc_t *val);
typedef enum {
LIS2DH12_SPI_4_WIRE = 0,
LIS2DH12_SPI_3_WIRE = 1,
} lis2dh12_sim_t;
int32_t lis2dh12_spi_mode_set(lis2dh12_ctx_t *ctx, lis2dh12_sim_t val);
int32_t lis2dh12_spi_mode_get(lis2dh12_ctx_t *ctx, lis2dh12_sim_t *val);
/**
* @}
*
*/
#ifdef __cplusplus
}
#endif
#endif /* LIS2DH12_REGS_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
@@ -0,0 +1,161 @@
on:
push:
name: generate executables
jobs:
windows:
name: windows
runs-on: windows-latest
steps:
- name: repo
uses: actions/checkout@v2.3.1
with:
path: asb
fetch-depth: 0
- name: python
uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: git
run: |
git config --global user.email "apollo3-uploader-builder@sparkfun.com"
git config --global user.name "apollo3-uploader-builder"
git config --global pull.ff only
cd asb
git status
git pull
cd ${GITHUB_WORKSPACE}
- name: install
run: |
python --version
python -m pip install --upgrade pip setuptools wheel
pip --version
pip install -r asb/requirements.txt
- name: build
run: |
cd asb
pyinstaller --onefile asb.py
cd ${GITHUB_WORKSPACE}
- name: copy
run: |
Remove-Item -Recurse -Force asb\dist\windows
mkdir asb\dist\windows
Move-Item -Path asb\dist\asb.exe -Destination asb\dist\windows\asb.exe
- name: commit
run: |
cd asb
git add dist\windows\*
git commit -m "generated windows executable"
git push
cd ${GITHUB_WORKSPACE}
linux:
name: linux
needs: windows
runs-on: ubuntu-latest
steps:
- name: repo
uses: actions/checkout@v2.3.1
with:
path: asb
fetch-depth: 0
- name: python
uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: git
run: |
git config --global user.email "apollo3-uploader-builder@sparkfun.com"
git config --global user.name "apollo3-uploader-builder"
git config --global pull.ff only
cd asb
git pull
cd ${GITHUB_WORKSPACE}
- name: install
run: |
python --version
python -m pip install --upgrade pip setuptools wheel
pip --version
pip install -r asb/requirements.txt
- name: build
run: |
cd asb
pyinstaller --onefile asb.py
cd ${GITHUB_WORKSPACE}
- name: copy
run: |
rm -rf ./asb/dist/linux
mkdir -p ./asb/dist/linux
mv ./asb/dist/asb ./asb/dist/linux/asb
- name: commit
run: |
cd ./asb
git add ./dist/linux/*
git commit -m "generated linux executable"
git push
cd ${GITHUB_WORKSPACE}
macosx:
name: macosx
needs: linux
runs-on: macos-latest
steps:
- name: repo
uses: actions/checkout@v2.3.1
with:
path: asb
fetch-depth: 0
- name: python
uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: git
run: |
git config --global user.email "apollo3-uploader-builder@sparkfun.com"
git config --global user.name "apollo3-uploader-builder"
git config --global pull.ff only
cd asb
git pull
cd ${GITHUB_WORKSPACE}
- name: install
run: |
python --version
python -m pip install --upgrade pip setuptools wheel
pip --version
pip install -r asb/requirements.txt
- name: build
run: |
cd asb
pyinstaller --onefile asb.py
cd ${GITHUB_WORKSPACE}
- name: copy
run: |
rm -rf ./asb/dist/macosx
mkdir -p ./asb/dist/macosx
mv ./asb/dist/asb ./asb/dist/macosx/asb
- name: commit
run: |
cd ./asb
git add ./dist/macosx/*
git commit -m "generated macosx executable"
git push
cd ${GITHUB_WORKSPACE}
@@ -0,0 +1,127 @@
# macosx
.DS_Store
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
@@ -0,0 +1,3 @@
![generate executables](https://github.com/sparkfun/Apollo3_Uploader_ASB/workflows/generate%20executables/badge.svg)
# Apollo3 Uploader - Ambiq Secure Bootloader (SVL)
@@ -0,0 +1,527 @@
#!/usr/bin/env python3
# Utility functioins
import sys
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
import array
import hashlib
import hmac
import os
import binascii
ivVal0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
FLASH_PAGE_SIZE = 0x2000 # 8K
MAX_DOWNLOAD_SIZE = 0x48000 # 288K
AM_SECBOOT_DEFAULT_NONSECURE_MAIN = 0xC000
AM_SECBOOT_AESCBC_BLOCK_SIZE_WORDS = 4
AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES = 4*AM_SECBOOT_AESCBC_BLOCK_SIZE_WORDS
AM_SECBOOT_MIN_KEYIDX_INFO0 = 8 ## KeyIdx 8 - 15
AM_SECBOOT_MAX_KEYIDX_INFO0 = 15
AM_SECBOOT_MIN_KEYIDX_INFO1 = 0 ## KeyIdx 0 - 7
AM_SECBOOT_MAX_KEYIDX_INFO1 = 7
AM_SECBOOT_KEYIDX_BYTES = 16
# Encryption Algorithm
AM_SECBOOT_ENC_ALGO_NONE = 0
AM_SECBOOT_ENC_ALGO_AES128 = 1
AM_SECBOOT_ENC_ALGO_MAX = AM_SECBOOT_ENC_ALGO_AES128
# String constants
helpEncAlgo = 'Encryption Algo? (0(default) = none, 1 = AES128)'
# Authentication Algorithm
AM_SECBOOT_AUTH_ALGO_NONE = 0
AM_SECBOOT_AUTH_ALGO_SHA256HMAC = 1
AM_SECBOOT_AUTH_ALGO_MAX = AM_SECBOOT_AUTH_ALGO_SHA256HMAC
# String constants
helpAuthAlgo = 'Authentication Algo? (0(default) = none, 1 = SHA256)'
FLASH_INVALID = 0xFFFFFFFF
# KeyWrap Mode
AM_SECBOOT_KEYWRAP_NONE = 0
AM_SECBOOT_KEYWRAP_XOR = 1
AM_SECBOOT_KEYWRAP_AES128 = 2
AM_SECBOOT_KEYWRAP_MAX = AM_SECBOOT_KEYWRAP_AES128
#******************************************************************************
#
# Magic Numbers
#
#******************************************************************************
AM_IMAGE_MAGIC_MAIN = 0xC0
AM_IMAGE_MAGIC_CHILD = 0xCC
AM_IMAGE_MAGIC_NONSECURE = 0xCB
AM_IMAGE_MAGIC_INFO0 = 0xCF
# Dummy for creating images for customer - not understood by SBL
# This could be any value from the definition:
# #define AM_IMAGE_MAGIC_CUST(x) ((((x) & 0xF0) == 0xC0) && ((x) != 0xC0) && ((x) != 0xCC) && ((x) != 0xCB) && ((x) != 0xCF))
AM_IMAGE_MAGIC_CUSTPATCH = 0xC1
#******************************************************************************
#
# Image Types
#
#******************************************************************************
AM_SECBOOT_WIRED_IMAGETYPE_SBL = 0
AM_SECBOOT_WIRED_IMAGETYPE_AM3P = 1
AM_SECBOOT_WIRED_IMAGETYPE_PATCH = 2
AM_SECBOOT_WIRED_IMAGETYPE_MAIN = 3
AM_SECBOOT_WIRED_IMAGETYPE_CHILD = 4
AM_SECBOOT_WIRED_IMAGETYPE_CUSTPATCH = 5
AM_SECBOOT_WIRED_IMAGETYPE_NONSECURE = 6
AM_SECBOOT_WIRED_IMAGETYPE_INFO0 = 7
AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA = 32
AM_SECBOOT_WIRED_IMAGETYPE_INVALID = 0xFF
#******************************************************************************
#
# Wired Message Types
#
#******************************************************************************
AM_SECBOOT_WIRED_MSGTYPE_HELLO = 0
AM_SECBOOT_WIRED_MSGTYPE_STATUS = 1
AM_SECBOOT_WIRED_MSGTYPE_OTADESC = 2
AM_SECBOOT_WIRED_MSGTYPE_UPDATE = 3
AM_SECBOOT_WIRED_MSGTYPE_ABORT = 4
AM_SECBOOT_WIRED_MSGTYPE_RECOVER = 5
AM_SECBOOT_WIRED_MSGTYPE_RESET = 6
AM_SECBOOT_WIRED_MSGTYPE_ACK = 7
AM_SECBOOT_WIRED_MSGTYPE_DATA = 8
#******************************************************************************
#
# Wired Message ACK Status
#
#******************************************************************************
AM_SECBOOT_WIRED_ACK_STATUS_SUCCESS = 0
AM_SECBOOT_WIRED_ACK_STATUS_FAILURE = 1
AM_SECBOOT_WIRED_ACK_STATUS_INVALID_INFO0 = 2
AM_SECBOOT_WIRED_ACK_STATUS_CRC = 3
AM_SECBOOT_WIRED_ACK_STATUS_SEC = 4
AM_SECBOOT_WIRED_ACK_STATUS_MSG_TOO_BIG = 5
AM_SECBOOT_WIRED_ACK_STATUS_UNKNOWN_MSGTYPE = 6
AM_SECBOOT_WIRED_ACK_STATUS_INVALID_ADDR = 7
AM_SECBOOT_WIRED_ACK_STATUS_INVALID_OPERATION = 8
AM_SECBOOT_WIRED_ACK_STATUS_INVALID_PARAM = 9
AM_SECBOOT_WIRED_ACK_STATUS_SEQ = 10
AM_SECBOOT_WIRED_ACK_STATUS_TOO_MUCH_DATA = 11
#******************************************************************************
#
# Definitions related to Image Headers
#
#******************************************************************************
AM_HMAC_SIG_SIZE = 32
AM_KEK_SIZE = 16
AM_CRC_SIZE = 4
AM_MAX_UART_MSG_SIZE = 8192 # 8K buffer in SBL
# Wiredupdate Image Header
AM_WU_IMAGEHDR_OFFSET_SIG = 16
AM_WU_IMAGEHDR_OFFSET_IV = 48
AM_WU_IMAGEHDR_OFFSET_KEK = 64
AM_WU_IMAGEHDR_OFFSET_IMAGETYPE = (AM_WU_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE)
AM_WU_IMAGEHDR_OFFSET_OPTIONS = (AM_WU_IMAGEHDR_OFFSET_IMAGETYPE + 1)
AM_WU_IMAGEHDR_OFFSET_KEY = (AM_WU_IMAGEHDR_OFFSET_IMAGETYPE + 4)
AM_WU_IMAGEHDR_OFFSET_ADDR = (AM_WU_IMAGEHDR_OFFSET_KEY + 4)
AM_WU_IMAGEHDR_OFFSET_SIZE = (AM_WU_IMAGEHDR_OFFSET_ADDR + 4)
AM_WU_IMAGEHDR_START_HMAC = (AM_WU_IMAGEHDR_OFFSET_SIG + AM_HMAC_SIG_SIZE)
AM_WU_IMAGEHDR_START_ENCRYPT = (AM_WU_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE)
AM_WU_IMAGEHDR_SIZE = (AM_WU_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE + 16)
# Image Header
AM_IMAGEHDR_SIZE_MAIN = 256
AM_IMAGEHDR_SIZE_AUX = (112 + AM_KEK_SIZE)
AM_IMAGEHDR_OFFSET_CRC = 4
AM_IMAGEHDR_OFFSET_SIG = 16
AM_IMAGEHDR_OFFSET_IV = 48
AM_IMAGEHDR_OFFSET_KEK = 64
AM_IMAGEHDR_OFFSET_SIGCLR = (AM_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE)
AM_IMAGEHDR_START_CRC = (AM_IMAGEHDR_OFFSET_CRC + AM_CRC_SIZE)
AM_IMAGEHDR_START_HMAC_INST = (AM_IMAGEHDR_OFFSET_SIG + AM_HMAC_SIG_SIZE)
AM_IMAGEHDR_START_ENCRYPT = (AM_IMAGEHDR_OFFSET_KEK + AM_KEK_SIZE)
AM_IMAGEHDR_START_HMAC = (AM_IMAGEHDR_OFFSET_SIGCLR + AM_HMAC_SIG_SIZE)
AM_IMAGEHDR_OFFSET_ADDR = AM_IMAGEHDR_START_HMAC
AM_IMAGEHDR_OFFSET_VERKEY = (AM_IMAGEHDR_OFFSET_ADDR + 4)
AM_IMAGEHDR_OFFSET_CHILDPTR = (AM_IMAGEHDR_OFFSET_VERKEY + 4)
# Recover message
AM_WU_RECOVERY_HDR_SIZE = 44
AM_WU_RECOVERY_HDR_OFFSET_CUSTID = 8
AM_WU_RECOVERY_HDR_OFFSET_RECKEY = (AM_WU_RECOVERY_HDR_OFFSET_CUSTID + 4)
AM_WU_RECOVERY_HDR_OFFSET_NONCE = (AM_WU_RECOVERY_HDR_OFFSET_RECKEY + 16)
AM_WU_RECOVERY_HDR_OFFSET_RECBLOB = (AM_WU_RECOVERY_HDR_OFFSET_NONCE + 16)
#******************************************************************************
#
# INFOSPACE related definitions
#
#******************************************************************************
AM_SECBOOT_INFO0_SIGN_PROGRAMMED0 = 0x48EAAD88
AM_SECBOOT_INFO0_SIGN_PROGRAMMED1 = 0xC9705737
AM_SECBOOT_INFO0_SIGN_PROGRAMMED2 = 0x0A6B8458
AM_SECBOOT_INFO0_SIGN_PROGRAMMED3 = 0xE41A9D74
AM_SECBOOT_INFO0_SIGN_UINIT0 = 0x5B75A5FA
AM_SECBOOT_INFO0_SIGN_UINIT1 = 0x7B9C8674
AM_SECBOOT_INFO0_SIGN_UINIT2 = 0x869A96FE
AM_SECBOOT_INFO0_SIGN_UINIT3 = 0xAEC90860
INFO_SIZE_BYTES = (8 * 1024)
INFO_MAX_AUTH_KEY_WORDS = 32
INFO_MAX_ENC_KEY_WORDS = 32
INFO_MAX_AUTH_KEYS = (INFO_MAX_AUTH_KEY_WORDS*4//AM_SECBOOT_KEYIDX_BYTES)
INFO_MAX_ENC_KEYS = (INFO_MAX_ENC_KEY_WORDS*4//AM_SECBOOT_KEYIDX_BYTES)
INFO0_SIGNATURE0_O = 0x00000000
INFO0_SIGNATURE1_O = 0x00000004
INFO0_SIGNATURE2_O = 0x00000008
INFO0_SIGNATURE3_O = 0x0000000c
INFO0_SECURITY_O = 0x00000010
INFO0_CUSTOMER_TRIM_O = 0x00000014
INFO0_CUSTOMER_TRIM2_O = 0x00000018
INFO0_SECURITY_OVR_O = 0x00000020
INFO0_SECURITY_WIRED_CFG_O = 0x00000024
INFO0_SECURITY_WIRED_IFC_CFG0_O = 0x00000028
INFO0_SECURITY_WIRED_IFC_CFG1_O = 0x0000002C
INFO0_SECURITY_WIRED_IFC_CFG2_O = 0x00000030
INFO0_SECURITY_WIRED_IFC_CFG3_O = 0x00000034
INFO0_SECURITY_WIRED_IFC_CFG4_O = 0x00000038
INFO0_SECURITY_WIRED_IFC_CFG5_O = 0x0000003C
INFO0_SECURITY_VERSION_O = 0x00000040
INFO0_SECURITY_SRAM_RESV_O = 0x00000050
AM_REG_INFO0_SECURITY_SRAM_RESV_SRAM_RESV_M = 0x0000FFFF
INFO0_WRITE_PROTECT_L_O = 0x000001f8
INFO0_WRITE_PROTECT_H_O = 0x000001fc
INFO0_COPY_PROTECT_L_O = 0x00000200
INFO0_COPY_PROTECT_H_O = 0x00000204
INFO0_WRITE_PROTECT_SBL_L_O = 0x000009f8
INFO0_WRITE_PROTECT_SBL_H_O = 0x000009fc
INFO0_COPY_PROTECT_SBL_L_O = 0x00000A00
INFO0_COPY_PROTECT_SBL_H_O = 0x00000A04
INFO0_MAIN_PTR1_O = 0x00000C00
INFO0_MAIN_PTR2_O = 0x00000C04
INFO0_KREVTRACK_O = 0x00000C08
INFO0_AREVTRACK_O = 0x00000C0C
INFO0_MAIN_CNT0_O = 0x00000FF8
INFO0_MAIN_CNT1_O = 0x00000FFC
INFO0_CUST_KEK_W0_O = 0x00001800
INFO0_CUST_KEK_W1_O = 0x00001804
INFO0_CUST_KEK_W2_O = 0x00001808
INFO0_CUST_KEK_W3_O = 0x0000180c
INFO0_CUST_KEK_W4_O = 0x00001810
INFO0_CUST_KEK_W5_O = 0x00001814
INFO0_CUST_KEK_W6_O = 0x00001818
INFO0_CUST_KEK_W7_O = 0x0000181c
INFO0_CUST_KEK_W8_O = 0x00001820
INFO0_CUST_KEK_W9_O = 0x00001824
INFO0_CUST_KEK_W10_O = 0x00001828
INFO0_CUST_KEK_W11_O = 0x0000182c
INFO0_CUST_KEK_W12_O = 0x00001830
INFO0_CUST_KEK_W13_O = 0x00001834
INFO0_CUST_KEK_W14_O = 0x00001838
INFO0_CUST_KEK_W15_O = 0x0000183c
INFO0_CUST_KEK_W16_O = 0x00001840
INFO0_CUST_KEK_W17_O = 0x00001844
INFO0_CUST_KEK_W18_O = 0x00001848
INFO0_CUST_KEK_W19_O = 0x0000184c
INFO0_CUST_KEK_W20_O = 0x00001850
INFO0_CUST_KEK_W21_O = 0x00001854
INFO0_CUST_KEK_W22_O = 0x00001858
INFO0_CUST_KEK_W23_O = 0x0000185c
INFO0_CUST_KEK_W24_O = 0x00001860
INFO0_CUST_KEK_W25_O = 0x00001864
INFO0_CUST_KEK_W26_O = 0x00001868
INFO0_CUST_KEK_W27_O = 0x0000186c
INFO0_CUST_KEK_W28_O = 0x00001870
INFO0_CUST_KEK_W29_O = 0x00001874
INFO0_CUST_KEK_W30_O = 0x00001878
INFO0_CUST_KEK_W31_O = 0x0000187c
INFO0_CUST_AUTH_W0_O = 0x00001880
INFO0_CUST_AUTH_W1_O = 0x00001884
INFO0_CUST_AUTH_W2_O = 0x00001888
INFO0_CUST_AUTH_W3_O = 0x0000188c
INFO0_CUST_AUTH_W4_O = 0x00001890
INFO0_CUST_AUTH_W5_O = 0x00001894
INFO0_CUST_AUTH_W6_O = 0x00001898
INFO0_CUST_AUTH_W7_O = 0x0000189c
INFO0_CUST_AUTH_W8_O = 0x000018a0
INFO0_CUST_AUTH_W9_O = 0x000018a4
INFO0_CUST_AUTH_W10_O = 0x000018a8
INFO0_CUST_AUTH_W11_O = 0x000018ac
INFO0_CUST_AUTH_W12_O = 0x000018b0
INFO0_CUST_AUTH_W13_O = 0x000018b4
INFO0_CUST_AUTH_W14_O = 0x000018b8
INFO0_CUST_AUTH_W15_O = 0x000018bc
INFO0_CUST_AUTH_W16_O = 0x000018c0
INFO0_CUST_AUTH_W17_O = 0x000018c4
INFO0_CUST_AUTH_W18_O = 0x000018c8
INFO0_CUST_AUTH_W19_O = 0x000018cc
INFO0_CUST_AUTH_W20_O = 0x000018d0
INFO0_CUST_AUTH_W21_O = 0x000018d4
INFO0_CUST_AUTH_W22_O = 0x000018d8
INFO0_CUST_AUTH_W23_O = 0x000018dc
INFO0_CUST_AUTH_W24_O = 0x000018e0
INFO0_CUST_AUTH_W25_O = 0x000018e4
INFO0_CUST_AUTH_W26_O = 0x000018e8
INFO0_CUST_AUTH_W27_O = 0x000018ec
INFO0_CUST_AUTH_W28_O = 0x000018f0
INFO0_CUST_AUTH_W29_O = 0x000018f4
INFO0_CUST_AUTH_W30_O = 0x000018f8
INFO0_CUST_AUTH_W31_O = 0x000018fc
INFO0_CUST_PUBKEY_W0_O = 0x00001900
INFO0_CUST_PUBKEY_W1_O = 0x00001904
INFO0_CUST_PUBKEY_W2_O = 0x00001908
INFO0_CUST_PUBKEY_W3_O = 0x0000190c
INFO0_CUST_PUBKEY_W4_O = 0x00001910
INFO0_CUST_PUBKEY_W5_O = 0x00001914
INFO0_CUST_PUBKEY_W6_O = 0x00001918
INFO0_CUST_PUBKEY_W7_O = 0x0000191c
INFO0_CUST_PUBKEY_W8_O = 0x00001920
INFO0_CUST_PUBKEY_W9_O = 0x00001924
INFO0_CUST_PUBKEY_W10_O = 0x00001928
INFO0_CUST_PUBKEY_W11_O = 0x0000192c
INFO0_CUST_PUBKEY_W12_O = 0x00001930
INFO0_CUST_PUBKEY_W13_O = 0x00001934
INFO0_CUST_PUBKEY_W14_O = 0x00001938
INFO0_CUST_PUBKEY_W15_O = 0x0000193c
INFO0_CUST_PUBKEY_W16_O = 0x00001940
INFO0_CUST_PUBKEY_W17_O = 0x00001944
INFO0_CUST_PUBKEY_W18_O = 0x00001948
INFO0_CUST_PUBKEY_W19_O = 0x0000194c
INFO0_CUST_PUBKEY_W20_O = 0x00001950
INFO0_CUST_PUBKEY_W21_O = 0x00001954
INFO0_CUST_PUBKEY_W22_O = 0x00001958
INFO0_CUST_PUBKEY_W23_O = 0x0000195c
INFO0_CUST_PUBKEY_W24_O = 0x00001960
INFO0_CUST_PUBKEY_W25_O = 0x00001964
INFO0_CUST_PUBKEY_W26_O = 0x00001968
INFO0_CUST_PUBKEY_W27_O = 0x0000196c
INFO0_CUST_PUBKEY_W28_O = 0x00001970
INFO0_CUST_PUBKEY_W29_O = 0x00001974
INFO0_CUST_PUBKEY_W30_O = 0x00001978
INFO0_CUST_PUBKEY_W31_O = 0x0000197c
INFO0_CUST_PUBKEY_W32_O = 0x00001980
INFO0_CUST_PUBKEY_W33_O = 0x00001984
INFO0_CUST_PUBKEY_W34_O = 0x00001988
INFO0_CUST_PUBKEY_W35_O = 0x0000198c
INFO0_CUST_PUBKEY_W36_O = 0x00001990
INFO0_CUST_PUBKEY_W37_O = 0x00001994
INFO0_CUST_PUBKEY_W38_O = 0x00001998
INFO0_CUST_PUBKEY_W39_O = 0x0000199c
INFO0_CUST_PUBKEY_W40_O = 0x000019a0
INFO0_CUST_PUBKEY_W41_O = 0x000019a4
INFO0_CUST_PUBKEY_W42_O = 0x000019a8
INFO0_CUST_PUBKEY_W43_O = 0x000019ac
INFO0_CUST_PUBKEY_W44_O = 0x000019b0
INFO0_CUST_PUBKEY_W45_O = 0x000019b4
INFO0_CUST_PUBKEY_W46_O = 0x000019b8
INFO0_CUST_PUBKEY_W47_O = 0x000019bc
INFO0_CUST_PUBKEY_W48_O = 0x000019c0
INFO0_CUST_PUBKEY_W49_O = 0x000019c4
INFO0_CUST_PUBKEY_W50_O = 0x000019c8
INFO0_CUST_PUBKEY_W51_O = 0x000019cc
INFO0_CUST_PUBKEY_W52_O = 0x000019d0
INFO0_CUST_PUBKEY_W53_O = 0x000019d4
INFO0_CUST_PUBKEY_W54_O = 0x000019d8
INFO0_CUST_PUBKEY_W55_O = 0x000019dc
INFO0_CUST_PUBKEY_W56_O = 0x000019e0
INFO0_CUST_PUBKEY_W57_O = 0x000019e4
INFO0_CUST_PUBKEY_W58_O = 0x000019e8
INFO0_CUST_PUBKEY_W59_O = 0x000019ec
INFO0_CUST_PUBKEY_W60_O = 0x000019f0
INFO0_CUST_PUBKEY_W61_O = 0x000019f4
INFO0_CUST_PUBKEY_W62_O = 0x000019f8
INFO0_CUST_PUBKEY_W63_O = 0x000019fc
INFO0_CUSTOMER_KEY0_O = 0x00001a00
INFO0_CUSTOMER_KEY1_O = 0x00001a04
INFO0_CUSTOMER_KEY2_O = 0x00001a08
INFO0_CUSTOMER_KEY3_O = 0x00001a0c
INFO0_CUST_PUBHASH_W0_O = 0x00001a10
INFO0_CUST_PUBHASH_W1_O = 0x00001a14
INFO0_CUST_PUBHASH_W2_O = 0x00001a18
INFO0_CUST_PUBHASH_W3_O = 0x00001a1c
#******************************************************************************
#
# CRC using ethernet poly, as used by Corvette hardware for validation
#
#******************************************************************************
def crc32(L):
return (binascii.crc32(L) & 0xFFFFFFFF)
#******************************************************************************
#
# Pad the text to the block_size. bZeroPad determines how to handle text which
# is already multiple of block_size
#
#******************************************************************************
def pad_to_block_size(text, block_size, bZeroPad):
text_length = len(text)
amount_to_pad = block_size - (text_length % block_size)
if (amount_to_pad == block_size):
if (bZeroPad == 0):
amount_to_pad = 0
for i in range(0, amount_to_pad, 1):
text += bytes(chr(amount_to_pad), 'ascii')
return text
#******************************************************************************
#
# AES CBC encryption
#
#******************************************************************************
def encrypt_app_aes(cleartext, encKey, iv):
key = array.array('B', encKey).tostring()
ivVal = array.array('B', iv).tostring()
plaintext = array.array('B', cleartext).tostring()
encryption_suite = AES.new(key, AES.MODE_CBC, ivVal)
cipher_text = encryption_suite.encrypt(plaintext)
return cipher_text
#******************************************************************************
#
# AES 128 CBC encryption
#
#******************************************************************************
def encrypt_app_aes128(cleartext, encKey, iv):
key = array.array('B', encKey).tostring()
ivVal = array.array('B', iv).tostring()
plaintext = array.array('B', cleartext).tostring()
encryption_suite = AES.new(key, AES.MODE_CBC, ivVal)
cipher_text = encryption_suite.encrypt(plaintext)
return cipher_text
#******************************************************************************
#
# SHA256 HMAC
#
#******************************************************************************
def compute_hmac(key, data):
sig = hmac.new(array.array('B', key).tostring(), array.array('B', data).tostring(), hashlib.sha256).digest()
return sig
#******************************************************************************
#
# RSA PKCS1_v1_5 sign
#
#******************************************************************************
def compute_rsa_sign(prvKeyFile, data):
key = open(prvKeyFile, "r").read()
rsakey = RSA.importKey(key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(bytes(data))
sign = signer.sign(digest)
return sign
#******************************************************************************
#
# RSA PKCS1_v1_5 sign verification
#
#******************************************************************************
def verify_rsa_sign(pubKeyFile, data, sign):
key = open(pubKeyFile, "r").read()
rsakey = RSA.importKey(key)
#print(hex(rsakey.n))
verifier = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(bytes(data))
return verifier.verify(digest, sign)
#******************************************************************************
#
# Fill one word in bytearray
#
#******************************************************************************
def fill_word(barray, offset, w):
barray[offset + 0] = (w >> 0) & 0x000000ff;
barray[offset + 1] = (w >> 8) & 0x000000ff;
barray[offset + 2] = (w >> 16) & 0x000000ff;
barray[offset + 3] = (w >> 24) & 0x000000ff;
#******************************************************************************
#
# Turn a 32-bit number into a series of bytes for transmission.
#
# This command will split a 32-bit integer into an array of bytes, ordered
# LSB-first for transmission over the UART.
#
#******************************************************************************
def int_to_bytes(n):
A = [n & 0xFF,
(n >> 8) & 0xFF,
(n >> 16) & 0xFF,
(n >> 24) & 0xFF]
return A
#******************************************************************************
#
# Extract a word from a byte array
#
#******************************************************************************
def word_from_bytes(B, n):
return (B[n] + (B[n + 1] << 8) + (B[n + 2] << 16) + (B[n + 3] << 24))
#******************************************************************************
#
# automatically figure out the integer format (base 10 or 16)
#
#******************************************************************************
def auto_int(x):
return int(x, 0)
#******************************************************************************
#
# User controllable Prints control
#
#******************************************************************************
# Defined print levels
AM_PRINT_LEVEL_MIN = 0
AM_PRINT_LEVEL_NONE = AM_PRINT_LEVEL_MIN
AM_PRINT_LEVEL_ERROR = 1
AM_PRINT_LEVEL_INFO = 2
AM_PRINT_LEVEL_VERBOSE = 4
AM_PRINT_LEVEL_DEBUG = 5
AM_PRINT_LEVEL_MAX = AM_PRINT_LEVEL_DEBUG
# Global variable to control the prints
AM_PRINT_VERBOSITY = AM_PRINT_LEVEL_INFO
helpPrintLevel = 'Set Log Level (0: None), (1: Error), (2: INFO), (4: Verbose), (5: Debug) [Default = Info]'
def am_set_print_level(level):
global AM_PRINT_VERBOSITY
AM_PRINT_VERBOSITY = level
def am_print(*args, level=AM_PRINT_LEVEL_INFO, **kwargs):
global AM_PRINT_VERBOSITY
if (AM_PRINT_VERBOSITY >= level):
print(*args, **kwargs)
@@ -0,0 +1,899 @@
#!/usr/bin/env python3
# Combination of the three steps to take an 'application.bin' file and run it on a SparkFun Artemis module
# Information:
# This script performs the three main tasks:
# 1. Convert 'application.bin' to an OTA update blob
# 2. Convert the OTA blob into a wired update blob
# 3. Push the wired update blob into the Artemis module
import argparse
import sys
from Crypto.Cipher import AES
import array
import hashlib
import hmac
import os
import binascii
import serial
import serial.tools.list_ports as list_ports
import time
# from sf_am_defines import *
from sys import exit
from am_defines import *
from keys_info import keyTblAes, keyTblHmac, minAesKeyIdx, maxAesKeyIdx, minHmacKeyIdx, maxHmacKeyIdx, INFO_KEY, FLASH_KEY
#******************************************************************************
#
# Global Variables
#
#******************************************************************************
loadTries = 0 #If we fail, try again. Tracks the number of tries we've attempted
loadSuccess = False
blob2wiredfile = ''
uploadbinfile = ''
#******************************************************************************
#
# Generate the image blob as per command line parameters
#
#******************************************************************************
def bin2blob_process(loadaddress, appFile, magicNum, crcI, crcB, authI, authB, protection, authKeyIdx, output, encKeyIdx, version, erasePrev, child0, child1, authalgo, encalgo):
global blob2wiredfile
app_binarray = bytearray()
# Open the file, and read it into an array of integers.
with appFile as f_app:
app_binarray.extend(f_app.read())
f_app.close()
encVal = 0
if (encalgo != 0):
encVal = 1
if ((encKeyIdx < minAesKeyIdx) or (encKeyIdx > maxAesKeyIdx)):
am_print("Invalid encKey Idx ", encKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
if (encalgo == 2):
if (encKeyIdx & 0x1):
am_print("Invalid encKey Idx ", encKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
keySize = 32
else:
keySize = 16
if (authalgo != 0):
if ((authKeyIdx < minHmacKeyIdx) or (authKeyIdx > maxHmacKeyIdx) or (authKeyIdx & 0x1)):
am_print("Invalid authKey Idx ", authKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
if (magicNum == AM_IMAGE_MAGIC_MAIN):
hdr_length = AM_IMAGEHDR_SIZE_MAIN; #fixed header length
elif ((magicNum == AM_IMAGE_MAGIC_CHILD) or (magicNum == AM_IMAGE_MAGIC_CUSTPATCH) or (magicNum == AM_IMAGE_MAGIC_NONSECURE) or (magicNum == AM_IMAGE_MAGIC_INFO0)):
hdr_length = AM_IMAGEHDR_SIZE_AUX; #fixed header length
else:
am_print("magic number", hex(magicNum), " not supported", level=AM_PRINT_LEVEL_ERROR)
return
am_print("Header Size = ", hex(hdr_length))
#generate mutable byte array for the header
hdr_binarray = bytearray([0x00]*hdr_length);
orig_app_length = (len(app_binarray))
am_print("original app_size ",hex(orig_app_length), "(",orig_app_length,")")
am_print("load_address ",hex(loadaddress), "(",loadaddress,")")
if (loadaddress & 0x3):
am_print("load address needs to be word aligned", level=AM_PRINT_LEVEL_ERROR)
return
if (magicNum == AM_IMAGE_MAGIC_INFO0):
if (orig_app_length & 0x3):
am_print("INFO0 blob length needs to be multiple of 4", level=AM_PRINT_LEVEL_ERROR)
return
if ((loadaddress + orig_app_length) > INFO_SIZE_BYTES):
am_print("INFO0 Offset and length exceed size", level=AM_PRINT_LEVEL_ERROR)
return
if (encVal == 1):
block_size = AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES
app_binarray = pad_to_block_size(app_binarray, block_size, 1)
else:
# Add Padding
app_binarray = pad_to_block_size(app_binarray, 4, 0)
app_length = (len(app_binarray))
am_print("app_size ",hex(app_length), "(",app_length,")")
# Create Image blobs
# w0
blobLen = hdr_length + app_length
w0 = (magicNum << 24) | ((encVal & 0x1) << 23) | blobLen
am_print("w0 =", hex(w0))
fill_word(hdr_binarray, 0, w0)
# w2
securityVal = ((authI << 1) | crcI) << 4 | (authB << 1) | crcB
am_print("Security Value ", hex(securityVal))
w2 = ((securityVal << 24) & 0xff000000) | ((authalgo) & 0xf) | ((authKeyIdx << 4) & 0xf0) | ((encalgo << 8) & 0xf00) | ((encKeyIdx << 12) & 0xf000)
fill_word(hdr_binarray, 8, w2)
am_print("w2 = ",hex(w2))
if (magicNum == AM_IMAGE_MAGIC_INFO0):
# Insert the INFO0 size and offset
addrWord = ((orig_app_length>>2) << 16) | ((loadaddress>>2) & 0xFFFF)
versionKeyWord = INFO_KEY
else:
# Insert the application binary load address.
addrWord = loadaddress | (protection & 0x3)
# Initialize versionKeyWord
versionKeyWord = (version & 0x7FFF) | ((erasePrev & 0x1) << 15)
am_print("addrWord = ",hex(addrWord))
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_ADDR, addrWord)
am_print("versionKeyWord = ",hex(versionKeyWord))
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_VERKEY, versionKeyWord)
# Initialize child (Child Ptr/ Feature key)
am_print("child0/feature = ",hex(child0))
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_CHILDPTR, child0)
am_print("child1 = ",hex(child1))
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_CHILDPTR + 4, child1)
authKeyIdx = authKeyIdx - minHmacKeyIdx
if (authB != 0): # Authentication needed
am_print("Boot Authentication Enabled")
# am_print("Key used for HMAC")
# am_print([hex(keyTblHmac[authKeyIdx*AM_SECBOOT_KEYIDX_BYTES + n]) for n in range (0, AM_HMAC_SIG_SIZE)])
# Initialize the clear image HMAC
sigClr = compute_hmac(keyTblHmac[authKeyIdx*AM_SECBOOT_KEYIDX_BYTES:(authKeyIdx*AM_SECBOOT_KEYIDX_BYTES+AM_HMAC_SIG_SIZE)], (hdr_binarray[AM_IMAGEHDR_START_HMAC:hdr_length] + app_binarray))
am_print("HMAC Clear")
am_print([hex(n) for n in sigClr])
# Fill up the HMAC
for x in range(0, AM_HMAC_SIG_SIZE):
hdr_binarray[AM_IMAGEHDR_OFFSET_SIGCLR + x] = sigClr[x]
# All the header fields part of the encryption are now final
if (encVal == 1):
am_print("Encryption Enabled")
encKeyIdx = encKeyIdx - minAesKeyIdx
ivValAes = os.urandom(AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES)
am_print("Initialization Vector")
am_print([hex(ivValAes[n]) for n in range (0, AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES)])
keyAes = os.urandom(keySize)
am_print("AES Key used for encryption")
am_print([hex(keyAes[n]) for n in range (0, keySize)])
# Encrypted Part
am_print("Encrypting blob of size " , (hdr_length - AM_IMAGEHDR_START_ENCRYPT + app_length))
enc_binarray = encrypt_app_aes((hdr_binarray[AM_IMAGEHDR_START_ENCRYPT:hdr_length] + app_binarray), keyAes, ivValAes)
# am_print("Key used for encrypting AES Key")
# am_print([hex(keyTblAes[encKeyIdx*keySize + n]) for n in range (0, keySize)])
# Encrypted Key
enc_key = encrypt_app_aes(keyAes, keyTblAes[encKeyIdx*keySize:encKeyIdx*keySize + keySize], ivVal0)
am_print("Encrypted Key")
am_print([hex(enc_key[n]) for n in range (0, keySize)])
# Fill up the IV
for x in range(0, AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES):
hdr_binarray[AM_IMAGEHDR_OFFSET_IV + x] = ivValAes[x]
# Fill up the Encrypted Key
for x in range(0, keySize):
hdr_binarray[AM_IMAGEHDR_OFFSET_KEK + x] = enc_key[x]
else:
enc_binarray = hdr_binarray[AM_IMAGEHDR_START_ENCRYPT:hdr_length] + app_binarray
if (authI != 0): # Install Authentication needed
am_print("Install Authentication Enabled")
# am_print("Key used for HMAC")
# am_print([hex(keyTblHmac[authKeyIdx*AM_SECBOOT_KEYIDX_BYTES + n]) for n in range (0, AM_HMAC_SIG_SIZE)])
# Initialize the top level HMAC
sig = compute_hmac(keyTblHmac[authKeyIdx*AM_SECBOOT_KEYIDX_BYTES:(authKeyIdx*AM_SECBOOT_KEYIDX_BYTES+AM_HMAC_SIG_SIZE)], (hdr_binarray[AM_IMAGEHDR_START_HMAC_INST:AM_IMAGEHDR_START_ENCRYPT] + enc_binarray))
am_print("Generated Signature")
am_print([hex(n) for n in sig])
# Fill up the HMAC
for x in range(0, AM_HMAC_SIG_SIZE):
hdr_binarray[AM_IMAGEHDR_OFFSET_SIG + x] = sig[x]
# compute the CRC for the blob - this is done on a clear image
crc = crc32(hdr_binarray[AM_IMAGEHDR_START_CRC:hdr_length] + app_binarray)
am_print("crc = ",hex(crc));
w1 = crc
fill_word(hdr_binarray, AM_IMAGEHDR_OFFSET_CRC, w1)
# now output all three binary arrays in the proper order
output = output + '_OTA_blob.bin'
blob2wiredfile = output # save the output of bin2blob for use by blob2wired
am_print("Writing to file ", output)
with open(output, mode = 'wb') as out:
out.write(hdr_binarray[0:AM_IMAGEHDR_START_ENCRYPT])
out.write(enc_binarray)
#******************************************************************************
#
# Generate the image blob as per command line parameters
#
#******************************************************************************
def blob2wired_process(appFile, imagetype, loadaddress, authalgo, encalgo, authKeyIdx, encKeyIdx, optionsVal, maxSize, output):
global uploadbinfile
app_binarray = bytearray()
# Open the file, and read it into an array of integers.
print('testing: ' + appFile )
with open(appFile,'rb') as f_app:
app_binarray.extend(f_app.read())
f_app.close()
# Make sure it is page multiple
if ((maxSize & (FLASH_PAGE_SIZE - 1)) != 0):
am_print ("split needs to be multiple of flash page size", level=AM_PRINT_LEVEL_ERROR)
return
if (encalgo != 0):
if ((encKeyIdx < minAesKeyIdx) or (encKeyIdx > maxAesKeyIdx)):
am_print("Invalid encKey Idx ", encKeyIdx, level=AM_PRINT_LEVEL_ERROR)
return
if (encalgo == 2):
if (encKeyIdx & 0x1):
am_print("Invalid encKey Idx ", encKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
keySize = 32
else:
keySize = 16
if (authalgo != 0):
if ((authKeyIdx < minHmacKeyIdx) or (authKeyIdx > maxHmacKeyIdx) or (authKeyIdx & 0x1)):
am_print("Invalid authKey Idx ", authKeyIdx, level=AM_PRINT_LEVEL_ERROR);
return
hdr_length = AM_WU_IMAGEHDR_SIZE; #fixed header length
am_print("Header Size = ", hex(hdr_length))
orig_app_length = (len(app_binarray))
if (encalgo != 0):
block_size = keySize
app_binarray = pad_to_block_size(app_binarray, block_size, 1)
else:
# Add Padding
app_binarray = pad_to_block_size(app_binarray, 4, 0)
app_length = (len(app_binarray))
am_print("app_size ",hex(app_length), "(",app_length,")")
if (app_length + hdr_length > maxSize):
am_print("Image size bigger than max - Creating Split image")
start = 0
# now output all three binary arrays in the proper order
output = output + '_Wired_OTA_blob.bin'
uploadbinfile = output; # save the name of the output from blob2wired
out = open(output, mode = 'wb')
while (start < app_length):
#generate mutable byte array for the header
hdr_binarray = bytearray([0x00]*hdr_length);
if (app_length - start > maxSize):
end = start + maxSize
else:
end = app_length
if (imagetype == AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA):
key = INFO_KEY
# word offset
fill_word(hdr_binarray, AM_WU_IMAGEHDR_OFFSET_ADDR, loadaddress>>2)
else:
key = FLASH_KEY
# load address
fill_word(hdr_binarray, AM_WU_IMAGEHDR_OFFSET_ADDR, loadaddress)
# Create imageType & options
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_IMAGETYPE] = imagetype
# Set the options only for the first block
if (start == 0):
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_OPTIONS] = optionsVal
else:
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_OPTIONS] = 0
# Create Info0 Update Blob for wired update
fill_word(hdr_binarray, AM_WU_IMAGEHDR_OFFSET_KEY, key)
# update size
fill_word(hdr_binarray, AM_WU_IMAGEHDR_OFFSET_SIZE, end-start)
w0 = ((authalgo & 0xf) | ((authKeyIdx << 8) & 0xf00) | ((encalgo << 16) & 0xf0000) | ((encKeyIdx << 24) & 0x0f000000))
fill_word(hdr_binarray, 0, w0)
if (encalgo != 0):
keyIdx = encKeyIdx - minAesKeyIdx
ivValAes = os.urandom(AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES)
am_print("Initialization Vector")
am_print([hex(n) for n in ivValAes])
keyAes = os.urandom(keySize)
am_print("AES Key used for encryption")
am_print([hex(keyAes[n]) for n in range (0, keySize)])
# Encrypted Part - after security header
enc_binarray = encrypt_app_aes((hdr_binarray[AM_WU_IMAGEHDR_START_ENCRYPT:hdr_length] + app_binarray[start:end]), keyAes, ivValAes)
# am_print("Key used for encrypting AES Key")
# am_print([hex(keyTblAes[keyIdx*AM_SECBOOT_KEYIDX_BYTES + n]) for n in range (0, keySize)])
# Encrypted Key
enc_key = encrypt_app_aes(keyAes, keyTblAes[keyIdx*AM_SECBOOT_KEYIDX_BYTES:(keyIdx*AM_SECBOOT_KEYIDX_BYTES + keySize)], ivVal0)
am_print("Encrypted Key")
am_print([hex(enc_key[n]) for n in range (0, keySize)])
# Fill up the IV
for x in range(0, AM_SECBOOT_AESCBC_BLOCK_SIZE_BYTES):
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_IV + x] = ivValAes[x]
# Fill up the Encrypted Key
for x in range(0, keySize):
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_KEK + x] = enc_key[x]
else:
enc_binarray = hdr_binarray[AM_WU_IMAGEHDR_START_ENCRYPT:hdr_length] + app_binarray[start:end]
if (authalgo != 0): # Authentication needed
keyIdx = authKeyIdx - minHmacKeyIdx
# am_print("Key used for HMAC")
# am_print([hex(keyTblHmac[keyIdx*AM_SECBOOT_KEYIDX_BYTES + n]) for n in range (0, AM_HMAC_SIG_SIZE)])
# Initialize the HMAC - Sign is computed on image following the signature
sig = compute_hmac(keyTblHmac[keyIdx*AM_SECBOOT_KEYIDX_BYTES:(keyIdx*AM_SECBOOT_KEYIDX_BYTES+AM_HMAC_SIG_SIZE)], hdr_binarray[AM_WU_IMAGEHDR_START_HMAC:AM_WU_IMAGEHDR_START_ENCRYPT] + enc_binarray)
am_print("HMAC")
am_print([hex(n) for n in sig])
# Fill up the HMAC
for x in range(0, AM_HMAC_SIG_SIZE):
hdr_binarray[AM_WU_IMAGEHDR_OFFSET_SIG + x] = sig[x]
am_print("Writing to file ", output)
am_print("Image from ", str(hex(start)), " to ", str(hex(end)), " will be loaded at", str(hex(loadaddress)))
out.write(hdr_binarray[0:AM_WU_IMAGEHDR_START_ENCRYPT])
out.write(enc_binarray)
# Reset start for next chunk
start = end
loadaddress = loadaddress + maxSize
#******************************************************************************
#
# Main function
#
#******************************************************************************
def upload(args, verboseprint):
global loadTries
global loadSuccess
# Open a serial port, and communicate with Device
#
# Max flashing time depends on the amount of SRAM available.
# For very large images, the flashing happens page by page.
# However if the image can fit in the free SRAM, it could take a long time
# for the whole image to be flashed at the end.
# The largest image which can be stored depends on the max SRAM.
# Assuming worst case ~100 ms/page of flashing time, and allowing for the
# image to be close to occupying full SRAM (256K) which is 128 pages.
connection_timeout = 5
print('Connecting over serial port {}...'.format(args.port), flush=True)
#Check to see if the com port is available
try:
with serial.Serial(args.port, args.baud, timeout=connection_timeout) as ser:
pass
except:
#Show a list of com ports and recommend one
print("Detected Serial Ports:")
devices = list_ports.comports()
port = None
for dev in devices:
print(dev.description)
# The SparkFun BlackBoard has CH340 in the description
if 'CH340' in dev.description:
print("The port you selected was not found. But we did detect a CH340 on " + dev.device + " so you might try again on that port.")
break
elif 'FTDI' in dev.description:
print("The port you selected was not found. But we did detect an FTDI on " + dev.device + " so you might try again on that port.")
break
elif 'USB Serial Device' in dev.description:
print("The port you selected was not found. But we did detect a USB Serial Device on " + dev.device + " so you might try again on that port.")
break
else:
print("Com Port not found - Did you select the right one?")
exit()
#Begin talking over com port
#The auto-bootload sequence is good but not fullproof. The bootloader
#fails to correctly catch the BOOT signal about 1 out of ten times.
#Auto-retry this number of times before we give up.
while loadTries < 3:
loadSuccess = False
with serial.Serial(args.port, args.baud, timeout=connection_timeout) as ser:
#DTR is driven low when serial port open. DTR has now pulled RST low.
time.sleep(0.005) #3ms and 10ms work well. Not 50, and not 0.
#Setting RTS/DTR high causes the bootload pin to go high, then fall across 100ms
ser.setDTR(0) #Set DTR high
ser.setRTS(0) #Set RTS high - support the CH340E
#Give bootloader a chance to run and check bootload pin before communication begins. But must initiate com before bootloader timeout of 250ms.
time.sleep(0.100) #100ms works well
ser.reset_input_buffer() # reset the input bufer to discard any UART traffic that the device may have generated
connect_device(ser, args, verboseprint)
if(loadSuccess == True):
print("Tries =", loadTries)
print('Upload complete!')
exit()
else:
print("Fail")
loadTries = loadTries + 1
print("Tries =", loadTries)
print("Upload failed")
exit()
#******************************************************************************
#
# Communicate with Device
#
# Given a serial port, connects to the target device using the
# UART.
#
#******************************************************************************
def connect_device(ser, args, verboseprint):
global loadSuccess
# Send Hello
#generate mutable byte array for the header
hello = bytearray([0x00]*4)
fill_word(hello, 0, ((8 << 16) | AM_SECBOOT_WIRED_MSGTYPE_HELLO))
verboseprint('Sending Hello.')
response = send_command(hello, 88, ser, verboseprint)
#Check if response failed
if response == False:
verboseprint("Failed to respond")
return
verboseprint("Received response for Hello")
word = word_from_bytes(response, 4)
if ((word & 0xFFFF) == AM_SECBOOT_WIRED_MSGTYPE_STATUS):
# Received Status
print("Bootloader connected")
verboseprint("Received Status")
verboseprint("length = ", hex((word >> 16)))
verboseprint("version = ", hex(word_from_bytes(response, 8)))
verboseprint("Max Storage = ", hex(word_from_bytes(response, 12)))
verboseprint("Status = ", hex(word_from_bytes(response, 16)))
verboseprint("State = ", hex(word_from_bytes(response, 20)))
verboseprint("AMInfo = ")
for x in range(24, 88, 4):
verboseprint(hex(word_from_bytes(response, x)))
abort = args.abort
if (abort != -1):
# Send OTA Desc
verboseprint('Sending Abort command.')
abortMsg = bytearray([0x00]*8);
fill_word(abortMsg, 0, ((12 << 16) | AM_SECBOOT_WIRED_MSGTYPE_ABORT))
fill_word(abortMsg, 4, abort)
if send_ackd_command(abortMsg, ser, verboseprint) == False:
verboseprint("Failed to ack command")
return
otadescaddr = args.otadesc
if (otadescaddr != 0xFFFFFFFF):
# Send OTA Desc
verboseprint('Sending OTA Descriptor = ', hex(otadescaddr))
otaDesc = bytearray([0x00]*8);
fill_word(otaDesc, 0, ((12 << 16) | AM_SECBOOT_WIRED_MSGTYPE_OTADESC))
fill_word(otaDesc, 4, otadescaddr)
if send_ackd_command(otaDesc, ser, verboseprint) == False:
verboseprint("Failed to ack command")
return
imageType = args.imagetype
if (uploadbinfile != ''):
# Read the binary file from the command line.
with open(uploadbinfile, mode='rb') as binfile:
application = binfile.read()
# Gather the important binary metadata.
totalLen = len(application)
# Send Update command
verboseprint('Sending Update Command.')
# It is assumed that maxSize is 256b multiple
maxImageSize = args.split
if ((maxImageSize & (FLASH_PAGE_SIZE - 1)) != 0):
verboseprint ("split needs to be multiple of flash page size")
return
# Each Block of image consists of AM_WU_IMAGEHDR_SIZE Bytes Image header and the Image blob
maxUpdateSize = AM_WU_IMAGEHDR_SIZE + maxImageSize
numUpdates = (totalLen + maxUpdateSize - 1) // maxUpdateSize # Integer division
verboseprint("number of updates needed = ", numUpdates)
end = totalLen
for numUpdates in range(numUpdates, 0 , -1):
start = (numUpdates-1)*maxUpdateSize
crc = crc32(application[start:end])
applen = end - start
verboseprint("Sending block of size ", str(hex(applen)), " from ", str(hex(start)), " to ", str(hex(end)))
end = end - applen
update = bytearray([0x00]*16);
fill_word(update, 0, ((20 << 16) | AM_SECBOOT_WIRED_MSGTYPE_UPDATE))
fill_word(update, 4, applen)
fill_word(update, 8, crc)
# Size = 0 => We're not piggybacking any data to IMAGE command
fill_word(update, 12, 0)
if send_ackd_command(update, ser, verboseprint) == False:
verboseprint("Failed to ack command")
return
# Loop over the bytes in the image, and send them to the target.
resp = 0
# Max chunk size is AM_MAX_UART_MSG_SIZE adjusted for the header for Data message
maxChunkSize = AM_MAX_UART_MSG_SIZE - 12
for x in range(0, applen, maxChunkSize):
# Split the application into chunks of maxChunkSize bytes.
# This is the max chunk size supported by the UART bootloader
if ((x + maxChunkSize) > applen):
chunk = application[start+x:start+applen]
# print(str(hex(start+x)), " to ", str(hex(applen)))
else:
chunk = application[start+x:start+x+maxChunkSize]
# print(str(hex(start+x)), " to ", str(hex(start + x + maxChunkSize)))
chunklen = len(chunk)
# Build a data packet with a "data command" a "length" and the actual
# payload bytes, and send it to the target.
dataMsg = bytearray([0x00]*8);
fill_word(dataMsg, 0, (((chunklen + 12) << 16) | AM_SECBOOT_WIRED_MSGTYPE_DATA))
# seqNo
fill_word(dataMsg, 4, x)
verboseprint("Sending Data Packet of length ", chunklen)
if send_ackd_command(dataMsg + chunk, ser, verboseprint) == False:
verboseprint("Failed to ack command")
return
if (args.raw != ''):
# Read the binary file from the command line.
with open(args.raw, mode='rb') as rawfile:
blob = rawfile.read()
# Send Raw command
verboseprint('Sending Raw Command.')
ser.write(blob)
if (args.reset != 0):
# Send reset
verboseprint('Sending Reset Command.')
resetmsg = bytearray([0x00]*8);
fill_word(resetmsg, 0, ((12 << 16) | AM_SECBOOT_WIRED_MSGTYPE_RESET))
# options
fill_word(resetmsg, 4, args.reset)
if send_ackd_command(resetmsg, ser, verboseprint) == False:
verboseprint("Failed to ack command")
return
#Success! We're all done
loadSuccess = True
else:
# Received Wrong message
verboseprint("Received Unknown Message")
word = word_from_bytes(response, 4)
verboseprint("msgType = ", hex(word & 0xFFFF))
verboseprint("Length = ", hex(word >> 16))
verboseprint([hex(n) for n in response])
#print("!!!Wired Upgrade Unsuccessful!!!....Terminating the script")
#exit()
#******************************************************************************
#
# Send ACK'd command
#
# Sends a command, and waits for an ACK.
#
#******************************************************************************
def send_ackd_command(command, ser, verboseprint):
response = send_command(command, 20, ser, verboseprint)
#Check if response failed
if response == False:
verboseprint("Response not valid")
return False #Return error
word = word_from_bytes(response, 4)
if ((word & 0xFFFF) == AM_SECBOOT_WIRED_MSGTYPE_ACK):
# Received ACK
if (word_from_bytes(response, 12) != AM_SECBOOT_WIRED_ACK_STATUS_SUCCESS):
verboseprint("Received NACK")
verboseprint("msgType = ", hex(word_from_bytes(response, 8)))
verboseprint("error = ", hex(word_from_bytes(response, 12)))
verboseprint("seqNo = ", hex(word_from_bytes(response, 16)))
#print("!!!Wired Upgrade Unsuccessful!!!....Terminating the script")
verboseprint("Upload failed: No ack to command")
return False #Return error
return response
#******************************************************************************
#
# Send command
#
# Sends a command, and waits for the response.
#
#******************************************************************************
def send_command(params, response_len, ser, verboseprint):
# Compute crc
crc = crc32(params)
# print([hex(n) for n in int_to_bytes(crc)])
# print([hex(n) for n in params])
# send crc first
ser.write(int_to_bytes(crc))
# Next, send the parameters.
ser.write(params)
response = ''
response = ser.read(response_len)
# Make sure we got the number of bytes we asked for.
if len(response) != response_len:
verboseprint('No response for command 0x{:08X}'.format(word_from_bytes(params, 0) & 0xFFFF))
n = len(response)
if (n != 0):
verboseprint("received bytes ", len(response))
verboseprint([hex(n) for n in response])
return False
return response
#******************************************************************************
#
# Send a command that uses an array of bytes as its parameters.
#
#******************************************************************************
def send_bytewise_command(command, params, response_len, ser):
# Send the command first.
ser.write(int_to_bytes(command))
# Next, send the parameters.
ser.write(params)
response = ''
response = ser.read(response_len)
# Make sure we got the number of bytes we asked for.
if len(response) != response_len:
print("Upload failed: No reponse to command")
verboseprint('No response for command 0x{:08X}'.format(command))
exit()
return response
#******************************************************************************
#
# Errors
#
#******************************************************************************
class BootError(Exception):
pass
class NoAckError(BootError):
pass
def parse_arguments():
parser = argparse.ArgumentParser(description =
'Combination script to upload application binaries to Artemis module. Includes:\n\t\'- bin2blob: create OTA blob from binary image\'\n\t\'- blob2wired: create wired update image from OTA blob\'\n\t\'- upload: send wired update image to Apollo3 Artemis module via serial port\'\n\nThere are many command-line arguments. They have been labeled by which steps they apply to\n')
parser.add_argument('-a', dest = 'abort', default=-1, type=int, choices = [0,1,-1],
help = 'upload: Should it send abort command? (0 = abort, 1 = abort and quit, -1 = no abort) (default is -1)')
parser.add_argument('--authalgo', dest = 'authalgo', type=auto_int, default=0, choices=range(0, AM_SECBOOT_AUTH_ALGO_MAX+1),
help = 'bin2blob, blob2wired: ' + str(helpAuthAlgo))
parser.add_argument('--authI', dest = 'authI', type=auto_int, default=0, choices=[0,1],
help = 'bin2blob: Install Authentication check enabled (Default = N)?')
parser.add_argument('--authB', dest = 'authB', type=auto_int, default=0, choices=[0,1],
help = 'bin2blob: Boot Authentication check enabled (Default = N)?')
parser.add_argument('--authkey', dest = 'authkey', type=auto_int, default=(minHmacKeyIdx), choices = range(minHmacKeyIdx, maxHmacKeyIdx + 1),
help = 'bin2blob, blob2wired: Authentication Key Idx? (' + str(minHmacKeyIdx) + ' to ' + str(maxHmacKeyIdx) + ')')
parser.add_argument('-b', dest='baud', default=115200, type=int,
help = 'upload: Baud Rate (default is 115200)')
parser.add_argument('--bin', dest='appFile', type=argparse.FileType('rb'),
help='bin2blob: binary file (blah.bin)')
parser.add_argument('-clean', dest='clean', default=0, type=int,
help = 'All: whether or not to remove intermediate files')
parser.add_argument('--child0', dest = 'child0', type=auto_int, default=hex(0xFFFFFFFF),
help = 'bin2blob: child (blobPtr#0 for Main / feature key for AM3P)')
parser.add_argument('--child1', dest = 'child1', type=auto_int, default=hex(0xFFFFFFFF),
help = 'bin2blob: child (blobPtr#1 for Main)')
parser.add_argument('--crcI', dest = 'crcI', type=auto_int, default=1, choices=[0,1],
help = 'bin2blob: Install CRC check enabled (Default = Y)?')
parser.add_argument('--crcB', dest = 'crcB', type=auto_int, default=0, choices=[0,1],
help = 'bin2blob: Boot CRC check enabled (Default = N)?')
parser.add_argument('--encalgo', dest = 'encalgo', type=auto_int, default=0, choices = range(0, AM_SECBOOT_ENC_ALGO_MAX+1),
help = 'bin2blob, blob2wired: ' + str(helpEncAlgo))
parser.add_argument('--erasePrev', dest = 'erasePrev', type=auto_int, default=0, choices=[0,1],
help = 'bin2blob: erasePrev (Valid only for main)')
# parser.add_argument('-f', dest='binfile', default='',
# help = 'upload: Binary file to program into the target device')
parser.add_argument('-i', dest = 'imagetype', default=AM_SECBOOT_WIRED_IMAGETYPE_INVALID, type=auto_int,
choices = [
(AM_SECBOOT_WIRED_IMAGETYPE_SBL),
(AM_SECBOOT_WIRED_IMAGETYPE_AM3P),
(AM_SECBOOT_WIRED_IMAGETYPE_PATCH),
(AM_SECBOOT_WIRED_IMAGETYPE_MAIN),
(AM_SECBOOT_WIRED_IMAGETYPE_CHILD),
(AM_SECBOOT_WIRED_IMAGETYPE_CUSTPATCH),
(AM_SECBOOT_WIRED_IMAGETYPE_NONSECURE),
(AM_SECBOOT_WIRED_IMAGETYPE_INFO0),
(AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA),
(AM_SECBOOT_WIRED_IMAGETYPE_INVALID)
],
help = 'blob2wired, upload: ImageType ('
+ str(AM_SECBOOT_WIRED_IMAGETYPE_SBL) + ': SBL, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_AM3P) + ': AM3P, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_PATCH) + ': Patch, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_MAIN) + ': Main, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_CHILD) + ': Child, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_CUSTPATCH) + ': CustOTA, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_NONSECURE) + ': NonSecure, '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_INFO0) + ': Info0 '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_INFO0_NOOTA) + ': Info0_NOOTA) '
+ str(AM_SECBOOT_WIRED_IMAGETYPE_INVALID) + ': Invalid) '
'- default[Invalid]')
parser.add_argument('--kek', dest = 'kek', type=auto_int, default=(minAesKeyIdx), choices = range(minAesKeyIdx, maxAesKeyIdx+1),
help = 'KEK index? (' + str(minAesKeyIdx) + ' to ' + str(maxAesKeyIdx) + ')')
parser.add_argument('--load-address-wired', dest='loadaddress_blob', type=auto_int, default=hex(0x60000),
help='blob2wired: Load address of the binary - Where in flash the blob will be stored (could be different than install address of binary within).')
parser.add_argument('--load-address-blob', dest='loadaddress_image', type=auto_int, default=hex(AM_SECBOOT_DEFAULT_NONSECURE_MAIN),
help='bin2blob: Load address of the binary.')
parser.add_argument('--loglevel', dest='loglevel', type=auto_int, default=AM_PRINT_LEVEL_INFO,
choices = range(AM_PRINT_LEVEL_MIN, AM_PRINT_LEVEL_MAX+1),
help='bin2blob, blob2wired: ' + str(helpPrintLevel))
parser.add_argument('--magic-num', dest='magic_num', default=hex(AM_IMAGE_MAGIC_NONSECURE),
type=lambda x: x.lower(),
# type = str.lower,
choices = [
hex(AM_IMAGE_MAGIC_MAIN),
hex(AM_IMAGE_MAGIC_CHILD),
hex(AM_IMAGE_MAGIC_CUSTPATCH),
hex(AM_IMAGE_MAGIC_NONSECURE),
hex(AM_IMAGE_MAGIC_INFO0)
],
help = 'bin2blob: Magic Num ('
+ str(hex(AM_IMAGE_MAGIC_MAIN)) + ': Main, '
+ str(hex(AM_IMAGE_MAGIC_CHILD)) + ': Child, '
+ str(hex(AM_IMAGE_MAGIC_CUSTPATCH)) + ': CustOTA, '
+ str(hex(AM_IMAGE_MAGIC_NONSECURE)) + ': NonSecure, '
+ str(hex(AM_IMAGE_MAGIC_INFO0)) + ': Info0) '
'- default[Main]'
)
parser.add_argument('-o', dest = 'output', default='wuimage',
help = 'all: Output filename (without the extension) [also used for intermediate filenames]')
parser.add_argument('-ota', dest = 'otadesc', type=auto_int, default=0xFE000,
help = 'upload: OTA Descriptor Page address (hex) - (Default is 0xFE000 - at the end of main flash) - enter 0xFFFFFFFF to instruct SBL to skip OTA')
parser.add_argument('--options', dest = 'options', type=auto_int, default=0x1,
help = 'blob2wired: Options (16b hex value) - bit0 instructs to perform OTA of the image after wired download (set to 0 if only downloading & skipping OTA flow)')
parser.add_argument('-p', dest = 'protection', type=auto_int, default=0, choices = [0x0, 0x1, 0x2, 0x3],
help = 'bin2blob: protection info 2 bit C W')
parser.add_argument('-port', dest = 'port', help = 'upload: Serial COMx Port')
parser.add_argument('-r', dest = 'reset', default=1, type=auto_int, choices = [0,1,2],
help = 'upload: Should it send reset command after image download? (0 = no reset, 1 = POI, 2 = POR) (default is 1)')
parser.add_argument('--raw', dest='raw', default='',
help = 'upload: Binary file for raw message')
parser.add_argument('--split', dest='split', type=auto_int, default=hex(MAX_DOWNLOAD_SIZE),
help='blob2wired, upload: Specify the max block size if the image will be downloaded in pieces')
parser.add_argument('--version', dest = 'version', type=auto_int, default=0,
help = 'bin2blob: version (15 bit)')
parser.add_argument("-v", "--verbose", default=0, help="All: Enable verbose output",
action="store_true")
args = parser.parse_args()
args.magic_num = int(args.magic_num, 16)
return args
#******************************************************************************
#
# Main function.
#
#******************************************************************************
# example calling:
# python artemis_bin_to_board.py --bin application.bin --load-address-blob 0x20000 --magic-num 0xCB -o application --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b 921600 -port COM4 -r 1 -v
def main():
# Read the arguments.
args = parse_arguments()
am_set_print_level(args.loglevel)
global blob2wiredfile
bin2blob_process(args.loadaddress_blob, args.appFile, args.magic_num, args.crcI, args.crcB, args.authI, args.authB, args.protection, args.authkey, args.output, args.kek, args.version, args.erasePrev, args.child0, args.child1, args.authalgo, args.encalgo)
blob2wired_process( blob2wiredfile, args.imagetype, args.loadaddress_image, args.authalgo, args.encalgo, args.authkey, args.kek, args.options, args.split, args.output)
# todo: link the bin2blob step with the blob2wired step by input/output files
#Create print function for verbose output if caller deems it: https://stackoverflow.com/questions/5980042/how-to-implement-the-verbose-or-v-option-into-a-script
if args.verbose:
def verboseprint(*args):
# Print each argument separately so caller doesn't need to
# stuff everything to be printed into a single string
for arg in args:
print(arg, end=''),
print()
else:
verboseprint = lambda *a: None # do-nothing function
upload(args, verboseprint)
if(args.clean == 1):
print('Cleaning up intermediate files') # todo: why isnt this showing w/ -clean option?
if __name__ == '__main__':
main()
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
from am_defines import *
minAesKeyIdx = 8
maxAesKeyIdx = 15
minHmacKeyIdx = 8
maxHmacKeyIdx = 15
###### Following are just dummy keys - Should be substituted with real keys #######
keyTblAes = [
# Info0 Keys - Starting at index 8
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE,
]
keyTblHmac = [
# Info0 Keys - Starting at index 8
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE,
]
custKey = [
0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE,
]
# These are dummy values. Contact AMBIQ to get the real Recovery Key
recoveryKey = [
0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE,
]
###################################################################################
wrapKey = custKey
minWrapMode = AM_SECBOOT_KEYWRAP_NONE
INFO_KEY = 0xd894e09e
FLASH_KEY = 0x12344321
@@ -0,0 +1,4 @@
###### Requirements ######`
pyinstaller == 3.6
pycryptodome
pyserial
@@ -0,0 +1,40 @@
//connect to device
device AMA3B1KK-KBR
si SWD
speed 1000
r
sleep 10
//set C runtime environment
wreg MSP, 0x10000100
// erase info0
w4 0x10000000 0 // flash info instance
w4 0x10000004 0xd894e09e // info 0 key
w4 0x10000008 0xFFFFFFFF // clear return value
setPC 0x08000085 // call the ROM helper function flash_info_erase_from_sram
g
sleep 50
mem32 0x10000008 1 // dump return value for check
// program info0
w4 0x10000000 0 // flash info instance
w4 0x10000004 0 // offset
w4 0x10000008 0x800 // length in words
w4 0x1000000C 0xd894e09e // info 0 key
w4 0x10000010 0xFFFFFFFF // clear return value
loadbin info0_artemis_47_115200.bin 0x10001000 //load the info0 binary into sram
setPC 0x08000061 // call the ROM helper function flash_program_info_area_from_sram
g
sleep 50
mem32 0x10000010 1 // dump return value for check
loadbin artemis_svl.bin 0x0000C000 //load SVL into 0xC000 (end of Ambiq bootloader)
loadbin example1_blink.ino.bin 0x00010000 //load Blink after SVL
// perform software POI
w4 0x40000004 0x1B
// quit
qc
@@ -0,0 +1,25 @@
Artemis Bootloader
==========================
The Artemis module is loaded with two bootloaders: the ASB and SVL. The Ambiq Secure Boot Loader (ASB) resides from 0x00 to 0xC000. This bootloader is physically part of the IC and is configured using the info0 registers. At power up, if the ASB is not activated, it jumps to 0xC000. The SparkFun Variable Bootloader (SVL) resides at 0xC000 and will wait for an incoming serial character. If a character is received, the baud rate will be auto-detected, the SVL will load new code, then jump to the new user code starting at 0x10000. The SVL times out after 50ms.
This directory contains the various binaries that are programmed onto each Artemis module:
* info0_artemis_47_115200.bin - Sets the Ambiq Secure Bootloader (ASB) to 115200bps with boot pin on 47
* artemis_svl.bin - the SparkFun Variable Loader (SVL), starts at 0xC000
* example1_blink.ino.bin - An example sketch to blink the LED. This shows code has been loaded but will be overwritten with new sketches.
For more information on the Artemis Bootloader see the Artemis Bootloader in the [Arduino_Apollo3 repo](https://github.com/sparkfun/Arduino_Apollo3/tree/master/bootloaders/artemis/!artemis_svl).
The ASB is configured based on the documents from Ambiq (Ambiq calls it the secure bootloader or SBL). See \AmbiqSuite-Rel2.x.x\docs\secure_bootloader\ for how to modify the info0 image.
* Run the bootloader at 921600bps: --u0 0x1C299c0
* Currently pin 47 is used for BOOTLOAD: --gpio 0x2f
* Bootloader to check if BOOTLOAD pin is high (not low): --gpiolvl 1
* Trim timeout to 2500ms: --wTO 2500
This was used for Artemis v10 module that used pin 47 for boot:
create_info0.py --valid 1 info0_artemis_47 --pl 1 --u0 0x1C200c0 --u1 0xFFFF3031 --u2 0x2 --u3 0x0 --u4 0x0 --u5 0x0 --main 0xC000 --gpio 0x2f --version 0 --wTO 2500 --gpiolvl 1
We load a conservative 115200bps image into the Ambiq ASB section so that future updates can be applied. The SparkFun Variable Loader is a variable bootloader capable of operating from 9600bps to 921600bps.
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
# requires:
# make
# example usage
# locations:
# from bsp repo root:
# common/bsp_pinconfig/scripts/regen_bsp_libs.sh
# from remote location: (requires $AMSDK environment variable -- {boards_sfe} can be whatever you named the root of the bsp repo )
# $AMSDK/{boards_sfe}/common/bsp_pinconfig/scripts/regen_bsp_libs.sh -r $AMSDK/{boards_sfe}
# arguments:
# [-r $BSP_ROOT] path to bsp root optional -- defaults to the current directory
# (should be specified when calling script remotely)
# [-b $BOARDS_FILE] path to boards file optional -- defaults to all supported bsp boards
# (for now boards must still have source files located in the bsp repo)
# setup
set -e
set -o errexit
echo "" 1>&2
# get enclosing directory
DIR=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")")
# defaults
BSP_ROOT=.
BOARDS_FILE=$DIR/configuration/boards.sh
# handle arguments
while getopts ":r:b:" opt; do
case $opt in
r) BSP_ROOT="$OPTARG"
;;
b) BOARDS_FILE="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" 1>&2
;;
esac
done
# verify bsp root
echo "Using \$BSP_ROOT=$BSP_ROOT" 1>&2
VFILE=$BSP_ROOT/README.md
if [ -f "$VFILE" ];
then
echo "\$BSP_ROOT verification passed" 1>&2
else
echo "\$BSP_ROOT verification failed" 1>&2
exit 1
fi
# load in boards to handle
echo "Using \$BOARDS_FILE=$BOARDS_FILE" 1>&2
source $BOARDS_FILE
echo "" 1>&2
for value in $BOARDS
do
echo "Cleaning all examples for: $value" 1>&2
# https://unix.stackexchange.com/questions/86722/how-do-i-loop-through-only-directories-in-bash
# https://stackoverflow.com/questions/4515866/iterate-through-subdirectories-in-bash
# https://stackoverflow.com/questions/9018723/what-is-the-simplest-way-to-remove-a-trailing-slash-from-each-parameter
# shopt -s nullglob
for f in $BSP_ROOT/$value/examples/*/; do
if [[ "$f" = "*" ]]; then continue; fi # protect from empty directories
if [[ -d "$f" && ! -L "$f" ]]; then
# # $f is a directory and is not a symlink
# echo "Removing: $f/gcc/bin"
# rm -rf $f/gcc/bin
echo "cleaning ${f%/}"
make -f ${f%/}/gcc/Makefile clean PROJECTPATH=${f%/}
fi
done
done
@@ -0,0 +1 @@
export BOARDS="edge edge2 artemis_module artemis_thing_plus redboard_artemis redboard_artemis_atp redboard_artemis_nano artemis_dk"
@@ -0,0 +1,107 @@
{
"copy": [
{
"from": "devices",
"to": "targets/TARGET_Ambiq_Micro/sdk/devices",
"ignore": [
"am_devices_da14581.c",
"am_devices_da14581.h",
"am_devices_em9304.c",
"am_devices_em9304.h",
"am_devices_fireball.c",
"am_devices_fireball.h",
"am_devices_mb85rc256v.c",
"am_devices_mb85rc256v.h",
"am_devices_mb85rs1mt.c",
"am_devices_mb85rs1mt.h",
"am_devices_mspi_atxp032.c",
"am_devices_mspi_atxp032.h",
"am_devices_mspi_psram_aps6404l.c",
"am_devices_mspi_psram_aps6404l.h",
"am_devices_mspi_rm67162.c",
"am_devices_mspi_rm67162.h",
"am_devices_mspi_s25fs064s.c",
"am_devices_mspi_s25fs064s.h",
"am_devices_spiflash.c",
"am_devices_spiflash.h"
]
},
{
"from": "utils",
"to": "targets/TARGET_Ambiq_Micro/sdk/utils",
"ignore": [
"am_util_faultisr.c",
"am_util_regdump.c"
]
},
{
"from": "mcu",
"to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/sdk/mcu",
"ignore": [
"apollo",
"apollo2",
"apollo3p",
"Makefile",
"gcc",
"iar",
"keil"
]
},
{
"from": "CMSIS",
"to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/sdk/CMSIS",
"ignore": [
"apollo1.h",
"apollo2.h",
"apollo3p.h",
"system_apollo1.h",
"system_apollo2.h",
"system_apollo3p.h",
"system_apollo1.c",
"system_apollo2.c",
"system_apollo3p.c",
"startup_apollo1.s",
"startup_apollo2.s",
"startup_apollo3.s",
"startup_apollo3p.s",
"arm_math.h",
"cmsis_armcc.h",
"cmsis_armclang.h",
"cmsis_compiler.h",
"cmsis_gcc.h",
"cmsis_iccarm.h",
"cmsis_version.h",
"core_cm4.h",
"mpu_armv7.h",
"arm_cortexM4l_math.lib",
"arm_cortexM4lf_math.lib",
"iar_cortexM4l_math.a",
"iar_cortexM4lf_math.a",
"libarm_cortexM4l_math.a"
]
},
{"from": "boards_sfe/artemis_dk/bsp", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_SFE_ARTEMIS_DK/bsp", "ignore": ["gcc", "bsp_pins.src"]},
{"from": "boards_sfe/artemis_thing_plus/bsp", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_SFE_ARTEMIS_THING_PLUS/bsp", "ignore": ["gcc", "bsp_pins.src"]},
{"from": "boards_sfe/edge/bsp", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_SFE_EDGE/bsp", "ignore": ["gcc", "bsp_pins.src"]},
{"from": "boards_sfe/edge2/bsp", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_SFE_EDGE2/bsp", "ignore": ["gcc", "bsp_pins.src"]},
{"from": "boards_sfe/redboard_artemis/bsp", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_SFE_ARTEMIS/bsp", "ignore": ["gcc", "bsp_pins.src"]},
{"from": "boards_sfe/redboard_artemis_atp/bsp", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_SFE_ARTEMIS_ATP/bsp", "ignore": ["gcc", "bsp_pins.src"]},
{"from": "boards_sfe/redboard_artemis_nano/bsp", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_SFE_ARTEMIS_NANO/bsp", "ignore": ["gcc", "bsp_pins.src"]},
{"from": "boards_sfe/common/third_party/hm01b0", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/COMPONENT_hm01b0/hm01b0", "ignore": []},
{"from": "boards_sfe/common/third_party/lis2dh12", "to": "targets/TARGET_Ambiq_Micro/TARGET_Apollo3/COMPONENT_lis2dh12/lis2dh12", "ignore": []}
],
"generate": {
"pincfgs": {
"peripherals": {
"src": "{_sdk}/boards_sfe/common/support/apollo3/peripherals/pins.src",
"dest": "{_mbed}/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPinConfigs",
"guard": "_APOLLO3_PERIPHERAL_PIN_CONFIGS_H_",
"bgaguard": "AM_PACKAGE_BGA",
"prefix": "AP3_PER"
}
}
}
}
@@ -0,0 +1,62 @@
#!/usr/bin/env bash
# requires:
# - 'make' available at the command line
# - 'arm-none-eabi-xxx' available at the command line (preferred version is q4-2018-major)
# example usage
# locations:
# from bsp repo root:
# common/bsp_pinconfig/scripts/regen_bsp_libs.sh
# from remote location: (requires $AMSDK environment variable -- {boards_sfe} can be whatever you named the root of the bsp repo )
# $AMSDK/{boards_sfe}/common/bsp_pinconfig/scripts/regen_bsp_libs.sh -r $AMSDK/{boards_sfe}
# arguments:
# [-r $BSP_ROOT] path to bsp root optional -- defaults to the current directory
# (should be specified when calling script remotely)
# [-b $BOARDS_FILE] path to boards file optional -- defaults to all supported bsp boards
# (for now boards must still have source files located in the bsp repo)
# setup
set -e
set -o errexit
echo "" 1>&2
# get enclosing directory
DIR=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")")
# defaults
BSP_ROOT=.
BOARDS_FILE=$DIR/configuration/boards.sh
# handle arguments
while getopts ":r:b:" opt; do
case $opt in
r) BSP_ROOT="$OPTARG"
;;
b) BOARDS_FILE="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" 1>&2
;;
esac
done
# verify bsp root
echo "Using \$BSP_ROOT=$BSP_ROOT" 1>&2
VFILE=$BSP_ROOT/README.md
if [ -f "$VFILE" ];
then
echo "\$BSP_ROOT verification passed" 1>&2
else
echo "\$BSP_ROOT verification failed" 1>&2
exit 1
fi
# load in boards to handle
echo "Using \$BOARDS_FILE=$BOARDS_FILE" 1>&2
source $BOARDS_FILE
echo "" 1>&2
for value in $BOARDS
do
echo "Regenerating bsp library for: $value" 1>&2
make -C $BSP_ROOT/$value/bsp/gcc
done
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# requires:
# - python3 available at the command line
# example usage
# locations:
# from bsp repo root:
# common/bsp_pinconfig/scripts/regen_bsp_pins.sh
# from remote location: (requires $AMSDK environment variable -- {boards_sfe} can be whatever you named the root of the bsp repo )
# $AMSDK/{boards_sfe}/common/bsp_pinconfig/scripts/regen_bsp_pins.sh -r $AMSDK/{boards_sfe}
# arguments:
# [-r $BSP_ROOT] path to bsp root optional -- defaults to the current directory
# (should be specified when calling script remotely)
# [-b $BOARDS_FILE] path to boards file optional -- defaults to all supported bsp boards
# (for now boards must still have source files located in the bsp repo)
# setup
set -e
set -o errexit
echo "" 1>&2
# get enclosing directory
DIR=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")")
# defaults
BSP_ROOT=.
BOARDS_FILE=$DIR/configuration/boards.sh
# handle arguments
while getopts ":r:b:" opt; do
case $opt in
r) BSP_ROOT="$OPTARG"
;;
b) BOARDS_FILE="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" 1>&2
;;
esac
done
# verify bsp root
echo "Using \$BSP_ROOT=$BSP_ROOT" 1>&2
VFILE=$BSP_ROOT/README.md
if [ -f "$VFILE" ];
then
echo "\$BSP_ROOT verification passed" 1>&2
else
echo "\$BSP_ROOT verification failed" 1>&2
exit 1
fi
# load in boards to handle
echo "Using \$BOARDS_FILE=$BOARDS_FILE" 1>&2
source $BOARDS_FILE
# generate bsp files for every board
echo "" 1>&2
for value in $BOARDS
do
echo "Regenerating bsp_pins files for: $value" 1>&2
$BSP_ROOT/common/bsp_pinconfig/pinconfig.py $BSP_ROOT/$value/bsp/bsp_pins.src h > $BSP_ROOT/$value/bsp/am_bsp_pins.h
$BSP_ROOT/common/bsp_pinconfig/pinconfig.py $BSP_ROOT/$value/bsp/bsp_pins.src c > $BSP_ROOT/$value/bsp/am_bsp_pins.c
done
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# requires:
# - see requirements of source scripts
# example usage
# locations:
# from bsp repo root:
# common/bsp_pinconfig/scripts/regen_bsps.sh
# from remote location: (requires $AMSDK environment variable -- {boards_sfe} can be whatever you named the root of the bsp repo )
# $AMSDK/{boards_sfe}/common/bsp_pinconfig/scripts/regen_bsps.sh -r $AMSDK/{boards_sfe}
# arguments:
# [-r $BSP_ROOT] path to bsp root optional -- defaults to the current directory
# (should be specified when calling script remotely)
# [-b $BOARDS_FILE] path to boards file optional -- defaults to all supported bsp boards
# (for now boards must still have source files located in the bsp repo)
# setup
set -e
set -o errexit
echo "" 1>&2
# get enclosing directory
DIR=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")")
# defaults
BSP_ROOT=.
BOARDS_FILE=$BSP_ROOT/common/tools_sfe/scripts/configuration/boards.sh
# handle arguments
while getopts ":r:b:" opt; do
case $opt in
r) BSP_ROOT="$OPTARG"
;;
b) BOARDS_FILE="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" 1>&2
;;
esac
done
# regen pins and libs
$BSP_ROOT/common/tools_sfe/scripts/regen_bsp_pins.sh -r $BSP_ROOT -b $BOARDS_FILE # regenerates source (.h and .c) files from the bsp_pins.src files
$BSP_ROOT/common/tools_sfe/scripts/regen_bsp_libs.sh -r $BSP_ROOT -b $BOARDS_FILE # regenerates library archive files from bsp source (.h and .c) files
@@ -0,0 +1,103 @@
#!/usr/bin/env python3.8
# requires python3.8
import argparse
import json
import shutil
import os
import subprocess
from braceexpand import braceexpand as expand
# ***********************************************************************************
#
# Main function
#
# ***********************************************************************************
def main():
# load configuration
with open(args.config, 'r') as fin:
config = json.loads(fin.read())
# handle copy steps
for step in config['copy']:
src_path = os.path.join(args.sdk, step['from'])
dest_path = os.path.join(args.mbed, step['to'])
ignore_patterns = step['ignore']
print("copy")
print("from '" + src_path + "'")
print("to '" + dest_path + "'")
print("\texcluding:")
print(ignore_patterns)
print()
shutil.rmtree(dest_path, ignore_errors=True)
shutil.copytree(src_path, dest_path, ignore=shutil.ignore_patterns(*ignore_patterns), dirs_exist_ok=True)
# handle pincfg generation
print('generate pincfgs:')
def absolutify(path):
new_path = path
new_path = new_path.replace('{_mbed}', args.mbed)
new_path = new_path.replace('{_sdk}', args.sdk)
return new_path
selectors = ['c', 'h']
for name, job in config['generate']['pincfgs'].items():
print('\t', name)
for selector in selectors:
results = subprocess.run( [
'python',
absolutify('{_sdk}/boards_sfe/common/bsp_pinconfig/pinconfig.py'),
absolutify(job['src']), selector,
'-g', job['guard'],
'-p', job['prefix'],
'-b', job['bgaguard']
],
capture_output=True)
with open(absolutify(job['dest']) + '.' + selector, 'wb') as fout:
fout.write(results.stdout)
errors = str(results.stderr)
if errors != "b''":
print('error: ', str(results.stderr))
exit()
# ******************************************************************************
#
# Main program flow
#
# ******************************************************************************
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Utility to generate GCC flag and symbol files from mbed build profiles')
parser.add_argument('-m', '--mbed', dest='mbed', required=True, help='path to root of mbed')
parser.add_argument('-c', '--config', dest='config', required=False, default='./boards_sfe/common/tools_sfe/scripts/configuration/mbed-config.json', help='path to the json configuration file')
parser.add_argument('-s', '--sdk', dest='sdk', required=False, default='.', help='path to root of AmbiqSuiteSDK')
parser.add_argument('-v', '--verbose', default=0, help='enable verbose output', action='store_true')
args = parser.parse_args()
# Create print function for verbose output if caller deems it: https://stackoverflow.com/questions/5980042/how-to-implement-the-verbose-or-v-option-into-a-script
if args.verbose:
def verboseprint(*args):
# Print each argument separately so caller doesn't need to
# stuff everything to be printed into a single string
for arg in args:
print(arg, end='', flush=True)
print()
else:
verboseprint = lambda *a: None # do-nothing function
def twopartprint(verbosestr, printstr):
if args.verbose:
print(verbosestr, end = '')
print(printstr)
main()
@@ -0,0 +1,81 @@
#!/usr/bin/env bash
# requires:
# a script to aid in upgrading the AmbiqSuite SDK
# # get enclosing directory
# DIR=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")") # can handle symlinks but fails on mac
DIR=$(dirname -- "$BASH_SOURCE") # assumes no symlinks.... (for mac compatibility)
# import sh-realpath
source $DIR/utility/sh-realpath/realpath.sh
# defaults
SDK_ROOT=$DIR/../../../..
UPGRADE_ROOT=
# handle arguments
while getopts ":r:u:" opt; do
case $opt in
r) SDK_ROOT="$OPTARG"
;;
u) UPGRADE_ROOT="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" 1>&2
;;
esac
done
# ensure user provided -u option
if [ -z "$UPGRADE_ROOT" ]
then
echo "User must provide -u option (path to upgrade sdk directory)"
exit 1
fi
# make a temporary directory to hold the old sdk
TMP_DIR=$(mktemp -d -t ambiqsuite_sdk_upgrade_tmp)
echo "created temporary directory $TMP_DIR"
# get the sdk folder name (and verify)
SDK_ROOT=$(realpath $SDK_ROOT)
SDK_NAME=$(basename $SDK_ROOT)
echo "Got SDK name: $SDK_NAME"
VFILE=$SDK_ROOT/VERSION.txt
if [ -f "$VFILE" ];
then
echo "\$SDK_ROOT verification passed" 1>&2
else
echo "\$SDK_ROOT verification failed" 1>&2
exit 1
fi
# get the upgrade folder (and verify)
UPGRADE_ROOT=$(realpath $UPGRADE_ROOT)
echo "Got upgrade SDK path: $UPGRADE_ROOT"
VFILE=$UPGRADE_ROOT/VERSION.txt
if [ -f "$VFILE" ];
then
echo "\$UPGRADE_ROOT verification passed" 1>&2
else
echo "\$UPGRADE_ROOT verification failed" 1>&2
exit 1
fi
# copy sdk to temporary dir (being sure to keep hidden files)
cp -r $SDK_ROOT/. $TMP_DIR
# remove old directory
rm -rf $SDK_ROOT
# copy the upgrade to the SDK_ROOT
cp -r $UPGRADE_ROOT $SDK_ROOT
# copy important directories from the old SDK to the upgrade
cp -r $TMP_DIR/.git* $SDK_ROOT
cp -r $TMP_DIR/README.md $SDK_ROOT
cp -r $TMP_DIR/boards_sfe $SDK_ROOT
# clean up temporary folder
rm -rf $TMP_DIR
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# this script relies on the environment variable $AMSDK being set to the root of your AmbiqSuite SDK
# use it when you have a pre-built binary file to upload onto a board
# default variables
BINFILE=.
ASB_UPLOAD_BAUD=115200
PORT=COM4
# immutables
COMMONPATH=$AMSDK/boards_sfe/common
PYTHON3=python3
AMBIQ_BIN2BOARD=$COMMONPATH/tools_sfe/asb/asb.py
BINPATH=temp_
# handle arguments
while getopts ":p:f:b:u:" opt; do
case $opt in
p) PORT="$OPTARG"
;;
f) BINFILE="$OPTARG"
;;
b) ASB_UPLOAD_BAUD="$OPTARG"
;;
u) UPLOADER="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" >&2
;;
esac
done
printf "Uploading file with Ambiq Secure Bootloader:\n%s\n\n" "$BINFILE"
$PYTHON3 $AMBIQ_BIN2BOARD --bin $BINFILE --load-address-blob 0x20000 --magic-num 0xCB -o $BINPATH --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b $ASB_UPLOAD_BAUD -port $PORT -r 2 -v
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Michael Kropat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,18 @@
.PHONY: test
test: lint unit-test
.PHONY: lint
lint:
-shellcheck realpath.sh
-checkbashisms realpath.sh
.PHONY: unit-test
unit-test: t/*
t/%: force
bash "$@"
dash "$@"
.PHONY: force
force: ;
@@ -0,0 +1,43 @@
# sh-realpath
*A portable, pure shell implementation of realpath*
Copy the functions in [realpath.sh](realpath.sh) into your shell script to
avoid introducing a dependency on either `realpath` or `readlink -f`, since:
* `realpath` does not come installed by default
* `readlink -f` **is not portable** to OS-X ([relevant man page](https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man1/readlink.1.html))
## Usage
$ source ./realpath.sh
$ realpath /proc/self
/proc/2772
Or we can get tricky:
$ cd /tmp
$ mkdir -p somedir/targetdir somedir/anotherdir
$ ln -s somedir somedirlink
$ ln -s somedir/anotherdir/../anotherlink somelink
$ ln -s targetdir/targetpath somedir/anotherlink
$ realpath .///somedirlink/././anotherdir/../../somelink
/tmp/somedir/targetdir/targetpath
## API
Note: unlike `realpath(1)`, these functions take no options; **do not** use `--` to escape any arguments
| Function | Description
| --------------------------------- | -------------
| <pre>realpath PATH</pre> | Resolve all symlinks to `PATH`, then output the canonicalized result
| <pre>resolve_symlinks PATH</pre> | If `PATH` is a symlink, follow it as many times as possible; output the path of the first non-symlink found
| <pre>canonicalize_path PATH</pre> | Output absolute path that `PATH` refers to, resolving any relative directories (`.`, `..`) in `PATH` and any symlinks in `PATH`'s ancestor directories
### readlink Emulation
`realpath.sh` includes optional readlink emulation. It exposes a `readlink`
function that calls the system `readlink(1)` if it exists. Otherwise it uses
`stat(1)` to emulate the same functionality. In contrast to the functions in
the previous section, you may pass `--` as the first argument, since you may be
calling the system `readlink(1)`.
@@ -0,0 +1,111 @@
#!/bin/sh
realpath() {
canonicalize_path "$(resolve_symlinks "$1")"
}
resolve_symlinks() {
_resolve_symlinks "$1"
}
_resolve_symlinks() {
_assert_no_path_cycles "$@" || return
local dir_context path
path=$(readlink -- "$1")
if [ $? -eq 0 ]; then
dir_context=$(dirname -- "$1")
_resolve_symlinks "$(_prepend_dir_context_if_necessary "$dir_context" "$path")" "$@"
else
printf '%s\n' "$1"
fi
}
_prepend_dir_context_if_necessary() {
if [ "$1" = . ]; then
printf '%s\n' "$2"
else
_prepend_path_if_relative "$1" "$2"
fi
}
_prepend_path_if_relative() {
case "$2" in
/* ) printf '%s\n' "$2" ;;
* ) printf '%s\n' "$1/$2" ;;
esac
}
_assert_no_path_cycles() {
local target path
target=$1
shift
for path in "$@"; do
if [ "$path" = "$target" ]; then
return 1
fi
done
}
canonicalize_path() {
if [ -d "$1" ]; then
_canonicalize_dir_path "$1"
else
_canonicalize_file_path "$1"
fi
}
_canonicalize_dir_path() {
(cd "$1" 2>/dev/null && pwd -P)
}
_canonicalize_file_path() {
local dir file
dir=$(dirname -- "$1")
file=$(basename -- "$1")
(cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
}
# Optionally, you may also want to include:
### readlink emulation ###
readlink() {
if _has_command readlink; then
_system_readlink "$@"
else
_emulated_readlink "$@"
fi
}
_has_command() {
hash -- "$1" 2>/dev/null
}
_system_readlink() {
command readlink "$@"
}
_emulated_readlink() {
if [ "$1" = -- ]; then
shift
fi
_gnu_stat_readlink "$@" || _bsd_stat_readlink "$@"
}
_gnu_stat_readlink() {
local output
output=$(stat -c %N -- "$1" 2>/dev/null) &&
printf '%s\n' "$output" |
sed "s/^[^]* -> \(.*\)/\1/
s/^'[^']*' -> '\(.*\)'/\1/"
# FIXME: handle newlines
}
_bsd_stat_readlink() {
stat -f %Y -- "$1" 2>/dev/null
}
@@ -0,0 +1,130 @@
#!/bin/sh
. ./realpath.sh
setUp() {
_test_previousdir=$PWD
_test_workingdir=$(mktemp -d -t sh-realpath.XXXXXX)
cd -P -- "$_test_workingdir"
}
tearDown() {
cd -- "$_test_previousdir"
rm -rf -- "$_test_workingdir"
}
it_outputs_pwd_when_passed_zero_args() {
local output
output=$(canonicalize_path)
assertTrue '`canonicalize_path` succeeds' $?
assertEquals 'outputs $PWD' "$PWD/" "$output"
}
it_outputs_absolute_path_to_target_when_passed_the_name_of_a_non_existent_file() {
local output
output=$(canonicalize_path non_existent_file)
assertTrue '`canonicalize_path non_existent_file` succeeds' $?
assertEquals 'output is "$PWD/non_existent_file"' "$PWD/non_existent_file" "$output"
}
it_returns_an_error_when_passed_a_path_in_a_non_existent_dir() {
local output
output=$(canonicalize_path non_existent_dir/somepath 2>&1)
assertFalse '`canonicalize_path non_existent_dir/somepath` fails' $?
assertNull 'no output' "$output"
}
it_outputs_absolute_path_when_passed_the_name_of_a_path_in_a_subdir() {
local output
mkdir somedir
output=$(canonicalize_path somedir/somepath)
assertTrue '`canonicalize_path somedir/somepath` succeeds' $?
assertEquals 'output is "$PWD/somedir/somepath"' "$PWD/somedir/somepath" "$output"
}
it_returns_an_error_when_passed_a_path_in_a_symlink_to_nowhere() {
ln -s non/existent/dir somelink
canonicalize_path somelink/somepath
assertFalse '`canonicalize_path somelink/somepath` fails' $?
}
it_returns_the_target_dir_when_passed_a_symlink_to_another_dir() {
local output
mkdir somedir
ln -s somedir somelink
output=$(canonicalize_path somelink)
assertTrue '`canonicalize_path somelink` succeeds' $?
assertEquals 'output is "$PWD/somedir"' "$PWD/somedir" "$output"
}
it_returns_absolute_path_of_target_directory_when_passed_a_path_in_a_symlink_to_another_dir() {
local output
mkdir somedir
ln -s somedir somelink
output=$(canonicalize_path somelink/somepath)
assertTrue '`canonicalize_path somelink/somepath` succeeds' $?
assertEquals 'output is "$PWD/somedir/somepath"' "$PWD/somedir/somepath" "$output"
}
it_collapses_current_dir_references() {
local output
output=$(canonicalize_path ././somepath)
assertTrue '`canonicalize_path ././somepath` succeeds' $?
assertEquals 'output is "$PWD/somepath"' "$PWD/somepath" "$output"
}
it_collapses_extra_slashes() {
local output
output=$(canonicalize_path .///somepath)
assertTrue '`canonicalize_path .///somepath` succeeds' $?
assertEquals 'output is "$PWD/somepath"' "$PWD/somepath" "$output"
}
it_collapses_parent_dir_references() {
local output
mkdir -p somedir/anotherdir
output=$(canonicalize_path somedir/anotherdir/../../somepath)
assertTrue '`canonicalize_path somedir/anotherdir/../../somepath` succeeds' $?
assertEquals 'output is "$PWD/somepath"' "$PWD/somepath" "$output"
}
##### Test Harness #####
# suite() -- find and register tests to be run
# Derived from Gary Bernhardt's screencast #68
# (https://www.destroyallsoftware.com/screencasts/catalog/test-driving-shell-scripts)
suite() {
local name tests
tests=$(grep ^it_ "$0" | cut -d '(' -f 1)
for name in $tests; do
suite_addTest "$name"
done
}
if hash shunit2 2>/dev/null; then
. shunit2
else
echo 'Error: shunit2(1) could not be located. Please install it on your $PATH.' >&2
exit 1
fi
@@ -0,0 +1,126 @@
#!/bin/sh
. ./realpath.sh
setUp() {
unset _system_readlink _gnu_stat_readlink _bsd_stat_readlink
_has_command() {
return 1
}
}
it_calls_system_readlink_when_has_command_readlink_is_true() {
_has_command() {
test "$1" = readlink
}
local readlink_arg1 readlink_arg2
_system_readlink() {
readlink_arg1="$1"
readlink_arg2="$2"
}
readlink -- some/path
assertEquals -- "$readlink_arg1"
assertEquals some/path "$readlink_arg2"
}
it_calls__gnu_stat_readlink_when_has_command_readlink_is_false() {
local called
_gnu_stat_readlink() {
called=1
}
readlink -- some/path
assertNotNull "_gnu_stat_readlink called" "$called"
}
it_passes_actual_arg_to__gnu_stat_readlink() {
local arg
_gnu_stat_readlink() {
arg="$1"
}
readlink -- some/path
assertEquals some/path "$arg"
}
it_passes_first_arg_to__gnu_stat_readlink_when_no_dashes() {
local arg
_gnu_stat_readlink() {
arg="$1"
}
readlink some/path
assertEquals some/path "$arg"
}
it_doesnt_call__bsd_stat_readlink_when__gnu_stat_readlink_returns_true() {
_gnu_stat_readlink() {
return 0
}
local called
_bsd_stat_readlink() {
called=1
}
readlink -- some/path
assertNull "_bsd_stat_readlink not called" "$called"
}
it_calls__bsd_stat_readlink_when__gnu_stat_readlink_returns_false() {
_gnu_stat_readlink() {
return 1
}
local called
_bsd_stat_readlink() {
called=1
}
readlink -- some/path
assertNotNull "_bsd_stat_readlink called" "$called"
}
it_passes_actual_arg_to__bsd_stat_readlink() {
_gnu_stat_readlink() {
return 1
}
local arg
_bsd_stat_readlink() {
arg="$1"
}
readlink -- some/path
assertEquals some/path "$arg"
}
##### Test Harness #####
# suite() -- find and register tests to be run
# Derived from Gary Bernhardt's screencast #68
# (https://www.destroyallsoftware.com/screencasts/catalog/test-driving-shell-scripts)
suite() {
local name tests
tests=$(grep ^it_ "$0" | cut -d '(' -f 1)
for name in $tests; do
suite_addTest "$name"
done
}
if hash shunit2 2>/dev/null; then
. shunit2
else
echo 'Error: shunit2(1) could not be located. Please install it on your $PATH.' >&2
exit 1
fi

Some files were not shown because too many files have changed in this diff Show More