You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2016/09/23 00:43:08 UTC

incubator-mynewt-core git commit: MYNEWT-3 HAL SPI API changes

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 2454b8c18 -> 26dfea0fb


MYNEWT-3 HAL SPI API changes

This commit adds a simple spitest program along with the changes
to the HAL SPI API. The commit also contains changes for some of
the nordic BSPS (not all of them). The additional BSP's will be
added shortly.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/26dfea0f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/26dfea0f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/26dfea0f

Branch: refs/heads/develop
Commit: 26dfea0fb142a9071c94d0d3bd69e5cfe96dfeae
Parents: 2454b8c
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Sep 22 17:38:58 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Thu Sep 22 17:41:49 2016 -0700

----------------------------------------------------------------------
 apps/spitest/pkg.yml                        |  36 +++
 apps/spitest/src/main.c                     | 360 +++++++++++++++++++++
 hw/bsp/nrf51dk/include/bsp/bsp.h            |   5 +-
 hw/bsp/nrf51dk/include/bsp/nrf_drv_config.h |   2 -
 hw/bsp/nrf51dk/pkg.yml                      |  10 +-
 hw/bsp/nrf51dk/src/os_bsp.c                 |   5 +-
 hw/bsp/nrf52dk/include/bsp/bsp.h            |   5 +-
 hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h |   2 -
 hw/bsp/nrf52dk/src/os_bsp.c                 |   6 +-
 hw/hal/include/hal/hal_spi.h                |  81 +++--
 hw/mcu/nordic/nrf51xxx/src/hal_spi.c        | 299 ++++++++++-------
 hw/mcu/nordic/nrf52xxx/src/hal_spi.c        | 396 +++++++++++++++--------
 12 files changed, 919 insertions(+), 288 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/apps/spitest/pkg.yml
----------------------------------------------------------------------
diff --git a/apps/spitest/pkg.yml b/apps/spitest/pkg.yml
new file mode 100644
index 0000000..58a8872
--- /dev/null
+++ b/apps/spitest/pkg.yml
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+
+pkg.name: apps/spitest
+pkg.type: app
+pkg.description: A board to board test for hal spi master/slave.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - libs/console/full
+    - libs/os
+    - libs/shell
+    - sys/config
+    - sys/log
+    - sys/stats
+
+pkg.syscfg_vals:
+    - SHELL_TASK: 0

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/apps/spitest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/spitest/src/main.c b/apps/spitest/src/main.c
new file mode 100755
index 0000000..3e8fafa
--- /dev/null
+++ b/apps/spitest/src/main.c
@@ -0,0 +1,360 @@
+/**
+ * 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 "os/os.h"
+#include "bsp/bsp.h"
+#include "hal/hal_gpio.h"
+#include "hal/hal_spi.h"
+#include "stats/stats.h"
+#include "config/config.h"
+#include <os/os_dev.h>
+#include <assert.h>
+#include <string.h>
+#ifdef ARCH_sim
+#include <mcu/mcu_sim.h>
+#endif
+#include "app_util_platform.h"
+#include "app_error.h"
+
+/* The spi txrx callback */
+struct sblinky_spi_cb_arg
+{
+    int transfers;
+    int txlen;
+    uint32_t tx_rx_bytes;
+};
+struct sblinky_spi_cb_arg spi_cb_obj;
+void *spi_cb_arg;
+
+/* Init all tasks */
+volatile int tasks_initialized;
+int init_tasks(void);
+
+/* Task 1 */
+#define TASK1_PRIO (1)
+#define TASK1_STACK_SIZE    OS_STACK_ALIGN(1024)
+struct os_task task1;
+os_stack_t stack1[TASK1_STACK_SIZE];
+
+/* Global test semaphore */
+struct os_sem g_test_sem;
+
+/* For LED toggling */
+int g_led_pin;
+
+#if MYNEWT_VAL(SPI_MASTER)
+uint8_t g_spi_tx_buf[32];
+uint8_t g_spi_rx_buf[32];
+uint32_t g_spi_xfr_num;
+uint8_t g_spi_null_rx;
+
+void
+sblinky_spi_irqm_handler(void *arg, int len)
+{
+    int i;
+    uint8_t expval;
+    struct sblinky_spi_cb_arg *cb;
+
+    hal_gpio_set(SPI_SS_PIN);
+
+    assert(arg == spi_cb_arg);
+    if (spi_cb_arg) {
+        cb = (struct sblinky_spi_cb_arg *)arg;
+        assert(len == cb->txlen);
+        ++cb->transfers;
+    }
+
+    /* Make sure we get back the data we expect! */
+    if (g_spi_xfr_num == 1) {
+        /* The first time we expect entire buffer to be filled with 0x88 */
+        for (i = 0; i < len; ++i) {
+            if (g_spi_rx_buf[i] != 0x88) {
+                assert(0);
+            }
+        }
+    } else {
+        /*
+         * We expect the buffer to be filled with an incrementing pattern
+         * That starts at 31 less than the first value sent this time.
+         */
+        if (g_spi_null_rx == 0) {
+            expval = g_spi_tx_buf[0];
+            expval = (uint8_t)(expval - 31);
+            for (i = 0; i < len; ++i) {
+                if (g_spi_rx_buf[i] != expval) {
+                    assert(0);
+                }
+                ++expval;
+            }
+        }
+    }
+    ++g_spi_xfr_num;
+}
+
+void
+sblinky_spi_cfg(int spi_num)
+{
+    int spi_id;
+    struct hal_spi_settings my_spi;
+
+    my_spi.data_order = HAL_SPI_MSB_FIRST;
+    my_spi.data_mode = HAL_SPI_MODE0;
+    my_spi.baudrate = 8000;
+    my_spi.word_size = HAL_SPI_WORD_SIZE_8BIT;
+    spi_id = 0;
+    hal_spi_config(spi_id, &my_spi);
+}
+#endif
+
+#if MYNEWT_VAL(SPI_SLAVE)
+uint8_t g_spi_tx_buf[32];
+uint8_t g_spi_rx_buf[32];
+uint32_t g_spi_xfr_num;
+
+/* XXX: This is an ugly hack for now. */
+#ifdef NRF51
+#define SPI_SLAVE_ID    (1)
+#else
+#define SPI_SLAVE_ID    (0)
+#endif
+
+void
+sblinky_spi_irqs_handler(void *arg, int len)
+{
+    struct sblinky_spi_cb_arg *cb;
+
+    assert(arg == spi_cb_arg);
+    if (spi_cb_arg) {
+        cb = (struct sblinky_spi_cb_arg *)arg;
+        ++cb->transfers;
+        cb->tx_rx_bytes += len;
+    }
+
+    /* Post semaphore to task waiting for SPI slave */
+    os_sem_release(&g_test_sem);
+}
+
+void
+sblinky_spi_cfg(int spi_num)
+{
+    int spi_id;
+    struct hal_spi_settings my_spi;
+
+    my_spi.data_order = HAL_SPI_MSB_FIRST;
+    my_spi.data_mode = HAL_SPI_MODE0;
+    my_spi.baudrate = 0;
+    my_spi.word_size = HAL_SPI_WORD_SIZE_8BIT;
+    spi_id = SPI_SLAVE_ID;
+    hal_spi_config(spi_id, &my_spi);
+    hal_spi_set_txrx_cb(spi_num, sblinky_spi_irqs_handler, spi_cb_arg);
+}
+#endif
+
+#if MYNEWT_VAL(SPI_MASTER)
+void
+task1_handler(void *arg)
+{
+    int i;
+    int rc;
+    uint16_t rxval;
+    uint8_t last_val;
+    uint8_t spi_nb_cntr;
+    uint8_t spi_b_cntr;
+
+    /* Set the led pin for the E407 devboard */
+    g_led_pin = LED_BLINK_PIN;
+    hal_gpio_init_out(g_led_pin, 1);
+
+    /* Use SS pin for testing */
+    hal_gpio_init_out(SPI_SS_PIN, 1);
+    sblinky_spi_cfg(0);
+    hal_spi_set_txrx_cb(0, NULL, NULL);
+    hal_spi_enable(0);
+
+    /*
+     * Send some bytes in a non-blocking manner to SPI using tx val. The
+     * slave should send back 0x77.
+     */
+    g_spi_tx_buf[0] = 0xde;
+    g_spi_tx_buf[1] = 0xad;
+    g_spi_tx_buf[2] = 0xbe;
+    g_spi_tx_buf[3] = 0xef;
+    hal_gpio_clear(SPI_SS_PIN);
+    for (i = 0; i < 4; ++i) {
+        rxval = hal_spi_tx_val(0, g_spi_tx_buf[i]);
+        assert(rxval == 0x77);
+        g_spi_rx_buf[i] = (uint8_t)rxval;
+    }
+    hal_gpio_set(SPI_SS_PIN);
+    ++g_spi_xfr_num;
+
+    /* Set up the callback to use when non-blocking API used */
+    hal_spi_disable(0);
+    spi_cb_arg = &spi_cb_obj;
+    spi_cb_obj.txlen = 32;
+    hal_spi_set_txrx_cb(0, sblinky_spi_irqm_handler, spi_cb_arg);
+    hal_spi_enable(0);
+    spi_nb_cntr = 0;
+    spi_b_cntr = 0;
+
+    while (1) {
+        /* Wait one second */
+        os_time_delay(OS_TICKS_PER_SEC);
+
+        /* Toggle the LED */
+        hal_gpio_toggle(g_led_pin);
+
+        /*
+         * Send to a slave, using blocking and non-blocking calls. The
+         * slave should be sending back the last thing we sent it.
+         */
+        last_val = g_spi_tx_buf[31];
+        for (i = 0; i < 32; ++i) {
+            g_spi_tx_buf[i] = (uint8_t)(last_val + i);
+        }
+
+        if (g_spi_xfr_num & 1) {
+            /* Send non-blocking */
+            ++spi_nb_cntr;
+            assert(hal_gpio_read(SPI_SS_PIN) == 1);
+            hal_gpio_clear(SPI_SS_PIN);
+            if (spi_nb_cntr == 7) {
+                g_spi_null_rx = 1;
+                rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, NULL, 32);
+            } else {
+                g_spi_null_rx = 0;
+                rc = hal_spi_txrx_noblock(0, g_spi_tx_buf, g_spi_rx_buf, 32);
+            }
+            assert(!rc);
+        } else {
+            /* Send blocking */
+            ++spi_b_cntr;
+            assert(hal_gpio_read(SPI_SS_PIN) == 1);
+            hal_gpio_clear(SPI_SS_PIN);
+            if (spi_b_cntr == 7) {
+                g_spi_null_rx = 1;
+                rc = hal_spi_txrx(0, g_spi_tx_buf, NULL, 32);
+                spi_b_cntr = 0;
+            } else {
+                g_spi_null_rx = 0;
+                rc = hal_spi_txrx(0, g_spi_tx_buf, g_spi_rx_buf, 32);
+            }
+            assert(!rc);
+            hal_gpio_set(SPI_SS_PIN);
+        }
+    }
+}
+#endif
+
+#if MYNEWT_VAL(SPI_SLAVE)
+void
+task1_handler(void *arg)
+{
+    int rc;
+
+    /* Set the led pin for the E407 devboard */
+    g_led_pin = LED_BLINK_PIN;
+    hal_gpio_init_out(g_led_pin, 1);
+
+    sblinky_spi_cfg(SPI_SLAVE_ID);
+    hal_spi_enable(SPI_SLAVE_ID);
+
+    /* Make the default character 0x77 */
+    hal_spi_slave_set_def_tx_val(SPI_SLAVE_ID, 0x77);
+
+    /*
+     * Fill buffer with 0x77 for first transfer. This should be a 0xdeadbeef
+     * transfer from master to start things off
+     */
+    memset(g_spi_tx_buf, 0x77, 32);
+    rc = hal_spi_txrx_noblock(SPI_SLAVE_ID, g_spi_tx_buf, g_spi_rx_buf,
+                              32);
+
+    while (1) {
+        /* Wait for semaphore from ISR */
+        os_sem_pend(&g_test_sem, OS_TIMEOUT_NEVER);
+
+        if (g_spi_xfr_num == 0) {
+            /* Since we dont know what master will send, we fill 0x88 */
+            memset(g_spi_tx_buf, 0x88, 32);
+            rc = hal_spi_txrx_noblock(SPI_SLAVE_ID, g_spi_tx_buf, g_spi_rx_buf,
+                                      32);
+        } else {
+            /* transmit back what we just received */
+            memcpy(g_spi_tx_buf, g_spi_rx_buf, 32);
+            rc = hal_spi_txrx_noblock(SPI_SLAVE_ID, g_spi_tx_buf, g_spi_rx_buf,
+                                      32);
+            assert(rc == 0);
+        }
+        ++g_spi_xfr_num;
+
+        /* Toggle the LED */
+        hal_gpio_toggle(g_led_pin);
+    }
+}
+#endif
+
+/**
+ * init_tasks
+ *
+ * Called by main.c after os_init(). This function performs initializations
+ * that are required before tasks are running.
+ *
+ * @return int 0 success; error otherwise.
+ */
+int
+init_tasks(void)
+{
+    /* Initialize global test semaphore */
+    os_sem_init(&g_test_sem, 0);
+
+    os_task_init(&task1, "task1", task1_handler, NULL,
+            TASK1_PRIO, OS_WAIT_FOREVER, stack1, TASK1_STACK_SIZE);
+
+    tasks_initialized = 1;
+    return 0;
+}
+
+/**
+ * main
+ *
+ * The main function for the project. This function initializes the os, calls
+ * init_tasks to initialize tasks (and possibly other objects), then starts the
+ * OS. We should not return from os start.
+ *
+ * @return int NOTE: this function should never return!
+ */
+int
+main(int argc, char **argv)
+{
+    int rc;
+
+#ifdef ARCH_sim
+    mcu_sim_parse_args(argc, argv);
+#endif
+
+    os_init();
+    rc = init_tasks();
+    os_start();
+
+    /* os start should never return. If it does, this should be an error */
+    assert(0);
+
+    return rc;
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/bsp/nrf51dk/include/bsp/bsp.h
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk/include/bsp/bsp.h b/hw/bsp/nrf51dk/include/bsp/bsp.h
index e5d73a5..205dad9 100644
--- a/hw/bsp/nrf51dk/include/bsp/bsp.h
+++ b/hw/bsp/nrf51dk/include/bsp/bsp.h
@@ -6,7 +6,7 @@
  * 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,
@@ -39,6 +39,9 @@ extern uint8_t _ram_start;
 /* LED pins */
 #define LED_BLINK_PIN   (21)
 
+/* SPI SS */
+#define SPI_SS_PIN      (24)
+
 /* UART info */
 #define CONSOLE_UART            "uart0"
 #define CONSOLE_UART_SPEED      115200

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/bsp/nrf51dk/include/bsp/nrf_drv_config.h
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk/include/bsp/nrf_drv_config.h b/hw/bsp/nrf51dk/include/bsp/nrf_drv_config.h
index f97fb5c..feac50b 100644
--- a/hw/bsp/nrf51dk/include/bsp/nrf_drv_config.h
+++ b/hw/bsp/nrf51dk/include/bsp/nrf_drv_config.h
@@ -209,7 +209,6 @@
 #if (SPI0_ENABLED == 1)
 #define SPI0_USE_EASY_DMA 0
 /* NOTE: SCK definitions match NRF51 DK product brief */
-#define SPI0_CONFIG_CSN_PIN         24 /* Note: not defined by SDK */
 #define SPI0_CONFIG_SCK_PIN         29
 #define SPI0_CONFIG_MOSI_PIN        25
 #define SPI0_CONFIG_MISO_PIN        28
@@ -261,7 +260,6 @@
 #define SPIS1_ENABLED 1
 
 #if (SPIS1_ENABLED == 1)
-#define SPIS1_CONFIG_CSN_PIN         24 /* Note: not defined by SDK */
 #define SPIS1_CONFIG_SCK_PIN         29
 #define SPIS1_CONFIG_MOSI_PIN        25
 #define SPIS1_CONFIG_MISO_PIN        28

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/bsp/nrf51dk/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk/pkg.yml b/hw/bsp/nrf51dk/pkg.yml
index 2be9fc2..8ad78e3 100644
--- a/hw/bsp/nrf51dk/pkg.yml
+++ b/hw/bsp/nrf51dk/pkg.yml
@@ -65,16 +65,10 @@ pkg.syscfg_defs:
 
     ADC_0:
         description: 'TBD'
-        value: 0
-    ADC_0_RESOLUTION:
-        description: 'TBD'
-        value: 'SAADC_CONFIG_RESOLUTION'
-    ADC_0_OVERSAMPLE:
-        description: 'TBD'
-        value: 'SAADC_CONFIG_OVERSAMPLE'
+        value: 1
     ADC_0_INTERRUPT_PRIORITY:
         description: 'TBD'
-        value: 'SAADC_CONFIG_IRQ_PRIORITY'
+        value: 'ADC_CONFIG_IRQ_PRIORITY'
 
     UART_0:
         description: 'TBD'

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/bsp/nrf51dk/src/os_bsp.c
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk/src/os_bsp.c b/hw/bsp/nrf51dk/src/os_bsp.c
index fe1600f..dfdc22c 100644
--- a/hw/bsp/nrf51dk/src/os_bsp.c
+++ b/hw/bsp/nrf51dk/src/os_bsp.c
@@ -18,6 +18,7 @@
  */
 #include <assert.h>
 #include "syscfg/syscfg.h"
+#include "bsp.h"
 #include "hal/flash_map.h"
 #include "hal/hal_bsp.h"
 #include "hal/hal_spi.h"
@@ -124,14 +125,12 @@ bsp_init(void)
       sizeof(bsp_flash_areas) / sizeof(bsp_flash_areas[0]));
 
 #if MYNEWT_VAL(SPI_MASTER)
