You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2022/03/03 15:27:59 UTC

[GitHub] [mynewt-core] t3zeng opened a new pull request #2784: Ambiq Apollo3 EVB Mynewt Port

t3zeng opened a new pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784


   This changeset brings BSP support for Ambiq Apollo3 EVB and MCU support for mynewt projects using the Ambiq Apollo3 MCU.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826251212



##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {

Review comment:
       Fixed

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);

Review comment:
       Removed extra space

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int
+hal_i2c_init(uint8_t i2c_num, void *usercfg)
+{
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg *cfg = usercfg;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(cfg->sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(cfg->scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg) {
+    am_hal_iom_config_t iom_cfg;
+        
+    iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
+
+    /* Frequency is in khz, map to AM_HAL_IOM frequencies */
+    switch(cfg->frequency) {
+        case 100:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
+            break;
+        case 400:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
+            break;
+        case 1000:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
+            break;
+        default:
+            return -1;
+    }
+
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &iom_cfg);
+
+    return 0;
+}
+
+int
+hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_TX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32TxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;

Review comment:
       Removed the line




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] sjanc commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r827066195



##########
File path: hw/mcu/ambiq/apollo2/pkg.yml
##########
@@ -25,6 +25,13 @@ pkg.keywords:
     - ambiq
     - apollo2
 
+pkg.cflags:
+    - '-DAM_PART_APOLLO2'
+
+pkg.src_dirs:
+    - "ext/AmbiqSuite/utils/"
+    - "ext/AmbiqSuite/mcu/"

Review comment:
       looks like this broke apollo2 build on travis
   should this be src/ext/Ambiq.. ?
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826253963



##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );

Review comment:
       Fixed

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);

Review comment:
       Added the spaces

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);

Review comment:
       Added the spaces




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826250999



##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =

Review comment:
       Renamed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#issuecomment-1067195718


   > 
   
   I went ahead and added arduino pins and defined the led blink pin for the blinky app. 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826277870



##########
File path: hw/mcu/ambiq/apollo3/src/hal_system.c
##########
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdint.h>
+#include "os/mynewt.h"
+#include "mcu/cortex_m4.h"
+#include "hal/hal_system.h"
+#include "am_mcu_apollo.h"
+
+am_hal_mcuctrl_device_t adevinfo;
+
+void
+hal_system_init(void)
+{
+}
+
+void
+hal_system_reset(void)
+{
+
+#if MYNEWT_VAL(HAL_SYSTEM_RESET_CB)
+    hal_system_reset_cb();
+#endif
+
+    while (1) {
+        HAL_DEBUG_BREAK();
+        NVIC_SystemReset();
+    }
+}
+
+enum hal_reset_reason
+hal_reset_cause(void)
+{
+    enum hal_reset_reason reason = 0;
+    return (reason);

Review comment:
       Changed this to `HAL_RESET_OTHER` and added a todo




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826248444



##########
File path: hw/drivers/adc/adc_apollo3/include/adc_apollo3/adc_apollo3.h
##########
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __ADC_APOLLO3_H__
+#define __ADC_APOLLO3_H__
+
+#include <adc/adc.h>
+#include "am_mcu_apollo.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ADC_APOLLO3_TMR_NUM
+
+enum apollo3_adc_clock_num_e {
+    APOLLO3_ADC_CLOCK_0 = 0,
+    APOLLO3_ADC_CLOCK_1,
+    APOLLO3_ADC_CLOCK_2,
+    APOLLO3_ADC_CLOCK_3,
+    APOLLO3_ADC_CLOCK_CNT
+};
+
+enum apollo3_adc_timer_ab_e {
+    APOLLO3_ADC_TIMER_A = 0,
+    APOLLO3_ADC_TIMER_B,
+    APOLLO3_ADC_TIMER_BOTH
+};
+#define APOLLO3_ADC_TIMER_AB_CNT APOLLO3_ADC_TIMER_BOTH
+
+enum apollo3_adc_timer_func_e {
+    APOLLO3_ADC_TIMER_FUNC_ONCE = 0,
+    APOLLO3_ADC_TIMER_FUNC_REPEAT,
+    APOLLO3_ADC_TIMER_FUNC_PWM_ONCE,
+    APOLLO3_ADC_TIMER_FUNC_PWM_REPEAT,
+    APOLLO3_ADC_TIMER_FUNC_CONTINUOUS
+};
+
+struct apollo3_clk_cfg {

Review comment:
       Changed the name to `apollo3_adc_clk_cfg`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826251808



##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int
+hal_i2c_init(uint8_t i2c_num, void *usercfg)
+{
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg *cfg = usercfg;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(cfg->sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(cfg->scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg) {
+    am_hal_iom_config_t iom_cfg;
+        
+    iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
+
+    /* Frequency is in khz, map to AM_HAL_IOM frequencies */
+    switch(cfg->frequency) {
+        case 100:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
+            break;
+        case 400:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
+            break;
+        case 1000:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
+            break;
+        default:
+            return -1;
+    }
+
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &iom_cfg);
+
+    return 0;
+}
+
+int
+hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_TX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32TxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;

Review comment:
       Added a return status check so it doesn't blindly return 0 all the time

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int
+hal_i2c_init(uint8_t i2c_num, void *usercfg)
+{
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg *cfg = usercfg;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(cfg->sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(cfg->scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg) {
+    am_hal_iom_config_t iom_cfg;
+        
+    iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
+
+    /* Frequency is in khz, map to AM_HAL_IOM frequencies */
+    switch(cfg->frequency) {
+        case 100:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
+            break;
+        case 400:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
+            break;
+        case 1000:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
+            break;
+        default:
+            return -1;
+    }
+
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &iom_cfg);
+
+    return 0;
+}
+
+int
+hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_TX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32TxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int
+hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                    uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_RX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32RxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int hal_i2c_master_probe(uint8_t i2c_num, uint8_t address, uint32_t timeout) {
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_RX;
+    Transaction.ui32NumBytes    = 0;
+    Transaction.pui32RxBuffer   = NULL;
+    Transaction.bContinue       = false;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t)address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int hal_i2c_enable(uint8_t i2c_num) {
+    am_hal_iom_enable(g_i2c_handles[i2c_num]);
+    
+    return 0;
+}
+
+int hal_i2c_disable(uint8_t i2c_num) {
+    am_hal_iom_enable(g_i2c_handles[i2c_num]);

Review comment:
       Good catch, changed this




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826250794



##########
File path: hw/mcu/ambiq/apollo3/src/hal_flash.c
##########
@@ -0,0 +1,205 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include "os/mynewt.h"
+#include <am_hal_flash.h>
+#include <hal/hal_flash_int.h>
+#include <hal/hal_flash.h>
+#include <mcu/system_apollo3.h>
+
+
+static int
+apollo3_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
+    uint32_t num_bytes);
+static int
+apollo3_flash_write(const struct hal_flash *dev, uint32_t address,
+        const void *src, uint32_t num_bytes);
+static int
+apollo3_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_addr);
+static int
+apollo3_flash_sector_info(const struct hal_flash *dev, int idx, uint32_t *addr,
+    uint32_t *sz);
+static int
+apollo3_flash_init(const struct hal_flash *dev);
+
+static const struct hal_flash_funcs apollo3_flash_funcs = {
+    .hff_read = apollo3_flash_read,
+    .hff_write = apollo3_flash_write,
+    .hff_erase_sector = apollo3_flash_erase_sector,
+    .hff_sector_info = apollo3_flash_sector_info,
+    .hff_init = apollo3_flash_init
+};
+
+const struct hal_flash apollo3_flash_dev = {
+        .hf_itf = &apollo3_flash_funcs,
+        .hf_base_addr = 0x00000000,
+        .hf_size = 1024 * 1024,
+        .hf_sector_cnt = 128,
+        .hf_align = 1,
+        .hf_erased_val = 0xff,
+};

Review comment:
       I removed the brackets from the return values for consistency

##########
File path: hw/mcu/ambiq/apollo3/src/hal_gpio.c
##########
@@ -0,0 +1,217 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include "hal/hal_gpio.h"
+#include "mcu/apollo3.h"
+#include "mcu/cmsis_nvic.h"
+#include "am_mcu_apollo.h"
+#include "am_hal_pin.h"
+#include "am_hal_gpio.h"
+
+/* GPIO interrupts */
+#define HAL_GPIO_MAX_IRQ        8
+
+/* Storage for GPIO callbacks. */
+struct hal_gpio_irq {
+    int pin_num;
+    hal_gpio_irq_handler_t func;
+    void *arg;
+};
+
+int
+hal_gpio_init_in(int pin, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;
+    }
+    am_hal_gpio_pinconfig(pin, cfg);
+
+    return (0);
+}
+
+int
+hal_gpio_init_out(int pin, int val)
+{
+    am_hal_gpio_pinconfig(pin, g_AM_HAL_GPIO_OUTPUT);
+    hal_gpio_write(pin, val);
+
+    return (0);
+}
+
+
+void
+hal_gpio_write(int pin, int val)
+{
+    if (val) {
+        am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_SET);
+    } else {
+        am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR);
+    }
+}
+
+int
+hal_gpio_read(int pin)
+{
+    uint32_t state;
+
+    am_hal_gpio_state_read(pin, AM_HAL_GPIO_INPUT_READ, &state);
+
+    return (int)state;
+}
+
+int
+hal_gpio_toggle(int pin)
+{
+    am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_TOGGLE);
+
+    return (0);
+}
+
+/*
+ * GPIO irq handler
+ *
+ * Handles the gpio interrupt attached to a gpio pin.
+ *
+ * @param index
+ */
+static void
+hal_gpio_irq_handler(void)
+{
+    uint64_t status;
+
+    os_trace_isr_enter();
+
+    /* Read and clear the GPIO interrupt status. */
+    am_hal_gpio_interrupt_status_get(false, &status);
+    am_hal_gpio_interrupt_clear(status);
+    am_hal_gpio_interrupt_service(status);
+
+    os_trace_isr_exit();
+}
+
+/*
+ * Register IRQ handler for GPIOTE, and enable it.
+ * Only executed once, during first registration.
+ */
+static void
+hal_gpio_irq_setup(void)
+{
+    static uint8_t irq_setup;
+
+    if (!irq_setup) {
+        NVIC_SetVector(GPIO_IRQn, (uint32_t)hal_gpio_irq_handler);
+        NVIC_SetPriority(GPIO_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+        NVIC_ClearPendingIRQ(GPIO_IRQn);
+        NVIC_EnableIRQ(GPIO_IRQn);
+        irq_setup = 1;
+    }
+}
+
+/**
+ * gpio irq init
+ *
+ * Initialize an external interrupt on a gpio pin
+ *
+ * @param pin       Pin number to enable gpio.
+ * @param handler   Interrupt handler
+ * @param arg       Argument to pass to interrupt handler
+ * @param trig      Trigger mode of interrupt
+ * @param pull      Push/pull mode of input.
+ *
+ * @return int
+ */
+int
+hal_gpio_irq_init(int pin, hal_gpio_irq_handler_t handler, void *arg,
+                  hal_gpio_irq_trig_t trig, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;
+    }
+
+    switch(trig) {

Review comment:
       Added space




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826252155



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size

Review comment:
       Converted these comments to mynewt style




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826255336



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;

Review comment:
       Renamed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] andrzej-kaczmarek commented on pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#issuecomment-1067197607


   you need to rebase this so there are no merges from other branches, just plain commits


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826278399



##########
File path: hw/mcu/ambiq/apollo3/src/hal_uart.c
##########
@@ -0,0 +1,693 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_uart.h"
+#include "mcu/cmsis_nvic.h"
+#include "bsp/bsp.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef UART
+
+uint8_t g_pui8TxBuffer[256];
+uint8_t g_pui8RxBuffer[2];
+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),
+};
+
+/* IRQ handler type */
+typedef void apollo3_uart_irqh_t(void);
+
+/*
+ * 2 UART on Ambiq Apollo 3
+ */
+struct apollo3_uart {
+    uint8_t u_open:1;
+    uint8_t u_rx_stall:1;
+    uint8_t u_tx_started:1;
+    uint8_t u_rx_buf;
+    uint8_t u_tx_buf[1];
+    hal_uart_rx_char u_rx_func;
+    hal_uart_tx_char u_tx_func;
+    hal_uart_tx_done u_tx_done;
+    void *u_func_arg;
+    void *uart_handle;
+};
+static struct apollo3_uart uarts[UART_CNT];
+
+static inline void
+apollo3_uart_enable_tx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_disable_tx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_enable_rx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+static inline void
+apollo3_uart_disable_rx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+int
+hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
+  hal_uart_rx_char rx_func, void *arg)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return -1;
+    }
+
+    u = &uarts[port];
+    if (u->u_open) {
+        return -1;
+    }
+
+    u->u_rx_func = rx_func;
+    u->u_tx_func = tx_func;
+    u->u_tx_done = tx_done;
+    u->u_func_arg = arg;
+
+    return 0;
+}
+
+void
+hal_uart_start_tx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int data;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    if (u->u_tx_started == 0) {
+        while (1) {
+            if (UARTn(0)->FR&UART0_FR_TXFF_Msk) {
+                u->u_tx_started = 1;
+                apollo3_uart_enable_tx_irq();
+                break;
+            }
+
+            data = u->u_tx_func(u->u_func_arg);
+            if (data < 0) {
+                if (u->u_tx_done) {
+                    u->u_tx_done(u->u_func_arg);
+                }
+                break;
+            }
+
+            UARTn(0)->DR = data;
+        }
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+hal_uart_start_rx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int rc;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    if (u->u_rx_stall) {
+        OS_ENTER_CRITICAL(sr);
+        rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+        if (rc == 0) {
+            u->u_rx_stall = 0;
+            apollo3_uart_enable_rx_irq();
+        }
+
+        OS_EXIT_CRITICAL(sr);
+    }
+}
+
+void
+hal_uart_blocking_tx(int port, uint8_t data)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    while (UARTn(0)->FR & UART0_FR_TXFF_Msk);
+    UARTn(0)->DR = data;
+}
+
+static void
+apollo3_uart_irqh_x(int num)
+{
+    struct apollo3_uart *u;
+    uint32_t status;
+    int data;
+    int rc;
+
+    os_trace_isr_enter();
+
+    u = &uarts[num];
+
+    status = UARTn(0)->IES;
+    UARTn(0)->IEC &= ~status;
+
+    if (status & (UART0_IES_TXRIS_Msk)) {
+        if (u->u_tx_started) {
+            while (1) {
+                if (UARTn(0)->FR & UART0_FR_TXFF_Msk) {
+                    break;
+                }
+
+                data = u->u_tx_func(u->u_func_arg);
+                if (data < 0) {
+                    if (u->u_tx_done) {
+                        u->u_tx_done(u->u_func_arg);
+                    }
+                    apollo3_uart_disable_tx_irq();
+                    u->u_tx_started = 0;
+                    break;
+                }
+
+                UARTn(0)->DR = data;
+            }
+        }
+    }
+
+    if (status & (UART0_IES_RXRIS_Msk | UART0_IES_RTRIS_Msk)) {
+        /* Service receive buffer */
+        while (!(UARTn(0)->FR & UART0_FR_RXFE_Msk)) {
+            u->u_rx_buf = UARTn(0)->DR;
+            rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+            if (rc < 0) {
+                u->u_rx_stall = 1;
+                break;
+            }
+        }
+    }
+
+    os_trace_isr_exit();
+}
+
+static void apollo3_uart_irqh_0(void) { apollo3_uart_irqh_x(0); }
+static void apollo3_uart_irqh_1(void) { apollo3_uart_irqh_x(1); }
+
+static int
+apollo3_uart_irq_info(int port, int *out_irqn, apollo3_uart_irqh_t **out_irqh)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+
+    switch (port) {
+    case 0:
+        irqn = UART0_IRQn;
+        irqh = apollo3_uart_irqh_0;
+        break;
+
+    case 1:
+        irqn = UART1_IRQn;
+        irqh = apollo3_uart_irqh_1;
+        break;
+
+    default:
+        return -1;
+    }
+
+    if (out_irqn != NULL) {
+        *out_irqn = irqn;
+    }
+    if (out_irqh != NULL) {
+        *out_irqh = irqh;
+    }
+    return 0;
+}
+
+static void
+apollo3_uart_set_nvic(int port)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+    int rc;
+
+    rc = apollo3_uart_irq_info(port, &irqn, &irqh);
+    assert(rc == 0);
+
+    NVIC_SetVector(irqn, (uint32_t)irqh);
+}
+
+int
+hal_uart_init(int port, void *arg)
+{
+    struct apollo3_uart_cfg *cfg;
+    am_hal_gpio_pincfg_t pincfg;
+
+    cfg = arg;
+
+    if (port >= UART_CNT) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_uart_initialize(port, &(uarts[port].uart_handle));
+
+    am_hal_uart_power_control(uarts[port].uart_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    am_hal_uart_clock_speed_e eUartClockSpeed = eUART_CLK_SPEED_DEFAULT;

Review comment:
       Moved declaration to the top and changed variable name from camel case to snake case




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826277021



##########
File path: hw/mcu/ambiq/apollo3/src/hal_gpio.c
##########
@@ -0,0 +1,217 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include "hal/hal_gpio.h"
+#include "mcu/apollo3.h"
+#include "mcu/cmsis_nvic.h"
+#include "am_mcu_apollo.h"
+#include "am_hal_pin.h"
+#include "am_hal_gpio.h"
+
+/* GPIO interrupts */
+#define HAL_GPIO_MAX_IRQ        8
+
+/* Storage for GPIO callbacks. */
+struct hal_gpio_irq {
+    int pin_num;
+    hal_gpio_irq_handler_t func;
+    void *arg;
+};
+
+int
+hal_gpio_init_in(int pin, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;
+    }
+    am_hal_gpio_pinconfig(pin, cfg);
+
+    return (0);
+}
+
+int
+hal_gpio_init_out(int pin, int val)
+{
+    am_hal_gpio_pinconfig(pin, g_AM_HAL_GPIO_OUTPUT);
+    hal_gpio_write(pin, val);
+
+    return (0);
+}
+
+
+void
+hal_gpio_write(int pin, int val)
+{
+    if (val) {
+        am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_SET);
+    } else {
+        am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR);
+    }
+}
+
+int
+hal_gpio_read(int pin)
+{
+    uint32_t state;
+
+    am_hal_gpio_state_read(pin, AM_HAL_GPIO_INPUT_READ, &state);
+
+    return (int)state;
+}
+
+int
+hal_gpio_toggle(int pin)
+{
+    am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_TOGGLE);
+
+    return (0);
+}
+
+/*
+ * GPIO irq handler
+ *
+ * Handles the gpio interrupt attached to a gpio pin.
+ *
+ * @param index
+ */
+static void
+hal_gpio_irq_handler(void)
+{
+    uint64_t status;
+
+    os_trace_isr_enter();
+
+    /* Read and clear the GPIO interrupt status. */
+    am_hal_gpio_interrupt_status_get(false, &status);
+    am_hal_gpio_interrupt_clear(status);
+    am_hal_gpio_interrupt_service(status);
+
+    os_trace_isr_exit();
+}
+
+/*
+ * Register IRQ handler for GPIOTE, and enable it.
+ * Only executed once, during first registration.
+ */
+static void
+hal_gpio_irq_setup(void)
+{
+    static uint8_t irq_setup;
+
+    if (!irq_setup) {
+        NVIC_SetVector(GPIO_IRQn, (uint32_t)hal_gpio_irq_handler);
+        NVIC_SetPriority(GPIO_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+        NVIC_ClearPendingIRQ(GPIO_IRQn);
+        NVIC_EnableIRQ(GPIO_IRQn);
+        irq_setup = 1;
+    }
+}
+
+/**
+ * gpio irq init
+ *
+ * Initialize an external interrupt on a gpio pin
+ *
+ * @param pin       Pin number to enable gpio.
+ * @param handler   Interrupt handler
+ * @param arg       Argument to pass to interrupt handler
+ * @param trig      Trigger mode of interrupt
+ * @param pull      Push/pull mode of input.
+ *
+ * @return int
+ */
+int
+hal_gpio_irq_init(int pin, hal_gpio_irq_handler_t handler, void *arg,
+                  hal_gpio_irq_trig_t trig, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;

Review comment:
       Fixed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#issuecomment-1067219170


   Rebased to master and split changes to 2 commits, one for Ambiq SDK stuff and one for MCU/BSP implementation


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826252356



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;

Review comment:
       Moved the indentation

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =

Review comment:
       Renamed variable




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826276752



##########
File path: hw/mcu/ambiq/apollo3/src/hal_gpio.c
##########
@@ -0,0 +1,217 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include "hal/hal_gpio.h"
+#include "mcu/apollo3.h"
+#include "mcu/cmsis_nvic.h"
+#include "am_mcu_apollo.h"
+#include "am_hal_pin.h"
+#include "am_hal_gpio.h"
+
+/* GPIO interrupts */
+#define HAL_GPIO_MAX_IRQ        8
+
+/* Storage for GPIO callbacks. */
+struct hal_gpio_irq {
+    int pin_num;
+    hal_gpio_irq_handler_t func;
+    void *arg;
+};
+
+int
+hal_gpio_init_in(int pin, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;

Review comment:
       I implemented pulldown functionality to gpio hal




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826255707



##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int
+hal_i2c_init(uint8_t i2c_num, void *usercfg)
+{
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg *cfg = usercfg;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(cfg->sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(cfg->scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg) {
+    am_hal_iom_config_t iom_cfg;
+        
+    iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
+
+    /* Frequency is in khz, map to AM_HAL_IOM frequencies */
+    switch(cfg->frequency) {
+        case 100:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
+            break;
+        case 400:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
+            break;
+        case 1000:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
+            break;
+        default:
+            return -1;
+    }
+
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &iom_cfg);
+
+    return 0;
+}
+
+int
+hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_TX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32TxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int
+hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                    uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_RX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32RxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int hal_i2c_master_probe(uint8_t i2c_num, uint8_t address, uint32_t timeout) {
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_RX;
+    Transaction.ui32NumBytes    = 0;
+    Transaction.pui32RxBuffer   = NULL;
+    Transaction.bContinue       = false;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t)address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);

Review comment:
       Added error code check here




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826249347



##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }

Review comment:
       Fixed

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))

Review comment:
       Fixed

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);

Review comment:
       Added space

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {

Review comment:
       Fixed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826249104



##########
File path: hw/mcu/ambiq/apollo2/src/ext/AmbiqSuite/utils/am_util_stxetx.c
##########
@@ -45,7 +45,7 @@
 //*****************************************************************************
 #include <stdint.h>
 #include <stdbool.h>
-#include <am_mcu_apollo.h>
+#include "am_mcu_apollo.h"

Review comment:
       Not necessary, I think I just changed this because ambiq sdk had it like that. Reverted




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826253137



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+    uint32_t tx_buf = val;
+    uint32_t rx_buf = 0xffff;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = sizeof(val);
+    Transaction.pui32TxBuffer   = &tx_buf;
+    Transaction.pui32RxBuffer   = &rx_buf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+    
+    if (am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction) != AM_HAL_STATUS_SUCCESS) {
+        return 0xffff;
+    }
+
+    return rx_buf;
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    /* Not implemented */
+    return SYS_ERANGE;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int num_bytes)
+{
+    am_hal_iom_transfer_t Transaction;

Review comment:
       Renamed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826250329



##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {
+                rc = OS_EINVAL;
+                goto err;
+            }
+
+            am_hal_adc_configure_dma(g_apollo3_adc_handle, &(cfg->adc_dma_cfg));
+            g_bADCDMAComplete = false;
+            g_bADCDMAError = false;
+
+            am_hal_adc_interrupt_clear(g_apollo3_adc_handle, 0xFFFFFFFF);
+            break;
+        }
+    }
+
+    *result = (int) sample[0].ui32Sample;
+    rc = 0;
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+    return rc;
+}
+
+static int
+apollo3_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)
+{
+    am_hal_adc_sample_t val;
+    int data_off;
+
+    data_off = off * sizeof(am_hal_adc_sample_t);
+    assert(data_off < buf_len);
+
+    val = *(am_hal_adc_sample_t *) ((uint8_t *) buf + data_off);
+    *result = (int)val.ui32Sample;
+
+    return 0;
+}
+
+static int
+apollo3_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+    return sizeof(am_hal_adc_sample_t) * chans * samples;
+}
+
+void apollo3_irq_handler(void) {
+    uint32_t ui32IntMask;

Review comment:
       Renamed variable




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826253286



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+    uint32_t tx_buf = val;
+    uint32_t rx_buf = 0xffff;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = sizeof(val);
+    Transaction.pui32TxBuffer   = &tx_buf;
+    Transaction.pui32RxBuffer   = &rx_buf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+    
+    if (am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction) != AM_HAL_STATUS_SUCCESS) {
+        return 0xffff;
+    }
+
+    return rx_buf;
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    /* Not implemented */
+    return SYS_ERANGE;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int num_bytes)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = num_bytes;
+    Transaction.pui32TxBuffer   = txbuf;
+    Transaction.pui32RxBuffer   = rxbuf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+
+    return am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction);
+}
+
+/**
+ * Non-blocking interface to send a buffer and store received values. Can be
+ * used for both master and slave SPI types. The user must configure the
+ * callback (using hal_spi_set_txrx_cb); the txrx callback is executed at
+ * interrupt context when the buffer is sent.
+ *
+ * The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL
+ *     SLAVE: Slave "preloads" the data to be sent to the master (values
+ *            stored in txbuf) and places received data from master in rxbuf
+ *            (if not NULL). The txrx callback occurs when len values are
+ *            transferred or master de-asserts chip select. If txbuf is NULL,
+ *            the slave transfers its default byte. Both rxbuf and txbuf cannot
+ *            be NULL.
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param num_bytes Number of 8-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */

Review comment:
       Removed this

##########
File path: hw/mcu/ambiq/apollo3/src/hal_system.c
##########
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdint.h>
+#include "os/mynewt.h"
+#include "mcu/cortex_m4.h"
+#include "hal/hal_system.h"
+#include "am_mcu_apollo.h"
+
+am_hal_mcuctrl_device_t adevinfo;

Review comment:
       Removed

