andrzej-kaczmarek commented on a change in pull request #1507: [RFC] Add 
generic serial bus driver
URL: https://github.com/apache/mynewt-core/pull/1507#discussion_r234258876
 
 

 ##########
 File path: hw/bus/spi/src/spi.c
 ##########
 @@ -0,0 +1,225 @@
+/*
+ * 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 "hal/hal_gpio.h"
+#include "hal/hal_spi.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/spi.h"
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+
+    rc = hal_spi_enable(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 *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(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(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(dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(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_dev *dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    uint8_t val;
+    int i;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    rc = 0;
+
+    hal_gpio_write(node->pin_cs, 0);
+
+    for (i = 0; i < length; i++) {
+        val = hal_spi_tx_val(dev->cfg.spi_num, 0xAA);
+        if (val == 0xFFFF) {
+            rc = SYS_EINVAL;
+            break;
+        }
+
+        buf[i] = val;
+    }
+
+    if (rc || !(flags & BUS_F_NOSTOP)) {
+        hal_gpio_write(node->pin_cs, 1);
+    }
+
+    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_dev *dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    hal_gpio_write(node->pin_cs, 0);
+
+    /* XXX update HAL to accept const instead */
+    rc = hal_spi_txrx(dev->cfg.spi_num, (uint8_t *)buf, NULL, length);
+
+    if (!(flags & BUS_F_NOSTOP)) {
+        hal_gpio_write(node->pin_cs, 1);
+    }
+
+    return rc;
+}
+
+static int bus_spi_disable(struct bus_dev *bdev)
+{
+    struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+
+    rc = hal_spi_disable(dev->cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static const struct bus_dev_ops bus_spi_ops = {
+    .enable = bus_spi_enable,
+    .configure = bus_spi_configure,
+    .read = bus_spi_read,
+    .write = bus_spi_write,
+    .disable = bus_spi_disable,
 
 Review comment:
   `bus_node_write_read_transact` does write-then-read to simplify perhaps one 
of most common transaction for peripheral devices. I also had write-and-read 
API prototype but removed it as I did not implement it since I don't really 
know device which would require it (I've only seen ones that can use it, but 
not require). This can be added later as a `bus_node` API and as a new op here 
(like `write_read`). My original idea was that this would work as expected for 
SPI bus and return `SYS_ENOTSUP` for I2C bus. For now, as you mentioned, one 
can just lock bus manually via `bus_dev_lock_by_node` (btw, I don't like this 
name, thinking of changing it) and use HAL if really necessary.
   
   Once I add async APIs which can use non-blocking HAL calls I think it will 
require to add non-blocking versions of read, write (and read-write) ops as 
well.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to