-    /*  We initialize one SPI interface as a master. */
     rc = hal_spi_init(0, &spi_cfg, HAL_SPI_TYPE_MASTER);
     assert(rc == 0);
 #endif
 
 #if MYNEWT_VAL(SPI_SLAVE)
-    /*  We initialize one SPI interface as a master. */
-    spi_cfg.csn_pin = SPIS1_CONFIG_CSN_PIN;
+    spi_cfg.csn_pin = SPI_SS_PIN;
     spi_cfg.csn_pullup = NRF_GPIO_PIN_PULLUP;
     rc = hal_spi_init(1, &spi_cfg, HAL_SPI_TYPE_SLAVE);
     assert(rc == 0);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/bsp/nrf52dk/include/bsp/bsp.h
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52dk/include/bsp/bsp.h b/hw/bsp/nrf52dk/include/bsp/bsp.h
index 85ba3c6..08ebe93 100644
--- a/hw/bsp/nrf52dk/include/bsp/bsp.h
+++ b/hw/bsp/nrf52dk/include/bsp/bsp.h
@@ -6,7 +6,7 @@
  * 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,
@@ -40,6 +40,9 @@ extern uint8_t _ram_start;
 /* LED pins */
 #define LED_BLINK_PIN   (17)
 
+/* SPI SS */
+#define SPI_SS_PIN      (22)
+
 /* UART info */
 #define CONSOLE_UART    "uart0"
 #define CONSOLE_UART_SPEED      115200

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h b/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h
index 173193a..653a4de 100644
--- a/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h
+++ b/hw/bsp/nrf52dk/include/bsp/nrf_drv_config.h
@@ -208,7 +208,6 @@
 
 #if (SPI0_ENABLED == 1)
 #define SPI0_USE_EASY_DMA 1
-#define SPI0_CONFIG_CSN_PIN         22 /* Note: not defined by SDK */
 #define SPI0_CONFIG_SCK_PIN         23
 #define SPI0_CONFIG_MOSI_PIN        24
 #define SPI0_CONFIG_MISO_PIN        25
@@ -249,7 +248,6 @@
 #define SPIS0_ENABLED 1
 
 #if (SPIS0_ENABLED == 1)
-#define SPIS0_CONFIG_CSN_PIN         22 /* Note: not defined by SDK */
 #define SPIS0_CONFIG_SCK_PIN         23
 #define SPIS0_CONFIG_MOSI_PIN        24
 #define SPIS0_CONFIG_MISO_PIN        25

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/bsp/nrf52dk/src/os_bsp.c
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52dk/src/os_bsp.c b/hw/bsp/nrf52dk/src/os_bsp.c
index 80f8bac..fc135ff 100644
--- a/hw/bsp/nrf52dk/src/os_bsp.c
+++ b/hw/bsp/nrf52dk/src/os_bsp.c
@@ -29,6 +29,7 @@
 #include "uart/uart.h"
 #include "uart_hal/uart_hal.h"
 #include "os/os_dev.h"
+#include "bsp.h"
 
 #if MYNEWT_VAL(SPI_MASTER)
 #include "nrf_drv_spi.h"
@@ -158,14 +159,13 @@ bsp_init(void)
     assert(rc == 0);
 
 #if MYNEWT_VAL(SPI_MASTER)
-    /*  We initialize one SPI interface as a master. */
     rc = hal_spi_init(0, &spi_cfg, HAL_SPI_TYPE_MASTER);
     assert(rc == 0);
 #endif
 
 #if MYNEWT_VAL(SPI_SLAVE)