##########
File path: hw/mcu/ambiq/apollo3/src/hal_timer.c
##########
@@ -0,0 +1,815 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "os/mynewt.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_timer.h"
+
+#include "am_mcu_apollo.h"
+
+/**
+ * Note: Each "BSP timer" is implemented using two MCU timers:
+ *
+ * 1. Continuous timer - This timer is constantly running.  It provides
+ *    absolute time values, and is used for converting between relative and
+ *    absolute times.  Its output compare registers are never set.
+ *
+ * 2. "Once" timer - This timer is only used for generating interrupts at
+ *    scheduled times.  It is restarted at 0 for each scheduled event, and only
+ *    relative times are used with this timer.
+ *
+ * As with other HAL timer implementations, event expiry values are stored in
+ * absolute tick values.  To set the "once" timer's output compare register,
+ * the code uses the continuous timer to determine the current time, and uses
+ * the result to calculate the relative offset of the scheduled event.  The
+ * relative time then gets written to the "once" timer's output compare
+ * register.
+ *
+ * This scheme introduces some inaccuracy.  Some amount of time invariably
+ * passes after the current time is read and before the output compare register
+ * is written.  This gap in time causes the timer interrupt to occur later than
+ * it should.  This procedure is done in a critical section to minimize error.
+ *
+ * This somewhat convoluted scheme is required due to hardware limitations. (Apollo3 Blue MCU Datasheet v1.01 section 13.2.7)
+ * Ideally, each BSP timer would be implemented using a single continuous MCU
+ * timer.  However, the MCU only allows a timer to generate a single interrupt
+ * while it is running.  To schedule a second event, the timer would need to be
+ * stopped, cleared, and started again, which defeats the purpose of a
+ * continuous timer.
+ */
+
+#define APOLLO3_TIMER_ANY_ENABLED   \
+    (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(ADC_0))
+
+struct apollo3_timer {
+    TAILQ_HEAD(hal_timer_qhead, hal_timer) hal_timer_q;
+    struct apollo3_timer_cfg cfg;
+    uint32_t freq_hz;       /* Actual frequency. */
+
+    /* Index of continuous timer; measures absolute time. */
+    uint8_t cont_timer_idx;
+
+    /* Index of 'once' timer; used for scheduling interrupts. */
+    uint8_t once_timer_idx;
+
+    /* True if clock is adc clock */
+    bool is_adc_clk;
+};
+
+/**
+ * These lookup tables map frequency values to timer configuration settings.
+ * They are used for selecting a configuration that is closest to the user's
+ * requested frequency.
+ *
+ * Note: These tables must be in ascending order of frequency.
+ */
+struct apollo3_timer_freq_entry {
+    uint32_t freq;
+    uint32_t cfg;
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_hfrc[] = {
+    { 12000,    AM_HAL_CTIMER_HFRC_12KHZ },
+    { 47000,    AM_HAL_CTIMER_HFRC_47KHZ },
+    { 187500,   AM_HAL_CTIMER_HFRC_187_5KHZ },
+    { 3000000,  AM_HAL_CTIMER_HFRC_3MHZ },
+    { 12000000, AM_HAL_CTIMER_HFRC_12MHZ },
+    { 0 },
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_xt[] = {
+    { 256,      AM_HAL_CTIMER_XT_256HZ },
+    { 2048,     AM_HAL_CTIMER_XT_2_048KHZ },
+    { 16384,    AM_HAL_CTIMER_XT_16_384KHZ },
+    { 32768,    AM_HAL_CTIMER_XT_32_768KHZ },
+    { 0 },
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_lfrc[] = {
+    { 1,        AM_HAL_CTIMER_LFRC_1HZ },
+    { 32,       AM_HAL_CTIMER_LFRC_32HZ },
+    { 512,      AM_HAL_CTIMER_LFRC_512HZ },
+    { 1024,     AM_HAL_CTIMER_LFRC_1_16HZ },
+    { 0 },
+};
+
+#if MYNEWT_VAL(TIMER_0)
+static struct apollo3_timer apollo3_timer_0 = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_0.hal_timer_q),
+    .cont_timer_idx = 0,
+    .once_timer_idx = 1,
+    .is_adc_clk = false
+};
+#endif
+#if MYNEWT_VAL(TIMER_1)
+static struct apollo3_timer apollo3_timer_1 = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_1.hal_timer_q),
+    .cont_timer_idx = 2,
+    .once_timer_idx = 4,
+    .is_adc_clk = false
+};
+#endif
+#if MYNEWT_VAL(ADC_0)
+static struct apollo3_timer apollo3_timer_adc = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_adc.hal_timer_q),
+    .cont_timer_idx = 3,
+    .once_timer_idx = 3,
+    .is_adc_clk = true
+};
+#endif
+
+static struct apollo3_timer *
+apollo3_timer_resolve(int timer_num)
+{
+    switch (timer_num) {
+#if MYNEWT_VAL(TIMER_0)
+        case 0:     return &apollo3_timer_0;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+        case 1:     return &apollo3_timer_1;
+#endif
+#if MYNEWT_VAL(ADC_0)
+        case 3:     return &apollo3_timer_adc;
+#endif
+        default:    return NULL;
+    }

Review comment:
       Redid the indentation

##########
File path: hw/mcu/ambiq/apollo3/src/hal_uart.c
##########
@@ -0,0 +1,693 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_uart.h"
+#include "mcu/cmsis_nvic.h"
+#include "bsp/bsp.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef UART
+
+uint8_t g_pui8TxBuffer[256];
+uint8_t g_pui8RxBuffer[2];
+const am_hal_uart_config_t g_sUartConfig =

Review comment:
       Renamed the variables

##########
File path: hw/mcu/ambiq/apollo3/src/hal_uart.c
##########
@@ -0,0 +1,693 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_uart.h"
+#include "mcu/cmsis_nvic.h"
+#include "bsp/bsp.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef UART
+
+uint8_t g_pui8TxBuffer[256];
+uint8_t g_pui8RxBuffer[2];
+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),
+};
+
+/* IRQ handler type */
+typedef void apollo3_uart_irqh_t(void);
+
+/*
+ * 2 UART on Ambiq Apollo 3
+ */
+struct apollo3_uart {
+    uint8_t u_open:1;
+    uint8_t u_rx_stall:1;
+    uint8_t u_tx_started:1;
+    uint8_t u_rx_buf;
+    uint8_t u_tx_buf[1];
+    hal_uart_rx_char u_rx_func;
+    hal_uart_tx_char u_tx_func;
+    hal_uart_tx_done u_tx_done;
+    void *u_func_arg;
+    void *uart_handle;
+};
+static struct apollo3_uart uarts[UART_CNT];
+
+static inline void
+apollo3_uart_enable_tx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_disable_tx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_enable_rx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+static inline void
+apollo3_uart_disable_rx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+int
+hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
+  hal_uart_rx_char rx_func, void *arg)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return -1;
+    }
+
+    u = &uarts[port];
+    if (u->u_open) {
+        return -1;
+    }
+
+    u->u_rx_func = rx_func;
+    u->u_tx_func = tx_func;
+    u->u_tx_done = tx_done;
+    u->u_func_arg = arg;
+
+    return 0;
+}
+
+void
+hal_uart_start_tx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int data;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    if (u->u_tx_started == 0) {
+        while (1) {
+            if (UARTn(0)->FR&UART0_FR_TXFF_Msk) {
+                u->u_tx_started = 1;
+                apollo3_uart_enable_tx_irq();
+                break;
+            }
+
+            data = u->u_tx_func(u->u_func_arg);
+            if (data < 0) {
+                if (u->u_tx_done) {
+                    u->u_tx_done(u->u_func_arg);
+                }
+                break;
+            }
+
+            UARTn(0)->DR = data;
+        }
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+hal_uart_start_rx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int rc;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    if (u->u_rx_stall) {
+        OS_ENTER_CRITICAL(sr);
+        rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+        if (rc == 0) {
+            u->u_rx_stall = 0;
+            apollo3_uart_enable_rx_irq();
+        }
+
+        OS_EXIT_CRITICAL(sr);
+    }
+}
+
+void
+hal_uart_blocking_tx(int port, uint8_t data)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    while (UARTn(0)->FR & UART0_FR_TXFF_Msk);
+    UARTn(0)->DR = data;
+}
+
+static void
+apollo3_uart_irqh_x(int num)
+{
+    struct apollo3_uart *u;
+    uint32_t status;
+    int data;
+    int rc;
+
+    os_trace_isr_enter();
+
+    u = &uarts[num];
+
+    status = UARTn(0)->IES;
+    UARTn(0)->IEC &= ~status;
+
+    if (status & (UART0_IES_TXRIS_Msk)) {
+        if (u->u_tx_started) {
+            while (1) {
+                if (UARTn(0)->FR & UART0_FR_TXFF_Msk) {
+                    break;
+                }
+
+                data = u->u_tx_func(u->u_func_arg);
+                if (data < 0) {
+                    if (u->u_tx_done) {
+                        u->u_tx_done(u->u_func_arg);
+                    }
+                    apollo3_uart_disable_tx_irq();
+                    u->u_tx_started = 0;
+                    break;
+                }
+
+                UARTn(0)->DR = data;
+            }
+        }
+    }
+
+    if (status & (UART0_IES_RXRIS_Msk | UART0_IES_RTRIS_Msk)) {
+        /* Service receive buffer */
+        while (!(UARTn(0)->FR & UART0_FR_RXFE_Msk)) {
+            u->u_rx_buf = UARTn(0)->DR;
+            rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+            if (rc < 0) {
+                u->u_rx_stall = 1;
+                break;
+            }
+        }
+    }
+
+    os_trace_isr_exit();
+}
+
+static void apollo3_uart_irqh_0(void) { apollo3_uart_irqh_x(0); }
+static void apollo3_uart_irqh_1(void) { apollo3_uart_irqh_x(1); }
+
+static int
+apollo3_uart_irq_info(int port, int *out_irqn, apollo3_uart_irqh_t **out_irqh)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+
+    switch (port) {
+    case 0:
+        irqn = UART0_IRQn;
+        irqh = apollo3_uart_irqh_0;
+        break;
+
+    case 1:
+        irqn = UART1_IRQn;
+        irqh = apollo3_uart_irqh_1;
+        break;
+
+    default:
+        return -1;
+    }
+
+    if (out_irqn != NULL) {
+        *out_irqn = irqn;
+    }
+    if (out_irqh != NULL) {
+        *out_irqh = irqh;
+    }
+    return 0;
+}
+
+static void
+apollo3_uart_set_nvic(int port)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+    int rc;
+
+    rc = apollo3_uart_irq_info(port, &irqn, &irqh);
+    assert(rc == 0);
+
+    NVIC_SetVector(irqn, (uint32_t)irqh);
+}
+
+int
+hal_uart_init(int port, void *arg)
+{
+    struct apollo3_uart_cfg *cfg;
+    am_hal_gpio_pincfg_t pincfg;
+
+    cfg = arg;
+
+    if (port >= UART_CNT) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_uart_initialize(port, &(uarts[port].uart_handle));
+
+    am_hal_uart_power_control(uarts[port].uart_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    am_hal_uart_clock_speed_e eUartClockSpeed = eUART_CLK_SPEED_DEFAULT;
+    am_hal_uart_control(uarts[port].uart_handle, AM_HAL_UART_CONTROL_CLKSEL, &eUartClockSpeed);
+    am_hal_uart_configure(uarts[port].uart_handle, &g_sUartConfig);
+
+    switch (port) {
+      case 0:
+        switch (cfg->suc_pin_tx) {
+          case 22:
+          case 39:
+          case 48:
+            pincfg.uFuncSel = 0;
+            break;
+          case 1:
+            pincfg.uFuncSel = 2;
+            break;
+          case 20:
+          case 30:
+            pincfg.uFuncSel = 4;
+            break;
+          case 7:
+            pincfg.uFuncSel = 5;
+            break;
+          case 16:
+          case 26:
+          case 28:
+          case 41:
+          case 44:
+            pincfg.uFuncSel = 6;
+            break;
+          default:
+            return SYS_EINVAL;

Review comment:
       Redid the indentation

##########
File path: hw/mcu/ambiq/apollo3/src/hal_uart.c
##########
@@ -0,0 +1,693 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_uart.h"
+#include "mcu/cmsis_nvic.h"
+#include "bsp/bsp.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef UART
+
+uint8_t g_pui8TxBuffer[256];
+uint8_t g_pui8RxBuffer[2];
+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),
+};
+
+/* IRQ handler type */
+typedef void apollo3_uart_irqh_t(void);
+
+/*
+ * 2 UART on Ambiq Apollo 3
+ */
+struct apollo3_uart {
+    uint8_t u_open:1;
+    uint8_t u_rx_stall:1;
+    uint8_t u_tx_started:1;
+    uint8_t u_rx_buf;
+    uint8_t u_tx_buf[1];
+    hal_uart_rx_char u_rx_func;
+    hal_uart_tx_char u_tx_func;
+    hal_uart_tx_done u_tx_done;
+    void *u_func_arg;
+    void *uart_handle;
+};
+static struct apollo3_uart uarts[UART_CNT];
+
+static inline void
+apollo3_uart_enable_tx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_disable_tx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_enable_rx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+static inline void
+apollo3_uart_disable_rx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+int
+hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
+  hal_uart_rx_char rx_func, void *arg)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return -1;
+    }
+
+    u = &uarts[port];
+    if (u->u_open) {
+        return -1;
+    }
+
+    u->u_rx_func = rx_func;
+    u->u_tx_func = tx_func;
+    u->u_tx_done = tx_done;
+    u->u_func_arg = arg;
+
+    return 0;
+}
+
+void
+hal_uart_start_tx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int data;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    if (u->u_tx_started == 0) {
+        while (1) {
+            if (UARTn(0)->FR&UART0_FR_TXFF_Msk) {
+                u->u_tx_started = 1;
+                apollo3_uart_enable_tx_irq();
+                break;
+            }
+
+            data = u->u_tx_func(u->u_func_arg);
+            if (data < 0) {
+                if (u->u_tx_done) {
+                    u->u_tx_done(u->u_func_arg);
+                }
+                break;
+            }
+
+            UARTn(0)->DR = data;
+        }
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+hal_uart_start_rx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int rc;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    if (u->u_rx_stall) {
+        OS_ENTER_CRITICAL(sr);
+        rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+        if (rc == 0) {
+            u->u_rx_stall = 0;
+            apollo3_uart_enable_rx_irq();
+        }
+
+        OS_EXIT_CRITICAL(sr);
+    }
+}
+
+void
+hal_uart_blocking_tx(int port, uint8_t data)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    while (UARTn(0)->FR & UART0_FR_TXFF_Msk);
+    UARTn(0)->DR = data;
+}
+
+static void
+apollo3_uart_irqh_x(int num)
+{
+    struct apollo3_uart *u;
+    uint32_t status;
+    int data;
+    int rc;
+
+    os_trace_isr_enter();
+
+    u = &uarts[num];
+
+    status = UARTn(0)->IES;
+    UARTn(0)->IEC &= ~status;
+
+    if (status & (UART0_IES_TXRIS_Msk)) {
+        if (u->u_tx_started) {
+            while (1) {
+                if (UARTn(0)->FR & UART0_FR_TXFF_Msk) {
+                    break;
+                }
+
+                data = u->u_tx_func(u->u_func_arg);
+                if (data < 0) {
+                    if (u->u_tx_done) {
+                        u->u_tx_done(u->u_func_arg);
+                    }
+                    apollo3_uart_disable_tx_irq();
+                    u->u_tx_started = 0;
+                    break;
+                }
+
+                UARTn(0)->DR = data;
+            }
+        }
+    }
+
+    if (status & (UART0_IES_RXRIS_Msk | UART0_IES_RTRIS_Msk)) {
+        /* Service receive buffer */
+        while (!(UARTn(0)->FR & UART0_FR_RXFE_Msk)) {
+            u->u_rx_buf = UARTn(0)->DR;
+            rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+            if (rc < 0) {
+                u->u_rx_stall = 1;
+                break;
+            }
+        }
+    }
+
+    os_trace_isr_exit();
+}
+
+static void apollo3_uart_irqh_0(void) { apollo3_uart_irqh_x(0); }
+static void apollo3_uart_irqh_1(void) { apollo3_uart_irqh_x(1); }
+
+static int
+apollo3_uart_irq_info(int port, int *out_irqn, apollo3_uart_irqh_t **out_irqh)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+
+    switch (port) {
+    case 0:
+        irqn = UART0_IRQn;
+        irqh = apollo3_uart_irqh_0;
+        break;
+
+    case 1:
+        irqn = UART1_IRQn;
+        irqh = apollo3_uart_irqh_1;
+        break;
+
+    default:
+        return -1;
+    }
+
+    if (out_irqn != NULL) {
+        *out_irqn = irqn;
+    }
+    if (out_irqh != NULL) {
+        *out_irqh = irqh;
+    }
+    return 0;
+}
+
+static void
+apollo3_uart_set_nvic(int port)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+    int rc;
+
+    rc = apollo3_uart_irq_info(port, &irqn, &irqh);
+    assert(rc == 0);
+
+    NVIC_SetVector(irqn, (uint32_t)irqh);
+}
+
+int
+hal_uart_init(int port, void *arg)
+{
+    struct apollo3_uart_cfg *cfg;
+    am_hal_gpio_pincfg_t pincfg;
+
+    cfg = arg;
+
+    if (port >= UART_CNT) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_uart_initialize(port, &(uarts[port].uart_handle));
+
+    am_hal_uart_power_control(uarts[port].uart_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    am_hal_uart_clock_speed_e eUartClockSpeed = eUART_CLK_SPEED_DEFAULT;
+    am_hal_uart_control(uarts[port].uart_handle, AM_HAL_UART_CONTROL_CLKSEL, &eUartClockSpeed);
+    am_hal_uart_configure(uarts[port].uart_handle, &g_sUartConfig);
+
+    switch (port) {
+      case 0:
+        switch (cfg->suc_pin_tx) {
+          case 22:
+          case 39:
+          case 48:
+            pincfg.uFuncSel = 0;
+            break;
+          case 1:
+            pincfg.uFuncSel = 2;
+            break;
+          case 20:
+          case 30:
+            pincfg.uFuncSel = 4;
+            break;
+          case 7:
+            pincfg.uFuncSel = 5;
+            break;
+          case 16:
+          case 26:
+          case 28:
+          case 41:
+          case 44:
+            pincfg.uFuncSel = 6;
+            break;
+          default:
+            return SYS_EINVAL;
+        }
+        break;
+      case 1:
+        switch (cfg->suc_pin_tx) {
+          case 10:
+          case 24:
+          case 42:
+            pincfg.uFuncSel = 0;
+            break;
+          case 39:
+            pincfg.uFuncSel = 1;
+            break;
+          case 14:
+          case 35:
+            pincfg.uFuncSel = 2;
+            break;
+          case 20:
+          case 37:
+            pincfg.uFuncSel = 5;
+            break;
+          case 8:
+          case 18:
+          case 46:
+            pincfg.uFuncSel = 6;
+            break;
+          case 12:
+            pincfg.uFuncSel = 7;
+            break;
+          default:
+            return SYS_EINVAL;
+        }
+        break;
+      default:
+        return SYS_EINVAL;
+    }
+    pincfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA;
+    am_hal_gpio_pinconfig(cfg->suc_pin_tx, pincfg);
+
+    switch (port) {
+      case 0:
+        switch (cfg->suc_pin_rx) {
+          case 23:
+          case 27:
+          case 40:
+          case 49:
+            pincfg.uFuncSel = 0;
+            break;
+          case 2:
+            pincfg.uFuncSel = 2;
+            break;
+          case 21:
+          case 31:
+            pincfg.uFuncSel = 4;
+            break;
+          case 11:
+          case 17:
+          case 29:
+          case 34:
+          case 45:
+            pincfg.uFuncSel = 6;
+            break;
+          default:
+            return SYS_EINVAL;
+        }
+        break;
+      case 1:
+        switch (cfg->suc_pin_rx) {
+          case 2:
+          case 25:
+          case 43:
+            pincfg.uFuncSel = 0;
+            break;
+          case 40:
+            pincfg.uFuncSel = 1;
+            break;
+          case 15:
+          case 36:
+            pincfg.uFuncSel = 2;
+            break;
+          case 4:
+          case 21:
+            pincfg.uFuncSel = 5;
+            break;
+          case 9:
+          case 19:
+          case 38:
+          case 47:
+            pincfg.uFuncSel = 6;
+            break;
+          case 13:
+            pincfg.uFuncSel = 7;
+            break;
+          default:
+            return SYS_EINVAL;
+        }
+        break;
+      default:
+        return SYS_EINVAL;
+    }
+    am_hal_gpio_pinconfig(cfg->suc_pin_rx, pincfg);
+
+    /* RTS pin is optional. */
+    if (cfg->suc_pin_rts >= 0) {
+      switch (port) {
+        case 0:
+          switch (cfg->suc_pin_rts) {
+            case 3:
+              pincfg.uFuncSel = 0;
+              break;
+            case 5:
+            case 37:
+              pincfg.uFuncSel = 2;
+              break;
+            case 18:
+              pincfg.uFuncSel = 4;
+              break;
+            case 34:
+              pincfg.uFuncSel = 5;
+              break;
+            case 13:
+            case 35:
+              pincfg.uFuncSel = 6;
+              break;
+            case 41:
+              pincfg.uFuncSel = 7;
+              break;
+            default:
+              return SYS_EINVAL;
+          }
+          break;
+        case 1:
+          switch (cfg->suc_pin_rts) {
+            case 44:
+              pincfg.uFuncSel = 0;
+              break;
+            case 34:
+              pincfg.uFuncSel = 2;
+              break;
+            case 10:
+            case 30:
+            case 41:
+              pincfg.uFuncSel = 5;
+              break;
+            case 16:
+            case 20:
+            case 31:
+              pincfg.uFuncSel = 7;
+              break;
+            default:
+              return SYS_EINVAL;
+          }
+          break;
+        default:
+          return SYS_EINVAL;
+      }
+      pincfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA;
+      am_hal_gpio_pinconfig(cfg->suc_pin_rts, pincfg);
+    }
+
+    /* CTS pin is optional. */
+    if (cfg->suc_pin_cts >= 0) {
+      switch (port) {
+        case 0:
+          switch (cfg->suc_pin_cts) {
+            case 4:
+              pincfg.uFuncSel = 0;
+              break;
+            case 6:
+            case 38:
+              pincfg.uFuncSel = 2;
+              break;
+            case 24:
+            case 29:
+              pincfg.uFuncSel = 4;
+              break;
+            case 33:
+              pincfg.uFuncSel = 5;
+              break;
+            case 12:
+            case 36:
+              pincfg.uFuncSel = 6;
+              break;
+            default:
+              return SYS_EINVAL;
+          }
+          break;
+        case 1:
+          switch (cfg->suc_pin_cts) {
+            case 45:
+              pincfg.uFuncSel = 0;
+              break;
+            case 11:
+            case 29:
+            case 36:
+            case 41:
+              pincfg.uFuncSel = 5;
+              break;
+            case 17:
+            case 21:
+            case 26:
+            case 32:
+              pincfg.uFuncSel = 7;
+              break;
+            default:
+              return SYS_EINVAL;
+          }
+          break;
+        default:
+          return SYS_EINVAL;
+      }
+      am_hal_gpio_pinconfig(cfg->suc_pin_cts, pincfg);
+    }
+
+    apollo3_uart_set_nvic(port);
+
+    return 0;
+}
+
+int
+hal_uart_config(int port, int32_t baudrate, uint8_t databits, uint8_t stopbits,
+  enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
+{
+    struct apollo3_uart *u;
+    int irqn;
+    int rc;
+
+    am_hal_uart_config_t uart_cfg =
+    {

Review comment:
       Fixed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826254451



##########
File path: hw/mcu/ambiq/apollo3/src/apollo3_periph.c
##########
@@ -0,0 +1,550 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_i2c.h"
+#include "hal/hal_spi.h"
+#include "bsp/bsp.h"
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+#include "bus/bus.h"
+#if MYNEWT_VAL(I2C_0) || MYNEWT_VAL(I2C_1) || MYNEWT_VAL(I2C_2) || MYNEWT_VAL(I2C_3) || MYNEWT_VAL(I2C_4) || MYNEWT_VAL(I2C_5)
+#include "bus/drivers/i2c_hal.h"
+#endif
+#if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_1_MASTER) || MYNEWT_VAL(SPI_2_MASTER) || MYNEWT_VAL(SPI_3_MASTER) || MYNEWT_VAL(SPI_4_MASTER) || MYNEWT_VAL(SPI_5_MASTER)
+#include "bus/drivers/spi_apollo3.h"
+#endif
+#endif
+#if MYNEWT_VAL(UART_0) || MYNEWT_VAL(UART_1)
+#include "uart/uart.h"
+#include "uart_hal/uart_hal.h"
+#endif
+#if MYNEWT_VAL(ADC_0)
+#include <adc/adc.h>
+#include <adc_apollo3/adc_apollo3.h>
+#endif
+
+#if MYNEWT_VAL(ADC_0)
+#define ADC_SAMPLE_BUF_SIZE 128
+uint32_t g_ui32ADCSampleBuffer[ADC_SAMPLE_BUF_SIZE];
+
+static struct adc_dev os_bsp_adc0;
+static struct adc_cfg os_bsp_adc0_config = {
+    .adc_cfg = {
+        .eClock             = AM_HAL_ADC_CLKSEL_HFRC,
+        .ePolarity          = AM_HAL_ADC_TRIGPOL_RISING,
+        .eTrigger           = AM_HAL_ADC_TRIGSEL_SOFTWARE,
+        .eReference         = AM_HAL_ADC_REFSEL_INT_1P5,
+        .eClockMode         = AM_HAL_ADC_CLKMODE_LOW_LATENCY,
+        .ePowerMode         = AM_HAL_ADC_LPMODE0,
+        .eRepeat            = AM_HAL_ADC_REPEATING_SCAN,
+    },
+    .adc_slot_cfg = {
+        .eMeasToAvg      = AM_HAL_ADC_SLOT_AVG_128,
+        .ePrecisionMode  = AM_HAL_ADC_SLOT_14BIT,
+        .eChannel        = AM_HAL_ADC_SLOT_CHSEL_SE0,
+        .bWindowCompare  = false,
+        .bEnabled        = true,
+    },
+    .adc_dma_cfg = {
+        .bDynamicPriority = true,
+        .ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED,
+        .bDMAEnable = true,
+        .ui32SampleCount = ADC_SAMPLE_BUF_SIZE,
+        .ui32TargetAddress = (uint32_t)g_ui32ADCSampleBuffer
+    },
+    .clk_cfg = {
+        .clk_freq = 12000000,
+        .clk_period = 10,
+        .clk_on_time = 5,
+        .clk_num = APOLLO3_ADC_CLOCK_3,
+        .timer_ab = APOLLO3_ADC_TIMER_A,
+        .timer_func = APOLLO3_ADC_TIMER_FUNC_REPEAT,
+    }
+};
+#endif
+
+#if MYNEWT_VAL(UART_0)
+static struct uart_dev os_bsp_uart0;
+static const struct apollo3_uart_cfg os_bsp_uart0_cfg = {
+    .suc_pin_tx = MYNEWT_VAL(UART_0_PIN_TX),
+    .suc_pin_rx = MYNEWT_VAL(UART_0_PIN_RX),
+    .suc_pin_rts = MYNEWT_VAL(UART_0_PIN_RTS),
+    .suc_pin_cts = MYNEWT_VAL(UART_0_PIN_CTS),
+};
+#endif
+#if MYNEWT_VAL(UART_1)
+static struct uart_dev os_bsp_uart1;
+static const struct apollo3_uart_cfg os_bsp_uart1_cfg = {
+    .suc_pin_tx = MYNEWT_VAL(UART_1_PIN_TX),
+    .suc_pin_rx = MYNEWT_VAL(UART_1_PIN_RX),
+    .suc_pin_rts = MYNEWT_VAL(UART_1_PIN_RTS),
+    .suc_pin_cts = MYNEWT_VAL(UART_1_PIN_CTS),
+};
+#endif
+
+#if MYNEWT_VAL(I2C_0)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c0_cfg = {
+    .i2c_num = 0,
+    .pin_sda = MYNEWT_VAL(I2C_0_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_0_PIN_SCL),
+};
+static struct bus_i2c_dev i2c0_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c0_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_0_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_0_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_0_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_1)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c1_cfg = {
+    .i2c_num = 1,
+    .pin_sda = MYNEWT_VAL(I2C_1_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_1_PIN_SCL),
+};
+static struct bus_i2c_dev i2c1_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c1_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_1_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_1_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_1_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_2)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c2_cfg = {
+    .i2c_num = 2,
+    .pin_sda = MYNEWT_VAL(I2C_2_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_2_PIN_SCL),
+};
+static struct bus_i2c_dev i2c2_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c2_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_2_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_2_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_2_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_3)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c3_cfg = {
+    .i2c_num = 3,
+    .pin_sda = MYNEWT_VAL(I2C_3_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_3_PIN_SCL),
+};
+static struct bus_i2c_dev i2c3_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c3_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_3_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_3_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_3_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_4)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c4_cfg = {
+    .i2c_num = 4,
+    .pin_sda = MYNEWT_VAL(I2C_4_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_4_PIN_SCL),
+};
+static struct bus_i2c_dev i2c4_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c4_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_4_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_4_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_4_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_5)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c5_cfg = {
+    .i2c_num = 5,
+    .pin_sda = MYNEWT_VAL(I2C_5_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_5_PIN_SCL),
+};
+static struct bus_i2c_dev i2c5_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c5_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_5_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_5_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_5_FREQ_KHZ),
+};
+#endif
+#endif
+
+#if MYNEWT_VAL(SPI_0_SLAVE)
+static const struct apollo3_spi_cfg os_bsp_spi0s_cfg = {
+    .sck_pin      = MYNEWT_VAL(SPI_0_SLAVE_PIN_SCK),
+    .mosi_pin     = MYNEWT_VAL(SPI_0_SLAVE_PIN_MOSI),
+    .miso_pin     = MYNEWT_VAL(SPI_0_SLAVE_PIN_MISO),
+    .ss_pin       = { MYNEWT_VAL(SPI_0_SLAVE_PIN_CS), -1, -1, -1 }
+};
+#endif
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_spi_dev_cfg spi0_cfg = {
+    .spi_num = 0,
+    .pin_sck = MYNEWT_VAL(SPI_0_PIN_SCK),

Review comment:
       Good catch, fixed the misname




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826252768



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;

Review comment:
       Redid the indentation

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:

Review comment:
       Redid the indentation




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng closed pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng closed pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] kasjer commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
kasjer commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r825740258



