You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2020/04/25 07:58:06 UTC
[mynewt-core] branch master updated: hw/drivers/i2s: Add I2S driver
for NRF52 family
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new fd33ea1 hw/drivers/i2s: Add I2S driver for NRF52 family
fd33ea1 is described below
commit fd33ea1c98c2bc1d658254c7a9fbc4aa7264374f
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Fri Apr 10 16:25:40 2020 +0200
hw/drivers/i2s: Add I2S driver for NRF52 family
I2S driver implementation for NRF52 MCUs.
---
.../i2s/i2s_nrf52/include/i2s_nrf52/i2s_nrf52.h | 37 ++++
hw/drivers/i2s/i2s_nrf52/pkg.yml | 29 +++
hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c | 235 +++++++++++++++++++++
hw/drivers/i2s/i2s_nrf52/syscfg.yml | 19 ++
4 files changed, 320 insertions(+)
diff --git a/hw/drivers/i2s/i2s_nrf52/include/i2s_nrf52/i2s_nrf52.h b/hw/drivers/i2s/i2s_nrf52/include/i2s_nrf52/i2s_nrf52.h
new file mode 100644
index 0000000..2e5f3d6
--- /dev/null
+++ b/hw/drivers/i2s/i2s_nrf52/include/i2s_nrf52/i2s_nrf52.h
@@ -0,0 +1,37 @@
+/*
+ * 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 _I2S_NRF52_H
+#define _I2S_NRF52_H
+
+#include <stdint.h>
+#include <nrfx/nrfx.h>
+#include <nrfx/drivers/include/nrfx_i2s.h>
+
+struct i2s;
+
+struct i2s_cfg {
+ nrfx_i2s_config_t nrfx_i2s_cfg;
+
+ uint32_t sample_rate;
+
+ struct i2s_buffer_pool *pool;
+};
+
+#endif /* _I2S_NRF52_H */
diff --git a/hw/drivers/i2s/i2s_nrf52/pkg.yml b/hw/drivers/i2s/i2s_nrf52/pkg.yml
new file mode 100644
index 0000000..14bae07
--- /dev/null
+++ b/hw/drivers/i2s/i2s_nrf52/pkg.yml
@@ -0,0 +1,29 @@
+#
+# 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: hw/drivers/i2s/i2s_nrf52
+pkg.description: I2S driver for NRF52
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.apis:
+ - I2S_HW_IMPL
+pkg.deps:
+ - "@apache-mynewt-core/hw/drivers/i2s"
diff --git a/hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c b/hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c
new file mode 100644
index 0000000..ea39f81
--- /dev/null
+++ b/hw/drivers/i2s/i2s_nrf52/src/i2s_nrf52.c
@@ -0,0 +1,235 @@
+/*
+ * 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/mynewt.h>
+#include <bsp/bsp.h>
+#include <i2s/i2s.h>
+#include <i2s/i2s_driver.h>
+#include <i2s_nrf52/i2s_nrf52.h>
+#include <nrfx/drivers/include/nrfx_i2s.h>
+
+struct nrf52_i2s {
+ nrfx_i2s_config_t nrfx_i2s_cfg;
+ bool running;
+ int8_t nrfx_queued_count;
+ struct i2s *i2s;
+ struct i2s_sample_buffer *nrfx_buffers[2];
+};
+
+static struct nrf52_i2s nrf52_i2s;
+
+static void
+nrfx_add_buffer(struct i2s *i2s, struct i2s_sample_buffer *buffer)
+{
+ nrfx_i2s_buffers_t nrfx_buffers = {0};
+ nrfx_err_t err;
+
+ assert(i2s != NULL);
+ if (buffer == NULL) {
+ return;
+ }
+
+ if (i2s->direction == I2S_OUT || i2s->direction == I2S_OUT_IN) {
+ nrfx_buffers.p_tx_buffer = buffer->sample_data;
+ }
+ if (i2s->direction == I2S_IN || i2s->direction == I2S_OUT_IN) {
+ nrfx_buffers.p_rx_buffer = buffer->sample_data;
+ }
+
+ assert(nrf52_i2s.nrfx_queued_count < 2);
+ assert(nrf52_i2s.nrfx_buffers[nrf52_i2s.nrfx_queued_count] == NULL);
+
+ nrf52_i2s.nrfx_buffers[nrf52_i2s.nrfx_queued_count] = buffer;
+ nrf52_i2s.nrfx_queued_count++;
+ if (nrf52_i2s.nrfx_queued_count == 1) {
+ i2s_driver_state_changed (i2s, I2S_STATE_RUNNING);
+ err = nrfx_i2s_start(&nrfx_buffers, buffer->sample_count * i2s->sample_size_in_bytes / 4, 0);
+ } else {
+ err = nrfx_i2s_next_buffers_set(&nrfx_buffers);
+ }
+
+ assert(err == NRFX_SUCCESS);
+}
+
+static void
+feed_nrfx(void)
+{
+ struct i2s_sample_buffer *buffer;
+
+ buffer = i2s_driver_buffer_get(nrf52_i2s.i2s);
+ nrfx_add_buffer(nrf52_i2s.i2s, buffer);
+}
+
+static void
+nrf52_i2s_data_handler(const nrfx_i2s_buffers_t *p_released, uint32_t status)
+{
+ struct i2s_sample_buffer *buffer;
+
+ if (p_released != NULL &&
+ (p_released->p_rx_buffer != NULL || p_released->p_tx_buffer != NULL)) {
+ nrf52_i2s.nrfx_queued_count--;
+ assert(nrf52_i2s.nrfx_queued_count >= 0);
+ buffer = nrf52_i2s.nrfx_buffers[0];
+ assert(buffer->sample_data == p_released->p_tx_buffer || buffer->sample_data == p_released->p_rx_buffer);
+ nrf52_i2s.nrfx_buffers[0] = nrf52_i2s.nrfx_buffers[1];
+ nrf52_i2s.nrfx_buffers[1] = NULL;
+ i2s_driver_buffer_put(nrf52_i2s.i2s, buffer);
+ }
+ if (nrf52_i2s.running && nrf52_i2s.nrfx_queued_count < 2) {
+ assert(nrf52_i2s.nrfx_buffers[1] == NULL);
+ feed_nrfx();
+ }
+ if (status == NRFX_I2S_STATUS_TRANSFER_STOPPED) {
+ i2s_driver_state_changed(nrf52_i2s.i2s, I2S_STATE_STOPPED);
+ }
+}
+
+static int
+nrf52_i2s_init(struct i2s *i2s, const struct i2s_cfg *cfg)
+{
+ int rc;
+
+ nrf52_i2s.i2s = i2s;
+
+ NVIC_SetVector(nrfx_get_irq_number(NRF_I2S), (uint32_t) nrfx_i2s_irq_handler);
+
+ nrf52_i2s.nrfx_i2s_cfg = cfg->nrfx_i2s_cfg;
+ switch (cfg->nrfx_i2s_cfg.sample_width) {
+ case NRF_I2S_SWIDTH_8BIT:
+ i2s->sample_size_in_bytes = 1;
+ break;
+ case NRF_I2S_SWIDTH_16BIT:
+ i2s->sample_size_in_bytes = 2;
+ break;
+ case NRF_I2S_SWIDTH_24BIT:
+ i2s->sample_size_in_bytes = 4;
+ break;
+ }
+
+ i2s->direction = I2S_INVALID;
+ if (cfg->nrfx_i2s_cfg.sdin_pin != NRFX_I2S_PIN_NOT_USED) {
+ i2s->direction = I2S_IN;
+ }
+ if (cfg->nrfx_i2s_cfg.sdout_pin != NRFX_I2S_PIN_NOT_USED) {
+ i2s->direction |= I2S_OUT;
+ }
+
+ rc = i2s_init(i2s, cfg->pool);
+
+ if (rc != OS_OK) {
+ nrfx_i2s_uninit();
+ goto end;
+ }
+
+ i2s->sample_rate = cfg->sample_rate;
+ i2s->driver_data = &nrf52_i2s;
+end:
+ return rc;
+}
+
+int
+i2s_create(struct i2s *i2s, const char *name, const struct i2s_cfg *cfg)
+{
+ return os_dev_create(&i2s->dev, name, OS_DEV_INIT_PRIMARY,
+ 100, (os_dev_init_func_t)nrf52_i2s_init, (void *)cfg);
+}
+
+int
+i2s_driver_stop(struct i2s *i2s)
+{
+ struct i2s_sample_buffer *buffer;
+
+ nrf52_i2s.running = false;
+ nrfx_i2s_stop();
+
+ assert(nrf52_i2s.i2s->state == I2S_STATE_STOPPED);
+
+ while (NULL != (buffer = i2s_driver_buffer_get(i2s))) {
+ i2s_driver_buffer_put(i2s, buffer);
+ }
+
+ return 0;
+}
+
+static void
+nrf52_select_i2s_clock_cfg(nrfx_i2s_config_t *cfg, uint32_t sample_rate)
+{
+ cfg->ratio = NRF_I2S_RATIO_32X;
+ switch (sample_rate) {
+ case 16000:
+ cfg->mck_setup = NRF_I2S_MCK_32MDIV63;
+ break;
+ case 22500:
+ cfg->mck_setup = NRF_I2S_MCK_32MDIV42;
+ break;
+ case 32000:
+ cfg->mck_setup = NRF_I2S_MCK_32MDIV31;
+ break;
+ case 441000:
+ cfg->mck_setup = NRF_I2S_MCK_32MDIV23;
+ break;
+ case 48000:
+ cfg->ratio = NRF_I2S_RATIO_48X;
+ cfg->mck_setup = NRF_I2S_MCK_32MDIV21;
+ break;
+ default:
+ assert(0);
+ cfg->mck_setup = NRF_I2S_MCK_32MDIV63;
+ }
+}
+
+int
+i2s_driver_start(struct i2s *i2s)
+{
+ int rc = 0;
+
+ if (!nrf52_i2s.running) {
+ nrf52_i2s.running = true;
+ nrf52_select_i2s_clock_cfg(&nrf52_i2s.nrfx_i2s_cfg, i2s->sample_rate);
+ nrfx_i2s_init(&nrf52_i2s.nrfx_i2s_cfg, nrf52_i2s_data_handler);
+
+ assert(nrf52_i2s.nrfx_buffers[0] == NULL);
+ assert(nrf52_i2s.nrfx_buffers[1] == NULL);
+ assert(!STAILQ_EMPTY(&i2s->driver_queue));
+
+ nrf52_i2s.nrfx_queued_count = 0;
+ feed_nrfx();
+ }
+ return rc;
+}
+
+void
+i2s_driver_buffer_queued(struct i2s *i2s)
+{
+ if (nrf52_i2s.nrfx_queued_count < 2 && nrf52_i2s.running) {
+ feed_nrfx();
+ }
+}
+
+int
+i2s_driver_suspend(struct i2s *i2s, os_time_t timeout, int arg)
+{
+ return OS_OK;
+}
+
+int
+i2s_driver_resume(struct i2s *i2s)
+{
+ return OS_OK;
+}
diff --git a/hw/drivers/i2s/i2s_nrf52/syscfg.yml b/hw/drivers/i2s/i2s_nrf52/syscfg.yml
new file mode 100644
index 0000000..2cdd574
--- /dev/null
+++ b/hw/drivers/i2s/i2s_nrf52/syscfg.yml
@@ -0,0 +1,19 @@
+# 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.
+#
+
+syscfg.defs: