From 52c2f806258db213b5d2328e4051a8bc83084c20 Mon Sep 17 00:00:00 2001 From: Bumsik Kim Date: Thu, 24 Oct 2019 12:00:28 +0900 Subject: [PATCH 1/7] [VirtIO] Copy files from example project --- cores/arduino/stm32/OpenAMP/mbox_ipcc.c | 211 ++++++++++++++++++ cores/arduino/stm32/OpenAMP/mbox_ipcc.h | 50 +++++ cores/arduino/stm32/OpenAMP/openamp.c | 176 +++++++++++++++ cores/arduino/stm32/OpenAMP/openamp.h | 63 ++++++ cores/arduino/stm32/OpenAMP/openamp_conf.h | 243 +++++++++++++++++++++ cores/arduino/stm32/OpenAMP/openamp_log.c | 104 +++++++++ cores/arduino/stm32/OpenAMP/openamp_log.h | 138 ++++++++++++ cores/arduino/stm32/OpenAMP/rsc_table.c | 176 +++++++++++++++ cores/arduino/stm32/OpenAMP/rsc_table.h | 48 ++++ 9 files changed, 1209 insertions(+) create mode 100644 cores/arduino/stm32/OpenAMP/mbox_ipcc.c create mode 100644 cores/arduino/stm32/OpenAMP/mbox_ipcc.h create mode 100644 cores/arduino/stm32/OpenAMP/openamp.c create mode 100644 cores/arduino/stm32/OpenAMP/openamp.h create mode 100644 cores/arduino/stm32/OpenAMP/openamp_conf.h create mode 100644 cores/arduino/stm32/OpenAMP/openamp_log.c create mode 100644 cores/arduino/stm32/OpenAMP/openamp_log.h create mode 100644 cores/arduino/stm32/OpenAMP/rsc_table.c create mode 100644 cores/arduino/stm32/OpenAMP/rsc_table.h diff --git a/cores/arduino/stm32/OpenAMP/mbox_ipcc.c b/cores/arduino/stm32/OpenAMP/mbox_ipcc.c new file mode 100644 index 0000000000..dc0facc41d --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/mbox_ipcc.c @@ -0,0 +1,211 @@ +/** + ****************************************************************************** + * @file mbox_ipcc.c + * @author MCD Application Team + * @brief This file provides code for the configuration + * of the mailbox_ipcc_if.c MiddleWare. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +#ifdef VIRTIOCON + +/* + * Channel direction and usage: + * virtio_rpmsg_bus.c rpmsg_virtio.c + * ======== <-- new msg ---=============--------<------ ======= + * || || rvq (rx) || CHANNEL 1 || svq (tx_vq) || || + * || A7 || ------->-------=============--- buf free--> || M4 || + * || || || || + * ||master|| <-- buf free---=============--------<------ ||slave|| + * || || svq (tx) || CHANNEL 2 || rvq (rx_vq) || || + * ======== ------->-------=============----new msg --> ======= + */ + +/* Includes ------------------------------------------------------------------*/ +#include "openamp/open_amp.h" +#include "stm32_def.h" +#include "openamp_conf.h" + +/* Within 'USER CODE' section, code will be kept by default at each generation */ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* Private define ------------------------------------------------------------*/ +#define MASTER_CPU_ID 0 +#define REMOTE_CPU_ID 1 +#define IPCC_CPU_A7 MASTER_CPU_ID +#define IPCC_CPU_M4 REMOTE_CPU_ID + +#define RX_NO_MSG 0 +#define RX_NEW_MSG 1 +#define RX_BUF_FREE 2 + +/* Private variables ---------------------------------------------------------*/ +extern IPCC_HandleTypeDef hipcc; +int msg_received_ch1 = RX_NO_MSG; +int msg_received_ch2 = RX_NO_MSG; +uint32_t vring0_id = 0; /* used for channel 1 */ +uint32_t vring1_id = 1; /* used for channel 2 */ + + + + +IPCC_HandleTypeDef hipcc; + + + + +/* Private function prototypes -----------------------------------------------*/ +void IPCC_channel1_callback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir); +void IPCC_channel2_callback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir); + + +/** + * @brief Initialize MAILBOX with IPCC peripheral + * @param None + * @retval : Operation result + */ +int MAILBOX_Init(void) +{ + __HAL_RCC_IPCC_CLK_ENABLE(); + HAL_NVIC_SetPriority(IPCC_RX1_IRQn, IPCC_IRQ_PRIO, IPCC_IRQ_SUBPRIO); + HAL_NVIC_EnableIRQ(IPCC_RX1_IRQn); + hipcc.Instance = IPCC; + if (HAL_IPCC_Init(&hipcc) != HAL_OK) { + Error_Handler(); + } + + if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_1, IPCC_CHANNEL_DIR_RX, + IPCC_channel1_callback) != HAL_OK) { + Error_Handler(); + return -1; + } + + if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_2, IPCC_CHANNEL_DIR_RX, + IPCC_channel2_callback) != HAL_OK) { + Error_Handler(); + return -1; + } + + return 0; +} + +/** + * @brief Initialize MAILBOX with IPCC peripheral + * @param virtio device + * @retval : Operation result + */ +int MAILBOX_Poll(struct virtio_device *vdev) +{ + /* If we got an interrupt, ask for the corresponding virtqueue processing */ + + if (msg_received_ch1 == RX_BUF_FREE) { + OPENAMP_log_dbg("Running virt0 (ch_1 buf free)\r\n"); + rproc_virtio_notified(vdev, VRING0_ID); + msg_received_ch1 = RX_NO_MSG; + return 0; + } + + if (msg_received_ch2 == RX_NEW_MSG) { + OPENAMP_log_dbg("Running virt1 (ch_2 new msg)\r\n"); + rproc_virtio_notified(vdev, VRING1_ID); + msg_received_ch2 = RX_NO_MSG; + + /* The OpenAMP framework does not notify for free buf: do it here */ + rproc_virtio_notified(NULL, VRING1_ID); + return 0; + } + + return -1; +} + + +/** + * @brief Callback function called by OpenAMP MW to notify message processing + * @param VRING id + * @retval Operation result + */ +int MAILBOX_Notify(void *priv, uint32_t id) +{ + uint32_t channel; + (void)priv; + + /* Called after virtqueue processing: time to inform the remote */ + if (id == VRING0_ID) { + channel = IPCC_CHANNEL_1; + } else if (id == VRING1_ID) { + /* Note: the OpenAMP framework never notifies this */ + channel = IPCC_CHANNEL_2; + return -1; + } else { + return -1; + } + + /* Check that the channel is free (otherwise wait until it is) */ + if (HAL_IPCC_GetChannelStatus(&hipcc, channel, IPCC_CHANNEL_DIR_TX) == IPCC_CHANNEL_STATUS_OCCUPIED) { + // Wait for channel to be freed + while (HAL_IPCC_GetChannelStatus(&hipcc, channel, IPCC_CHANNEL_DIR_TX) == IPCC_CHANNEL_STATUS_OCCUPIED) + ; + } + + /* Inform A7 (either new message, or buf free) */ + HAL_IPCC_NotifyCPU(&hipcc, channel, IPCC_CHANNEL_DIR_TX); + return 0; +} + +/* Private function ---------------------------------------------------------*/ +/* Callback from IPCC Interrupt Handler: Master Processor informs that there are some free buffers */ +void IPCC_channel1_callback(IPCC_HandleTypeDef *hipcc, + uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir) +{ + if (msg_received_ch1 != RX_NO_MSG) { + OPENAMP_log_dbg("IPCC_channel1_callback: previous IRQ not treated (status = %d)\r\n", msg_received_ch1); + } + + msg_received_ch1 = RX_BUF_FREE; + + /* Inform A7 that we have received the 'buff free' msg */ + HAL_IPCC_NotifyCPU(hipcc, ChannelIndex, IPCC_CHANNEL_DIR_RX); +} + +/* Callback from IPCC Interrupt Handler: new message received from Master Processor */ +void IPCC_channel2_callback(IPCC_HandleTypeDef *hipcc, + uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir) +{ + if (msg_received_ch2 != RX_NO_MSG) { + OPENAMP_log_dbg("IPCC_channel2_callback: previous IRQ not treated (status = %d)\r\n", msg_received_ch2); + } + + msg_received_ch2 = RX_NEW_MSG; + + /* Inform A7 that we have received the new msg */ + OPENAMP_log_dbg("Ack new message on ch2\r\n"); + HAL_IPCC_NotifyCPU(hipcc, ChannelIndex, IPCC_CHANNEL_DIR_RX); +} + +/** + * @brief This function handles IPCC RX1 occupied interrupt. + */ +void IPCC_RX1_IRQHandler(void) +{ + /* USER CODE BEGIN IPCC_RX1_IRQn 0 */ + /* USER CODE END IPCC_RX1_IRQn 0 */ + HAL_IPCC_RX_IRQHandler(&hipcc); + /* USER CODE BEGIN IPCC_RX1_IRQn 1 */ + + /* USER CODE END IPCC_RX1_IRQn 1 */ +} + +#endif /* VIRTIOCON */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/OpenAMP/mbox_ipcc.h b/cores/arduino/stm32/OpenAMP/mbox_ipcc.h new file mode 100644 index 0000000000..be338872b2 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/mbox_ipcc.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * @file mbox_ipcc.h + * @author MCD Application Team + * @brief Header for mbox_ipcc.c module + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +#ifndef MBOX_IPCC_H_ +#define MBOX_IPCC_H_ + +#ifdef VIRTIOCON + +/* Interrupt priority */ +#ifndef IPCC_IRQ_PRIO +#define IPCC_IRQ_PRIO 1 +#endif +#ifndef IPCC_IRQ_SUBPRIO +#define IPCC_IRQ_SUBPRIO 0 +#endif + +/* USER CODE BEGIN firstSection */ +/* can be used to modify / undefine following code or add new definitions */ +/* USER CODE END firstSection */ + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +int MAILBOX_Init(void); +int MAILBOX_Notify(void *priv, uint32_t id); +int MAILBOX_Poll(struct virtio_device *vdev); + +/* USER CODE BEGIN lastSection */ +/* can be used to modify / undefine previous code or add new definitions */ +/* USER CODE END lastSection */ + +#endif /* VIRTIOCON */ +#endif /* MBOX_IPCC_H_ */ diff --git a/cores/arduino/stm32/OpenAMP/openamp.c b/cores/arduino/stm32/OpenAMP/openamp.c new file mode 100644 index 0000000000..65291dcdb8 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/openamp.c @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file openamp.c + * @author MCD Application Team + * @brief Code for openamp applications + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +#ifdef VIRTIOCON + +#include "openamp/open_amp.h" +#include "openamp.h" +#include "rsc_table.h" +#include "metal/sys.h" +#include "metal/device.h" +/* Private define ------------------------------------------------------------*/ + +#define SHM_DEVICE_NAME "STM32_SHM" + +/* Globals */ + +static struct metal_io_region *shm_io; +static struct metal_io_region *rsc_io; +static struct shared_resource_table *rsc_table; +static struct rpmsg_virtio_shm_pool shpool; +static struct rpmsg_virtio_device rvdev; + + +static metal_phys_addr_t shm_physmap; + +struct metal_device shm_device = { + .name = SHM_DEVICE_NAME, + .num_regions = 2, + .regions = { + {.virt = NULL}, /* shared memory */ + {.virt = NULL}, /* rsc_table memory */ + }, + .node = { NULL }, + .irq_num = 0, + .irq_info = NULL +}; + +static int OPENAMP_shmem_init(int RPMsgRole) +{ + int status = 0; + struct metal_device *device; + struct metal_init_params metal_params = METAL_INIT_DEFAULTS; + void *rsc_tab_addr; + int rsc_size; + + metal_init(&metal_params); + + status = metal_register_generic_device(&shm_device); + if (status != 0) { + return status; + } + + status = metal_device_open("generic", SHM_DEVICE_NAME, &device); + if (status != 0) { + return status; + } + + shm_physmap = SHM_START_ADDRESS; + metal_io_init(&device->regions[0], (void *)SHM_START_ADDRESS, &shm_physmap, + SHM_SIZE, -1, 0, NULL); + + shm_io = metal_device_io_region(device, 0); + if (shm_io == NULL) { + return -1; + } + + /* Initialize resources table variables */ + resource_table_init(RPMsgRole, &rsc_tab_addr, &rsc_size); + rsc_table = (struct shared_resource_table *)rsc_tab_addr; + if (!rsc_table) { + return -1; + } + + metal_io_init(&device->regions[1], rsc_table, + (metal_phys_addr_t *)rsc_table, rsc_size, -1U, 0, NULL); + + rsc_io = metal_device_io_region(device, 1); + if (rsc_io == NULL) { + return -1; + } + + return 0; +} + +int OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb) +{ + struct fw_rsc_vdev_vring *vring_rsc; + struct virtio_device *vdev; + int status = 0; + + MAILBOX_Init(); + + /* Libmetal Initilalization */ + status = OPENAMP_shmem_init(RPMsgRole); + if (status) { + return status; + } + + vdev = rproc_virtio_create_vdev(RPMsgRole, VDEV_ID, &rsc_table->vdev, + rsc_io, NULL, MAILBOX_Notify, NULL); + if (vdev == NULL) { + return -1; + } + + rproc_virtio_wait_remote_ready(vdev); + vring_rsc = &rsc_table->vring0; + status = rproc_virtio_init_vring(vdev, 0, vring_rsc->notifyid, + (void *)vring_rsc->da, shm_io, + vring_rsc->num, vring_rsc->align); + if (status != 0) { + return status; + } + vring_rsc = &rsc_table->vring1; + status = rproc_virtio_init_vring(vdev, 1, vring_rsc->notifyid, + (void *)vring_rsc->da, shm_io, + vring_rsc->num, vring_rsc->align); + if (status != 0) { + return status; + } + + rpmsg_virtio_init_shm_pool(&shpool, (void *)VRING_BUFF_ADDRESS, + (size_t)SHM_SIZE); + rpmsg_init_vdev(&rvdev, vdev, ns_bind_cb, shm_io, &shpool); + + return 0; +} + +void OPENAMP_DeInit() +{ + rpmsg_deinit_vdev(&rvdev); + + metal_finish(); +} + +void OPENAMP_init_ept(struct rpmsg_endpoint *ept) +{ + rpmsg_init_ept(ept, "", RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, NULL, NULL); +} + +int OPENAMP_create_endpoint(struct rpmsg_endpoint *ept, const char *name, + uint32_t dest, rpmsg_ept_cb cb, + rpmsg_ns_unbind_cb unbind_cb) +{ + return rpmsg_create_ept(ept, &rvdev.rdev, name, RPMSG_ADDR_ANY, dest, cb, + unbind_cb); +} + +void OPENAMP_check_for_message(void) +{ + MAILBOX_Poll(rvdev.vdev); +} + +void OPENAMP_Wait_EndPointready(struct rpmsg_endpoint *rp_ept) +{ + while (!is_rpmsg_ept_ready(rp_ept)) { + MAILBOX_Poll(rvdev.vdev); + } +} + +#endif /* VIRTIOCON */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/OpenAMP/openamp.h b/cores/arduino/stm32/OpenAMP/openamp.h new file mode 100644 index 0000000000..8d8ee0f604 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/openamp.h @@ -0,0 +1,63 @@ +/** + ****************************************************************************** + * @file openamp.h + * @brief Header for openamp applications + * @author MCD Application Team + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __openamp_H +#define __openamp_H + +#ifdef VIRTIOCON + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "openamp_conf.h" + + +#define OPENAMP_send rpmsg_send +#define OPENAMP_destroy_ept rpmsg_destroy_ept + +/* Initialize the openamp framework*/ +int OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb); + +/* Deinitialize the openamp framework*/ +void OPENAMP_DeInit(void); + +/* Initialize the endpoint struct*/ +void OPENAMP_init_ept(struct rpmsg_endpoint *ept); + +/* Create and register the endpoint */ +int OPENAMP_create_endpoint(struct rpmsg_endpoint *ept, const char *name, + uint32_t dest, rpmsg_ept_cb cb, + rpmsg_ns_unbind_cb unbind_cb); + +/* Check for new rpmsg reception */ +void OPENAMP_check_for_message(void); + +/* Wait loop on endpoint ready ( message dest address is know)*/ +void OPENAMP_Wait_EndPointready(struct rpmsg_endpoint *rp_ept); + +#ifdef __cplusplus +} +#endif +#endif /* VIRTIOCON */ +#endif /*__openamp_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/OpenAMP/openamp_conf.h b/cores/arduino/stm32/OpenAMP/openamp_conf.h new file mode 100644 index 0000000000..7e9c64fe78 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/openamp_conf.h @@ -0,0 +1,243 @@ +/** + ****************************************************************************** + * @file openamp_conf.h + * @author MCD Application Team + * @brief Configuration file for OpenAMP MW + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __OPENAMP_CONF__H__ +#define __OPENAMP_CONF__H__ + +#ifdef VIRTIOCON + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_) +#include "openamp_log.h" +#endif + +/* ########################## Mailbox Interface Selection ############################## */ +/** + * @brief This is the list of Mailbox interface to be used in the OpenAMP MW + * Please note that not all interfaces are supported by a STM32 device + */ +#define MAILBOX_IPCC_IF_ENABLED +//#define MAILBOX_HSEM_IF_ENABLED + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include Maibox interface header file + */ + +#ifdef MAILBOX_IPCC_IF_ENABLED +#include "mbox_ipcc.h" +#endif /* MAILBOX_IPCC_IF_ENABLED */ + +#ifdef MAILBOX_HSEM_IF_ENABLED +#include "mbox_hsem.h" +#endif /* MAILBOX_HSEM_IF_ENABLED */ + +/* ########################## Virtual Diver Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the OpenAMP Virtual driver module + * Please note that virtual driver are not supported on all stm32 families + */ +#define VIRTUAL_UART_MODULE_ENABLED +//#define VIRTUAL_I2C_MODULE_ENABLED + + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include Virtual Driver module's header file + */ + +#ifdef VIRTUAL_UART_MODULE_ENABLED +#include "virt_uart.h" +#endif /* VIRTUAL_UART_MODULE_ENABLED */ + +#ifdef VIRTUAL_I2C_MODULE_ENABLED +#include "virt_i2c.h" +#endif /* VIRTUAL_I2C_MODULE_ENABLED */ + + + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup OPENAMP_MW + * @{ + */ + +/** @defgroup OPENAMP_CONF OPENAMP_CONF + * @brief Configuration file for Openamp mw + * @{ + */ + +/** @defgroup OPENAMP_CONF_Exported_Variables OPENAMP_CONF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** + * @} + */ + +/** @defgroup OPENAMP_CONF_Exported_Defines OPENAMP_CONF_Exported_Defines + * @brief Defines for configuration of the Openamp mw + * @{ + */ + + +#if defined (__ICCARM__) +/* + * For IAR, the .icf file should contain the following lines: + * define symbol __OPENAMP_region_start__ = BASE_ADDRESS; (0x38000400 for example) + * define symbol __OPENAMP_region_size__ = MEM_SIZE; (0xB000 as example) + * + * export symbol __OPENAMP_region_start__; + * export symbol __OPENAMP_region_size__; + */ +extern const uint32_t __OPENAMP_region_start__; +extern const uint8_t __OPENAMP_region_size__; +#define SHM_START_ADDRESS ((metal_phys_addr_t)&__OPENAMP_region_start__) +#define SHM_SIZE ((size_t)&__OPENAMP_region_size__) + +#elif defined(__CC_ARM) +/* + * For MDK-ARM, the scatter file .sct should contain the following line: + * LR_IROM1 .... { + * ... + * __OpenAMP_SHMEM__ 0x38000400 EMPTY 0x0000B000 {} ; Shared Memory area used by OpenAMP + * } + * + */ +extern unsigned int Image$$__OpenAMP_SHMEM__$$Base; +extern unsigned int Image$$__OpenAMP_SHMEM__$$ZI$$Length; +#define SHM_START_ADDRESS (unsigned int)&Image$$__OpenAMP_SHMEM__$$Base +#define SHM_SIZE ((size_t)&Image$$__OpenAMP_SHMEM__$$ZI$$Length) + +#else +/* + * for GCC add the following content to the .ld file: + * MEMORY + * { + * ... + * OPEN_AMP_SHMEM (xrw) : ORIGIN = 0x38000400, LENGTH = 63K + * } + * __OPENAMP_region_start__ = ORIGIN(OPEN_AMP_SHMEM); + * __OPENAMP_region_end__ = ORIGIN(OPEN_AMP_SHMEM) + LENGTH(OPEN_AMP_SHMEM); + * + * using the LENGTH(OPEN_AMP_SHMEM) to set the SHM_SIZE lead to a crash thus we + * use the start and end address. + */ + +extern int __OPENAMP_region_start__[]; /* defined by linker script */ +extern int __OPENAMP_region_end__[]; /* defined by linker script */ + +#define SHM_START_ADDRESS ((metal_phys_addr_t)__OPENAMP_region_start__) +#define SHM_SIZE (size_t)((void *)__OPENAMP_region_end__ - (void *) __OPENAMP_region_start__) + +#endif + +#if defined STM32MP1xx +#define VRING_RX_ADDRESS -1 /* allocated by Master processor: CA7 */ +#define VRING_TX_ADDRESS -1 /* allocated by Master processor: CA7 */ +#define VRING_BUFF_ADDRESS -1 /* allocated by Master processor: CA7 */ +#define VRING_ALIGNMENT 16 /* fixed to match with linux constraint */ +#define VRING_NUM_BUFFS 16 /* number of rpmsg buffer */ +#else +#define VRING_RX_ADDRESS SHM_START_ADDRESS +#define VRING_TX_ADDRESS (SHM_START_ADDRESS + 0x400) +#define VRING_BUFF_ADDRESS (SHM_START_ADDRESS + 0x800) +#define VRING_ALIGNMENT 4 +#define VRING_NUM_BUFFS 4 /* number of rpmsg buffers */ +#endif + +/* Fixed parameter */ +#define NUM_RESOURCE_ENTRIES 2 +#define VRING_COUNT 2 + +#define VDEV_ID 0xFF +#define VRING0_ID 0 /* VRING0 ID (master to remote) fixed to 0 for linux compatibility*/ +#define VRING1_ID 1 /* VRING1 ID (remote to master) fixed to 1 for linux compatibility */ + +/** + * @} + */ + +/** @defgroup OPENAMP_CONF_Exported_Macros OPENAMP_CONF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* DEBUG macros */ + +#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_) +#define OPENAMP_log_dbg log_dbg +#define OPENAMP_log_info log_info +#define OPENAMP_log_warn log_warn +#define OPENAMP_log_err log_err +#else +#define OPENAMP_log_dbg(...) +#define OPENAMP_log_info(...) +#define OPENAMP_log_warn(...) +#define OPENAMP_log_err(...) +#endif + +/** + * @} + */ + +/** @defgroup OPENAMP_CONF_Exported_Types OPENAMP_CONF_Exported_Types + * @brief Types. + * @{ + */ + +/** + * @} + */ + +/** @defgroup OPENAMP_CONF_Exported_FunctionsPrototype OPENAMP_CONF_Exported_FunctionsPrototype + * @brief Declaration of public functions for OpenAMP mw. + * @{ + */ + +/* Exported functions -------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* VIRTIOCON */ +#endif /* __OPENAMP_CONF__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/OpenAMP/openamp_log.c b/cores/arduino/stm32/OpenAMP/openamp_log.c new file mode 100644 index 0000000000..e2368c2242 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/openamp_log.c @@ -0,0 +1,104 @@ +/** + ****************************************************************************** + * @file log.c + * @author MCD Application Team + * @brief Ressource table + * + * This file provides services for logging + * + ****************************************************************************** + * + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + * + ****************************************************************************** + */ +#ifdef VIRTIOCON +/** @addtogroup LOG + * @{ + */ + +/** @addtogroup STM32MP1xx_log + * @{ + */ + +/** @addtogroup STM32MP1xx_Log_Private_Includes + * @{ + */ +#include "openamp_log.h" +/** + * @} + */ + +/** @addtogroup STM32MP1xx_Log_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32MP1xx_Log_Private_Defines + * @{ + */ + +/** + * @} + */ + +#if defined (__LOG_TRACE_IO_) +char system_log_buf[SYSTEM_TRACE_BUF_SZ]; + +__weak void log_buff(int ch) +{ + /* Place your implementation of fputc here */ + /* e.g. write a character to the USART1 and Loop until the end of transmission */ + static int offset = 0; + + if (offset + 1 >= SYSTEM_TRACE_BUF_SZ) { + offset = 0; + } + + system_log_buf[offset] = ch; + system_log_buf[offset++ + 1] = '\0'; +} + +#endif + +#if defined ( __CC_ARM) || (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) +#define PUTCHAR_PROTOTYPE int stdout_putchar(int ch) +#elif __GNUC__ +/* With GCC/RAISONANCE, small log_info (option LD Linker->Libraries->Small log_info + set to 'Yes') calls __io_putchar() */ +#define PUTCHAR_PROTOTYPE int __attribute__(( weak )) __io_putchar(int ch) +#else +#define PUTCHAR_PROTOTYPE int __attribute__(( weak )) fputc(int ch, FILE *f) +#endif /* __GNUC__ */ + +#if defined (__LOG_UART_IO_) || defined (__LOG_TRACE_IO_) +PUTCHAR_PROTOTYPE { + /* Place your implementation of fputc here */ + /* e.g. write a character to the USART1 and Loop until the end of transmission */ +#if defined (__LOG_UART_IO_) + extern UART_HandleTypeDef huart; + HAL_UART_Transmit(&huart, (uint8_t *)&ch, 1, HAL_MAX_DELAY); +#endif +#if defined (__LOG_TRACE_IO_) + log_buff(ch); +#endif + return ch; +} +#else +/* No printf output */ +#endif + +#endif /* VIRTIOCON */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file diff --git a/cores/arduino/stm32/OpenAMP/openamp_log.h b/cores/arduino/stm32/OpenAMP/openamp_log.h new file mode 100644 index 0000000000..06475dcd47 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/openamp_log.h @@ -0,0 +1,138 @@ +/** + ****************************************************************************** + * @file log.h + * @author MCD Application Team + * @brief logging services + ****************************************************************************** + * + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + * + ****************************************************************************** + */ + +/** @addtogroup LOG + * @{ + */ + +/** @addtogroup stm32mp1xx_Log + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#ifndef __LOG_STM32MP1XX_H +#define __LOG_STM32MP1XX_H + +#ifdef VIRTIOCON + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup STM32MP1xx_Log_Includes + * @{ + */ +#include "stm32_def.h" +/** + * @} + */ + +/** @addtogroup STM32MP1xx_Log_Exported_Constants + * @{ + */ +#if defined (__LOG_TRACE_IO_) +#define SYSTEM_TRACE_BUF_SZ 2048 +#endif + +#define LOGQUIET 0 +#define LOGERR 1 +#define LOGWARN 2 +#define LOGINFO 3 +#define LOGDBG 4 + +#ifndef LOGLEVEL +#define LOGLEVEL LOGINFO +#endif + + +/** + * @} + */ + +/** @addtogroup STM32MP1xx_Log_Exported_types + * @{ + */ +#if defined (__LOG_TRACE_IO_) +extern char system_log_buf[SYSTEM_TRACE_BUF_SZ]; /*!< buffer for debug traces */ +#endif /* __LOG_TRACE_IO_ */ +/** + * @} + */ + +/** @addtogroup STM32MP1xx_Log_Exported_Macros + * @{ + */ +#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_) +#if LOGLEVEL >= LOGDBG +#define log_dbg(fmt, ...) printf("[%05ld.%03ld][DBG ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__) +#else +#define log_dbg(fmt, ...) +#endif +#if LOGLEVEL >= LOGINFO +#define log_info(fmt, ...) printf("[%05ld.%03ld][INFO ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__) +#else +#define log_info(fmt, ...) +#endif +#if LOGLEVEL >= LOGWARN +#define log_warn(fmt, ...) printf("[%05ld.%03ld][WARN ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__) +#else +#define log_warn(fmt, ...) +#endif +#if LOGLEVEL >= LOGERR +#define log_err(fmt, ...) printf("[%05ld.%03ld][ERR ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__) +#else +#define log_err(fmt, ...) +#endif +#else +#define log_dbg(fmt, ...) +#define log_info(fmt, ...) +#define log_warn(fmt, ...) +#define log_err(fmt, ...) +#endif /* __LOG_TRACE_IO_ */ +/** + * @} + */ + +/** @addtogroup STM32MP1xx_Log_Exported_Functions + * @{ + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* VIRTIOCON */ +#endif /*__LOG_STM32MP1XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/OpenAMP/rsc_table.c b/cores/arduino/stm32/OpenAMP/rsc_table.c new file mode 100644 index 0000000000..1d5ec3da29 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/rsc_table.c @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file rsc_table.c + * @author MCD Application Team + * @brief Ressource table + * + * This file provides a default resource table requested by remote proc to + * load the elf file. It also allows to add debug trace using a shared buffer. + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +#ifdef VIRTIOCON +/** @addtogroup RSC_TABLE + * @{ + */ + +/** @addtogroup resource_table + * @{ + */ + +/** @addtogroup resource_table_Private_Includes + * @{ + */ + +#if defined(__ICCARM__) || defined (__CC_ARM) +#include /* needed for offsetof definition*/ +#endif +#include "rsc_table.h" +#include "openamp/open_amp.h" + +/** + * @} + */ + +/** @addtogroup resource_table_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup resource_table_Private_Defines + * @{ + */ + +/* Place resource table in special ELF section */ +#if defined(__GNUC__) +#define __section_t(S) __attribute__((__section__(#S))) +#define __resource __section_t(.resource_table) +#endif + +#if defined (STM32MP1xx) +#ifdef VIRTIO_MASTER_ONLY +#define CONST +#else +#define CONST const +#endif +#else +#define CONST +#endif + +#define RPMSG_IPU_C0_FEATURES 1 +#define VRING_COUNT 2 + +/* VirtIO rpmsg device id */ +#define VIRTIO_ID_RPMSG_ 7 + +#if defined (__LOG_TRACE_IO_) +extern char system_log_buf[]; +#endif + +#if defined(__GNUC__) +#if !defined (__CC_ARM) && !defined (STM32MP1xx) + +/* Since GCC is not initializing the resource_table at startup, it is declared as volatile to avoid compiler optimization + * for the CM4 (see resource_table_init() below) + */ +volatile struct shared_resource_table __resource __attribute__((used)) resource_table; +#else +CONST struct shared_resource_table __resource __attribute__((used)) resource_table = { +#endif +#elif defined(__ICCARM__) +__root CONST struct shared_resource_table resource_table @ ".resource_table" = { +#endif + +#if defined(__ICCARM__) || defined (__CC_ARM) || defined (STM32MP1xx) +.version = 1, +#if defined (__LOG_TRACE_IO_) +.num = 2, +#else +.num = 1, +#endif +.reserved = {0, 0}, +.offset = { + offsetof(struct shared_resource_table, vdev), + offsetof(struct shared_resource_table, cm_trace), +}, + +/* Virtio device entry */ +.vdev = { + RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, + VRING_COUNT, {0, 0}, +}, + +/* Vring rsc entry - part of vdev rsc entry */ +.vring0 = {VRING_TX_ADDRESS, VRING_ALIGNMENT, VRING_NUM_BUFFS, VRING0_ID, 0}, +.vring1 = {VRING_RX_ADDRESS, VRING_ALIGNMENT, VRING_NUM_BUFFS, VRING1_ID, 0}, + +#if defined (__LOG_TRACE_IO_) +.cm_trace = { + RSC_TRACE, + (uint32_t)system_log_buf, SYSTEM_TRACE_BUF_SZ, 0, "cm4_log", +}, +#endif +} ; +#endif + +void resource_table_init(int RPMsgRole, void **table_ptr, int *length) +{ + +#if !defined (STM32MP1xx) +#if defined (__GNUC__) && ! defined (__CC_ARM) +#ifdef VIRTIO_MASTER_ONLY + + /* + * Currently the GCC linker doesn't initialize the resource_table global variable at startup + * it is done here by the master application. + */ + memset(&resource_table, '\0', sizeof(struct shared_resource_table)); + resource_table.num = 1; + resource_table.version = 1; + resource_table.offset[0] = offsetof(struct shared_resource_table, vdev); + + resource_table.vring0.da = VRING_TX_ADDRESS; + resource_table.vring0.align = VRING_ALIGNMENT; + resource_table.vring0.num = VRING_NUM_BUFFS; + resource_table.vring0.notifyid = VRING0_ID; + + resource_table.vring1.da = VRING_RX_ADDRESS; + resource_table.vring1.align = VRING_ALIGNMENT; + resource_table.vring1.num = VRING_NUM_BUFFS; + resource_table.vring1.notifyid = VRING1_ID; + + + resource_table.vdev.type = RSC_VDEV; + resource_table.vdev.id = VIRTIO_ID_RPMSG_; + resource_table.vdev.num_of_vrings = VRING_COUNT; + resource_table.vdev.dfeatures = RPMSG_IPU_C0_FEATURES; +#else + + /* For the slave application let's wait until the resource_table is correctly initialized */ + while (resource_table.vring1.da != VRING_RX_ADDRESS) { + + } +#endif +#endif +#endif + + (void)RPMsgRole; + *length = sizeof(resource_table); + *table_ptr = (void *)&resource_table; +} + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/rsc_table.h b/cores/arduino/stm32/OpenAMP/rsc_table.h new file mode 100644 index 0000000000..ccb9260b9f --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/rsc_table.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 STMicroelectronics. + * All rights reserved. + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + */ + +/* This file populates resource table for BM remote + * for use by the Linux Master */ + +#ifndef RSC_TABLE_H_ +#define RSC_TABLE_H_ + +#ifdef VIRTIOCON + +#include "openamp/open_amp.h" +#include "openamp_conf.h" + +/* Place resource table in special ELF section */ +//#define __section_t(S) __attribute__((__section__(#S))) +//#define __resource __section_t(.resource_table) + + + + +/* Resource table for the given remote */ +struct shared_resource_table { + unsigned int version; + unsigned int num; + unsigned int reserved[2]; + unsigned int offset[NUM_RESOURCE_ENTRIES]; + /* text carveout entry */ + + /* rpmsg vdev entry */ + struct fw_rsc_vdev vdev; + struct fw_rsc_vdev_vring vring0; + struct fw_rsc_vdev_vring vring1; + struct fw_rsc_trace cm_trace; +}; + +void resource_table_init(int RPMsgRole, void **table_ptr, int *length); + +#endif /* VIRTIOCON */ +#endif /* RSC_TABLE_H_ */ From e27a95cdd755124a44d678acc0f17f57f6101208 Mon Sep 17 00:00:00 2001 From: Bumsik Kim Date: Thu, 24 Oct 2019 12:02:44 +0900 Subject: [PATCH 2/7] [VirtIO] Link OpenAMP middleware files to the core --- cores/arduino/stm32/OpenAMP/libmetal/device.c | 5 +++++ .../stm32/OpenAMP/libmetal/generic/condition.c | 5 +++++ .../stm32/OpenAMP/libmetal/generic/cortexm/sys.c | 5 +++++ .../stm32/OpenAMP/libmetal/generic/generic_device.c | 5 +++++ .../stm32/OpenAMP/libmetal/generic/generic_init.c | 5 +++++ .../stm32/OpenAMP/libmetal/generic/generic_io.c | 5 +++++ .../stm32/OpenAMP/libmetal/generic/generic_shmem.c | 5 +++++ cores/arduino/stm32/OpenAMP/libmetal/generic/time.c | 5 +++++ cores/arduino/stm32/OpenAMP/libmetal/init.c | 5 +++++ cores/arduino/stm32/OpenAMP/libmetal/io.c | 5 +++++ cores/arduino/stm32/OpenAMP/libmetal/log.c | 5 +++++ cores/arduino/stm32/OpenAMP/libmetal/shmem.c | 5 +++++ .../OpenAMP/open-amp/remoteproc/remoteproc_virtio.c | 5 +++++ cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c | 5 +++++ .../stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c | 5 +++++ cores/arduino/stm32/OpenAMP/virt_uart.c | 13 +++++++++++++ cores/arduino/stm32/OpenAMP/virtio/virtio.c | 5 +++++ cores/arduino/stm32/OpenAMP/virtio/virtqueue.c | 5 +++++ 18 files changed, 98 insertions(+) create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/device.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/generic/condition.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/generic/cortexm/sys.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/generic/generic_device.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/generic/generic_init.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/generic/generic_io.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/generic/generic_shmem.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/generic/time.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/init.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/io.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/log.c create mode 100644 cores/arduino/stm32/OpenAMP/libmetal/shmem.c create mode 100644 cores/arduino/stm32/OpenAMP/open-amp/remoteproc/remoteproc_virtio.c create mode 100644 cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c create mode 100644 cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c create mode 100644 cores/arduino/stm32/OpenAMP/virt_uart.c create mode 100644 cores/arduino/stm32/OpenAMP/virtio/virtio.c create mode 100644 cores/arduino/stm32/OpenAMP/virtio/virtqueue.c diff --git a/cores/arduino/stm32/OpenAMP/libmetal/device.c b/cores/arduino/stm32/OpenAMP/libmetal/device.c new file mode 100644 index 0000000000..ad62849d0f --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/device.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/device.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/generic/condition.c b/cores/arduino/stm32/OpenAMP/libmetal/generic/condition.c new file mode 100644 index 0000000000..a8f7a7427d --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/generic/condition.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/system/generic/condition.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/generic/cortexm/sys.c b/cores/arduino/stm32/OpenAMP/libmetal/generic/cortexm/sys.c new file mode 100644 index 0000000000..83f98dd29f --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/generic/cortexm/sys.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/system/generic/cortexm/sys.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_device.c b/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_device.c new file mode 100644 index 0000000000..85a97eef94 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_device.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/system/generic/generic_device.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_init.c b/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_init.c new file mode 100644 index 0000000000..abdbe5cf12 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_init.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/system/generic/generic_init.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_io.c b/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_io.c new file mode 100644 index 0000000000..d1fcb36feb --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_io.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/system/generic/generic_io.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_shmem.c b/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_shmem.c new file mode 100644 index 0000000000..75be24b343 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/generic/generic_shmem.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/system/generic/generic_shmem.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/generic/time.c b/cores/arduino/stm32/OpenAMP/libmetal/generic/time.c new file mode 100644 index 0000000000..917e7b88bc --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/generic/time.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/system/generic/time.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/init.c b/cores/arduino/stm32/OpenAMP/libmetal/init.c new file mode 100644 index 0000000000..e7ddd67304 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/init.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/init.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/io.c b/cores/arduino/stm32/OpenAMP/libmetal/io.c new file mode 100644 index 0000000000..902aca060e --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/io.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/io.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/log.c b/cores/arduino/stm32/OpenAMP/libmetal/log.c new file mode 100644 index 0000000000..03eff42dc6 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/log.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/log.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/libmetal/shmem.c b/cores/arduino/stm32/OpenAMP/libmetal/shmem.c new file mode 100644 index 0000000000..83b2e508a1 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/libmetal/shmem.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "libmetal/lib/shmem.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/open-amp/remoteproc/remoteproc_virtio.c b/cores/arduino/stm32/OpenAMP/open-amp/remoteproc/remoteproc_virtio.c new file mode 100644 index 0000000000..af4d8a2341 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/open-amp/remoteproc/remoteproc_virtio.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "open-amp/lib/remoteproc/remoteproc_virtio.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c b/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c new file mode 100644 index 0000000000..bf650fffdc --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "open-amp/lib/rpmsg/rpmsg.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c b/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c new file mode 100644 index 0000000000..086354d102 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "open-amp/lib/rpmsg/rpmsg_virtio.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/virt_uart.c b/cores/arduino/stm32/OpenAMP/virt_uart.c new file mode 100644 index 0000000000..d6b918ed79 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/virt_uart.c @@ -0,0 +1,13 @@ +#ifdef VIRTIOCON + + +// #include "openamp/open_amp.h" + +/* Configurable parameters */ +#ifndef RPMSG_BUFFER_SIZE +#define RPMSG_BUFFER_SIZE (512) +#endif + +#include "virtual_driver/virt_uart.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/virtio/virtio.c b/cores/arduino/stm32/OpenAMP/virtio/virtio.c new file mode 100644 index 0000000000..0efadcfea5 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/virtio/virtio.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "open-amp/lib/virtio/virtio.c" + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/virtio/virtqueue.c b/cores/arduino/stm32/OpenAMP/virtio/virtqueue.c new file mode 100644 index 0000000000..62b71b43ac --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/virtio/virtqueue.c @@ -0,0 +1,5 @@ +#ifdef VIRTIOCON + +#include "open-amp/lib/virtio/virtqueue.c" + +#endif /* VIRTIOCON */ From 662d591d0fa9a1b484dfe61c940750b0759e00f7 Mon Sep 17 00:00:00 2001 From: Bumsik Kim Date: Thu, 7 Nov 2019 11:31:59 +0900 Subject: [PATCH 3/7] [VirtIO] Add first VirtIO and ringbuffer --- boards.txt | 10 +- cores/arduino/VirtIOSerial.cpp | 217 ++++++++++++++++++ cores/arduino/VirtIOSerial.h | 83 +++++++ cores/arduino/WSerial.cpp | 5 + cores/arduino/WSerial.h | 17 ++ cores/arduino/stm32/OpenAMP/mbox_ipcc.c | 146 ++++++------ cores/arduino/stm32/OpenAMP/mbox_ipcc.h | 20 +- .../open-amp/remoteproc/remoteproc_virtio.c | 1 + .../stm32/OpenAMP/open-amp/rpmsg/rpmsg.c | 1 + .../OpenAMP/open-amp/rpmsg/rpmsg_virtio.c | 1 + cores/arduino/stm32/OpenAMP/openamp.c | 74 +++++- cores/arduino/stm32/OpenAMP/openamp.h | 22 +- cores/arduino/stm32/OpenAMP/openamp_conf.h | 178 +------------- cores/arduino/stm32/OpenAMP/rsc_table.c | 173 ++++---------- cores/arduino/stm32/OpenAMP/rsc_table.h | 14 +- cores/arduino/stm32/OpenAMP/virt_uart.c | 9 +- cores/arduino/stm32/OpenAMP/virtio/virtio.c | 1 + .../arduino/stm32/OpenAMP/virtio/virtqueue.c | 1 + cores/arduino/stm32/OpenAMP/virtio_buffer.c | 130 +++++++++++ cores/arduino/stm32/OpenAMP/virtio_buffer.h | 66 ++++++ cores/arduino/stm32/OpenAMP/virtio_config.h | 31 +++ platform.txt | 7 +- 22 files changed, 772 insertions(+), 435 deletions(-) create mode 100644 cores/arduino/VirtIOSerial.cpp create mode 100644 cores/arduino/VirtIOSerial.h create mode 100644 cores/arduino/stm32/OpenAMP/virtio_buffer.c create mode 100644 cores/arduino/stm32/OpenAMP/virtio_buffer.h create mode 100644 cores/arduino/stm32/OpenAMP/virtio_config.h diff --git a/boards.txt b/boards.txt index 5d3d3bc785..60396186ba 100644 --- a/boards.txt +++ b/boards.txt @@ -5,6 +5,7 @@ menu.pnum=Board part number menu.xserial=U(S)ART support menu.usb=USB support (if available) menu.xusb=USB speed (if available) +menu.virtio=Virtual serial support menu.opt=Optimize menu.rtlib=C Runtime Library @@ -707,7 +708,7 @@ STM32MP1.build.mcu=cortex-m4 STM32MP1.build.flags.fp=-mfpu=fpv4-sp-d16 -mfloat-abi=hard STM32MP1.build.series=STM32MP1xx STM32MP1.build.cmsis_lib_gcc=arm_cortexM4l_math -STM32MP1.build.extra_flags=-DCORE_CM4 -DUSE_FULL_LL_DRIVER -D{build.product_line} {build.xSerial} +STM32MP1.build.extra_flags=-DCORE_CM4 -DUSE_FULL_LL_DRIVER -D{build.product_line} {build.enable_virtio} {build.xSerial} # STM32MP157A-DK1 board STM32MP1.menu.pnum.STM32MP157A_DK1=STM32MP157A-DK1 @@ -1886,6 +1887,13 @@ Eval.menu.xserial.none.build.xSerial=-DHAL_UART_MODULE_ENABLED -DHWSERIAL_NONE Eval.menu.xserial.disabled=Disabled (no Serial support) Eval.menu.xserial.disabled.build.xSerial= +STM32MP1.menu.virtio.disable=Disabled (no SerialVirtIO nor /dev/ttyRPMSG0 available) +STM32MP1.menu.virtio.disable.build.enable_virtio= +STM32MP1.menu.virtio.generic=SerialVirtIO (= generic 'Serial') <=> /dev/ttyRPMSG0 +STM32MP1.menu.virtio.generic.build.enable_virtio={build.virtio_flags} +STM32MP1.menu.virtio.enabled=SerialVirtIO <=> /dev/ttyRPMSG0 +STM32MP1.menu.virtio.enabled.build.enable_virtio={build.virtio_flags} -DDISABLE_GENERIC_SERIALVIRTIO + STM32MP1.menu.xserial.generic=UART only (generic 'Serial') STM32MP1.menu.xserial.generic.build.xSerial=-DHAL_UART_MODULE_ENABLED STM32MP1.menu.xserial.none=UART only (no generic 'Serial') diff --git a/cores/arduino/VirtIOSerial.cpp b/cores/arduino/VirtIOSerial.cpp new file mode 100644 index 0000000000..cfee3298a9 --- /dev/null +++ b/cores/arduino/VirtIOSerial.cpp @@ -0,0 +1,217 @@ +/** + * MIT License: + * Copyright (c) 2019 Bumsik kim + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (VIRTIOCON) + +#include "VirtIOSerial.h" +#include "core_debug.h" + +#if !defined(VIRTIOSERIAL_NUM) +#define VIRTIOSERIAL_NUM 1 +#endif + +VirtIOSerialObj_t *VirtIOSerial_Handle[VIRTIOSERIAL_NUM] = {NULL}; + +uint32_t VirtIOSerial::VirtIOSerial_index = 0; + +// Default instance +VirtIOSerial SerialVirtIO; + +void serialEventVirtIO() __attribute__((weak)); +VirtIOSerialObj_t *get_VirtIOSerial_obj(VIRT_UART_HandleTypeDef *huart); + +void VirtIOSerial::begin(void) +{ + virtio_buffer_init(&_VirtIOSerialObj.ring); + if (_VirtIOSerialObj.initialized) { + return; + } + if (OPENAMP_Init() != 0) { + Error_Handler(); + } + if (VIRT_UART_Init(&_VirtIOSerialObj.handle) != VIRT_UART_OK) { + Error_Handler(); + } + + VirtIOSerial_index ++; + _VirtIOSerialObj.__this = (void *)this; + + /* Need to register callback for message reception by channels */ + if (VIRT_UART_RegisterCallback(&_VirtIOSerialObj.handle, VIRT_UART_RXCPLT_CB_ID, rxGenericCallback) != VIRT_UART_OK) { + Error_Handler(); + } + + VirtIOSerial_Handle[VirtIOSerial_index] = &_VirtIOSerialObj; + _VirtIOSerialObj.initialized = true; + _VirtIOSerialObj.first_message_discarded = false; + + // This will wait for the first message "DUMMY", see rxCallback(). + OPENAMP_Wait_EndPointready(&_VirtIOSerialObj.handle.ept); +} + +void VirtIOSerial::begin(uint32_t /* baud_count */) +{ + // uart config is ignored in OpenAMP + begin(); +} + +void VirtIOSerial::begin(uint32_t /* baud_count */, uint8_t /* config */) +{ + // uart config is ignored in OpenAMP + begin(); +} + +void VirtIOSerial::end() +{ + VIRT_UART_DeInit(&_VirtIOSerialObj.handle); + OPENAMP_DeInit(); + virtio_buffer_init(&_VirtIOSerialObj.ring); + _VirtIOSerialObj.initialized = false; +} + +int VirtIOSerial::available(void) +{ + checkMessageFromISR(); + return virtio_buffer_read_available(&_VirtIOSerialObj.ring); +} + +int VirtIOSerial::availableForWrite() +{ + checkMessageFromISR(); + // Just return max length of VIRT_UART_Transmit() can transmit. + // See VIRT_UART_Transmit(). + return RPMSG_VRING_PAYLOAD_SIZE; +} + +int VirtIOSerial::peek(void) +{ + checkMessageFromISR(); + if (virtio_buffer_read_available(&_VirtIOSerialObj.ring) > 0) { + uint8_t tmp; + virtio_buffer_peek(&_VirtIOSerialObj.ring, &tmp, 1); + return tmp; + } else { + return -1; + } +} + +int VirtIOSerial::read(void) +{ + if (available() > 0) { + char ch; + readBytes(&ch, 1); + return ch; + } else { + return -1; + } +} + +size_t VirtIOSerial::readBytes(char *buffer, size_t length) +{ + checkMessageFromISR(); + const size_t size = virtio_buffer_read(&_VirtIOSerialObj.ring, reinterpret_cast(buffer), length); + // The ring buffer might be available enough to write after reading + checkMessageFromISR(); + return size; +} + +size_t VirtIOSerial::write(uint8_t ch) +{ + // Just write single-byte buffer. + return write(&ch, 1); +} + +// Warning: Currently VirtIOSerial implementation is synchronous, blocking +// until all bytes are sent. But it will be fast enough. +size_t VirtIOSerial::write(const uint8_t *buffer, size_t size) +{ + checkMessageFromISR(); + if (VIRT_UART_Transmit(&_VirtIOSerialObj.handle, const_cast(buffer), size) != VIRT_UART_OK) { + // This error usually happens when size > 496. See VirtIOSerial::availableForWrite() + core_debug("ERROR: VirtIOSerial::write() failed. Check availableForWrite().\n"); + return 0; + } + // It is likely receive "buf free" from the Linux host right after + // VIRT_UART_Transmit(). So check it here too. + checkMessageFromISR(); + return size; +} + +void VirtIOSerial::flush(void) +{ + checkMessageFromISR(); + // write() is blocked until all bytes are sent. So flush() doesn't need to do + // anything. See rpmsg_send(). + return; +} + +/** + * @brief Check if RPMsg message arrived from IPCC ISR + * @note This should called as mush as possible to consume RPMsg ring buffers, + * so that the host processor can send more messages quickly. + */ +void VirtIOSerial::checkMessageFromISR(void) +{ + OPENAMP_check_for_tx_message(); + if (virtio_buffer_write_available(&_VirtIOSerialObj.ring) >= RPMSG_VRING_TOTAL_PAYLOAD_SIZE) { + // This calls rxCallback() VRING_NUM_BUFFS times at maximum + OPENAMP_check_for_rx_message(); + } +} + +void VirtIOSerial::rxGenericCallback(VIRT_UART_HandleTypeDef *huart) +{ + VirtIOSerialObj_t *obj = get_VirtIOSerial_obj(huart); + VirtIOSerial *VIOS = (VirtIOSerial *)(obj->__this); + + VIOS->rxCallback(huart); +} + +void VirtIOSerial::rxCallback(VIRT_UART_HandleTypeDef *huart) +{ + // Linux host must send a dummy data first to finish initialization of rpmsg + // on the coprocessor side. This message should be discarded. + // run_arduino_gen.sh script will send dummy data: "DUMMY". + // See: https://github.com/OpenAMP/open-amp/issues/182 + // See: run_arduino_gen.sh + if (!_VirtIOSerialObj.first_message_discarded) { + huart->RxXferSize = 0; + _VirtIOSerialObj.first_message_discarded = true; + } + + size_t size = min(huart->RxXferSize, virtio_buffer_write_available(&_VirtIOSerialObj.ring)); + while (size > 0) { + size -= virtio_buffer_write(&_VirtIOSerialObj.ring, huart->pRxBuffPtr, size); + } +} + +/* Aim of the function is to get _VirtIOSerialObj pointer using huart pointer */ +/* Highly inspired from magical linux kernel's "container_of" */ +VirtIOSerialObj_t *get_VirtIOSerial_obj(VIRT_UART_HandleTypeDef *huart) +{ + VirtIOSerialObj_t *obj; + obj = (VirtIOSerialObj_t *)((char *)huart - offsetof(VirtIOSerialObj_t, handle)); + return (obj); +} + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/VirtIOSerial.h b/cores/arduino/VirtIOSerial.h new file mode 100644 index 0000000000..010e863249 --- /dev/null +++ b/cores/arduino/VirtIOSerial.h @@ -0,0 +1,83 @@ +/** + * MIT License: + * Copyright (c) 2019 Bumsik kim + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _VIRTIOSERIAL_H_ +#define _VIRTIOSERIAL_H_ + +#if defined (VIRTIOCON) +#include "Stream.h" +#include "openamp.h" +#include "openamp_log.h" +#include "wiring.h" +#include "virtio_buffer.h" + +//================================================================================ +// Serial over OpenAMP + +// This structure is used to be able to get VirtIOSerial instance (C++ class) +// from handler (C structure) specially for rpmsg message management +typedef struct { + // Those 2 first fields must remain in this order at the beginning of the structure + void *__this; + VIRT_UART_HandleTypeDef handle; + bool initialized; + bool first_message_discarded; + virtio_buffer_t ring; +} VirtIOSerialObj_t; + + +class VirtIOSerial : public Stream { + public: + void begin(void); + void begin(uint32_t); + void begin(uint32_t, uint8_t); + void end(void); + + virtual int available(void); + virtual int availableForWrite(void); + virtual int peek(void); + virtual int read(void); + virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buffer, size_t size); + virtual void flush(void); + + static void rxGenericCallback(VIRT_UART_HandleTypeDef *huart); + void rxCallback(VIRT_UART_HandleTypeDef *huart); + + using Print::write; // pull in write(str) from Print + operator bool(void) + { + return true; + } + + private: + static uint32_t VirtIOSerial_index; + VirtIOSerialObj_t _VirtIOSerialObj; + void checkMessageFromISR(void); +}; + +extern VirtIOSerial SerialVirtIO; + +#endif /* VIRTIOCON */ +#endif /* _VIRTIOSERIAL_H_ */ diff --git a/cores/arduino/WSerial.cpp b/cores/arduino/WSerial.cpp index 3d866cae2f..dfbda4320d 100644 --- a/cores/arduino/WSerial.cpp +++ b/cores/arduino/WSerial.cpp @@ -62,5 +62,10 @@ WEAK void serialEventRun(void) serialEventUSB(); } #endif +#if defined(HAVE_SERIALVIRTIO) + if (serialEventVirtIO && SerialVirtIO.available()) { + serialEventVirtIO(); + } +#endif } diff --git a/cores/arduino/WSerial.h b/cores/arduino/WSerial.h index ffdc98ad52..6132593314 100644 --- a/cores/arduino/WSerial.h +++ b/cores/arduino/WSerial.h @@ -4,6 +4,7 @@ #include "variant.h" #include "HardwareSerial.h" #include "USBSerial.h" +#include "VirtIOSerial.h" #if defined (USBCON) && defined(USBD_USE_CDC) #ifndef DISABLE_GENERIC_SERIALUSB @@ -21,6 +22,22 @@ extern void serialEventUSB(void) __attribute__((weak)); #endif /* USBCON && USBD_USE_CDC */ +#if defined(VIRTIOCON) +#ifndef DISABLE_GENERIC_SERIALVIRTIO +#define ENABLE_SERIALVIRTIO +#if !defined(Serial) +#define Serial SerialVirtIO +#define serialEvent serialEventVirtIO +#endif +#endif + +#if defined(ENABLE_SERIALVIRTIO) +#define HAVE_SERIALVIRTIO +#endif + +extern void serialEventVirtIO(void) __attribute__((weak)); +#endif /* VIRTIOCON */ + #if defined(HAL_UART_MODULE_ENABLED) && !defined(HAL_UART_MODULE_ONLY) #if !defined(HWSERIAL_NONE) && defined(SERIAL_UART_INSTANCE) #if SERIAL_UART_INSTANCE == 0 diff --git a/cores/arduino/stm32/OpenAMP/mbox_ipcc.c b/cores/arduino/stm32/OpenAMP/mbox_ipcc.c index dc0facc41d..cb55eaea86 100644 --- a/cores/arduino/stm32/OpenAMP/mbox_ipcc.c +++ b/cores/arduino/stm32/OpenAMP/mbox_ipcc.c @@ -21,25 +21,22 @@ /* * Channel direction and usage: - * virtio_rpmsg_bus.c rpmsg_virtio.c - * ======== <-- new msg ---=============--------<------ ======= - * || || rvq (rx) || CHANNEL 1 || svq (tx_vq) || || - * || A7 || ------->-------=============--- buf free--> || M4 || - * || || || || - * ||master|| <-- buf free---=============--------<------ ||slave|| - * || || svq (tx) || CHANNEL 2 || rvq (rx_vq) || || - * ======== ------->-------=============----new msg --> ======= +virtio_rpmsg_bus.c virtqueue vring rpmsg_virtio.c + ======== <-- new msg ---=============--------<------ ========== +|| || rvq (rx) || IPCC CHANNEL 1 || svq (tx_vq) -> vring0 || || +|| A7 || ------->-------=============--- buf free--> || M4 || +|| || || || +||master|| <-- buf free---=============--------<------ || slave || +|| || svq (tx) || IPCC CHANNEL 2 || rvq (rx_vq) -> vring1 ||(remote)|| + ======== ------->-------=============----new msg --> ========== */ /* Includes ------------------------------------------------------------------*/ -#include "openamp/open_amp.h" +#include "virtio_config.h" +#include #include "stm32_def.h" #include "openamp_conf.h" - -/* Within 'USER CODE' section, code will be kept by default at each generation */ -/* USER CODE BEGIN 0 */ - -/* USER CODE END 0 */ +#include "mbox_ipcc.h" /* Private define ------------------------------------------------------------*/ #define MASTER_CPU_ID 0 @@ -47,30 +44,21 @@ #define IPCC_CPU_A7 MASTER_CPU_ID #define IPCC_CPU_M4 REMOTE_CPU_ID -#define RX_NO_MSG 0 -#define RX_NEW_MSG 1 -#define RX_BUF_FREE 2 +typedef enum { + MBOX_NO_MSG = 0, + MBOX_NEW_MSG = 1, + MBOX_BUF_FREE = 2 +} mbox_status_t; /* Private variables ---------------------------------------------------------*/ -extern IPCC_HandleTypeDef hipcc; -int msg_received_ch1 = RX_NO_MSG; -int msg_received_ch2 = RX_NO_MSG; -uint32_t vring0_id = 0; /* used for channel 1 */ -uint32_t vring1_id = 1; /* used for channel 2 */ - - - - IPCC_HandleTypeDef hipcc; - - - +mbox_status_t msg_received_ch1 = MBOX_NO_MSG; +mbox_status_t msg_received_ch2 = MBOX_NO_MSG; /* Private function prototypes -----------------------------------------------*/ void IPCC_channel1_callback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir); void IPCC_channel2_callback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir); - /** * @brief Initialize MAILBOX with IPCC peripheral * @param None @@ -81,6 +69,7 @@ int MAILBOX_Init(void) __HAL_RCC_IPCC_CLK_ENABLE(); HAL_NVIC_SetPriority(IPCC_RX1_IRQn, IPCC_IRQ_PRIO, IPCC_IRQ_SUBPRIO); HAL_NVIC_EnableIRQ(IPCC_RX1_IRQn); + hipcc.Instance = IPCC; if (HAL_IPCC_Init(&hipcc) != HAL_OK) { Error_Handler(); @@ -102,49 +91,58 @@ int MAILBOX_Init(void) } /** - * @brief Initialize MAILBOX with IPCC peripheral - * @param virtio device - * @retval : Operation result - */ -int MAILBOX_Poll(struct virtio_device *vdev) + * @brief Process vring messages received from IPCC ISR + * @param vdev: virtio device + * @param vring_id: Vring ID + * @retval : Operation result + */ +int MAILBOX_Poll(struct virtio_device *vdev, uint32_t vring_id) { - /* If we got an interrupt, ask for the corresponding virtqueue processing */ - - if (msg_received_ch1 == RX_BUF_FREE) { - OPENAMP_log_dbg("Running virt0 (ch_1 buf free)\r\n"); - rproc_virtio_notified(vdev, VRING0_ID); - msg_received_ch1 = RX_NO_MSG; - return 0; + int ret = -1; + + switch (vring_id) { + case VRING0_ID: + if (msg_received_ch1 == MBOX_BUF_FREE) { + /* This calls rpmsg_virtio_tx_callback(), which actually does nothing. */ + rproc_virtio_notified(vdev, VRING0_ID); + msg_received_ch1 = MBOX_NO_MSG; + ret = 0; + } + break; + case VRING1_ID: + if (msg_received_ch2 == MBOX_NEW_MSG) { + /** + * This calls rpmsg_virtio_rx_callback(), which calls virt_uart rx callback + * RING_NUM_BUFFS times at maximum. + */ + rproc_virtio_notified(vdev, VRING1_ID); + msg_received_ch2 = MBOX_NO_MSG; + ret = 0; + } + break; + default: + break; } - if (msg_received_ch2 == RX_NEW_MSG) { - OPENAMP_log_dbg("Running virt1 (ch_2 new msg)\r\n"); - rproc_virtio_notified(vdev, VRING1_ID); - msg_received_ch2 = RX_NO_MSG; - - /* The OpenAMP framework does not notify for free buf: do it here */ - rproc_virtio_notified(NULL, VRING1_ID); - return 0; - } - - return -1; + return ret; } - /** - * @brief Callback function called by OpenAMP MW to notify message processing - * @param VRING id + * @brief Callback function called by OpenAMP MW to notify message processing (aka. kick) + * @note This callback is called by virtqueue_kick() in rpmsg_virtio_send_offchannel_raw(). + * Therefore, it is only called while tx, but not rx. + * @param Vring id * @retval Operation result */ -int MAILBOX_Notify(void *priv, uint32_t id) +int MAILBOX_Notify(void *priv, uint32_t vring_id) { - uint32_t channel; (void)priv; + uint32_t channel; /* Called after virtqueue processing: time to inform the remote */ - if (id == VRING0_ID) { + if (vring_id == VRING0_ID) { channel = IPCC_CHANNEL_1; - } else if (id == VRING1_ID) { + } else if (vring_id == VRING1_ID) { /* Note: the OpenAMP framework never notifies this */ channel = IPCC_CHANNEL_2; return -1; @@ -154,12 +152,12 @@ int MAILBOX_Notify(void *priv, uint32_t id) /* Check that the channel is free (otherwise wait until it is) */ if (HAL_IPCC_GetChannelStatus(&hipcc, channel, IPCC_CHANNEL_DIR_TX) == IPCC_CHANNEL_STATUS_OCCUPIED) { - // Wait for channel to be freed + /* Wait for channel to be freed */ while (HAL_IPCC_GetChannelStatus(&hipcc, channel, IPCC_CHANNEL_DIR_TX) == IPCC_CHANNEL_STATUS_OCCUPIED) ; } - /* Inform A7 (either new message, or buf free) */ + /* Inform the host processor (either new message, or buf free) */ HAL_IPCC_NotifyCPU(&hipcc, channel, IPCC_CHANNEL_DIR_TX); return 0; } @@ -169,13 +167,10 @@ int MAILBOX_Notify(void *priv, uint32_t id) void IPCC_channel1_callback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir) { - if (msg_received_ch1 != RX_NO_MSG) { - OPENAMP_log_dbg("IPCC_channel1_callback: previous IRQ not treated (status = %d)\r\n", msg_received_ch1); - } - - msg_received_ch1 = RX_BUF_FREE; + (void) ChannelDir; + msg_received_ch1 = MBOX_BUF_FREE; - /* Inform A7 that we have received the 'buff free' msg */ + /* Inform the host processor that we have received the 'buff free' msg */ HAL_IPCC_NotifyCPU(hipcc, ChannelIndex, IPCC_CHANNEL_DIR_RX); } @@ -183,14 +178,10 @@ void IPCC_channel1_callback(IPCC_HandleTypeDef *hipcc, void IPCC_channel2_callback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir) { - if (msg_received_ch2 != RX_NO_MSG) { - OPENAMP_log_dbg("IPCC_channel2_callback: previous IRQ not treated (status = %d)\r\n", msg_received_ch2); - } - - msg_received_ch2 = RX_NEW_MSG; + (void) ChannelDir; + msg_received_ch2 = MBOX_NEW_MSG; - /* Inform A7 that we have received the new msg */ - OPENAMP_log_dbg("Ack new message on ch2\r\n"); + /* Inform the host processor that we have received the msg */ HAL_IPCC_NotifyCPU(hipcc, ChannelIndex, IPCC_CHANNEL_DIR_RX); } @@ -199,12 +190,7 @@ void IPCC_channel2_callback(IPCC_HandleTypeDef *hipcc, */ void IPCC_RX1_IRQHandler(void) { - /* USER CODE BEGIN IPCC_RX1_IRQn 0 */ - /* USER CODE END IPCC_RX1_IRQn 0 */ HAL_IPCC_RX_IRQHandler(&hipcc); - /* USER CODE BEGIN IPCC_RX1_IRQn 1 */ - - /* USER CODE END IPCC_RX1_IRQn 1 */ } #endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/mbox_ipcc.h b/cores/arduino/stm32/OpenAMP/mbox_ipcc.h index be338872b2..34dbb7af84 100644 --- a/cores/arduino/stm32/OpenAMP/mbox_ipcc.h +++ b/cores/arduino/stm32/OpenAMP/mbox_ipcc.h @@ -17,8 +17,8 @@ ****************************************************************************** */ -#ifndef MBOX_IPCC_H_ -#define MBOX_IPCC_H_ +#ifndef __OPENAMP_MBOX_IPCC_H +#define __OPENAMP_MBOX_IPCC_H #ifdef VIRTIOCON @@ -30,21 +30,9 @@ #define IPCC_IRQ_SUBPRIO 0 #endif -/* USER CODE BEGIN firstSection */ -/* can be used to modify / undefine following code or add new definitions */ -/* USER CODE END firstSection */ - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ int MAILBOX_Init(void); +int MAILBOX_Poll(struct virtio_device *vdev, uint32_t vring_id); int MAILBOX_Notify(void *priv, uint32_t id); -int MAILBOX_Poll(struct virtio_device *vdev); - -/* USER CODE BEGIN lastSection */ -/* can be used to modify / undefine previous code or add new definitions */ -/* USER CODE END lastSection */ #endif /* VIRTIOCON */ -#endif /* MBOX_IPCC_H_ */ +#endif /* __OPENAMP_MBOX_IPCC_H */ diff --git a/cores/arduino/stm32/OpenAMP/open-amp/remoteproc/remoteproc_virtio.c b/cores/arduino/stm32/OpenAMP/open-amp/remoteproc/remoteproc_virtio.c index af4d8a2341..c829226b93 100644 --- a/cores/arduino/stm32/OpenAMP/open-amp/remoteproc/remoteproc_virtio.c +++ b/cores/arduino/stm32/OpenAMP/open-amp/remoteproc/remoteproc_virtio.c @@ -1,5 +1,6 @@ #ifdef VIRTIOCON +#include "virtio_config.h" #include "open-amp/lib/remoteproc/remoteproc_virtio.c" #endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c b/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c index bf650fffdc..11b66787ff 100644 --- a/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c +++ b/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg.c @@ -1,5 +1,6 @@ #ifdef VIRTIOCON +#include "virtio_config.h" #include "open-amp/lib/rpmsg/rpmsg.c" #endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c b/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c index 086354d102..8a89668a05 100644 --- a/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c +++ b/cores/arduino/stm32/OpenAMP/open-amp/rpmsg/rpmsg_virtio.c @@ -1,5 +1,6 @@ #ifdef VIRTIOCON +#include "virtio_config.h" #include "open-amp/lib/rpmsg/rpmsg_virtio.c" #endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/openamp.c b/cores/arduino/stm32/OpenAMP/openamp.c index 65291dcdb8..095785eff1 100644 --- a/cores/arduino/stm32/OpenAMP/openamp.c +++ b/cores/arduino/stm32/OpenAMP/openamp.c @@ -18,11 +18,13 @@ */ #ifdef VIRTIOCON +#include "virtio_config.h" #include "openamp/open_amp.h" #include "openamp.h" #include "rsc_table.h" #include "metal/sys.h" #include "metal/device.h" +#include "mbox_ipcc.h" /* Private define ------------------------------------------------------------*/ #define SHM_DEVICE_NAME "STM32_SHM" @@ -34,10 +36,11 @@ static struct metal_io_region *rsc_io; static struct shared_resource_table *rsc_table; static struct rpmsg_virtio_shm_pool shpool; static struct rpmsg_virtio_device rvdev; - - static metal_phys_addr_t shm_physmap; +/** + * @brief OpenAMP libmetal device structure + */ struct metal_device shm_device = { .name = SHM_DEVICE_NAME, .num_regions = 2, @@ -50,6 +53,12 @@ struct metal_device shm_device = { .irq_info = NULL }; +/** + * @brief Initialize OpenAMP shared memory (libmetal and resource table) + * + * @param RPMsgRole: RPMSG_REMOTE - Device is remote (slave) + * @retval 0 on success + */ static int OPENAMP_shmem_init(int RPMsgRole) { int status = 0; @@ -97,7 +106,12 @@ static int OPENAMP_shmem_init(int RPMsgRole) return 0; } -int OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb) +/** + * @brief Initialize the openamp framework + * + * @retval 0 when success + */ +int OPENAMP_Init() { struct fw_rsc_vdev_vring *vring_rsc; struct virtio_device *vdev; @@ -106,12 +120,12 @@ int OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb) MAILBOX_Init(); /* Libmetal Initilalization */ - status = OPENAMP_shmem_init(RPMsgRole); + status = OPENAMP_shmem_init(RPMSG_REMOTE); if (status) { return status; } - vdev = rproc_virtio_create_vdev(RPMsgRole, VDEV_ID, &rsc_table->vdev, + vdev = rproc_virtio_create_vdev(RPMSG_REMOTE, VDEV_ID, &rsc_table->vdev, rsc_io, NULL, MAILBOX_Notify, NULL); if (vdev == NULL) { return -1; @@ -135,11 +149,14 @@ int OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb) rpmsg_virtio_init_shm_pool(&shpool, (void *)VRING_BUFF_ADDRESS, (size_t)SHM_SIZE); - rpmsg_init_vdev(&rvdev, vdev, ns_bind_cb, shm_io, &shpool); + rpmsg_init_vdev(&rvdev, vdev, NULL, shm_io, &shpool); return 0; } +/** + * @brief Deinitialize the openamp framework + */ void OPENAMP_DeInit() { rpmsg_deinit_vdev(&rvdev); @@ -147,11 +164,27 @@ void OPENAMP_DeInit() metal_finish(); } +/** + * @brief Initialize the endpoint struct + * + * @param ept: virtio rpmsg endpoint + */ void OPENAMP_init_ept(struct rpmsg_endpoint *ept) { rpmsg_init_ept(ept, "", RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, NULL, NULL); } +/** + * @brief Create and register the name service endpoint + * + * @param ept: virtio rpmsg endpoint + * @param name: virtio rpmsg name service name + * @param dest: message destination address. Set RPMSG_ADDR_ANY if + * the host processor will decide this + * @param cb: virtio rpmsg endpoint callback (receive) + * @param unbind_cb: virtio rpmsg endpoint destroy callback + * @retval 0 when success + */ int OPENAMP_create_endpoint(struct rpmsg_endpoint *ept, const char *name, uint32_t dest, rpmsg_ept_cb cb, rpmsg_ns_unbind_cb unbind_cb) @@ -160,15 +193,38 @@ int OPENAMP_create_endpoint(struct rpmsg_endpoint *ept, const char *name, unbind_cb); } -void OPENAMP_check_for_message(void) +/** + * @brief Check and process any received messages from tx channel + * @note Don't call this in an ISR. + */ +void OPENAMP_check_for_tx_message(void) { - MAILBOX_Poll(rvdev.vdev); + MAILBOX_Poll(rvdev.vdev, VRING0_ID); } +/** + * @brief Check and process any received messages from rx channel + * @note Don't call this in an ISR. + */ +void OPENAMP_check_for_rx_message(void) +{ + MAILBOX_Poll(rvdev.vdev, VRING1_ID); +} + +/** + * @brief Wait loop on rpmsg endpoint (VirtIOSerial) ready to send a message. + * (until message dest address is known) + * @note This will wait until the first message arrives from the Linux host. + * If we send a rpmsg message before this it will fail. + * @note Don't call this in an ISR. + * @see VirtIOSerial::rxCallback + * @param rp_ept: virtio rpmsg endpoint + */ void OPENAMP_Wait_EndPointready(struct rpmsg_endpoint *rp_ept) { while (!is_rpmsg_ept_ready(rp_ept)) { - MAILBOX_Poll(rvdev.vdev); + MAILBOX_Poll(rvdev.vdev, VRING0_ID); + MAILBOX_Poll(rvdev.vdev, VRING1_ID); } } diff --git a/cores/arduino/stm32/OpenAMP/openamp.h b/cores/arduino/stm32/OpenAMP/openamp.h index 8d8ee0f604..09b684edd7 100644 --- a/cores/arduino/stm32/OpenAMP/openamp.h +++ b/cores/arduino/stm32/OpenAMP/openamp.h @@ -18,8 +18,8 @@ */ /* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __openamp_H -#define __openamp_H +#ifndef __OPENAMP_OPENAMP_H +#define __OPENAMP_OPENAMP_H #ifdef VIRTIOCON @@ -30,34 +30,24 @@ extern "C" { #include #include "openamp_conf.h" - #define OPENAMP_send rpmsg_send #define OPENAMP_destroy_ept rpmsg_destroy_ept -/* Initialize the openamp framework*/ -int OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb); - -/* Deinitialize the openamp framework*/ +int OPENAMP_Init(void); void OPENAMP_DeInit(void); - -/* Initialize the endpoint struct*/ void OPENAMP_init_ept(struct rpmsg_endpoint *ept); -/* Create and register the endpoint */ int OPENAMP_create_endpoint(struct rpmsg_endpoint *ept, const char *name, uint32_t dest, rpmsg_ept_cb cb, rpmsg_ns_unbind_cb unbind_cb); - -/* Check for new rpmsg reception */ -void OPENAMP_check_for_message(void); - -/* Wait loop on endpoint ready ( message dest address is know)*/ +void OPENAMP_check_for_tx_message(void); +void OPENAMP_check_for_rx_message(void); void OPENAMP_Wait_EndPointready(struct rpmsg_endpoint *rp_ept); #ifdef __cplusplus } #endif #endif /* VIRTIOCON */ -#endif /*__openamp_H */ +#endif /*__OPENAMP_OPENAMP_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/OpenAMP/openamp_conf.h b/cores/arduino/stm32/OpenAMP/openamp_conf.h index 7e9c64fe78..140709dcdf 100644 --- a/cores/arduino/stm32/OpenAMP/openamp_conf.h +++ b/cores/arduino/stm32/OpenAMP/openamp_conf.h @@ -18,8 +18,8 @@ */ /* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __OPENAMP_CONF__H__ -#define __OPENAMP_CONF__H__ +#ifndef __OPENAMP_OPENAMP_CONF_H +#define __OPENAMP_OPENAMP_CONF_H #ifdef VIRTIOCON @@ -31,109 +31,13 @@ extern "C" { #if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_) #include "openamp_log.h" #endif - -/* ########################## Mailbox Interface Selection ############################## */ -/** - * @brief This is the list of Mailbox interface to be used in the OpenAMP MW - * Please note that not all interfaces are supported by a STM32 device - */ -#define MAILBOX_IPCC_IF_ENABLED -//#define MAILBOX_HSEM_IF_ENABLED - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include Maibox interface header file - */ - -#ifdef MAILBOX_IPCC_IF_ENABLED -#include "mbox_ipcc.h" -#endif /* MAILBOX_IPCC_IF_ENABLED */ - -#ifdef MAILBOX_HSEM_IF_ENABLED -#include "mbox_hsem.h" -#endif /* MAILBOX_HSEM_IF_ENABLED */ - -/* ########################## Virtual Diver Module Selection ############################## */ /** - * @brief This is the list of modules to be used in the OpenAMP Virtual driver module - * Please note that virtual driver are not supported on all stm32 families - */ -#define VIRTUAL_UART_MODULE_ENABLED -//#define VIRTUAL_I2C_MODULE_ENABLED - - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include Virtual Driver module's header file - */ - -#ifdef VIRTUAL_UART_MODULE_ENABLED -#include "virt_uart.h" -#endif /* VIRTUAL_UART_MODULE_ENABLED */ - -#ifdef VIRTUAL_I2C_MODULE_ENABLED -#include "virt_i2c.h" -#endif /* VIRTUAL_I2C_MODULE_ENABLED */ - - - -/* USER CODE BEGIN INCLUDE */ - -/* USER CODE END INCLUDE */ - -/** @addtogroup OPENAMP_MW - * @{ - */ - -/** @defgroup OPENAMP_CONF OPENAMP_CONF - * @brief Configuration file for Openamp mw - * @{ - */ - -/** @defgroup OPENAMP_CONF_Exported_Variables OPENAMP_CONF_Exported_Variables - * @brief Public variables. - * @{ - */ - -/** - * @} - */ - -/** @defgroup OPENAMP_CONF_Exported_Defines OPENAMP_CONF_Exported_Defines - * @brief Defines for configuration of the Openamp mw - * @{ - */ - - -#if defined (__ICCARM__) -/* - * For IAR, the .icf file should contain the following lines: - * define symbol __OPENAMP_region_start__ = BASE_ADDRESS; (0x38000400 for example) - * define symbol __OPENAMP_region_size__ = MEM_SIZE; (0xB000 as example) - * - * export symbol __OPENAMP_region_start__; - * export symbol __OPENAMP_region_size__; - */ -extern const uint32_t __OPENAMP_region_start__; -extern const uint8_t __OPENAMP_region_size__; -#define SHM_START_ADDRESS ((metal_phys_addr_t)&__OPENAMP_region_start__) -#define SHM_SIZE ((size_t)&__OPENAMP_region_size__) - -#elif defined(__CC_ARM) -/* - * For MDK-ARM, the scatter file .sct should contain the following line: - * LR_IROM1 .... { - * ... - * __OpenAMP_SHMEM__ 0x38000400 EMPTY 0x0000B000 {} ; Shared Memory area used by OpenAMP - * } - * + * Note: Do not remove this. Removing this might not trigger compile error but + * the configuration can be significantly different. */ -extern unsigned int Image$$__OpenAMP_SHMEM__$$Base; -extern unsigned int Image$$__OpenAMP_SHMEM__$$ZI$$Length; -#define SHM_START_ADDRESS (unsigned int)&Image$$__OpenAMP_SHMEM__$$Base -#define SHM_SIZE ((size_t)&Image$$__OpenAMP_SHMEM__$$ZI$$Length) +#include "virtio_config.h" +#include "virt_uart.h" -#else /* * for GCC add the following content to the .ld file: * MEMORY @@ -147,30 +51,25 @@ extern unsigned int Image$$__OpenAMP_SHMEM__$$ZI$$Length; * using the LENGTH(OPEN_AMP_SHMEM) to set the SHM_SIZE lead to a crash thus we * use the start and end address. */ - extern int __OPENAMP_region_start__[]; /* defined by linker script */ extern int __OPENAMP_region_end__[]; /* defined by linker script */ #define SHM_START_ADDRESS ((metal_phys_addr_t)__OPENAMP_region_start__) #define SHM_SIZE (size_t)((void *)__OPENAMP_region_end__ - (void *) __OPENAMP_region_start__) -#endif - #if defined STM32MP1xx #define VRING_RX_ADDRESS -1 /* allocated by Master processor: CA7 */ #define VRING_TX_ADDRESS -1 /* allocated by Master processor: CA7 */ #define VRING_BUFF_ADDRESS -1 /* allocated by Master processor: CA7 */ #define VRING_ALIGNMENT 16 /* fixed to match with linux constraint */ +#ifndef VRING_NUM_BUFFS #define VRING_NUM_BUFFS 16 /* number of rpmsg buffer */ +#endif #else -#define VRING_RX_ADDRESS SHM_START_ADDRESS -#define VRING_TX_ADDRESS (SHM_START_ADDRESS + 0x400) -#define VRING_BUFF_ADDRESS (SHM_START_ADDRESS + 0x800) -#define VRING_ALIGNMENT 4 -#define VRING_NUM_BUFFS 4 /* number of rpmsg buffers */ +#error "VRING configuration for the device missing" #endif -/* Fixed parameter */ +/* Fixed parameters */ #define NUM_RESOURCE_ENTRIES 2 #define VRING_COUNT 2 @@ -178,66 +77,11 @@ extern int __OPENAMP_region_end__[]; /* defined by linker script */ #define VRING0_ID 0 /* VRING0 ID (master to remote) fixed to 0 for linux compatibility*/ #define VRING1_ID 1 /* VRING1 ID (remote to master) fixed to 1 for linux compatibility */ -/** - * @} - */ - -/** @defgroup OPENAMP_CONF_Exported_Macros OPENAMP_CONF_Exported_Macros - * @brief Aliases. - * @{ - */ - -/* DEBUG macros */ - -#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_) -#define OPENAMP_log_dbg log_dbg -#define OPENAMP_log_info log_info -#define OPENAMP_log_warn log_warn -#define OPENAMP_log_err log_err -#else -#define OPENAMP_log_dbg(...) -#define OPENAMP_log_info(...) -#define OPENAMP_log_warn(...) -#define OPENAMP_log_err(...) -#endif - -/** - * @} - */ - -/** @defgroup OPENAMP_CONF_Exported_Types OPENAMP_CONF_Exported_Types - * @brief Types. - * @{ - */ - -/** - * @} - */ - -/** @defgroup OPENAMP_CONF_Exported_FunctionsPrototype OPENAMP_CONF_Exported_FunctionsPrototype - * @brief Declaration of public functions for OpenAMP mw. - * @{ - */ - -/* Exported functions -------------------------------------------------------*/ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - #ifdef __cplusplus } #endif #endif /* VIRTIOCON */ -#endif /* __OPENAMP_CONF__H__ */ +#endif /* __OPENAMP_OPENAMP_CONF_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/OpenAMP/rsc_table.c b/cores/arduino/stm32/OpenAMP/rsc_table.c index 1d5ec3da29..8b38114380 100644 --- a/cores/arduino/stm32/OpenAMP/rsc_table.c +++ b/cores/arduino/stm32/OpenAMP/rsc_table.c @@ -21,153 +21,72 @@ ****************************************************************************** */ #ifdef VIRTIOCON -/** @addtogroup RSC_TABLE - * @{ - */ - -/** @addtogroup resource_table - * @{ - */ -/** @addtogroup resource_table_Private_Includes - * @{ - */ - -#if defined(__ICCARM__) || defined (__CC_ARM) -#include /* needed for offsetof definition*/ -#endif #include "rsc_table.h" #include "openamp/open_amp.h" -/** - * @} - */ - -/** @addtogroup resource_table_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup resource_table_Private_Defines - * @{ - */ - -/* Place resource table in special ELF section */ -#if defined(__GNUC__) -#define __section_t(S) __attribute__((__section__(#S))) -#define __resource __section_t(.resource_table) -#endif - -#if defined (STM32MP1xx) -#ifdef VIRTIO_MASTER_ONLY -#define CONST -#else -#define CONST const -#endif -#else -#define CONST -#endif - -#define RPMSG_IPU_C0_FEATURES 1 -#define VRING_COUNT 2 +#define RPMSG_IPU_C0_FEATURES 1 +#define VRING_COUNT 2 /* VirtIO rpmsg device id */ -#define VIRTIO_ID_RPMSG_ 7 +#define VIRTIO_ID_RPMSG 7 #if defined (__LOG_TRACE_IO_) extern char system_log_buf[]; #endif -#if defined(__GNUC__) -#if !defined (__CC_ARM) && !defined (STM32MP1xx) - -/* Since GCC is not initializing the resource_table at startup, it is declared as volatile to avoid compiler optimization - * for the CM4 (see resource_table_init() below) - */ -volatile struct shared_resource_table __resource __attribute__((used)) resource_table; -#else -CONST struct shared_resource_table __resource __attribute__((used)) resource_table = { -#endif -#elif defined(__ICCARM__) -__root CONST struct shared_resource_table resource_table @ ".resource_table" = { -#endif - -#if defined(__ICCARM__) || defined (__CC_ARM) || defined (STM32MP1xx) -.version = 1, +const struct shared_resource_table __attribute__((__section__(".resource_table"))) __attribute__((used)) resource_table = { + .version = 1, #if defined (__LOG_TRACE_IO_) -.num = 2, + .num = 2, #else -.num = 1, + .num = 1, #endif -.reserved = {0, 0}, -.offset = { - offsetof(struct shared_resource_table, vdev), - offsetof(struct shared_resource_table, cm_trace), -}, - -/* Virtio device entry */ -.vdev = { - RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, - VRING_COUNT, {0, 0}, -}, - -/* Vring rsc entry - part of vdev rsc entry */ -.vring0 = {VRING_TX_ADDRESS, VRING_ALIGNMENT, VRING_NUM_BUFFS, VRING0_ID, 0}, -.vring1 = {VRING_RX_ADDRESS, VRING_ALIGNMENT, VRING_NUM_BUFFS, VRING1_ID, 0}, - + .reserved = {0, 0}, + .offset = { + offsetof(struct shared_resource_table, vdev), + offsetof(struct shared_resource_table, cm_trace), + }, + /* Virtio device entry */ + .vdev = { + .type = RSC_VDEV, + .id = VIRTIO_ID_RPMSG, + .notifyid = 0, + .dfeatures = RPMSG_IPU_C0_FEATURES, + .gfeatures = 0, + .config_len = 0, + .status = 0, + .num_of_vrings = VRING_COUNT, + .reserved = {0, 0}, + }, + /* Vring rsc entry - part of vdev rsc entry */ + .vring0 = { + .da = VRING_TX_ADDRESS, + .align = VRING_ALIGNMENT, + .num = VRING_NUM_BUFFS, + .notifyid = VRING0_ID, + .reserved = 0 + }, + .vring1 = { + .da = VRING_RX_ADDRESS, + .align = VRING_ALIGNMENT, + .num = VRING_NUM_BUFFS, + .notifyid = VRING1_ID, + .reserved = 0 + }, #if defined (__LOG_TRACE_IO_) -.cm_trace = { - RSC_TRACE, - (uint32_t)system_log_buf, SYSTEM_TRACE_BUF_SZ, 0, "cm4_log", -}, + .cm_trace = { + .type = RSC_TRACE, + .da = (uint32_t)system_log_buf, + .len = SYSTEM_TRACE_BUF_SZ, + .reserved = 0, + .name = "arduino_core_debug", + }, #endif } ; -#endif void resource_table_init(int RPMsgRole, void **table_ptr, int *length) { - -#if !defined (STM32MP1xx) -#if defined (__GNUC__) && ! defined (__CC_ARM) -#ifdef VIRTIO_MASTER_ONLY - - /* - * Currently the GCC linker doesn't initialize the resource_table global variable at startup - * it is done here by the master application. - */ - memset(&resource_table, '\0', sizeof(struct shared_resource_table)); - resource_table.num = 1; - resource_table.version = 1; - resource_table.offset[0] = offsetof(struct shared_resource_table, vdev); - - resource_table.vring0.da = VRING_TX_ADDRESS; - resource_table.vring0.align = VRING_ALIGNMENT; - resource_table.vring0.num = VRING_NUM_BUFFS; - resource_table.vring0.notifyid = VRING0_ID; - - resource_table.vring1.da = VRING_RX_ADDRESS; - resource_table.vring1.align = VRING_ALIGNMENT; - resource_table.vring1.num = VRING_NUM_BUFFS; - resource_table.vring1.notifyid = VRING1_ID; - - - resource_table.vdev.type = RSC_VDEV; - resource_table.vdev.id = VIRTIO_ID_RPMSG_; - resource_table.vdev.num_of_vrings = VRING_COUNT; - resource_table.vdev.dfeatures = RPMSG_IPU_C0_FEATURES; -#else - - /* For the slave application let's wait until the resource_table is correctly initialized */ - while (resource_table.vring1.da != VRING_RX_ADDRESS) { - - } -#endif -#endif -#endif - (void)RPMsgRole; *length = sizeof(resource_table); *table_ptr = (void *)&resource_table; diff --git a/cores/arduino/stm32/OpenAMP/rsc_table.h b/cores/arduino/stm32/OpenAMP/rsc_table.h index ccb9260b9f..3979dc15f3 100644 --- a/cores/arduino/stm32/OpenAMP/rsc_table.h +++ b/cores/arduino/stm32/OpenAMP/rsc_table.h @@ -12,21 +12,15 @@ /* This file populates resource table for BM remote * for use by the Linux Master */ -#ifndef RSC_TABLE_H_ -#define RSC_TABLE_H_ +#ifndef __OPENAMP_RSC_TABLE_H +#define __OPENAMP_RSC_TABLE_H #ifdef VIRTIOCON +#include "virtio_config.h" #include "openamp/open_amp.h" #include "openamp_conf.h" -/* Place resource table in special ELF section */ -//#define __section_t(S) __attribute__((__section__(#S))) -//#define __resource __section_t(.resource_table) - - - - /* Resource table for the given remote */ struct shared_resource_table { unsigned int version; @@ -45,4 +39,4 @@ struct shared_resource_table { void resource_table_init(int RPMsgRole, void **table_ptr, int *length); #endif /* VIRTIOCON */ -#endif /* RSC_TABLE_H_ */ +#endif /* __OPENAMP_RSC_TABLE_H */ diff --git a/cores/arduino/stm32/OpenAMP/virt_uart.c b/cores/arduino/stm32/OpenAMP/virt_uart.c index d6b918ed79..3b86748c66 100644 --- a/cores/arduino/stm32/OpenAMP/virt_uart.c +++ b/cores/arduino/stm32/OpenAMP/virt_uart.c @@ -1,13 +1,6 @@ #ifdef VIRTIOCON - -// #include "openamp/open_amp.h" - -/* Configurable parameters */ -#ifndef RPMSG_BUFFER_SIZE -#define RPMSG_BUFFER_SIZE (512) -#endif - +#include "virtio_config.h" #include "virtual_driver/virt_uart.c" #endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/virtio/virtio.c b/cores/arduino/stm32/OpenAMP/virtio/virtio.c index 0efadcfea5..2e7ec33eae 100644 --- a/cores/arduino/stm32/OpenAMP/virtio/virtio.c +++ b/cores/arduino/stm32/OpenAMP/virtio/virtio.c @@ -1,5 +1,6 @@ #ifdef VIRTIOCON +#include "virtio_config.h" #include "open-amp/lib/virtio/virtio.c" #endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/virtio/virtqueue.c b/cores/arduino/stm32/OpenAMP/virtio/virtqueue.c index 62b71b43ac..150a7d06d3 100644 --- a/cores/arduino/stm32/OpenAMP/virtio/virtqueue.c +++ b/cores/arduino/stm32/OpenAMP/virtio/virtqueue.c @@ -1,5 +1,6 @@ #ifdef VIRTIOCON +#include "virtio_config.h" #include "open-amp/lib/virtio/virtqueue.c" #endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/virtio_buffer.c b/cores/arduino/stm32/OpenAMP/virtio_buffer.c new file mode 100644 index 0000000000..b6643f2688 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/virtio_buffer.c @@ -0,0 +1,130 @@ +/** + * MIT License: + * Copyright (c) 2019 Bumsik kim + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifdef VIRTIOCON + +#include "virtio_config.h" +#include "virtio_buffer.h" +#include +#include "wiring.h" + +void virtio_buffer_init(virtio_buffer_t *ring) +{ + ring->write_index = 0; + ring->read_index = 0; +} + +uint16_t virtio_buffer_read_available(virtio_buffer_t *ring) +{ + int32_t delta = ring->write_index - ring->read_index; + + if (delta < 0) { + return (VIRTIO_BUFFER_SIZE + delta); + } + return delta; +} + +/* WARNING no protection against race codition (on ring->read_index) when used in interruption */ +static uint16_t read(virtio_buffer_t *ring, uint8_t *dst, uint16_t size, bool peek) +{ + uint16_t read_index = ring->read_index; + int32_t delta = ring->write_index - read_index; + if (delta < 0) { + delta += VIRTIO_BUFFER_SIZE; + } + + size = min(size, delta); + + if ((size + read_index) > VIRTIO_BUFFER_SIZE) { + // Manage ring buffer rollover + // First, copy ring buffer from read index to end of buffer + memcpy(dst, ring->buffer + read_index, VIRTIO_BUFFER_SIZE - read_index); + // then, copy ring buffer from begining of buffer to end of read + memcpy(dst + VIRTIO_BUFFER_SIZE - read_index, ring->buffer, size - (VIRTIO_BUFFER_SIZE - read_index)); + } else { + memcpy(dst, ring->buffer + read_index, size); + } + + // Update read index if not peeked + if (!peek) { + ring->read_index += size; + + // Manage ring buffer rollover + if (ring->read_index >= VIRTIO_BUFFER_SIZE) { + ring->read_index -= VIRTIO_BUFFER_SIZE; + } + } + return size; +} + +uint16_t virtio_buffer_read(virtio_buffer_t *ring, uint8_t *dst, uint16_t size) +{ + return read(ring, dst, size, false); +} + + +uint16_t virtio_buffer_peek(virtio_buffer_t *ring, uint8_t *dst, uint16_t size) +{ + return read(ring, dst, size, true); +} + + + +uint16_t virtio_buffer_write_available(virtio_buffer_t *ring) +{ + int32_t delta = ring->read_index - ring->write_index - 1; + + if (delta < 0) { + return (VIRTIO_BUFFER_SIZE + delta); + } + return delta; +} + +/* WARNING no protection against race codition (on ring->write_index) when used in interruption */ +uint16_t virtio_buffer_write(virtio_buffer_t *ring, uint8_t *src, uint16_t size) +{ + uint16_t write_index = ring->write_index; + int32_t delta = ring->read_index - write_index - 1; + if (delta < 0) { + delta += VIRTIO_BUFFER_SIZE; + } + + size = min(size, delta); + + if ((size + write_index) > VIRTIO_BUFFER_SIZE) { + // Manage ring buffer rollover + // First, write ring buffer from write index to end of buffer + memcpy(ring->buffer + write_index, src, VIRTIO_BUFFER_SIZE - write_index); + // then, write ring buffer from beginning of buffer to end of read + memcpy(ring->buffer, src + VIRTIO_BUFFER_SIZE - write_index, size - (VIRTIO_BUFFER_SIZE - write_index)); + } else { + memcpy(ring->buffer + write_index, src, size); + } + + ring->write_index += size; + if (ring->write_index >= VIRTIO_BUFFER_SIZE) { + ring->write_index -= VIRTIO_BUFFER_SIZE; + } + return size; +} + +#endif /* VIRTIOCON */ diff --git a/cores/arduino/stm32/OpenAMP/virtio_buffer.h b/cores/arduino/stm32/OpenAMP/virtio_buffer.h new file mode 100644 index 0000000000..d88f83810c --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/virtio_buffer.h @@ -0,0 +1,66 @@ +/** + * MIT License: + * Copyright (c) 2019 Bumsik kim + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __OPENAMP_VIRTIO_BUFFER_H +#define __OPENAMP_VIRTIO_BUFFER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Size of virtio ring buffer + * @note See virtio_config.h for the size decision. (7937 bytes by default) + * The multiplier should be at least 1. As a result, the minimum + * required size of the initial virtio_buffer_write_available() + * must be RPMSG_VRING_TOTAL_PAYLOAD_SIZE. + * @note If VIRTIO_BUFFER_SIZE is still too big, RPMSG_VRING_TOTAL_PAYLOAD_SIZE + * can be reduced by reducing the number of VRING_NUM_BUFFS in + * virtio_config.h. + */ +#ifndef VIRTIO_BUFFER_SIZE +#define VIRTIO_BUFFER_SIZE (RPMSG_VRING_TOTAL_PAYLOAD_SIZE * 1 + 1) +#endif + +typedef struct { + uint8_t buffer[VIRTIO_BUFFER_SIZE]; + volatile uint16_t write_index; + volatile uint16_t read_index; +} virtio_buffer_t; + +void virtio_buffer_init(virtio_buffer_t *ring); + +uint16_t virtio_buffer_read_available(virtio_buffer_t *ring); +uint16_t virtio_buffer_read(virtio_buffer_t *ring, uint8_t *dst, uint16_t size); +uint16_t virtio_buffer_peek(virtio_buffer_t *ring, uint8_t *dst, uint16_t size); + +uint16_t virtio_buffer_write_available(virtio_buffer_t *ring); +uint16_t virtio_buffer_write(virtio_buffer_t *ring, uint8_t *src, uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif // __OPENAMP_VIRTIO_BUFFER_H diff --git a/cores/arduino/stm32/OpenAMP/virtio_config.h b/cores/arduino/stm32/OpenAMP/virtio_config.h new file mode 100644 index 0000000000..da931c5a9b --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/virtio_config.h @@ -0,0 +1,31 @@ +#ifndef __OPENAMP_VIRTIO_CONFIG_H +#define __OPENAMP_VIRTIO_CONFIG_H + +#ifndef RPMSG_BUFFER_SIZE +/** + * @brief Size of buffer of each vring buffers + * @note If the host processor is Linux, RPMSG_BUFFER_SIZE must be aligned + * with the kernel definition. + * Reference: https://elixir.bootlin.com/linux/v5.5.2/source/drivers/rpmsg/virtio_rpmsg_bus.c#L137 + */ +#define RPMSG_BUFFER_SIZE (512) +#endif + +/** Size of header of a vqueue message */ +#define RPMSG_VRING_HEADER_SIZE (16) +/** Available size of payload of a vqueue message */ +#define RPMSG_VRING_PAYLOAD_SIZE (RPMSG_BUFFER_SIZE - RPMSG_VRING_HEADER_SIZE) + +/** + * number of rpmsg buffer + * This means that a single call of rproc_virtio_notified(rvdev.vdev, VRING1_ID) + * will trigger VirtIOSerial::rxCallback() VRING_NUM_BUFFS times at maximum. + * A buffer handles VirtIOSerial::rxCallback() requires to be + * (RPMSG_VRING_PAYLOAD_SIZE * VRING_NUM_BUFFS) at minimum to prevent overflow. + */ +#ifndef VRING_NUM_BUFFS +#define VRING_NUM_BUFFS (16) +#endif +#define RPMSG_VRING_TOTAL_PAYLOAD_SIZE (RPMSG_VRING_PAYLOAD_SIZE * VRING_NUM_BUFFS) + +#endif // __OPENAMP_VIRTIO_CONFIG_H diff --git a/platform.txt b/platform.txt index 7e359536ca..b016d642ba 100644 --- a/platform.txt +++ b/platform.txt @@ -9,7 +9,7 @@ version=1.0.0 # STM compile variables # ---------------------- -compiler.stm.extra_include="-I{build.source.path}" "-I{build.core.path}/avr" "-I{build.core.path}/stm32" "-I{build.core.path}/stm32/LL" "-I{build.core.path}/stm32/usb" "-I{build.core.path}/stm32/usb/hid" "-I{build.core.path}/stm32/usb/cdc" "-I{build.system.path}/Drivers/{build.series}_HAL_Driver/Inc" "-I{build.system.path}/Drivers/{build.series}_HAL_Driver/Src" "-I{build.system.path}/{build.series}" "-I{build.system.path}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" "-I{build.system.path}/Middlewares/ST/STM32_USB_Device_Library/Core/Src" +compiler.stm.extra_include="-I{build.source.path}" "-I{build.core.path}/avr" "-I{build.core.path}/stm32" "-I{build.core.path}/stm32/LL" "-I{build.core.path}/stm32/usb" "-I{build.core.path}/stm32/OpenAMP" "-I{build.core.path}/stm32/usb/hid" "-I{build.core.path}/stm32/usb/cdc" "-I{build.system.path}/Drivers/{build.series}_HAL_Driver/Inc" "-I{build.system.path}/Drivers/{build.series}_HAL_Driver/Src" "-I{build.system.path}/{build.series}" "-I{build.system.path}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" "-I{build.system.path}/Middlewares/ST/STM32_USB_Device_Library/Core/Src" {build.virtio_extra_include} compiler.warning_flags=-w compiler.warning_flags.none=-w @@ -84,6 +84,10 @@ build.pid=0 # options here, since then the default would be a defined, but empty macro # that the preprocessor cannot detect. +# VirtIO RPMsg Serial Flags +build.virtio_flags=-DVIRTIOCON -DHAL_IPCC_MODULE_ENABLED -DNO_ATOMIC_64_SUPPORT -DMETAL_INTERNAL -DMETAL_MAX_DEVICE_REGIONS=2 -DVIRTIO_SLAVE_ONLY -D__LOG_TRACE_IO_ +build.virtio_extra_include="-I{build.system.path}/Middlewares/OpenAMP" "-I{build.system.path}/Middlewares/OpenAMP/open-amp/lib/include" "-I{build.system.path}/Middlewares/OpenAMP/libmetal/lib/include" "-I{build.system.path}/Middlewares/OpenAMP/virtual_driver" + # Build information's build.info.flags=-D{build.series} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DBOARD_NAME="{build.board}" @@ -91,6 +95,7 @@ build.info.flags=-D{build.series} -DARDUINO={runtime.ide.version} -DARDUINO_{bui build.xSerial=-DHAL_UART_MODULE_ENABLED build.enable_usb= build.usb_speed= +build.enable_virtio= build.startup_file= build.flags.fp= build.flags.optimize=-Os From 3faacd3cbd66a3c6be102db9bb0dde31308876e6 Mon Sep 17 00:00:00 2001 From: Bumsik Kim Date: Sat, 14 Mar 2020 20:02:50 +0900 Subject: [PATCH 4/7] [VirtIO] Add logging support for core_debug() --- cores/arduino/Print.cpp | 9 +- cores/arduino/VirtIOSerial.h | 1 - cores/arduino/stm32/OpenAMP/openamp_conf.h | 4 - cores/arduino/stm32/OpenAMP/openamp_log.c | 104 --------------- cores/arduino/stm32/OpenAMP/openamp_log.h | 138 -------------------- cores/arduino/stm32/OpenAMP/rsc_table.c | 14 +- cores/arduino/stm32/OpenAMP/virtio_config.h | 11 ++ cores/arduino/stm32/OpenAMP/virtio_log.c | 43 ++++++ cores/arduino/stm32/OpenAMP/virtio_log.h | 49 +++++++ platform.txt | 2 +- 10 files changed, 119 insertions(+), 256 deletions(-) delete mode 100644 cores/arduino/stm32/OpenAMP/openamp_log.c delete mode 100644 cores/arduino/stm32/OpenAMP/openamp_log.h create mode 100644 cores/arduino/stm32/OpenAMP/virtio_log.c create mode 100644 cores/arduino/stm32/OpenAMP/virtio_log.h diff --git a/cores/arduino/Print.cpp b/cores/arduino/Print.cpp index da2b7c6f5d..b1dd901bca 100644 --- a/cores/arduino/Print.cpp +++ b/cores/arduino/Print.cpp @@ -28,6 +28,10 @@ #include "Print.h" +#if defined (VIRTIO_LOG) +#include "virtio_log.h" +#endif + // Public Methods ////////////////////////////////////////////////////////////// /* default implementation: may be overridden */ @@ -203,10 +207,13 @@ extern "C" { switch (file) { case STDOUT_FILENO: case STDERR_FILENO: -#if defined(HAL_UART_MODULE_ENABLED) && !defined(HAL_UART_MODULE_ONLY) /* Used for core_debug() */ +#if defined (VIRTIO_LOG) + virtio_log((uint8_t *)ptr, (uint32_t)len); +#elif defined(HAL_UART_MODULE_ENABLED) && !defined(HAL_UART_MODULE_ONLY) uart_debug_write((uint8_t *)ptr, (uint32_t)len); #endif + break; case STDIN_FILENO: break; default: diff --git a/cores/arduino/VirtIOSerial.h b/cores/arduino/VirtIOSerial.h index 010e863249..416ad3dc24 100644 --- a/cores/arduino/VirtIOSerial.h +++ b/cores/arduino/VirtIOSerial.h @@ -27,7 +27,6 @@ #if defined (VIRTIOCON) #include "Stream.h" #include "openamp.h" -#include "openamp_log.h" #include "wiring.h" #include "virtio_buffer.h" diff --git a/cores/arduino/stm32/OpenAMP/openamp_conf.h b/cores/arduino/stm32/OpenAMP/openamp_conf.h index 140709dcdf..0d1fd35954 100644 --- a/cores/arduino/stm32/OpenAMP/openamp_conf.h +++ b/cores/arduino/stm32/OpenAMP/openamp_conf.h @@ -27,10 +27,6 @@ extern "C" { #endif -/* Includes ------------------------------------------------------------------*/ -#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_) -#include "openamp_log.h" -#endif /** * Note: Do not remove this. Removing this might not trigger compile error but * the configuration can be significantly different. diff --git a/cores/arduino/stm32/OpenAMP/openamp_log.c b/cores/arduino/stm32/OpenAMP/openamp_log.c deleted file mode 100644 index e2368c2242..0000000000 --- a/cores/arduino/stm32/OpenAMP/openamp_log.c +++ /dev/null @@ -1,104 +0,0 @@ -/** - ****************************************************************************** - * @file log.c - * @author MCD Application Team - * @brief Ressource table - * - * This file provides services for logging - * - ****************************************************************************** - * - * @attention - * - *