##########
File path: hw/mcu/ambiq/apollo2/src/ext/AmbiqSuite/utils/am_util_stxetx.c
##########
@@ -45,7 +45,7 @@
 //*****************************************************************************
 #include <stdint.h>
 #include <stdbool.h>
-#include <am_mcu_apollo.h>
+#include "am_mcu_apollo.h"

Review comment:
       Is this change from **<>** to **""** really necessary?

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;

Review comment:
       In mynewt preferred style does not have capital letters in variables rather _ is used

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);

Review comment:
       missing space around `*`

##########
File path: hw/drivers/adc/adc_apollo3/include/adc_apollo3/adc_apollo3.h
##########
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __ADC_APOLLO3_H__
+#define __ADC_APOLLO3_H__
+
+#include <adc/adc.h>
+#include "am_mcu_apollo.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ADC_APOLLO3_TMR_NUM
+
+enum apollo3_adc_clock_num_e {
+    APOLLO3_ADC_CLOCK_0 = 0,
+    APOLLO3_ADC_CLOCK_1,
+    APOLLO3_ADC_CLOCK_2,
+    APOLLO3_ADC_CLOCK_3,
+    APOLLO3_ADC_CLOCK_CNT
+};
+
+enum apollo3_adc_timer_ab_e {
+    APOLLO3_ADC_TIMER_A = 0,
+    APOLLO3_ADC_TIMER_B,
+    APOLLO3_ADC_TIMER_BOTH
+};
+#define APOLLO3_ADC_TIMER_AB_CNT APOLLO3_ADC_TIMER_BOTH
+
+enum apollo3_adc_timer_func_e {
+    APOLLO3_ADC_TIMER_FUNC_ONCE = 0,
+    APOLLO3_ADC_TIMER_FUNC_REPEAT,
+    APOLLO3_ADC_TIMER_FUNC_PWM_ONCE,
+    APOLLO3_ADC_TIMER_FUNC_PWM_REPEAT,
+    APOLLO3_ADC_TIMER_FUNC_CONTINUOUS
+};
+
+struct apollo3_clk_cfg {

Review comment:
       consider changing name to **apollo3_adc_clk_cfg**

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {
+                rc = OS_EINVAL;
+                goto err;
+            }
+
+            am_hal_adc_configure_dma(g_apollo3_adc_handle, &(cfg->adc_dma_cfg));
+            g_bADCDMAComplete = false;
+            g_bADCDMAError = false;
+
+            am_hal_adc_interrupt_clear(g_apollo3_adc_handle, 0xFFFFFFFF);
+            break;
+        }
+    }
+
+    *result = (int) sample[0].ui32Sample;
+    rc = 0;
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+    return rc;
+}
+
+static int
+apollo3_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)
+{
+    am_hal_adc_sample_t val;
+    int data_off;
+
+    data_off = off * sizeof(am_hal_adc_sample_t);
+    assert(data_off < buf_len);
+
+    val = *(am_hal_adc_sample_t *) ((uint8_t *) buf + data_off);
+    *result = (int)val.ui32Sample;
+
+    return 0;
+}
+
+static int
+apollo3_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+    return sizeof(am_hal_adc_sample_t) * chans * samples;
+}
+
+void apollo3_irq_handler(void) {
+    uint32_t ui32IntMask;
+
+    /* Read the interrupt status. */
+    am_hal_adc_interrupt_status(g_apollo3_adc_handle, &ui32IntMask, false);
+
+    /* Clear the ADC interrupt. */
+    am_hal_adc_interrupt_clear(g_apollo3_adc_handle, ui32IntMask);
+
+    /* If we got a DMA complete, set the flag. */
+    if (ui32IntMask & AM_HAL_ADC_INT_DCMP)
+    {
+        g_bADCDMAComplete = true;
+    }
+
+    /* If we got a DMA error, set the flag. */
+    if (ui32IntMask & AM_HAL_ADC_INT_DERR)
+    {

Review comment:
       `{` should be placed in lines with `)` same few lines above

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {
+                rc = OS_EINVAL;
+                goto err;
+            }
+
+            am_hal_adc_configure_dma(g_apollo3_adc_handle, &(cfg->adc_dma_cfg));
+            g_bADCDMAComplete = false;
+            g_bADCDMAError = false;
+
+            am_hal_adc_interrupt_clear(g_apollo3_adc_handle, 0xFFFFFFFF);
+            break;
+        }
+    }
+
+    *result = (int) sample[0].ui32Sample;
+    rc = 0;
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+    return rc;
+}
+
+static int
+apollo3_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)
+{
+    am_hal_adc_sample_t val;
+    int data_off;
+
+    data_off = off * sizeof(am_hal_adc_sample_t);
+    assert(data_off < buf_len);
+
+    val = *(am_hal_adc_sample_t *) ((uint8_t *) buf + data_off);
+    *result = (int)val.ui32Sample;
+
+    return 0;
+}
+
+static int
+apollo3_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+    return sizeof(am_hal_adc_sample_t) * chans * samples;
+}
+
+void apollo3_irq_handler(void) {
+    uint32_t ui32IntMask;

Review comment:
       camel case naming convention use here is not preferred in mynew

##########
File path: hw/mcu/ambiq/apollo3/src/hal_gpio.c
##########
@@ -0,0 +1,217 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include "hal/hal_gpio.h"
+#include "mcu/apollo3.h"
+#include "mcu/cmsis_nvic.h"
+#include "am_mcu_apollo.h"
+#include "am_hal_pin.h"
+#include "am_hal_gpio.h"
+
+/* GPIO interrupts */
+#define HAL_GPIO_MAX_IRQ        8
+
+/* Storage for GPIO callbacks. */
+struct hal_gpio_irq {
+    int pin_num;
+    hal_gpio_irq_handler_t func;
+    void *arg;
+};
+
+int
+hal_gpio_init_in(int pin, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;
+    }
+    am_hal_gpio_pinconfig(pin, cfg);
+
+    return (0);
+}
+
+int
+hal_gpio_init_out(int pin, int val)
+{
+    am_hal_gpio_pinconfig(pin, g_AM_HAL_GPIO_OUTPUT);
+    hal_gpio_write(pin, val);
+
+    return (0);
+}
+
+
+void
+hal_gpio_write(int pin, int val)
+{
+    if (val) {
+        am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_SET);
+    } else {
+        am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR);
+    }
+}
+
+int
+hal_gpio_read(int pin)
+{
+    uint32_t state;
+
+    am_hal_gpio_state_read(pin, AM_HAL_GPIO_INPUT_READ, &state);
+
+    return (int)state;
+}
+
+int
+hal_gpio_toggle(int pin)
+{
+    am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_TOGGLE);
+
+    return (0);
+}
+
+/*
+ * GPIO irq handler
+ *
+ * Handles the gpio interrupt attached to a gpio pin.
+ *
+ * @param index
+ */
+static void
+hal_gpio_irq_handler(void)
+{
+    uint64_t status;
+
+    os_trace_isr_enter();
+
+    /* Read and clear the GPIO interrupt status. */
+    am_hal_gpio_interrupt_status_get(false, &status);
+    am_hal_gpio_interrupt_clear(status);
+    am_hal_gpio_interrupt_service(status);
+
+    os_trace_isr_exit();
+}
+
+/*
+ * Register IRQ handler for GPIOTE, and enable it.
+ * Only executed once, during first registration.
+ */
+static void
+hal_gpio_irq_setup(void)
+{
+    static uint8_t irq_setup;
+
+    if (!irq_setup) {
+        NVIC_SetVector(GPIO_IRQn, (uint32_t)hal_gpio_irq_handler);
+        NVIC_SetPriority(GPIO_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+        NVIC_ClearPendingIRQ(GPIO_IRQn);
+        NVIC_EnableIRQ(GPIO_IRQn);
+        irq_setup = 1;
+    }
+}
+
+/**
+ * gpio irq init
+ *
+ * Initialize an external interrupt on a gpio pin
+ *
+ * @param pin       Pin number to enable gpio.
+ * @param handler   Interrupt handler
+ * @param arg       Argument to pass to interrupt handler
+ * @param trig      Trigger mode of interrupt
+ * @param pull      Push/pull mode of input.
+ *
+ * @return int
+ */
+int
+hal_gpio_irq_init(int pin, hal_gpio_irq_handler_t handler, void *arg,
+                  hal_gpio_irq_trig_t trig, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;
+    }
+
+    switch(trig) {

Review comment:
       space missing after switch

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);

Review comment:
       extra space before `i2c_cfg`
   
   same in next funtion

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {

Review comment:
       `{` should be on next line

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;

Review comment:
       cases indentation should be same as switch

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+

Review comment:
       indentation mismatch
   `ss_pin_funct_sel` and `spi_ss_cfg` should be declared at the beginning of function

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }

Review comment:
       space missing after `if(` shuld be `if (`

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {
+                rc = OS_EINVAL;
+                goto err;
+            }
+
+            am_hal_adc_configure_dma(g_apollo3_adc_handle, &(cfg->adc_dma_cfg));
+            g_bADCDMAComplete = false;
+            g_bADCDMAError = false;
+
+            am_hal_adc_interrupt_clear(g_apollo3_adc_handle, 0xFFFFFFFF);
+            break;
+        }
+    }
+
+    *result = (int) sample[0].ui32Sample;
+    rc = 0;
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+    return rc;
+}
+
+static int
+apollo3_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)

Review comment:
       strange line alignment

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+    uint32_t tx_buf = val;
+    uint32_t rx_buf = 0xffff;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = sizeof(val);
+    Transaction.pui32TxBuffer   = &tx_buf;
+    Transaction.pui32RxBuffer   = &rx_buf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+    
+    if (am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction) != AM_HAL_STATUS_SUCCESS) {
+        return 0xffff;
+    }
+
+    return rx_buf;
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    /* Not implemented */
+    return SYS_ERANGE;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int num_bytes)
+{
+    am_hal_iom_transfer_t Transaction;

Review comment:
       `Transaction` should be `transaction`

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:

Review comment:
       indentation mismatch

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {

Review comment:
       `{` should stay on previous line

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {

Review comment:
       missing space after while

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))

Review comment:
       line should end with `{`

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {
+                rc = OS_EINVAL;
+                goto err;
+            }
+
+            am_hal_adc_configure_dma(g_apollo3_adc_handle, &(cfg->adc_dma_cfg));
+            g_bADCDMAComplete = false;
+            g_bADCDMAError = false;
+
+            am_hal_adc_interrupt_clear(g_apollo3_adc_handle, 0xFFFFFFFF);
+            break;
+        }
+    }
+
+    *result = (int) sample[0].ui32Sample;
+    rc = 0;
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+    return rc;
+}
+
+static int
+apollo3_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)
+{
+    am_hal_adc_sample_t val;
+    int data_off;
+
+    data_off = off * sizeof(am_hal_adc_sample_t);
+    assert(data_off < buf_len);
+
+    val = *(am_hal_adc_sample_t *) ((uint8_t *) buf + data_off);
+    *result = (int)val.ui32Sample;
+
+    return 0;
+}
+
+static int
+apollo3_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+    return sizeof(am_hal_adc_sample_t) * chans * samples;
+}
+
+void apollo3_irq_handler(void) {

Review comment:
       for functions `{` should be in next line

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+    uint32_t tx_buf = val;
+    uint32_t rx_buf = 0xffff;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = sizeof(val);
+    Transaction.pui32TxBuffer   = &tx_buf;
+    Transaction.pui32RxBuffer   = &rx_buf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+    
+    if (am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction) != AM_HAL_STATUS_SUCCESS) {
+        return 0xffff;
+    }
+
+    return rx_buf;
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    /* Not implemented */
+    return SYS_ERANGE;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int num_bytes)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = num_bytes;
+    Transaction.pui32TxBuffer   = txbuf;
+    Transaction.pui32RxBuffer   = rxbuf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+
+    return am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction);
+}
+
+/**
+ * Non-blocking interface to send a buffer and store received values. Can be
+ * used for both master and slave SPI types. The user must configure the
+ * callback (using hal_spi_set_txrx_cb); the txrx callback is executed at
+ * interrupt context when the buffer is sent.
+ *
+ * The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL
+ *     SLAVE: Slave "preloads" the data to be sent to the master (values
+ *            stored in txbuf) and places received data from master in rxbuf
+ *            (if not NULL). The txrx callback occurs when len values are
+ *            transferred or master de-asserts chip select. If txbuf is NULL,
+ *            the slave transfers its default byte. Both rxbuf and txbuf cannot
+ *            be NULL.
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param num_bytes Number of 8-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */

Review comment:
       I would get rid of this comment which is almost identical to prototype in header file

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =

Review comment:
       not mynewt variable naming style used here

##########
File path: hw/mcu/ambiq/apollo3/src/hal_uart.c
##########
@@ -0,0 +1,693 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_uart.h"
+#include "mcu/cmsis_nvic.h"
+#include "bsp/bsp.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef UART
+
+uint8_t g_pui8TxBuffer[256];
+uint8_t g_pui8RxBuffer[2];
+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),
+};
+
+/* IRQ handler type */
+typedef void apollo3_uart_irqh_t(void);
+
+/*
+ * 2 UART on Ambiq Apollo 3
+ */
+struct apollo3_uart {
+    uint8_t u_open:1;
+    uint8_t u_rx_stall:1;
+    uint8_t u_tx_started:1;
+    uint8_t u_rx_buf;
+    uint8_t u_tx_buf[1];
+    hal_uart_rx_char u_rx_func;
+    hal_uart_tx_char u_tx_func;
+    hal_uart_tx_done u_tx_done;
+    void *u_func_arg;
+    void *uart_handle;
+};
+static struct apollo3_uart uarts[UART_CNT];
+
+static inline void
+apollo3_uart_enable_tx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_disable_tx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_enable_rx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+static inline void
+apollo3_uart_disable_rx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+int
+hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
+  hal_uart_rx_char rx_func, void *arg)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return -1;
+    }
+
+    u = &uarts[port];
+    if (u->u_open) {
+        return -1;
+    }
+
+    u->u_rx_func = rx_func;
+    u->u_tx_func = tx_func;
+    u->u_tx_done = tx_done;
+    u->u_func_arg = arg;
+
+    return 0;
+}
+
+void
+hal_uart_start_tx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int data;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    if (u->u_tx_started == 0) {
+        while (1) {
+            if (UARTn(0)->FR&UART0_FR_TXFF_Msk) {
+                u->u_tx_started = 1;
+                apollo3_uart_enable_tx_irq();
+                break;
+            }
+
+            data = u->u_tx_func(u->u_func_arg);
+            if (data < 0) {
+                if (u->u_tx_done) {
+                    u->u_tx_done(u->u_func_arg);
+                }
+                break;
+            }
+
+            UARTn(0)->DR = data;
+        }
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+hal_uart_start_rx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int rc;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    if (u->u_rx_stall) {
+        OS_ENTER_CRITICAL(sr);
+        rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+        if (rc == 0) {
+            u->u_rx_stall = 0;
+            apollo3_uart_enable_rx_irq();
+        }
+
+        OS_EXIT_CRITICAL(sr);
+    }
+}
+
+void
+hal_uart_blocking_tx(int port, uint8_t data)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    while (UARTn(0)->FR & UART0_FR_TXFF_Msk);
+    UARTn(0)->DR = data;
+}
+
+static void
+apollo3_uart_irqh_x(int num)
+{
+    struct apollo3_uart *u;
+    uint32_t status;
+    int data;
+    int rc;
+
+    os_trace_isr_enter();
+
+    u = &uarts[num];
+
+    status = UARTn(0)->IES;
+    UARTn(0)->IEC &= ~status;
+
+    if (status & (UART0_IES_TXRIS_Msk)) {
+        if (u->u_tx_started) {
+            while (1) {
+                if (UARTn(0)->FR & UART0_FR_TXFF_Msk) {
+                    break;
+                }
+
+                data = u->u_tx_func(u->u_func_arg);
+                if (data < 0) {
+                    if (u->u_tx_done) {
+                        u->u_tx_done(u->u_func_arg);
+                    }
+                    apollo3_uart_disable_tx_irq();
+                    u->u_tx_started = 0;
+                    break;
+                }
+
+                UARTn(0)->DR = data;
+            }
+        }
+    }
+
+    if (status & (UART0_IES_RXRIS_Msk | UART0_IES_RTRIS_Msk)) {
+        /* Service receive buffer */
+        while (!(UARTn(0)->FR & UART0_FR_RXFE_Msk)) {
+            u->u_rx_buf = UARTn(0)->DR;
+            rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+            if (rc < 0) {
+                u->u_rx_stall = 1;
+                break;
+            }
+        }
+    }
+
+    os_trace_isr_exit();
+}
+
+static void apollo3_uart_irqh_0(void) { apollo3_uart_irqh_x(0); }
+static void apollo3_uart_irqh_1(void) { apollo3_uart_irqh_x(1); }
+
+static int
+apollo3_uart_irq_info(int port, int *out_irqn, apollo3_uart_irqh_t **out_irqh)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+
+    switch (port) {
+    case 0:
+        irqn = UART0_IRQn;
+        irqh = apollo3_uart_irqh_0;
+        break;
+
+    case 1:
+        irqn = UART1_IRQn;
+        irqh = apollo3_uart_irqh_1;
+        break;
+
+    default:
+        return -1;
+    }
+
+    if (out_irqn != NULL) {
+        *out_irqn = irqn;
+    }
+    if (out_irqh != NULL) {
+        *out_irqh = irqh;
+    }
+    return 0;
+}
+
+static void
+apollo3_uart_set_nvic(int port)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+    int rc;
+
+    rc = apollo3_uart_irq_info(port, &irqn, &irqh);
+    assert(rc == 0);
+
+    NVIC_SetVector(irqn, (uint32_t)irqh);
+}
+
+int
+hal_uart_init(int port, void *arg)
+{
+    struct apollo3_uart_cfg *cfg;
+    am_hal_gpio_pincfg_t pincfg;
+
+    cfg = arg;
+
+    if (port >= UART_CNT) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_uart_initialize(port, &(uarts[port].uart_handle));
+
+    am_hal_uart_power_control(uarts[port].uart_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    am_hal_uart_clock_speed_e eUartClockSpeed = eUART_CLK_SPEED_DEFAULT;
+    am_hal_uart_control(uarts[port].uart_handle, AM_HAL_UART_CONTROL_CLKSEL, &eUartClockSpeed);
+    am_hal_uart_configure(uarts[port].uart_handle, &g_sUartConfig);
+
+    switch (port) {
+      case 0:
+        switch (cfg->suc_pin_tx) {
+          case 22:
+          case 39:
+          case 48:
+            pincfg.uFuncSel = 0;
+            break;
+          case 1:
+            pincfg.uFuncSel = 2;
+            break;
+          case 20:
+          case 30:
+            pincfg.uFuncSel = 4;
+            break;
+          case 7:
+            pincfg.uFuncSel = 5;
+            break;
+          case 16:
+          case 26:
+          case 28:
+          case 41:
+          case 44:
+            pincfg.uFuncSel = 6;
+            break;
+          default:
+            return SYS_EINVAL;
+        }
+        break;
+      case 1:
+        switch (cfg->suc_pin_tx) {
+          case 10:
+          case 24:
+          case 42:
+            pincfg.uFuncSel = 0;
+            break;
+          case 39:
+            pincfg.uFuncSel = 1;
+            break;
+          case 14:
+          case 35:
+            pincfg.uFuncSel = 2;
+            break;
+          case 20:
+          case 37:
+            pincfg.uFuncSel = 5;
+            break;
+          case 8:
+          case 18:
+          case 46:
+            pincfg.uFuncSel = 6;
+            break;
+          case 12:
+            pincfg.uFuncSel = 7;
+            break;
+          default:
+            return SYS_EINVAL;
+        }
+        break;
+      default:
+        return SYS_EINVAL;
+    }
+    pincfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA;
+    am_hal_gpio_pinconfig(cfg->suc_pin_tx, pincfg);
+
+    switch (port) {
+      case 0:
+        switch (cfg->suc_pin_rx) {
+          case 23:
+          case 27:
+          case 40:
+          case 49:
+            pincfg.uFuncSel = 0;
+            break;
+          case 2:
+            pincfg.uFuncSel = 2;
+            break;
+          case 21:
+          case 31:
+            pincfg.uFuncSel = 4;
+            break;
+          case 11:
+          case 17:
+          case 29:
+          case 34:
+          case 45:
+            pincfg.uFuncSel = 6;
+            break;
+          default:
+            return SYS_EINVAL;
+        }
+        break;
+      case 1:
+        switch (cfg->suc_pin_rx) {
+          case 2:
+          case 25:
+          case 43:
+            pincfg.uFuncSel = 0;
+            break;
+          case 40:
+            pincfg.uFuncSel = 1;
+            break;
+          case 15:
+          case 36:
+            pincfg.uFuncSel = 2;
+            break;
+          case 4:
+          case 21:
+            pincfg.uFuncSel = 5;
+            break;
+          case 9:
+          case 19:
+          case 38:
+          case 47:
+            pincfg.uFuncSel = 6;
+            break;
+          case 13:
+            pincfg.uFuncSel = 7;
+            break;
+          default:
+            return SYS_EINVAL;
+        }
+        break;
+      default:
+        return SYS_EINVAL;
+    }
+    am_hal_gpio_pinconfig(cfg->suc_pin_rx, pincfg);
+
+    /* RTS pin is optional. */
+    if (cfg->suc_pin_rts >= 0) {
+      switch (port) {
+        case 0:
+          switch (cfg->suc_pin_rts) {
+            case 3:
+              pincfg.uFuncSel = 0;
+              break;
+            case 5:
+            case 37:
+              pincfg.uFuncSel = 2;
+              break;
+            case 18:
+              pincfg.uFuncSel = 4;
+              break;
+            case 34:
+              pincfg.uFuncSel = 5;
+              break;
+            case 13:
+            case 35:
+              pincfg.uFuncSel = 6;
+              break;
+            case 41:
+              pincfg.uFuncSel = 7;
+              break;
+            default:
+              return SYS_EINVAL;
+          }
+          break;
+        case 1:
+          switch (cfg->suc_pin_rts) {
+            case 44:
+              pincfg.uFuncSel = 0;
+              break;
+            case 34:
+              pincfg.uFuncSel = 2;
+              break;
+            case 10:
+            case 30:
+            case 41:
+              pincfg.uFuncSel = 5;
+              break;
+            case 16:
+            case 20:
+            case 31:
+              pincfg.uFuncSel = 7;
+              break;
+            default:
+              return SYS_EINVAL;
+          }
+          break;
+        default:
+          return SYS_EINVAL;
+      }
+      pincfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA;
+      am_hal_gpio_pinconfig(cfg->suc_pin_rts, pincfg);
+    }
+
+    /* CTS pin is optional. */
+    if (cfg->suc_pin_cts >= 0) {
+      switch (port) {
+        case 0:
+          switch (cfg->suc_pin_cts) {
+            case 4:
+              pincfg.uFuncSel = 0;
+              break;
+            case 6:
+            case 38:
+              pincfg.uFuncSel = 2;
+              break;
+            case 24:
+            case 29:
+              pincfg.uFuncSel = 4;
+              break;
+            case 33:
+              pincfg.uFuncSel = 5;
+              break;
+            case 12:
+            case 36:
+              pincfg.uFuncSel = 6;
+              break;
+            default:
+              return SYS_EINVAL;
+          }
+          break;
+        case 1:
+          switch (cfg->suc_pin_cts) {
+            case 45:
+              pincfg.uFuncSel = 0;
+              break;
+            case 11:
+            case 29:
+            case 36:
+            case 41:
+              pincfg.uFuncSel = 5;
+              break;
+            case 17:
+            case 21:
+            case 26:
+            case 32:
+              pincfg.uFuncSel = 7;
+              break;
+            default:
+              return SYS_EINVAL;
+          }
+          break;
+        default:
+          return SYS_EINVAL;
+      }
+      am_hal_gpio_pinconfig(cfg->suc_pin_cts, pincfg);
+    }
+
+    apollo3_uart_set_nvic(port);
+
+    return 0;
+}
+
+int
+hal_uart_config(int port, int32_t baudrate, uint8_t databits, uint8_t stopbits,
+  enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
+{
+    struct apollo3_uart *u;
+    int irqn;
+    int rc;
+
+    am_hal_uart_config_t uart_cfg =
+    {

Review comment:
       `{` should stay on previous line

##########
File path: hw/mcu/ambiq/apollo3/src/hal_flash.c
##########
@@ -0,0 +1,205 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include "os/mynewt.h"
+#include <am_hal_flash.h>
+#include <hal/hal_flash_int.h>
+#include <hal/hal_flash.h>
+#include <mcu/system_apollo3.h>
+
+
+static int
+apollo3_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
+    uint32_t num_bytes);
+static int
+apollo3_flash_write(const struct hal_flash *dev, uint32_t address,
+        const void *src, uint32_t num_bytes);
+static int
+apollo3_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_addr);
+static int
+apollo3_flash_sector_info(const struct hal_flash *dev, int idx, uint32_t *addr,
+    uint32_t *sz);
+static int
+apollo3_flash_init(const struct hal_flash *dev);
+
+static const struct hal_flash_funcs apollo3_flash_funcs = {
+    .hff_read = apollo3_flash_read,
+    .hff_write = apollo3_flash_write,
+    .hff_erase_sector = apollo3_flash_erase_sector,
+    .hff_sector_info = apollo3_flash_sector_info,
+    .hff_init = apollo3_flash_init
+};
+
+const struct hal_flash apollo3_flash_dev = {
+        .hf_itf = &apollo3_flash_funcs,
+        .hf_base_addr = 0x00000000,
+        .hf_size = 1024 * 1024,
+        .hf_sector_cnt = 128,
+        .hf_align = 1,
+        .hf_erased_val = 0xff,
+};

Review comment:
       more consistency with indentation would be appreciated
   
   same goes to return statement
   ```c
   return (rc);
   ```
   or
   ```c
   return rc;
   ```

##########
File path: hw/mcu/ambiq/apollo3/src/hal_gpio.c
##########
@@ -0,0 +1,217 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include "hal/hal_gpio.h"
+#include "mcu/apollo3.h"
+#include "mcu/cmsis_nvic.h"
+#include "am_mcu_apollo.h"
+#include "am_hal_pin.h"
+#include "am_hal_gpio.h"
+
+/* GPIO interrupts */
+#define HAL_GPIO_MAX_IRQ        8
+
+/* Storage for GPIO callbacks. */
+struct hal_gpio_irq {
+    int pin_num;
+    hal_gpio_irq_handler_t func;
+    void *arg;
+};
+
+int
+hal_gpio_init_in(int pin, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;

Review comment:
       Apollo seems to support pull-down as well.
   Maybe add `todo:` to mark this for the future

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);

Review comment:
       missing space around `/`

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);

Review comment:
       missing spaces around `/`

##########
File path: hw/mcu/ambiq/apollo3/src/hal_gpio.c
##########
@@ -0,0 +1,217 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include "hal/hal_gpio.h"
+#include "mcu/apollo3.h"
+#include "mcu/cmsis_nvic.h"
+#include "am_mcu_apollo.h"
+#include "am_hal_pin.h"
+#include "am_hal_gpio.h"
+
+/* GPIO interrupts */
+#define HAL_GPIO_MAX_IRQ        8
+
+/* Storage for GPIO callbacks. */
+struct hal_gpio_irq {
+    int pin_num;
+    hal_gpio_irq_handler_t func;
+    void *arg;
+};
+
+int
+hal_gpio_init_in(int pin, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;
+    }
+    am_hal_gpio_pinconfig(pin, cfg);
+
+    return (0);
+}
+
+int
+hal_gpio_init_out(int pin, int val)
+{
+    am_hal_gpio_pinconfig(pin, g_AM_HAL_GPIO_OUTPUT);
+    hal_gpio_write(pin, val);
+
+    return (0);
+}
+
+
+void
+hal_gpio_write(int pin, int val)
+{
+    if (val) {
+        am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_SET);
+    } else {
+        am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR);
+    }
+}
+
+int
+hal_gpio_read(int pin)
+{
+    uint32_t state;
+
+    am_hal_gpio_state_read(pin, AM_HAL_GPIO_INPUT_READ, &state);
+
+    return (int)state;
+}
+
+int
+hal_gpio_toggle(int pin)
+{
+    am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_TOGGLE);
+
+    return (0);
+}
+
+/*
+ * GPIO irq handler
+ *
+ * Handles the gpio interrupt attached to a gpio pin.
+ *
+ * @param index
+ */
+static void
+hal_gpio_irq_handler(void)
+{
+    uint64_t status;
+
+    os_trace_isr_enter();
+
+    /* Read and clear the GPIO interrupt status. */
+    am_hal_gpio_interrupt_status_get(false, &status);
+    am_hal_gpio_interrupt_clear(status);
+    am_hal_gpio_interrupt_service(status);
+
+    os_trace_isr_exit();
+}
+
+/*
+ * Register IRQ handler for GPIOTE, and enable it.
+ * Only executed once, during first registration.
+ */
+static void
+hal_gpio_irq_setup(void)
+{
+    static uint8_t irq_setup;
+
+    if (!irq_setup) {
+        NVIC_SetVector(GPIO_IRQn, (uint32_t)hal_gpio_irq_handler);
+        NVIC_SetPriority(GPIO_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+        NVIC_ClearPendingIRQ(GPIO_IRQn);
+        NVIC_EnableIRQ(GPIO_IRQn);
+        irq_setup = 1;
+    }
+}
+
+/**
+ * gpio irq init
+ *
+ * Initialize an external interrupt on a gpio pin
+ *
+ * @param pin       Pin number to enable gpio.
+ * @param handler   Interrupt handler
+ * @param arg       Argument to pass to interrupt handler
+ * @param trig      Trigger mode of interrupt
+ * @param pull      Push/pull mode of input.
+ *
+ * @return int
+ */
+int
+hal_gpio_irq_init(int pin, hal_gpio_irq_handler_t handler, void *arg,
+                  hal_gpio_irq_trig_t trig, hal_gpio_pull_t pull)
+{
+    am_hal_gpio_pincfg_t cfg;
+
+    switch (pull)  {
+        case HAL_GPIO_PULL_UP:
+            cfg = g_AM_HAL_GPIO_INPUT_PULLUP;
+            break;
+        default:
+            cfg = g_AM_HAL_GPIO_INPUT;
+            break;

Review comment:
       indentation for `case` in `switch` is usually in same line in mynewt, also extra spece before `{`

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+    uint32_t tx_buf = val;
+    uint32_t rx_buf = 0xffff;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = sizeof(val);
+    Transaction.pui32TxBuffer   = &tx_buf;
+    Transaction.pui32RxBuffer   = &rx_buf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+    
+    if (am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction) != AM_HAL_STATUS_SUCCESS) {
+        return 0xffff;
+    }
+
+    return rx_buf;
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    /* Not implemented */
+    return SYS_ERANGE;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int num_bytes)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = num_bytes;
+    Transaction.pui32TxBuffer   = txbuf;
+    Transaction.pui32RxBuffer   = rxbuf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+
+    return am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction);

