fc04d551创建于 4月21日历史提交
/****************************************************************************
 * arch/arm/src/nrf53/nrf53_ipc.c
 *
 * 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.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <nuttx/config.h>

#include <assert.h>
#include <debug.h>
#include <inttypes.h>
#include <stdint.h>

#include <nuttx/arch.h>

#include "arm_internal.h"
#include "nrf53_ipc.h"
#include "hardware/nrf53_ipc.h"

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/****************************************************************************
 * Private Types
 ****************************************************************************/

/* IPC receive channel configuration */

struct nrf53_ipc_recv_s
{
  ipc_callback_t callback;
  void *args;
};

/* IPC device */

struct nrf53_ipc_s
{
  struct nrf53_ipc_recv_s recv[NRF53_IPC_CHANS];
};

/****************************************************************************
 * Private Data
 ****************************************************************************/

struct nrf53_ipc_s g_nrf53_ipc;

/****************************************************************************
 * Private Functions
 ****************************************************************************/

/****************************************************************************
 * Name: nrf53_ipc_interrupt
 ****************************************************************************/

static int nrf53_ipc_interrupt(int irq, void *context, void *args)
{
  struct nrf53_ipc_s *dev    = args;
  uint32_t            regval = 0;
  int                 i      = 0;

  regval = getreg32(NRF53_IPC_INTPEND);

  ipcinfo("IPC interrupt 0x%" PRIx32 "\n", regval);

  for (i = 0; i < NRF53_IPC_CHANS; i += 1)
    {
      if (regval & IPC_CHAN_ID(i))
        {
          if (dev->recv[i].callback)
            {
              dev->recv[i].callback(i, dev->recv[i].args);
            }

          /* Clear EVENT */

          putreg32(0, NRF53_IPC_EVENTS_RECEIVE(i));
        }
    }

  return 0;
}

/****************************************************************************
 * Public Functions
 ****************************************************************************/

/****************************************************************************
 * Name: nrf53_ipc_subscribe
 ****************************************************************************/

void nrf53_ipc_subscribe(int id, ipc_callback_t callback, void *args)
{
  struct nrf53_ipc_s *dev = &g_nrf53_ipc;

  DEBUGASSERT(id < NRF53_IPC_CHANS);

  ipcinfo("IPC subscribe %d\n", id);

  /* Register callaback */

  dev->recv[id].callback = callback;
  dev->recv[id].args = args;

  if (callback)
    {
      /* Register as receive channel and enable interrupts */

      putreg32(IPC_CHAN_ID(id), NRF53_IPC_RECEIVE_CNF(id));
      putreg32(IPC_CHAN_ID(id), NRF53_IPC_INTENSET);
    }
  else
    {
      /* Disable interrupts */

      putreg32(IPC_CHAN_ID(id), NRF53_IPC_INTENCLR);
    }
}

/****************************************************************************
 * Name: nrf53_ipc_signal
 ****************************************************************************/

void nrf53_ipc_signal(int id)
{
  DEBUGASSERT(id < NRF53_IPC_CHANS);

  ipcinfo("IPC signal %d\n", id);

  putreg32(1, NRF53_IPC_TASKS_SEND(id));
}

/****************************************************************************
 * Name: nrf53_ipc_send_cfg
 ****************************************************************************/

void nrf53_ipc_send_cfg(int id)
{
  DEBUGASSERT(id < NRF53_IPC_CHANS);

  ipcinfo("IPC send cfg %d\n", id);

  /* Enable send event on a single IPC channel */

  putreg32(IPC_CHAN_ID(id), NRF53_IPC_SEND_CNF(id));
}

/****************************************************************************
 * Name: nrf53_ipc_init
 ****************************************************************************/

void nrf53_ipc_init(void)
{
  struct nrf53_ipc_s *dev = &g_nrf53_ipc;

  /* Reset device */

  memset(dev, 0, sizeof(struct nrf53_ipc_s));

  /* Attach and enable the IRQ */

  irq_attach(NRF53_IRQ_IPC, nrf53_ipc_interrupt, dev);

  up_enable_irq(NRF53_IRQ_IPC);
}