-    /*  We initialize one SPI interface as a master. */
-    spi_cfg.csn_pin = SPIS0_CONFIG_CSN_PIN;
+    spi_cfg.csn_pin = SPI_SS_PIN;
+    spi_cfg.csn_pullup = NRF_GPIO_PIN_PULLUP;
     rc = hal_spi_init(0, &spi_cfg, HAL_SPI_TYPE_SLAVE);
     assert(rc == 0);
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/hal/include/hal/hal_spi.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_spi.h b/hw/hal/include/hal/hal_spi.h
index 09d0f18..c542123 100644
--- a/hw/hal/include/hal/hal_spi.h
+++ b/hw/hal/include/hal/hal_spi.h
@@ -51,13 +51,10 @@ typedef void (*hal_spi_txrx_cb)(void *arg, int len);
  * can be changed on the fly from the hal
  */
 struct hal_spi_settings {
-    uint8_t         spi_type;
     uint8_t         data_mode;
     uint8_t         data_order;
     uint8_t         word_size;
     uint32_t        baudrate;
-    hal_spi_txrx_cb txrx_cb_func;
-    void            *txrx_cb_arg;
 };
 
 /**
@@ -74,7 +71,11 @@ struct hal_spi_settings {
 int hal_spi_init(int spi_num, void *cfg, uint8_t spi_type);
 
 /**
- * Configure the spi.
+ * 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
@@ -85,10 +86,12 @@ int hal_spi_config(int spi_num, struct hal_spi_settings *psettings);
 
 /**
  * Sets the txrx callback (executed at interrupt context) when the
- * buffer is transferred by the master or the slave using the hal_spi_rxtx API.
- * Allowed to be called when the spi is enabled but not when a transfer is in
- * progress. This callback will also be called when chip select is de-asserted
- * on the slave.
+ * 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
@@ -121,12 +124,12 @@ int hal_spi_disable(int spi_num);
 
 /**
  * Blocking call to send a value on the SPI. Returns the value received from the
- * SPI.
+ * SPI slave.
  *
  * MASTER: Sends the value and returns the received value from the slave.
  * SLAVE: Invalid API. Returns 0xFFFF
  *
- * @param spi_num   Spin interface to use
+ * @param spi_num   Spi interface to use
  * @param val       Value to send
  *
  * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
@@ -135,32 +138,66 @@ int hal_spi_disable(int spi_num);
 uint16_t hal_spi_tx_val(int spi_num, uint16_t val);
 
 /**
- * Sends a buffer and also stores the received values. This is always a
- * non-blocking call for a spi slave. It is a blocking call if the callback is
- * NULL; non-blocking if callback is set. For both the master and slave, the
- * txrx callback is executed at interrupt context when the buffer is sent.
+ * 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 cnt);
+
+/**
+ * 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
+ *     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. Can
- *                  be NULL.
- * @param len       Number of values to be transferred.
+ * @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 len);
+int hal_spi_txrx_noblock(int spi_num, void *txbuf, void *rxbuf, int cnt);
 
 /**
- * Sets the default value transferred by the slave.
+ * Sets the default value transferred by the slave. Not valid for master
  *
  * @param spi_num SPI interface to use
  *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/mcu/nordic/nrf51xxx/src/hal_spi.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf51xxx/src/hal_spi.c b/hw/mcu/nordic/nrf51xxx/src/hal_spi.c
index 010bd8b..cfa4a6d 100644
--- a/hw/mcu/nordic/nrf51xxx/src/hal_spi.c
+++ b/hw/mcu/nordic/nrf51xxx/src/hal_spi.c
@@ -58,6 +58,7 @@
 #define HAL_SPI_SLAVE_STATE_READY       (2)
 
 struct nrf51_hal_spi {
+    uint8_t spi_type;
     uint8_t spi_xfr_flag;   /* Master only */
     uint8_t slave_state;    /* Slave only */
     uint16_t nhs_buflen;
@@ -69,8 +70,13 @@ struct nrf51_hal_spi {
         nrf_drv_spis_t  spis;
     } nhs_spi;
 
+    /* Pointers to tx/rx buffers */
     uint8_t *nhs_txbuf;
     uint8_t *nhs_rxbuf;
+
+    /* Callback and arguments */
+    hal_spi_txrx_cb txrx_cb_func;
+    void            *txrx_cb_arg;
 };
 
 #if SPI0_ENABLED