Review comment:
       bud driver code can call `hal_spi_txrx()` with `rxbuf == NULL` then **am_hal_iom_spi_blocking_fullduplex()** should not be called

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int
+hal_i2c_init(uint8_t i2c_num, void *usercfg)
+{
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg *cfg = usercfg;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(cfg->sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(cfg->scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg) {
+    am_hal_iom_config_t iom_cfg;
+        
+    iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
+
+    /* Frequency is in khz, map to AM_HAL_IOM frequencies */
+    switch(cfg->frequency) {
+        case 100:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
+            break;
+        case 400:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
+            break;
+        case 1000:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
+            break;
+        default:
+            return -1;
+    }
+
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &iom_cfg);
+
+    return 0;
+}
+
+int
+hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_TX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32TxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int
+hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                    uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_RX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32RxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int hal_i2c_master_probe(uint8_t i2c_num, uint8_t address, uint32_t timeout) {
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_RX;
+    Transaction.ui32NumBytes    = 0;
+    Transaction.pui32RxBuffer   = NULL;
+    Transaction.bContinue       = false;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t)address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);

Review comment:
       if error code was tested it would work as expected since it does send address on I2C and can detected devices

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;

Review comment:
       **T**ransaction should be `transaction`

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }

Review comment:
       local for variables and indentation could be fixed

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int
+hal_i2c_init(uint8_t i2c_num, void *usercfg)
+{
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg *cfg = usercfg;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(cfg->sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(cfg->scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg) {
+    am_hal_iom_config_t iom_cfg;
+        
+    iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
+
+    /* Frequency is in khz, map to AM_HAL_IOM frequencies */
+    switch(cfg->frequency) {
+        case 100:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
+            break;
+        case 400:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
+            break;
+        case 1000:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
+            break;
+        default:
+            return -1;
+    }
+
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &iom_cfg);
+
+    return 0;
+}
+
+int
+hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_TX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32TxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;

Review comment:
       I2C usually can fail it looks a little bit strange that no error is reported
   
   same goes for next function which is could also fail if there is no device attached or address is wrong

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int
+hal_i2c_init(uint8_t i2c_num, void *usercfg)
+{
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg *cfg = usercfg;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(cfg->sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(cfg->scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg) {
+    am_hal_iom_config_t iom_cfg;
+        
+    iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
+
+    /* Frequency is in khz, map to AM_HAL_IOM frequencies */
+    switch(cfg->frequency) {
+        case 100:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
+            break;
+        case 400:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
+            break;
+        case 1000:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
+            break;
+        default:
+            return -1;
+    }
+
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &iom_cfg);
+
+    return 0;
+}
+
+int
+hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_TX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32TxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int
+hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                    uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_RX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32RxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int hal_i2c_master_probe(uint8_t i2c_num, uint8_t address, uint32_t timeout) {
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_RX;
+    Transaction.ui32NumBytes    = 0;
+    Transaction.pui32RxBuffer   = NULL;
+    Transaction.bContinue       = false;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t)address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;
+    am_hal_iom_blocking_transfer(g_i2c_handles[i2c_num], &Transaction);
+
+    return 0;
+}
+
+int hal_i2c_enable(uint8_t i2c_num) {
+    am_hal_iom_enable(g_i2c_handles[i2c_num]);
+    
+    return 0;
+}
+
+int hal_i2c_disable(uint8_t i2c_num) {
+    am_hal_iom_enable(g_i2c_handles[i2c_num]);

Review comment:
       I guess it should rather be `am_hal_iom_disable`

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+    uint32_t tx_buf = val;
+    uint32_t rx_buf = 0xffff;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = sizeof(val);
+    Transaction.pui32TxBuffer   = &tx_buf;
+    Transaction.pui32RxBuffer   = &rx_buf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+    
+    if (am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction) != AM_HAL_STATUS_SUCCESS) {
+        return 0xffff;
+    }
+
+    return rx_buf;
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    /* Not implemented */
+    return SYS_ERANGE;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int num_bytes)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);

Review comment:
       mynewt prefers to have `ss_pin_index` at the beginning of function

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;

Review comment:
       indentation mismatch