© Copyright (c) 2019 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under BSD 3-Clause license, - * the "License"; You may not use this file except in compliance with the - * License. You may obtain a copy of the License at: - * opensource.org/licenses/BSD-3-Clause - * - * - ****************************************************************************** - */ -#ifdef VIRTIOCON -/** @addtogroup LOG - * @{ - */ - -/** @addtogroup STM32MP1xx_log - * @{ - */ - -/** @addtogroup STM32MP1xx_Log_Private_Includes - * @{ - */ -#include "openamp_log.h" -/** - * @} - */ - -/** @addtogroup STM32MP1xx_Log_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32MP1xx_Log_Private_Defines - * @{ - */ - -/** - * @} - */ - -#if defined (__LOG_TRACE_IO_) -char system_log_buf[SYSTEM_TRACE_BUF_SZ]; - -__weak void log_buff(int ch) -{ - /* Place your implementation of fputc here */ - /* e.g. write a character to the USART1 and Loop until the end of transmission */ - static int offset = 0; - - if (offset + 1 >= SYSTEM_TRACE_BUF_SZ) { - offset = 0; - } - - system_log_buf[offset] = ch; - system_log_buf[offset++ + 1] = '\0'; -} - -#endif - -#if defined ( __CC_ARM) || (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) -#define PUTCHAR_PROTOTYPE int stdout_putchar(int ch) -#elif __GNUC__ -/* With GCC/RAISONANCE, small log_info (option LD Linker->Libraries->Small log_info - set to 'Yes') calls __io_putchar() */ -#define PUTCHAR_PROTOTYPE int __attribute__(( weak )) __io_putchar(int ch) -#else -#define PUTCHAR_PROTOTYPE int __attribute__(( weak )) fputc(int ch, FILE *f) -#endif /* __GNUC__ */ - -#if defined (__LOG_UART_IO_) || defined (__LOG_TRACE_IO_) -PUTCHAR_PROTOTYPE { - /* Place your implementation of fputc here */ - /* e.g. write a character to the USART1 and Loop until the end of transmission */ -#if defined (__LOG_UART_IO_) - extern UART_HandleTypeDef huart; - HAL_UART_Transmit(&huart, (uint8_t *)&ch, 1, HAL_MAX_DELAY); -#endif -#if defined (__LOG_TRACE_IO_) - log_buff(ch); -#endif - return ch; -} -#else -/* No printf output */ -#endif - -#endif /* VIRTIOCON */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file diff --git a/cores/arduino/stm32/OpenAMP/openamp_log.h b/cores/arduino/stm32/OpenAMP/openamp_log.h deleted file mode 100644 index 06475dcd47..0000000000 --- a/cores/arduino/stm32/OpenAMP/openamp_log.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - ****************************************************************************** - * @file log.h - * @author MCD Application Team - * @brief logging services - ****************************************************************************** - * - * @attention - * - *

