Skip to content
Permalink
Browse files

sample: mhu: IPM MHU dual core on V2M Musca

Sample walk through:
    1. CPU 0 will wake up CPU 1 after initialization
    2. CPU 1 will send to CPU 0 an interrupt over MHU0
    3. CPU 0 return the same to CPU 1 when received MHU0 interrupt
    4. Test done when CPU 1 received MHU0 interrupt

The wake up second core and private core ID are soc specific.

Signed-off-by: Karl Zhang <karl.zhang@linaro.org>
  • Loading branch information...
karl-zh authored and galak committed Jan 27, 2019
1 parent 2a7824a commit d75f3cede86d47c7f1a9cf021fb6c62a8c4b41bf
@@ -0,0 +1,12 @@
#
# Copyright (c) 2019 Linaro Limited
#
# SPDX-License-Identifier: Apache-2.0
#

cmake_minimum_required(VERSION 3.13.1)

include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(ipm_mhu_dual_core)

target_sources(app PRIVATE src/main.c)
@@ -0,0 +1,63 @@
.. _ipm_mhu_dual_core:

MHU Dual Core
#############

Overview
********
An MHU (Message Handling Unit) enables software to raise interrupts to
the processor cores. This sample is a simple dual-core example for a
Musca A1 board that has two MHU units. This sample only test MHU0, the
steps are:

1. CPU 0 will wake up CPU 1 after initialization
2. CPU 1 will send to CPU 0 an interrupt over MHU0
3. CPU 0 return the same to CPU 1 when received MHU0 interrupt
4. Test done when CPU 1 received MHU0 interrupt

Building and Running
********************

This project outputs 'IPM MHU sample on musca_a' to the console.
It can be built and executed on Musca A1 CPU 0 as follows:

.. zephyr-app-commands::
:zephyr-app: samples/subsys/ipc/ipm_mhu_dual_core
:board: v2m_musca
:goals: run
:compact:

This project outputs 'IPM MHU sample on v2m_musca_nonsecure' to the console.
It can be built and executed on Musca A1 CPU 1 as follows:

.. zephyr-app-commands::
:zephyr-app: samples/subsys/ipc/ipm_mhu_dual_core
:board: v2m_musca_nonsecure
:goals: run
:compact:

Open a serial terminal (minicom, putty, etc.) and connect the board with the
following settings:

- Speed: 115200
- Data: 8 bits
- Parity: None
- Stop bits: 1

Reset the board and the following message will appear on the corresponding
serial port.

Sample Output
=============

.. code-block:: console

***** Booting Zephyr OS zephyr-v1.13.0-3378-g3625524 *****
IPM MHU sample on musca_a
CPU 0, get MHU0 success!
***** Booting Zephyr OS zephyr-v1.13.0-3378-g3625524 *****
IPM MHU sample on musca_a_nonsecure
CPU 1, get MHU0 success!
MHU ISR on CPU 0
MHU ISR on CPU 1
MHU Test Done.
@@ -0,0 +1,2 @@
CONFIG_IPM=y
CONFIG_IPM_MHU=y
@@ -0,0 +1,8 @@
sample:
description: MHU dual core sample
application
name: ipm_mhu_dual_core
tests:
test:
tags: ipm
platform_whitelist: v2m_musca v2m_musca_nonsecure
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2019 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr.h>
#include <misc/printk.h>
#include <ipm.h>

enum cpu_id_t {
MHU_CPU0 = 0,
MHU_CPU1,
MHU_CPU_MAX,
};

struct device *mhu0;

static void main_cpu_0(void)
{
while (1) {
}
}

static void main_cpu_1(void)
{
const u32_t set_mhu = 1;

ipm_send(mhu0, 0, MHU_CPU0, &set_mhu, 1);

while (1) {
}
}

static void mhu_isr_callback(void *context, u32_t cpu_id,
volatile void *data)
{
const u32_t set_mhu = 1;

printk("MHU ISR on CPU %d\n", cpu_id);
if (cpu_id == MHU_CPU0) {
ipm_send(mhu0, 0, MHU_CPU1, &set_mhu, 1);
} else if (cpu_id == MHU_CPU1) {
printk("MHU Test Done.\n");
}
}

void main(void)
{
printk("IPM MHU sample on %s\n", CONFIG_BOARD);

mhu0 = device_get_binding(DT_ARM_MHU_0_LABEL);
if (!mhu0) {
printk("CPU %d, get MHU0 fail!\n",
sse_200_platform_get_cpu_id());
while (1) {
}
} else {
printk("CPU %d, get MHU0 success!\n",
sse_200_platform_get_cpu_id());
ipm_register_callback(mhu0, mhu_isr_callback, mhu0);
}

if (sse_200_platform_get_cpu_id() == MHU_CPU0) {
wakeup_cpu1();
main_cpu_0();
}

main_cpu_1();
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Linaro Limited
* Copyright (c) 2018-2019 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -8,6 +8,45 @@
#include <init.h>
#include <soc.h>

/* (Secure System Control) Base Address */
#define SSE_200_SYSTEM_CTRL_S_BASE (0x50021000UL)
#define SSE_200_SYSTEM_CTRL_INITSVTOR1 (SSE_200_SYSTEM_CTRL_S_BASE + 0x114)
#define SSE_200_SYSTEM_CTRL_CPU_WAIT (SSE_200_SYSTEM_CTRL_S_BASE + 0x118)
#define SSE_200_CPU_ID_UNIT_BASE (0x5001F000UL)

#define NON_SECURE_FLASH_ADDRESS (192 * 1024)
#define NON_SECURE_IMAGE_HEADER (0x400)
#define NON_SECURE_FLASH_OFFSET (0x10000000)

/**
* @brief Wake up CPU 1 from another CPU, this is plaform specific.
*
*/
void wakeup_cpu1(void)
{
/* Set the Initial Secure Reset Vector Register for CPU 1 */
*(u32_t *)(SSE_200_SYSTEM_CTRL_INITSVTOR1) =
CONFIG_FLASH_BASE_ADDRESS +
NON_SECURE_FLASH_ADDRESS +
NON_SECURE_IMAGE_HEADER -
NON_SECURE_FLASH_OFFSET;

/* Set the CPU Boot wait control after reset */
*(u32_t *)(SSE_200_SYSTEM_CTRL_CPU_WAIT) = 0;
}

/**
* @brief Get the current CPU ID, this is plaform specific.
*
* @return Current CPU ID
*/
u32_t sse_200_platform_get_cpu_id(void)
{
volatile u32_t *p_cpu_id = (volatile u32_t *)SSE_200_CPU_ID_UNIT_BASE;

return (u32_t)*p_cpu_id;
}

/**
* @brief Perform basic hardware initialization at boot.
*
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Linaro Limited
* Copyright (c) 2018-2019 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,4 +13,8 @@
#include <misc/util.h>
#endif

extern void wakeup_cpu1(void);

extern u32_t sse_200_platform_get_cpu_id(void);

#endif /* _SOC_H_ */

0 comments on commit d75f3ce

Please sign in to comment.
You can’t perform that action at this time.