##########
File path: hw/mcu/ambiq/apollo3/src/hal_i2c.c
##########
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_i2c.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+/* Pointer array that points to am_hal_iom */
+void *g_i2c_handles[AM_REG_IOM_NUM_MODULES];
+
+static am_hal_iom_config_t g_sIOMI2cDefaultConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
+    .ui32ClockFreq  = AM_HAL_IOM_1MHZ,
+};
+
+/*  | i2c:cfg   | scl   | sda   |
+ *  |-----------+-------+-------|
+ *  | 0:0       | 5     | 6     |
+ *  | 1:0       | 8     | 9     |
+ *  | 2:4       | 27    | 25    |
+ *  | 3:4       | 42    | 43    |
+ *  | 4:4       | 39    | 40    |
+ *  | 5:4       | 48    | 49    |
+ */
+static int
+hal_i2c_pin_config(int i2c_num, const struct apollo3_i2c_cfg *pins)
+{
+    switch (i2c_num) {
+#if MYNEWT_VAL(I2C_0)
+    case 0:
+        if (pins->scl_pin == 5 && pins->sda_pin == 6) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_1)
+    case 1:
+        if (pins->scl_pin == 8 && pins->sda_pin == 9) {
+            return 0;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_2)
+    case 2:
+        if (pins->scl_pin == 27 && pins->sda_pin == 25) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_3)
+    case 3:
+        if (pins->scl_pin == 42 && pins->sda_pin == 43) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_4)
+    case 4:
+        if (pins->scl_pin == 39 && pins->sda_pin == 40) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(I2C_5)
+    case 5:
+        if (pins->scl_pin == 48 && pins->sda_pin == 49) {
+            return 4;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg) {
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg apollo_i2c_cfg;
+    
+     apollo_i2c_cfg.sda_pin = cfg->pin_sda;
+     apollo_i2c_cfg.scl_pin = cfg->pin_scl;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, &apollo_i2c_cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(apollo_i2c_cfg.scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int
+hal_i2c_init(uint8_t i2c_num, void *usercfg)
+{
+    int pin_cfg;
+    am_hal_gpio_pincfg_t i2c_cfg;
+    struct apollo3_i2c_cfg *cfg = usercfg;
+
+    /* Initialize the IOM. */
+    am_hal_iom_initialize(i2c_num, &g_i2c_handles[i2c_num]);
+
+    am_hal_iom_power_ctrl(g_i2c_handles[i2c_num], AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set the required configuration settings for the IOM. */
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &g_sIOMI2cDefaultConfig);
+
+    /* Configure GPIOs for I2C based on i2c_num */
+    pin_cfg = hal_i2c_pin_config(i2c_num, cfg);
+    if (pin_cfg == -1) {
+        return SYS_EINVAL;
+    }
+
+    i2c_cfg.uFuncSel            = pin_cfg;
+    i2c_cfg.ePullup             = AM_HAL_GPIO_PIN_PULLUP_1_5K;
+    i2c_cfg.eDriveStrength      = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    i2c_cfg.eGPOutcfg           = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
+    i2c_cfg.uIOMnum             = i2c_num;
+
+    am_hal_gpio_pinconfig(cfg->sda_pin,  i2c_cfg);
+    am_hal_gpio_pinconfig(cfg->scl_pin,  i2c_cfg);
+
+    hal_i2c_enable(i2c_num);
+
+    return 0;
+}
+
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg) {
+    am_hal_iom_config_t iom_cfg;
+        
+    iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
+
+    /* Frequency is in khz, map to AM_HAL_IOM frequencies */
+    switch(cfg->frequency) {
+        case 100:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_100KHZ;
+            break;
+        case 400:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_400KHZ;
+            break;
+        case 1000:
+            iom_cfg.ui32ClockFreq = AM_HAL_IOM_1MHZ;
+            break;
+        default:
+            return -1;
+    }
+
+    am_hal_iom_configure(g_i2c_handles[i2c_num], &iom_cfg);
+
+    return 0;
+}
+
+int
+hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op)
+{
+    am_hal_iom_transfer_t       Transaction;
+
+    Transaction.ui32InstrLen    = 0;
+    Transaction.ui32Instr       = 0;
+    Transaction.eDirection      = AM_HAL_IOM_TX;
+    Transaction.ui32NumBytes    = pdata->len;
+    Transaction.pui32TxBuffer   = (uint32_t *)pdata->buffer;
+    Transaction.bContinue       = !(bool)last_op;
+    Transaction.ui8RepeatCount  = 0;
+    Transaction.ui32PauseCondition = 0;
+    Transaction.ui32StatusSetClr = 0;
+    Transaction.uPeerInfo.ui32I2CDevAddr = pdata->address;
+
+    // g_i2c_handles[i2c_num]->waitTimeout = timeout;

Review comment:
       c++ style comment is not used in mynewt, line should go away anyway
   
   same for next function

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size

Review comment:
       c++ style comment not preferred here

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =

Review comment:
       variable name not in mynewt coding style

##########
File path: hw/mcu/ambiq/apollo3/src/hal_system.c
##########
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdint.h>
+#include "os/mynewt.h"
+#include "mcu/cortex_m4.h"
+#include "hal/hal_system.h"
+#include "am_mcu_apollo.h"
+
+am_hal_mcuctrl_device_t adevinfo;
+
+void
+hal_system_init(void)
+{
+}
+
+void
+hal_system_reset(void)
+{
+
+#if MYNEWT_VAL(HAL_SYSTEM_RESET_CB)
+    hal_system_reset_cb();
+#endif
+
+    while (1) {
+        HAL_DEBUG_BREAK();
+        NVIC_SystemReset();
+    }
+}
+
+enum hal_reset_reason
+hal_reset_cause(void)
+{
+    enum hal_reset_reason reason = 0;
+    return (reason);

Review comment:
       this look strange to set value out of range of enum and return it maybe just **HAL_RESET_OTHER** till this fixed and maybe todo comment

##########
File path: hw/mcu/ambiq/apollo3/src/hal_uart.c
##########
@@ -0,0 +1,693 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_uart.h"
+#include "mcu/cmsis_nvic.h"
+#include "bsp/bsp.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef UART
+
+uint8_t g_pui8TxBuffer[256];
+uint8_t g_pui8RxBuffer[2];
+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),
+};
+
+/* IRQ handler type */
+typedef void apollo3_uart_irqh_t(void);
+
+/*
+ * 2 UART on Ambiq Apollo 3
+ */
+struct apollo3_uart {
+    uint8_t u_open:1;
+    uint8_t u_rx_stall:1;
+    uint8_t u_tx_started:1;
+    uint8_t u_rx_buf;
+    uint8_t u_tx_buf[1];
+    hal_uart_rx_char u_rx_func;
+    hal_uart_tx_char u_tx_func;
+    hal_uart_tx_done u_tx_done;
+    void *u_func_arg;
+    void *uart_handle;
+};
+static struct apollo3_uart uarts[UART_CNT];
+
+static inline void
+apollo3_uart_enable_tx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_disable_tx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_enable_rx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+static inline void
+apollo3_uart_disable_rx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+int
+hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
+  hal_uart_rx_char rx_func, void *arg)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return -1;
+    }
+
+    u = &uarts[port];
+    if (u->u_open) {
+        return -1;
+    }
+
+    u->u_rx_func = rx_func;
+    u->u_tx_func = tx_func;
+    u->u_tx_done = tx_done;
+    u->u_func_arg = arg;
+
+    return 0;
+}
+
+void
+hal_uart_start_tx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int data;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    if (u->u_tx_started == 0) {
+        while (1) {
+            if (UARTn(0)->FR&UART0_FR_TXFF_Msk) {
+                u->u_tx_started = 1;
+                apollo3_uart_enable_tx_irq();
+                break;
+            }
+
+            data = u->u_tx_func(u->u_func_arg);
+            if (data < 0) {
+                if (u->u_tx_done) {
+                    u->u_tx_done(u->u_func_arg);
+                }
+                break;
+            }
+
+            UARTn(0)->DR = data;
+        }
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+hal_uart_start_rx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int rc;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    if (u->u_rx_stall) {
+        OS_ENTER_CRITICAL(sr);
+        rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+        if (rc == 0) {
+            u->u_rx_stall = 0;
+            apollo3_uart_enable_rx_irq();
+        }
+
+        OS_EXIT_CRITICAL(sr);
+    }
+}
+
+void
+hal_uart_blocking_tx(int port, uint8_t data)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    while (UARTn(0)->FR & UART0_FR_TXFF_Msk);
+    UARTn(0)->DR = data;
+}
+
+static void
+apollo3_uart_irqh_x(int num)
+{
+    struct apollo3_uart *u;
+    uint32_t status;
+    int data;
+    int rc;
+
+    os_trace_isr_enter();
+
+    u = &uarts[num];
+
+    status = UARTn(0)->IES;
+    UARTn(0)->IEC &= ~status;
+
+    if (status & (UART0_IES_TXRIS_Msk)) {
+        if (u->u_tx_started) {
+            while (1) {
+                if (UARTn(0)->FR & UART0_FR_TXFF_Msk) {
+                    break;
+                }
+
+                data = u->u_tx_func(u->u_func_arg);
+                if (data < 0) {
+                    if (u->u_tx_done) {
+                        u->u_tx_done(u->u_func_arg);
+                    }
+                    apollo3_uart_disable_tx_irq();
+                    u->u_tx_started = 0;
+                    break;
+                }
+
+                UARTn(0)->DR = data;
+            }
+        }
+    }
+
+    if (status & (UART0_IES_RXRIS_Msk | UART0_IES_RTRIS_Msk)) {
+        /* Service receive buffer */
+        while (!(UARTn(0)->FR & UART0_FR_RXFE_Msk)) {
+            u->u_rx_buf = UARTn(0)->DR;
+            rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+            if (rc < 0) {
+                u->u_rx_stall = 1;
+                break;
+            }
+        }
+    }
+
+    os_trace_isr_exit();
+}
+
+static void apollo3_uart_irqh_0(void) { apollo3_uart_irqh_x(0); }
+static void apollo3_uart_irqh_1(void) { apollo3_uart_irqh_x(1); }
+
+static int
+apollo3_uart_irq_info(int port, int *out_irqn, apollo3_uart_irqh_t **out_irqh)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+
+    switch (port) {
+    case 0:
+        irqn = UART0_IRQn;
+        irqh = apollo3_uart_irqh_0;
+        break;
+
+    case 1:
+        irqn = UART1_IRQn;
+        irqh = apollo3_uart_irqh_1;
+        break;
+
+    default:
+        return -1;
+    }
+
+    if (out_irqn != NULL) {
+        *out_irqn = irqn;
+    }
+    if (out_irqh != NULL) {
+        *out_irqh = irqh;
+    }
+    return 0;
+}
+
+static void
+apollo3_uart_set_nvic(int port)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+    int rc;
+
+    rc = apollo3_uart_irq_info(port, &irqn, &irqh);
+    assert(rc == 0);
+
+    NVIC_SetVector(irqn, (uint32_t)irqh);
+}
+
+int
+hal_uart_init(int port, void *arg)
+{
+    struct apollo3_uart_cfg *cfg;
+    am_hal_gpio_pincfg_t pincfg;
+
+    cfg = arg;
+
+    if (port >= UART_CNT) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_uart_initialize(port, &(uarts[port].uart_handle));
+
+    am_hal_uart_power_control(uarts[port].uart_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    am_hal_uart_clock_speed_e eUartClockSpeed = eUART_CLK_SPEED_DEFAULT;

Review comment:
       variable name in the middle of statements not used in mynewt

##########
File path: hw/mcu/ambiq/apollo3/src/hal_system.c
##########
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdint.h>
+#include "os/mynewt.h"
+#include "mcu/cortex_m4.h"
+#include "hal/hal_system.h"
+#include "am_mcu_apollo.h"
+
+am_hal_mcuctrl_device_t adevinfo;

Review comment:
       this does not seem to be used anywhere

##########
File path: hw/mcu/ambiq/apollo3/src/hal_uart.c
##########
@@ -0,0 +1,693 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_uart.h"
+#include "mcu/cmsis_nvic.h"
+#include "bsp/bsp.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef UART
+
+uint8_t g_pui8TxBuffer[256];
+uint8_t g_pui8RxBuffer[2];
+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),
+};
+
+/* IRQ handler type */
+typedef void apollo3_uart_irqh_t(void);
+
+/*
+ * 2 UART on Ambiq Apollo 3
+ */
+struct apollo3_uart {
+    uint8_t u_open:1;
+    uint8_t u_rx_stall:1;
+    uint8_t u_tx_started:1;
+    uint8_t u_rx_buf;
+    uint8_t u_tx_buf[1];
+    hal_uart_rx_char u_rx_func;
+    hal_uart_tx_char u_tx_func;
+    hal_uart_tx_done u_tx_done;
+    void *u_func_arg;
+    void *uart_handle;
+};
+static struct apollo3_uart uarts[UART_CNT];
+
+static inline void
+apollo3_uart_enable_tx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_disable_tx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_TX);
+}
+
+static inline void
+apollo3_uart_enable_rx_irq(void)
+{
+    UARTn(0)->IER |= (AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+static inline void
+apollo3_uart_disable_rx_irq(void)
+{
+    UARTn(0)->IER &= ~(AM_HAL_UART_INT_RX |
+            AM_HAL_UART_INT_RX_TMOUT);
+}
+
+int
+hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
+  hal_uart_rx_char rx_func, void *arg)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return -1;
+    }
+
+    u = &uarts[port];
+    if (u->u_open) {
+        return -1;
+    }
+
+    u->u_rx_func = rx_func;
+    u->u_tx_func = tx_func;
+    u->u_tx_done = tx_done;
+    u->u_func_arg = arg;
+
+    return 0;
+}
+
+void
+hal_uart_start_tx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int data;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    if (u->u_tx_started == 0) {
+        while (1) {
+            if (UARTn(0)->FR&UART0_FR_TXFF_Msk) {
+                u->u_tx_started = 1;
+                apollo3_uart_enable_tx_irq();
+                break;
+            }
+
+            data = u->u_tx_func(u->u_func_arg);
+            if (data < 0) {
+                if (u->u_tx_done) {
+                    u->u_tx_done(u->u_func_arg);
+                }
+                break;
+            }
+
+            UARTn(0)->DR = data;
+        }
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+hal_uart_start_rx(int port)
+{
+    struct apollo3_uart *u;
+    os_sr_t sr;
+    int rc;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    if (u->u_rx_stall) {
+        OS_ENTER_CRITICAL(sr);
+        rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+        if (rc == 0) {
+            u->u_rx_stall = 0;
+            apollo3_uart_enable_rx_irq();
+        }
+
+        OS_EXIT_CRITICAL(sr);
+    }
+}
+
+void
+hal_uart_blocking_tx(int port, uint8_t data)
+{
+    struct apollo3_uart *u;
+
+    if (port >= UART_CNT) {
+        return;
+    }
+
+    u = &uarts[port];
+    if (!u->u_open) {
+        return;
+    }
+
+    while (UARTn(0)->FR & UART0_FR_TXFF_Msk);
+    UARTn(0)->DR = data;
+}
+
+static void
+apollo3_uart_irqh_x(int num)
+{
+    struct apollo3_uart *u;
+    uint32_t status;
+    int data;
+    int rc;
+
+    os_trace_isr_enter();
+
+    u = &uarts[num];
+
+    status = UARTn(0)->IES;
+    UARTn(0)->IEC &= ~status;
+
+    if (status & (UART0_IES_TXRIS_Msk)) {
+        if (u->u_tx_started) {
+            while (1) {
+                if (UARTn(0)->FR & UART0_FR_TXFF_Msk) {
+                    break;
+                }
+
+                data = u->u_tx_func(u->u_func_arg);
+                if (data < 0) {
+                    if (u->u_tx_done) {
+                        u->u_tx_done(u->u_func_arg);
+                    }
+                    apollo3_uart_disable_tx_irq();
+                    u->u_tx_started = 0;
+                    break;
+                }
+
+                UARTn(0)->DR = data;
+            }
+        }
+    }
+
+    if (status & (UART0_IES_RXRIS_Msk | UART0_IES_RTRIS_Msk)) {
+        /* Service receive buffer */
+        while (!(UARTn(0)->FR & UART0_FR_RXFE_Msk)) {
+            u->u_rx_buf = UARTn(0)->DR;
+            rc = u->u_rx_func(u->u_func_arg, u->u_rx_buf);
+            if (rc < 0) {
+                u->u_rx_stall = 1;
+                break;
+            }
+        }
+    }
+
+    os_trace_isr_exit();
+}
+
+static void apollo3_uart_irqh_0(void) { apollo3_uart_irqh_x(0); }
+static void apollo3_uart_irqh_1(void) { apollo3_uart_irqh_x(1); }
+
+static int
+apollo3_uart_irq_info(int port, int *out_irqn, apollo3_uart_irqh_t **out_irqh)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+
+    switch (port) {
+    case 0:
+        irqn = UART0_IRQn;
+        irqh = apollo3_uart_irqh_0;
+        break;
+
+    case 1:
+        irqn = UART1_IRQn;
+        irqh = apollo3_uart_irqh_1;
+        break;
+
+    default:
+        return -1;
+    }
+
+    if (out_irqn != NULL) {
+        *out_irqn = irqn;
+    }
+    if (out_irqh != NULL) {
+        *out_irqh = irqh;
+    }
+    return 0;
+}
+
+static void
+apollo3_uart_set_nvic(int port)
+{
+    apollo3_uart_irqh_t *irqh;
+    int irqn;
+    int rc;
+
+    rc = apollo3_uart_irq_info(port, &irqn, &irqh);
+    assert(rc == 0);
+
+    NVIC_SetVector(irqn, (uint32_t)irqh);
+}
+
+int
+hal_uart_init(int port, void *arg)
+{
+    struct apollo3_uart_cfg *cfg;
+    am_hal_gpio_pincfg_t pincfg;
+
+    cfg = arg;
+
+    if (port >= UART_CNT) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_uart_initialize(port, &(uarts[port].uart_handle));
+
+    am_hal_uart_power_control(uarts[port].uart_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    am_hal_uart_clock_speed_e eUartClockSpeed = eUART_CLK_SPEED_DEFAULT;
+    am_hal_uart_control(uarts[port].uart_handle, AM_HAL_UART_CONTROL_CLKSEL, &eUartClockSpeed);
+    am_hal_uart_configure(uarts[port].uart_handle, &g_sUartConfig);
+
+    switch (port) {
+      case 0:
+        switch (cfg->suc_pin_tx) {
+          case 22:
+          case 39:
+          case 48:
+            pincfg.uFuncSel = 0;
+            break;
+          case 1:
+            pincfg.uFuncSel = 2;
+            break;
+          case 20:
+          case 30:
+            pincfg.uFuncSel = 4;
+            break;
+          case 7:
+            pincfg.uFuncSel = 5;
+            break;
+          case 16:
+          case 26:
+          case 28:
+          case 41:
+          case 44:
+            pincfg.uFuncSel = 6;
+            break;
+          default:
+            return SYS_EINVAL;

Review comment:
       wrong indentations

##########
File path: hw/mcu/ambiq/apollo3/src/hal_timer.c
##########
@@ -0,0 +1,815 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "os/mynewt.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_timer.h"
+
+#include "am_mcu_apollo.h"
+
+/**
+ * Note: Each "BSP timer" is implemented using two MCU timers:
+ *
+ * 1. Continuous timer - This timer is constantly running.  It provides
+ *    absolute time values, and is used for converting between relative and
+ *    absolute times.  Its output compare registers are never set.
+ *
+ * 2. "Once" timer - This timer is only used for generating interrupts at
+ *    scheduled times.  It is restarted at 0 for each scheduled event, and only
+ *    relative times are used with this timer.
+ *
+ * As with other HAL timer implementations, event expiry values are stored in
+ * absolute tick values.  To set the "once" timer's output compare register,
+ * the code uses the continuous timer to determine the current time, and uses
+ * the result to calculate the relative offset of the scheduled event.  The
+ * relative time then gets written to the "once" timer's output compare
+ * register.
+ *
+ * This scheme introduces some inaccuracy.  Some amount of time invariably
+ * passes after the current time is read and before the output compare register
+ * is written.  This gap in time causes the timer interrupt to occur later than
+ * it should.  This procedure is done in a critical section to minimize error.
+ *
+ * This somewhat convoluted scheme is required due to hardware limitations. (Apollo3 Blue MCU Datasheet v1.01 section 13.2.7)
+ * Ideally, each BSP timer would be implemented using a single continuous MCU
+ * timer.  However, the MCU only allows a timer to generate a single interrupt
+ * while it is running.  To schedule a second event, the timer would need to be
+ * stopped, cleared, and started again, which defeats the purpose of a
+ * continuous timer.
+ */
+
+#define APOLLO3_TIMER_ANY_ENABLED   \
+    (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(ADC_0))
+
+struct apollo3_timer {
+    TAILQ_HEAD(hal_timer_qhead, hal_timer) hal_timer_q;
+    struct apollo3_timer_cfg cfg;
+    uint32_t freq_hz;       /* Actual frequency. */
+
+    /* Index of continuous timer; measures absolute time. */
+    uint8_t cont_timer_idx;
+
+    /* Index of 'once' timer; used for scheduling interrupts. */
+    uint8_t once_timer_idx;
+
+    /* True if clock is adc clock */
+    bool is_adc_clk;
+};
+
+/**
+ * These lookup tables map frequency values to timer configuration settings.
+ * They are used for selecting a configuration that is closest to the user's
+ * requested frequency.
+ *
+ * Note: These tables must be in ascending order of frequency.
+ */
+struct apollo3_timer_freq_entry {
+    uint32_t freq;
+    uint32_t cfg;
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_hfrc[] = {
+    { 12000,    AM_HAL_CTIMER_HFRC_12KHZ },
+    { 47000,    AM_HAL_CTIMER_HFRC_47KHZ },
+    { 187500,   AM_HAL_CTIMER_HFRC_187_5KHZ },
+    { 3000000,  AM_HAL_CTIMER_HFRC_3MHZ },
+    { 12000000, AM_HAL_CTIMER_HFRC_12MHZ },
+    { 0 },
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_xt[] = {
+    { 256,      AM_HAL_CTIMER_XT_256HZ },
+    { 2048,     AM_HAL_CTIMER_XT_2_048KHZ },
+    { 16384,    AM_HAL_CTIMER_XT_16_384KHZ },
+    { 32768,    AM_HAL_CTIMER_XT_32_768KHZ },
+    { 0 },
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_lfrc[] = {
+    { 1,        AM_HAL_CTIMER_LFRC_1HZ },
+    { 32,       AM_HAL_CTIMER_LFRC_32HZ },
+    { 512,      AM_HAL_CTIMER_LFRC_512HZ },
+    { 1024,     AM_HAL_CTIMER_LFRC_1_16HZ },
+    { 0 },
+};
+
+#if MYNEWT_VAL(TIMER_0)
+static struct apollo3_timer apollo3_timer_0 = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_0.hal_timer_q),
+    .cont_timer_idx = 0,
+    .once_timer_idx = 1,
+    .is_adc_clk = false
+};
+#endif
+#if MYNEWT_VAL(TIMER_1)
+static struct apollo3_timer apollo3_timer_1 = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_1.hal_timer_q),
+    .cont_timer_idx = 2,
+    .once_timer_idx = 4,
+    .is_adc_clk = false
+};
+#endif
+#if MYNEWT_VAL(ADC_0)
+static struct apollo3_timer apollo3_timer_adc = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_adc.hal_timer_q),
+    .cont_timer_idx = 3,
+    .once_timer_idx = 3,
+    .is_adc_clk = true
+};
+#endif
+
+static struct apollo3_timer *
+apollo3_timer_resolve(int timer_num)
+{
+    switch (timer_num) {
+#if MYNEWT_VAL(TIMER_0)
+        case 0:     return &apollo3_timer_0;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+        case 1:     return &apollo3_timer_1;
+#endif
+#if MYNEWT_VAL(ADC_0)
+        case 3:     return &apollo3_timer_adc;
+#endif
+        default:    return NULL;
+    }

Review comment:
       unorthodox indentation

##########
File path: hw/mcu/ambiq/apollo3/src/hal_timer.c
##########
@@ -0,0 +1,815 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "os/mynewt.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_timer.h"
+
+#include "am_mcu_apollo.h"
+
+/**
+ * Note: Each "BSP timer" is implemented using two MCU timers:
+ *
+ * 1. Continuous timer - This timer is constantly running.  It provides
+ *    absolute time values, and is used for converting between relative and
+ *    absolute times.  Its output compare registers are never set.
+ *
+ * 2. "Once" timer - This timer is only used for generating interrupts at
+ *    scheduled times.  It is restarted at 0 for each scheduled event, and only
+ *    relative times are used with this timer.
+ *
+ * As with other HAL timer implementations, event expiry values are stored in
+ * absolute tick values.  To set the "once" timer's output compare register,
+ * the code uses the continuous timer to determine the current time, and uses
+ * the result to calculate the relative offset of the scheduled event.  The
+ * relative time then gets written to the "once" timer's output compare
+ * register.
+ *
+ * This scheme introduces some inaccuracy.  Some amount of time invariably
+ * passes after the current time is read and before the output compare register
+ * is written.  This gap in time causes the timer interrupt to occur later than
+ * it should.  This procedure is done in a critical section to minimize error.
+ *
+ * This somewhat convoluted scheme is required due to hardware limitations. (Apollo3 Blue MCU Datasheet v1.01 section 13.2.7)
+ * Ideally, each BSP timer would be implemented using a single continuous MCU
+ * timer.  However, the MCU only allows a timer to generate a single interrupt
+ * while it is running.  To schedule a second event, the timer would need to be
+ * stopped, cleared, and started again, which defeats the purpose of a
+ * continuous timer.
+ */
+
+#define APOLLO3_TIMER_ANY_ENABLED   \
+    (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(ADC_0))
+
+struct apollo3_timer {
+    TAILQ_HEAD(hal_timer_qhead, hal_timer) hal_timer_q;
+    struct apollo3_timer_cfg cfg;
+    uint32_t freq_hz;       /* Actual frequency. */
+
+    /* Index of continuous timer; measures absolute time. */
+    uint8_t cont_timer_idx;
+
+    /* Index of 'once' timer; used for scheduling interrupts. */
+    uint8_t once_timer_idx;
+
+    /* True if clock is adc clock */
+    bool is_adc_clk;
+};
+
+/**
+ * These lookup tables map frequency values to timer configuration settings.
+ * They are used for selecting a configuration that is closest to the user's
+ * requested frequency.
+ *
+ * Note: These tables must be in ascending order of frequency.
+ */
+struct apollo3_timer_freq_entry {
+    uint32_t freq;
+    uint32_t cfg;
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_hfrc[] = {
+    { 12000,    AM_HAL_CTIMER_HFRC_12KHZ },
+    { 47000,    AM_HAL_CTIMER_HFRC_47KHZ },
+    { 187500,   AM_HAL_CTIMER_HFRC_187_5KHZ },
+    { 3000000,  AM_HAL_CTIMER_HFRC_3MHZ },
+    { 12000000, AM_HAL_CTIMER_HFRC_12MHZ },
+    { 0 },
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_xt[] = {
+    { 256,      AM_HAL_CTIMER_XT_256HZ },
+    { 2048,     AM_HAL_CTIMER_XT_2_048KHZ },
+    { 16384,    AM_HAL_CTIMER_XT_16_384KHZ },
+    { 32768,    AM_HAL_CTIMER_XT_32_768KHZ },
+    { 0 },
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_lfrc[] = {
+    { 1,        AM_HAL_CTIMER_LFRC_1HZ },
+    { 32,       AM_HAL_CTIMER_LFRC_32HZ },
+    { 512,      AM_HAL_CTIMER_LFRC_512HZ },
+    { 1024,     AM_HAL_CTIMER_LFRC_1_16HZ },
+    { 0 },
+};
+
+#if MYNEWT_VAL(TIMER_0)
+static struct apollo3_timer apollo3_timer_0 = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_0.hal_timer_q),
+    .cont_timer_idx = 0,
+    .once_timer_idx = 1,
+    .is_adc_clk = false
+};
+#endif
+#if MYNEWT_VAL(TIMER_1)
+static struct apollo3_timer apollo3_timer_1 = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_1.hal_timer_q),
+    .cont_timer_idx = 2,
+    .once_timer_idx = 4,
+    .is_adc_clk = false
+};
+#endif
+#if MYNEWT_VAL(ADC_0)
+static struct apollo3_timer apollo3_timer_adc = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_adc.hal_timer_q),
+    .cont_timer_idx = 3,
+    .once_timer_idx = 3,
+    .is_adc_clk = true
+};
+#endif
+
+static struct apollo3_timer *
+apollo3_timer_resolve(int timer_num)
+{
+    switch (timer_num) {
+#if MYNEWT_VAL(TIMER_0)
+        case 0:     return &apollo3_timer_0;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+        case 1:     return &apollo3_timer_1;
+#endif
+#if MYNEWT_VAL(ADC_0)
+        case 3:     return &apollo3_timer_adc;
+#endif
+        default:    return NULL;
+    }
+}
+
+/**
+ * Retrieves the entry from a lookup table whose frequency value most closely
+ * matches the one specified.
+ */
+static const struct apollo3_timer_freq_entry *
+apollo3_timer_tbl_find(const struct apollo3_timer_freq_entry *table,
+                       uint32_t freq)
+{
+    const struct apollo3_timer_freq_entry *prev;
+    const struct apollo3_timer_freq_entry *cur;
+    uint32_t delta1;
+    uint32_t delta2;
+    int i;
+
+    /* If the requested value is less than all entries in the table, return the
+     * smallest one.
+     */
+    if (table[0].freq >= freq) {
+        return &table[0];
+    }
+
+    /* Find the first entry with a frequency value that is greater than the one
+     * being requested.  Then determine which of it or its predecessor is
+     * closer to the specified value.
+     */
+    for (i = 1; table[i].freq != 0; i++) {
+        cur = &table[i];
+        if (cur->freq >= freq) {
+            prev = cur - 1;
+            delta1 = freq - prev->freq;
+            delta2 = cur->freq - freq;
+
+            if (delta1 <= delta2) {
+                return prev;
+            } else {
+                return cur;
+            }
+        }
+    }
+
+    /* Requested value is greater than all entries in the table; return the
+     * largest.
+     */
+    return table + i - 1;
+}
+
+/**
+ * Calculates the best SDK configuration value for the specified timer.  The
+ * calculated value is called an "SDK configuration value" because it gets
+ * passed to the Apollo3 SDK timer configuration function.  Flags specific to
+ * the continuous or "once" timer are not included in the result; these must be
+ * ORed in, depending on the MCU timer being configured.
+ */
+static int
+apollo3_timer_sdk_cfg(const struct apollo3_timer_cfg *cfg, uint32_t freq_hz,
+                      uint32_t *out_actual_hz, uint32_t *out_cfg)
+{
+    const struct apollo3_timer_freq_entry *entry;
+
+    switch (cfg->source) {
+    case APOLLO3_TIMER_SOURCE_HFRC:
+        entry = apollo3_timer_tbl_find(apollo3_timer_tbl_hfrc, freq_hz);
+        *out_actual_hz = entry->freq;
+        *out_cfg = entry->cfg;
+        return 0;
+
+    case APOLLO3_TIMER_SOURCE_XT:
+        entry = apollo3_timer_tbl_find(apollo3_timer_tbl_xt, freq_hz);
+        *out_actual_hz = entry->freq;
+        *out_cfg = entry->cfg;
+        return 0;
+
+    case APOLLO3_TIMER_SOURCE_LFRC:
+        entry = apollo3_timer_tbl_find(apollo3_timer_tbl_lfrc, freq_hz);
+        *out_actual_hz = entry->freq;
+        *out_cfg = entry->cfg;
+        return 0;
+
+    case APOLLO3_TIMER_SOURCE_RTC:
+        *out_actual_hz = 100;
+        *out_cfg = AM_HAL_CTIMER_RTC_100HZ;
+        return 0;
+
+    case APOLLO3_TIMER_SOURCE_HCLK:
+        *out_actual_hz = 48000000;
+        *out_cfg = AM_HAL_CTIMER_HCLK_DIV4;
+        return 0;
+
+    default:
+        return SYS_EINVAL;
+    }
+}
+
+/**
+ * Calculates the value to write to the specified timer's ISR configuration
+ * register.
+ */ 
+static int
+apollo3_timer_isr_cfg(const struct apollo3_timer *bsp_timer,
+                      uint32_t *out_isr_cfg)
+{
+    switch (bsp_timer->once_timer_idx) {
+#if MYNEWT_VAL(TIMER_0)
+    case 1:
+        *out_isr_cfg = AM_HAL_CTIMER_INT_TIMERA1C0;
+        return 0;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    case 4:
+        *out_isr_cfg = AM_HAL_CTIMER_INT_TIMERA4C0;
+        return 0;
+#endif
+#if MYNEWT_VAL(ADC_0)
+    case 3:
+        *out_isr_cfg = AM_HAL_CTIMER_INT_TIMERA3C0;
+        return 0;
+#endif
+    default:
+        return SYS_EINVAL;
+    }
+}
+
+/**
+ * Retrieves the current time from the specified timer.
+ */
+static uint32_t
+apollo3_timer_cur_ticks(const struct apollo3_timer *bsp_timer)
+{
+    return am_hal_ctimer_read(bsp_timer->cont_timer_idx, AM_HAL_CTIMER_BOTH);
+}
+
+/**
+ * Configures a BSP timer to generate an interrupt at the speficied relative
+ * time.
+ */
+static void
+apollo3_timer_set_ocmp(const struct apollo3_timer *bsp_timer,
+                       uint32_t ticks_from_now)
+{
+    uint32_t isr_cfg;
+    int rc;
+
+    /* Calculate the ISR flags for the "once" timer. */
+    rc = apollo3_timer_isr_cfg(bsp_timer, &isr_cfg);
+    assert(rc == 0);
+
+    /* Clear any pending interrupt for this timer. */
+    am_hal_ctimer_int_clear(isr_cfg);
+
+    /* Stop and clear the "once" timer. */
+    am_hal_ctimer_stop(bsp_timer->once_timer_idx, AM_HAL_CTIMER_BOTH);
+    am_hal_ctimer_clear(bsp_timer->once_timer_idx, AM_HAL_CTIMER_BOTH);
+
+    /* Schedule an interrupt at the requested relative time. */
+    am_hal_ctimer_period_set(bsp_timer->once_timer_idx, AM_HAL_CTIMER_BOTH,
+                             ticks_from_now, 0);
+
+    /* Enable interrupts for this timer, in case they haven't been enabled
+     * yet.
+     */
+    am_hal_ctimer_int_enable(isr_cfg);
+
+    /* Restart the timer. */
+    am_hal_ctimer_start(bsp_timer->once_timer_idx, AM_HAL_CTIMER_BOTH);
+}
+
+/**
+ * Configures a BSP timer to generate an interrupt at the specified absolute
+ * time.
+ */
+static void
+apollo3_timer_set_ocmp_at(const struct apollo3_timer *bsp_timer, uint32_t at)
+{
+    uint32_t isr_cfg;
+    uint32_t now;
+    int32_t ticks_from_now;
+    int rc;
+
+    now = apollo3_timer_cur_ticks(bsp_timer);
+    ticks_from_now = at - now;
+    if (ticks_from_now <= 0) {
+        /* Event already occurred. */
+        rc = apollo3_timer_isr_cfg(bsp_timer, &isr_cfg);
+        assert(rc == 0);
+        am_hal_ctimer_int_set(isr_cfg);
+    } else {
+        apollo3_timer_set_ocmp(bsp_timer, ticks_from_now);
+    }
+}
+
+/**
+ * Unsets a scheduled interrupt for the specified BSP timer.
+ */
+static void
+apollo3_timer_clear_ocmp(const struct apollo3_timer *bsp_timer)
+{
+    uint32_t isr_cfg;
+    int rc;
+
+    rc = apollo3_timer_isr_cfg(bsp_timer, &isr_cfg);
+    assert(rc == 0);
+
+    am_hal_ctimer_int_disable(isr_cfg);
+}
+
+#if APOLLO3_TIMER_ANY_ENABLED
+/**
+ * Executes callbacks for all expired timers in a BSP timer's queue.  This
+ * function is called when a timer interrupt is handled.
+ */
+static void
+apollo3_timer_chk_queue(struct apollo3_timer *bsp_timer)
+{
+    struct hal_timer *timer;
+    uint32_t ticks;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    /* Remove and process each expired timer in the sorted queue. */
+    while ((timer = TAILQ_FIRST(&bsp_timer->hal_timer_q)) != NULL) {
+        ticks = apollo3_timer_cur_ticks(bsp_timer);
+        if ((int32_t)(ticks - timer->expiry) >= 0) {
+            TAILQ_REMOVE(&bsp_timer->hal_timer_q, timer, link);
+            timer->link.tqe_prev = NULL;
+            timer->cb_func(timer->cb_arg);
+        } else {
+            break;
+        }
+    }
+
+    /* If any timers remain, schedule an interrupt for the timer that expires
+     * next.
+     */
+    if (timer != NULL) {
+        apollo3_timer_set_ocmp_at(bsp_timer, timer->expiry);
+    } else {
+        apollo3_timer_clear_ocmp(bsp_timer);
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}
+#endif
+
+/**
+ * Handles a ctimer interrupt.
+ */
+static void
+apollo3_timer_isr(void)
+{
+    uint32_t status;
+
+    /* Read the ctimer status to determine which timers generated the
+     * interrupt.
+     */
+    status = am_hal_ctimer_int_status_get(true);
+    am_hal_ctimer_int_clear(status);
+
+    /* Service the appropriate timers. */
+#if MYNEWT_VAL(TIMER_0)
+    if (status & (AM_HAL_CTIMER_INT_TIMERA1C0 | AM_HAL_CTIMER_INT_TIMERA1C1)) {
+        apollo3_timer_chk_queue(&apollo3_timer_0);
+    }
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    if (status & (AM_HAL_CTIMER_INT_TIMERA3C0 | AM_HAL_CTIMER_INT_TIMERA3C1)) {
+        apollo3_timer_chk_queue(&apollo3_timer_1);
+    }
+#endif
+#if MYNEWT_VAL(ADC_0)
+    if (status & AM_HAL_CTIMER_INT_TIMERA3C0) {
+        apollo3_timer_chk_queue(&apollo3_timer_adc);
+    }
+#endif
+}
+
+/**
+ * hal timer init
+ *
+ * Initialize platform specific timer items
+ *
+ * @param timer_num     Timer number to initialize
+ * @param cfg           Pointer to platform specific configuration
+ *
+ * @return int          0: success; error code otherwise
+ */
+int
+hal_timer_init(int timer_num, void *vcfg)
+{
+#if !APOLLO3_TIMER_ANY_ENABLED
+    return SYS_EINVAL;
+#endif
+
+    static int nvic_configured;

Review comment:
       considering usage it could be uint8_t or bool to save RAM

##########
File path: hw/mcu/ambiq/apollo3/src/hal_uart.c
##########
@@ -0,0 +1,693 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_uart.h"
+#include "mcu/cmsis_nvic.h"
+#include "bsp/bsp.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef UART
+
+uint8_t g_pui8TxBuffer[256];
+uint8_t g_pui8RxBuffer[2];
+const am_hal_uart_config_t g_sUartConfig =

Review comment:
       camel case no used in mynewt

##########
File path: hw/mcu/ambiq/apollo3/src/apollo3_periph.c
##########
@@ -0,0 +1,550 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_i2c.h"
+#include "hal/hal_spi.h"
+#include "bsp/bsp.h"
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+#include "bus/bus.h"
+#if MYNEWT_VAL(I2C_0) || MYNEWT_VAL(I2C_1) || MYNEWT_VAL(I2C_2) || MYNEWT_VAL(I2C_3) || MYNEWT_VAL(I2C_4) || MYNEWT_VAL(I2C_5)
+#include "bus/drivers/i2c_hal.h"
+#endif
+#if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_1_MASTER) || MYNEWT_VAL(SPI_2_MASTER) || MYNEWT_VAL(SPI_3_MASTER) || MYNEWT_VAL(SPI_4_MASTER) || MYNEWT_VAL(SPI_5_MASTER)
+#include "bus/drivers/spi_apollo3.h"
+#endif
+#endif
+#if MYNEWT_VAL(UART_0) || MYNEWT_VAL(UART_1)
+#include "uart/uart.h"
+#include "uart_hal/uart_hal.h"
+#endif
+#if MYNEWT_VAL(ADC_0)
+#include <adc/adc.h>
+#include <adc_apollo3/adc_apollo3.h>
+#endif
+
+#if MYNEWT_VAL(ADC_0)
+#define ADC_SAMPLE_BUF_SIZE 128
+uint32_t g_ui32ADCSampleBuffer[ADC_SAMPLE_BUF_SIZE];
+
+static struct adc_dev os_bsp_adc0;
+static struct adc_cfg os_bsp_adc0_config = {
+    .adc_cfg = {
+        .eClock             = AM_HAL_ADC_CLKSEL_HFRC,
+        .ePolarity          = AM_HAL_ADC_TRIGPOL_RISING,
+        .eTrigger           = AM_HAL_ADC_TRIGSEL_SOFTWARE,
+        .eReference         = AM_HAL_ADC_REFSEL_INT_1P5,
+        .eClockMode         = AM_HAL_ADC_CLKMODE_LOW_LATENCY,
+        .ePowerMode         = AM_HAL_ADC_LPMODE0,
+        .eRepeat            = AM_HAL_ADC_REPEATING_SCAN,
+    },
+    .adc_slot_cfg = {
+        .eMeasToAvg      = AM_HAL_ADC_SLOT_AVG_128,
+        .ePrecisionMode  = AM_HAL_ADC_SLOT_14BIT,
+        .eChannel        = AM_HAL_ADC_SLOT_CHSEL_SE0,
+        .bWindowCompare  = false,
+        .bEnabled        = true,
+    },
+    .adc_dma_cfg = {
+        .bDynamicPriority = true,
+        .ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED,
+        .bDMAEnable = true,
+        .ui32SampleCount = ADC_SAMPLE_BUF_SIZE,
+        .ui32TargetAddress = (uint32_t)g_ui32ADCSampleBuffer
+    },
+    .clk_cfg = {
+        .clk_freq = 12000000,
+        .clk_period = 10,
+        .clk_on_time = 5,
+        .clk_num = APOLLO3_ADC_CLOCK_3,
+        .timer_ab = APOLLO3_ADC_TIMER_A,
+        .timer_func = APOLLO3_ADC_TIMER_FUNC_REPEAT,
+    }
+};
+#endif
+
+#if MYNEWT_VAL(UART_0)
+static struct uart_dev os_bsp_uart0;
+static const struct apollo3_uart_cfg os_bsp_uart0_cfg = {
+    .suc_pin_tx = MYNEWT_VAL(UART_0_PIN_TX),
+    .suc_pin_rx = MYNEWT_VAL(UART_0_PIN_RX),
+    .suc_pin_rts = MYNEWT_VAL(UART_0_PIN_RTS),
+    .suc_pin_cts = MYNEWT_VAL(UART_0_PIN_CTS),
+};
+#endif
+#if MYNEWT_VAL(UART_1)
+static struct uart_dev os_bsp_uart1;
+static const struct apollo3_uart_cfg os_bsp_uart1_cfg = {
+    .suc_pin_tx = MYNEWT_VAL(UART_1_PIN_TX),
+    .suc_pin_rx = MYNEWT_VAL(UART_1_PIN_RX),
+    .suc_pin_rts = MYNEWT_VAL(UART_1_PIN_RTS),
+    .suc_pin_cts = MYNEWT_VAL(UART_1_PIN_CTS),
+};
+#endif
+
+#if MYNEWT_VAL(I2C_0)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c0_cfg = {
+    .i2c_num = 0,
+    .pin_sda = MYNEWT_VAL(I2C_0_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_0_PIN_SCL),
+};
+static struct bus_i2c_dev i2c0_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c0_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_0_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_0_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_0_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_1)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c1_cfg = {
+    .i2c_num = 1,
+    .pin_sda = MYNEWT_VAL(I2C_1_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_1_PIN_SCL),
+};
+static struct bus_i2c_dev i2c1_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c1_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_1_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_1_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_1_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_2)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c2_cfg = {
+    .i2c_num = 2,
+    .pin_sda = MYNEWT_VAL(I2C_2_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_2_PIN_SCL),
+};
+static struct bus_i2c_dev i2c2_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c2_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_2_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_2_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_2_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_3)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c3_cfg = {
+    .i2c_num = 3,
+    .pin_sda = MYNEWT_VAL(I2C_3_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_3_PIN_SCL),
+};
+static struct bus_i2c_dev i2c3_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c3_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_3_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_3_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_3_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_4)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c4_cfg = {
+    .i2c_num = 4,
+    .pin_sda = MYNEWT_VAL(I2C_4_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_4_PIN_SCL),
+};
+static struct bus_i2c_dev i2c4_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c4_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_4_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_4_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_4_FREQ_KHZ),
+};
+#endif
+#endif
+#if MYNEWT_VAL(I2C_5)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c5_cfg = {
+    .i2c_num = 5,
+    .pin_sda = MYNEWT_VAL(I2C_5_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_5_PIN_SCL),
+};
+static struct bus_i2c_dev i2c5_bus;
+#else
+static const struct apollo3_hal_i2c_cfg hal_i2c5_cfg = {
+    .scl_pin = MYNEWT_VAL(I2C_5_PIN_SCL),
+    .sda_pin = MYNEWT_VAL(I2C_5_PIN_SDA),
+    .i2c_frequency = MYNEWT_VAL(I2C_5_FREQ_KHZ),
+};
+#endif
+#endif
+
+#if MYNEWT_VAL(SPI_0_SLAVE)
+static const struct apollo3_spi_cfg os_bsp_spi0s_cfg = {
+    .sck_pin      = MYNEWT_VAL(SPI_0_SLAVE_PIN_SCK),
+    .mosi_pin     = MYNEWT_VAL(SPI_0_SLAVE_PIN_MOSI),
+    .miso_pin     = MYNEWT_VAL(SPI_0_SLAVE_PIN_MISO),
+    .ss_pin       = { MYNEWT_VAL(SPI_0_SLAVE_PIN_CS), -1, -1, -1 }
+};
+#endif
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_spi_dev_cfg spi0_cfg = {
+    .spi_num = 0,
+    .pin_sck = MYNEWT_VAL(SPI_0_PIN_SCK),

Review comment:
       I guess this should be `SPI_0_MASTER_PIN_SCK`

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {

Review comment:
       variable in `for` statement not used in mynewt
   
   also local variables in blocks are not usually used

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );

Review comment:
       extra space before `)`

##########
File path: hw/mcu/ambiq/apollo3/src/apollo3_periph.c
##########
@@ -0,0 +1,550 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_i2c.h"
+#include "hal/hal_spi.h"
+#include "bsp/bsp.h"
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+#include "bus/bus.h"
+#if MYNEWT_VAL(I2C_0) || MYNEWT_VAL(I2C_1) || MYNEWT_VAL(I2C_2) || MYNEWT_VAL(I2C_3) || MYNEWT_VAL(I2C_4) || MYNEWT_VAL(I2C_5)
+#include "bus/drivers/i2c_hal.h"
+#endif
+#if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_1_MASTER) || MYNEWT_VAL(SPI_2_MASTER) || MYNEWT_VAL(SPI_3_MASTER) || MYNEWT_VAL(SPI_4_MASTER) || MYNEWT_VAL(SPI_5_MASTER)
+#include "bus/drivers/spi_apollo3.h"
+#endif
+#endif
+#if MYNEWT_VAL(UART_0) || MYNEWT_VAL(UART_1)
+#include "uart/uart.h"
+#include "uart_hal/uart_hal.h"
+#endif
+#if MYNEWT_VAL(ADC_0)
+#include <adc/adc.h>
+#include <adc_apollo3/adc_apollo3.h>
+#endif
+
+#if MYNEWT_VAL(ADC_0)
+#define ADC_SAMPLE_BUF_SIZE 128
+uint32_t g_ui32ADCSampleBuffer[ADC_SAMPLE_BUF_SIZE];

Review comment:
       camel case is not preferred here

##########
File path: hw/bus/drivers/spi_apollo3/src/spi_apollo3.c
##########
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "defs/error.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_spi.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/drivers/spi_apollo3.h"
+
+static int
+bus_spi_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node_cfg *cfg = arg;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    node->pin_cs = cfg->pin_cs;
+    node->mode = cfg->mode;
+    node->data_order = cfg->data_order;
+    node->freq = cfg->freq;
+    node->quirks = cfg->quirks;
+
+    hal_gpio_init_out(node->pin_cs, 1);
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+
+static void
+bus_spi_txrx_cb(void *arg, int len)
+{
+    struct bus_spi_apollo3_dev *dev = arg;
+
+    os_sem_release(&dev->sem);
+}
+#endif
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+    if (rc) {
+        hal_spi_disable(dev->spi_dev.cfg.spi_num);
+        rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+        assert(rc == 0);
+   }
+#endif
+
+    rc = hal_spi_enable(dev->spi_dev.cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_spi_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_spi_dev *spi_dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+    struct hal_spi_settings spi_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    /* No need to reconfigure if already configured with the same settings */
+    if (current_node && (current_node->mode == node->mode) &&
+                        (current_node->data_order == node->data_order) &&
+                        (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_spi_disable(spi_dev->cfg.spi_num);
+    if (rc) {
+        goto done;
+    }
+
+    spi_cfg.data_mode = node->mode;
+    spi_cfg.data_order = node->data_order;
+    spi_cfg.baudrate = node->freq;
+    /* XXX add support for other word sizes */
+    spi_cfg.word_size = HAL_SPI_WORD_SIZE_8BIT;
+
+    rc = hal_spi_config(spi_dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(spi_dev->cfg.spi_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    (void)timeout;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+    /* Use output buffer as input to generate SPI clock.
+     * For security mostly, do not output random data, fill it with 0xFF.
+     */
+    memset(buf, 0xFF, length);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write_read(struct bus_dev *bdev, struct bus_node *bnode,
+                   const uint8_t *wbuf, uint16_t wlength,
+                   uint8_t *rbuf, uint16_t rlength,
+                   os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    uint8_t buf[16];
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        memset(buf + wlength, 0xFF, rlength);
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+            if (rc == 0) {
+                os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            }
+        }
+    }
+#else
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+        }
+    }
+#endif
+
+    return rc;
+}
+
+static int bus_spi_disable(struct bus_dev *bdev)

Review comment:
       `static int` should go to separate line

##########
File path: hw/bus/drivers/spi_apollo3/src/spi_apollo3.c
##########
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "defs/error.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_spi.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/drivers/spi_apollo3.h"
+
+static int
+bus_spi_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node_cfg *cfg = arg;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    node->pin_cs = cfg->pin_cs;
+    node->mode = cfg->mode;
+    node->data_order = cfg->data_order;
+    node->freq = cfg->freq;
+    node->quirks = cfg->quirks;
+
+    hal_gpio_init_out(node->pin_cs, 1);
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+
+static void
+bus_spi_txrx_cb(void *arg, int len)
+{
+    struct bus_spi_apollo3_dev *dev = arg;
+
+    os_sem_release(&dev->sem);
+}
+#endif
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+    if (rc) {
+        hal_spi_disable(dev->spi_dev.cfg.spi_num);
+        rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+        assert(rc == 0);
+   }
+#endif
+
+    rc = hal_spi_enable(dev->spi_dev.cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_spi_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_spi_dev *spi_dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+    struct hal_spi_settings spi_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    /* No need to reconfigure if already configured with the same settings */
+    if (current_node && (current_node->mode == node->mode) &&
+                        (current_node->data_order == node->data_order) &&
+                        (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_spi_disable(spi_dev->cfg.spi_num);
+    if (rc) {
+        goto done;
+    }
+
+    spi_cfg.data_mode = node->mode;
+    spi_cfg.data_order = node->data_order;
+    spi_cfg.baudrate = node->freq;
+    /* XXX add support for other word sizes */
+    spi_cfg.word_size = HAL_SPI_WORD_SIZE_8BIT;
+
+    rc = hal_spi_config(spi_dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(spi_dev->cfg.spi_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    (void)timeout;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+    /* Use output buffer as input to generate SPI clock.
+     * For security mostly, do not output random data, fill it with 0xFF.
+     */
+    memset(buf, 0xFF, length);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write_read(struct bus_dev *bdev, struct bus_node *bnode,
+                   const uint8_t *wbuf, uint16_t wlength,
+                   uint8_t *rbuf, uint16_t rlength,
+                   os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    uint8_t buf[16];
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        memset(buf + wlength, 0xFF, rlength);
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+            if (rc == 0) {
+                os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            }
+        }
+    }
+#else
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);

Review comment:
       continuation flag should be set before this line and restored before next read part otherwise write/read that are longer will have chip select de-asserted for before read




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826255090



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+    uint32_t tx_buf = val;
+    uint32_t rx_buf = 0xffff;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = sizeof(val);
+    Transaction.pui32TxBuffer   = &tx_buf;
+    Transaction.pui32RxBuffer   = &rx_buf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+    
+    if (am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction) != AM_HAL_STATUS_SUCCESS) {
+        return 0xffff;
+    }
+
+    return rx_buf;
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    /* Not implemented */
+    return SYS_ERANGE;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int num_bytes)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = num_bytes;
+    Transaction.pui32TxBuffer   = txbuf;
+    Transaction.pui32RxBuffer   = rxbuf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+
+    return am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction);

Review comment:
       Good point, I added null checks for rxbuf and txbuf and will perform half duplex transactions if either rxbuf or txbuf is null. 

##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
+/**
+ * Configure the spi. Must be called after the spi is initialized (after
+ * hal_spi_init is called) and when the spi is disabled (user must call
+ * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
+ * to calling this function). Can also be used to reconfigure an initialized
+ * SPI (assuming it is disabled as described previously).
+ *
+ * @param spi_num The number of the SPI to configure.
+ * @param psettings The settings to configure this SPI with
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_config(int spi_num, struct hal_spi_settings *settings)
+{
+    const struct apollo3_spi *spi;
+    int rc;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    if (spi->spi_type == HAL_SPI_TYPE_MASTER) {
+        rc = hal_spi_config_master(spi_num, settings);
+    } else {
+        rc = hal_spi_config_slave(spi_num, settings);
+    }
+
+    return rc;
+}
+
+/**
+ * Enables the SPI. This does not start a transmit or receive operation;
+ * it is used for power mgmt. Cannot be called when a SPI transfer is in
+ * progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_enable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_enable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
+ * in progress.
+ *
+ * @param spi_num
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_disable(int spi_num)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    am_hal_iom_disable(spi->spi_handle);
+
+    return 0;
+}
+
+/**
+ * Blocking call to send a value on the SPI. Returns the value received from
+ * the SPI slave.
+ *
+ * MASTER: Sends the value and returns the received value from the slave.
+ * SLAVE: Invalid API. Returns 0xFFFF
+ *
+ * @param spi_num   Spi interface to use
+ * @param val       Value to send
+ *
+ * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
+ * if called when the SPI is configured to be a slave
+ */
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+    uint32_t tx_buf = val;
+    uint32_t rx_buf = 0xffff;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);
+    if (hal_spi_ss_pin_init(spi, ss_pin_index, spi->cur_ss_pin) != 0) {
+        return SYS_EINVAL;
+    }
+
+    memset(&Transaction, 0x0, sizeof(am_hal_iom_transfer_t ));
+    Transaction.eDirection      = AM_HAL_IOM_FULLDUPLEX;
+    Transaction.ui32NumBytes    = sizeof(val);
+    Transaction.pui32TxBuffer   = &tx_buf;
+    Transaction.pui32RxBuffer   = &rx_buf;
+    Transaction.bContinue       = spi->cont_tx;
+
+    Transaction.uPeerInfo.ui32SpiChipSelect = ss_pin_index;
+    
+    if (am_hal_iom_spi_blocking_fullduplex(spi->spi_handle, &Transaction) != AM_HAL_STATUS_SUCCESS) {
+        return 0xffff;
+    }
+
+    return rx_buf;
+}
+
+/**
+ * Sets the txrx callback (executed at interrupt context) when the
+ * buffer is transferred by the master or the slave using the non-blocking API.
+ * Cannot be called when the spi is enabled. This callback will also be called
+ * when chip select is de-asserted on the slave.
+ *
+ * NOTE: This callback is only used for the non-blocking interface and must
+ * be called prior to using the non-blocking API.
+ *
+ * @param spi_num   SPI interface on which to set callback
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
+{
+    /* Not implemented */
+    return SYS_ERANGE;
+}
+
+/**
+ * Blocking interface to send a buffer and store the received values from the
+ * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
+ * values or 16-bit values depending on whether the spi is configured for 8 bit
+ * data or more than 8 bits per value. The 'cnt' parameter is the number of
+ * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
+ * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
+ * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
+ *
+ * NOTE: these buffers are in the native endian-ness of the platform.
+ *
+ *     MASTER: master sends all the values in the buffer and stores the
+ *             stores the values in the receive buffer if rxbuf is not NULL.
+ *             The txbuf parameter cannot be NULL.
+ *     SLAVE: cannot be called for a slave; returns -1
+ *
+ * @param spi_num   SPI interface to use
+ * @param txbuf     Pointer to buffer where values to transmit are stored.
+ * @param rxbuf     Pointer to buffer to store values received from peer.
+ * @param cnt       Number of 8-bit or 16-bit values to be transferred.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int num_bytes)
+{
+    am_hal_iom_transfer_t Transaction;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    int ss_pin_index = hal_spi_get_uNCE(spi_num, spi->cur_ss_pin);

Review comment:
       Moved declaration to top of function




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826255825



##########
File path: hw/mcu/ambiq/apollo3/src/apollo3_periph.c
##########
@@ -0,0 +1,550 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_i2c.h"
+#include "hal/hal_spi.h"
+#include "bsp/bsp.h"
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+#include "bus/bus.h"
+#if MYNEWT_VAL(I2C_0) || MYNEWT_VAL(I2C_1) || MYNEWT_VAL(I2C_2) || MYNEWT_VAL(I2C_3) || MYNEWT_VAL(I2C_4) || MYNEWT_VAL(I2C_5)
+#include "bus/drivers/i2c_hal.h"
+#endif
+#if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_1_MASTER) || MYNEWT_VAL(SPI_2_MASTER) || MYNEWT_VAL(SPI_3_MASTER) || MYNEWT_VAL(SPI_4_MASTER) || MYNEWT_VAL(SPI_5_MASTER)
+#include "bus/drivers/spi_apollo3.h"
+#endif
+#endif
+#if MYNEWT_VAL(UART_0) || MYNEWT_VAL(UART_1)
+#include "uart/uart.h"
+#include "uart_hal/uart_hal.h"
+#endif
+#if MYNEWT_VAL(ADC_0)
+#include <adc/adc.h>
+#include <adc_apollo3/adc_apollo3.h>
+#endif
+
+#if MYNEWT_VAL(ADC_0)
+#define ADC_SAMPLE_BUF_SIZE 128
+uint32_t g_ui32ADCSampleBuffer[ADC_SAMPLE_BUF_SIZE];

Review comment:
       Renamed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826249961



##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {

Review comment:
       Moved `{`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826277684



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {

Review comment:
       It is used for `cfg->ss_pin[i]`. I moved declaration to top of function




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826276319



##########
File path: hw/bus/drivers/spi_apollo3/src/spi_apollo3.c
##########
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "defs/error.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_spi.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/drivers/spi_apollo3.h"
+
+static int
+bus_spi_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node_cfg *cfg = arg;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    node->pin_cs = cfg->pin_cs;
+    node->mode = cfg->mode;
+    node->data_order = cfg->data_order;
+    node->freq = cfg->freq;
+    node->quirks = cfg->quirks;
+
+    hal_gpio_init_out(node->pin_cs, 1);
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+
+static void
+bus_spi_txrx_cb(void *arg, int len)
+{
+    struct bus_spi_apollo3_dev *dev = arg;
+
+    os_sem_release(&dev->sem);
+}
+#endif
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+    if (rc) {
+        hal_spi_disable(dev->spi_dev.cfg.spi_num);
+        rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+        assert(rc == 0);
+   }
+#endif
+
+    rc = hal_spi_enable(dev->spi_dev.cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_spi_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_spi_dev *spi_dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+    struct hal_spi_settings spi_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    /* No need to reconfigure if already configured with the same settings */
+    if (current_node && (current_node->mode == node->mode) &&
+                        (current_node->data_order == node->data_order) &&
+                        (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_spi_disable(spi_dev->cfg.spi_num);
+    if (rc) {
+        goto done;
+    }
+
+    spi_cfg.data_mode = node->mode;
+    spi_cfg.data_order = node->data_order;
+    spi_cfg.baudrate = node->freq;
+    /* XXX add support for other word sizes */
+    spi_cfg.word_size = HAL_SPI_WORD_SIZE_8BIT;
+
+    rc = hal_spi_config(spi_dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(spi_dev->cfg.spi_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    (void)timeout;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+    /* Use output buffer as input to generate SPI clock.
+     * For security mostly, do not output random data, fill it with 0xFF.
+     */
+    memset(buf, 0xFF, length);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write_read(struct bus_dev *bdev, struct bus_node *bnode,
+                   const uint8_t *wbuf, uint16_t wlength,
+                   uint8_t *rbuf, uint16_t rlength,
+                   os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    uint8_t buf[16];
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        memset(buf + wlength, 0xFF, rlength);
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+            if (rc == 0) {
+                os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            }
+        }
+    }
+#else
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);

Review comment:
       I'm confused about this one. If `BUS_F_NOSTOP` is in the flags then we should expect another read/write until the last one in which case there will be no `BUS_F_NOSTOP` in flags and continuation is false on the last read/write right?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] sjanc merged pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
sjanc merged pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826250101



##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {
+                rc = OS_EINVAL;
+                goto err;
+            }
+
+            am_hal_adc_configure_dma(g_apollo3_adc_handle, &(cfg->adc_dma_cfg));
+            g_bADCDMAComplete = false;
+            g_bADCDMAError = false;
+
+            am_hal_adc_interrupt_clear(g_apollo3_adc_handle, 0xFFFFFFFF);
+            break;
+        }
+    }
+
+    *result = (int) sample[0].ui32Sample;
+    rc = 0;
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+    return rc;
+}
+
+static int
+apollo3_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)