@@ -133,11 +139,11 @@ nrf51_irqm_handler(struct nrf51_hal_spi *spi)
         }
         ++spi->nhs_rxd_bytes;
         if (spi->nhs_rxd_bytes == spi->nhs_buflen) {
-            if (spi->spi_cfg.txrx_cb_func) {
-                spi->spi_cfg.txrx_cb_func(spi->spi_cfg.txrx_cb_arg,
-                                          spi->nhs_buflen);
+            if (spi->txrx_cb_func) {
+                spi->txrx_cb_func(spi->txrx_cb_arg, spi->nhs_buflen);
             }
             spi->spi_xfr_flag = 0;
+            nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK);
         }
         if (spi->nhs_txd_bytes != spi->nhs_buflen) {
             nrf_spi_txd_set(p_spi, spi->nhs_txbuf[spi->nhs_txd_bytes]);
@@ -181,14 +187,14 @@ nrf51_irqs_handler(struct nrf51_hal_spi *spi)
     if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_END)) {
         nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END);
         if (spi->slave_state == HAL_SPI_SLAVE_STATE_READY) {
-            if (spi->spi_cfg.txrx_cb_func) {
+            if (spi->txrx_cb_func) {
                 /* Get transfer length */
                 if (spi->nhs_txbuf == NULL) {
                     xfr_len = nrf_spis_rx_amount_get(p_spis);
                 } else {
                     xfr_len = nrf_spis_tx_amount_get(p_spis);
                 }
-                spi->spi_cfg.txrx_cb_func(spi->spi_cfg.txrx_cb_arg, xfr_len);
+                spi->txrx_cb_func(spi->txrx_cb_arg, xfr_len);
             }
             spi->slave_state = HAL_SPI_SLAVE_STATE_IDLE;
         }
@@ -202,7 +208,7 @@ nrf51_irqs_handler(struct nrf51_hal_spi *spi)
 void
 nrf51_spi0_irq_handler(void)
 {
-    if (nrf51_hal_spi0.spi_cfg.spi_type == HAL_SPI_TYPE_MASTER) {
+    if (nrf51_hal_spi0.spi_type == HAL_SPI_TYPE_MASTER) {
         nrf51_irqm_handler(&nrf51_hal_spi0);
     } else {
         assert(0);
@@ -214,7 +220,7 @@ nrf51_spi0_irq_handler(void)
 void
 nrf51_spi1_irq_handler(void)
 {
-    if (nrf51_hal_spi1.spi_cfg.spi_type == HAL_SPI_TYPE_MASTER) {
+    if (nrf51_hal_spi1.spi_type == HAL_SPI_TYPE_MASTER) {
 #if SPI1_ENABLED
         nrf51_irqm_handler(&nrf51_hal_spi1);
 #else
@@ -326,6 +332,7 @@ hal_spi_config_slave(struct nrf51_hal_spi *spi,
     nrf_spis_bit_order_t bit_order;
 
     p_spis = spi->nhs_spi.spis.p_reg;
+    memcpy(&spi->spi_cfg, settings, sizeof(*settings));
 
     spi_mode = 0;
     switch (settings->data_mode) {
@@ -522,14 +529,15 @@ hal_spi_master_send_first(NRF_SPI_Type *p_spi, uint8_t txval)
 }
 
 /**
- * Initialize the SPI interface
+ * 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)
  *
- * @param spi_num
- * @param cfg
- * @param spi_type
- *
- * @return int
+ * @return int 0 on success, non-zero error code on failure.
  */
 int
 hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
@@ -551,7 +559,7 @@ hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
     }
 
     irq_handler = NULL;
-    spi->spi_cfg.spi_type  = spi_type;
+    spi->spi_type  = spi_type;
     if (spi_num == 0) {
 #if SPI0_ENABLED
         irq_handler = nrf51_spi0_irq_handler;
@@ -602,6 +610,18 @@ err:
     return (rc);
 }
 
+/**
+ * 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)
 {
@@ -610,10 +630,7 @@ hal_spi_config(int spi_num, struct hal_spi_settings *settings)
 
     NRF51_HAL_SPI_RESOLVE(spi_num, spi);
 
-    spi->spi_cfg.txrx_cb_func = settings->txrx_cb_func;
-    spi->spi_cfg.txrx_cb_arg = settings->txrx_cb_arg;
-
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         rc = hal_spi_config_master(spi, settings);
     } else {
         rc = hal_spi_config_slave(spi, settings);
@@ -642,16 +659,11 @@ hal_spi_enable(int spi_num)
 
     NRF51_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         p_spi = (NRF_SPI_Type *)spi->nhs_spi.spim.p_registers;
-        /* We need to enable this in blocking or non-blocking mode */
-        if (spi->spi_cfg.txrx_cb_func) {
-            nrf_spi_event_clear(p_spi, NRF_SPI_INT_READY_MASK);
-            nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK);
-        }
         nrf_spi_enable(p_spi);
     } else {
-        if (spi->spi_cfg.txrx_cb_func == NULL) {
+        if (spi->txrx_cb_func == NULL) {
             rc = EINVAL;
             goto err;
         }
@@ -686,7 +698,7 @@ hal_spi_disable(int spi_num)
 
     NRF51_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         p_spi = (NRF_SPI_Type *)spi->nhs_spi.spim.p_registers;
         nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK);
         spi->spi_xfr_flag = 0;
@@ -709,20 +721,19 @@ err:
 
 /**
  * Blocking call to send a value on the SPI. Returns the value received from the
- * SPI.
+ * SPI slave.
  *
  * MASTER: Sends the value and returns the received value from the slave.
- * SLAVE: Sets the value to send to the master when the master transfers a
- *        value. This value will be sent until another call to hal_spi_tx_val()
- *        is made. The return code is ignored for a slave.\ufffd
+ * SLAVE: Invalid API. Returns 0xFFFF
  *
- * @param spi_num
- * @param val
+ * @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 SPI configured as a Slave.
+ * if called when the SPI is configured to be a slave
  */
-uint16_t hal_spi_tx_val(int spi_num, uint16_t val)
+uint16_t
+hal_spi_tx_val(int spi_num, uint16_t val)
 {
     int rc;
     uint16_t retval;
@@ -731,7 +742,7 @@ uint16_t hal_spi_tx_val(int spi_num, uint16_t val)
 
     NRF51_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         p_spi = (NRF_SPI_Type *) spi->nhs_spi.spim.p_registers;
         nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
         nrf_spi_txd_set(p_spi, (uint8_t) val);
@@ -750,20 +761,18 @@ err:
 
 /**
  * Sets the txrx callback (executed at interrupt context) when the
- * buffer is transferred by the master or the slave using the hal_spi_rxtx API.
- * This callback is also called when the SPI is a slave and chip select is
- * de-asserted and there is data available in the receive buffer.
- *
- * If the callback is NULL, the SPI will be in blocking mode; otherwise it is
- * in non-blocking mode.
+ * 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.
  *
- * Cannot be called when the SPI is enabled.
+ * 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_cb   Pointer to callback function. NULL to set into blocking mode
- * @param arg       Argument passed to callback function.
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
  *
- * @return int 0 on success, -1 if spi is already enabled.
+ * @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)
@@ -782,8 +791,8 @@ hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
     if (p_spi->ENABLE != 0) {
         rc = -1;
     } else {
-        spi->spi_cfg.txrx_cb_func = txrx_cb;
-        spi->spi_cfg.txrx_cb_arg = arg;
+        spi->txrx_cb_func = txrx_cb;
+        spi->txrx_cb_arg = arg;
         rc = 0;
     }
 
@@ -792,24 +801,25 @@ err:
 }
 
 /**
- * Send a buffer and also store the received values. This call can be either
- * blocking or non-blocking for the master; it is always non-blocking for slave.
- * In non-blocking mode, the txrx callback is executed at interrupt context when
- * the buffer is sent.
+ * 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: 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 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.
+ *     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. Can
- *                  be NULL.
- * @param len       Number of values to be transferred.
+ * @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.
  */
@@ -825,66 +835,133 @@ hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int len)
     struct nrf51_hal_spi *spi;
 
     rc = EINVAL;
-    if (!len || (len > 255)) {
+    if (!len) {
         goto err;
     }
 
     NRF51_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
+        /* Must have a txbuf for master! */
+        if (txbuf == NULL) {
+            goto err;
+        }
+
         p_spi = (NRF_SPI_Type *) spi->nhs_spi.spim.p_registers;
-        if (spi->spi_cfg.txrx_cb_func) {
-            /* Must have a txbuf for master! */
-            if (txbuf == NULL) {
-                goto err;
-            }
+        nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK);
 
-            /* Not allowed if transfer in progress */
-            if (spi->spi_xfr_flag) {
-                rc = -1;
-                goto err;
+        /* Blocking spi transfer */
+        txd = (uint8_t *)txbuf;
+        hal_spi_master_send_first(p_spi, txd[0]);
+        txcnt = len - 1;
+        rxd = (uint8_t *)rxbuf;
+        for (i = 0; i < len; ++i) {
+            if (txcnt) {
+                ++txd;
+                nrf_spi_txd_set(p_spi, *txd);
+                --txcnt;
             }
-            spi->spi_xfr_flag = 1;
-
-            spi->nhs_buflen = (uint16_t)len;
-            spi->nhs_txbuf = txbuf;
-            spi->nhs_rxbuf = rxbuf;
-            spi->nhs_rxd_bytes = 0;
-            txd = (uint8_t *)txbuf;
-            hal_spi_master_send_first(p_spi, txd[0]);
-            spi->nhs_txd_bytes = 1;
-            if (len > 1) {
-                nrf_spi_txd_set(p_spi, txd[1]);
-                ++spi->nhs_txd_bytes;
-            }
-            nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK);
-        } else {
-            /* Blocking spi transfer */
-            txd = (uint8_t *)txbuf;
-            hal_spi_master_send_first(p_spi, txd[0]);
-            txcnt = len - 1;
-            rxd = (uint8_t *)rxbuf;
-            for (i = 0; i < len; ++i) {
-                if (txcnt) {
-                    ++txd;
-                    nrf_spi_txd_set(p_spi, *txd);
-                    --txcnt;
-                }
-                while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {}
-                nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
-                rxval = nrf_spi_rxd_get(p_spi);
-                if (rxbuf) {
-                    *rxd = rxval;
-                    ++rxd;
-                }
+            while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {}
+            nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
+            rxval = nrf_spi_rxd_get(p_spi);
+            if (rxbuf) {
+                *rxd = rxval;
+                ++rxd;
             }
         }
+        return 0;
+    }
+
+err:
+    return rc;
+}
+
+/**
+ * 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 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_noblock(int spi_num, void *txbuf, void *rxbuf, int len)
+{
+    int rc;
+    uint8_t *txd;
+    NRF_SPI_Type *p_spi;
+    struct nrf51_hal_spi *spi;
+
+    rc = EINVAL;
+    NRF51_HAL_SPI_RESOLVE(spi_num, spi);
+
+    if ((spi->txrx_cb_func == NULL) || (len == 0)) {
+        goto err;
+    }
+
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
+        /* Must have a txbuf for master! */
+        if (txbuf == NULL) {
+            goto err;
+        }
+
+        /* Not allowed if transfer in progress */
+        if (spi->spi_xfr_flag) {
+            rc = -1;
+            goto err;
+        }
+
+        p_spi = (NRF_SPI_Type *) spi->nhs_spi.spim.p_registers;
+        nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK);
+        spi->spi_xfr_flag = 1;
+
+        spi->nhs_buflen = (uint16_t)len;
+        spi->nhs_txbuf = txbuf;
+        spi->nhs_rxbuf = rxbuf;
+        spi->nhs_rxd_bytes = 0;
+        txd = (uint8_t *)txbuf;
+        hal_spi_master_send_first(p_spi, txd[0]);
+        spi->nhs_txd_bytes = 1;
+        if (len > 1) {
+            nrf_spi_txd_set(p_spi, txd[1]);
+            ++spi->nhs_txd_bytes;
+        }
+        nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK);
     } else {
-        /* Must have txbuf and rxbuf */
+        /* Must have txbuf or rxbuf */
         if ((txbuf == NULL) && (rxbuf == NULL)) {
             goto err;
         }
 
+        /* XXX: not sure what to for length > 255 */
+        if (len > 255) {
+            goto err;
+        }
+
         /*
          * Ready the slave for a transfer. Do not allow this to be called
          * if the slave has already been readied or is requesting the
@@ -908,7 +985,7 @@ err:
 }
 
 /**
- * Sets the default value transferred by the slave.
+ * Sets the default value transferred by the slave. Not valid for master
  *
  * @param spi_num SPI interface to use
  *
@@ -922,9 +999,10 @@ hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val)
     struct nrf51_hal_spi *spi;
 
     NRF51_HAL_SPI_RESOLVE(spi_num, spi);
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_SLAVE) {
+    if (spi->spi_type  == HAL_SPI_TYPE_SLAVE) {
         p_spis = spi->nhs_spi.spis.p_reg;
         nrf_spis_def_set(p_spis, (uint8_t) val);
+        nrf_spis_orc_set(p_spis, (uint8_t) val);
         rc = 0;
     } else {
         rc = EINVAL;
@@ -935,8 +1013,7 @@ err:
 }
 
 /**
- * This aborts the current transfer but keeps the spi enabled. Should only
- * be used when the SPI is in non-blocking mode.
+ * This aborts the current transfer but keeps the spi enabled.
  *
  * @param spi_num   SPI interface on which transfer should be aborted.
  *
@@ -954,11 +1031,7 @@ hal_spi_abort(int spi_num)
     NRF51_HAL_SPI_RESOLVE(spi_num, spi);
 
     rc = 0;
-    if (spi->spi_cfg.txrx_cb_func == NULL) {
-        goto err;
-    }
-
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         p_spi = (NRF_SPI_Type *)spi->nhs_spi.spim.p_registers;
         if (spi->spi_xfr_flag) {
             nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/26dfea0f/hw/mcu/nordic/nrf52xxx/src/hal_spi.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_spi.c b/hw/mcu/nordic/nrf52xxx/src/hal_spi.c
index 9b0e5c2..f2b0b1d 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_spi.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_spi.c
@@ -32,6 +32,10 @@
 #include <nrf_drv_common.h>
 #include <app_util_platform.h>
 
+#ifndef min
+#define min(a, b) ((a)<(b)?(a):(b))
+#endif
+
 /* XXX:
  * 1) what about stats?
  * 2) Dealing with errors (OVERFLOW, OVERREAD)
@@ -58,19 +62,25 @@
 #define HAL_SPI_SLAVE_STATE_READY       (2)
 
 struct nrf52_hal_spi {
+    uint8_t spi_type;
     uint8_t spi_xfr_flag;   /* Master only */
     uint8_t dummy_rx;       /* Master only */
     uint8_t slave_state;    /* Slave only */
-    uint8_t slave_buflen;   /* Slave only */
+    uint16_t nhs_buflen;
+    uint16_t nhs_bytes_txd;
     struct hal_spi_settings spi_cfg; /* Slave and master */
     union {
         nrf_drv_spi_t   spim;
         nrf_drv_spis_t  spis;
     } nhs_spi;
 
-    /* These are slave only */
-    uint8_t *slave_txbuf;
-    uint8_t *slave_rxbuf;
+    /* Pointers to tx/rx buffers */
+    uint8_t *nhs_txbuf;
+    uint8_t *nhs_rxbuf;
+
+    /* Callback and arguments */
+    hal_spi_txrx_cb txrx_cb_func;
+    void            *txrx_cb_arg;
 };
 
 #if SPI0_ENABLED || SPIS0_ENABLED
@@ -121,6 +131,8 @@ nrf_drv_spis_t inst_spi1_s = NRF_DRV_SPIS_INSTANCE(1);
 static void
 nrf52_irqm_handler(struct nrf52_hal_spi *spi)
 {
+    uint8_t xfr_bytes;
+    uint16_t len;
     NRF_SPIM_Type *p_spim;
 
     p_spim = spi->nhs_spi.spim.p_registers;
@@ -132,11 +144,29 @@ nrf52_irqm_handler(struct nrf52_hal_spi *spi)
             return;
         }
 
-        if (spi->spi_cfg.txrx_cb_func) {
-            spi->spi_cfg.txrx_cb_func(spi->spi_cfg.txrx_cb_arg,
-                                      p_spim->TXD.AMOUNT);
+        /* Are there more bytes to send? */
+        xfr_bytes = p_spim->TXD.AMOUNT;
+        spi->nhs_bytes_txd += xfr_bytes;
+        if (spi->nhs_bytes_txd < spi->nhs_buflen) {
+            spi->nhs_txbuf += xfr_bytes;
+            len = spi->nhs_buflen - spi->nhs_bytes_txd;
+            len = min(255, len);
+            nrf_spim_tx_buffer_set(p_spim, spi->nhs_txbuf, (uint8_t)len);
+
+            /* If no rxbuf, we need to set rxbuf and maxcnt to 1 */
+            if (spi->nhs_rxbuf) {
+                spi->nhs_rxbuf += xfr_bytes;
+                nrf_spim_rx_buffer_set(p_spim, spi->nhs_rxbuf, (uint8_t)len);
+            }
+            nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
+        } else {
+            if (spi->txrx_cb_func) {
+                spi->txrx_cb_func(spi->txrx_cb_arg, spi->nhs_buflen);
+
+            }
+            spi->spi_xfr_flag = 0;
+            nrf_spim_int_disable(p_spim, NRF_SPIM_INT_END_MASK);
         }
-        spi->spi_xfr_flag = 0;
     }
 }
 #endif
@@ -155,16 +185,16 @@ nrf52_irqs_handler(struct nrf52_hal_spi *spi)
         nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
 
         if (spi->slave_state == HAL_SPI_SLAVE_STATE_ACQ_SEM) {
-            if (spi->slave_txbuf == NULL) {
+            if (spi->nhs_txbuf == NULL) {
                 nrf_spis_tx_buffer_set(p_spis, 0, 0);
             } else {
-                nrf_spis_tx_buffer_set(p_spis, spi->slave_txbuf, spi->slave_buflen);
+                nrf_spis_tx_buffer_set(p_spis, spi->nhs_txbuf, spi->nhs_buflen);
             }
 
-            if (spi->slave_rxbuf == NULL) {
+            if (spi->nhs_rxbuf == NULL) {
                 nrf_spis_rx_buffer_set(p_spis, 0, 0);
             } else {
-                nrf_spis_rx_buffer_set(p_spis, spi->slave_rxbuf, spi->slave_buflen);
+                nrf_spis_rx_buffer_set(p_spis, spi->nhs_rxbuf, spi->nhs_buflen);
             }
             nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_RELEASE);
             spi->slave_state = HAL_SPI_SLAVE_STATE_READY;
@@ -175,14 +205,14 @@ nrf52_irqs_handler(struct nrf52_hal_spi *spi)
     if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_END)) {
         nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END);
         if (spi->slave_state == HAL_SPI_SLAVE_STATE_READY) {
-            if (spi->spi_cfg.txrx_cb_func) {
+            if (spi->txrx_cb_func) {
                 /* Get transfer length */
-                if (spi->slave_txbuf == NULL) {
+                if (spi->nhs_txbuf == NULL) {
                     xfr_len = nrf_spis_rx_amount_get(p_spis);
                 } else {
                     xfr_len = nrf_spis_tx_amount_get(p_spis);
                 }
-                spi->spi_cfg.txrx_cb_func(spi->spi_cfg.txrx_cb_arg, xfr_len);
+                spi->txrx_cb_func(spi->txrx_cb_arg, xfr_len);
             }
             spi->slave_state = HAL_SPI_SLAVE_STATE_IDLE;
         }
@@ -196,7 +226,7 @@ nrf52_irqs_handler(struct nrf52_hal_spi *spi)
 void
 nrf52_spi0_irq_handler(void)
 {
-    if (nrf52_hal_spi0.spi_cfg.spi_type == HAL_SPI_TYPE_MASTER) {
+    if (nrf52_hal_spi0.spi_type == HAL_SPI_TYPE_MASTER) {
         nrf52_irqm_handler(&nrf52_hal_spi0);
     } else {
         nrf52_irqs_handler(&nrf52_hal_spi0);
@@ -208,7 +238,7 @@ nrf52_spi0_irq_handler(void)
 void
 nrf52_spi1_irq_handler(void)
 {
-    if (nrf52_hal_spi1.spi_cfg.spi_type == HAL_SPI_TYPE_MASTER) {
+    if (nrf52_hal_spi1.spi_type == HAL_SPI_TYPE_MASTER) {
         nrf52_irqm_handler(&nrf52_hal_spi1);
     } else {
         nrf52_irqs_handler(&nrf52_hal_spi1);
@@ -508,14 +538,15 @@ hal_spi_init_slave(nrf_drv_spis_t *p_instance,
 }
 
 /**
- * Initialize the SPI interface
+ * 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)
  *
- * @param spi_num
- * @param cfg
- * @param spi_type
- *
- * @return int
+ * @return int 0 on success, non-zero error code on failure.
  */
 int
 hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
@@ -537,7 +568,7 @@ hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
     }
 
     irq_handler = NULL;
-    spi->spi_cfg.spi_type  = spi_type;
+    spi->spi_type  = spi_type;
     if (spi_num == 0) {
 #if SPI0_ENABLED || SPIS0_ENABLED
         irq_handler = nrf52_spi0_irq_handler;
@@ -596,18 +627,37 @@ err:
     return (rc);
 }
 
+/**
+ * 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)
 {
     int rc;
     struct nrf52_hal_spi *spi;
+    NRF_SPIM_Type *p_spim;
 
     NRF52_HAL_SPI_RESOLVE(spi_num, spi);
 
-    spi->spi_cfg.txrx_cb_func = settings->txrx_cb_func;
-    spi->spi_cfg.txrx_cb_arg = settings->txrx_cb_arg;
+    /*
+     * This looks odd, but the ENABLE register is in the same location for
+     * SPIM, SPI and SPIS
+     */
+    p_spim = spi->nhs_spi.spim.p_registers;
+    if (p_spim->ENABLE != 0) {
+        return -1;
+    }
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         rc = hal_spi_config_master(spi, settings);
     } else {
         rc = hal_spi_config_slave(spi, settings);
@@ -636,18 +686,12 @@ hal_spi_enable(int spi_num)
 
     NRF52_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
+        /* For now, enable this in normal SPI mode (not spim) */
         p_spim = spi->nhs_spi.spim.p_registers;
-        /* We need to enable this in blocking or non-blocking mode */
-        if (spi->spi_cfg.txrx_cb_func) {
-            nrf_spim_event_clear(p_spim, NRF_SPIM_INT_END_MASK);
-            nrf_spim_int_enable(p_spim, NRF_SPIM_INT_END_MASK);
-            nrf_spim_enable(p_spim);
-        } else {
-            nrf_spi_enable((NRF_SPI_Type *)p_spim);
-        }
+        nrf_spi_enable((NRF_SPI_Type *)p_spim);
     } else {
-        if (spi->spi_cfg.txrx_cb_func == NULL) {
+        if (spi->txrx_cb_func == NULL) {
             rc = EINVAL;
             goto err;
         }
@@ -682,7 +726,7 @@ hal_spi_disable(int spi_num)
 
     NRF52_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         p_spim = spi->nhs_spi.spim.p_registers;
         nrf_spim_int_disable(p_spim, NRF_SPI_IRQ_DISABLE_ALL);
         if (spi->spi_xfr_flag) {
@@ -697,9 +741,13 @@ hal_spi_disable(int spi_num)
         nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
         nrf_spis_disable(p_spis);
         spi->slave_state = HAL_SPI_SLAVE_STATE_IDLE;
-        spi->slave_txbuf = NULL;
-        spi->slave_rxbuf = NULL;
     }
+
+    spi->nhs_txbuf = NULL;
+    spi->nhs_rxbuf = NULL;
+    spi->nhs_buflen = 0;
+    spi->nhs_bytes_txd = 0;
+
     rc = 0;
 
 err:
@@ -708,18 +756,16 @@ err:
 
 /**
  * Blocking call to send a value on the SPI. Returns the value received from the
- * SPI.
+ * SPI slave.
  *
  * MASTER: Sends the value and returns the received value from the slave.
- * SLAVE: Sets the value to send to the master when the master transfers a
- *        value. This value will be sent until another call to hal_spi_tx_val()
- *        is made. The return code is ignored for a slave.\ufffd
+ * SLAVE: Invalid API. Returns 0xFFFF
  *
- * @param spi_num
- * @param val
+ * @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 SPI configured as a Slave.
+ * if called when the SPI is configured to be a slave
  */
 uint16_t hal_spi_tx_val(int spi_num, uint16_t val)
 {
@@ -730,7 +776,7 @@ uint16_t hal_spi_tx_val(int spi_num, uint16_t val)
 
     NRF52_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         p_spi = (NRF_SPI_Type *) spi->nhs_spi.spim.p_registers;
         nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
         nrf_spi_txd_set(p_spi, (uint8_t) val);
@@ -749,20 +795,18 @@ err:
 
 /**
  * Sets the txrx callback (executed at interrupt context) when the
- * buffer is transferred by the master or the slave using the hal_spi_rxtx API.
- * This callback is also called when the SPI is a slave and chip select is
- * de-asserted and there is data available in the receive buffer.
- *
- * If the callback is NULL, the SPI will be in blocking mode; otherwise it is
- * in non-blocking mode.
+ * 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.
  *
- * Cannot be called when the SPI is enabled.
+ * 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_cb   Pointer to callback function. NULL to set into blocking mode
- * @param arg       Argument passed to callback function.
+ * @param txrx      Callback function
+ * @param arg       Argument to be passed to callback function
  *
- * @return int 0 on success, -1 if spi is already enabled.
+ * @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)
@@ -781,8 +825,8 @@ hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
     if (p_spim->ENABLE != 0) {
         rc = -1;
     } else {
-        spi->spi_cfg.txrx_cb_func = txrx_cb;
-        spi->spi_cfg.txrx_cb_arg = arg;
+        spi->txrx_cb_func = txrx_cb;
+        spi->txrx_cb_arg = arg;
         rc = 0;
     }
 
@@ -791,24 +835,25 @@ err:
 }
 
 /**
- * Send a buffer and also store the received values. This call can be either
- * blocking or non-blocking for the master; it is always non-blocking for slave.
- * In non-blocking mode, the txrx callback is executed at interrupt context when
- * the buffer is sent.
+ * 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: 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 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.
+ *     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. Can
- *                  be NULL.
- * @param len       Number of values to be transferred.
+ * @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.
  */
@@ -818,6 +863,7 @@ hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int len)
     int i;
     int rc;
     int txcnt;
+    uint32_t enabled;
     uint8_t *txd, *rxd;
     uint8_t rxval;
     NRF_SPI_Type *p_spi;
@@ -825,73 +871,161 @@ hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int len)
     struct nrf52_hal_spi *spi;
 
     rc = EINVAL;
-    if (!len || (len > 255)) {
+    if (!len) {
         goto err;
     }
 
     NRF52_HAL_SPI_RESOLVE(spi_num, spi);
 
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
-        if (spi->spi_cfg.txrx_cb_func) {
-            /* Must have a txbuf for master! */
-            if (txbuf == NULL) {
-                goto err;
-            }
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
+        /* Must have a txbuf for master! */
+        if (txbuf == NULL) {
+            goto err;
+        }
 
-            /* Not allowed if transfer in progress */
-            if (spi->spi_xfr_flag) {
-                rc = -1;
-                goto err;
-            }
-            spi->spi_xfr_flag = 1;
+        /*
+         * If SPIM is enabled, we want to stop, disable, then enable
+         * the legacy SPI interface.
+         */
+        p_spim = spi->nhs_spi.spim.p_registers;
+        enabled = p_spim->ENABLE;
+        if (enabled == SPIM_ENABLE_ENABLE_Enabled) {
+            nrf_spim_int_disable(p_spim, NRF_SPI_IRQ_DISABLE_ALL);
+            hal_spi_stop_transfer(p_spim);
+            nrf_spim_disable(p_spim);
+            enabled = 0;
+        }
 
-            p_spim = spi->nhs_spi.spim.p_registers;
-            nrf_spim_tx_buffer_set(p_spim, txbuf, len);
+        if (enabled == 0) {
+            nrf_spi_enable((NRF_SPI_Type *)p_spim);
+        }
 
-            /* If no rxbuf, we need to set rxbuf and maxcnt to 1 */
-            if (rxbuf == NULL) {
-                nrf_spim_rx_buffer_set(p_spim, &spi->dummy_rx, 1);
-            } else {
-                nrf_spim_rx_buffer_set(p_spim, rxbuf, len);
+        p_spi = (NRF_SPI_Type *) spi->nhs_spi.spim.p_registers;
+        while (nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {
+            rxval = nrf_spi_rxd_get(p_spi);
+            nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
+        }
+        txd = (uint8_t *)txbuf;
+        nrf_spi_txd_set(p_spi, *txd);
+        txcnt = len - 1;
+        rxd = (uint8_t *)rxbuf;
+        for (i = 0; i < len; ++i) {
+            if (txcnt) {
+                ++txd;
+                nrf_spi_txd_set(p_spi, *txd);
+                --txcnt;
+            }
+            while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {}
+            nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
+            rxval = nrf_spi_rxd_get(p_spi);
+            if (rxbuf) {
+                *rxd = rxval;
+                ++rxd;
             }
+        }
+        return 0;
+    }
 
-            nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
-            nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STOPPED);
+err:
+    return rc;
+}
 
-            nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
-            nrf_spim_int_enable(p_spim, NRF_SPIM_INT_END_MASK);
+/**
+ * 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 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_noblock(int spi_num, void *txbuf, void *rxbuf, int len)
+{
+    int rc;
+    NRF_SPIM_Type *p_spim;
+    struct nrf52_hal_spi *spi;
+
+    rc = EINVAL;
+    NRF52_HAL_SPI_RESOLVE(spi_num, spi);
+
+    if ((spi->txrx_cb_func == NULL) || (len == 0)) {
+        goto err;
+    }
+
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
+        /* Must have a txbuf for master! */
+        if (txbuf == NULL) {
+            goto err;
+        }
+
+        /* Not allowed if transfer in progress */
+        if (spi->spi_xfr_flag) {
+            rc = -1;
+            goto err;
+        }
+        p_spim = spi->nhs_spi.spim.p_registers;
+        nrf_spim_int_disable(p_spim, NRF_SPIM_INT_END_MASK);
+        spi->spi_xfr_flag = 1;
+
+        /* Must be enabled for SPIM as opposed to SPI */
+        if (p_spim->ENABLE != SPIM_ENABLE_ENABLE_Enabled) {
+            p_spim->ENABLE = 0;
+            nrf_spim_enable(p_spim);
+        }
+
+        spi->nhs_bytes_txd = 0;
+        spi->nhs_buflen = len;
+        spi->nhs_txbuf = txbuf;
+        nrf_spim_tx_buffer_set(p_spim, txbuf, len);
+
+        /* If no rxbuf, we need to set rxbuf and maxcnt to 1 */
+        spi->nhs_rxbuf = rxbuf;
+        if (rxbuf == NULL) {
+            nrf_spim_rx_buffer_set(p_spim, &spi->dummy_rx, 1);
         } else {
-            /* Blocking spi transfer */
-            p_spi = (NRF_SPI_Type *) spi->nhs_spi.spim.p_registers;
-            while (nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {
-                rxval = nrf_spi_rxd_get(p_spi);
-                nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
-            }
-            txd = (uint8_t *)txbuf;
-            nrf_spi_txd_set(p_spi, *txd);
-            txcnt = len - 1;
-            rxd = (uint8_t *)rxbuf;
-            for (i = 0; i < len; ++i) {
-                if (txcnt) {
-                    ++txd;
-                    nrf_spi_txd_set(p_spi, *txd);
-                    --txcnt;
-                }
-                while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {}
-                nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY);
-                rxval = nrf_spi_rxd_get(p_spi);
-                if (rxbuf) {
-                    *rxd = rxval;
-                    ++rxd;
-                }
-            }
+            nrf_spim_rx_buffer_set(p_spim, rxbuf, len);
         }
+
+        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
+        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STOPPED);
+
+        nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
+        nrf_spim_int_enable(p_spim, NRF_SPIM_INT_END_MASK);
     } else {
-        /* Must have txbuf and rxbuf */
+        /* Must have txbuf or rxbuf */
         if ((txbuf == NULL) && (rxbuf == NULL)) {
             goto err;
         }
 
+        /* XXX: what to do here? */
+        if (len > 255) {
+            goto err;
+        }
+
         /*
          * Ready the slave for a transfer. Do not allow this to be called
          * if the slave has already been readied or is requesting the
@@ -902,9 +1036,9 @@ hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int len)
             goto err;
         }
 
-        spi->slave_rxbuf = rxbuf;
-        spi->slave_txbuf = txbuf;
-        spi->slave_buflen = len;
+        spi->nhs_rxbuf = rxbuf;
+        spi->nhs_txbuf = txbuf;
+        spi->nhs_buflen = len;
         spi->slave_state = HAL_SPI_SLAVE_STATE_ACQ_SEM;
         nrf_spis_task_trigger(spi->nhs_spi.spis.p_reg, NRF_SPIS_TASK_ACQUIRE);
     }
@@ -915,7 +1049,7 @@ err:
 }
 
 /**
- * Sets the default value transferred by the slave.
+ * Sets the default value transferred by the slave. Not valid for master
  *
  * @param spi_num SPI interface to use
  *
@@ -929,9 +1063,10 @@ hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val)
     struct nrf52_hal_spi *spi;
 
     NRF52_HAL_SPI_RESOLVE(spi_num, spi);
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_SLAVE) {
+    if (spi->spi_type  == HAL_SPI_TYPE_SLAVE) {
         p_spis = spi->nhs_spi.spis.p_reg;
         nrf_spis_def_set(p_spis, (uint8_t) val);
+        nrf_spis_orc_set(p_spis, (uint8_t) val);
         rc = 0;
     } else {
         rc = EINVAL;
@@ -942,8 +1077,7 @@ err:
 }
 
 /**
- * This aborts the current transfer but keeps the spi enabled. Should only
- * be used when the SPI is in non-blocking mode.
+ * This aborts the current transfer but keeps the spi enabled.
  *
  * @param spi_num   SPI interface on which transfer should be aborted.
  *
@@ -961,11 +1095,7 @@ hal_spi_abort(int spi_num)
     NRF52_HAL_SPI_RESOLVE(spi_num, spi);
 
     rc = 0;
-    if (spi->spi_cfg.txrx_cb_func == NULL) {
-        goto err;
-    }
-
-    if (spi->spi_cfg.spi_type  == HAL_SPI_TYPE_MASTER) {
+    if (spi->spi_type  == HAL_SPI_TYPE_MASTER) {
         p_spim = spi->nhs_spi.spim.p_registers;
         if (spi->spi_xfr_flag) {
             nrf_spim_int_disable(p_spim, NRF_SPI_IRQ_DISABLE_ALL);