© Copyright (c) 2019 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under BSD 3-Clause license, - * the "License"; You may not use this file except in compliance with the - * License. You may obtain a copy of the License at: - * opensource.org/licenses/BSD-3-Clause - * - * - ****************************************************************************** - */ - -/** @addtogroup LOG - * @{ - */ - -/** @addtogroup stm32mp1xx_Log - * @{ - */ - -/** - * @brief Define to prevent recursive inclusion - */ -#ifndef __LOG_STM32MP1XX_H -#define __LOG_STM32MP1XX_H - -#ifdef VIRTIOCON - -#ifdef __cplusplus -extern "C" { -#endif - -/** @addtogroup STM32MP1xx_Log_Includes - * @{ - */ -#include "stm32_def.h" -/** - * @} - */ - -/** @addtogroup STM32MP1xx_Log_Exported_Constants - * @{ - */ -#if defined (__LOG_TRACE_IO_) -#define SYSTEM_TRACE_BUF_SZ 2048 -#endif - -#define LOGQUIET 0 -#define LOGERR 1 -#define LOGWARN 2 -#define LOGINFO 3 -#define LOGDBG 4 - -#ifndef LOGLEVEL -#define LOGLEVEL LOGINFO -#endif - - -/** - * @} - */ - -/** @addtogroup STM32MP1xx_Log_Exported_types - * @{ - */ -#if defined (__LOG_TRACE_IO_) -extern char system_log_buf[SYSTEM_TRACE_BUF_SZ]; /*!< buffer for debug traces */ -#endif /* __LOG_TRACE_IO_ */ -/** - * @} - */ - -/** @addtogroup STM32MP1xx_Log_Exported_Macros - * @{ - */ -#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_) -#if LOGLEVEL >= LOGDBG -#define log_dbg(fmt, ...) printf("[%05ld.%03ld][DBG ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__) -#else -#define log_dbg(fmt, ...) -#endif -#if LOGLEVEL >= LOGINFO -#define log_info(fmt, ...) printf("[%05ld.%03ld][INFO ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__) -#else -#define log_info(fmt, ...) -#endif -#if LOGLEVEL >= LOGWARN -#define log_warn(fmt, ...) printf("[%05ld.%03ld][WARN ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__) -#else -#define log_warn(fmt, ...) -#endif -#if LOGLEVEL >= LOGERR -#define log_err(fmt, ...) printf("[%05ld.%03ld][ERR ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__) -#else -#define log_err(fmt, ...) -#endif -#else -#define log_dbg(fmt, ...) -#define log_info(fmt, ...) -#define log_warn(fmt, ...) -#define log_err(fmt, ...) -#endif /* __LOG_TRACE_IO_ */ -/** - * @} - */ - -/** @addtogroup STM32MP1xx_Log_Exported_Functions - * @{ - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* VIRTIOCON */ -#endif /*__LOG_STM32MP1XX_H */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/OpenAMP/rsc_table.c b/cores/arduino/stm32/OpenAMP/rsc_table.c index 8b38114380..ed1078661b 100644 --- a/cores/arduino/stm32/OpenAMP/rsc_table.c +++ b/cores/arduino/stm32/OpenAMP/rsc_table.c @@ -31,13 +31,13 @@ /* VirtIO rpmsg device id */ #define VIRTIO_ID_RPMSG 7 -#if defined (__LOG_TRACE_IO_) -extern char system_log_buf[]; +#if defined (VIRTIO_LOG) +extern char virtio_log_buffer[]; #endif const struct shared_resource_table __attribute__((__section__(".resource_table"))) __attribute__((used)) resource_table = { .version = 1, -#if defined (__LOG_TRACE_IO_) +#if defined (VIRTIO_LOG) .num = 2, #else .num = 1, @@ -74,13 +74,13 @@ const struct shared_resource_table __attribute__((__section__(".resource_table") .notifyid = VRING1_ID, .reserved = 0 }, -#if defined (__LOG_TRACE_IO_) +#if defined (VIRTIO_LOG) .cm_trace = { .type = RSC_TRACE, - .da = (uint32_t)system_log_buf, - .len = SYSTEM_TRACE_BUF_SZ, + .da = (uint32_t)virtio_log_buffer, + .len = VIRTIO_LOG_BUFFER_SIZE, .reserved = 0, - .name = "arduino_core_debug", + .name = "arduino_log", }, #endif } ; diff --git a/cores/arduino/stm32/OpenAMP/virtio_config.h b/cores/arduino/stm32/OpenAMP/virtio_config.h index da931c5a9b..4ca823ea36 100644 --- a/cores/arduino/stm32/OpenAMP/virtio_config.h +++ b/cores/arduino/stm32/OpenAMP/virtio_config.h @@ -28,4 +28,15 @@ #endif #define RPMSG_VRING_TOTAL_PAYLOAD_SIZE (RPMSG_VRING_PAYLOAD_SIZE * VRING_NUM_BUFFS) +#if defined (VIRTIO_LOG) +/** + * OpenAMP trace (log) buffer configuration. + * Users are free to redefine the size if needed. + */ +#ifndef VIRTIO_LOG_BUFFER_SIZE +#define VIRTIO_LOG_BUFFER_SIZE (2048) +#endif + +#endif + #endif // __OPENAMP_VIRTIO_CONFIG_H diff --git a/cores/arduino/stm32/OpenAMP/virtio_log.c b/cores/arduino/stm32/OpenAMP/virtio_log.c new file mode 100644 index 0000000000..c20c21ae21 --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/virtio_log.c @@ -0,0 +1,43 @@ +/** + * MIT License: + * Copyright (c) 2020 Bumsik kim + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#if defined(VIRTIOCON) && defined(VIRTIO_LOG) + +#include "virtio_config.h" +#include "virtio_log.h" + +char virtio_log_buffer[VIRTIO_LOG_BUFFER_SIZE]; + +void virtio_log(uint8_t *data, uint32_t size) +{ + static int offset = 0; + + for (uint32_t i = 0; i < size; i++) { + virtio_log_buffer[offset++] = *(data + i); + if ((offset + 1) >= VIRTIO_LOG_BUFFER_SIZE) { + offset = 0; + } + } + virtio_log_buffer[offset] = '\0'; +} + +#endif diff --git a/cores/arduino/stm32/OpenAMP/virtio_log.h b/cores/arduino/stm32/OpenAMP/virtio_log.h new file mode 100644 index 0000000000..6c29c1ae6a --- /dev/null +++ b/cores/arduino/stm32/OpenAMP/virtio_log.h @@ -0,0 +1,49 @@ +/** + * MIT License: + * Copyright (c) 2020 Bumsik kim + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef __OPENAMP_VIRTIO_LOG_H +#define __OPENAMP_VIRTIO_LOG_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Write data to the OpenAMP trace buffer + * @note By writing OpenAMP trace (log) buffer here, the Linux host can access + * to the content by the following command: + * $ cat /sys/kernel/debug/remoteproc/remoteproc0/trace0 + * @note When the buffer overflows (2kb by default, configurable.), + * the buffer is cleaned by a null character. Consider increasing + * VIRTIO_LOG_BUFFER_SIZE if a larger log buffer is needed. + * @param data: Data to send + * @param size: size of data + */ +void virtio_log(uint8_t *data, uint32_t size); + +#ifdef __cplusplus +} +#endif + +#endif // __OPENAMP_VIRTIO_LOG_H diff --git a/platform.txt b/platform.txt index b016d642ba..f9109293f1 100644 --- a/platform.txt +++ b/platform.txt @@ -85,7 +85,7 @@ build.pid=0 # that the preprocessor cannot detect. # VirtIO RPMsg Serial Flags -build.virtio_flags=-DVIRTIOCON -DHAL_IPCC_MODULE_ENABLED -DNO_ATOMIC_64_SUPPORT -DMETAL_INTERNAL -DMETAL_MAX_DEVICE_REGIONS=2 -DVIRTIO_SLAVE_ONLY -D__LOG_TRACE_IO_ +build.virtio_flags=-DVIRTIOCON -DHAL_IPCC_MODULE_ENABLED -DNO_ATOMIC_64_SUPPORT -DMETAL_INTERNAL -DMETAL_MAX_DEVICE_REGIONS=2 -DVIRTIO_SLAVE_ONLY -DVIRTIO_LOG build.virtio_extra_include="-I{build.system.path}/Middlewares/OpenAMP" "-I{build.system.path}/Middlewares/OpenAMP/open-amp/lib/include" "-I{build.system.path}/Middlewares/OpenAMP/libmetal/lib/include" "-I{build.system.path}/Middlewares/OpenAMP/virtual_driver" # Build information's From 29b6c7d427b1b33cc89ea9b02e2b0b41c24f3ec3 Mon Sep 17 00:00:00 2001 From: Bumsik Kim Date: Sat, 9 Nov 2019 03:02:22 +0900 Subject: [PATCH 5/7] [STM32MP157_DK] Add SERIAL_PORT_LINUXBRIDGE as SerialVirtIO --- variants/STM32MP157_DK/variant.h | 1 + 1 file changed, 1 insertion(+) diff --git a/variants/STM32MP157_DK/variant.h b/variants/STM32MP157_DK/variant.h index 8acc778e07..d94a9c0936 100644 --- a/variants/STM32MP157_DK/variant.h +++ b/variants/STM32MP157_DK/variant.h @@ -178,6 +178,7 @@ extern "C" { // pins are NOT connected to anything by default. #define SERIAL_PORT_MONITOR Serial #define SERIAL_PORT_HARDWARE Serial +#define SERIAL_PORT_LINUXBRIDGE SerialVirtIO #endif #endif /* _VARIANT_ARDUINO_STM32_ */ From f7c1d95f5fb97d4be580467e4d4f340fba7bc5fe Mon Sep 17 00:00:00 2001 From: Alexandre Bourdiol Date: Tue, 28 Jan 2020 15:41:07 +0100 Subject: [PATCH 6/7] [STM32MP157_DK] README: Add VirtIO --- variants/STM32MP157_DK/README.md | 150 +++++++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 5 deletions(-) diff --git a/variants/STM32MP157_DK/README.md b/variants/STM32MP157_DK/README.md index ac6c453883..c5b0f79c25 100644 --- a/variants/STM32MP157_DK/README.md +++ b/variants/STM32MP157_DK/README.md @@ -43,7 +43,8 @@ In this example, the user **must** upload `/run_ardui After uploading the user can use `sh run_arduino_.sh start` in the console of host Linux via either SSH or Serial Console, to run the Arduino firmware. #### Note - * `sh run_arduino_.sh start` is a one-shot command, the Arduino firmware only runs for the current boot. If you want to make it run after reboot, you need to use `sh run_arduino_.sh install` command. + +* `sh run_arduino_.sh start` is a one-shot command, the Arduino firmware only runs for the current boot. If you want to make it run after reboot, you need to use `sh run_arduino_.sh install` command. `run_arduino_.sh` help page summary: @@ -63,6 +64,21 @@ After uploading the user can use `sh run_arduino_.sh start` in the sh run_arduino_.sh uninstall Uninstall the autostart service. + sh run_arduino_.sh monitor + Monitor data received from the coprocessor via the virtual serial. + + sh run_arduino_.sh send-msg + Send a message to the coprocessor via the virtual serial. + + sh run_arduino_.sh send-file + Send a file content to the coprocessor via the virtual serial. + + sh run_arduino_.sh minicom + Launch minicom interactive serial communication program. + + sh run_arduino_.sh log + Print debugging log in OpenAMP trace buffer. + sh run_arduino_.sh stop Stop the coprocessor. @@ -73,6 +89,122 @@ See the source code [run_arduino_gen.sh] for the full help page and the more det [run_arduino_gen.sh] is the shell script that produces a copy of the script called `run_arduino_.sh` but with the sketch binary self-contained. +## Virtual Serial + +With Virtual Serial, you can easily implement inter-core communication between the Linux host and Arduino coprocessor. Virtual Serial uses OpenAMP rpmsg framework. This is available as `SerialVirtIO` object and you can use it as a standard Arduino Serial object. + +Enable `SerialVirtIO` in Arduino IDE->Tools->Virtual serial support. You can optionally alias generic `Serial` object with `SerialVirtIO` as well. + +When enabled, `/dev/ttyRPMSG0` is available to the Linux host. You can use it as a normal serial tty. `sh run_arduino_.sh` provides `monitor`, `minicom`, `send-msg`, `send-file` as a convenience. See above command descriptions. + +See [OpenAMP] and [Linux RPMsg] to learn more. + +### Configuration + +To increase the performance of SerialVirtIO you can resize the related buffer configurations. There are three definitions you can use: + +* [`VRING_NUM_BUFFS`](/cores/arduino/stm32/OpenAMP/virtio_config.h) +* [`RPMSG_BUFFER_SIZE`](/cores/arduino/stm32/OpenAMP/virtio_config.h) +* [`VIRTIO_BUFFER_SIZE`](/cores/arduino/stm32/OpenAMP/virtio_buffer.h) + +The recommended option is to resize `VRING_NUM_BUFFS`. Be very cautious when resizing `RPMSG_BUFFER_SIZE`, which must be matched with the Linux kernel definition. Also `VIRTIO_BUFFER_SIZE` has the minimum required size depending on the other two. See their links above for further descriptions. + +To redefine these definitions, see how to create `build_opt.h` described in Debugging section below. + +### Virtual Serial Example + +Here is a basic echo example: +```cpp +int available; +char buffer[1024]; + +unsigned long time = 0; + +void setup() { + // You can SerialVirtIO.begin() and use SerialVirtIO later instead. + Serial.begin(); // You don't need to configure speed, it is ignored. + pinMode(LED_BUILTIN, OUTPUT); +} + +void loop() { + available = Serial.available(); + while (available > 0) { + int size = min(available, Serial.availableForWrite()); + Serial.readBytes(buffer, size); + Serial.write(buffer, size); + available -= size; + } + + // Heartbeat. If Arduino stops the LED won't flash anymore. + if ((millis() - time) > 1000) { + time = millis(); + digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); + } +} +``` + +Note the use of `Serial.availableForWrite()`. SerialVirtIO has [a hard restriction of the write size], so it is important to `Serial.write()` less than the value of `Serial.availableForWrite()`. + +After loading Arduino, You can use SerialVirtIO in two ways in this example: + +* Run `sh run_arduino_.sh minicom` and type anything in the minicom console. The console will print out what you type immediately. + +* Open two Linux consoles (using SSH) + 1. In the first console, run `sh run_arduino_.sh monitor` + 2. In the second console, run `sh run_arduino_.sh send-msg ` or `sh run_arduino_.sh send-file `, the first console will print the content of the message. + +## Debugging + +For printf-style debugging, `core_debug()` is highly recommended instead of using Arduino Serial. In STM32MP1, `core_debug()` utilizes OpenAMP trace buffer and it has a minimal real-time impact (other than the overhead of printf) because it is not bound to the speed of a hardware IO peripheral while printing it. + +Create [build_opt.h] in the sketch directory and simply put `-DCORE_DEBUG`. Additionally you can resize the buffer size of logging by redefining `VIRTIO_LOG_BUFFER_SIZE` (2kb by default). As an example you can create a file like the following: + +``` +build_opt.h (in the same directory of your Sketch) +----------------------------- + +-DCORE_DEBUG +-DVIRTIO_LOG_BUFFER_SIZE=4086 +``` + +Don't forget to change any of Arduino IDE option to reflect this as in the warning section in [build_opt.h description in wiki]. This is important because if `-DCORE_DEBUG` is not configured correctly `core_debug()` silently becomes an empty function without triggering any build error. Don't forget to add `#include "core_debug.h"` in your code in order to use `core_debug()`. + +Also, you must enable the Virtual Serial (described in the above section) and include `SerialVirtIO.begin();` in your Arduino sketch, because this logging feature is tightly coupled to OpenAMP virtio. + +You can use `sh run_arduino_.sh log` command or `cat /sys/kernel/debug/remoteproc/remoteproc0/trace0` command to print out the debug log in the Linux host. + +Note that when overflow occurs the trace buffer is re-written from the beginning, removing existing logs. Consider increasing `VIRTIO_LOG_BUFFER_SIZE` in this case, as mentioned above. + +See [virtio_log.h] for more information. + +### Debugging Example + +Here is a basic blink example with `core_debug()`: +```cpp +#include "core_debug.h" + +unsigned long time = 0; +unsigned long count = 1; + +void setup() { + // You must enable SerialVirtIO to use core_debug(), even if you don't use SerialVirtIO. + SerialVirtIO.begin(); + pinMode(LED_BUILTIN, OUTPUT); +} + +void loop() { + if ((millis() - time) > 1000) { + time = millis(); + core_debug("%u seconds\n", count++); + digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); + } +} +``` + +Don't forget to add [build_opt.h] described above. + +After loading Arduino, you can simply `sh run_arduino_.sh log` to print the current `core_debug()` logs. + ## Pin mapping The boards have two pin headers: Raspberry Pi HAT headers and Arduino shield headers. This project currently supports Arduino Shield headers only, leaving RPi HAT headers for the Linux applications. @@ -108,7 +240,7 @@ There are additional pins for LEDs and buttons. | PA_13 | 17 / LED_RED | USER2_BTN | Active Low, LED LD6, also connected to B4 button | | PH_7 | 18 / LED_ORANGE / LED_BUILTIN | | Active High, LED LD7 | -[`variant.h` of the board](https://github.com/stm32duino/Arduino_Core_STM32/tree/master/variants/STM32MP157_DK/variant.h) has the complete information about the pinouts. +[`variant.h` of the board] has the complete information about the pinouts. ## Uploading @@ -152,9 +284,8 @@ And then the Device Tree should enable TIM1 for the coprocessor, although this d ## Limitations * Ethernet and USB are not supported. Use them in the Linux host. -* Currently there is no easy way for communication between the Linux host and Arduino coprocessor. There is ongoing work for virtual serial communications using OpenAMP rpmsg framework. Currently one possible way is to wire between UART7 (Arduino SCL/SDA pins) and USART3 (Linux RPi HAT GPIO14/GPIO15 pins), however, users should manually modify [Linux Device tree to enable `usart3` and recompile it](usart3). * I2C pins on Raspberry Pi HAT header (GPIO2 and GPIO3) are not available in Linux host. This is because the Discovery board shares I2C pins on Arduino header and those on the HAT header. -* [Early firmware loading from U-Boot stage] is not supported. Only firmware loading on Linux boot stage by systemd supported. The binary itself may be loaded by U-Boot without any problems, but there is no out-of-box tool to configure U-Boot to load the firmware using Arduino IDE yet. +* [Early firmware loading from U-Boot stage] is not supported. Only firmware loading on Linux boot stage by systemd (aka. `sh run_arduino_.sh install`) supported. The binary itself may be loaded by U-Boot without any problems, but there is no out-of-box tool to configure U-Boot to load the firmware using Arduino IDE yet. * EEPROM library: Those devices do not have non-volatile memory. The emulation is done using RETRAM. Therefore data will be preserved *only* when VBAT is supplied (e.g. A coin battery is connected to CN3 on STM32MP157A_DK1) and the coprocessor is waken up from sleep. This implies that cold boot the board may cause data loss, even if VBAT is supplied. See [discussions on RETRAM] for more detail. @@ -170,11 +301,20 @@ And then the Device Tree should enable TIM1 for the coprocessor, although this d [run_arduino_gen.sh]: https://github.com/stm32duino/Arduino_Tools/blob/master/run_arduino_gen.sh +[OpenAMP]: https://github.com/OpenAMP/open-amp/wiki/OpenAMP-Overview +[Linux RPMsg]: https://wiki.st.com/stm32mpu/wiki/Linux_RPMsg_framework_overview +[a hard restriction of the write size]: /cores/arduino/VirtIOSerial.cpp#L148 + +[build_opt.h]: https://github.com/stm32duino/wiki/wiki/Customize-build-options-using-build_opt.h +[build_opt.h description in wiki]: https://github.com/stm32duino/wiki/wiki/Customize-build-options-using-build_opt.h +[virtio_log.h]: /cores/arduino/stm32/OpenAMP/virtio_log.h + +[`variant.h` of the board]: /variants/STM32MP157_DK/variant.h + [The ST Wiki page on C-Kermit]: https://wiki.st.com/stm32mpu/wiki/How_to_transfer_a_file_over_serial_console [a bug in OpenSTLinux]: https://community.st.com/s/question/0D50X0000B9vHa4/cannot-get-download-a-file-using-kermit [stm32mp157c-dk2-m4-examples.dts]: https://github.com/STMicroelectronics/meta-st-stm32mp/blob/d8cbac759e1275b1a27d4ba38b64a0d83d0e8c9f/recipes-kernel/linux/linux-stm32mp/4.19/4.19.49/0029-ARM-stm32mp1-r2-DEVICETREE.patch#L4334 -[usart3]: https://github.com/STMicroelectronics/meta-st-stm32mp/blob/d8cbac759e1275b1a27d4ba38b64a0d83d0e8c9f/recipes-kernel/linux/linux-stm32mp/4.19/4.19.49/0029-ARM-stm32mp1-r2-DEVICETREE.patch#L4274 [Early firmware loading from U-Boot stage]: https://wiki.st.com/stm32mpu/wiki/How_to_start_the_coprocessor_from_the_bootloader [discussions on RETRAM]: https://community.st.com/s/question/0D50X0000B44pHUSQY/doesnt-the-mcu-coprocessor-have-nonvolatile-memory From a6dcefeb3ad1a4cc259e01f2113dfd5d6e9cbe0c Mon Sep 17 00:00:00 2001 From: Bumsik Kim Date: Wed, 4 Mar 2020 23:40:46 +0900 Subject: [PATCH 7/7] [CI] Add virtio in CI builds --- CI/build/conf/cores_config.json | 8 ++++++++ CI/build/conf/cores_config_ci.json | 8 ++++++++ CI/build/conf/cores_config_travis.json | 8 ++++++++ CI/build/examples/BareMinimum/BareMinimum.ino | 3 ++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CI/build/conf/cores_config.json b/CI/build/conf/cores_config.json index 3b57a8331e..8e152b82eb 100644 --- a/CI/build/conf/cores_config.json +++ b/CI/build/conf/cores_config.json @@ -11,6 +11,14 @@ { "name": "STEVAL_MKSBOX1V1", "options": "usb=CDCgen" + }, + { + "name": "STM32MP157A_DK1", + "options": "virtio=enabled" + }, + { + "name": "STM32MP157C_DK2", + "options": "virtio=generic" } ], "sketches": [ diff --git a/CI/build/conf/cores_config_ci.json b/CI/build/conf/cores_config_ci.json index fadf93e7d6..23a436db43 100644 --- a/CI/build/conf/cores_config_ci.json +++ b/CI/build/conf/cores_config_ci.json @@ -11,6 +11,14 @@ { "name": "STEVAL_MKSBOX1V1", "options": "usb=CDCgen" + }, + { + "name": "STM32MP157A_DK1", + "options": "virtio=enabled" + }, + { + "name": "STM32MP157C_DK2", + "options": "virtio=generic" } ], "sketches": [ diff --git a/CI/build/conf/cores_config_travis.json b/CI/build/conf/cores_config_travis.json index be1cad29a3..ae87b824af 100644 --- a/CI/build/conf/cores_config_travis.json +++ b/CI/build/conf/cores_config_travis.json @@ -7,6 +7,14 @@ { "name": "NUCLEO_L031K6", "options": "opt=oslto" + }, + { + "name": "STM32MP157A_DK1", + "options": "virtio=enabled" + }, + { + "name": "STM32MP157C_DK2", + "options": "virtio=generic" } ], "sketches": [ diff --git a/CI/build/examples/BareMinimum/BareMinimum.ino b/CI/build/examples/BareMinimum/BareMinimum.ino index 9fdfe0df4e..1e39c262d8 100644 --- a/CI/build/examples/BareMinimum/BareMinimum.ino +++ b/CI/build/examples/BareMinimum/BareMinimum.ino @@ -42,7 +42,8 @@ SoftwareSerial swSerial(10, 11); void setup() { // Serial HW & SW -#if !defined(USBD_USE_CDC) && !defined(DISABLE_GENERIC_SERIALUSB) +#if (!defined(USBD_USE_CDC) && !defined(DISABLE_GENERIC_SERIALUSB)) &&\ + (!defined(VIRTIOCON) && !defined(DISABLE_GENERIC_SERIALVIRTIO)) Serial.setRx(PIN_SERIAL_RX); Serial.setTx(digitalPinToPinName(PIN_SERIAL_TX)); #endif