Review comment:
       Fixed alignment

##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {
+                rc = OS_EINVAL;
+                goto err;
+            }
+
+            am_hal_adc_configure_dma(g_apollo3_adc_handle, &(cfg->adc_dma_cfg));
+            g_bADCDMAComplete = false;
+            g_bADCDMAError = false;
+
+            am_hal_adc_interrupt_clear(g_apollo3_adc_handle, 0xFFFFFFFF);
+            break;
+        }
+    }
+
+    *result = (int) sample[0].ui32Sample;
+    rc = 0;
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+    return rc;
+}
+
+static int
+apollo3_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)
+{
+    am_hal_adc_sample_t val;
+    int data_off;
+
+    data_off = off * sizeof(am_hal_adc_sample_t);
+    assert(data_off < buf_len);
+
+    val = *(am_hal_adc_sample_t *) ((uint8_t *) buf + data_off);
+    *result = (int)val.ui32Sample;
+
+    return 0;
+}
+
+static int
+apollo3_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+    return sizeof(am_hal_adc_sample_t) * chans * samples;
+}
+
+void apollo3_irq_handler(void) {

Review comment:
       Fixed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826250571



##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;
+
+static void
+init_adc_timer(struct apollo3_clk_cfg *cfg)
+{
+    uint32_t ctimer;
+    uint32_t timer_int = 0;
+
+    /* 
+    * Timer 3A is a special case timer that can trigger for the ADC
+    * (Apollo3 Blue MCU Datasheet v1.0.1 Section 19.4.2). Support for other clocks to be added later
+    */
+    assert(cfg->clk_num == APOLLO3_ADC_CLOCK_3);
+
+    /* Use cfg to craft timer args */
+    switch (cfg->timer_ab) {
+        case APOLLO3_ADC_TIMER_A:
+            ctimer = AM_HAL_CTIMER_TIMERA;
+            break;
+        case APOLLO3_ADC_TIMER_B:
+            ctimer = AM_HAL_CTIMER_TIMERB;
+            break;
+        case APOLLO3_ADC_TIMER_BOTH:
+            ctimer = AM_HAL_CTIMER_BOTH;
+            break;
+        default:
+            ctimer = 0;
+            break;
+    }
+    assert(ctimer != 0);
+
+    /* Start a timer to trigger the ADC periodically (1 second). */
+    am_hal_ctimer_config_single(cfg->clk_num, ctimer,
+                                AM_HAL_CTIMER_HFRC_12MHZ    |
+                                AM_HAL_CTIMER_FN_REPEAT     |
+                                AM_HAL_CTIMER_INT_ENABLE);
+    
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_A || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[0][cfg->clk_num];
+    }
+    if(cfg->timer_ab == APOLLO3_ADC_TIMER_B || cfg->timer_ab == APOLLO3_ADC_TIMER_BOTH) {
+        timer_int |= g_apollo3_timer_int_lut[1][cfg->clk_num];
+    }
+    
+    am_hal_ctimer_int_enable(timer_int);
+
+    am_hal_ctimer_period_set(cfg->clk_num, ctimer, cfg->clk_period, cfg->clk_on_time);
+
+    if (cfg->clk_num == APOLLO3_ADC_CLOCK_3) {
+        /* Enable the timer A3 to trigger the ADC directly */
+        am_hal_ctimer_adc_trigger_enable();
+    }
+
+    /* Start the timer. */
+    am_hal_ctimer_start(cfg->clk_num, ctimer);
+}
+
+/**
+ * Open the Apollo3 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait.  If 0 specified, returns immediately
+ *             if resource unavailable.  If OS_WAIT_FOREVER specified, blocks
+ *             until resource is available.
+ * @param arg  Argument provided by higher layer to open, in this case
+ *             it can be a adc_cfg, to override the default
+ *             configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    int rc = 0;
+    int unlock = 0;
+    struct adc_dev *dev = (struct adc_dev *) odev;
+    struct adc_cfg *adc_config = (struct adc_cfg *) arg;
+
+    if (!adc_config) {
+        adc_config = dev->ad_dev.od_init_arg;
+    }
+
+    /* Configuration must be set before opening adc or it must be passed in */
+    assert(adc_config != NULL);
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, wait);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_initialize(0, &g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_WAKE, false);
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* ad_chan_count holds number of slots, each slot can configure a channel */
+    for (int slot = 0; slot < dev->ad_chan_count; slot++) {
+        /* Set up an ADC slot */
+        am_hal_adc_configure_slot(g_apollo3_adc_handle, slot, &(adc_config->adc_slot_cfg));
+    }
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_enable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_enable(g_apollo3_adc_handle);
+
+    /* Start timer for ADC measurements */
+    init_adc_timer(&(adc_config->clk_cfg));
+
+    /* Enable adc irq */
+    NVIC_EnableIRQ(ADC_IRQn);
+    am_hal_interrupt_master_enable();
+
+    /* Trigger manually the first time */
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Close the Apollo3 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+apollo3_adc_close(struct os_dev *odev)
+{
+    struct adc_dev *dev;
+    int rc = 0;
+    int unlock = 0;
+
+    dev = (struct adc_dev *) odev;
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+    
+    /* Initialize the ADC and get the handle. */
+    am_hal_adc_deinitialize(&g_apollo3_adc_handle);
+
+    /* Power on the ADC. */
+    am_hal_adc_power_control(g_apollo3_adc_handle, AM_HAL_SYSCTRL_NORMALSLEEP, false);
+
+    /* Wake up for each adc interrupt by default */
+    am_hal_adc_interrupt_disable(g_apollo3_adc_handle, AM_HAL_ADC_INT_DERR | AM_HAL_ADC_INT_DCMP );
+
+    /* Enable the ADC. */
+    am_hal_adc_disable(g_apollo3_adc_handle);
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+
+    return rc;
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ *                a adc_cfg
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+apollo3_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata)
+{
+    struct adc_cfg *adc_config = (struct adc_cfg *) cfgdata;
+
+    /* Update device's args */
+    dev->ad_dev.od_init_arg = adc_config;
+    
+    if (cnum >= AM_HAL_ADC_MAX_SLOTS) {
+        return OS_EINVAL;
+    }
+
+    /* Set up the ADC configuration parameters.*/
+    am_hal_adc_configure(g_apollo3_adc_handle, &(adc_config->adc_cfg));
+
+    /* Set up an ADC slot */
+    am_hal_adc_configure_slot(g_apollo3_adc_handle, cnum, &(adc_config->adc_slot_cfg));
+
+    /* Configure the ADC to use DMA for the sample transfer. */
+    am_hal_adc_configure_dma(g_apollo3_adc_handle, &(adc_config->adc_dma_cfg));
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    /* Store these values in channel definitions, for conversions to
+     * milivolts.
+     */
+    dev->ad_chans[cnum].c_cnum = cnum;
+    dev->ad_chans[cnum].c_res = adc_config->adc_slot_cfg.ePrecisionMode;
+    dev->ad_chans[cnum].c_refmv = adc_config->adc_cfg.eReference;
+    dev->ad_chans[cnum].c_configured = 1;
+
+    return 0;
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Apollo3 cfg takes one buffer
+ */
+static int
+apollo3_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf1);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDynamicPriority = true;
+    cfg.ePriority = AM_HAL_ADC_PRIOR_SERVICE_IMMED;
+    cfg.bDMAEnable = true;
+    cfg.ui32TargetAddress = (uint32_t)buf1;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+static int
+apollo3_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+    am_hal_adc_dma_config_t cfg;
+    assert(dev);
+    assert(buf);
+
+    if (buf_len <= 0) {
+        return OS_EINVAL;
+    }
+
+    cfg = ((struct adc_cfg *)(dev->ad_dev.od_init_arg))->adc_dma_cfg;
+    cfg.bDMAEnable = false;
+    cfg.ui32TargetAddress = (uint32_t)buf;
+    cfg.ui32SampleCount = buf_len/sizeof(am_hal_adc_sample_t);
+
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_configure_dma(g_apollo3_adc_handle, &cfg))
+    {
+        return OS_EINVAL;
+    }
+    g_bADCDMAComplete = false;
+    g_bADCDMAError = false;
+
+    return 0;
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+apollo3_adc_sample(struct adc_dev *dev)
+{
+    if (AM_HAL_STATUS_SUCCESS != am_hal_adc_sw_trigger(g_apollo3_adc_handle)) {
+        return OS_EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+apollo3_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+    int rc;
+    int unlock = 0;
+    struct adc_cfg * cfg= dev->ad_dev.od_init_arg;
+    am_hal_adc_sample_t sample[cfg->adc_dma_cfg.ui32SampleCount];
+
+    if (os_started()) {
+        rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER);
+        if (rc != OS_OK) {
+            goto err;
+        }
+        unlock = 1;
+    }
+
+    memset(sample, 0, sizeof(am_hal_adc_sample_t)*cfg->adc_dma_cfg.ui32SampleCount);
+
+    am_hal_adc_sw_trigger(g_apollo3_adc_handle);
+
+    /* Blocking read */
+    while(1) {
+        assert(g_bADCDMAError != true);
+        if (g_bADCDMAComplete) {
+            if (AM_HAL_STATUS_SUCCESS != am_hal_adc_samples_read(g_apollo3_adc_handle, true, (uint32_t *)cfg->adc_dma_cfg.ui32TargetAddress, &(cfg->adc_dma_cfg.ui32SampleCount), sample))
+            {
+                rc = OS_EINVAL;
+                goto err;
+            }
+
+            am_hal_adc_configure_dma(g_apollo3_adc_handle, &(cfg->adc_dma_cfg));
+            g_bADCDMAComplete = false;
+            g_bADCDMAError = false;
+
+            am_hal_adc_interrupt_clear(g_apollo3_adc_handle, 0xFFFFFFFF);
+            break;
+        }
+    }
+
+    *result = (int) sample[0].ui32Sample;
+    rc = 0;
+
+err:
+    if (unlock) {
+        os_mutex_release(&dev->ad_lock);
+    }
+    return rc;
+}
+
+static int
+apollo3_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+                      int *result)
+{
+    am_hal_adc_sample_t val;
+    int data_off;
+
+    data_off = off * sizeof(am_hal_adc_sample_t);
+    assert(data_off < buf_len);
+
+    val = *(am_hal_adc_sample_t *) ((uint8_t *) buf + data_off);
+    *result = (int)val.ui32Sample;
+
+    return 0;
+}
+
+static int
+apollo3_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+    return sizeof(am_hal_adc_sample_t) * chans * samples;
+}
+
+void apollo3_irq_handler(void) {
+    uint32_t ui32IntMask;
+
+    /* Read the interrupt status. */
+    am_hal_adc_interrupt_status(g_apollo3_adc_handle, &ui32IntMask, false);
+
+    /* Clear the ADC interrupt. */
+    am_hal_adc_interrupt_clear(g_apollo3_adc_handle, ui32IntMask);
+
+    /* If we got a DMA complete, set the flag. */
+    if (ui32IntMask & AM_HAL_ADC_INT_DCMP)
+    {
+        g_bADCDMAComplete = true;
+    }
+
+    /* If we got a DMA error, set the flag. */
+    if (ui32IntMask & AM_HAL_ADC_INT_DERR)
+    {

Review comment:
       Fixed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826249254



##########
File path: hw/drivers/adc/adc_apollo3/src/adc_apollo3.c
##########
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_bsp.h>
+#include <adc/adc.h>
+#include <mcu/cmsis_nvic.h>
+
+/* Ambiq Apollo3 header */
+#include "am_mcu_apollo.h"
+
+#include "adc_apollo3/adc_apollo3.h"
+
+/* Each slot can have a channel setting described by am_hal_adc_slot_chan_e */
+static struct adc_chan_config g_apollo3_adc_chans[AM_HAL_ADC_MAX_SLOTS];
+void *g_apollo3_adc_handle;
+
+uint32_t g_apollo3_timer_int_lut[APOLLO3_ADC_TIMER_AB_CNT][APOLLO3_ADC_CLOCK_CNT] = {
+    {AM_HAL_CTIMER_INT_TIMERA0, AM_HAL_CTIMER_INT_TIMERA1, AM_HAL_CTIMER_INT_TIMERA2, AM_HAL_CTIMER_INT_TIMERA3},
+    {AM_HAL_CTIMER_INT_TIMERB0, AM_HAL_CTIMER_INT_TIMERB1, AM_HAL_CTIMER_INT_TIMERB2, AM_HAL_CTIMER_INT_TIMERB3}
+};
+
+/* ADC DMA complete flag. */
+volatile bool                   g_bADCDMAComplete;
+
+/* ADC DMA error flag. */
+volatile bool                   g_bADCDMAError;

Review comment:
       Renamed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826255418



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+static int
+hal_spi_init_master(int spi_num, const struct apollo3_spi_cfg *cfg)
+{
+    struct apollo3_spi *spi;
+    int spi_pin_func_sel;
+    am_hal_gpio_pincfg_t spi_sck_cfg, spi_miso_cfg, spi_mosi_cfg;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+    memset(spi, 0, sizeof *spi);
+
+    /* Initialize the IOM. */
+    if (am_hal_iom_initialize(spi_num, &(spi->spi_handle)) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+    
+    if (am_hal_iom_power_ctrl(spi->spi_handle, AM_HAL_SYSCTRL_WAKE, false) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Set the required configuration settings for the IOM. */
+    if (am_hal_iom_configure(spi->spi_handle, &g_sIOMSpiConfig) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Configure the IOM pins. */
+    spi_pin_func_sel = hal_spi_pin_config(spi_num, 1, cfg);
+    if (spi_pin_func_sel == -1) {
+        return SYS_EINVAL;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int ss_pin_func_sel = hal_spi_ss_pin_config(spi_num, 1, cfg->ss_pin[i]);
+      if (ss_pin_func_sel != -1) {
+        am_hal_gpio_pincfg_t spi_ss_cfg;
+
+        memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+        spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+        spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+        spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+        spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+        spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+        spi_ss_cfg.uIOMnum = spi_num;
+        spi_ss_cfg.uNCE = hal_spi_get_uNCE(spi_num, cfg->ss_pin[i]);
+        spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+        if (am_hal_gpio_pinconfig(cfg->ss_pin[i], spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+            return SYS_EINVAL;
+        }
+        spi->ss_pin[i] = cfg->ss_pin[i];
+        spi->cur_ss_pin = cfg->ss_pin[i];
+      } else {
+        spi->ss_pin[i] = -1;
+      }
+    }
+
+    memset(&spi_sck_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_sck_cfg.uFuncSel = spi_pin_func_sel;
+    spi_sck_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_sck_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->sck_pin, spi_sck_cfg) != AM_HAL_STATUS_SUCCESS){
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_miso_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_miso_cfg.uFuncSel = spi_pin_func_sel;
+    spi_miso_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->miso_pin, spi_miso_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    memset(&spi_mosi_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+    spi_mosi_cfg.uFuncSel = spi_pin_func_sel;
+    spi_mosi_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+    spi_mosi_cfg.uIOMnum = spi_num;
+    if (am_hal_gpio_pinconfig(cfg->mosi_pin, spi_mosi_cfg) != AM_HAL_STATUS_SUCCESS) {
+        return SYS_EINVAL;
+    }
+
+    /* Enable the IOM. */
+    hal_spi_enable(spi_num);
+
+    spi->spi_num = spi_num;
+    spi->cont_tx = false;
+    spi->spi_type = HAL_SPI_TYPE_MASTER;
+
+    return 0;
+}
+
+static int
+hal_spi_init_slave(int spi_num, struct apollo3_spi_cfg *cfg)
+{
+    return SYS_ERANGE;
+}
+
+int apollo3_spi_set_ss_pin(int spi_num, int8_t ss_pin)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cur_ss_pin = ss_pin;
+
+  return 0;
+}
+
+int apollo3_spi_set_continuation(int spi_num, bool cont)
+{
+  struct apollo3_spi *spi;
+
+  spi = apollo3_spi_resolve(spi_num);
+  if (spi == NULL) {
+      return SYS_EINVAL;
+  }
+
+  spi->cont_tx = cont;
+
+  return 0;
+}
+
+/**
+ * Initialize the SPI, given by spi_num.
+ *
+ * @param spi_num The number of the SPI to initialize
+ * @param cfg HW/MCU specific configuration,
+ *            passed to the underlying implementation, providing extra
+ *            configuration.
+ * @param spi_type SPI type (master or slave)
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int
+hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
+{
+    int rc;
+
+    if (cfg == NULL) {
+        return SYS_EINVAL;
+    }
+
+    switch (spi_type) {
+    case HAL_SPI_TYPE_MASTER:
+        rc = hal_spi_init_master(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    case HAL_SPI_TYPE_SLAVE:
+        rc = hal_spi_init_slave(spi_num, cfg);
+        if (rc != 0) {
+            return rc;
+        }
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct apollo3_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    for (int i = 0; i < 4; i++) {
+      hal_cfg.ss_pin[i] = -1;
+    }
+    if (spi_type == HAL_SPI_TYPE_MASTER) {
+      int spi_index = hal_spi_get_uNCE(spi_num, cfg->pin_ss);
+      if (spi_index != -1) {
+        hal_cfg.ss_pin[spi_index] = cfg->pin_ss;
+      }
+    } else {
+      hal_cfg.ss_pin[0] = cfg->pin_ss;
+    }

Review comment:
       Redid the indentation




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826253032



##########
File path: hw/mcu/ambiq/apollo3/src/hal_spi.c
##########
@@ -0,0 +1,1112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+#include "hal/hal_spi.h"
+#include "mcu/hal_apollo3.h"
+#include "mcu/cmsis_nvic.h"
+
+#include "am_mcu_apollo.h"
+
+/* Prevent CMSIS from breaking apollo3 macros. */
+#undef GPIO
+#undef IOSLAVE
+#undef CLKGEN
+
+#define SPI_MASTER_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_MASTER) ||  \
+    MYNEWT_VAL(SPI_1_MASTER) ||  \
+    MYNEWT_VAL(SPI_2_MASTER) ||  \
+    MYNEWT_VAL(SPI_3_MASTER) ||  \
+    MYNEWT_VAL(SPI_4_MASTER) ||  \
+    MYNEWT_VAL(SPI_5_MASTER))
+
+#define SPI_SLAVE_ANY_ENABLED ( \
+    MYNEWT_VAL(SPI_0_SLAVE))
+
+#if SPI_MASTER_ANY_ENABLED || SPI_SLAVE_ANY_ENABLED
+
+struct apollo3_spi {
+    uint8_t spi_num;
+    uint8_t spi_type;
+    int8_t  ss_pin[4];
+    void *spi_handle;
+
+    int8_t cur_ss_pin;
+    bool  cont_tx;
+
+    hal_spi_txrx_cb txrx_cb_func;
+    void *txrx_cb_arg;
+};
+
+#if MYNEWT_VAL(SPI_0_MASTER)
+static struct apollo3_spi apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+static struct apollo3_spi apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+static struct apollo3_spi apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+static struct apollo3_spi apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+static struct apollo3_spi apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+static struct apollo3_spi apollo3_spi5_master;
+#endif
+
+static am_hal_iom_config_t g_sIOMSpiConfig =
+{
+    .eInterfaceMode = AM_HAL_IOM_SPI_MODE,
+    .ui32ClockFreq = AM_HAL_IOM_4MHZ,
+    .eSpiMode = AM_HAL_IOM_SPI_MODE_0, /* CPOL = 0; CPHA = 0 */
+};
+
+#define AM_IOS_TX_BUFSIZE_MAX   1023
+uint8_t g_pui8TxFifoBuffer[AM_IOS_TX_BUFSIZE_MAX];
+static am_hal_ios_config_t g_sIOSSpiConfig =
+{
+    // Configure the IOS in SPI mode.
+    .ui32InterfaceSelect = AM_HAL_IOS_USE_SPI,
+
+    // Eliminate the "read-only" section, so an external host can use the
+    // entire "direct write" section.
+    .ui32ROBase = 0x78,
+
+    // Making the "FIFO" section as big as possible.
+    .ui32FIFOBase = 0x80,
+
+    // We don't need any RAM space, so extend the FIFO all the way to the end
+    // of the LRAM.
+    .ui32RAMBase = 0x100,
+
+    // FIFO Threshold - set to half the size
+    .ui32FIFOThreshold = 0x20,
+
+    .pui8SRAMBuffer = g_pui8TxFifoBuffer,
+    .ui32SRAMBufferCap = AM_IOS_TX_BUFSIZE_MAX,
+};
+
+static struct apollo3_spi *
+apollo3_spi_resolve(int spi_num)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        return &apollo3_spi0_master;
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        return &apollo3_spi1_master;
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        return &apollo3_spi2_master;
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        return &apollo3_spi3_master;
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        return &apollo3_spi4_master;
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        return &apollo3_spi5_master;
+#endif
+    default:
+        return NULL;
+    }
+}
+
+static uint32_t
+apollo3_spi_data_mode(int spi_mode)
+{
+    switch (spi_mode) {
+        case HAL_SPI_MODE0:     return AM_HAL_IOM_SPI_MODE_0;
+        case HAL_SPI_MODE1:     return AM_HAL_IOM_SPI_MODE_1;
+        case HAL_SPI_MODE2:     return AM_HAL_IOM_SPI_MODE_2;
+        case HAL_SPI_MODE3:     return AM_HAL_IOM_SPI_MODE_3;
+        default:                return -1;
+    }
+}
+
+static int
+hal_spi_config_master(int spi_num, const struct hal_spi_settings *settings)
+{
+    am_hal_iom_config_t sdk_config;
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    sdk_config.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
+    sdk_config.ui32ClockFreq = settings->baudrate;
+    sdk_config.eSpiMode = (am_hal_iom_spi_mode_e)apollo3_spi_data_mode(settings->data_mode);
+    am_hal_iom_configure(spi->spi_handle, &sdk_config);
+
+    return 0;
+}
+
+static int
+hal_spi_config_slave(int spi_num, const struct hal_spi_settings *settings)
+{
+    struct apollo3_spi *spi;
+
+    spi = apollo3_spi_resolve(spi_num);
+    if (spi == NULL) {
+        return SYS_EINVAL;
+    }
+
+    am_hal_ios_configure(spi->spi_handle, &g_sIOSSpiConfig);
+
+    return 0;
+}
+
+/*  | spi:cfg   | sck   | miso  | mosi  |
+ *  |-----------+-------+-------+-------|
+ *  | 0:1       | 5     | 6     | 7     |
+ *  | 1:1       | 8     | 9     | 10    |
+ *  | 2:5       | 27    | 28    | 25    |
+ *  | 3:5       | 42    | 43    | 38    |
+ *  | 4:5       | 39    | 40    | 44    |
+ *  | 5:5       | 48    | 49    | 47    |
+ */
+static int
+hal_spi_pin_config_master(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_MASTER_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+    case 0:
+        if (sck == 5 && miso == 6 && mosi == 7) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+    case 1:
+        if (sck == 8 && miso == 9 && mosi == 10) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+    case 2:
+        if (sck == 27 && miso == 25 && mosi == 28) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+    case 3:
+        if (sck == 42 && miso == 43 && mosi == 38) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+    case 4:
+        if (sck == 39 && miso == 40 && mosi == 44) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+    case 5:
+        if (sck == 48 && miso == 49 && mosi == 47) {
+            return 5;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_pin_config_slave(int spi_num, const struct apollo3_spi_cfg *pins)
+{
+#if SPI_SLAVE_ANY_ENABLED
+    const int8_t miso = pins->miso_pin;
+    const int8_t mosi = pins->mosi_pin;
+    const int8_t sck = pins->sck_pin;
+#endif
+
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        if (sck == 0 && miso == 2 && mosi == 1) {
+            return 1;
+        } else {
+            return -1;
+        }
+#endif
+    default:
+        return -1;
+    }
+}
+
+static int
+hal_spi_ss_pin_config_master(int spi_num, int8_t ss_pin)
+{
+  switch (ss_pin) {
+    case 7:
+    case 41:
+      return 0;
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+      return 1;
+    case 3:
+    case 4:
+    case 8:
+    case 9:
+    case 10:
+      return 2;
+    case 0:
+    case 1:
+    case 2:
+      return 7;
+    default:
+      return -1;
+  }
+}
+
+static int
+hal_spi_ss_pin_config_slave(int spi_num, int8_t ss_pin)
+{
+    switch (spi_num) {
+#if MYNEWT_VAL(SPI_0_SLAVE)
+    case 0:
+        switch (ss_pin) {
+          case 3:
+            return 1;
+          default:
+            return -1;
+        }
+#endif
+    default:
+      return -1;
+    }
+}
+
+static uint32_t
+hal_spi_get_uNCE(int spi_num, int ss_pin) {
+    switch(spi_num) {
+#if MYNEWT_VAL(SPI_0_MASTER)
+        case 0:
+          switch (ss_pin) {
+            case 8:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 13:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 25:
+            case 33:
+            case 37:
+            case 44:
+            case 48:
+              return 2;
+            case 15:
+            case 19:
+            case 22:
+            case 30:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+        case 1:
+          switch (ss_pin) {
+            case 11:
+            case 16:
+            case 23:
+            case 27:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 4:
+            case 17:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 29:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 0:
+            case 15:
+            case 19:
+            case 26:
+            case 34:
+            case 38:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_2_MASTER)
+        case 2:
+          switch (ss_pin) {
+            case 3:
+            case 11:
+            case 16:
+            case 23:
+            case 31:
+            case 35:
+            case 42:
+              return 0;
+            case 2:
+            case 17:
+            case 20:
+            case 24:
+            case 32:
+            case 41:
+            case 43:
+            case 47:
+              return 1;
+            case 1:
+            case 14:
+            case 18:
+            case 21:
+            case 33:
+            case 44:
+            case 48:
+              return 2;
+            case 9:
+            case 15:
+            case 34:
+            case 38:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_3_MASTER)
+        case 3:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 11:
+            case 12:
+            case 27:
+            case 35:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 28:
+            case 36:
+            case 47:
+              return 1;
+            case 0:
+            case 10:
+            case 18:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+            case 48:
+              return 2;
+            case 2:
+            case 9:
+            case 19:
+            case 22:
+            case 26:
+            case 30:
+            case 34:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_4_MASTER)
+        case 4:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 23:
+            case 27:
+            case 31:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 17:
+            case 20:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 14:
+            case 21:
+            case 25:
+            case 29:
+            case 37:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 45:
+            case 49:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+#if MYNEWT_VAL(SPI_5_MASTER)
+        case 5:
+          switch (ss_pin) {
+            case 3:
+            case 8:
+            case 12:
+            case 16:
+            case 27:
+            case 42:
+            case 46:
+              return 0;
+            case 4:
+            case 7:
+            case 13:
+            case 20:
+            case 24:
+            case 28:
+            case 36:
+              return 1;
+            case 0:
+            case 10:
+            case 21:
+            case 25:
+            case 29:
+            case 33:
+            case 37:
+            case 44:
+              return 2;
+            case 2:
+            case 9:
+            case 22:
+            case 26:
+            case 30:
+            case 38:
+            case 45:
+              return 3;
+            default:
+              return -1;
+          }
+#endif
+        default:
+            return -1;
+    }
+}
+
+static int
+hal_spi_pin_config(int spi_num, int master, const struct apollo3_spi_cfg *pins)
+{
+    if (master) {
+        return hal_spi_pin_config_master(spi_num, pins);
+    } else {
+        return hal_spi_pin_config_slave(spi_num, pins);
+    }
+}
+
+static int
+hal_spi_ss_pin_config(int spi_num, int master, int8_t ss_pin)
+{
+    if (master) {
+        return hal_spi_ss_pin_config_master(spi_num, ss_pin);
+    } else {
+        return hal_spi_ss_pin_config_slave(spi_num, ss_pin);
+    }
+}
+
+static int
+hal_spi_ss_pin_init(struct apollo3_spi *spi, int8_t ss_index, int8_t ss_pin)
+{
+  if (spi->ss_pin[ss_index] != ss_pin) {
+    int ss_pin_func_sel = hal_spi_ss_pin_config(spi->spi_num, 1, ss_pin);
+    if (ss_pin_func_sel != -1 && ss_index != -1) {
+      am_hal_gpio_pincfg_t spi_ss_cfg;
+
+      memset(&spi_ss_cfg, 0x0, sizeof(am_hal_gpio_pincfg_t));
+      spi_ss_cfg.uFuncSel = ss_pin_func_sel;
+      spi_ss_cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
+      spi_ss_cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
+      spi_ss_cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE;
+      spi_ss_cfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
+      spi_ss_cfg.uIOMnum = spi->spi_num;
+      spi_ss_cfg.uNCE = ss_index;
+      spi_ss_cfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
+      if (am_hal_gpio_pinconfig(ss_pin, spi_ss_cfg) != AM_HAL_STATUS_SUCCESS) {
+          return SYS_EINVAL;
+      }
+      spi->ss_pin[ss_index] = ss_pin;
+    } else {
+      return SYS_EINVAL;
+    }
+  }
+

Review comment:
       Redid the indentation, declared variables at the top of function




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826278032



##########
File path: hw/mcu/ambiq/apollo3/src/hal_timer.c
##########
@@ -0,0 +1,815 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "os/mynewt.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_timer.h"
+
+#include "am_mcu_apollo.h"
+
+/**
+ * Note: Each "BSP timer" is implemented using two MCU timers:
+ *
+ * 1. Continuous timer - This timer is constantly running.  It provides
+ *    absolute time values, and is used for converting between relative and
+ *    absolute times.  Its output compare registers are never set.
+ *
+ * 2. "Once" timer - This timer is only used for generating interrupts at
+ *    scheduled times.  It is restarted at 0 for each scheduled event, and only
+ *    relative times are used with this timer.
+ *
+ * As with other HAL timer implementations, event expiry values are stored in
+ * absolute tick values.  To set the "once" timer's output compare register,
+ * the code uses the continuous timer to determine the current time, and uses
+ * the result to calculate the relative offset of the scheduled event.  The
+ * relative time then gets written to the "once" timer's output compare
+ * register.
+ *
+ * This scheme introduces some inaccuracy.  Some amount of time invariably
+ * passes after the current time is read and before the output compare register
+ * is written.  This gap in time causes the timer interrupt to occur later than
+ * it should.  This procedure is done in a critical section to minimize error.
+ *
+ * This somewhat convoluted scheme is required due to hardware limitations. (Apollo3 Blue MCU Datasheet v1.01 section 13.2.7)
+ * Ideally, each BSP timer would be implemented using a single continuous MCU
+ * timer.  However, the MCU only allows a timer to generate a single interrupt
+ * while it is running.  To schedule a second event, the timer would need to be
+ * stopped, cleared, and started again, which defeats the purpose of a
+ * continuous timer.
+ */
+
+#define APOLLO3_TIMER_ANY_ENABLED   \
+    (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(ADC_0))
+
+struct apollo3_timer {
+    TAILQ_HEAD(hal_timer_qhead, hal_timer) hal_timer_q;
+    struct apollo3_timer_cfg cfg;
+    uint32_t freq_hz;       /* Actual frequency. */
+
+    /* Index of continuous timer; measures absolute time. */
+    uint8_t cont_timer_idx;
+
+    /* Index of 'once' timer; used for scheduling interrupts. */
+    uint8_t once_timer_idx;
+
+    /* True if clock is adc clock */
+    bool is_adc_clk;
+};
+
+/**
+ * These lookup tables map frequency values to timer configuration settings.
+ * They are used for selecting a configuration that is closest to the user's
+ * requested frequency.
+ *
+ * Note: These tables must be in ascending order of frequency.
+ */
+struct apollo3_timer_freq_entry {
+    uint32_t freq;
+    uint32_t cfg;
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_hfrc[] = {
+    { 12000,    AM_HAL_CTIMER_HFRC_12KHZ },
+    { 47000,    AM_HAL_CTIMER_HFRC_47KHZ },
+    { 187500,   AM_HAL_CTIMER_HFRC_187_5KHZ },
+    { 3000000,  AM_HAL_CTIMER_HFRC_3MHZ },
+    { 12000000, AM_HAL_CTIMER_HFRC_12MHZ },
+    { 0 },
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_xt[] = {
+    { 256,      AM_HAL_CTIMER_XT_256HZ },
+    { 2048,     AM_HAL_CTIMER_XT_2_048KHZ },
+    { 16384,    AM_HAL_CTIMER_XT_16_384KHZ },
+    { 32768,    AM_HAL_CTIMER_XT_32_768KHZ },
+    { 0 },
+};
+
+static const struct apollo3_timer_freq_entry apollo3_timer_tbl_lfrc[] = {
+    { 1,        AM_HAL_CTIMER_LFRC_1HZ },
+    { 32,       AM_HAL_CTIMER_LFRC_32HZ },
+    { 512,      AM_HAL_CTIMER_LFRC_512HZ },
+    { 1024,     AM_HAL_CTIMER_LFRC_1_16HZ },
+    { 0 },
+};
+
+#if MYNEWT_VAL(TIMER_0)
+static struct apollo3_timer apollo3_timer_0 = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_0.hal_timer_q),
+    .cont_timer_idx = 0,
+    .once_timer_idx = 1,
+    .is_adc_clk = false
+};
+#endif
+#if MYNEWT_VAL(TIMER_1)
+static struct apollo3_timer apollo3_timer_1 = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_1.hal_timer_q),
+    .cont_timer_idx = 2,
+    .once_timer_idx = 4,
+    .is_adc_clk = false
+};
+#endif
+#if MYNEWT_VAL(ADC_0)
+static struct apollo3_timer apollo3_timer_adc = {
+    .hal_timer_q = TAILQ_HEAD_INITIALIZER(apollo3_timer_adc.hal_timer_q),
+    .cont_timer_idx = 3,
+    .once_timer_idx = 3,
+    .is_adc_clk = true
+};
+#endif
+
+static struct apollo3_timer *
+apollo3_timer_resolve(int timer_num)
+{
+    switch (timer_num) {
+#if MYNEWT_VAL(TIMER_0)
+        case 0:     return &apollo3_timer_0;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+        case 1:     return &apollo3_timer_1;
+#endif
+#if MYNEWT_VAL(ADC_0)
+        case 3:     return &apollo3_timer_adc;
+#endif
+        default:    return NULL;
+    }
+}
+
+/**
+ * Retrieves the entry from a lookup table whose frequency value most closely
+ * matches the one specified.
+ */
+static const struct apollo3_timer_freq_entry *
+apollo3_timer_tbl_find(const struct apollo3_timer_freq_entry *table,
+                       uint32_t freq)
+{
+    const struct apollo3_timer_freq_entry *prev;
+    const struct apollo3_timer_freq_entry *cur;
+    uint32_t delta1;
+    uint32_t delta2;
+    int i;
+
+    /* If the requested value is less than all entries in the table, return the
+     * smallest one.
+     */
+    if (table[0].freq >= freq) {
+        return &table[0];
+    }
+
+    /* Find the first entry with a frequency value that is greater than the one
+     * being requested.  Then determine which of it or its predecessor is
+     * closer to the specified value.
+     */
+    for (i = 1; table[i].freq != 0; i++) {
+        cur = &table[i];
+        if (cur->freq >= freq) {
+            prev = cur - 1;
+            delta1 = freq - prev->freq;
+            delta2 = cur->freq - freq;
+
+            if (delta1 <= delta2) {
+                return prev;
+            } else {
+                return cur;
+            }
+        }
+    }
+
+    /* Requested value is greater than all entries in the table; return the
+     * largest.
+     */
+    return table + i - 1;
+}
+
+/**
+ * Calculates the best SDK configuration value for the specified timer.  The
+ * calculated value is called an "SDK configuration value" because it gets
+ * passed to the Apollo3 SDK timer configuration function.  Flags specific to
+ * the continuous or "once" timer are not included in the result; these must be
+ * ORed in, depending on the MCU timer being configured.
+ */
+static int
+apollo3_timer_sdk_cfg(const struct apollo3_timer_cfg *cfg, uint32_t freq_hz,
+                      uint32_t *out_actual_hz, uint32_t *out_cfg)
+{
+    const struct apollo3_timer_freq_entry *entry;
+
+    switch (cfg->source) {
+    case APOLLO3_TIMER_SOURCE_HFRC:
+        entry = apollo3_timer_tbl_find(apollo3_timer_tbl_hfrc, freq_hz);
+        *out_actual_hz = entry->freq;
+        *out_cfg = entry->cfg;
+        return 0;
+
+    case APOLLO3_TIMER_SOURCE_XT:
+        entry = apollo3_timer_tbl_find(apollo3_timer_tbl_xt, freq_hz);
+        *out_actual_hz = entry->freq;
+        *out_cfg = entry->cfg;
+        return 0;
+
+    case APOLLO3_TIMER_SOURCE_LFRC:
+        entry = apollo3_timer_tbl_find(apollo3_timer_tbl_lfrc, freq_hz);
+        *out_actual_hz = entry->freq;
+        *out_cfg = entry->cfg;
+        return 0;
+
+    case APOLLO3_TIMER_SOURCE_RTC:
+        *out_actual_hz = 100;
+        *out_cfg = AM_HAL_CTIMER_RTC_100HZ;
+        return 0;
+
+    case APOLLO3_TIMER_SOURCE_HCLK:
+        *out_actual_hz = 48000000;
+        *out_cfg = AM_HAL_CTIMER_HCLK_DIV4;
+        return 0;
+
+    default:
+        return SYS_EINVAL;
+    }
+}
+
+/**
+ * Calculates the value to write to the specified timer's ISR configuration
+ * register.
+ */ 
+static int
+apollo3_timer_isr_cfg(const struct apollo3_timer *bsp_timer,
+                      uint32_t *out_isr_cfg)
+{
+    switch (bsp_timer->once_timer_idx) {
+#if MYNEWT_VAL(TIMER_0)
+    case 1:
+        *out_isr_cfg = AM_HAL_CTIMER_INT_TIMERA1C0;
+        return 0;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    case 4:
+        *out_isr_cfg = AM_HAL_CTIMER_INT_TIMERA4C0;
+        return 0;
+#endif
+#if MYNEWT_VAL(ADC_0)
+    case 3:
+        *out_isr_cfg = AM_HAL_CTIMER_INT_TIMERA3C0;
+        return 0;
+#endif
+    default:
+        return SYS_EINVAL;
+    }
+}
+
+/**
+ * Retrieves the current time from the specified timer.
+ */
+static uint32_t
+apollo3_timer_cur_ticks(const struct apollo3_timer *bsp_timer)
+{
+    return am_hal_ctimer_read(bsp_timer->cont_timer_idx, AM_HAL_CTIMER_BOTH);
+}
+
+/**
+ * Configures a BSP timer to generate an interrupt at the speficied relative
+ * time.
+ */
+static void
+apollo3_timer_set_ocmp(const struct apollo3_timer *bsp_timer,
+                       uint32_t ticks_from_now)
+{
+    uint32_t isr_cfg;
+    int rc;
+
+    /* Calculate the ISR flags for the "once" timer. */
+    rc = apollo3_timer_isr_cfg(bsp_timer, &isr_cfg);
+    assert(rc == 0);
+
+    /* Clear any pending interrupt for this timer. */
+    am_hal_ctimer_int_clear(isr_cfg);
+
+    /* Stop and clear the "once" timer. */
+    am_hal_ctimer_stop(bsp_timer->once_timer_idx, AM_HAL_CTIMER_BOTH);
+    am_hal_ctimer_clear(bsp_timer->once_timer_idx, AM_HAL_CTIMER_BOTH);
+
+    /* Schedule an interrupt at the requested relative time. */
+    am_hal_ctimer_period_set(bsp_timer->once_timer_idx, AM_HAL_CTIMER_BOTH,
+                             ticks_from_now, 0);
+
+    /* Enable interrupts for this timer, in case they haven't been enabled
+     * yet.
+     */
+    am_hal_ctimer_int_enable(isr_cfg);
+
+    /* Restart the timer. */
+    am_hal_ctimer_start(bsp_timer->once_timer_idx, AM_HAL_CTIMER_BOTH);
+}
+
+/**
+ * Configures a BSP timer to generate an interrupt at the specified absolute
+ * time.
+ */
+static void
+apollo3_timer_set_ocmp_at(const struct apollo3_timer *bsp_timer, uint32_t at)
+{
+    uint32_t isr_cfg;
+    uint32_t now;
+    int32_t ticks_from_now;
+    int rc;
+
+    now = apollo3_timer_cur_ticks(bsp_timer);
+    ticks_from_now = at - now;
+    if (ticks_from_now <= 0) {
+        /* Event already occurred. */
+        rc = apollo3_timer_isr_cfg(bsp_timer, &isr_cfg);
+        assert(rc == 0);
+        am_hal_ctimer_int_set(isr_cfg);
+    } else {
+        apollo3_timer_set_ocmp(bsp_timer, ticks_from_now);
+    }
+}
+
+/**
+ * Unsets a scheduled interrupt for the specified BSP timer.
+ */
+static void
+apollo3_timer_clear_ocmp(const struct apollo3_timer *bsp_timer)
+{
+    uint32_t isr_cfg;
+    int rc;
+
+    rc = apollo3_timer_isr_cfg(bsp_timer, &isr_cfg);
+    assert(rc == 0);
+
+    am_hal_ctimer_int_disable(isr_cfg);
+}
+
+#if APOLLO3_TIMER_ANY_ENABLED
+/**
+ * Executes callbacks for all expired timers in a BSP timer's queue.  This
+ * function is called when a timer interrupt is handled.
+ */
+static void
+apollo3_timer_chk_queue(struct apollo3_timer *bsp_timer)
+{
+    struct hal_timer *timer;
+    uint32_t ticks;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    /* Remove and process each expired timer in the sorted queue. */
+    while ((timer = TAILQ_FIRST(&bsp_timer->hal_timer_q)) != NULL) {
+        ticks = apollo3_timer_cur_ticks(bsp_timer);
+        if ((int32_t)(ticks - timer->expiry) >= 0) {
+            TAILQ_REMOVE(&bsp_timer->hal_timer_q, timer, link);
+            timer->link.tqe_prev = NULL;
+            timer->cb_func(timer->cb_arg);
+        } else {
+            break;
+        }
+    }
+
+    /* If any timers remain, schedule an interrupt for the timer that expires
+     * next.
+     */
+    if (timer != NULL) {
+        apollo3_timer_set_ocmp_at(bsp_timer, timer->expiry);
+    } else {
+        apollo3_timer_clear_ocmp(bsp_timer);
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}
+#endif
+
+/**
+ * Handles a ctimer interrupt.
+ */
+static void
+apollo3_timer_isr(void)
+{
+    uint32_t status;
+
+    /* Read the ctimer status to determine which timers generated the
+     * interrupt.
+     */
+    status = am_hal_ctimer_int_status_get(true);
+    am_hal_ctimer_int_clear(status);
+
+    /* Service the appropriate timers. */
+#if MYNEWT_VAL(TIMER_0)
+    if (status & (AM_HAL_CTIMER_INT_TIMERA1C0 | AM_HAL_CTIMER_INT_TIMERA1C1)) {
+        apollo3_timer_chk_queue(&apollo3_timer_0);
+    }
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    if (status & (AM_HAL_CTIMER_INT_TIMERA3C0 | AM_HAL_CTIMER_INT_TIMERA3C1)) {
+        apollo3_timer_chk_queue(&apollo3_timer_1);
+    }
+#endif
+#if MYNEWT_VAL(ADC_0)
+    if (status & AM_HAL_CTIMER_INT_TIMERA3C0) {
+        apollo3_timer_chk_queue(&apollo3_timer_adc);
+    }
+#endif
+}
+
+/**
+ * hal timer init
+ *
+ * Initialize platform specific timer items
+ *
+ * @param timer_num     Timer number to initialize
+ * @param cfg           Pointer to platform specific configuration
+ *
+ * @return int          0: success; error code otherwise
+ */
+int
+hal_timer_init(int timer_num, void *vcfg)
+{
+#if !APOLLO3_TIMER_ANY_ENABLED
+    return SYS_EINVAL;
+#endif
+
+    static int nvic_configured;

Review comment:
       changed type to uint8_t




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] kasjer commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
kasjer commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826394611



##########
File path: hw/bus/drivers/spi_apollo3/src/spi_apollo3.c
##########
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "defs/error.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_spi.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/drivers/spi_apollo3.h"
+
+static int
+bus_spi_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node_cfg *cfg = arg;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    node->pin_cs = cfg->pin_cs;
+    node->mode = cfg->mode;
+    node->data_order = cfg->data_order;
+    node->freq = cfg->freq;
+    node->quirks = cfg->quirks;
+
+    hal_gpio_init_out(node->pin_cs, 1);
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+
+static void
+bus_spi_txrx_cb(void *arg, int len)
+{
+    struct bus_spi_apollo3_dev *dev = arg;
+
+    os_sem_release(&dev->sem);
+}
+#endif
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+    if (rc) {
+        hal_spi_disable(dev->spi_dev.cfg.spi_num);
+        rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+        assert(rc == 0);
+   }
+#endif
+
+    rc = hal_spi_enable(dev->spi_dev.cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_spi_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_spi_dev *spi_dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+    struct hal_spi_settings spi_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    /* No need to reconfigure if already configured with the same settings */
+    if (current_node && (current_node->mode == node->mode) &&
+                        (current_node->data_order == node->data_order) &&
+                        (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_spi_disable(spi_dev->cfg.spi_num);
+    if (rc) {
+        goto done;
+    }
+
+    spi_cfg.data_mode = node->mode;
+    spi_cfg.data_order = node->data_order;
+    spi_cfg.baudrate = node->freq;
+    /* XXX add support for other word sizes */
+    spi_cfg.word_size = HAL_SPI_WORD_SIZE_8BIT;
+
+    rc = hal_spi_config(spi_dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(spi_dev->cfg.spi_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    (void)timeout;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+    /* Use output buffer as input to generate SPI clock.
+     * For security mostly, do not output random data, fill it with 0xFF.
+     */
+    memset(buf, 0xFF, length);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write_read(struct bus_dev *bdev, struct bus_node *bnode,
+                   const uint8_t *wbuf, uint16_t wlength,
+                   uint8_t *rbuf, uint16_t rlength,
+                   os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    uint8_t buf[16];
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        memset(buf + wlength, 0xFF, rlength);
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+            if (rc == 0) {
+                os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            }
+        }
+    }
+#else
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);

Review comment:
       If we have simple transaction that first writes to the device and then it expect to read some bytes (let's say 100).
   At first BUS_F_NOSTOP is not set as transaction as such expect chip select to be de-asserted at the end.
   apollo3_spi_set_continuation() will be set to release chip select.
   Then code splits transaction for write and read (two calls for hal_spi_txrx) and first one after sending command will release chip select and then read will assert it again but it will be in most cases wrong.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826256041



##########
File path: hw/bus/drivers/spi_apollo3/src/spi_apollo3.c
##########
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "defs/error.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_spi.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/drivers/spi_apollo3.h"
+
+static int
+bus_spi_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node_cfg *cfg = arg;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    node->pin_cs = cfg->pin_cs;
+    node->mode = cfg->mode;
+    node->data_order = cfg->data_order;
+    node->freq = cfg->freq;
+    node->quirks = cfg->quirks;
+
+    hal_gpio_init_out(node->pin_cs, 1);
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+
+static void
+bus_spi_txrx_cb(void *arg, int len)
+{
+    struct bus_spi_apollo3_dev *dev = arg;
+
+    os_sem_release(&dev->sem);
+}
+#endif
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+    if (rc) {
+        hal_spi_disable(dev->spi_dev.cfg.spi_num);
+        rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+        assert(rc == 0);
+   }
+#endif
+
+    rc = hal_spi_enable(dev->spi_dev.cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_spi_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_spi_dev *spi_dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+    struct hal_spi_settings spi_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    /* No need to reconfigure if already configured with the same settings */
+    if (current_node && (current_node->mode == node->mode) &&
+                        (current_node->data_order == node->data_order) &&
+                        (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_spi_disable(spi_dev->cfg.spi_num);
+    if (rc) {
+        goto done;
+    }
+
+    spi_cfg.data_mode = node->mode;
+    spi_cfg.data_order = node->data_order;
+    spi_cfg.baudrate = node->freq;
+    /* XXX add support for other word sizes */
+    spi_cfg.word_size = HAL_SPI_WORD_SIZE_8BIT;
+
+    rc = hal_spi_config(spi_dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(spi_dev->cfg.spi_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    (void)timeout;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+    /* Use output buffer as input to generate SPI clock.
+     * For security mostly, do not output random data, fill it with 0xFF.
+     */
+    memset(buf, 0xFF, length);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write_read(struct bus_dev *bdev, struct bus_node *bnode,
+                   const uint8_t *wbuf, uint16_t wlength,
+                   uint8_t *rbuf, uint16_t rlength,
+                   os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    uint8_t buf[16];
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        memset(buf + wlength, 0xFF, rlength);
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+            if (rc == 0) {
+                os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            }
+        }
+    }
+#else
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+        }
+    }
+#endif
+
+    return rc;
+}
+
+static int bus_spi_disable(struct bus_dev *bdev)

Review comment:
       Placed `static int` into the line above




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] kasjer commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
kasjer commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826991549



##########
File path: hw/bus/drivers/spi_apollo3/src/spi_apollo3.c
##########
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "defs/error.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_spi.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/drivers/spi_apollo3.h"
+
+static int
+bus_spi_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node_cfg *cfg = arg;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    node->pin_cs = cfg->pin_cs;
+    node->mode = cfg->mode;
+    node->data_order = cfg->data_order;
+    node->freq = cfg->freq;
+    node->quirks = cfg->quirks;
+
+    hal_gpio_init_out(node->pin_cs, 1);
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+
+static void
+bus_spi_txrx_cb(void *arg, int len)
+{
+    struct bus_spi_apollo3_dev *dev = arg;
+
+    os_sem_release(&dev->sem);
+}
+#endif
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+    if (rc) {
+        hal_spi_disable(dev->spi_dev.cfg.spi_num);
+        rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+        assert(rc == 0);
+   }
+#endif
+
+    rc = hal_spi_enable(dev->spi_dev.cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_spi_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_spi_dev *spi_dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+    struct hal_spi_settings spi_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    /* No need to reconfigure if already configured with the same settings */
+    if (current_node && (current_node->mode == node->mode) &&
+                        (current_node->data_order == node->data_order) &&
+                        (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_spi_disable(spi_dev->cfg.spi_num);
+    if (rc) {
+        goto done;
+    }
+
+    spi_cfg.data_mode = node->mode;
+    spi_cfg.data_order = node->data_order;
+    spi_cfg.baudrate = node->freq;
+    /* XXX add support for other word sizes */
+    spi_cfg.word_size = HAL_SPI_WORD_SIZE_8BIT;
+
+    rc = hal_spi_config(spi_dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(spi_dev->cfg.spi_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    (void)timeout;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+    /* Use output buffer as input to generate SPI clock.
+     * For security mostly, do not output random data, fill it with 0xFF.
+     */
+    memset(buf, 0xFF, length);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write_read(struct bus_dev *bdev, struct bus_node *bnode,
+                   const uint8_t *wbuf, uint16_t wlength,
+                   uint8_t *rbuf, uint16_t rlength,
+                   os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    uint8_t buf[16];
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        memset(buf + wlength, 0xFF, rlength);
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+            if (rc == 0) {
+                os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            }
+        }
+    }
+#else
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);

Review comment:
       correct




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r826979916



##########
File path: hw/bus/drivers/spi_apollo3/src/spi_apollo3.c
##########
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "defs/error.h"
+#include "mcu/hal_apollo3.h"
+#include "hal/hal_spi.h"
+#include "hal/hal_gpio.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/drivers/spi_apollo3.h"
+
+static int
+bus_spi_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
+{
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node_cfg *cfg = arg;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    node->pin_cs = cfg->pin_cs;
+    node->mode = cfg->mode;
+    node->data_order = cfg->data_order;
+    node->freq = cfg->freq;
+    node->quirks = cfg->quirks;
+
+    hal_gpio_init_out(node->pin_cs, 1);
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+
+static void
+bus_spi_txrx_cb(void *arg, int len)
+{
+    struct bus_spi_apollo3_dev *dev = arg;
+
+    os_sem_release(&dev->sem);
+}
+#endif
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+    if (rc) {
+        hal_spi_disable(dev->spi_dev.cfg.spi_num);
+        rc = hal_spi_set_txrx_cb(dev->spi_dev.cfg.spi_num, bus_spi_txrx_cb, dev);
+        assert(rc == 0);
+   }
+#endif
+
+    rc = hal_spi_enable(dev->spi_dev.cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_spi_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_spi_dev *spi_dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+    struct hal_spi_settings spi_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    /* No need to reconfigure if already configured with the same settings */
+    if (current_node && (current_node->mode == node->mode) &&
+                        (current_node->data_order == node->data_order) &&
+                        (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_spi_disable(spi_dev->cfg.spi_num);
+    if (rc) {
+        goto done;
+    }
+
+    spi_cfg.data_mode = node->mode;
+    spi_cfg.data_order = node->data_order;
+    spi_cfg.baudrate = node->freq;
+    /* XXX add support for other word sizes */
+    spi_cfg.word_size = HAL_SPI_WORD_SIZE_8BIT;
+
+    rc = hal_spi_config(spi_dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(spi_dev->cfg.spi_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    (void)timeout;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+    /* Use output buffer as input to generate SPI clock.
+     * For security mostly, do not output random data, fill it with 0xFF.
+     */
+    memset(buf, 0xFF, length);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+    if (rc == 0) {
+        os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+    }
+#else
+    rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)buf, NULL, length);
+#endif
+
+    return rc;
+}
+
+static int
+bus_spi_write_read(struct bus_dev *bdev, struct bus_node *bnode,
+                   const uint8_t *wbuf, uint16_t wlength,
+                   uint8_t *rbuf, uint16_t rlength,
+                   os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_apollo3_dev *dev = (struct bus_spi_apollo3_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    bool cont = false;
+    int rc;
+    uint8_t buf[16];
+
+    BUS_DEBUG_VERIFY_DEV(&dev->spi_dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (flags & BUS_F_NOSTOP) {
+      cont = true;
+    }
+    apollo3_spi_set_ss_pin(dev->spi_dev.cfg.spi_num, node->pin_cs);
+    apollo3_spi_set_continuation(dev->spi_dev.cfg.spi_num, cont);
+
+#if MYNEWT_VAL(SPI_APOLLO3_USE_NOBLOCK)
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        memset(buf + wlength, 0xFF, rlength);
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);
+        if (rc == 0) {
+            os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            memset(rbuf, 0xFF, rlength);
+            rc = hal_spi_txrx_noblock(dev->spi_dev.cfg.spi_num, rbuf, rbuf, rlength);
+            if (rc == 0) {
+                os_sem_pend(&dev->sem, OS_TIMEOUT_NEVER);
+            }
+        }
+    }
+#else
+    if (wlength + rlength <= sizeof(buf)) {
+        memcpy(buf, wbuf, wlength);
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, buf, buf, wlength + rlength);
+        if (rc == 0) {
+            memcpy(rbuf, buf + wlength, rlength);
+        }
+    } else {
+        rc = hal_spi_txrx(dev->spi_dev.cfg.spi_num, (uint8_t *)wbuf, NULL, wlength);

Review comment:
       Ok, I think I understand. In scenarios where `BUS_F_NOSTOP` is not set but we still require two calls to `hal_spi_txrx` we must force the cont flag to true to prevent deasserting the chip select before performing the read on line 247. I would just need to force set continuation to true before line 244 and then set continuation based on `BUS_F_NOSTOP` before line 247




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [mynewt-core] t3zeng commented on a change in pull request #2784: Ambiq Apollo3 EVB Mynewt Port

Posted by GitBox <gi...@apache.org>.
t3zeng commented on a change in pull request #2784:
URL: https://github.com/apache/mynewt-core/pull/2784#discussion_r827239799



##########
File path: hw/mcu/ambiq/apollo2/pkg.yml
##########
@@ -25,6 +25,13 @@ pkg.keywords:
     - ambiq
     - apollo2
 
+pkg.cflags:
+    - '-DAM_PART_APOLLO2'
+
+pkg.src_dirs:
+    - "ext/AmbiqSuite/utils/"
+    - "ext/AmbiqSuite/mcu/"

Review comment:
       You're right, I went and fixed it




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org