diff options
Diffstat (limited to 'bsp')
291 files changed, 38002 insertions, 1631 deletions
diff --git a/bsp/ls2kdev/drivers/board.c b/bsp/ls2kdev/drivers/board.c index 6a66777121..30fb59091a 100644 --- a/bsp/ls2kdev/drivers/board.c +++ b/bsp/ls2kdev/drivers/board.c @@ -16,15 +16,22 @@ #include "exception.h" #include "drv_uart.h" #include "board.h" +#include "ls2k1000.h" + /** * this function will reset CPU * */ void rt_hw_cpu_reset(void) { + WDT_EN = 0x01; + WDT_TIMER = 0x01; + WDT_SET = 0x01; rt_kprintf("reboot system...\n"); while (1); } +MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset cpu); + /** * this function will shutdown CPU @@ -32,10 +39,13 @@ void rt_hw_cpu_reset(void) */ void rt_hw_cpu_shutdown(void) { + PM1_STS &= 0xffffffff; + PM1_CNT = 0x3c00; rt_kprintf("shutdown...\n"); while (1); } +MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_shutdown, poweroff, shutdown cpu); /** diff --git a/bsp/ls2kdev/drivers/ls2k1000.h b/bsp/ls2kdev/drivers/ls2k1000.h index 38e83875fb..668d484d9c 100644 --- a/bsp/ls2kdev/drivers/ls2k1000.h +++ b/bsp/ls2kdev/drivers/ls2k1000.h @@ -3,6 +3,7 @@ #include <mips.h> #include "interrupt.h" +#include <rthw.h> #define APB_BASE CKSEG1ADDR(0xbfe00000) @@ -24,6 +25,28 @@ #define GEN_CONFIG0_REG (0xFFFFFFFFBfe10420) + +/* + * General PM Configuration Register + */ +#define PMCON_BASE (APB_BASE | (0x7 << 12)) + +/* + * Power Management1 Configuration Registers + */ +#define PM1_BASE (PMCON_BASE + 0x0C) +#define PM1_STS HWREG32(PM1_BASE) +#define PM1_EN HWREG32(PM1_BASE + 0x04) +#define PM1_CNT HWREG32(PM1_BASE + 0x08) + +/* + * Watch Dog Configuration Registers + */ +#define WDT_BASE (PMCON_BASE + 0x30) +#define WDT_EN HWREG32(WDT_BASE) +#define WDT_SET HWREG32(WDT_BASE + 0x04) +#define WDT_TIMER HWREG32(WDT_BASE + 0x08) + void rt_hw_timer_handler(void); void rt_hw_uart_init(void); diff --git a/bsp/nrf5x/libraries/drivers/SConscript b/bsp/nrf5x/libraries/drivers/SConscript index 2b29998d75..f8629162f2 100644 --- a/bsp/nrf5x/libraries/drivers/SConscript +++ b/bsp/nrf5x/libraries/drivers/SConscript @@ -32,6 +32,9 @@ if GetDepend(['BSP_USING_PWM']): if GetDepend(['BSP_USING_WDT']): src += ['drv_wdt.c'] +if GetDepend(['BSP_USING_ONCHIP_RTC']): + src += ['drv_rtc.c'] + path = [cwd] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) diff --git a/bsp/nrf5x/libraries/drivers/drv_rtc.c b/bsp/nrf5x/libraries/drivers/drv_rtc.c new file mode 100644 index 0000000000..e7a7359523 --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/drv_rtc.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-09-08 Chenyingchun first version + */ + +#include "board.h" +#include <rtthread.h> +#include <rtdevice.h> + +#include <nrfx_rtc.h> +#include <nrfx_clock.h> + +#ifdef BSP_USING_ONCHIP_RTC + +#define LOG_TAG "drv.rtc" +#define DBG_LVL DBG_LOG +#include <rtdbg.h> + +/* 2018-01-30 14:44:50 = RTC_TIME_INIT(2018, 1, 30, 14, 44, 50) */ +#define RTC_TIME_INIT(year, month, day, hour, minute, second) \ + {.tm_year = year - 1900, .tm_mon = month - 1, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second} + +#ifndef ONCHIP_RTC_TIME_DEFAULT +#define ONCHIP_RTC_TIME_DEFAULT RTC_TIME_INIT(2018, 1, 1, 0, 0 ,0) +#endif + +#ifndef RTC_INSTANCE_ID +#define RTC_INSTANCE_ID (2) +#endif + +#define TICK_FREQUENCE_HZ (RT_TICK_PER_SECOND) // RTC tick frequence, in HZ + +static struct rt_device rtc; +static time_t init_time; +static uint32_t tick = 0; + +static void rtc_callback(nrfx_rtc_int_type_t int_type) +{ + static uint32_t count = 0; + + if (int_type == NRFX_RTC_INT_TICK) + { + count++; + if((count % TICK_FREQUENCE_HZ) == 0) + { + tick++; + } + } +} + +static rt_err_t rt_rtc_config(struct rt_device *dev) +{ + #define SYSTICK_CLOCK_HZ (32768UL) + #define RTC_PRESCALER ((uint32_t) (NRFX_ROUNDED_DIV(SYSTICK_CLOCK_HZ, TICK_FREQUENCE_HZ) - 1)) + + const nrfx_rtc_t rtc_instance = NRFX_RTC_INSTANCE(RTC_INSTANCE_ID); + nrf_clock_lf_src_set(NRF_CLOCK, (nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC); + nrfx_clock_lfclk_start(); + + //Initialize RTC instance + nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG; + config.prescaler = RTC_PRESCALER; + + nrfx_rtc_init(&rtc_instance, &config, rtc_callback); + + nrfx_rtc_tick_enable(&rtc_instance, true); + + //Power on RTC instance + nrfx_rtc_enable(&rtc_instance); + + return RT_EOK; +} + +static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args) +{ + time_t *time; + RT_ASSERT(dev != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + { + time = (time_t *) args; + *time = init_time + tick; + break; + } + case RT_DEVICE_CTRL_RTC_SET_TIME: + { + time = (time_t *) args; + init_time = *time - tick; + break; + } + } + return RT_EOK; +} + + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rtc_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + rt_rtc_control +}; +#endif + +static rt_err_t rt_hw_rtc_register(rt_device_t device, const char *name, rt_uint32_t flag) +{ + struct tm time_new = ONCHIP_RTC_TIME_DEFAULT; + + RT_ASSERT(device != RT_NULL); + + init_time = mktime(&time_new); + if (rt_rtc_config(device) != RT_EOK) + { + return -RT_ERROR; + } +#ifdef RT_USING_DEVICE_OPS + device->ops = &rtc_ops; +#else + device->init = RT_NULL; + device->open = RT_NULL; + device->close = RT_NULL; + device->read = RT_NULL; + device->write = RT_NULL; + device->control = rt_rtc_control; +#endif + device->type = RT_Device_Class_RTC; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + device->user_data = RT_NULL; + + /* register a character device */ + rt_device_register(device, name, flag); + + return RT_EOK; +} + +int rt_hw_rtc_init(void) +{ + rt_err_t result; + result = rt_hw_rtc_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR); + if (result != RT_EOK) + { + LOG_E("rtc register err code: %d", result); + return result; + } + LOG_D("rtc init success"); + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_rtc_init); + +#endif /* BSP_USING_ONCHIP_RTC */ + diff --git a/bsp/nrf5x/nrf52832/board/Kconfig b/bsp/nrf5x/nrf52832/board/Kconfig index 80756b5372..41a3aa6c39 100644 --- a/bsp/nrf5x/nrf52832/board/Kconfig +++ b/bsp/nrf5x/nrf52832/board/Kconfig @@ -313,6 +313,39 @@ endif int default 1 endif + + menuconfig BSP_USING_ONCHIP_RTC + bool "Enable RTC" + select RT_USING_RTC + select RT_USING_LIBC + default n + if BSP_USING_ONCHIP_RTC + config NRFX_CLOCK_ENABLED + int + default 1 + config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY + int + default 7 + config NRFX_RTC_ENABLED + int + default 1 + config NRFX_RTC0_ENABLED + int + default 1 + config NRFX_RTC1_ENABLED + int + default 1 + config NRFX_RTC2_ENABLED + int + default 1 + config RTC_INSTANCE_ID + int + default 2 + config RTC_INSTANCE_ID + int "select RTC instance id, must be 0, 1, 2" + range 0 2 + default 2 + endif endmenu endmenu diff --git a/bsp/nrf5x/nrf52840/board/Kconfig b/bsp/nrf5x/nrf52840/board/Kconfig index 1a3fd7d8ba..9ec3b5c71f 100644 --- a/bsp/nrf5x/nrf52840/board/Kconfig +++ b/bsp/nrf5x/nrf52840/board/Kconfig @@ -346,8 +346,41 @@ menu "On-chip Peripheral Drivers" int default 1 endif -endmenu + menuconfig BSP_USING_ONCHIP_RTC + bool "Enable RTC" + select RT_USING_RTC + select RT_USING_LIBC + default n + if BSP_USING_ONCHIP_RTC + config NRFX_CLOCK_ENABLED + int + default 1 + config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY + int + default 7 + config NRFX_RTC_ENABLED + int + default 1 + config NRFX_RTC0_ENABLED + int + default 1 + config NRFX_RTC1_ENABLED + int + default 1 + config NRFX_RTC2_ENABLED + int + default 1 + config RTC_INSTANCE_ID + int + default 2 + config RTC_INSTANCE_ID + int "select RTC instance id, must be 0, 1, 2" + range 0 2 + default 2 + endif + +endmenu choice prompt "BLE STACK" diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c b/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c index 85b54fe637..8d1995c41b 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_gpio.c @@ -8,7 +8,8 @@ * 2018-11-06 balanceTWK first version * 2019-04-23 WillianChan Fix GPIO serial number disorder * 2020-06-16 thread-liu add STM32MP1 - * 2020-09-01 thread-liu add GPIOZ + * 2020-09-01 thread-liu add GPIOZ + * 2020-09-18 geniusgogo optimization design pin-index algorithm */ #include <board.h> @@ -16,225 +17,53 @@ #ifdef RT_USING_PIN -static const struct pin_index pins[] = -{ -#if defined(GPIOA) - __STM32_PIN(0 , A, 0 ), - __STM32_PIN(1 , A, 1 ), - __STM32_PIN(2 , A, 2 ), - __STM32_PIN(3 , A, 3 ), - __STM32_PIN(4 , A, 4 ), - __STM32_PIN(5 , A, 5 ), - __STM32_PIN(6 , A, 6 ), - __STM32_PIN(7 , A, 7 ), - __STM32_PIN(8 , A, 8 ), - __STM32_PIN(9 , A, 9 ), - __STM32_PIN(10, A, 10), - __STM32_PIN(11, A, 11), - __STM32_PIN(12, A, 12), - __STM32_PIN(13, A, 13), - __STM32_PIN(14, A, 14), - __STM32_PIN(15, A, 15), -#if defined(GPIOB) - __STM32_PIN(16, B, 0), - __STM32_PIN(17, B, 1), - __STM32_PIN(18, B, 2), - __STM32_PIN(19, B, 3), - __STM32_PIN(20, B, 4), - __STM32_PIN(21, B, 5), - __STM32_PIN(22, B, 6), - __STM32_PIN(23, B, 7), - __STM32_PIN(24, B, 8), - __STM32_PIN(25, B, 9), - __STM32_PIN(26, B, 10), - __STM32_PIN(27, B, 11), - __STM32_PIN(28, B, 12), - __STM32_PIN(29, B, 13), - __STM32_PIN(30, B, 14), - __STM32_PIN(31, B, 15), -#if defined(GPIOC) - __STM32_PIN(32, C, 0), - __STM32_PIN(33, C, 1), - __STM32_PIN(34, C, 2), - __STM32_PIN(35, C, 3), - __STM32_PIN(36, C, 4), - __STM32_PIN(37, C, 5), - __STM32_PIN(38, C, 6), - __STM32_PIN(39, C, 7), - __STM32_PIN(40, C, 8), - __STM32_PIN(41, C, 9), - __STM32_PIN(42, C, 10), - __STM32_PIN(43, C, 11), - __STM32_PIN(44, C, 12), - __STM32_PIN(45, C, 13), - __STM32_PIN(46, C, 14), - __STM32_PIN(47, C, 15), -#if defined(GPIOD) - __STM32_PIN(48, D, 0), - __STM32_PIN(49, D, 1), - __STM32_PIN(50, D, 2), - __STM32_PIN(51, D, 3), - __STM32_PIN(52, D, 4), - __STM32_PIN(53, D, 5), - __STM32_PIN(54, D, 6), - __STM32_PIN(55, D, 7), - __STM32_PIN(56, D, 8), - __STM32_PIN(57, D, 9), - __STM32_PIN(58, D, 10), - __STM32_PIN(59, D, 11), - __STM32_PIN(60, D, 12), - __STM32_PIN(61, D, 13), - __STM32_PIN(62, D, 14), - __STM32_PIN(63, D, 15), -#if defined(GPIOE) - __STM32_PIN(64, E, 0), - __STM32_PIN(65, E, 1), - __STM32_PIN(66, E, 2), - __STM32_PIN(67, E, 3), - __STM32_PIN(68, E, 4), - __STM32_PIN(69, E, 5), - __STM32_PIN(70, E, 6), - __STM32_PIN(71, E, 7), - __STM32_PIN(72, E, 8), - __STM32_PIN(73, E, 9), - __STM32_PIN(74, E, 10), - __STM32_PIN(75, E, 11), - __STM32_PIN(76, E, 12), - __STM32_PIN(77, E, 13), - __STM32_PIN(78, E, 14), - __STM32_PIN(79, E, 15), -#if defined(GPIOF) - __STM32_PIN(80, F, 0), - __STM32_PIN(81, F, 1), - __STM32_PIN(82, F, 2), - __STM32_PIN(83, F, 3), - __STM32_PIN(84, F, 4), - __STM32_PIN(85, F, 5), - __STM32_PIN(86, F, 6), - __STM32_PIN(87, F, 7), - __STM32_PIN(88, F, 8), - __STM32_PIN(89, F, 9), - __STM32_PIN(90, F, 10), - __STM32_PIN(91, F, 11), - __STM32_PIN(92, F, 12), - __STM32_PIN(93, F, 13), - __STM32_PIN(94, F, 14), - __STM32_PIN(95, F, 15), -#if defined(GPIOG) - __STM32_PIN(96, G, 0), - __STM32_PIN(97, G, 1), - __STM32_PIN(98, G, 2), - __STM32_PIN(99, G, 3), - __STM32_PIN(100, G, 4), - __STM32_PIN(101, G, 5), - __STM32_PIN(102, G, 6), - __STM32_PIN(103, G, 7), - __STM32_PIN(104, G, 8), - __STM32_PIN(105, G, 9), - __STM32_PIN(106, G, 10), - __STM32_PIN(107, G, 11), - __STM32_PIN(108, G, 12), - __STM32_PIN(109, G, 13), - __STM32_PIN(110, G, 14), - __STM32_PIN(111, G, 15), -#if defined(GPIOH) - __STM32_PIN(112, H, 0), - __STM32_PIN(113, H, 1), - __STM32_PIN(114, H, 2), - __STM32_PIN(115, H, 3), - __STM32_PIN(116, H, 4), - __STM32_PIN(117, H, 5), - __STM32_PIN(118, H, 6), - __STM32_PIN(119, H, 7), - __STM32_PIN(120, H, 8), - __STM32_PIN(121, H, 9), - __STM32_PIN(122, H, 10), - __STM32_PIN(123, H, 11), - __STM32_PIN(124, H, 12), - __STM32_PIN(125, H, 13), - __STM32_PIN(126, H, 14), - __STM32_PIN(127, H, 15), -#if defined(GPIOI) - __STM32_PIN(128, I, 0), - __STM32_PIN(129, I, 1), - __STM32_PIN(130, I, 2), - __STM32_PIN(131, I, 3), - __STM32_PIN(132, I, 4), - __STM32_PIN(133, I, 5), - __STM32_PIN(134, I, 6), - __STM32_PIN(135, I, 7), - __STM32_PIN(136, I, 8), - __STM32_PIN(137, I, 9), - __STM32_PIN(138, I, 10), - __STM32_PIN(139, I, 11), - __STM32_PIN(140, I, 12), - __STM32_PIN(141, I, 13), - __STM32_PIN(142, I, 14), - __STM32_PIN(143, I, 15), -#if defined(GPIOJ) - __STM32_PIN(144, J, 0), - __STM32_PIN(145, J, 1), - __STM32_PIN(146, J, 2), - __STM32_PIN(147, J, 3), - __STM32_PIN(148, J, 4), - __STM32_PIN(149, J, 5), - __STM32_PIN(150, J, 6), - __STM32_PIN(151, J, 7), - __STM32_PIN(152, J, 8), - __STM32_PIN(153, J, 9), - __STM32_PIN(154, J, 10), - __STM32_PIN(155, J, 11), - __STM32_PIN(156, J, 12), - __STM32_PIN(157, J, 13), - __STM32_PIN(158, J, 14), - __STM32_PIN(159, J, 15), -#if defined(GPIOK) - __STM32_PIN(160, K, 0), - __STM32_PIN(161, K, 1), - __STM32_PIN(162, K, 2), - __STM32_PIN(163, K, 3), - __STM32_PIN(164, K, 4), - __STM32_PIN(165, K, 5), - __STM32_PIN(166, K, 6), - __STM32_PIN(167, K, 7), - __STM32_PIN(168, K, 8), - __STM32_PIN(169, K, 9), - __STM32_PIN(170, K, 10), - __STM32_PIN(171, K, 11), - __STM32_PIN(172, K, 12), - __STM32_PIN(173, K, 13), - __STM32_PIN(174, K, 14), - __STM32_PIN(175, K, 15), +#define PIN_NUM(port, no) (((((port) & 0xFu) << 4) | ((no) & 0xFu))) +#define PIN_PORT(pin) ((uint8_t)(((pin) >> 4) & 0xFu)) +#define PIN_NO(pin) ((uint8_t)((pin) & 0xFu)) + +#if defined(SOC_SERIES_STM32MP1) #if defined(GPIOZ) - __STM32_PIN(176, Z, 0), - __STM32_PIN(177, Z, 1), - __STM32_PIN(178, Z, 2), - __STM32_PIN(179, Z, 3), - __STM32_PIN(180, Z, 4), - __STM32_PIN(181, Z, 5), - __STM32_PIN(182, Z, 6), - __STM32_PIN(183, Z, 7), - __STM32_PIN(184, Z, 8), - __STM32_PIN(185, Z, 9), - __STM32_PIN(186, Z, 10), - __STM32_PIN(187, Z, 11), - __STM32_PIN(188, Z, 12), - __STM32_PIN(189, Z, 13), - __STM32_PIN(190, Z, 14), - __STM32_PIN(191, Z, 15), -#endif /* defined(GPIOZ) */ -#endif /* defined(GPIOK) */ -#endif /* defined(GPIOJ) */ -#endif /* defined(GPIOI) */ -#endif /* defined(GPIOH) */ -#endif /* defined(GPIOG) */ -#endif /* defined(GPIOF) */ -#endif /* defined(GPIOE) */ -#endif /* defined(GPIOD) */ -#endif /* defined(GPIOC) */ -#endif /* defined(GPIOB) */ -#endif /* defined(GPIOA) */ -}; +#define gpioz_port_base (175) /* PIN_STPORT_MAX * 16 - 16 */ +#define PIN_STPORT(pin) ((pin > gpioz_port_base) ? ((GPIO_TypeDef *)(GPIOZ_BASE )) : ((GPIO_TypeDef *)(GPIOA_BASE + (0x1000u * PIN_PORT(pin))))) +#else +#define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x1000u * PIN_PORT(pin))))) +#endif /* GPIOZ */ +#else +#define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x400u * PIN_PORT(pin)))) +#endif /* SOC_SERIES_STM32MP1 */ + +#define PIN_STPIN(pin) ((uint16_t)(1u << PIN_NO(pin))) + +#if defined(GPIOZ) +#define __STM32_PORT_MAX 12u +#elif defined(GPIOK) +#define __STM32_PORT_MAX 11u +#elif defined(GPIOJ) +#define __STM32_PORT_MAX 10u +#elif defined(GPIOI) +#define __STM32_PORT_MAX 9u +#elif defined(GPIOH) +#define __STM32_PORT_MAX 8u +#elif defined(GPIOG) +#define __STM32_PORT_MAX 7u +#elif defined(GPIOF) +#define __STM32_PORT_MAX 6u +#elif defined(GPIOE) +#define __STM32_PORT_MAX 5u +#elif defined(GPIOD) +#define __STM32_PORT_MAX 4u +#elif defined(GPIOC) +#define __STM32_PORT_MAX 3u +#elif defined(GPIOB) +#define __STM32_PORT_MAX 2u +#elif defined(GPIOA) +#define __STM32_PORT_MAX 1u +#else +#define __STM32_PORT_MAX 0u +#error Unsupported STM32 GPIO peripheral. +#endif + +#define PIN_STPORT_MAX __STM32_PORT_MAX static const struct pin_irq_map pin_irq_map[] = { @@ -254,7 +83,7 @@ static const struct pin_irq_map pin_irq_map[] = {GPIO_PIN_12, EXTI4_15_IRQn}, {GPIO_PIN_13, EXTI4_15_IRQn}, {GPIO_PIN_14, EXTI4_15_IRQn}, - {GPIO_PIN_15, EXTI4_15_IRQn}, + {GPIO_PIN_15, EXTI4_15_IRQn}, #elif defined(SOC_SERIES_STM32MP1) {GPIO_PIN_0, EXTI0_IRQn}, {GPIO_PIN_1, EXTI1_IRQn}, @@ -271,7 +100,7 @@ static const struct pin_irq_map pin_irq_map[] = {GPIO_PIN_12, EXTI12_IRQn}, {GPIO_PIN_13, EXTI13_IRQn}, {GPIO_PIN_14, EXTI14_IRQn}, - {GPIO_PIN_15, EXTI15_IRQn}, + {GPIO_PIN_15, EXTI15_IRQn}, #else {GPIO_PIN_0, EXTI0_IRQn}, {GPIO_PIN_1, EXTI1_IRQn}, @@ -311,33 +140,15 @@ static struct rt_pin_irq_hdr pin_irq_hdr_tab[] = {-1, 0, RT_NULL, RT_NULL}, {-1, 0, RT_NULL, RT_NULL}, }; -static uint32_t pin_irq_enable_mask=0; +static uint32_t pin_irq_enable_mask = 0; #define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) -static const struct pin_index *get_pin(uint8_t pin) -{ - const struct pin_index *index; - - if (pin < ITEM_NUM(pins)) - { - index = &pins[pin]; - if (index->index == -1) - index = RT_NULL; - } - else - { - index = RT_NULL; - } - - return index; -}; static rt_base_t stm32_pin_get(const char *name) { rt_base_t pin = 0; int hw_port_num, hw_pin_num = 0; - int i, name_len = 1; - int mul = 1; + int i, name_len; name_len = rt_strlen(name); @@ -359,68 +170,58 @@ static rt_base_t stm32_pin_get(const char *name) return -RT_EINVAL; } - for (i = name_len - 1; i > 2; i--) + for (i = 3; i < name_len; i++) { - hw_pin_num += ((int)(name[i] - '0') * mul); - mul = mul * 10; + hw_pin_num *= 10; + hw_pin_num += name[i] - '0'; } - pin = 16 * hw_port_num + hw_pin_num; + pin = PIN_NUM(hw_port_num, hw_pin_num); - if (pin < ITEM_NUM(pins)) - { - return pin; - } - else - { - return -RT_EINVAL; - } + return pin; } static void stm32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { - const struct pin_index *index; + GPIO_TypeDef *gpio_port; + uint16_t gpio_pin; - index = get_pin(pin); - if (index == RT_NULL) + if (PIN_PORT(pin) < PIN_STPORT_MAX) { - return; - } + gpio_port = PIN_STPORT(pin); + gpio_pin = PIN_STPIN(pin); - HAL_GPIO_WritePin(index->gpio, index->pin, (GPIO_PinState)value); + HAL_GPIO_WritePin(gpio_port, gpio_pin, (GPIO_PinState)value); + } } static int stm32_pin_read(rt_device_t dev, rt_base_t pin) { - int value; - const struct pin_index *index; - - value = PIN_LOW; + GPIO_TypeDef *gpio_port; + uint16_t gpio_pin; + int value = PIN_LOW; - index = get_pin(pin); - if (index == RT_NULL) + if (PIN_PORT(pin) < PIN_STPORT_MAX) { - return value; + gpio_port = PIN_STPORT(pin); + gpio_pin = PIN_STPIN(pin); + value = HAL_GPIO_ReadPin(gpio_port, gpio_pin); } - value = HAL_GPIO_ReadPin(index->gpio, index->pin); - return value; } static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) { - const struct pin_index *index; GPIO_InitTypeDef GPIO_InitStruct; - index = get_pin(pin); - if (index == RT_NULL) + if (PIN_PORT(pin) >= PIN_STPORT_MAX) { return; } /* Configure GPIO_InitStructure */ - GPIO_InitStruct.Pin = index->pin; + GPIO_InitStruct.Pin = PIN_STPIN(pin); GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; @@ -456,7 +257,7 @@ static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) GPIO_InitStruct.Pull = GPIO_NOPULL; } - HAL_GPIO_Init(index->gpio, &GPIO_InitStruct); + HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct); } rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) @@ -485,16 +286,15 @@ rt_inline const struct pin_irq_map *get_pin_irq_map(uint32_t pinbit) static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) { - const struct pin_index *index; rt_base_t level; rt_int32_t irqindex = -1; - index = get_pin(pin); - if (index == RT_NULL) + if (PIN_PORT(pin) >= PIN_STPORT_MAX) { - return RT_ENOSYS; + return -RT_ENOSYS; } - irqindex = bit2bitno(index->pin); + + irqindex = bit2bitno(PIN_STPIN(pin)); if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) { return RT_ENOSYS; @@ -502,9 +302,9 @@ static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, level = rt_hw_interrupt_disable(); if (pin_irq_hdr_tab[irqindex].pin == pin && - pin_irq_hdr_tab[irqindex].hdr == hdr && - pin_irq_hdr_tab[irqindex].mode == mode && - pin_irq_hdr_tab[irqindex].args == args) + pin_irq_hdr_tab[irqindex].hdr == hdr && + pin_irq_hdr_tab[irqindex].mode == mode && + pin_irq_hdr_tab[irqindex].args == args) { rt_hw_interrupt_enable(level); return RT_EOK; @@ -525,16 +325,15 @@ static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, static rt_err_t stm32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) { - const struct pin_index *index; rt_base_t level; rt_int32_t irqindex = -1; - index = get_pin(pin); - if (index == RT_NULL) + if (PIN_PORT(pin) >= PIN_STPORT_MAX) { - return RT_ENOSYS; + return -RT_ENOSYS; } - irqindex = bit2bitno(index->pin); + + irqindex = bit2bitno(PIN_STPIN(pin)); if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) { return RT_ENOSYS; @@ -558,21 +357,19 @@ static rt_err_t stm32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) { - const struct pin_index *index; const struct pin_irq_map *irqmap; rt_base_t level; rt_int32_t irqindex = -1; GPIO_InitTypeDef GPIO_InitStruct; - index = get_pin(pin); - if (index == RT_NULL) + if (PIN_PORT(pin) >= PIN_STPORT_MAX) { - return RT_ENOSYS; + return -RT_ENOSYS; } if (enabled == PIN_IRQ_ENABLE) { - irqindex = bit2bitno(index->pin); + irqindex = bit2bitno(PIN_STPIN(pin)); if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) { return RT_ENOSYS; @@ -589,7 +386,7 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin, irqmap = &pin_irq_map[irqindex]; /* Configure GPIO_InitStructure */ - GPIO_InitStruct.Pin = index->pin; + GPIO_InitStruct.Pin = PIN_STPIN(pin); GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; switch (pin_irq_hdr_tab[irqindex].mode) { @@ -606,7 +403,7 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin, GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; break; } - HAL_GPIO_Init(index->gpio, &GPIO_InitStruct); + HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct); HAL_NVIC_SetPriority(irqmap->irqno, 5, 0); HAL_NVIC_EnableIRQ(irqmap->irqno); @@ -616,7 +413,7 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin, } else if (enabled == PIN_IRQ_DISABLE) { - irqmap = get_pin_irq_map(index->pin); + irqmap = get_pin_irq_map(PIN_STPIN(pin)); if (irqmap == RT_NULL) { return RT_ENOSYS; @@ -624,57 +421,57 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin, level = rt_hw_interrupt_disable(); - HAL_GPIO_DeInit(index->gpio, index->pin); + HAL_GPIO_DeInit(PIN_STPORT(pin), PIN_STPIN(pin)); pin_irq_enable_mask &= ~irqmap->pinbit; #if defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) - if (( irqmap->pinbit>=GPIO_PIN_0 )&&( irqmap->pinbit<=GPIO_PIN_1 )) + if ((irqmap->pinbit >= GPIO_PIN_0) && (irqmap->pinbit <= GPIO_PIN_1)) { - if(!(pin_irq_enable_mask&(GPIO_PIN_0|GPIO_PIN_1))) - { + if (!(pin_irq_enable_mask & (GPIO_PIN_0 | GPIO_PIN_1))) + { HAL_NVIC_DisableIRQ(irqmap->irqno); } } - else if (( irqmap->pinbit>=GPIO_PIN_2 )&&( irqmap->pinbit<=GPIO_PIN_3 )) + else if ((irqmap->pinbit >= GPIO_PIN_2) && (irqmap->pinbit <= GPIO_PIN_3)) { - if(!(pin_irq_enable_mask&(GPIO_PIN_2|GPIO_PIN_3))) - { + if (!(pin_irq_enable_mask & (GPIO_PIN_2 | GPIO_PIN_3))) + { HAL_NVIC_DisableIRQ(irqmap->irqno); } } - else if (( irqmap->pinbit>=GPIO_PIN_4 )&&( irqmap->pinbit<=GPIO_PIN_15 )) + else if ((irqmap->pinbit >= GPIO_PIN_4) && (irqmap->pinbit <= GPIO_PIN_15)) { - if(!(pin_irq_enable_mask&(GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9| - GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15))) - { + if (!(pin_irq_enable_mask & (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | + GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15))) + { HAL_NVIC_DisableIRQ(irqmap->irqno); } - } + } else { HAL_NVIC_DisableIRQ(irqmap->irqno); - } -#else - if (( irqmap->pinbit>=GPIO_PIN_5 )&&( irqmap->pinbit<=GPIO_PIN_9 )) + } +#else + if ((irqmap->pinbit >= GPIO_PIN_5) && (irqmap->pinbit <= GPIO_PIN_9)) { - if(!(pin_irq_enable_mask&(GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9))) - { + if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9))) + { HAL_NVIC_DisableIRQ(irqmap->irqno); } } - else if (( irqmap->pinbit>=GPIO_PIN_10 )&&( irqmap->pinbit<=GPIO_PIN_15 )) + else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15)) { - if(!(pin_irq_enable_mask&(GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15))) - { + if (!(pin_irq_enable_mask & (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15))) + { HAL_NVIC_DisableIRQ(irqmap->irqno); } } else { HAL_NVIC_DisableIRQ(irqmap->irqno); - } -#endif - rt_hw_interrupt_enable(level); + } +#endif + rt_hw_interrupt_enable(level); } else { @@ -754,100 +551,116 @@ void EXTI4_15_IRQHandler(void) } #elif defined(SOC_STM32MP157A) -void EXTI0_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); - rt_interrupt_leave(); +void EXTI0_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); + rt_interrupt_leave(); } -void EXTI1_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); - rt_interrupt_leave(); +void EXTI1_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); + rt_interrupt_leave(); } -void EXTI2_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); - rt_interrupt_leave(); +void EXTI2_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); + rt_interrupt_leave(); } -void EXTI3_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); - rt_interrupt_leave(); +void EXTI3_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); + rt_interrupt_leave(); } -void EXTI4_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); - rt_interrupt_leave(); +void EXTI4_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); + rt_interrupt_leave(); } -void EXTI5_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5); - rt_interrupt_leave(); +void EXTI5_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5); + rt_interrupt_leave(); } -void EXTI6_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6); - rt_interrupt_leave(); +void EXTI6_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6); + rt_interrupt_leave(); } -void EXTI7_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); - rt_interrupt_leave(); +void EXTI7_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); + rt_interrupt_leave(); } -void EXTI8_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); - rt_interrupt_leave(); +void EXTI8_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); + rt_interrupt_leave(); } -void EXTI9_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); - rt_interrupt_leave(); +void EXTI9_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); + rt_interrupt_leave(); } -void EXTI10_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); - rt_interrupt_leave(); +void EXTI10_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); + rt_interrupt_leave(); } -void EXTI11_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11); - rt_interrupt_leave(); +void EXTI11_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11); + rt_interrupt_leave(); } -void EXTI12_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12); - rt_interrupt_leave(); +void EXTI12_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12); + rt_interrupt_leave(); } -void EXTI13_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); - rt_interrupt_leave(); +void EXTI13_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); + rt_interrupt_leave(); } -void EXTI14_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14); - rt_interrupt_leave(); +void EXTI14_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14); + rt_interrupt_leave(); } -void EXTI15_IRQHandler(void) { - rt_interrupt_enter(); - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15); - rt_interrupt_leave(); +void EXTI15_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15); + rt_interrupt_leave(); } #else @@ -916,15 +729,15 @@ int rt_hw_pin_init(void) #if defined(__HAL_RCC_GPIOA_CLK_ENABLE) __HAL_RCC_GPIOA_CLK_ENABLE(); #endif - + #if defined(__HAL_RCC_GPIOB_CLK_ENABLE) __HAL_RCC_GPIOB_CLK_ENABLE(); #endif - + #if defined(__HAL_RCC_GPIOC_CLK_ENABLE) __HAL_RCC_GPIOC_CLK_ENABLE(); #endif - + #if defined(__HAL_RCC_GPIOD_CLK_ENABLE) __HAL_RCC_GPIOD_CLK_ENABLE(); #endif diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_gpio.h b/bsp/stm32/libraries/HAL_Drivers/drv_gpio.h index 69bd71dbc3..bbcbdcccff 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_gpio.h +++ b/bsp/stm32/libraries/HAL_Drivers/drv_gpio.h @@ -8,6 +8,7 @@ * 2018-11-06 balanceTWK first version * 2020-06-16 thread-liu add stm32mp1 * 2020-09-01 thread-liu add GPIOZ + * 2020-09-18 geniusgogo optimization design pin-index algorithm */ #ifndef __DRV_GPIO_H__ @@ -16,6 +17,10 @@ #include <drv_common.h> #include <board.h> +#ifdef __cplusplus +extern "C" { +#endif + #define __STM32_PORT(port) GPIO##port##_BASE #if defined(SOC_SERIES_STM32MP1) @@ -24,24 +29,6 @@ #define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN) #endif -#define __STM32_PIN(index, gpio, gpio_index) \ - { \ - index, GPIO##gpio, GPIO_PIN_##gpio_index \ - } - -#define __STM32_PIN_RESERVE \ - { \ - -1, 0, 0 \ - } - -/* STM32 GPIO driver */ -struct pin_index -{ - int index; - GPIO_TypeDef *gpio; - uint32_t pin; -}; - struct pin_irq_map { rt_uint16_t pinbit; @@ -50,5 +37,9 @@ struct pin_irq_map int rt_hw_pin_init(void); +#ifdef __cplusplus +} +#endif + #endif /* __DRV_GPIO_H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/.config b/bsp/stm32/stm32mp157a-st-discovery/.config index bfff68de2f..01ca2120fa 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/.config +++ b/bsp/stm32/stm32mp157a-st-discovery/.config @@ -426,6 +426,7 @@ CONFIG_BSP_USING_STLINK_TO_USART=y # CONFIG_BSP_USING_PMIC is not set # CONFIG_BSP_USING_PWR is not set # CONFIG_BSP_USING_RCC is not set +# CONFIG_BSP_USING_OPENAMP is not set # # On-chip Peripheral Drivers diff --git a/bsp/stm32/stm32mp157a-st-discovery/.cproject b/bsp/stm32/stm32mp157a-st-discovery/.cproject index 478525a8c2..ce78ef0eb8 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/.cproject +++ b/bsp/stm32/stm32mp157a-st-discovery/.cproject @@ -67,15 +67,14 @@ <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board/CubeMX_Config/CM4/Inc}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board/ports}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/HAL_Drivers/config}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/HAL_Drivers}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Core/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Inc}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/HAL_Drivers/config}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/HAL_Drivers}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Core/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Inc}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/include}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/finsh}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/libc/compilers/newlib}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/include}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/libcpu/arm/common}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/libcpu/arm/cortex-m4}"" /> @@ -102,8 +101,6 @@ <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.libs.1135656995" name="Libraries (-l)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.libs" useByScannerDiscovery="false"> <listOptionValue builtIn="false" value="c" /> <listOptionValue builtIn="false" value="m" /> - <listOptionValue builtIn="false" value="c " /> - <listOptionValue builtIn="false" value="m " /> </option> <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.paths.36884122" name="Library search path (-L)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.paths" useByScannerDiscovery="false" /> <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.other.396049466" name="Other linker flags" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.linker.other" useByScannerDiscovery="false" value="" valueType="string" /> @@ -161,15 +158,14 @@ <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board/CubeMX_Config/CM4/Inc}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board/ports}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/HAL_Drivers/config}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/HAL_Drivers}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Core/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Inc}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/HAL_Drivers/config}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/HAL_Drivers}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Core/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Inc}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/include}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/finsh}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/libc/compilers/newlib}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/include}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/libcpu/arm/common}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/libcpu/arm/cortex-m4}"" /> @@ -182,7 +178,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="//board/CubeMX_Config/CM4/Src/main.c|//board/CubeMX_Config/CM4/Src/stm32mp1xx_it.c|//board/ports|//libraries/HAL_Drivers/drv_adc.c|//libraries/HAL_Drivers/drv_can.c|//libraries/HAL_Drivers/drv_crypto.c|//libraries/HAL_Drivers/drv_dac.c|//libraries/HAL_Drivers/drv_eth.c|//libraries/HAL_Drivers/drv_flash|//libraries/HAL_Drivers/drv_hwtimer.c|//libraries/HAL_Drivers/drv_lcd.c|//libraries/HAL_Drivers/drv_lcd_mipi.c|//libraries/HAL_Drivers/drv_lptim.c|//libraries/HAL_Drivers/drv_pm.c|//libraries/HAL_Drivers/drv_pulse_encoder.c|//libraries/HAL_Drivers/drv_pwm.c|//libraries/HAL_Drivers/drv_qspi.c|//libraries/HAL_Drivers/drv_rtc.c|//libraries/HAL_Drivers/drv_sdio.c|//libraries/HAL_Drivers/drv_sdram.c|//libraries/HAL_Drivers/drv_soft_i2c.c|//libraries/HAL_Drivers/drv_spi.c|//libraries/HAL_Drivers/drv_usbd.c|//libraries/HAL_Drivers/drv_usbh.c|//libraries/HAL_Drivers/drv_wdt.c|//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/arm|//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/iar|//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/system_stm32mp1xx.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cec.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_crc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_crc_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cryp.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cryp_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dcmi.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_fdcan.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_hash.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_hash_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_lptim.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_mdios.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_msp_template.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_qspi.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rng.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rtc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rtc_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_smbus.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spdifrx.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spi_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sram.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_timebase_tim_template.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_usart.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_usart_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_wwdg.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_adc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_delayblock.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_dma.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_exti.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_fmc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_gpio.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_i2c.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_lptim.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_pwr.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_rcc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_rtc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_sdmmc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_spi.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_tim.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_usart.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_utils.c|//rt-thread/components/cplusplus|//rt-thread/components/dfs|//rt-thread/components/drivers/audio|//rt-thread/components/drivers/can|//rt-thread/components/drivers/cputime|//rt-thread/components/drivers/hwcrypto|//rt-thread/components/drivers/hwtimer|//rt-thread/components/drivers/i2c|//rt-thread/components/drivers/misc/adc.c|//rt-thread/components/drivers/misc/dac.c|//rt-thread/components/drivers/misc/pulse_encoder.c|//rt-thread/components/drivers/misc/rt_drv_pwm.c|//rt-thread/components/drivers/misc/rt_inputcapture.c|//rt-thread/components/drivers/mtd|//rt-thread/components/drivers/pm|//rt-thread/components/drivers/rtc|//rt-thread/components/drivers/sdio|//rt-thread/components/drivers/sensors|//rt-thread/components/drivers/spi|//rt-thread/components/drivers/touch|//rt-thread/components/drivers/usb|//rt-thread/components/drivers/watchdog|//rt-thread/components/drivers/wlan|//rt-thread/components/finsh/msh_file.c|//rt-thread/components/finsh/symbol.c|//rt-thread/components/libc/aio|//rt-thread/components/libc/compilers/armlibc|//rt-thread/components/libc/compilers/common|//rt-thread/components/libc/compilers/dlib|//rt-thread/components/libc/compilers/minilibc|//rt-thread/components/libc/libdl|//rt-thread/components/libc/mmap|//rt-thread/components/libc/pthreads|//rt-thread/components/libc/signal|//rt-thread/components/libc/termios|//rt-thread/components/libc/time|//rt-thread/components/lwp|//rt-thread/components/net|//rt-thread/components/utilities|//rt-thread/components/vbus|//rt-thread/components/vmm|//rt-thread/libcpu/arm/AT91SAM7S|//rt-thread/libcpu/arm/AT91SAM7X|//rt-thread/libcpu/arm/am335x|//rt-thread/libcpu/arm/arm926|//rt-thread/libcpu/arm/armv6|//rt-thread/libcpu/arm/common/divsi3.S|//rt-thread/libcpu/arm/cortex-a|//rt-thread/libcpu/arm/cortex-m0|//rt-thread/libcpu/arm/cortex-m23|//rt-thread/libcpu/arm/cortex-m3|//rt-thread/libcpu/arm/cortex-m33|//rt-thread/libcpu/arm/cortex-m4/context_iar.S|//rt-thread/libcpu/arm/cortex-m4/context_rvds.S|//rt-thread/libcpu/arm/cortex-m7|//rt-thread/libcpu/arm/cortex-r4|//rt-thread/libcpu/arm/dm36x|//rt-thread/libcpu/arm/lpc214x|//rt-thread/libcpu/arm/lpc24xx|//rt-thread/libcpu/arm/realview-a8-vmm|//rt-thread/libcpu/arm/s3c24x0|//rt-thread/libcpu/arm/s3c44b0|//rt-thread/libcpu/arm/sep4020|//rt-thread/libcpu/arm/zynq7000|//rt-thread/src/cpu.c|//rt-thread/src/mem.c|//rt-thread/src/slab.c|//rt-thread/tools" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" /> + <entry excluding="//board/CubeMX_Config/CM4/Src/main.c|//board/CubeMX_Config/CM4/Src/stm32mp1xx_it.c|//board/ports|//rt-thread/bsp/CME_M7|//rt-thread/bsp/allwinner_tina|//rt-thread/bsp/amebaz|//rt-thread/bsp/apollo2|//rt-thread/bsp/asm9260t|//rt-thread/bsp/at32|//rt-thread/bsp/at91sam9260|//rt-thread/bsp/at91sam9g45|//rt-thread/bsp/avr32uc3b0|//rt-thread/bsp/beaglebone|//rt-thread/bsp/bf533|//rt-thread/bsp/ck802|//rt-thread/bsp/cypress|//rt-thread/bsp/dm365|//rt-thread/bsp/efm32|//rt-thread/bsp/essemi|//rt-thread/bsp/fh8620|//rt-thread/bsp/frdm-k64f|//rt-thread/bsp/gd32303e-eval|//rt-thread/bsp/gd32450z-eval|//rt-thread/bsp/gd32e230k-start|//rt-thread/bsp/gd32vf103v-eval|//rt-thread/bsp/gkipc|//rt-thread/bsp/hifive1|//rt-thread/bsp/imx6sx|//rt-thread/bsp/imx6ul|//rt-thread/bsp/imxrt|//rt-thread/bsp/k210|//rt-thread/bsp/lm3s8962|//rt-thread/bsp/lm3s9b9x|//rt-thread/bsp/lm4f232|//rt-thread/bsp/lpc1114|//rt-thread/bsp/lpc176x|//rt-thread/bsp/lpc178x|//rt-thread/bsp/lpc2148|//rt-thread/bsp/lpc2478|//rt-thread/bsp/lpc408x|//rt-thread/bsp/lpc43xx|//rt-thread/bsp/lpc5410x|//rt-thread/bsp/lpc54114-lite|//rt-thread/bsp/lpc54608-LPCXpresso|//rt-thread/bsp/lpc55sxx|//rt-thread/bsp/lpc824|//rt-thread/bsp/ls1bdev|//rt-thread/bsp/ls1cdev|//rt-thread/bsp/ls2kdev|//rt-thread/bsp/m16c62p|//rt-thread/bsp/mb9bf500r|//rt-thread/bsp/mb9bf506r|//rt-thread/bsp/mb9bf568r|//rt-thread/bsp/mb9bf618s|//rt-thread/bsp/microblaze|//rt-thread/bsp/mini2440|//rt-thread/bsp/mini4020|//rt-thread/bsp/mipssim|//rt-thread/bsp/mm32l07x|//rt-thread/bsp/mm32l3xx|//rt-thread/bsp/nios_ii|//rt-thread/bsp/nrf51822|//rt-thread/bsp/nrf52832|//rt-thread/bsp/nrf5x|//rt-thread/bsp/nuclei|//rt-thread/bsp/nuvoton|//rt-thread/bsp/nv32f100x|//rt-thread/bsp/pic32ethernet|//rt-thread/bsp/qemu-vexpress-a9|//rt-thread/bsp/qemu-vexpress-gemini|//rt-thread/bsp/raspberry-pi|//rt-thread/bsp/realview-a8|//rt-thread/bsp/rm48x50|//rt-thread/bsp/rv32m1_vega|//rt-thread/bsp/rx|//rt-thread/bsp/sam7x|//rt-thread/bsp/samd21|//rt-thread/bsp/sep6200|//rt-thread/bsp/simulator|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_adc.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_can.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_crypto.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_dac.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_eth.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_flash|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_hwtimer.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_lcd_mipi.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_lptim.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_pm.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_pulse_encoder.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_pwm.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_qspi.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_rtc.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_sdio.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_sdram.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_soft_i2c.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_spi.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_usbd.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_usbh.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_wdt.c|//rt-thread/bsp/stm32/libraries/STM32F0xx_HAL|//rt-thread/bsp/stm32/libraries/STM32F1xx_HAL|//rt-thread/bsp/stm32/libraries/STM32F2xx_HAL|//rt-thread/bsp/stm32/libraries/STM32F4xx_HAL|//rt-thread/bsp/stm32/libraries/STM32F7xx_HAL|//rt-thread/bsp/stm32/libraries/STM32G0xx_HAL|//rt-thread/bsp/stm32/libraries/STM32G4xx_HAL|//rt-thread/bsp/stm32/libraries/STM32H7xx_HAL|//rt-thread/bsp/stm32/libraries/STM32L0xx_HAL|//rt-thread/bsp/stm32/libraries/STM32L1xx_HAL|//rt-thread/bsp/stm32/libraries/STM32L4xx_HAL|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/arm|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/iar|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/system_stm32mp1xx.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cec.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_crc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_crc_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cryp.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cryp_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dcmi.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_fdcan.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_hash.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_hash_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_lptim.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_mdios.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_msp_template.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_qspi.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rng.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rtc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rtc_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_smbus.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spdifrx.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spi_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sram.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_timebase_tim_template.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_usart.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_usart_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_wwdg.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_adc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_delayblock.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_dma.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_exti.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_fmc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_gpio.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_i2c.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_lptim.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_pwr.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_rcc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_rtc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_sdmmc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_spi.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_tim.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_usart.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_utils.c|//rt-thread/bsp/stm32/libraries/templates|//rt-thread/bsp/stm32/stm32f072-st-nucleo|//rt-thread/bsp/stm32/stm32f091-st-nucleo|//rt-thread/bsp/stm32/stm32f103-atk-nano|//rt-thread/bsp/stm32/stm32f103-atk-warshipv3|//rt-thread/bsp/stm32/stm32f103-dofly-M3S|//rt-thread/bsp/stm32/stm32f103-dofly-lyc8|//rt-thread/bsp/stm32/stm32f103-fire-arbitrary|//rt-thread/bsp/stm32/stm32f103-gizwits-gokitv21|//rt-thread/bsp/stm32/stm32f103-hw100k-ibox|//rt-thread/bsp/stm32/stm32f103-mini-system|//rt-thread/bsp/stm32/stm32f103-onenet-nbiot|//rt-thread/bsp/stm32/stm32f103-yf-ufun|//rt-thread/bsp/stm32/stm32f107-uc-eval|//rt-thread/bsp/stm32/stm32f401-st-nucleo|//rt-thread/bsp/stm32/stm32f405-smdz-breadfruit|//rt-thread/bsp/stm32/stm32f407-atk-explorer|//rt-thread/bsp/stm32/stm32f407-st-discovery|//rt-thread/bsp/stm32/stm32f410-st-nucleo|//rt-thread/bsp/stm32/stm32f411-atk-nano|//rt-thread/bsp/stm32/stm32f411-st-nucleo|//rt-thread/bsp/stm32/stm32f411-weact-MiniF4|//rt-thread/bsp/stm32/stm32f412-st-nucleo|//rt-thread/bsp/stm32/stm32f413-st-nucleo|//rt-thread/bsp/stm32/stm32f427-robomaster-a|//rt-thread/bsp/stm32/stm32f429-armfly-v6|//rt-thread/bsp/stm32/stm32f429-atk-apollo|//rt-thread/bsp/stm32/stm32f429-fire-challenger|//rt-thread/bsp/stm32/stm32f429-st-disco|//rt-thread/bsp/stm32/stm32f446-st-nucleo|//rt-thread/bsp/stm32/stm32f469-st-disco|//rt-thread/bsp/stm32/stm32f746-st-disco|//rt-thread/bsp/stm32/stm32f767-atk-apollo|//rt-thread/bsp/stm32/stm32f767-fire-challenger|//rt-thread/bsp/stm32/stm32f767-st-nucleo|//rt-thread/bsp/stm32/stm32f769-st-disco|//rt-thread/bsp/stm32/stm32g070-st-nucleo|//rt-thread/bsp/stm32/stm32g071-st-nucleo|//rt-thread/bsp/stm32/stm32g431-st-nucleo|//rt-thread/bsp/stm32/stm32h743-atk-apollo|//rt-thread/bsp/stm32/stm32h743-st-nucleo|//rt-thread/bsp/stm32/stm32h747-st-discovery|//rt-thread/bsp/stm32/stm32h750-armfly-h7-tool|//rt-thread/bsp/stm32/stm32l010-st-nucleo|//rt-thread/bsp/stm32/stm32l053-st-nucleo|//rt-thread/bsp/stm32/stm32l412-st-nucleo|//rt-thread/bsp/stm32/stm32l432-st-nucleo|//rt-thread/bsp/stm32/stm32l433-st-nucleo|//rt-thread/bsp/stm32/stm32l452-st-nucleo|//rt-thread/bsp/stm32/stm32l475-atk-pandora|//rt-thread/bsp/stm32/stm32l475-st-discovery|//rt-thread/bsp/stm32/stm32l476-st-nucleo|//rt-thread/bsp/stm32/stm32l496-ali-developer|//rt-thread/bsp/stm32/stm32l496-st-nucleo|//rt-thread/bsp/stm32/stm32l4r5-st-nucleo|//rt-thread/bsp/stm32/stm32l4r9-st-eval|//rt-thread/bsp/stm32/stm32mp157a-st-ev1|//rt-thread/bsp/stm32f20x|//rt-thread/bsp/swm320-lq100|//rt-thread/bsp/synopsys|//rt-thread/bsp/taihu|//rt-thread/bsp/tm4c123bsp|//rt-thread/bsp/tm4c129x|//rt-thread/bsp/tms320f28379d|//rt-thread/bsp/upd70f3454|//rt-thread/bsp/w60x|//rt-thread/bsp/wh44b0|//rt-thread/bsp/x86|//rt-thread/bsp/xplorer4330|//rt-thread/bsp/zynq7000|//rt-thread/components/cplusplus|//rt-thread/components/dfs|//rt-thread/components/drivers/audio|//rt-thread/components/drivers/can|//rt-thread/components/drivers/cputime|//rt-thread/components/drivers/hwcrypto|//rt-thread/components/drivers/hwtimer|//rt-thread/components/drivers/i2c|//rt-thread/components/drivers/misc/adc.c|//rt-thread/components/drivers/misc/dac.c|//rt-thread/components/drivers/misc/pulse_encoder.c|//rt-thread/components/drivers/misc/rt_drv_pwm.c|//rt-thread/components/drivers/misc/rt_inputcapture.c|//rt-thread/components/drivers/mtd|//rt-thread/components/drivers/pm|//rt-thread/components/drivers/rtc|//rt-thread/components/drivers/sdio|//rt-thread/components/drivers/sensors|//rt-thread/components/drivers/spi|//rt-thread/components/drivers/touch|//rt-thread/components/drivers/usb|//rt-thread/components/drivers/watchdog|//rt-thread/components/drivers/wlan|//rt-thread/components/finsh/msh_file.c|//rt-thread/components/finsh/symbol.c|//rt-thread/components/libc|//rt-thread/components/lwp|//rt-thread/components/net|//rt-thread/components/utilities|//rt-thread/components/vbus|//rt-thread/components/vmm|//rt-thread/examples|//rt-thread/libcpu/aarch64|//rt-thread/libcpu/arc|//rt-thread/libcpu/arm/AT91SAM7S|//rt-thread/libcpu/arm/AT91SAM7X|//rt-thread/libcpu/arm/am335x|//rt-thread/libcpu/arm/arm926|//rt-thread/libcpu/arm/armv6|//rt-thread/libcpu/arm/common/divsi3.S|//rt-thread/libcpu/arm/cortex-a|//rt-thread/libcpu/arm/cortex-m0|//rt-thread/libcpu/arm/cortex-m23|//rt-thread/libcpu/arm/cortex-m3|//rt-thread/libcpu/arm/cortex-m33|//rt-thread/libcpu/arm/cortex-m4/context_iar.S|//rt-thread/libcpu/arm/cortex-m4/context_rvds.S|//rt-thread/libcpu/arm/cortex-m7|//rt-thread/libcpu/arm/cortex-r4|//rt-thread/libcpu/arm/dm36x|//rt-thread/libcpu/arm/lpc214x|//rt-thread/libcpu/arm/lpc24xx|//rt-thread/libcpu/arm/realview-a8-vmm|//rt-thread/libcpu/arm/s3c24x0|//rt-thread/libcpu/arm/s3c44b0|//rt-thread/libcpu/arm/sep4020|//rt-thread/libcpu/arm/zynq7000|//rt-thread/libcpu/avr32|//rt-thread/libcpu/blackfin|//rt-thread/libcpu/c-sky|//rt-thread/libcpu/ia32|//rt-thread/libcpu/m16c|//rt-thread/libcpu/mips|//rt-thread/libcpu/nios|//rt-thread/libcpu/ppc|//rt-thread/libcpu/risc-v|//rt-thread/libcpu/rx|//rt-thread/libcpu/sim|//rt-thread/libcpu/ti-dsp|//rt-thread/libcpu/unicore32|//rt-thread/libcpu/v850|//rt-thread/libcpu/xilinx|//rt-thread/src/cpu.c|//rt-thread/src/mem.c|//rt-thread/src/slab.c|//rt-thread/tools" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" /> </sourceEntries> </configuration> </storageModule> diff --git a/bsp/stm32/stm32mp157a-st-discovery/README.md b/bsp/stm32/stm32mp157a-st-discovery/README.md index 925e7e636c..b138e9073b 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/README.md +++ b/bsp/stm32/stm32mp157a-st-discovery/README.md @@ -37,25 +37,25 @@ For more details about this board, please refer to the ST official documentation Each peripheral supporting condition for this BSP is as follows: -| On-board Peripheral | **Support** | **Remark** | -| :----------------------------- | :---------: | :-----------------: | -| USB TO UART | YES | | -| PWR | YES | | -| RCC | YES | | -| SD Card (SDMMC) | NO | | -| ETH | NO | | -| AUDIO | NO | | -| **On-chip Peripheral Drivers** | **Support** | **Remark** | -| GPIO | YES | GPIOA-GPIOK, GPIOZ | -| UART | YES | UART4 (ST-Link) | -| EXTI | YES | | -| SPI | YES | | -| TIM | YES | | -| LPTIM | YES | | -| I2C | YES | Software & Hardware | -| ADC | YES | | -| DAC | YES | | -| WWDG | YES | | +| On-board Peripheral | **Support** | **Remark** | +| :----------------------------- | :---------: | :----------------: | +| USB TO UART | YES | | +| PWR | YES | | +| RCC | YES | | +| SD Card (SDMMC) | NO | | +| ETH | NO | | +| AUDIO | NO | | +| **On-chip Peripheral Drivers** | **Support** | **Remark** | +| GPIO | YES | GPIOA-GPIOK, GPIOZ | +| UART | YES | UART4 (ST-Link) | +| EXTI | YES | | +| SPI | YES | | +| TIM | YES | | +| LPTIM | YES | | +| I2C | YES | Software | +| ADC | YES | | +| DAC | YES | | +| WWDG | YES | | ## Execution Instruction diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/ipcc.h b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/ipcc.h new file mode 100644 index 0000000000..3f07bf7536 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/ipcc.h @@ -0,0 +1,58 @@ +/** + ****************************************************************************** + * File Name : IPCC.h + * Description : This file provides code for the configuration + * of the IPCC instances. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.</center></h2> + * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __ipcc_H +#define __ipcc_H +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +extern IPCC_HandleTypeDef hipcc; + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_IPCC_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif +#endif /*__ ipcc_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/mbox_ipcc.h b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/mbox_ipcc.h new file mode 100644 index 0000000000..0e605cc919 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/mbox_ipcc.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * @file mbox_ipcc.h + * @author MCD Application Team + * @brief Header for mbox_ipcc.c module + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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_ + +/* 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_Notify(void *priv, uint32_t id); +int MAILBOX_Init(void); +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 /* MBOX_IPCC_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp.h b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp.h new file mode 100644 index 0000000000..3589f3bdd1 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp.h @@ -0,0 +1,58 @@ +/** + ****************************************************************************** + * @file openamp.h + * @brief Header for openamp applications + * @author MCD Application Team + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 __cplusplus + extern "C" { +#endif + +#include "openamp/open_amp.h" +#include "openamp_conf.h" + +#define OPENAMP_send rpmsg_send +#define OPENAMP_destroy_ept rpmsg_destroy_ept + +/* Initialize the openamp framework*/ +int MX_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 /*__openamp_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp_conf.h b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp_conf.h new file mode 100644 index 0000000000..e6c32798dd --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp_conf.h @@ -0,0 +1,242 @@ +/** + ****************************************************************************** + * @file openamp_conf.h + * @author MCD Application Team + * @brief Configuration file for OpenAMP MW + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 __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 */ + + /* ########################## Linux Master Selection ############################## */ + /** + * @brief Due to Linux compatibility, it's important to distinguish if the MASTER is Linux or not. + * In that case, the LINUX_RPROC_MASTER define is required + */ +#define LINUX_RPROC_MASTER + +/* 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 LINUX_RPROC_MASTER +#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 0x10040000 /* allocated by Master processor: CA7 */ +#define VRING_TX_ADDRESS 0x10040400 /* allocated by Master processor: CA7 */ +#define VRING_BUFF_ADDRESS 0x10040800 /* allocated by Master processor: CA7 */ +#define VRING_ALIGNMENT 16 /* fixed to match with 4k page alignement requested by linux */ +#define VRING_NUM_BUFFS 16 /* number of rpmsg buffer */ +#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 /* __OPENAMP_CONF__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp_log.h b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp_log.h new file mode 100644 index 0000000000..60c3f2af58 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/openamp_log.h @@ -0,0 +1,134 @@ +/** + ****************************************************************************** + * @file log.h + * @author MCD Application Team + * @brief logging services + ****************************************************************************** + * + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32MP1xx_Log_Includes + * @{ + */ +#include "stm32mp1xx_hal.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 /*__LOG_STM32MP1XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/rsc_table.h b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/rsc_table.h new file mode 100644 index 0000000000..aaf818355c --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Inc/rsc_table.h @@ -0,0 +1,43 @@ +/* + * 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_ + +#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 /* RSC_TABLE_H_ */ + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/mbox_ipcc.c b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/mbox_ipcc.c new file mode 100644 index 0000000000..475f3a22cf --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/mbox_ipcc.c @@ -0,0 +1,182 @@ +/** + ****************************************************************************** + * @file mbox_ipcc.c + * @author MCD Application Team + * @brief This file provides code for the configuration + * of the mailbox_ipcc_if.c MiddleWare. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 + * + ****************************************************************************** + */ + +/* + * Channel direction and usage: + * + * ======== <-- new msg ---=============--------<------ ======= + * || || || CHANNEL 1 || || || + * || A7 || ------->-------=============--- buf free--> || M4 || + * || || || || + * ||master|| <-- buf free---=============--------<------ ||slave|| + * || || || CHANNEL 2 || || || + * ======== ------->-------=============----new msg --> ======= + */ + +/* Includes ------------------------------------------------------------------*/ +#include "openamp/open_amp.h" +#include "stm32mp1xx_hal.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 */ + +/* 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) +{ + + if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_1, IPCC_CHANNEL_DIR_RX, + IPCC_channel1_callback) != HAL_OK) { + OPENAMP_log_err("%s: ch_1 RX fail\n", __func__); + return -1; + } + + if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_2, IPCC_CHANNEL_DIR_RX, + IPCC_channel2_callback) != HAL_OK) { + OPENAMP_log_err("%s: ch_2 RX fail\n", __func__); + 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; + OPENAMP_log_dbg("Send msg on ch_1\r\n"); + } + else if (id == VRING1_ID) { + /* Note: the OpenAMP framework never notifies this */ + channel = IPCC_CHANNEL_2; + OPENAMP_log_dbg("Send 'buff free' on ch_2\r\n"); + } + else { + OPENAMP_log_err("invalid vring (%d)\r\n", (int)id); + 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) { + OPENAMP_log_dbg("Waiting for channel to be freed\r\n"); + 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 */ + OPENAMP_log_dbg("Ack 'buff free' message on ch1\r\n"); + 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); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/openamp.c b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/openamp.c new file mode 100644 index 0000000000..08ef2d4c02 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/openamp.c @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file openamp.c + * @author MCD Application Team + * @brief Code for openamp applications + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 + * + ****************************************************************************** + */ + +#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 MX_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); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/openamp_log.c b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/openamp_log.c new file mode 100644 index 0000000000..7ce1ba6a2a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/openamp_log.c @@ -0,0 +1,102 @@ +/** + ****************************************************************************** + * @file log.c + * @author MCD Application Team + * @brief Ressource table + * + * This file provides services for logging + * + ****************************************************************************** + * + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 + * @{ + */ + +/** @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 + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/rsc_table.c b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/rsc_table.c new file mode 100644 index 0000000000..581636ddca --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/rsc_table.c @@ -0,0 +1,174 @@ +/** + ****************************************************************************** + * @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 + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 RSC_TABLE + * @{ + */ + +/** @addtogroup resource_table + * @{ + */ + +/** @addtogroup resource_table_Private_Includes + * @{ + */ + +#if defined(__ICCARM__) || defined (__CC_ARM) +#include <stddef.h> /* 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 (LINUX_RPROC_MASTER) + #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 (LINUX_RPROC_MASTER) + +/* 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 (LINUX_RPROC_MASTER) + .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 (LINUX_RPROC_MASTER) +#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/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c index be1449028d..d31aa64197 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c +++ b/bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c @@ -73,6 +73,11 @@ void HAL_MspInit(void) /* System interrupt init*/ /* USER CODE BEGIN MspInit 1 */ +#if !defined(BSP_USING_OPENAMP) + __HAL_RCC_SYSRAM_CLK_ENABLE(); + __HAL_RCC_RETRAM_CLK_ENABLE(); +#endif + HAL_NVIC_SetPriority(RCC_WAKEUP_IRQn, 0, 0); HAL_NVIC_EnableIRQ(RCC_WAKEUP_IRQn); __HAL_RCC_ENABLE_IT(RCC_IT_WKUP); @@ -284,7 +289,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim) /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1; - PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE; + PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); @@ -531,12 +536,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) __HAL_RCC_GPIOF_CLK_ENABLE(); /**SPI5 GPIO Configuration PF9 ------> SPI5_MOSI + PF8 ------> SPI5_MISO PF7 ------> SPI5_SCK */ - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_7; + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI5; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/Kconfig b/bsp/stm32/stm32mp157a-st-discovery/board/Kconfig index 139b94e9d5..6f8ee6d865 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/Kconfig +++ b/bsp/stm32/stm32mp157a-st-discovery/board/Kconfig @@ -32,6 +32,12 @@ menu "Onboard Peripheral Drivers" config BSP_USING_RCC bool "Enable rcc use sample" default n + + config BSP_USING_OPENAMP + bool "Enable OpenAMP" + select RT_USING_OPENAMP + default n + endmenu menu "On-chip Peripheral Drivers" diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/SConscript b/bsp/stm32/stm32mp157a-st-discovery/board/SConscript index b6a3eb30b1..305b3e60d4 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/SConscript +++ b/bsp/stm32/stm32mp157a-st-discovery/board/SConscript @@ -13,6 +13,9 @@ CubeMX_Config/Common/System/system_stm32mp1xx.c CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c ''') +if GetDepend(['BSP_USING_SPI5']): + src += Glob('ports/spi_sample.c') + if GetDepend(['BSP_USING_RCC']): src += Glob('ports/drv_rcc.c') @@ -34,10 +37,32 @@ if GetDepend(['BSP_USING_TIM14']): if GetDepend(['BSP_USING_PMIC']): src += Glob('ports/drv_pmic.c') +if GetDepend(['BSP_USING_OPENAMP']): + src += Glob('CubeMX_Config/CM4/Src/ipcc.c') + src += Glob('CubeMX_Config/CM4/Src/openamp.c') + src += Glob('CubeMX_Config/CM4/Src/openamp_log.c') + src += Glob('CubeMX_Config/CM4/Src/mbox_ipcc.c') + src += Glob('CubeMX_Config/CM4/Src/rsc_table.c') + src += Glob('ports/OpenAMP/libmetal/lib/*.c') + src += Glob('ports/OpenAMP/libmetal/lib/system/generic/*.c') + src += Glob('ports/OpenAMP/libmetal/lib/system/generic/cortexm/*.c') + src += Glob('ports/OpenAMP/open-amp/lib/rpmsg/*.c') + src += Glob('ports/OpenAMP/open-amp/lib/remoteproc/*.c') + src += Glob('ports/OpenAMP/open-amp/lib/virtio/*.c') + src += Glob('ports/OpenAMP/virtual_driver/*.c') + src += Glob('ports/OpenAMP/drv_openamp.c') + path = [cwd] path += [cwd + '/CubeMX_Config/CM4/Inc'] path += [cwd + '/ports'] +if GetDepend(['BSP_USING_OPENAMP']): + path += [cwd + '/ports/OpenAMP'] + path += [cwd + '/ports/OpenAMP/open-amp/lib/include'] + path += [cwd + '/ports/OpenAMP/libmetal/lib/include'] + path += [cwd + '/ports/OpenAMP/virtual_driver'] + path += [cwd + '/CubeMX_Config/CM4/Inc'] + startup_path_prefix = SDK_LIB if rtconfig.CROSS_TOOL == 'gcc': diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/board.c b/bsp/stm32/stm32mp157a-st-discovery/board/board.c index 0a7bda208a..cb44c09515 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/board.c +++ b/bsp/stm32/stm32mp157a-st-discovery/board/board.c @@ -28,13 +28,17 @@ void SystemClock_Config(void) /**Initializes the CPU, AHB and APB busses clocks */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE - |RCC_OSCILLATORTYPE_LSE; - RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS_DIG; - RCC_OscInitStruct.LSEState = RCC_LSE_ON; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSICalibrationValue = 16; - RCC_OscInitStruct.HSIDivValue = RCC_HSI_DIV1; + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI + |RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE + |RCC_OSCILLATORTYPE_CSI; + RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS_DIG; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = 0x0; /* Default reset value */ + RCC_OscInitStruct.HSIDivValue = RCC_HSI_DIV1; + RCC_OscInitStruct.LSIState = RCC_LSI_ON; + RCC_OscInitStruct.CSIState = RCC_CSI_ON; + RCC_OscInitStruct.CSICalibrationValue = 0x10; /* Default reset value */ /**PLL1 Config */ @@ -166,7 +170,7 @@ void rt_hw_board_init() #if defined(RT_USING_HEAP) rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); #endif - + /* Pin driver initialization is open by default */ #ifdef RT_USING_PIN rt_hw_pin_init(); diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/board.h b/bsp/stm32/stm32mp157a-st-discovery/board/board.h index b23b83ee30..23fac89b39 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/board.h +++ b/bsp/stm32/stm32mp157a-st-discovery/board/board.h @@ -22,23 +22,25 @@ extern "C" { #endif -#define STM32_FLASH_START_ADRESS ((uint32_t)0x10000000) -#define STM32_FLASH_SIZE (256 * 1024) +#define STM32_FLASH_START_ADRESS ((uint32_t)0x10000000) +#if defined(BSP_USING_OPENAMP) +#define STM32_FLASH_SIZE (64 * 1024) +#else +#define STM32_FLASH_SIZE (256 * 1024) +#endif #define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE)) -#define STM32_SRAM_SIZE (128) -#define STM32_SRAM_END ((uint32_t)0x10040000 + (STM32_SRAM_SIZE * 1024)) - -#if defined(__CC_ARM) || defined(__CLANG_ARM) -extern int Image$$RW_IRAM1$$ZI$$Limit; -#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) -#elif __ICCARM__ -#pragma section="CSTACK" -#define HEAP_BEGIN (__segment_end("CSTACK")) + +#if defined(BSP_USING_OPENAMP) +#define STM32_SRAM_BEGIN (uint32_t)0x10020000 #else -extern int __bss_end__; -#define HEAP_BEGIN (0x10040000 + 64 * 1024) +#define STM32_SRAM_BEGIN (uint32_t)0x2FFF0000 #endif +#define STM32_SRAM_SIZE (64) +#define STM32_SRAM_END (STM32_SRAM_BEGIN + (STM32_SRAM_SIZE * 1024)) + +#define HEAP_BEGIN STM32_SRAM_BEGIN +#define HEAP_END STM32_SRAM_END #define HEAP_END STM32_SRAM_END diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/linker_scripts/link.icf b/bsp/stm32/stm32mp157a-st-discovery/board/linker_scripts/link.icf index c24e2cbc45..543a8a37d2 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/linker_scripts/link.icf +++ b/bsp/stm32/stm32mp157a-st-discovery/board/linker_scripts/link.icf @@ -1,28 +1,44 @@ /*###ICF### Section handled by ICF editor, don't touch! ****/ /*-Editor annotation file-*/ -/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */ /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x00000000; /*-Memory Regions-*/ -define symbol __ICFEDIT_region_ROM_start__ = 0x10000000; -define symbol __ICFEDIT_region_ROM_end__ = 0x1003FFFF; -define symbol __ICFEDIT_region_RAM_start__ = 0x10040000; -define symbol __ICFEDIT_region_RAM_end__ = 0x1005FFFF; +define symbol __ICFEDIT_region_text_start__ = 0x10000000; +define symbol __ICFEDIT_region_text_end__ = 0x1001FFFF; +define symbol __ICFEDIT_region_data_start__ = 0x10030000; +define symbol __ICFEDIT_region_data_end__ = 0x1003FFFF; /*-Sizes-*/ define symbol __ICFEDIT_size_cstack__ = 0x400; define symbol __ICFEDIT_size_heap__ = 0x000; /**** End of ICF editor section. ###ICF###*/ define memory mem with size = 4G; -define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; -define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region text_region = mem:[from __ICFEDIT_region_text_start__ to __ICFEDIT_region_text_end__]; +define region data_region = mem:[from __ICFEDIT_region_data_start__ to __ICFEDIT_region_data_end__]; + +keep { section .resource_table }; +".resource_table" : place in data_region {section .resource_table}; + +/* Create region for OPENAMP */ +/* !!! These 4 lines can be commented if OPENAMP is not used !!!*/ +define symbol __OPENAMP_region_start__ = 0x10040000; +define symbol __OPENAMP_region_size__ = 0x8000; +export symbol __OPENAMP_region_start__; +export symbol __OPENAMP_region_size__; + +define symbol __SDMMC_region_start__ = 0x10048000; +define symbol __SDMMC_region_size__ = 0x1FFFF; +export symbol __SDMMC_region_start__; +export symbol __SDMMC_region_size__; define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; initialize by copy { readwrite }; -do not initialize { section .noinit }; +do not initialize { section .noinit}; place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; - -place in ROM_region { readonly }; -place in RAM_region { readwrite, last block CSTACK}; +place in text_region { readonly }; +place in data_region { readwrite, + block CSTACK, block HEAP}; diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/drv_openamp.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/drv_openamp.c new file mode 100644 index 0000000000..2705f068a3 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/drv_openamp.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-24 thread-liu first version + */ + +#include <board.h> + +#ifdef BSP_USING_OPENAMP + +#include <drv_openamp.h> +#include <openamp.h> +#include <virt_uart.h> +#include <openamp/rpmsg_virtio.h> + +//#define DRV_DEBUG +#define LOG_TAG "drv.openamp" +#include <drv_log.h> + +IPCC_HandleTypeDef hipcc; +static VIRT_UART_HandleTypeDef huart0; + +static rt_uint8_t rx_buffer[MAX_BUFFER_SIZE]; +static rt_uint8_t tx_buffer[MAX_BUFFER_SIZE]; + +struct rthw_openamp +{ + struct rt_device parent; + struct rt_openamp serial; + struct rt_semaphore sema; +}; +static struct rthw_openamp dev_openamp; + +void IPCC_RX1_IRQHandler(void) +{ + rt_interrupt_enter(); + + HAL_IPCC_RX_IRQHandler(&hipcc); + + rt_interrupt_leave(); +} + +void IPCC_TX1_IRQHandler(void) +{ + rt_interrupt_enter(); + + HAL_IPCC_TX_IRQHandler(&hipcc); + + rt_interrupt_leave(); +} + +void VIRT_UART0_RxCpltCallback(VIRT_UART_HandleTypeDef *huart) +{ + rt_uint16_t rx_size = 0, i = 0; + rt_size_t count, size, offset; + rt_uint8_t *buf = RT_NULL; + + struct rthw_openamp *device; + device = (struct rthw_openamp *)rt_device_find("openamp"); + RT_ASSERT(device != RT_NULL); + + buf = device->serial.rbuf; + count = device->serial.rbuf_count; + size = device->serial.rbuf_size; + offset = device->serial.rbuf_start + count; + + rt_sem_take(&device->sema, RT_WAITING_FOREVER); + + rx_size = (huart->RxXferSize < MAX_BUFFER_SIZE) ? huart->RxXferSize : MAX_BUFFER_SIZE - 1; + + if (count < size) + { + if (offset >= size) + { + offset -= size; + } + + for (i = 0; i < rx_size; i++) + { + buf[offset++] = huart->pRxBuffPtr[i]; + count++; + } + } + + device->serial.rbuf_count = count; + + rt_sem_release(&device->sema); +} + +static rt_err_t _init(struct rt_device *dev) +{ + struct rthw_openamp *device; + device = (struct rthw_openamp *)dev; + RT_ASSERT(device != RT_NULL); + + device->serial.rbuf_start = 0; + device->serial.rbuf_count = 0; + device->serial.tbuf_start = 0; + device->serial.tbuf_count = 0; + device->serial.rbuf_size = MAX_BUFFER_SIZE; + device->serial.tbuf_size = MAX_BUFFER_SIZE; + device->serial.rbuf = rx_buffer; + device->serial.tbuf = tx_buffer; + + if (rt_sem_init(&device->sema, "openamplock", 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + return RT_ERROR; + } + + return RT_EOK; +} + +static rt_size_t _read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_size_t count, rbsize, offset; + rt_uint8_t *buf = RT_NULL; + rt_uint8_t *pBuffer = RT_NULL; + rt_uint16_t i = 0; + + struct rthw_openamp *device; + device = (struct rthw_openamp *)dev; + RT_ASSERT(device != RT_NULL); + + pBuffer = (unsigned char*)buffer; + count = device->serial.rbuf_count; + buf = device->serial.rbuf; + + if (count == 0) + { + return -RT_ERROR; + } + + rt_sem_take(&device->sema, RT_WAITING_FOREVER); + + if (count >= size) + { + count = size; + } + + offset = device->serial.rbuf_start; + rbsize = device->serial.rbuf_size; + + for (i = 0; i < count; i++) + { + *pBuffer++ = buf[offset++]; + if (offset > rbsize) + { + offset = 0; + } + } + + device->serial.rbuf_start = offset; + device->serial.rbuf_count -= count; + + rt_sem_release(&device->sema); + + return count; +} + +static rt_size_t _write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_err_t result = VIRT_UART_OK; + + struct rthw_openamp *device; + device = (struct rthw_openamp *)dev; + RT_ASSERT(device != RT_NULL); + + rt_sem_take(&device->sema, RT_WAITING_FOREVER); + result = VIRT_UART_Transmit(&huart0, (uint8_t *)buffer, size); + rt_sem_release(&device->sema); + + if (result != VIRT_UART_OK) + { + return -RT_ERROR; + } + + return size; +} + +static rt_err_t rt_hw_openamp_register(struct rthw_openamp *openamp, const char *name, rt_uint32_t flag, void *data) +{ + struct rt_device *device; + RT_ASSERT(openamp != RT_NULL); + + device = &(openamp->parent); + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + + device->init = _init; + device->open = RT_NULL; + device->close = RT_NULL; + device->read = _read; + device->write = _write; + device->control = RT_NULL; + device->user_data = data; + + /* register a character device */ + return rt_device_register(device, name, flag); +} + +static int openamp_init(void) +{ + extern int MX_OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb); + + /* IPCC init */ + hipcc.Instance = IPCC; + if (HAL_IPCC_Init(&hipcc) != HAL_OK) + { + return RT_ERROR; + } + /* openamp slave device */ + MX_OPENAMP_Init(RPMSG_REMOTE, NULL); + + if (VIRT_UART_Init(&huart0) != VIRT_UART_OK) + { + return RT_ERROR; + } + if (VIRT_UART_RegisterCallback(&huart0, VIRT_UART_RXCPLT_CB_ID, VIRT_UART0_RxCpltCallback) != VIRT_UART_OK) + { + return RT_ERROR; + } + + return RT_EOK; +} + +int rt_hw_openamp_init(void) +{ + openamp_init(); + + rt_hw_openamp_register(&dev_openamp, "openamp", 0, NULL); + + rt_console_set_device("openamp"); + + return RT_EOK; +} +INIT_PREV_EXPORT(rt_hw_openamp_init); + +static void openamp_thread_entry(void *parameter) +{ + rt_size_t size = 0; + struct rthw_openamp *device = RT_NULL; + + device = (struct rthw_openamp *)rt_device_find("openamp"); + RT_ASSERT(device != RT_NULL); + + for (;;) + { + OPENAMP_check_for_message(); + + size = device->serial.rbuf_count; + if (size > 0) + { + if (device->parent.rx_indicate != RT_NULL) + { + device->parent.rx_indicate(&device->parent, size); + } + } + + rt_thread_mdelay(1); + } +} + +static int creat_openamp_thread(void) +{ + rt_thread_t tid = RT_NULL; + + tid = rt_thread_create("OpenAMP", + openamp_thread_entry, + RT_NULL, + OPENAMP_THREAD_STACK_SIZE, + OPENAMP_THREAD_PRIORITY, + OPENAMP_THREAD_TIMESLICE); + + if (tid == RT_NULL) + { + LOG_E("openamp thread create failed!"); + return RT_ERROR; + } + + rt_thread_startup(tid); + + return RT_EOK; +} +INIT_APP_EXPORT(creat_openamp_thread); + +#endif diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/drv_openamp.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/drv_openamp.h new file mode 100644 index 0000000000..df1533b38b --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/drv_openamp.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-24 thread-liu first version + */ + +#ifndef __DRV_OPENAMP_H__ +#define __DRV_OPENAMP_H__ + +#include "board.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct rt_openamp +{ + rt_uint8_t *rbuf; + rt_uint8_t *tbuf; + volatile rt_uint16_t rbuf_size; + volatile rt_uint16_t tbuf_size; + volatile rt_uint16_t rbuf_start; + volatile rt_uint16_t rbuf_count; + volatile rt_uint16_t tbuf_start; + volatile rt_uint16_t tbuf_count; +}; + +#define OPENAMP_THREAD_STACK_SIZE 512 +#define OPENAMP_THREAD_PRIORITY 5 +#define OPENAMP_THREAD_TIMESLICE 10 + +#define MAX_BUFFER_SIZE 256 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/dma.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/dma.c new file mode 100644 index 0000000000..baeb21bd2a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/dma.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/errno.h> +#include <string.h> +#include <metal/device.h> +#include <metal/log.h> +#include <metal/dma.h> +#include <metal/atomic.h> + +int metal_dma_map(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out) +{ + int nents_out; + + if (!dev || !sg_in || !sg_out) + return -EINVAL; + if (!dev->bus->ops.dev_dma_map) + return -ENODEV; + + /* memory barrier */ + if (dir == METAL_DMA_DEV_R) + /* If it is device read, apply memory write fence. */ + atomic_thread_fence(memory_order_release); + else + /* If it is device write or device r/w, + apply memory r/w fence. */ + atomic_thread_fence(memory_order_acq_rel); + nents_out = dev->bus->ops.dev_dma_map(dev->bus, + dev, dir, sg_in, nents_in, sg_out); + return nents_out; +} + +void metal_dma_unmap(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg, + int nents) +{ + /* memory barrier */ + if (dir == METAL_DMA_DEV_R) + /* If it is device read, apply memory write fence. */ + atomic_thread_fence(memory_order_release); + else + /* If it is device write or device r/w, + apply memory r/w fence. */ + atomic_thread_fence(memory_order_acq_rel); + + if (!dev || !dev->bus->ops.dev_dma_unmap || !sg) + return; + dev->bus->ops.dev_dma_unmap(dev->bus, + dev, dir, sg, nents); +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/alloc.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/alloc.h new file mode 100644 index 0000000000..0e2d070c9b --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/alloc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file alloc.h + * @brief Memory allocation handling primitives for libmetal. + */ + +#ifndef __METAL_ALLOC__H__ +#define __METAL_ALLOC__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup Memory Allocation Interfaces + * @{ */ + +/** + * @brief allocate requested memory size + * return a pointer to the allocated memory + * + * @param[in] size size in byte of requested memory + * @return memory pointer, or 0 if it failed to allocate + */ +static inline void *metal_allocate_memory(unsigned int size); + +/** + * @brief free the memory previously allocated + * + * @param[in] ptr pointer to memory + */ +static inline void metal_free_memory(void *ptr); + +#include <metal/system/generic/alloc.h> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_ALLOC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/assert.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/assert.h new file mode 100644 index 0000000000..4476b641ae --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/assert.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file assert.h + * @brief Assertion support. + */ + +#ifndef __METAL_ASSERT__H__ +#define __METAL_ASSERT__H__ + +#include <metal/system/generic/assert.h> + +/** + * @brief Assertion macro. + * @param cond Condition to test. + */ +#define metal_assert(cond) metal_sys_assert(cond) + +#endif /* __METAL_ASSERT_H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/atomic.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/atomic.h new file mode 100644 index 0000000000..f80c2971cd --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/atomic.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file atomic.h + * @brief Atomic primitives for libmetal. + */ + +#ifndef __METAL_ATOMIC__H__ +#define __METAL_ATOMIC__H__ + +#include <metal/config.h> + +#if defined(HAVE_STDATOMIC_H) && !defined (__CC_ARM) && \ + !defined(__STDC_NO_ATOMICS__) && !defined(__cplusplus) + +# include <stdatomic.h> + +#ifndef atomic_thread_fence +#define atomic_thread_fence(order) +#endif + +#elif defined(__GNUC__) +# include <metal/compiler/gcc/atomic.h> +#else +# include <metal/processor/arm/atomic.h> +#endif + +#endif /* __METAL_ATOMIC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/cache.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/cache.h new file mode 100644 index 0000000000..31a94abe2b --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/cache.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cache.h + * @brief CACHE operation primitives for libmetal. + */ + +#ifndef __METAL_CACHE__H__ +#define __METAL_CACHE__H__ + +#include <metal/system/generic/cache.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \defgroup cache CACHE Interfaces + * @{ */ + +/** + * @brief flush specified data cache + * + * @param[in] addr start memory logical address + * @param[in] len length of memory + * If addr is NULL, and len is 0, + * It will flush the whole data cache. + */ +static inline void metal_cache_flush(void *addr, unsigned int len) +{ + __metal_cache_flush(addr, len); +} + +/** + * @brief invalidate specified data cache + * + * @param[in] addr start memory logical address + * @param[in] len length of memory + * If addr is NULL, and len is 0, + * It will invalidate the whole data cache. + */ +static inline void metal_cache_invalidate(void *addr, unsigned int len) +{ + __metal_cache_invalidate(addr, len); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CACHE__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler.h new file mode 100644 index 0000000000..c581d4dc4f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file compiler.h + * @brief Compiler specific primitives for libmetal. + */ + +#ifndef __METAL_COMPILER__H__ +#define __METAL_COMPILER__H__ + +#if defined(__GNUC__) +# include <metal/compiler/gcc/compiler.h> +#elif defined(__ICCARM__) +# include <metal/compiler/iar/compiler.h> +#elif defined (__CC_ARM) +# error "MDK-ARM ARMCC compiler requires the GNU extentions to work correctly" +#else +# error "Missing compiler support" +#endif + +#endif /* __METAL_COMPILER__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/atomic.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/atomic.h new file mode 100644 index 0000000000..9d046785c8 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/atomic.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file gcc/atomic.h + * @brief GCC specific atomic primitives for libmetal. + */ + +#ifndef __METAL_GCC_ATOMIC__H__ +#define __METAL_GCC_ATOMIC__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int atomic_flag; +typedef char atomic_char; +typedef unsigned char atomic_uchar; +typedef short atomic_short; +typedef unsigned short atomic_ushort; +typedef int atomic_int; +typedef unsigned int atomic_uint; +typedef long atomic_long; +typedef unsigned long atomic_ulong; +typedef long long atomic_llong; +typedef unsigned long long atomic_ullong; + +#define ATOMIC_FLAG_INIT 0 +#define ATOMIC_VAR_INIT(VAL) (VAL) + +typedef enum { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst, +} memory_order; + +#define atomic_flag_test_and_set(FLAG) \ + __sync_lock_test_and_set((FLAG), 1) +#define atomic_flag_test_and_set_explicit(FLAG, MO) \ + atomic_flag_test_and_set(FLAG) +#define atomic_flag_clear(FLAG) \ + __sync_lock_release((FLAG)) +#define atomic_flag_clear_explicit(FLAG, MO) \ + atomic_flag_clear(FLAG) +#define atomic_init(OBJ, VAL) \ + do { *(OBJ) = (VAL); } while (0) +#define atomic_is_lock_free(OBJ) \ + (sizeof(*(OBJ)) <= sizeof(long)) +#define atomic_store(OBJ, VAL) \ + do { *(OBJ) = (VAL); __sync_synchronize(); } while (0) +#define atomic_store_explicit(OBJ, VAL, MO) \ + atomic_store((OBJ), (VAL)) +#define atomic_load(OBJ) \ + ({ __sync_synchronize(); *(OBJ); }) +#define atomic_load_explicit(OBJ, MO) \ + atomic_load(OBJ) +#define atomic_exchange(OBJ, DES) \ + ({ \ + typeof(OBJ) obj = (OBJ); \ + typeof(*obj) des = (DES); \ + typeof(*obj) expval; \ + typeof(*obj) oldval = atomic_load(obj); \ + do { \ + expval = oldval; \ + oldval = __sync_val_compare_and_swap( \ + obj, expval, des); \ + } while (oldval != expval); \ + oldval; \ + }) +#define atomic_exchange_explicit(OBJ, DES, MO) \ + atomic_exchange((OBJ), (DES)) +#define atomic_compare_exchange_strong(OBJ, EXP, DES) \ + ({ \ + typeof(OBJ) obj = (OBJ); \ + typeof(EXP) exp = (EXP); \ + typeof(*obj) expval = *exp; \ + typeof(*obj) oldval = __sync_val_compare_and_swap( \ + obj, expval, (DES)); \ + *exp = oldval; \ + oldval == expval; \ + }) +#define atomic_compare_exchange_strong_explicit(OBJ, EXP, DES, MO) \ + atomic_compare_exchange_strong((OBJ), (EXP), (DES)) +#define atomic_compare_exchange_weak(OBJ, EXP, DES) \ + atomic_compare_exchange_strong((OBJ), (EXP), (DES)) +#define atomic_compare_exchange_weak_explicit(OBJ, EXP, DES, MO) \ + atomic_compare_exchange_weak((OBJ), (EXP), (DES)) +#define atomic_fetch_add(OBJ, VAL) \ + __sync_fetch_and_add((OBJ), (VAL)) +#define atomic_fetch_add_explicit(OBJ, VAL, MO) \ + atomic_fetch_add((OBJ), (VAL)) +#define atomic_fetch_sub(OBJ, VAL) \ + __sync_fetch_and_sub((OBJ), (VAL)) +#define atomic_fetch_sub_explicit(OBJ, VAL, MO) \ + atomic_fetch_sub((OBJ), (VAL)) +#define atomic_fetch_or(OBJ, VAL) \ + __sync_fetch_and_or((OBJ), (VAL)) +#define atomic_fetch_or_explicit(OBJ, VAL, MO) \ + atomic_fetch_or((OBJ), (VAL)) +#define atomic_fetch_xor(OBJ, VAL) \ + __sync_fetch_and_xor((OBJ), (VAL)) +#define atomic_fetch_xor_explicit(OBJ, VAL, MO) \ + atomic_fetch_xor((OBJ), (VAL)) +#define atomic_fetch_and(OBJ, VAL) \ + __sync_fetch_and_and((OBJ), (VAL)) +#define atomic_fetch_and_explicit(OBJ, VAL, MO) \ + atomic_fetch_and((OBJ), (VAL)) +#define atomic_thread_fence(MO) \ + __sync_synchronize() +#define atomic_signal_fence(MO) \ + __sync_synchronize() + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GCC_ATOMIC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/compiler.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/compiler.h new file mode 100644 index 0000000000..fe6a11552f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/compiler.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file gcc/compiler.h + * @brief GCC specific primitives for libmetal. + */ + +#ifndef __METAL_GCC_COMPILER__H__ +#define __METAL_GCC_COMPILER__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define restrict __restrict__ +#define metal_align(n) __attribute__((aligned(n))) +#define metal_weak __attribute__((weak)) + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GCC_COMPILER__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/compiler.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/compiler.h new file mode 100644 index 0000000000..618ba2cc16 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/compiler.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, ST Microelectronics. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file iar/compiler.h + * @brief IAR specific primitives for libmetal. + */ + +#ifndef __METAL_IAR_COMPILER__H__ +#define __METAL_IAR_COMPILER__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define restrict __restrict__ +#define metal_align(n) __attribute__((aligned(n))) +#define metal_weak __attribute__((weak)) + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_IAR_COMPILER__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/errno.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/errno.h new file mode 100644 index 0000000000..d05461c073 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/errno.h @@ -0,0 +1,289 @@ +/* + * * Copyright (c) 2019 STMicroelectronics. All rights reserved. + * * + * * Copyright (c) 1982, 1986, 1989, 1993 + * * The Regents of the University of California. All rights reserved. + * * Copyright (c) 1982, 1986, 1989, 1993 + * * The Regents of the University of California. All rights reserved. + * * (c) UNIX System Laboratories, Inc. + * * All or some portions of this file are derived from material licensed + * * to the University of California by American Telephone and Telegraph + * * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * * the permission of UNIX System Laboratories, Inc. + * + * * SPDX-License-Identifier: BSD-3-Clause + * */ + +#ifndef __METAL_ERRNO__H__ +#error "Include metal/errno.h instead of metal/iar/errno.h" +#endif + +#ifndef _ERRNO_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _ERRNO_H_ + + +#ifndef EPERM +#define EPERM 1 /* Not owner */ +#endif +#ifndef ENOENT +#define ENOENT 2 /* No such file or directory */ +#endif +#ifndef ESRCH +#define ESRCH 3 /* No such process */ +#endif +#ifndef EINTR +#define EINTR 4 /* Interrupted system call */ +#endif +#ifndef EIO +#define EIO 5 /* I/O error */ +#endif +#ifndef ENXIO +#define ENXIO 6 /* No such device or address */ +#endif +#ifndef E2BIG +#define E2BIG 7 /* Arg list too long */ +#endif +#ifndef ENOEXEC +#define ENOEXEC 8 /* Exec format error */ +#endif +#ifndef EBADF +#define EBADF 9 /* Bad file number */ +#endif +#ifndef ECHILD +#define ECHILD 10 /* No children */ +#endif +#ifndef EAGAIN +#define EAGAIN 11 /* No more processes */ +#endif +#ifndef ENOMEM +#define ENOMEM 12 /* Not enough space */ +#endif +#ifndef EACCES +#define EACCES 13 /* Permission denied */ +#endif +#ifndef EFAULT +#define EFAULT 14 /* Bad address */ +#endif +#ifndef EBUSY +#define EBUSY 16 /* Device or resource busy */ +#endif +#ifndef EEXIST +#define EEXIST 17 /* File exists */ +#endif +#ifndef EXDEV +#define EXDEV 18 /* Cross-device link */ +#endif +#ifndef ENODEV +#define ENODEV 19 /* No such device */ +#endif +#ifndef ENOTDIR +#define ENOTDIR 20 /* Not a directory */ +#endif +#ifndef EISDIR +#define EISDIR 21 /* Is a directory */ +#endif +#ifndef EINVAL +#define EINVAL 22 /* Invalid argument */ +#endif +#ifndef ENFILE +#define ENFILE 23 /* Too many open files in system */ +#endif +#ifndef EMFILE +#define EMFILE 24 /* File descriptor value too large */ +#endif +#ifndef ENOTTY +#define ENOTTY 25 /* Not a character device */ +#endif +#ifndef ETXTBSY +#define ETXTBSY 26 /* Text file busy */ +#endif +#ifndef EFBIG +#define EFBIG 27 /* File too large */ +#endif +#ifndef ENOSPC +#define ENOSPC 28 /* No space left on device */ +#endif +#ifndef ESPIPE +#define ESPIPE 29 /* Illegal seek */ +#endif +#ifndef EROFS +#define EROFS 30 /* Read-only file system */ +#endif +#ifndef EMLINK +#define EMLINK 31 /* Too many links */ +#endif +#ifndef EPIPE +#define EPIPE 32 /* Broken pipe */ +#endif +#ifndef EDOM +#define EDOM 33 /* Mathematics argument out of domain of function */ +#endif +#ifndef ERANGE +#define ERANGE 34 /* Result too large */ +#endif +#ifndef ENOMSG +#define ENOMSG 35 /* No message of desired type */ +#endif +#ifndef EIDRM +#define EIDRM 36 /* Identifier removed */ +#endif +#ifndef EDEADLK +#define EDEADLK 45 /* Deadlock */ +#endif +#ifndef ENOLCK +#define ENOLCK 46 /* No lock */ +#endif +#ifndef ENOSTR +#define ENOSTR 60 /* Not a stream */ +#endif +#ifndef ENODATA +#define ENODATA 61 /* No data (for no delay io) */ +#endif +#ifndef ETIME +#define ETIME 62 /* Stream ioctl timeout */ +#endif +#ifndef ENOSR +#define ENOSR 63 /* No stream resources */ +#endif +#ifndef ENOLINK +#define ENOLINK 67 /* Virtual circuit is gone */ +#endif +#ifndef EPROTO +#define EPROTO 71 /* Protocol error */ +#endif +#ifndef EMULTIHOP +#define EMULTIHOP 74 /* Multihop attempted */ +#endif +#ifndef EBADMSG +#define EBADMSG 77 /* Bad message */ +#endif +#ifndef EFTYPE +#define EFTYPE 79 /* Inappropriate file type or format */ +#endif +#ifndef ENOSYS +#define ENOSYS 88 /* Function not implemented */ +#endif +#ifndef ENOTEMPTY +#define ENOTEMPTY 90 /* Directory not empty */ +#endif +#ifndef ENAMETOOLONG +#define ENAMETOOLONG 91 /* File or path name too long */ +#endif +#ifndef ELOOP +#define ELOOP 92 /* Too many symbolic links */ +#endif +#ifndef EOPNOTSUPP +#define EOPNOTSUPP 95 /* Operation not supported on socket */ +#endif +#ifndef EPFNOSUPPORT +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#endif +#ifndef ECONNRESET +#define ECONNRESET 104 /* Connection reset by peer */ +#endif +#ifndef ENOBUFS +#define ENOBUFS 105 /* No buffer space available */ +#endif +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */ +#endif +#ifndef EPROTOTYPE +#define EPROTOTYPE 107 /* Protocol wrong type for socket */ +#endif +#ifndef ENOTSOCK +#define ENOTSOCK 108 /* Socket operation on non-socket */ +#endif +#ifndef ENOPROTOOPT +#define ENOPROTOOPT 109 /* Protocol not available */ +#endif +#ifndef ECONNREFUSED +#define ECONNREFUSED 111 /* Connection refused */ +#endif +#ifndef EADDRINUSE +#define EADDRINUSE 112 /* Address already in use */ +#endif +#ifndef ECONNABORTED +#define ECONNABORTED 113 /* Software caused connection abort */ +#endif +#ifndef ENETUNREACH +#define ENETUNREACH 114 /* Network is unreachable */ +#endif +#ifndef ENETDOWN +#define ENETDOWN 115 /* Network interface is not configured */ +#endif +#ifndef ETIMEDOUT +#define ETIMEDOUT 116 /* Connection timed out */ +#endif +#ifndef EHOSTDOWN +#define EHOSTDOWN 117 /* Host is down */ +#endif +#ifndef EHOSTUNREACH +#define EHOSTUNREACH 118 /* Host is unreachable */ +#endif +#ifndef EINPROGRESS +#define EINPROGRESS 119 /* Connection already in progress */ +#endif +#ifndef EALREADY +#define EALREADY 120 /* Socket already connected */ +#endif +#ifndef EDESTADDRREQ +#define EDESTADDRREQ 121 /* Destination address required */ +#endif +#ifndef EMSGSIZE +#define EMSGSIZE 122 /* Message too long */ +#endif +#ifndef EPROTONOSUPPORT +#define EPROTONOSUPPORT 123 /* Unknown protocol */ +#endif +#ifndef EADDRNOTAVAIL +#define EADDRNOTAVAIL 125 /* Address not available */ +#endif +#ifndef ENETRESET +#define ENETRESET 126 /* Connection aborted by network */ +#endif +#ifndef EISCONN +#define EISCONN 127 /* Socket is already connected */ +#endif +#ifndef ENOTCONN +#define ENOTCONN 128 /* Socket is not connected */ +#endif +#ifndef ETOOMANYREFS +#define ETOOMANYREFS 129 +#endif +#ifndef EDQUOT +#define EDQUOT 132 +#endif +#ifndef ESTALE +#define ESTALE 133 +#endif +#ifndef ENOTSUP +#define ENOTSUP 134 /* Not supported */ +#endif +#ifndef EILSEQ +#define EILSEQ 138 /* Illegal byte sequence */ +#endif +#ifndef EOVERFLOW +#define EOVERFLOW 139 /* Value too large for defined data type */ +#endif +#ifndef ECANCELED +#define ECANCELED 140 /* Operation canceled */ +#endif +#ifndef ENOTRECOVERABLE +#define ENOTRECOVERABLE 141 /* State not recoverable */ +#endif +#ifndef EOWNERDEAD +#define EOWNERDEAD 142 /* Previous owner died */ +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#endif + +#define __ELASTERROR 2000 /* Users can add values starting here */ + +#ifdef __cplusplus +} +#endif +#endif /* _ERRNO_H */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/mdk-arm/errno.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/mdk-arm/errno.h new file mode 100644 index 0000000000..5fc060eabb --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/mdk-arm/errno.h @@ -0,0 +1,137 @@ +/* + * * Copyright (c) 2019 STMicroelectronics. All rights reserved. + * * + * * Copyright (c) 1982, 1986, 1989, 1993 + * * The Regents of the University of California. All rights reserved. + * * Copyright (c) 1982, 1986, 1989, 1993 + * * The Regents of the University of California. All rights reserved. + * * (c) UNIX System Laboratories, Inc. + * * All or some portions of this file are derived from material licensed + * * to the University of California by American Telephone and Telegraph + * * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * * the permission of UNIX System Laboratories, Inc. + * + * * SPDX-License-Identifier: BSD-3-Clause + * */ + + +#ifndef __METAL_ERRNO__H__ +#error "Include metal/errno.h instead of metal/mdk-arm/errno.h" +#endif + +#ifndef _ERRNO_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _ERRNO_H_ + +#define EPERM 1 /* Not owner */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No children */ +#define EAGAIN 11 /* No more processes */ +#ifdef ENOMEM +#undef ENOMEM +#endif +#define ENOMEM 12 /* Not enough space */ + +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#ifdef EINVAL +#undef EINVAL +#endif +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* File descriptor value too large */ +#define ENOTTY 25 /* Not a character device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#ifdef EDOM +#undef EDOM +#endif +#define EDOM 33 /* Mathematics argument out of domain of function */ + +#ifdef ERANGE +#undef ERANGE +#endif +#define ERANGE 34 /* Result too large */ + +#define ENOMSG 35 /* No message of desired type */ +#define EIDRM 36 /* Identifier removed */ +#define EDEADLK 45 /* Deadlock */ +#define ENOLCK 46 /* No lock */ +#define ENOSTR 60 /* Not a stream */ +#define ENODATA 61 /* No data (for no delay io) */ +#define ETIME 62 /* Stream ioctl timeout */ +#define ENOSR 63 /* No stream resources */ +#define ENOLINK 67 /* Virtual circuit is gone */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 74 /* Multihop attempted */ +#define EBADMSG 77 /* Bad message */ +#define EFTYPE 79 /* Inappropriate file type or format */ +#define ENOSYS 88 /* Function not implemented */ +#define ENOTEMPTY 90 /* Directory not empty */ +#define ENAMETOOLONG 91 /* File or path name too long */ +#define ELOOP 92 /* Too many symbolic links */ +#define EOPNOTSUPP 95 /* Operation not supported on socket */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */ +#define EPROTOTYPE 107 /* Protocol wrong type for socket */ +#define ENOTSOCK 108 /* Socket operation on non-socket */ +#define ENOPROTOOPT 109 /* Protocol not available */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EADDRINUSE 112 /* Address already in use */ +#define ECONNABORTED 113 /* Software caused connection abort */ +#define ENETUNREACH 114 /* Network is unreachable */ +#define ENETDOWN 115 /* Network interface is not configured */ +#define ETIMEDOUT 116 /* Connection timed out */ +#define EHOSTDOWN 117 /* Host is down */ +#define EHOSTUNREACH 118 /* Host is unreachable */ +#define EINPROGRESS 119 /* Connection already in progress */ +#define EALREADY 120 /* Socket already connected */ +#define EDESTADDRREQ 121 /* Destination address required */ +#define EMSGSIZE 122 /* Message too long */ +#define EPROTONOSUPPORT 123 /* Unknown protocol */ +#define EADDRNOTAVAIL 125 /* Address not available */ +#define ENETRESET 126 /* Connection aborted by network */ +#define EISCONN 127 /* Socket is already connected */ +#define ENOTCONN 128 /* Socket is not connected */ +#define ETOOMANYREFS 129 +#define EDQUOT 132 +#define ESTALE 133 +#define ENOTSUP 134 /* Not supported */ +#ifdef EILSEQ +#undef EILSEQ +#endif +#define EILSEQ 138 /* Illegal byte sequence */ +#define EOVERFLOW 139 /* Value too large for defined data type */ +#define ECANCELED 140 /* Operation canceled */ +#define ENOTRECOVERABLE 141 /* State not recoverable */ +#define EOWNERDEAD 142 /* Previous owner died */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ + +#define __ELASTERROR 2000 /* Users can add values starting here */ + +#ifdef __cplusplus +} +#endif +#endif /* _ERRNO_H */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/condition.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/condition.h new file mode 100644 index 0000000000..fc0cc0dcab --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/condition.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file condition.h + * @brief Condition variable for libmetal. + */ + +#ifndef __METAL_CONDITION__H__ +#define __METAL_CONDITION__H__ + +#include <metal/mutex.h> +#include <metal/utilities.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup condition Condition Variable Interfaces + * @{ */ + +/** Opaque libmetal condition variable data structure. */ +struct metal_condition; + +/** + * @brief Initialize a libmetal condition variable. + * @param[in] cv condition variable to initialize. + */ +static inline void metal_condition_init(struct metal_condition *cv); + +/** + * @brief Notify one waiter. + * Before calling this function, the caller + * should have acquired the mutex. + * @param[in] cv condition variable + * @return zero on no errors, non-zero on errors + * @see metal_condition_wait, metal_condition_broadcast + */ +static inline int metal_condition_signal(struct metal_condition *cv); + +/** + * @brief Notify all waiters. + * Before calling this function, the caller + * should have acquired the mutex. + * @param[in] cv condition variable + * @return zero on no errors, non-zero on errors + * @see metal_condition_wait, metal_condition_signal + */ +static inline int metal_condition_broadcast(struct metal_condition *cv); + +/** + * @brief Block until the condition variable is notified. + * Before calling this function, the caller should + * have acquired the mutex. + * @param[in] cv condition variable + * @param[in] m mutex + * @return 0 on success, non-zero on failure. + * @see metal_condition_signal + */ +int metal_condition_wait(struct metal_condition *cv, metal_mutex_t *m); + +#include <metal/system/generic/condition.h> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CONDITION__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/config.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/config.h new file mode 100644 index 0000000000..256efa3861 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/config.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file config.h + * @brief Generated configuration settings for libmetal. + */ + +#ifndef __METAL_CONFIG__H__ +#define __METAL_CONFIG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Library major version number. */ +#define METAL_VER_MAJOR 0 + +/** Library minor version number. */ +#define METAL_VER_MINOR 1 + +/** Library patch level. */ +#define METAL_VER_PATCH 0 + +/** Library version string. */ +#define METAL_VER "0.1.0" + +/** System type (linux, generic, ...). */ +#define METAL_SYSTEM "generic" +#define METAL_SYSTEM_GENERIC + +/** Processor type (arm, x86_64, ...). */ +#define METAL_PROCESSOR "arm" +#define METAL_PROCESSOR_ARM + +/** Machine type (zynq, zynqmp, ...). */ +#define METAL_MACHINE "cortexm" +#define METAL_MACHINE_CORTEXM + +#define HAVE_STDATOMIC_H +/* #undef HAVE_FUTEX_H */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CONFIG__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/cpu.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/cpu.h new file mode 100644 index 0000000000..26dbaa2af7 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/cpu.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cpu.h + * @brief CPU primitives for libmetal. + */ + +#ifndef __METAL_CPU__H__ +#define __METAL_CPU__H__ + +# include <metal/processor/arm/cpu.h> + +#endif /* __METAL_CPU__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/device.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/device.h new file mode 100644 index 0000000000..5ed43d63b7 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/device.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file device.h + * @brief Bus abstraction for libmetal. + */ + +#ifndef __METAL_BUS__H__ +#define __METAL_BUS__H__ + +#include <stdint.h> +#include <metal/io.h> +#include <metal/list.h> +#include <metal/dma.h> +#include <metal/sys.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup device Bus Abstraction + * @{ */ + +#ifndef METAL_MAX_DEVICE_REGIONS +#define METAL_MAX_DEVICE_REGIONS 32 +#endif + +struct metal_bus; +struct metal_device; + +/** Bus operations. */ +struct metal_bus_ops { + void (*bus_close)(struct metal_bus *bus); + int (*dev_open)(struct metal_bus *bus, + const char *dev_name, + struct metal_device **device); + void (*dev_close)(struct metal_bus *bus, + struct metal_device *device); + void (*dev_irq_ack)(struct metal_bus *bus, + struct metal_device *device, + int irq); + int (*dev_dma_map)(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); + void (*dev_dma_unmap)(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents); +}; + +/** Libmetal bus structure. */ +struct metal_bus { + const char *name; + struct metal_bus_ops ops; + struct metal_list devices; + struct metal_list node; +}; + +/** Libmetal generic bus. */ +extern struct metal_bus metal_generic_bus; + +/** Libmetal device structure. */ +struct metal_device { + const char *name; /**< Device name */ + struct metal_bus *bus; /**< Bus that contains device */ + unsigned num_regions; /**< Number of I/O regions in + device */ + struct metal_io_region regions[METAL_MAX_DEVICE_REGIONS]; /**< Array of + I/O regions in device*/ + struct metal_list node; /**< Node on bus' list of devices */ + int irq_num; /**< Number of IRQs per device */ + void *irq_info; /**< IRQ ID */ +}; + +/** + * @brief Register a libmetal bus. + * @param[in] bus Pre-initialized bus structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_register(struct metal_bus *bus); + +/** + * @brief Unregister a libmetal bus. + * @param[in] bus Pre-registered bus structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_unregister(struct metal_bus *bus); + +/** + * @brief Find a libmetal bus by name. + * @param[in] name Bus name. + * @param[out] bus Returned bus handle. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_find(const char *name, struct metal_bus **bus); + +/** + * @brief Statically register a generic libmetal device. + * + * In non-Linux systems, devices are always required to be statically + * registered at application initialization. + * In Linux system, devices can be dynamically opened via sysfs or libfdt based + * enumeration at runtime. + * This interface is used for static registration of devices. Subsequent calls + * to metal_device_open() look up in this list of pre-registered devices on the + * "generic" bus. + * "generic" bus is used on non-Linux system to group the memory mapped devices. + * + * @param[in] device Generic device. + * @return 0 on success, or -errno on failure. + */ +extern int metal_register_generic_device(struct metal_device *device); + +/** + * @brief Open a libmetal device by name. + * @param[in] bus_name Bus name. + * @param[in] dev_name Device name. + * @param[out] device Returned device handle. + * @return 0 on success, or -errno on failure. + */ +extern int metal_device_open(const char *bus_name, const char *dev_name, + struct metal_device **device); + +/** + * @brief Close a libmetal device. + * @param[in] device Device handle. + */ +extern void metal_device_close(struct metal_device *device); + +/** + * @brief Get an I/O region accessor for a device region. + * + * @param[in] device Device handle. + * @param[in] index Region index. + * @return I/O accessor handle, or NULL on failure. + */ +static inline struct metal_io_region * +metal_device_io_region(struct metal_device *device, unsigned index) +{ + return (index < device->num_regions + ? &device->regions[index] + : NULL); +} + +/** @} */ + +#ifdef METAL_INTERNAL +extern int metal_generic_dev_sys_open(struct metal_device *dev); +extern int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name, + struct metal_device **device); +extern int metal_generic_dev_dma_map(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); +extern void metal_generic_dev_dma_unmap(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents); +#endif /* METAL_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_BUS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/dma.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/dma.h new file mode 100644 index 0000000000..6675adc347 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/dma.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file dma.h + * @brief DMA primitives for libmetal. + */ + +#ifndef __METAL_DMA__H__ +#define __METAL_DMA__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup dma DMA Interfaces + * @{ */ + +#include <stdint.h> +#include <metal/sys.h> + +#define METAL_DMA_DEV_R 1 /**< DMA direction, device read */ +#define METAL_DMA_DEV_W 2 /**< DMA direction, device write */ +#define METAL_DMA_DEV_WR 3 /**< DMA direction, device read/write */ + +/** + * @brief scatter/gather list element structure + */ +struct metal_sg { + void *virt; /**< CPU virtual address */ + struct metal_io_region *io; /**< IO region */ + int len; /**< length */ +}; + +struct metal_device; + +/** + * @brief Map memory for DMA transaction. + * After the memory is DMA mapped, the memory should be + * accessed by the DMA device but not the CPU. + * + * @param[in] dev DMA device + * @param[in] dir DMA direction + * @param[in] sg_in sg list of memory to map + * @param[in] nents_in number of sg list entries of memory to map + * @param[out] sg_out sg list of mapped memory + * @return number of mapped sg entries, -error on failure. + */ +int metal_dma_map(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); + +/** + * @brief Unmap DMA memory + * After the memory is DMA unmapped, the memory should + * be accessed by the CPU but not the DMA device. + * + * @param[in] dev DMA device + * @param[in] dir DMA direction + * @param[in] sg sg list of mapped DMA memory + * @param[in] nents number of sg list entries of DMA memory + */ +void metal_dma_unmap(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg, + int nents); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_DMA__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/errno.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/errno.h new file mode 100644 index 0000000000..1d1b677c9d --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/errno.h @@ -0,0 +1,24 @@ +/* + * * Copyright (c) 2019 STMicrolectonics , Xilinx Inc. and Contributors. All rights reserved. + * * + * * SPDX-License-Identifier: BSD-3-Clause + * */ + +/* + * * @file metal/errno.h + * * @brief error specific primitives for libmetal. + * */ + +#ifndef __METAL_ERRNO__H__ +#define __METAL_ERRNO__H__ + +#if defined (__CC_ARM) +# include <metal/compiler/mdk-arm/errno.h> +#elif defined (__ICCARM__) +# include <metal/compiler/iar/errno.h> +#else +#include <errno.h> +#endif + +#endif /* __METAL_ERRNO__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/io.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/io.h new file mode 100644 index 0000000000..6aeafc4969 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/io.h @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2015 - 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file io.h + * @brief I/O access primitives for libmetal. + */ + +#ifndef __METAL_IO__H__ +#define __METAL_IO__H__ + +#include <limits.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <metal/assert.h> +#include <metal/compiler.h> +#include <metal/atomic.h> +#include <metal/sys.h> +#include <metal/cpu.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup io IO Interfaces + * @{ */ + +#ifdef __MICROBLAZE__ +#define NO_ATOMIC_64_SUPPORT +#endif + +struct metal_io_region; + +/** Generic I/O operations. */ +struct metal_io_ops { + uint64_t (*read)(struct metal_io_region *io, + unsigned long offset, + memory_order order, + int width); + void (*write)(struct metal_io_region *io, + unsigned long offset, + uint64_t value, + memory_order order, + int width); + int (*block_read)(struct metal_io_region *io, + unsigned long offset, + void *restrict dst, + memory_order order, + int len); + int (*block_write)(struct metal_io_region *io, + unsigned long offset, + const void *restrict src, + memory_order order, + int len); + void (*block_set)(struct metal_io_region *io, + unsigned long offset, + unsigned char value, + memory_order order, + int len); + void (*close)(struct metal_io_region *io); +}; + +/** Libmetal I/O region structure. */ +struct metal_io_region { + void *virt; /**< base virtual address */ + const metal_phys_addr_t *physmap; /**< table of base physical address + of each of the pages in the I/O + region */ + size_t size; /**< size of the I/O region */ + unsigned long page_shift; /**< page shift of I/O region */ + metal_phys_addr_t page_mask; /**< page mask of I/O region */ + unsigned int mem_flags; /**< memory attribute of the + I/O region */ + struct metal_io_ops ops; /**< I/O region operations */ +}; + +/** + * @brief Open a libmetal I/O region. + * + * @param[in, out] io I/O region handle. + * @param[in] virt Virtual address of region. + * @param[in] physmap Array of physical addresses per page. + * @param[in] size Size of region. + * @param[in] page_shift Log2 of page size (-1 for single page). + * @param[in] mem_flags Memory flags + * @param[in] ops ops + */ +void +metal_io_init(struct metal_io_region *io, void *virt, + const metal_phys_addr_t *physmap, size_t size, + unsigned page_shift, unsigned int mem_flags, + const struct metal_io_ops *ops); + +/** + * @brief Close a libmetal shared memory segment. + * @param[in] io I/O region handle. + */ +static inline void metal_io_finish(struct metal_io_region *io) +{ + if (io->ops.close) + (*io->ops.close)(io); + memset(io, 0, sizeof(*io)); +} + +/** + * @brief Get size of I/O region. + * + * @param[in] io I/O region handle. + * @return Size of I/O region. + */ +static inline size_t metal_io_region_size(struct metal_io_region *io) +{ + return io->size; +} + +/** + * @brief Get virtual address for a given offset into the I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into shared memory segment. + * @return NULL if offset is out of range, or pointer to offset. + */ +static inline void * +metal_io_virt(struct metal_io_region *io, unsigned long offset) +{ + return (io->virt != METAL_BAD_VA && offset <= io->size + ? (uint8_t *)io->virt + offset + : NULL); +} + +/** + * @brief Convert a virtual address to offset within I/O region. + * @param[in] io I/O region handle. + * @param[in] virt Virtual address within segment. + * @return METAL_BAD_OFFSET if out of range, or offset. + */ +static inline unsigned long +metal_io_virt_to_offset(struct metal_io_region *io, void *virt) +{ + size_t offset = (uint8_t *)virt - (uint8_t *)io->virt; + return (offset < io->size ? offset : METAL_BAD_OFFSET); +} + +/** + * @brief Get physical address for a given offset into the I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into shared memory segment. + * @return METAL_BAD_PHYS if offset is out of range, or physical address + * of offset. + */ +static inline metal_phys_addr_t +metal_io_phys(struct metal_io_region *io, unsigned long offset) +{ + unsigned long page = (io->page_shift >= + sizeof(offset) * CHAR_BIT ? + 0 : offset >> io->page_shift); + return (io->physmap != NULL && offset <= io->size + ? io->physmap[page] + (offset & io->page_mask) + : METAL_BAD_PHYS); +} + +/** + * @brief Convert a physical address to offset within I/O region. + * @param[in] io I/O region handle. + * @param[in] phys Physical address within segment. + * @return METAL_BAD_OFFSET if out of range, or offset. + */ +static inline unsigned long +metal_io_phys_to_offset(struct metal_io_region *io, metal_phys_addr_t phys) +{ + unsigned long offset = + (io->page_mask == (metal_phys_addr_t)(-1) ? + phys - io->physmap[0] : phys & io->page_mask); + do { + if (metal_io_phys(io, offset) == phys) + return offset; + offset += io->page_mask + 1; + } while (offset < io->size); + return METAL_BAD_OFFSET; +} + +/** + * @brief Convert a physical address to virtual address. + * @param[in] io Shared memory segment handle. + * @param[in] phys Physical address within segment. + * @return NULL if out of range, or corresponding virtual address. + */ +static inline void * +metal_io_phys_to_virt(struct metal_io_region *io, metal_phys_addr_t phys) +{ + return metal_io_virt(io, metal_io_phys_to_offset(io, phys)); +} + +/** + * @brief Convert a virtual address to physical address. + * @param[in] io Shared memory segment handle. + * @param[in] virt Virtual address within segment. + * @return METAL_BAD_PHYS if out of range, or corresponding + * physical address. + */ +static inline metal_phys_addr_t +metal_io_virt_to_phys(struct metal_io_region *io, void *virt) +{ + return metal_io_phys(io, metal_io_virt_to_offset(io, virt)); +} + +/** + * @brief Read a value from an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] order Memory ordering. + * @param[in] width Width in bytes of datatype to read. This must be 1, 2, + * 4, or 8, and a compile time constant for this function + * to inline cleanly. + * @return Value. + */ +static inline uint64_t +metal_io_read(struct metal_io_region *io, unsigned long offset, + memory_order order, int width) +{ + void *ptr = metal_io_virt(io, offset); + + if (io->ops.read) + return (*io->ops.read)(io, offset, order, width); + else if (ptr && sizeof(atomic_uchar) == width) + return atomic_load_explicit((atomic_uchar *)ptr, order); + else if (ptr && sizeof(atomic_ushort) == width) + return atomic_load_explicit((atomic_ushort *)ptr, order); + else if (ptr && sizeof(atomic_uint) == width) + return atomic_load_explicit((atomic_uint *)ptr, order); + else if (ptr && sizeof(atomic_ulong) == width) + return atomic_load_explicit((atomic_ulong *)ptr, order); +#ifndef NO_ATOMIC_64_SUPPORT + else if (ptr && sizeof(atomic_ullong) == width) + return atomic_load_explicit((atomic_ullong *)ptr, order); +#endif + metal_assert(0); + return 0; /* quiet compiler */ +} + +/** + * @brief Write a value into an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] value Value to write. + * @param[in] order Memory ordering. + * @param[in] width Width in bytes of datatype to read. This must be 1, 2, + * 4, or 8, and a compile time constant for this function + * to inline cleanly. + */ +static inline void +metal_io_write(struct metal_io_region *io, unsigned long offset, + uint64_t value, memory_order order, int width) +{ + void *ptr = metal_io_virt(io, offset); + if (io->ops.write) + (*io->ops.write)(io, offset, value, order, width); + else if (ptr && sizeof(atomic_uchar) == width) + atomic_store_explicit((atomic_uchar *)ptr, value, order); + else if (ptr && sizeof(atomic_ushort) == width) + atomic_store_explicit((atomic_ushort *)ptr, value, order); + else if (ptr && sizeof(atomic_uint) == width) + atomic_store_explicit((atomic_uint *)ptr, value, order); + else if (ptr && sizeof(atomic_ulong) == width) + atomic_store_explicit((atomic_ulong *)ptr, value, order); +#ifndef NO_ATOMIC_64_SUPPORT + else if (ptr && sizeof(atomic_ullong) == width) + atomic_store_explicit((atomic_ullong *)ptr, value, order); +#endif + else + metal_assert (0); +} + +#define metal_io_read8_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 1) +#define metal_io_read8(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 1) +#define metal_io_write8_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 1) +#define metal_io_write8(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 1) + +#define metal_io_read16_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 2) +#define metal_io_read16(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 2) +#define metal_io_write16_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 2) +#define metal_io_write16(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 2) + +#define metal_io_read32_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 4) +#define metal_io_read32(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 4) +#define metal_io_write32_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 4) +#define metal_io_write32(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 4) + +#define metal_io_read64_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 8) +#define metal_io_read64(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 8) +#define metal_io_write64_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 8) +#define metal_io_write64(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 8) + +/** + * @brief Read a block from an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] dst destination to store the read data. + * @param[in] len length in bytes to read. + * @return On success, number of bytes read. On failure, negative value + */ +int metal_io_block_read(struct metal_io_region *io, unsigned long offset, + void *restrict dst, int len); + +/** + * @brief Write a block into an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] src source to write. + * @param[in] len length in bytes to write. + * @return On success, number of bytes written. On failure, negative value + */ +int metal_io_block_write(struct metal_io_region *io, unsigned long offset, + const void *restrict src, int len); + +/** + * @brief fill a block of an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] value value to fill into the block + * @param[in] len length in bytes to fill. + * @return On success, number of bytes filled. On failure, negative value + */ +int metal_io_block_set(struct metal_io_region *io, unsigned long offset, + unsigned char value, int len); + +#include <metal/system/generic/io.h> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_IO__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/irq.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/irq.h new file mode 100644 index 0000000000..e8c92f9f18 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/irq.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file irq.h + * @brief Interrupt handling primitives for libmetal. + */ + +#ifndef __METAL_IRQ__H__ +#define __METAL_IRQ__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup irq Interrupt Handling Interfaces + * @{ */ + +#include <stdlib.h> + +/** IRQ handled status */ +#define METAL_IRQ_NOT_HANDLED 0 +#define METAL_IRQ_HANDLED 1 + +/** + * @brief type of interrupt handler + * @param[in] irq interrupt id + * @param[in] priv private data + * @return irq handled status + */ +typedef int (*metal_irq_handler) (int irq, void *priv); + +struct metal_device; + +/** + * @brief Register interrupt handler for driver ID/device. + * + * @param[in] irq interrupt id + * @param[in] irq_handler interrupt handler + * @param[in] dev metal device this irq belongs to (can be NULL). + * @param[in] drv_id driver id is a unique interrupt handler identifier. + * It can also be used for driver data. + * @return 0 for success, non-zero on failure + */ +int metal_irq_register(int irq, + metal_irq_handler irq_handler, + struct metal_device *dev, + void *drv_id); + +/** + * @brief Unregister interrupt handler for driver ID and/or device. + * + * If interrupt handler (hd), driver ID (drv_id) and device (dev) + * are NULL, unregister all handlers for this interrupt. + * + * If interrupt handler (hd), device (dev) or driver ID (drv_id), + * are not NULL, unregister handlers matching non NULL criterias. + * e.g: when call is made with drv_id and dev non NULL, + * all handlers matching both are unregistered. + * + * If interrupt is not found, or other criterias not matching, + * return -ENOENT + * + * @param[in] irq interrupt id + * @param[in] irq_handler interrupt handler + * @param[in] dev metal device this irq belongs to + * @param[in] drv_id driver id. It can be used for driver data. + * @return 0 for success, non-zero on failure + */ +int metal_irq_unregister(int irq, + metal_irq_handler irq_handler, + struct metal_device *dev, + void *drv_id); + +/** + * @brief disable interrupts + * @return interrupts state + */ +unsigned int metal_irq_save_disable(void); + +/** + * @brief restore interrupts to their previous state + * @param[in] flags previous interrupts state + */ +void metal_irq_restore_enable(unsigned int flags); + +/** + * @brief metal_irq_enable + * + * Enables the given interrupt + * + * @param vector - interrupt vector number + */ +void metal_irq_enable(unsigned int vector); + +/** + * @brief metal_irq_disable + * + * Disables the given interrupt + * + * @param vector - interrupt vector number + */ +void metal_irq_disable(unsigned int vector); + +#include <metal/system/generic/irq.h> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_IRQ__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/list.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/list.h new file mode 100644 index 0000000000..554aebfdb6 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/list.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file list.h + * @brief List primitives for libmetal. + */ + +#ifndef __METAL_LIST__H__ +#define __METAL_LIST__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup list List Primitives + * @{ */ + +struct metal_list { + struct metal_list *next, *prev; +}; + +/* + * METAL_INIT_LIST - used for initializing an list elmenet in a static struct + * or global + */ +#define METAL_INIT_LIST(name) { .next = &name, .prev = &name } +/* + * METAL_DECLARE_LIST - used for defining and initializing a global or + * static singleton list + */ +#define METAL_DECLARE_LIST(name) \ + struct metal_list name = METAL_INIT_LIST(name) + +static inline void metal_list_init(struct metal_list *list) +{ + list->next = list->prev = list; +} + +static inline void metal_list_add_before(struct metal_list *node, + struct metal_list *new_node) +{ + new_node->prev = node->prev; + new_node->next = node; + new_node->next->prev = new_node; + new_node->prev->next = new_node; +} + +static inline void metal_list_add_after(struct metal_list *node, + struct metal_list *new_node) +{ + new_node->prev = node; + new_node->next = node->next; + new_node->next->prev = new_node; + new_node->prev->next = new_node; +} + +static inline void metal_list_add_head(struct metal_list *list, + struct metal_list *node) +{ + metal_list_add_after(list, node); +} + +static inline void metal_list_add_tail(struct metal_list *list, + struct metal_list *node) +{ + metal_list_add_before(list, node); +} + +static inline int metal_list_is_empty(struct metal_list *list) +{ + return list->next == list; +} + +static inline void metal_list_del(struct metal_list *node) +{ + node->next->prev = node->prev; + node->prev->next = node->next; + node->next = node->prev = node; +} + +static inline struct metal_list *metal_list_first(struct metal_list *list) +{ + return metal_list_is_empty(list) ? NULL : list->next; +} + +#define metal_list_for_each(list, node) \ + for ((node) = (list)->next; \ + (node) != (list); \ + (node) = (node)->next) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_LIST__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/log.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/log.h new file mode 100644 index 0000000000..3807bbbef4 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/log.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file log.h + * @brief Logging support for libmetal. + */ + +#ifndef __METAL_METAL_LOG__H__ +#define __METAL_METAL_LOG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup logging Library Logging Interfaces + * @{ */ + +/** Log message priority levels for libmetal. */ +enum metal_log_level { + METAL_LOG_EMERGENCY, /**< system is unusable. */ + METAL_LOG_ALERT, /**< action must be taken immediately. */ + METAL_LOG_CRITICAL, /**< critical conditions. */ + METAL_LOG_ERROR, /**< error conditions. */ + METAL_LOG_WARNING, /**< warning conditions. */ + METAL_LOG_NOTICE, /**< normal but significant condition. */ + METAL_LOG_INFO, /**< informational messages. */ + METAL_LOG_DEBUG, /**< debug-level messages. */ +}; + +/** Log message handler type. */ +typedef void (*metal_log_handler)(enum metal_log_level level, + const char *format, ...); + +/** + * @brief Set libmetal log handler. + * @param[in] handler log message handler. + * @return 0 on success, or -errno on failure. + */ +extern void metal_set_log_handler(metal_log_handler handler); + +/** + * @brief Get the current libmetal log handler. + * @return Current log handler. + */ +extern metal_log_handler metal_get_log_handler(void); + +/** + * @brief Set the level for libmetal logging. + * @param[in] level log message level. + */ +extern void metal_set_log_level(enum metal_log_level level); + +/** + * @brief Get the current level for libmetal logging. + * @return Current log level. + */ +extern enum metal_log_level metal_get_log_level(void); + +/** + * @brief Default libmetal log handler. This handler prints libmetal log + * mesages to stderr. + * @param[in] level log message level. + * @param[in] format log message format string. + * @return 0 on success, or -errno on failure. + */ +extern void metal_default_log_handler(enum metal_log_level level, + const char *format, ...); + + +/** + * Emit a log message if the log level permits. + * + * @param level Log level. + * @param ... Format string and arguments. + */ +#define metal_log(level, ...) \ + ((level <= _metal.common.log_level && _metal.common.log_handler) \ + ? (void)_metal.common.log_handler(level, __VA_ARGS__) \ + : (void)0) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#include <metal/system/generic/log.h> + +#endif /* __METAL_METAL_LOG__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/mutex.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/mutex.h new file mode 100644 index 0000000000..053f679200 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/mutex.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file mutex.h + * @brief Mutex primitives for libmetal. + */ + +#ifndef __METAL_MUTEX__H__ +#define __METAL_MUTEX__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup mutex Mutex Interfaces + * @{ */ + +#include <metal/system/generic/mutex.h> + +/** + * @brief Initialize a libmetal mutex. + * @param[in] mutex Mutex to initialize. + */ +static inline void metal_mutex_init(metal_mutex_t *mutex) +{ + __metal_mutex_init(mutex); +} + +/** + * @brief Deinitialize a libmetal mutex. + * @param[in] mutex Mutex to deinitialize. + */ +static inline void metal_mutex_deinit(metal_mutex_t *mutex) +{ + __metal_mutex_deinit(mutex); +} + +/** + * @brief Try to acquire a mutex + * @param[in] mutex Mutex to mutex. + * @return 0 on failure to acquire, non-zero on success. + */ +static inline int metal_mutex_try_acquire(metal_mutex_t *mutex) +{ + return __metal_mutex_try_acquire(mutex); +} + +/** + * @brief Acquire a mutex + * @param[in] mutex Mutex to mutex. + */ +static inline void metal_mutex_acquire(metal_mutex_t *mutex) +{ + __metal_mutex_acquire(mutex); +} + +/** + * @brief Release a previously acquired mutex. + * @param[in] mutex Mutex to mutex. + * @see metal_mutex_try_acquire, metal_mutex_acquire + */ +static inline void metal_mutex_release(metal_mutex_t *mutex) +{ + __metal_mutex_release(mutex); +} + +/** + * @brief Checked if a mutex has been acquired. + * @param[in] mutex mutex to check. + * @see metal_mutex_try_acquire, metal_mutex_acquire + */ +static inline int metal_mutex_is_acquired(metal_mutex_t *mutex) +{ + return __metal_mutex_is_acquired(mutex); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_MUTEX__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/atomic.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/atomic.h new file mode 100644 index 0000000000..3a577e378d --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/atomic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file arm/atomic.h + * @brief ARM specific atomic primitives for libmetal. + */ + +#ifndef __METAL_ARM_ATOMIC__H__ +#define __METAL_ARM_ATOMIC__H__ + +#endif /* __METAL_ARM_ATOMIC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/cpu.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/cpu.h new file mode 100644 index 0000000000..2141fb3982 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/cpu.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cpu.h + * @brief CPU specific primatives + */ + +#ifndef __METAL_ARM_CPU__H__ +#define __METAL_ARM_CPU__H__ + +#define metal_cpu_yield() + +#endif /* __METAL_ARM_CPU__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/shmem.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/shmem.h new file mode 100644 index 0000000000..17e9d2067e --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/shmem.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file shmem.h + * @brief Shared memory primitives for libmetal. + */ + +#ifndef __METAL_SHMEM__H__ +#define __METAL_SHMEM__H__ + +#include <metal/io.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup shmem Shared Memory Interfaces + * @{ */ + +/** Generic shared memory data structure. */ +struct metal_generic_shmem { + const char *name; + struct metal_io_region io; + struct metal_list node; +}; + +/** + * @brief Open a libmetal shared memory segment. + * + * Open a shared memory segment. + * + * @param[in] name Name of segment to open. + * @param[in] size Size of segment. + * @param[out] io I/O region handle, if successful. + * @return 0 on success, or -errno on failure. + * + * @see metal_shmem_create + */ +extern int metal_shmem_open(const char *name, size_t size, + struct metal_io_region **io); + +/** + * @brief Statically register a generic shared memory region. + * + * Shared memory regions may be statically registered at application + * initialization, or may be dynamically opened. This interface is used for + * static registration of regions. Subsequent calls to metal_shmem_open() look + * up in this list of pre-registered regions. + * + * @param[in] shmem Generic shmem structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_shmem_register_generic(struct metal_generic_shmem *shmem); + +#ifdef METAL_INTERNAL + +/** + * @brief Open a statically registered shmem segment. + * + * This interface is meant for internal libmetal use within system specific + * shmem implementations. + * + * @param[in] name Name of segment to open. + * @param[in] size Size of segment. + * @param[out] io I/O region handle, if successful. + * @return 0 on success, or -errno on failure. + */ +int metal_shmem_open_generic(const char *name, size_t size, + struct metal_io_region **result); + +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SHMEM__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/sleep.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/sleep.h new file mode 100644 index 0000000000..1131934655 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/sleep.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file sleep.h + * @brief Sleep primitives for libmetal. + */ + +#ifndef __METAL_SLEEP__H__ +#define __METAL_SLEEP__H__ + +#include <metal/system/generic/sleep.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup sleep Sleep Interfaces + * @{ */ + +/** + * @brief delay in microseconds + * delay the next execution in the calling thread + * fo usec microseconds. + * + * @param[in] usec microsecond intervals + * @return 0 on success, non-zero for failures + */ +static inline int metal_sleep_usec(unsigned int usec) +{ + return __metal_sleep_usec(usec); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SLEEP__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/spinlock.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/spinlock.h new file mode 100644 index 0000000000..ebd4cae4ef --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/spinlock.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file spinlock.h + * @brief Spinlock primitives for libmetal. + */ + +#ifndef __METAL_SPINLOCK__H__ +#define __METAL_SPINLOCK__H__ + +#include <metal/atomic.h> +#include <metal/cpu.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup spinlock Spinlock Interfaces + * @{ */ +struct metal_spinlock { + union{ + atomic_int v; + atomic_flag w; + }; +}; + +/** Static metal spinlock initialization. */ +#define METAL_SPINLOCK_INIT {ATOMIC_VAR_INIT(0)} + +/** + * @brief Initialize a libmetal spinlock. + * @param[in] slock Spinlock to initialize. + */ +static inline void metal_spinlock_init(struct metal_spinlock *slock) +{ + atomic_store(&slock->v, 0); +} + +/** + * @brief Acquire a spinlock. + * @param[in] slock Spinlock to acquire. + * @see metal_spinlock_release + */ +static inline void metal_spinlock_acquire(struct metal_spinlock *slock) +{ + while (atomic_flag_test_and_set(&slock->w)) { + metal_cpu_yield(); + } +} + +/** + * @brief Release a previously acquired spinlock. + * @param[in] slock Spinlock to release. + * @see metal_spinlock_acquire + */ +static inline void metal_spinlock_release(struct metal_spinlock *slock) +{ + atomic_flag_clear(&slock->w); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SPINLOCK__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/sys.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/sys.h new file mode 100644 index 0000000000..908f796740 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/sys.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file sys.h + * @brief System primitives for libmetal. + * @brief Top level include internal to libmetal library code. + */ + +#ifndef __METAL_SYS__H__ +#define __METAL_SYS__H__ + +#include <stdlib.h> + +#include <metal/log.h> +#include <metal/list.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup system Top Level Interfaces + * @{ */ + +/** Physical address type. */ +typedef unsigned long metal_phys_addr_t; + +/** Interrupt request number. */ +typedef int metal_irq_t; + +/** Bad offset into shared memory or I/O region. */ +#define METAL_BAD_OFFSET ((unsigned long)-1) + +/** Bad physical address value. */ +#define METAL_BAD_PHYS ((metal_phys_addr_t)-1) + +/** Bad virtual address value. */ +#define METAL_BAD_VA ((void *)-1) + +/** Bad IRQ. */ +#define METAL_BAD_IRQ ((metal_irq_t)-1) + +/** + * Initialization configuration for libmetal. + */ +struct metal_init_params { + + /** log message handler (defaults to stderr). */ + metal_log_handler log_handler; + + /** default log message level (defaults to emergency). */ + enum metal_log_level log_level; +}; + +/** + * System independent runtime state for libmetal. This is part of a system + * specific singleton data structure (@see _metal). + */ +struct metal_common_state { + /** Current log level. */ + enum metal_log_level log_level; + + /** Current log handler (null for none). */ + metal_log_handler log_handler; + + /** List of registered buses. */ + struct metal_list bus_list; + + /** Generic statically defined shared memory segments. */ + struct metal_list generic_shmem_list; + + /** Generic statically defined devices. */ + struct metal_list generic_device_list; +}; + +struct metal_state; + +#include <metal/system/generic/sys.h> + +#ifndef METAL_INIT_DEFAULTS +#define METAL_INIT_DEFAULTS \ +{ \ + .log_handler = metal_default_log_handler, \ + .log_level = METAL_LOG_INFO, \ +} +#endif + +/** System specific runtime data. */ +extern struct metal_state _metal; + +/** + * @brief Initialize libmetal. + * + * Initialize the libmetal library. + * + * @param[in] params Initialization params (@see metal_init_params). + * + * @return 0 on success, or -errno on failure. + * + * @see metal_finish + */ +extern int metal_init(const struct metal_init_params *params); + +/** + * @brief Shutdown libmetal. + * + * Shutdown the libmetal library, and release all reserved resources. + * + * @see metal_init + */ +extern void metal_finish(void); + +#ifdef METAL_INTERNAL + +/** + * @brief libmetal system initialization. + * + * This function initializes libmetal on Linux or Generic platforms. This + * involves obtaining necessary pieces of system information (sysfs mount path, + * page size, etc.). + * + * @param[in] params Initialization parameters (@see metal_init_params). + * @return 0 on success, or -errno on failure. + */ +extern int metal_sys_init(const struct metal_init_params *params); + +/** + * @brief libmetal system shutdown. + * + * This function shuts down and releases resources held by libmetal Linux or + * Generic platform layers. + * + * @see metal_sys_init + */ +extern void metal_sys_finish(void); + +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/alloc.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/alloc.h new file mode 100644 index 0000000000..bcceba61a0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/alloc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/alloc.c + * @brief generic libmetal memory allocattion definitions. + */ + +#ifndef __METAL_ALLOC__H__ +#error "Include metal/alloc.h instead of metal/generic/alloc.h" +#endif + +#ifndef __METAL_GENERIC_ALLOC__H__ +#define __METAL_GENERIC_ALLOC__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void *metal_allocate_memory(unsigned int size) +{ + return (malloc(size)); +} + +static inline void metal_free_memory(void *ptr) +{ + free(ptr); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_ALLOC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/assert.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/assert.h new file mode 100644 index 0000000000..97f88ee5a5 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/assert.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file assert.h + * @brief Generic assertion support. + */ + +#ifndef __METAL_ASSERT__H__ +#error "Include metal/assert.h instead of metal/generic/assert.h" +#endif + +#ifndef __METAL_GENERIC_ASSERT__H__ +#define __METAL_GENERIC_ASSERT__H__ + +#include <assert.h> + +/** + * @brief Assertion macro for bare-metal applications. + * @param cond Condition to evaluate. + */ +#define metal_sys_assert(cond) assert(cond) + +#endif /* __METAL_GENERIC_ASSERT__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cache.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cache.h new file mode 100644 index 0000000000..962ffccfa9 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cache.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/cache.h + * @brief generic cache operation primitives for libmetal. + */ + +#ifndef __METAL_CACHE__H__ +#error "Include metal/cache.h instead of metal/generic/cache.h" +#endif + +#ifndef __METAL_GENERIC_CACHE__H__ +#define __METAL_GENERIC_CACHE__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void metal_machine_cache_flush(void *addr, unsigned int len); +extern void metal_machine_cache_invalidate(void *addr, unsigned int len); + +static inline void __metal_cache_flush(void *addr, unsigned int len) +{ + metal_machine_cache_flush(addr, len); +} + +static inline void __metal_cache_invalidate(void *addr, unsigned int len) +{ + metal_machine_cache_invalidate(addr, len); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_CACHE__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/condition.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/condition.h new file mode 100644 index 0000000000..5202f3345f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/condition.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/condition.h + * @brief Generic condition variable primitives for libmetal. + */ + +#ifndef __METAL_CONDITION__H__ +#error "Include metal/condition.h instead of metal/generic/condition.h" +#endif + +#ifndef __METAL_GENERIC_CONDITION__H__ +#define __METAL_GENERIC_CONDITION__H__ + +#if defined (__CC_ARM) +#include <stdio.h> +#endif +#include <metal/atomic.h> +#include <stdint.h> +#include <limits.h> +#include <metal/errno.h> + + + +#ifdef __cplusplus +extern "C" { +#endif + +struct metal_condition { + metal_mutex_t *m; /**< mutex. + The condition variable is attached to + this mutex when it is waiting. + It is also used to check correctness + in case there are multiple waiters. */ + + atomic_int v; /**< condition variable value. */ +}; + +/** Static metal condition variable initialization. */ +#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) } + +static inline void metal_condition_init(struct metal_condition *cv) +{ + cv->m = NULL; + atomic_init(&cv->v, 0); +} + +static inline int metal_condition_signal(struct metal_condition *cv) +{ + if (!cv) + return -EINVAL; + + /** wake up waiters if there are any. */ + atomic_fetch_add(&cv->v, 1); + return 0; +} + +static inline int metal_condition_broadcast(struct metal_condition *cv) +{ + return metal_condition_signal(cv); +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_CONDITION__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cortexm/sys.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cortexm/sys.h new file mode 100644 index 0000000000..f506887783 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cortexm/sys.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/mp1_m4/sys.h + * @brief generic mp1_m4 system primitives for libmetal. + */ + +#ifndef __METAL_GENERIC_SYS__H__ +#error "Include metal/sys.h instead of metal/generic/cortexm/sys.h" +#endif + +#ifndef __METAL_GENERIC_MP1_M4_SYS__H__ +#define __METAL_GENERIC_MP1_M4_SYS__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MAX_IRQS) +#define MAX_IRQS 8 /**< maximum number of irqs */ +#endif + +static inline void sys_irq_enable(unsigned int vector) +{ + (void)vector; +} + +static inline void sys_irq_disable(unsigned int vector) +{ + (void)vector; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_MP1_M4_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/io.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/io.h new file mode 100644 index 0000000000..adbbc44774 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/io.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/io.h + * @brief Generic specific io definitions. + */ + +#ifndef __METAL_IO__H__ +#error "Include metal/io.h instead of metal/generic/io.h" +#endif + +#ifndef __METAL_GENERIC_IO__H__ +#define __METAL_GENERIC_IO__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef METAL_INTERNAL + +/** + * @brief memory mapping for an I/O region + */ +void metal_sys_io_mem_map(struct metal_io_region *io); + +/** + * @brief memory mapping + */ +void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa, + size_t size, unsigned int flags); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_IO__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/irq.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/irq.h new file mode 100644 index 0000000000..c618c87fde --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/irq.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/irq.c + * @brief Generic libmetal irq definitions. + */ + +#ifndef __METAL_IRQ__H__ +#error "Include metal/irq.h instead of metal/generic/irq.h" +#endif + +#ifndef __METAL_GENERIC_IRQ__H__ +#define __METAL_GENERIC_IRQ__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief default interrupt handler + * @param[in] vector interrupt vector + */ +void metal_irq_isr(unsigned int vector); + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_IRQ__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/log.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/log.h new file mode 100644 index 0000000000..32611288ad --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/log.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Linaro nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/log.h + * @brief Generic libmetal log handler definition. + */ + +#ifndef __METAL_METAL_LOG__H__ +#error "Include metal/log.h instead of metal/generic/log.h" +#endif + +#ifndef __METAL_GENERIC_LOG__H__ +#define __METAL_GENERIC_LOG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_LOG__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/mutex.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/mutex.h new file mode 100644 index 0000000000..3613c194d1 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/mutex.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/mutex.h + * @brief Generic mutex primitives for libmetal. + */ + +#ifndef __METAL_MUTEX__H__ +#error "Include metal/mutex.h instead of metal/generic/mutex.h" +#endif + +#ifndef __METAL_GENERIC_MUTEX__H__ +#define __METAL_GENERIC_MUTEX__H__ + +#include <metal/atomic.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + union{ + atomic_int v; + atomic_flag w; + }; +} metal_mutex_t; + +/* + * METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct + * or global + */ +#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) } +/* + * METAL_MUTEX_DEFINE - used for defining and initializing a global or + * static singleton mutex + */ +#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m) + +static inline void __metal_mutex_init(metal_mutex_t *mutex) +{ + atomic_store(&mutex->v, 0); +} + +static inline void __metal_mutex_deinit(metal_mutex_t *mutex) +{ + (void)mutex; +} + +static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex) +{ + return 1 - atomic_flag_test_and_set(&mutex->w); +} + +static inline void __metal_mutex_acquire(metal_mutex_t *mutex) +{ + while (atomic_flag_test_and_set(&mutex->w)) { + ; + } +} + +static inline void __metal_mutex_release(metal_mutex_t *mutex) +{ + atomic_flag_clear(&mutex->w); +} + +static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex) +{ + return atomic_load(&mutex->v); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_MUTEX__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sleep.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sleep.h new file mode 100644 index 0000000000..aa86df492e --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sleep.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/sleep.h + * @brief Generic sleep primitives for libmetal. + */ + +#ifndef __METAL_SLEEP__H__ +#error "Include metal/sleep.h instead of metal/generic/sleep.h" +#endif + +#ifndef __METAL_GENERIC_SLEEP__H__ +#define __METAL_GENERIC_SLEEP__H__ + +#include <metal/utilities.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline int __metal_sleep_usec(unsigned int usec) +{ + metal_unused(usec); + /* Fix me */ + return 0; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_SLEEP__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sys.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sys.h new file mode 100644 index 0000000000..6f6143a4ce --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sys.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/sys.h + * @brief Generic system primitives for libmetal. + */ + +#ifndef __METAL_SYS__H__ +#error "Include metal/sys.h instead of metal/generic/sys.h" +#endif + +#ifndef __METAL_GENERIC_SYS__H__ +#define __METAL_GENERIC_SYS__H__ + +#include <metal/errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "./cortexm/sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef METAL_MAX_DEVICE_REGIONS +#define METAL_MAX_DEVICE_REGIONS 1 +#endif + +/** Structure of generic libmetal runtime state. */ +struct metal_state { + + /** Common (system independent) data. */ + struct metal_common_state common; +}; + +#ifdef METAL_INTERNAL + +/** + * @brief restore interrupts to state before disable_global_interrupt() + */ +void sys_irq_restore_enable(unsigned int flags); + +/** + * @brief disable all interrupts + */ +unsigned int sys_irq_save_disable(void); + +#endif /* METAL_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/time.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/time.h new file mode 100644 index 0000000000..0da6821783 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/time.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file time.h + * @brief Time primitives for libmetal. + */ + +#ifndef __METAL_TIME__H__ +#define __METAL_TIME__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup time TIME Interfaces + * @{ */ + +#include <stdint.h> +#include <metal/sys.h> + +/** + * @brief get timestamp + * This function returns the timestampe as unsigned long long + * value. + * + * @return timestamp + */ +unsigned long long metal_get_timestamp(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_TIME__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/utilities.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/utilities.h new file mode 100644 index 0000000000..eb540d2f0a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/utilities.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file utilities.h + * @brief Utility routines for libmetal. + */ + +#ifndef __METAL_UTILITIES__H__ +#define __METAL_UTILITIES__H__ + +#include <stdint.h> +#include <metal/assert.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup utilities Simple Utilities + * @{ */ + +/** Marker for unused function arguments/variables. */ +#define metal_unused(x) do { (x) = (x); } while (0) + +/** Figure out number of elements in an array. */ +#define metal_dim(x) (sizeof(x) / sizeof(x[0])) + +/** Minimum of two numbers (warning: multiple evaluation!). */ +#define metal_min(x, y) ((x) < (y) ? (x) : (y)) + +/** Maximum of two numbers (warning: multiple evaluation!). */ +#define metal_max(x, y) ((x) > (y) ? (x) : (y)) + +/** Sign of a number [-1, 0, or 1] (warning: multiple evaluation!). */ +#define metal_sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0)) + +/** Align 'size' down to a multiple of 'align' (must be a power of two). */ +#define metal_align_down(size, align) \ + ((size) & ~((align) - 1)) + +/** Align 'size' up to a multiple of 'align' (must be a power of two). */ +#define metal_align_up(size, align) \ + metal_align_down((size) + (align) - 1, align) + +/** Divide (and round down). */ +#define metal_div_round_down(num, den) \ + ((num) / (den)) + +/** Divide (and round up). */ +#define metal_div_round_up(num, den) \ + metal_div_round_down((num) + (den) - 1, (den)) + +/** Align 'ptr' down to a multiple of 'align' (must be a power of two). */ +#define metal_ptr_align_down(ptr, align) \ + (void *)(metal_align_down((uintptr_t)(ptr), (uintptr_t)(align))) + +/** Align 'ptr' up to a multiple of 'align' (must be a power of two). */ +#define metal_ptr_align_up(ptr, align) \ + (void *)(metal_align_up((uintptr_t)(ptr), (uintptr_t)(align))) + +/** Compute offset of a field within a structure. */ +#define metal_offset_of(structure, member) \ + ((uintptr_t) &(((structure *) 0)->member)) + +/** Compute pointer to a structure given a pointer to one of its fields. */ +#define metal_container_of(ptr, structure, member) \ + (void *)((uintptr_t)(ptr) - metal_offset_of(structure, member)) + +#define METAL_BITS_PER_ULONG (8 * sizeof(unsigned long)) + +#define metal_bit(bit) (1UL << (bit)) + +#define metal_bitmap_longs(x) metal_div_round_up((x), METAL_BITS_PER_ULONG) + +static inline void metal_bitmap_set_bit(unsigned long *bitmap, int bit) +{ + bitmap[bit / METAL_BITS_PER_ULONG] |= + metal_bit(bit & (METAL_BITS_PER_ULONG - 1)); +} + +static inline int metal_bitmap_is_bit_set(unsigned long *bitmap, int bit) +{ + return bitmap[bit / METAL_BITS_PER_ULONG] & + metal_bit(bit & (METAL_BITS_PER_ULONG - 1)); +} + +static inline void metal_bitmap_clear_bit(unsigned long *bitmap, int bit) +{ + bitmap[bit / METAL_BITS_PER_ULONG] &= + ~metal_bit(bit & (METAL_BITS_PER_ULONG - 1)); +} + +static inline int metal_bitmap_is_bit_clear(unsigned long *bitmap, int bit) +{ + return !metal_bitmap_is_bit_set(bitmap, bit); +} + +static inline unsigned int +metal_bitmap_next_set_bit(unsigned long *bitmap, unsigned int start, + unsigned int max) +{ + unsigned int bit; + for (bit = start; + bit < max && !metal_bitmap_is_bit_set(bitmap, bit); + bit ++) + ; + return bit; +} + +#define metal_bitmap_for_each_set_bit(bitmap, bit, max) \ + for ((bit) = metal_bitmap_next_set_bit((bitmap), 0, (max)); \ + (bit) < (max); \ + (bit) = metal_bitmap_next_set_bit((bitmap), (bit), (max))) + +static inline unsigned int +metal_bitmap_next_clear_bit(unsigned long *bitmap, unsigned int start, + unsigned int max) +{ + unsigned int bit; + for (bit = start; + bit < max && !metal_bitmap_is_bit_clear(bitmap, bit); + bit ++) + ; + return bit; +} + +#define metal_bitmap_for_each_clear_bit(bitmap, bit, max) \ + for ((bit) = metal_bitmap_next_clear_bit((bitmap), 0, (max)); \ + (bit) < (max); \ + (bit) = metal_bitmap_next_clear_bit((bitmap), (bit), (max))) + +static inline unsigned long metal_log2(unsigned long in) +{ + unsigned long result; + + metal_assert((in & (in - 1)) == 0); + + for (result = 0; (1UL << result) < in; result ++) + ; + return result; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_UTILITIES__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/version.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/version.h new file mode 100644 index 0000000000..f093c51201 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/include/metal/version.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file version.h + * @brief Library version information for libmetal. + */ + +#ifndef __METAL_VERSION__H__ +#define __METAL_VERSION__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup versions Library Version Interfaces + * @{ */ + +/** + * @brief Library major version number. + * + * Return the major version number of the library linked into the application. + * This is required to match the value of METAL_VER_MAJOR, which is the major + * version of the library that the application was compiled against. + * + * @return Library major version number. + * @see METAL_VER_MAJOR + */ +extern int metal_ver_major(void); + +/** + * @brief Library minor version number. + * + * Return the minor version number of the library linked into the application. + * This could differ from the value of METAL_VER_MINOR, which is the minor + * version of the library that the application was compiled against. + * + * @return Library minor version number. + * @see METAL_VER_MINOR + */ +extern int metal_ver_minor(void); + +/** + * @brief Library patch level. + * + * Return the patch level of the library linked into the application. This + * could differ from the value of METAL_VER_PATCH, which is the patch level of + * the library that the application was compiled against. + * + * @return Library patch level. + * @see METAL_VER_PATCH + */ +extern int metal_ver_patch(void); + +/** + * @brief Library version string. + * + * Return the version string of the library linked into the application. This + * could differ from the value of METAL_VER, which is the version string of + * the library that the application was compiled against. + * + * @return Library version string. + * @see METAL_VER + */ +extern const char *metal_ver(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_VERSION__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/init.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/init.c new file mode 100644 index 0000000000..315217741f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/init.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> +#include <metal/sys.h> + +int metal_init(const struct metal_init_params *params) +{ + int error = 0; + + memset(&_metal, 0, sizeof(_metal)); + + _metal.common.log_handler = params->log_handler; + _metal.common.log_level = params->log_level; + + metal_list_init(&_metal.common.bus_list); + metal_list_init(&_metal.common.generic_shmem_list); + metal_list_init(&_metal.common.generic_device_list); + + error = metal_sys_init(params); + if (error) + return error; + + return error; +} + +void metal_finish(void) +{ + metal_sys_finish(); + memset(&_metal, 0, sizeof(_metal)); +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/io.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/io.c new file mode 100644 index 0000000000..fccf1100e0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/io.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/errno.h> +#include <limits.h> +#include <metal/io.h> +#include <metal/sys.h> + +void metal_io_init(struct metal_io_region *io, void *virt, + const metal_phys_addr_t *physmap, size_t size, + unsigned page_shift, unsigned int mem_flags, + const struct metal_io_ops *ops) +{ + const struct metal_io_ops nops = {NULL, NULL, NULL, NULL, NULL, NULL}; + + io->virt = virt; + io->physmap = physmap; + io->size = size; + io->page_shift = page_shift; + if (page_shift >= sizeof(io->page_mask) * CHAR_BIT) + /* avoid overflow */ + io->page_mask = -1UL; + else + io->page_mask = (1UL << page_shift) - 1UL; + io->mem_flags = mem_flags; + io->ops = ops ? *ops : nops; + metal_sys_io_mem_map(io); +} + +int metal_io_block_read(struct metal_io_region *io, unsigned long offset, + void *restrict dst, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + unsigned char *dest = dst; + int retlen; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_read) { + retlen = (*io->ops.block_read)( + io, offset, dst, memory_order_seq_cst, len); + } else { + atomic_thread_fence(memory_order_seq_cst); + while ( len && ( + ((uintptr_t)dest % sizeof(int)) || + ((uintptr_t)ptr % sizeof(int)))) { + *(unsigned char *)dest = + *(const unsigned char *)ptr; + dest++; + ptr++; + len--; + } + for (; len >= (int)sizeof(int); dest += sizeof(int), + ptr += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)dest = *(const unsigned int *)ptr; + for (; len != 0; dest++, ptr++, len--) + *(unsigned char *)dest = + *(const unsigned char *)ptr; + } + return retlen; +} + +int metal_io_block_write(struct metal_io_region *io, unsigned long offset, + const void *restrict src, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + const unsigned char *source = src; + int retlen; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_write) { + retlen = (*io->ops.block_write)( + io, offset, src, memory_order_seq_cst, len); + } else { + while ( len && ( + ((uintptr_t)ptr % sizeof(int)) || + ((uintptr_t)source % sizeof(int)))) { + *(unsigned char *)ptr = + *(const unsigned char *)source; + ptr++; + source++; + len--; + } + for (; len >= (int)sizeof(int); ptr += sizeof(int), + source += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)ptr = *(const unsigned int *)source; + for (; len != 0; ptr++, source++, len--) + *(unsigned char *)ptr = + *(const unsigned char *)source; + atomic_thread_fence(memory_order_seq_cst); + } + return retlen; +} + +int metal_io_block_set(struct metal_io_region *io, unsigned long offset, + unsigned char value, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + int retlen = len; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_set) { + (*io->ops.block_set)( + io, offset, value, memory_order_seq_cst, len); + } else { + unsigned int cint = value; + unsigned int i; + + for (i = 1; i < sizeof(int); i++) + cint |= ((unsigned int)value << (8 * i)); + + for (; len && ((uintptr_t)ptr % sizeof(int)); ptr++, len--) + *(unsigned char *)ptr = (unsigned char) value; + for (; len >= (int)sizeof(int); ptr += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)ptr = cint; + for (; len != 0; ptr++, len--) + *(unsigned char *)ptr = (unsigned char) value; + atomic_thread_fence(memory_order_seq_cst); + } + return retlen; +} + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/log.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/log.c new file mode 100644 index 0000000000..83bec1f6d0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/log.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdarg.h> +#include <stdio.h> + +#include <metal/log.h> +#include <metal/sys.h> + +void metal_default_log_handler(enum metal_log_level level, + const char *format, ...) +{ +#ifdef DEFAULT_LOGGER_ON + char msg[1024]; + va_list args; + static const char *level_strs[] = { + "metal: emergency: ", + "metal: alert: ", + "metal: critical: ", + "metal: error: ", + "metal: warning: ", + "metal: notice: ", + "metal: info: ", + "metal: debug: ", + }; + + va_start(args, format); + vsnprintf(msg, sizeof(msg), format, args); + va_end(args); + + if (level <= METAL_LOG_EMERGENCY || level > METAL_LOG_DEBUG) + level = METAL_LOG_EMERGENCY; + + fprintf(stderr, "%s%s", level_strs[level], msg); +#else + (void)level; + (void)format; +#endif +} + +void metal_set_log_handler(metal_log_handler handler) +{ + _metal.common.log_handler = handler; +} + +metal_log_handler metal_get_log_handler(void) +{ + return _metal.common.log_handler; +} + +void metal_set_log_level(enum metal_log_level level) +{ + _metal.common.log_level = level; +} + +enum metal_log_level metal_get_log_level(void) +{ + return _metal.common.log_level; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/shmem.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/shmem.c new file mode 100644 index 0000000000..5ead8e755d --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/shmem.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/shmem.c + * @brief Generic libmetal shared memory handling. + */ + +#include <metal/errno.h> +#include <metal/assert.h> +#include <metal/shmem.h> +#include <metal/sys.h> +#include <metal/utilities.h> + +int metal_shmem_register_generic(struct metal_generic_shmem *shmem) +{ + /* Make sure that we can be found. */ + metal_assert(shmem->name && strlen(shmem->name) != 0); + + /* Statically registered shmem regions cannot have a destructor. */ + metal_assert(!shmem->io.ops.close); + + metal_list_add_tail(&_metal.common.generic_shmem_list, + &shmem->node); + return 0; +} + +int metal_shmem_open_generic(const char *name, size_t size, + struct metal_io_region **result) +{ + struct metal_generic_shmem *shmem; + struct metal_list *node; + + metal_list_for_each(&_metal.common.generic_shmem_list, node) { + shmem = metal_container_of(node, struct metal_generic_shmem, node); + if (strcmp(shmem->name, name) != 0) + continue; + if (size > metal_io_region_size(&shmem->io)) + continue; + *result = &shmem->io; + return 0; + } + + return -ENOENT; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/st_device.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/st_device.c new file mode 100644 index 0000000000..a3bc12caf3 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/st_device.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> +#include <metal/errno.h> +#include <metal/assert.h> +#include <metal/device.h> +#include <metal/list.h> +#include <metal/log.h> +#include <metal/sys.h> +#include <metal/utilities.h> +#include <metal/dma.h> +#include <metal/cache.h> + +int metal_bus_register(struct metal_bus *bus) +{ + if (!bus || !bus->name || !strlen(bus->name)) + return -EINVAL; + if (metal_bus_find(bus->name, NULL) == 0) + return -EEXIST; + metal_list_init(&bus->devices); + metal_list_add_tail(&_metal.common.bus_list, &bus->node); + metal_log(METAL_LOG_DEBUG, "registered %s bus\n", bus->name); + return 0; +} + +int metal_bus_unregister(struct metal_bus *bus) +{ + metal_list_del(&bus->node); + if (bus->ops.bus_close) + bus->ops.bus_close(bus); + metal_log(METAL_LOG_DEBUG, "unregistered %s bus\n", bus->name); + return 0; +} + +int metal_bus_find(const char *name, struct metal_bus **result) +{ + struct metal_list *node; + struct metal_bus *bus; + + metal_list_for_each(&_metal.common.bus_list, node) { + bus = metal_container_of(node, struct metal_bus, node); + if (strcmp(bus->name, name) != 0) + continue; + if (result) + *result = bus; + return 0; + } + return -ENOENT; +} + +int metal_device_open(const char *bus_name, const char *dev_name, + struct metal_device **device) +{ + struct metal_bus *bus; + int error; + + if (!bus_name || !strlen(bus_name) || + !dev_name || !strlen(dev_name) || + !device) + return -EINVAL; + + error = metal_bus_find(bus_name, &bus); + if (error) + return error; + + if (!bus->ops.dev_open) + return -ENODEV; + + error = (*bus->ops.dev_open)(bus, dev_name, device); + if (error) + return error; + + return 0; +} + +void metal_device_close(struct metal_device *device) +{ + metal_assert(device && device->bus); + if (device->bus->ops.dev_close) + device->bus->ops.dev_close(device->bus, device); +} + +int metal_register_generic_device(struct metal_device *device) +{ + if (!device->name || !strlen(device->name) || + device->num_regions > METAL_MAX_DEVICE_REGIONS) + return -EINVAL; + + device->bus = &metal_generic_bus; + metal_list_add_tail(&_metal.common.generic_device_list, + &device->node); + return 0; +} + +int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name, + struct metal_device **device) +{ + struct metal_list *node; + struct metal_device *dev; + + (void)bus; + + metal_list_for_each(&_metal.common.generic_device_list, node) { + dev = metal_container_of(node, struct metal_device, node); + if (strcmp(dev->name, dev_name) != 0) + continue; + *device = dev; + return metal_generic_dev_sys_open(dev); + } + + return -ENODEV; +} + +int metal_generic_dev_dma_map(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out) +{ + (void)bus; + (void)device; + int i; + + if (sg_out != sg_in) + memcpy(sg_out, sg_in, nents_in*(sizeof(struct metal_sg))); + for (i = 0; i < nents_in; i++) { + if (dir == METAL_DMA_DEV_W) { + metal_cache_flush(sg_out[i].virt, sg_out[i].len); + } + metal_cache_invalidate(sg_out[i].virt, sg_out[i].len); + } + + return nents_in; +} + +void metal_generic_dev_dma_unmap(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents) +{ + (void)bus; + (void)device; + (void)dir; + int i; + + for (i = 0; i < nents; i++) { + metal_cache_invalidate(sg[i].virt, sg[i].len); + } +} + +struct metal_bus metal_weak metal_generic_bus = { + .name = "generic", + .ops = { + .bus_close = NULL, + .dev_open = metal_generic_dev_open, + .dev_close = NULL, + .dev_irq_ack = NULL, + .dev_dma_map = metal_generic_dev_dma_map, + .dev_dma_unmap = metal_generic_dev_dma_unmap, + }, +}; diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/alloc.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/alloc.h new file mode 100644 index 0000000000..bcceba61a0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/alloc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/alloc.c + * @brief generic libmetal memory allocattion definitions. + */ + +#ifndef __METAL_ALLOC__H__ +#error "Include metal/alloc.h instead of metal/generic/alloc.h" +#endif + +#ifndef __METAL_GENERIC_ALLOC__H__ +#define __METAL_GENERIC_ALLOC__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void *metal_allocate_memory(unsigned int size) +{ + return (malloc(size)); +} + +static inline void metal_free_memory(void *ptr) +{ + free(ptr); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_ALLOC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/assert.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/assert.h new file mode 100644 index 0000000000..97f88ee5a5 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/assert.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file assert.h + * @brief Generic assertion support. + */ + +#ifndef __METAL_ASSERT__H__ +#error "Include metal/assert.h instead of metal/generic/assert.h" +#endif + +#ifndef __METAL_GENERIC_ASSERT__H__ +#define __METAL_GENERIC_ASSERT__H__ + +#include <assert.h> + +/** + * @brief Assertion macro for bare-metal applications. + * @param cond Condition to evaluate. + */ +#define metal_sys_assert(cond) assert(cond) + +#endif /* __METAL_GENERIC_ASSERT__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cache.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cache.h new file mode 100644 index 0000000000..962ffccfa9 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cache.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/cache.h + * @brief generic cache operation primitives for libmetal. + */ + +#ifndef __METAL_CACHE__H__ +#error "Include metal/cache.h instead of metal/generic/cache.h" +#endif + +#ifndef __METAL_GENERIC_CACHE__H__ +#define __METAL_GENERIC_CACHE__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void metal_machine_cache_flush(void *addr, unsigned int len); +extern void metal_machine_cache_invalidate(void *addr, unsigned int len); + +static inline void __metal_cache_flush(void *addr, unsigned int len) +{ + metal_machine_cache_flush(addr, len); +} + +static inline void __metal_cache_invalidate(void *addr, unsigned int len) +{ + metal_machine_cache_invalidate(addr, len); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_CACHE__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/condition.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/condition.c new file mode 100644 index 0000000000..493af6fc23 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/condition.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/condition.c + * @brief Generic libmetal condition variable handling. + */ + +#include <metal/condition.h> +#include <metal/irq.h> + +extern void metal_generic_default_poll(void); + +int metal_condition_wait(struct metal_condition *cv, + metal_mutex_t *m) +{ + metal_mutex_t *tmpm = 0; + int v; + unsigned int flags; + + /* Check if the mutex has been acquired */ + if (!cv || !m || !metal_mutex_is_acquired(m)) + return -EINVAL; + + if (!atomic_compare_exchange_strong(&cv->m->v, &tmpm->v, m->v)) { + if (m != tmpm) + return -EINVAL; + } + + v = atomic_load(&cv->v); + + /* Release the mutex first. */ + metal_mutex_release(m); + do { + flags = metal_irq_save_disable(); + if (atomic_load(&cv->v) != v) { + metal_irq_restore_enable(flags); + break; + } + metal_generic_default_poll(); + metal_irq_restore_enable(flags); + } while(1); + /* Acquire the mutex again. */ + metal_mutex_acquire(m); + return 0; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/condition.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/condition.h new file mode 100644 index 0000000000..abb2e8c73c --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/condition.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/condition.h + * @brief Generic condition variable primitives for libmetal. + */ + +#ifndef __METAL_CONDITION__H__ +#error "Include metal/condition.h instead of metal/generic/condition.h" +#endif + +#ifndef __METAL_GENERIC_CONDITION__H__ +#define __METAL_GENERIC_CONDITION__H__ + +#include <unistd.h> +#include <metal/atomic.h> +#include <stdint.h> +#include <limits.h> +#include <metal/errno.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct metal_condition { + metal_mutex_t *m; /**< mutex. + The condition variable is attached to + this mutex when it is waiting. + It is also used to check correctness + in case there are multiple waiters. */ + + atomic_int v; /**< condition variable value. */ +}; + +/** Static metal condition variable initialization. */ +#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) } + +static inline void metal_condition_init(struct metal_condition *cv) +{ + cv->m = NULL; + atomic_init(&cv->v, 0); +} + +static inline int metal_condition_signal(struct metal_condition *cv) +{ + if (!cv) + return -EINVAL; + + /** wake up waiters if there are any. */ + atomic_fetch_add(&cv->v, 1); + return 0; +} + +static inline int metal_condition_broadcast(struct metal_condition *cv) +{ + return metal_condition_signal(cv); +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_CONDITION__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.c new file mode 100644 index 0000000000..7b0b3856fe --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/sys.c + * @brief machine specific system primitives implementation. + */ + + +#include "metal/io.h" +#include "metal/sys.h" + +void sys_irq_restore_enable(unsigned int flags) +{ +} + +unsigned int sys_irq_save_disable(void) +{ + return 0; +} + +void metal_machine_cache_flush(void *addr, unsigned int len) +{ + (void)addr; + (void)len; +} + +void metal_machine_cache_invalidate(void *addr, unsigned int len) +{ + (void)addr; + (void)len; +} + +/** + * @brief poll function until some event happens + */ +void __attribute__((weak)) metal_generic_default_poll(void) +{ +} + +void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa, + size_t size, unsigned int flags) +{ + (void)va; + (void)pa; + (void)size; + (void)flags; + + return va; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.h new file mode 100644 index 0000000000..7fd8144cbf --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/mp1_m4/sys.h + * @brief generic mp1_m4 system primitives for libmetal. + */ + +#ifndef __METAL_GENERIC_SYS__H__ +#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h" +#endif + +#ifndef __METAL_GENERIC_MP1_M4_SYS__H__ +#define __METAL_GENERIC_MP1_M4_SYS__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MAX_IRQS) +#define MAX_IRQS 8 /**< maximum number of irqs */ +#endif + +static inline void sys_irq_enable(unsigned int vector) +{ + (void)vector; +} + +static inline void sys_irq_disable(unsigned int vector) +{ + (void)vector; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_MP1_M4_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_device.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_device.c new file mode 100644 index 0000000000..d01fd3cd75 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_device.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/device.c + * @brief Generic libmetal device operations. + */ + +#include <metal/device.h> +#include <metal/io.h> +#include <metal/sys.h> +#include <metal/utilities.h> + +int metal_generic_dev_sys_open(struct metal_device *dev) +{ + struct metal_io_region *io; + unsigned i; + + /* map I/O memory regions */ + for (i = 0; i < dev->num_regions; i++) { + io = &dev->regions[i]; + if (!io->size) + break; + metal_sys_io_mem_map(io); + } + + return 0; +} + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_init.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_init.c new file mode 100644 index 0000000000..833b1cd341 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_init.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/init.c + * @brief Generic libmetal initialization. + */ + +#include <metal/sys.h> +#include <metal/utilities.h> +#include <metal/device.h> + +struct metal_state _metal; + +int metal_sys_init(const struct metal_init_params *params) +{ + metal_unused(params); + metal_bus_register(&metal_generic_bus); + return 0; +} + +void metal_sys_finish(void) +{ + metal_bus_unregister(&metal_generic_bus); +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_io.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_io.c new file mode 100644 index 0000000000..670f239d5a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_io.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/io.c + * @brief Generic libmetal io operations + */ + +#include <metal/io.h> + +void metal_sys_io_mem_map(struct metal_io_region *io) +{ + unsigned long p; + size_t psize; + size_t *va; + + va = (size_t *)io->virt; + psize = io->size; + if (psize) { + if (psize >> io->page_shift) + psize = (size_t)1 << io->page_shift; + for (p = 0; p <= (io->size >> io->page_shift); p++) { + metal_machine_io_mem_map(va, io->physmap[p], + psize, io->mem_flags); + va += psize; + } + } +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.c new file mode 100644 index 0000000000..e61bc7e836 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2016 - 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/irq.c + * @brief generic libmetal irq definitions. + */ + +#include <metal/errno.h> +#include <metal/irq.h> +#include <metal/sys.h> +#include <metal/log.h> +#include <metal/mutex.h> +#include <metal/list.h> +#include <metal/utilities.h> +#include <metal/alloc.h> + +/** IRQ handlers descriptor structure */ +struct metal_irq_hddesc { + metal_irq_handler hd; /**< irq handler */ + void *drv_id; /**< id to identify the driver + of the irq handler */ + struct metal_device *dev; /**< device identifier */ + struct metal_list node; /**< node on irq handlers list */ +}; + +/** IRQ descriptor structure */ +struct metal_irq_desc { + int irq; /**< interrupt number */ + struct metal_list hdls; /**< interrupt handlers */ + struct metal_list node; /**< node on irqs list */ +}; + +/** IRQ state structure */ +struct metal_irqs_state { + struct metal_list irqs; /**< interrupt descriptors */ + metal_mutex_t irq_lock; /**< access lock */ +}; + +static struct metal_irqs_state _irqs = { + .irqs = METAL_INIT_LIST(_irqs.irqs), + .irq_lock = METAL_MUTEX_INIT(_irqs.irq_lock), +}; + +int metal_irq_register(int irq, + metal_irq_handler hd, + struct metal_device *dev, + void *drv_id) +{ + struct metal_irq_desc *irq_p = NULL; + struct metal_irq_hddesc *hdl_p; + struct metal_list *node; + unsigned int irq_flags_save; + + if (irq < 0) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d need to be a positive number\n", + __func__, irq); + return -EINVAL; + } + + if ((drv_id == NULL) || (hd == NULL)) { + metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n", + __func__, irq); + return -EINVAL; + } + + /* Search for irq in list */ + metal_mutex_acquire(&_irqs.irq_lock); + metal_list_for_each(&_irqs.irqs, node) { + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if (irq_p->irq == irq) { + struct metal_list *h_node; + + /* Check if drv_id already exist */ + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + /* if drv_id already exist reject */ + if ((hdl_p->drv_id == drv_id) && + ((dev == NULL) || (hdl_p->dev == dev))) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d already registered." + "Will not register again.\n", + __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return -EINVAL; + } + } + /* irq found and drv_id not used, get out of metal_list_for_each */ + break; + } + } + + /* Either need to add handler to an existing list or to a new one */ + hdl_p = metal_allocate_memory(sizeof(struct metal_irq_hddesc)); + if (hdl_p == NULL) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d cannot allocate mem for drv_id %d.\n", + __func__, irq, drv_id); + metal_mutex_release(&_irqs.irq_lock); + return -ENOMEM; + } + hdl_p->hd = hd; + hdl_p->drv_id = drv_id; + hdl_p->dev = dev; + + /* interrupt already registered, add handler to existing list*/ + if ((irq_p != NULL) && (irq_p->irq == irq)) { + irq_flags_save = metal_irq_save_disable(); + metal_list_add_tail(&irq_p->hdls, &hdl_p->node); + metal_irq_restore_enable(irq_flags_save); + + metal_log(METAL_LOG_DEBUG, "%s: success, irq %d add drv_id %p \n", + __func__, irq, drv_id); + metal_mutex_release(&_irqs.irq_lock); + return 0; + } + + /* interrupt was not already registered, add */ + irq_p = metal_allocate_memory(sizeof(struct metal_irq_desc)); + if (irq_p == NULL) { + metal_log(METAL_LOG_ERROR, "%s: irq %d cannot allocate mem.\n", + __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return -ENOMEM; + } + irq_p->irq = irq; + metal_list_init(&irq_p->hdls); + metal_list_add_tail(&irq_p->hdls, &hdl_p->node); + + irq_flags_save = metal_irq_save_disable(); + metal_list_add_tail(&_irqs.irqs, &irq_p->node); + metal_irq_restore_enable(irq_flags_save); + + metal_log(METAL_LOG_DEBUG, "%s: success, added irq %d\n", __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return 0; +} + +/* helper function for metal_irq_unregister() */ +static void metal_irq_delete_node(struct metal_list *node, void *p_to_free) +{ + unsigned int irq_flags_save; + + irq_flags_save=metal_irq_save_disable(); + metal_list_del(node); + metal_irq_restore_enable(irq_flags_save); + metal_free_memory(p_to_free); +} + +int metal_irq_unregister(int irq, + metal_irq_handler hd, + struct metal_device *dev, + void *drv_id) +{ + struct metal_irq_desc *irq_p; + struct metal_list *node; + + if (irq < 0) { + metal_log(METAL_LOG_ERROR, "%s: irq %d need to be a positive number\n", + __func__, irq); + return -EINVAL; + } + + /* Search for irq in list */ + metal_mutex_acquire(&_irqs.irq_lock); + metal_list_for_each(&_irqs.irqs, node) { + + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if (irq_p->irq == irq) { + struct metal_list *h_node, *h_prenode; + struct metal_irq_hddesc *hdl_p; + unsigned int delete_count = 0; + + metal_log(METAL_LOG_DEBUG, "%s: found irq %d\n", + __func__, irq); + + /* Search through handlers */ + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + if (((hd == NULL) || (hdl_p->hd == hd)) && + ((drv_id == NULL) || (hdl_p->drv_id == drv_id)) && + ((dev == NULL) || (hdl_p->dev == dev))) { + metal_log(METAL_LOG_DEBUG, + "%s: unregister hd=%p drv_id=%p dev=%p\n", + __func__, hdl_p->hd, hdl_p->drv_id, hdl_p->dev); + h_prenode = h_node->prev; + metal_irq_delete_node(h_node, hdl_p); + h_node = h_prenode; + delete_count++; + } + } + + /* we did not find any handler to delete */ + if (!delete_count) { + metal_log(METAL_LOG_DEBUG, "%s: No matching entry\n", + __func__); + metal_mutex_release(&_irqs.irq_lock); + return -ENOENT; + + } + + /* if interrupt handlers list is empty, unregister interrupt */ + if (metal_list_is_empty(&irq_p->hdls)) { + metal_log(METAL_LOG_DEBUG, + "%s: handlers list empty, unregister interrupt\n", + __func__); + metal_irq_delete_node(node, irq_p); + } + + metal_log(METAL_LOG_DEBUG, "%s: success\n", __func__); + + metal_mutex_release(&_irqs.irq_lock); + return 0; + } + } + + metal_log(METAL_LOG_DEBUG, "%s: No matching IRQ entry\n", __func__); + + metal_mutex_release(&_irqs.irq_lock); + return -ENOENT; +} + +unsigned int metal_irq_save_disable(void) +{ + return sys_irq_save_disable(); +} + +void metal_irq_restore_enable(unsigned int flags) +{ + sys_irq_restore_enable(flags); +} + +void metal_irq_enable(unsigned int vector) +{ + sys_irq_enable(vector); +} + +void metal_irq_disable(unsigned int vector) +{ + sys_irq_disable(vector); +} + +/** + * @brief default handler + */ +void metal_irq_isr(unsigned int vector) +{ + struct metal_list *node; + struct metal_irq_desc *irq_p; + + metal_list_for_each(&_irqs.irqs, node) { + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if ((unsigned int)irq_p->irq == vector) { + struct metal_list *h_node; + struct metal_irq_hddesc *hdl_p; + + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + (hdl_p->hd)(vector, hdl_p->drv_id); + } + } + } +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.h new file mode 100644 index 0000000000..5744275dc6 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/irq.c + * @brief Generic libmetal irq definitions. + */ + +#ifndef __METAL_IRQ__H__ +#error "Include metal/irq.h instead of metal/generic/irq.h" +#endif + +#ifndef __METAL_GENERIC_IRQ__H__ +#define __METAL_GENERIC_IRQ__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief default interrupt handler + * @param[in] vector interrupt vector + */ +void metal_irq_isr(unsigned int vector); + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_IRQ__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_shmem.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_shmem.c new file mode 100644 index 0000000000..8a28d8ae19 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_shmem.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/shmem.c + * @brief Generic libmetal shared memory handling. + */ + +#include <metal/shmem.h> + +int metal_shmem_open(const char *name, size_t size, + struct metal_io_region **io) +{ + return metal_shmem_open_generic(name, size, io); +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_time.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_time.c new file mode 100644 index 0000000000..fff76192aa --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/generic_time.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/time.c + * @brief Generic libmetal time handling. + */ + +#include <metal/time.h> + +unsigned long long metal_get_timestamp(void) +{ + /* TODO: Implement timestamp for generic system */ + return 0; +} + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/io.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/io.h new file mode 100644 index 0000000000..adbbc44774 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/io.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/io.h + * @brief Generic specific io definitions. + */ + +#ifndef __METAL_IO__H__ +#error "Include metal/io.h instead of metal/generic/io.h" +#endif + +#ifndef __METAL_GENERIC_IO__H__ +#define __METAL_GENERIC_IO__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef METAL_INTERNAL + +/** + * @brief memory mapping for an I/O region + */ +void metal_sys_io_mem_map(struct metal_io_region *io); + +/** + * @brief memory mapping + */ +void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa, + size_t size, unsigned int flags); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_IO__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/log.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/log.h new file mode 100644 index 0000000000..32611288ad --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/log.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Linaro nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/log.h + * @brief Generic libmetal log handler definition. + */ + +#ifndef __METAL_METAL_LOG__H__ +#error "Include metal/log.h instead of metal/generic/log.h" +#endif + +#ifndef __METAL_GENERIC_LOG__H__ +#define __METAL_GENERIC_LOG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_LOG__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/mutex.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/mutex.h new file mode 100644 index 0000000000..3613c194d1 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/mutex.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/mutex.h + * @brief Generic mutex primitives for libmetal. + */ + +#ifndef __METAL_MUTEX__H__ +#error "Include metal/mutex.h instead of metal/generic/mutex.h" +#endif + +#ifndef __METAL_GENERIC_MUTEX__H__ +#define __METAL_GENERIC_MUTEX__H__ + +#include <metal/atomic.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + union{ + atomic_int v; + atomic_flag w; + }; +} metal_mutex_t; + +/* + * METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct + * or global + */ +#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) } +/* + * METAL_MUTEX_DEFINE - used for defining and initializing a global or + * static singleton mutex + */ +#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m) + +static inline void __metal_mutex_init(metal_mutex_t *mutex) +{ + atomic_store(&mutex->v, 0); +} + +static inline void __metal_mutex_deinit(metal_mutex_t *mutex) +{ + (void)mutex; +} + +static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex) +{ + return 1 - atomic_flag_test_and_set(&mutex->w); +} + +static inline void __metal_mutex_acquire(metal_mutex_t *mutex) +{ + while (atomic_flag_test_and_set(&mutex->w)) { + ; + } +} + +static inline void __metal_mutex_release(metal_mutex_t *mutex) +{ + atomic_flag_clear(&mutex->w); +} + +static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex) +{ + return atomic_load(&mutex->v); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_MUTEX__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/sleep.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/sleep.h new file mode 100644 index 0000000000..aa86df492e --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/sleep.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/sleep.h + * @brief Generic sleep primitives for libmetal. + */ + +#ifndef __METAL_SLEEP__H__ +#error "Include metal/sleep.h instead of metal/generic/sleep.h" +#endif + +#ifndef __METAL_GENERIC_SLEEP__H__ +#define __METAL_GENERIC_SLEEP__H__ + +#include <metal/utilities.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline int __metal_sleep_usec(unsigned int usec) +{ + metal_unused(usec); + /* Fix me */ + return 0; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_SLEEP__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/sys.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/sys.h new file mode 100644 index 0000000000..320af6b0b7 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/system/generic/sys.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/sys.h + * @brief Generic system primitives for libmetal. + */ + +#ifndef __METAL_SYS__H__ +#error "Include metal/sys.h instead of metal/generic/sys.h" +#endif + +#ifndef __METAL_GENERIC_SYS__H__ +#define __METAL_GENERIC_SYS__H__ + +#include <metal/errno.h> +#include <fcntl.h> +#include <libgen.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "./@PROJECT_MACHINE@/sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef METAL_MAX_DEVICE_REGIONS +#define METAL_MAX_DEVICE_REGIONS 1 +#endif + +/** Structure of generic libmetal runtime state. */ +struct metal_state { + + /** Common (system independent) data. */ + struct metal_common_state common; +}; + +#ifdef METAL_INTERNAL + +/** + * @brief restore interrupts to state before disable_global_interrupt() + */ +void sys_irq_restore_enable(unsigned int flags); + +/** + * @brief disable all interrupts + */ +unsigned int sys_irq_save_disable(void); + +#endif /* METAL_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/version.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/version.c new file mode 100644 index 0000000000..9595a85f37 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/libmetal/lib/version.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/config.h> + +int metal_ver_major(void) +{ + return METAL_VER_MAJOR; +} + +int metal_ver_minor(void) +{ + return METAL_VER_MINOR; +} + +int metal_ver_patch(void) +{ + return METAL_VER_PATCH; +} + +const char *metal_ver(void) +{ + return METAL_VER; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/compiler.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/compiler.h new file mode 100644 index 0000000000..acb4c9b369 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/compiler.h @@ -0,0 +1,71 @@ +#ifndef _COMPILER_H_ +#define _COMPILER_H_ + +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * compiler.h + * + * DESCRIPTION + * + * This file defines compiler-specific macros. + * + ***************************************************************************/ +#if defined __cplusplus +extern "C" { +#endif + +/* IAR ARM build tools */ +#if defined(__ICCARM__) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN __packed +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END +#endif + +/* GNUC */ +#elif defined(__GNUC__) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END __attribute__((__packed__)) +#endif + +/* ARM GCC */ +#elif defined(__CC_ARM) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN _Pragma("pack(1U)") +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END _Pragma("pack()") +#endif + +#else +/* + * There is no default definition here to avoid wrong structures packing in case + * of not supported compiler + */ +#error Please implement the structure packing macros for your compiler here! +#endif + +#if defined __cplusplus +} +#endif + +#endif /* _COMPILER_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/elf_loader.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/elf_loader.h new file mode 100644 index 0000000000..3c6ec4af15 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/elf_loader.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ELF_LOADER_H_ +#define ELF_LOADER_H_ + +#include <openamp/remoteproc.h> +#include <openamp/remoteproc_loader.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* ELF32 base types - 32-bit. */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* ELF64 base types - 64-bit. */ +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Size of ELF identifier field in the ELF file header. */ +#define EI_NIDENT 16 + +/* ELF32 file header */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* ELF64 file header */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* e_ident */ +#define ET_NONE 0 +#define ET_REL 1 /* Re-locatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOOS 0xfe00 /* Operating system-specific */ +#define ET_HIOS 0xfeff /* Operating system-specific */ +#define ET_LOPROC 0xff00 /* remote_proc-specific */ +#define ET_HIPROC 0xffff /* remote_proc-specific */ + +/* e_machine */ +#define EM_ARM 40 /* ARM/Thumb Architecture */ + +/* e_version */ +#define EV_CURRENT 1 /* Current version */ + +/* e_ident[] Identification Indexes */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class */ +#define EI_DATA 5 /* Data encoding */ +#define EI_VERSION 6 /* File version */ +#define EI_OSABI 7 /* Operating system/ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* Start of padding bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +/* + * EI_MAG0 to EI_MAG3 - A file's first 4 bytes hold amagic number, identifying + * the file as an ELF object file + */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +/* + * EI_CLASS - The next byte, e_ident[EI_CLASS], identifies the file's class, or + * capacity. + */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +/* + * EI_DATA - Byte e_ident[EI_DATA] specifies the data encoding of the + * remote_proc-specific data in the object file. The following encodings are + * currently defined. + */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* See Data encodings, below */ +#define ELFDATA2MSB 2 /* See Data encodings, below */ + +/* EI_OSABI - We do not define an OS specific ABI */ +#define ELFOSABI_NONE 0 + +/* ELF32 program header */ +typedef struct elf32_phdr{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* ELF64 program header */ +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +/* segment types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* ELF32 section header. */ +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* ELF64 section header. */ +typedef struct { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_LOOS 0x60000000 +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* Relocation entry (without addend) */ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + +} Elf32_Rel; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; + +} Elf64_Rel; + +/* Relocation entry with addend */ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; + +} Elf32_Rela; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +/* Macros to extract information from 'r_info' field of relocation entries */ +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) + +/* Symbol table entry */ +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; + +} Elf32_Sym; + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +/* ARM specific dynamic relocation codes */ +#define R_ARM_GLOB_DAT 21 /* 0x15 */ +#define R_ARM_JUMP_SLOT 22 /* 0x16 */ +#define R_ARM_RELATIVE 23 /* 0x17 */ +#define R_ARM_ABS32 2 /* 0x02 */ + +/* ELF decoding information */ +struct elf32_info { + Elf32_Ehdr ehdr; + unsigned int load_state; + Elf32_Phdr *phdrs; + Elf32_Shdr *shdrs; + void *shstrtab; +}; + +struct elf64_info { + Elf64_Ehdr ehdr; + unsigned int load_state; + Elf64_Phdr *phdrs; + Elf64_Shdr *shdrs; + void *shstrtab; +}; + +#define ELF_STATE_INIT 0x0UL +#define ELF_STATE_WAIT_FOR_PHDRS 0x100UL +#define ELF_STATE_WAIT_FOR_SHDRS 0x200UL +#define ELF_STATE_WAIT_FOR_SHSTRTAB 0x400UL +#define ELF_STATE_HDRS_COMPLETE 0x800UL +#define ELF_STATE_MASK 0xFF00UL +#define ELF_NEXT_SEGMENT_MASK 0x00FFUL + +extern struct loader_ops elf_ops; + +/** + * elf_identify - check if it is an ELF file + * + * It will check if the input image header is an ELF header. + * + * @img_data: firmware private data which will be passed to user defined loader + * operations + * @len: firmware header length + * + * return 0 for success or negative value for failure. + */ +int elf_identify(const void *img_data, size_t len); + +/** + * elf_load_header - Load ELF headers + * + * It will get the ELF header, the program header, and the section header. + * + * @img_data: image data + * @offset: input image data offset to the start of image file + * @len: input image data length + * @img_info: pointer to store image information data + * @last_load_state: last state return by this function + * @noffset: pointer to next offset required by loading ELF header + * @nlen: pointer to next data length required by loading ELF header + * + * return ELF loading header state, or negative value for failure + */ +int elf_load_header(const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + size_t *noffset, size_t *nlen); + +/** + * elf_load - load ELF data + * + * It will parse the ELF image and return the target device address, + * offset to the start of the ELF image of the data to load and the + * length of the data to load. + * + * @rproc: pointer to remoteproc instance + * @img_data: image data which will passed to the function. + * it can be NULL, if image data doesn't need to be handled + * by the load function. E.g. binary data which was + * loaded to the target memory. + * @offset: last loaded image data offset to the start of image file + * @len: last loaded image data length + * @img_info: pointer to store image information data + * @last_load_state: the returned state of the last function call. + * @da: target device address, if the data to load is not for target memory + * the da will be set to ANY. + * @noffset: pointer to next offset required by loading ELF header + * @nlen: pointer to next data length required by loading ELF header + * @padding: value to pad it is possible that a size of a segment in memory + * is larger than what it is in the ELF image. e.g. a segment + * can have stack section .bss. It doesn't need to copy image file + * space, in this case, it will be packed with 0. + * @nmemsize: pointer to next data target memory size. The size of a segment + * in the target memory can be larger than the its size in the + * image file. + * + * return 0 for success, otherwise negative value for failure + */ +int elf_load(struct remoteproc *rproc, const void *img_data, + size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize); + +/** + * elf_release - Release ELF image information + * + * It will release ELF image information data. + * + * @img_info: pointer to ELF image information + */ +void elf_release(void *img_info); + +/** + * elf_get_entry - Get entry point + * + * It will return entry point specified in the ELF file. + * + * @img_info: pointer to ELF image information + * + * return entry address + */ +metal_phys_addr_t elf_get_entry(void *img_info); + +/** + * elf_locate_rsc_table - locate the resource table information + * + * It will return the length of the resource table, and the device address of + * the resource table. + * + * @img_info: pointer to ELF image information + * @da: pointer to the device address + * @offset: pointer to the offset to in the ELF image of the resource + * table section. + * @size: pointer to the size of the resource table section. + * + * return 0 if successfully locate the resource table, negative value for + * failure. + */ +int elf_locate_rsc_table(void *img_info, metal_phys_addr_t *da, + size_t *offset, size_t *size); + +#if defined __cplusplus +} +#endif + +#endif /* ELF_LOADER_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/open_amp.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/open_amp.h new file mode 100644 index 0000000000..1a01688a9f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/open_amp.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OPEN_AMP_H_ +#define OPEN_AMP_H_ + +#include <openamp/rpmsg.h> +#include <openamp/rpmsg_virtio.h> +#include <openamp/remoteproc.h> +#include <openamp/remoteproc_virtio.h> + + +#endif /* OPEN_AMP_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc.h new file mode 100644 index 0000000000..90d908729c --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc.h @@ -0,0 +1,871 @@ +/* + * Remoteproc Framework + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REMOTEPROC_H +#define REMOTEPROC_H + +#include <metal/io.h> +#include <metal/mutex.h> +#include <openamp/compiler.h> + +#if defined __cplusplus +extern "C" { +#endif + +#define RSC_NOTIFY_ID_ANY 0xFFFFFFFFUL + +/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote remote_proc. It may also include configuration entries. + * If needed, the remote remote_proc firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * Some resources entries are mere announcements, where the host is informed + * of specific remoteproc configuration. Other entries require the host to + * do something (e.g. allocate a system resource). Sometimes a negotiation + * is expected, where the firmware requests a resource, and once allocated, + * the host should provide back its details (e.g. address of an allocated + * memory region). + * + * The header of the resource table, as expressed by this structure, + * contains a version number (should we need to change this format in the + * future), the number of available resource entries, and their offsets + * in the table. + * + * Immediately following this header are the resource entries themselves, + * each of which begins with a resource entry header (as described below). + */ +OPENAMP_PACKED_BEGIN +struct resource_table { + uint32_t ver; + uint32_t num; + uint32_t reserved[2]; + uint32_t offset[0]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_hdr - firmware resource entry header + * @type: resource type + * @data: resource data + * + * Every resource entry begins with a 'struct fw_rsc_hdr' header providing + * its @type. The content of the entry itself will immediately follow + * this header, and it should be parsed according to the resource type. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_hdr { + uint32_t type; + uint8_t data[0]; +} OPENAMP_PACKED_END; + +/** + * enum fw_resource_type - types of resource entries + * + * @RSC_CARVEOUT: request for allocation of a physically contiguous + * memory region. + * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. + * @RSC_TRACE: announces the availability of a trace buffer into which + * the remote remote_proc will be writing logs. + * @RSC_VDEV: declare support for a virtio device, and serve as its + * virtio header. + * @RSC_VENDOR_START: start of the vendor specific resource types range + * @RSC_VENDOR_END : end of the vendor specific resource types range + * @RSC_LAST: just keep this one at the end + * + * For more details regarding a specific resource type, please see its + * dedicated structure below. + * + * Please note that these values are used as indices to the rproc_handle_rsc + * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to + * check the validity of an index before the lookup table is accessed, so + * please update it as needed. + */ +enum fw_resource_type { + RSC_CARVEOUT = 0, + RSC_DEVMEM = 1, + RSC_TRACE = 2, + RSC_VDEV = 3, + RSC_RPROC_MEM = 4, + RSC_FW_CHKSUM = 5, + RSC_LAST = 6, + RSC_VENDOR_START = 128, + RSC_VENDOR_END = 512, +}; + +#define FW_RSC_ADDR_ANY (0xFFFFFFFFFFFFFFFF) +#define FW_RSC_U32_ADDR_ANY (0xFFFFFFFF) + +/** + * struct fw_rsc_carveout - physically contiguous memory request + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @flags: iommu protection flags + * @reserved: reserved (must be zero) + * @name: human-readable name of the requested memory region + * + * This resource entry requests the host to allocate a physically contiguous + * memory region. + * + * These request entries should precede other firmware resource entries, + * as other entries might request placing other data objects inside + * these memory regions (e.g. data/code segments, trace resource entries, ...). + * + * Allocating memory this way helps utilizing the reserved physical memory + * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries + * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB + * pressure is important; it may have a substantial impact on performance. + * + * If the firmware is compiled with static addresses, then @da should specify + * the expected device address of this memory region. If @da is set to + * FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then + * overwrite @da with the dynamically allocated address. + * + * We will always use @da to negotiate the device addresses, even if it + * isn't using an iommu. In that case, though, it will obviously contain + * physical addresses. + * + * Some remote remote_procs needs to know the allocated physical address + * even if they do use an iommu. This is needed, e.g., if they control + * hardware accelerators which access the physical memory directly (this + * is the case with OMAP4 for instance). In that case, the host will + * overwrite @pa with the dynamically allocated physical address. + * Generally we don't want to expose physical addresses if we don't have to + * (remote remote_procs are generally _not_ trusted), so we might want to + * change this to happen _only_ when explicitly required by the hardware. + * + * @flags is used to provide IOMMU protection flags, and @name should + * (optionally) contain a human readable name of this carveout region + * (mainly for debugging purposes). + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_carveout { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t flags; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_devmem - iommu mapping request + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @flags: iommu protection flags + * @reserved: reserved (must be zero) + * @name: human-readable name of the requested region to be mapped + * + * This resource entry requests the host to iommu map a physically contiguous + * memory region. This is needed in case the remote remote_proc requires + * access to certain memory-based peripherals; _never_ use it to access + * regular memory. + * + * This is obviously only needed if the remote remote_proc is accessing memory + * via an iommu. + * + * @da should specify the required device address, @pa should specify + * the physical address we want to map, @len should specify the size of + * the mapping and @flags is the IOMMU protection flags. As always, @name may + * (optionally) contain a human readable name of this mapping (mainly for + * debugging purposes). + * + * Note: at this point we just "trust" those devmem entries to contain valid + * physical addresses, but this isn't safe and will be changed: eventually we + * want remoteproc implementations to provide us ranges of physical addresses + * the firmware is allowed to request, and not allow firmwares to request + * access to physical addresses that are outside those ranges. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_devmem { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t flags; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_trace - trace buffer declaration + * @da: device address + * @len: length (in bytes) + * @reserved: reserved (must be zero) + * @name: human-readable name of the trace buffer + * + * This resource entry provides the host information about a trace buffer + * into which the remote remote_proc will write log messages. + * + * @da specifies the device address of the buffer, @len specifies + * its size, and @name may contain a human readable name of the trace buffer. + * + * After booting the remote remote_proc, the trace buffers are exposed to the + * user via debugfs entries (called trace0, trace1, etc..). + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_trace { + uint32_t type; + uint32_t da; + uint32_t len; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vdev_vring - vring descriptor entry + * @da: device address + * @align: the alignment between the consumer and producer parts of the vring + * @num: num of buffers supported by this vring (must be power of two) + * @notifyid is a unique rproc-wide notify index for this vring. This notify + * index is used when kicking a remote remote_proc, to let it know that this + * vring is triggered. + * @reserved: reserved (must be zero) + * + * This descriptor is not a resource entry by itself; it is part of the + * vdev resource type (see below). + * + * Note that @da should either contain the device address where + * the remote remote_proc is expecting the vring, or indicate that + * dynamically allocation of the vring's device address is supported. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vdev_vring { + uint32_t da; + uint32_t align; + uint32_t num; + uint32_t notifyid; + uint32_t reserved; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vdev - virtio device header + * @id: virtio device id (as in virtio_ids.h) + * @notifyid is a unique rproc-wide notify index for this vdev. This notify + * index is used when kicking a remote remote_proc, to let it know that the + * status/features of this vdev have changes. + * @dfeatures specifies the virtio device features supported by the firmware + * @gfeatures is a place holder used by the host to write back the + * negotiated features that are supported by both sides. + * @config_len is the size of the virtio config space of this vdev. The config + * space lies in the resource table immediate after this vdev header. + * @status is a place holder where the host will indicate its virtio progress. + * @num_of_vrings indicates how many vrings are described in this vdev header + * @reserved: reserved (must be zero) + * @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'. + * + * This resource is a virtio device header: it provides information about + * the vdev, and is then used by the host and its peer remote remote_procs + * to negotiate and share certain virtio properties. + * + * By providing this resource entry, the firmware essentially asks remoteproc + * to statically allocate a vdev upon registration of the rproc (dynamic vdev + * allocation is not yet supported). + * + * Note: unlike virtualization systems, the term 'host' here means + * the Linux side which is running remoteproc to control the remote + * remote_procs. We use the name 'gfeatures' to comply with virtio's terms, + * though there isn't really any virtualized guest OS here: it's the host + * which is responsible for negotiating the final features. + * Yeah, it's a bit confusing. + * + * Note: immediately following this structure is the virtio config space for + * this vdev (which is specific to the vdev; for more info, read the virtio + * spec). the size of the config space is specified by @config_len. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vdev { + uint32_t type; + uint32_t id; + uint32_t notifyid; + uint32_t dfeatures; + uint32_t gfeatures; + uint32_t config_len; + uint8_t status; + uint8_t num_of_vrings; + uint8_t reserved[2]; + struct fw_rsc_vdev_vring vring[0]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vendor - remote processor vendor specific resource + * @len: length of the resource + * + * This resource entry tells the host the vendor specific resource + * required by the remote. + * + * These request entries should precede other shared resource entries + * such as vdevs, vrings. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vendor { + uint32_t type; + uint32_t len; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_rproc_mem - remote processor memory + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @reserved: reserved (must be zero) + * + * This resource entry tells the host to the remote processor + * memory that the host can be used as shared memory. + * + * These request entries should precede other shared resource entries + * such as vdevs, vrings. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_rproc_mem { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t reserved; +} OPENAMP_PACKED_END; + +/* + * struct fw_rsc_fw_chksum - firmware checksum + * @algo: algorithm to generate the cheksum + * @chksum: checksum of the firmware loadable sections. + * + * This resource entry provides checksum for the firmware loadable sections. + * It is used to check if the remote already runs with the expected firmware to + * decide if it needs to start the remote if the remote is already running. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_fw_chksum { + uint32_t type; + uint8_t algo[16]; + uint8_t chksum[64]; +} OPENAMP_PACKED_END; + +struct loader_ops; +struct image_store_ops; +struct remoteproc_ops; + +/** + * struct remoteproc_mem + * + * This structure presents the memory used by the remote processor + * + * @da: device memory + * @pa: physical memory + * @size: size of the memory + * @io: pointer to the I/O region + * @node: list node + */ +struct remoteproc_mem { + metal_phys_addr_t da; + metal_phys_addr_t pa; + size_t size; + char name[32]; + struct metal_io_region *io; + struct metal_list node; +}; + +/** + * struct remoteproc + * + * This structure is maintained by the remoteproc to represent the remote + * processor instance. This structure acts as a prime parameter to use + * the remoteproc APIs. + * + * @bootadd: boot address + * @loader: executable loader + * @lock: mutext lock + * @ops: remoteproc operations + * @rsc_table: pointer to resource table + * @rsc_len: length of resource table + * @rsc_io: metal I/O region of resource table + * @mems: remoteproc memories + * @vdevs: remoteproc virtio devices + * @bitmap: bitmap for notify IDs for remoteproc subdevices + * @state: remote processor state + * @priv: private data + */ +struct remoteproc { + metal_mutex_t lock; + void *rsc_table; + size_t rsc_len; + struct metal_io_region *rsc_io; + struct metal_list mems; + struct metal_list vdevs; + unsigned long bitmap; + struct remoteproc_ops *ops; + metal_phys_addr_t bootaddr; + struct loader_ops *loader; + unsigned int state; + void *priv; +}; + +/** + * struct remoteproc_ops + * + * remoteproc operations needs to be implemented by each remoteproc driver + * + * @init: initialize the remoteproc instance + * @remove: remove the remoteproc instance + * @mmap: memory mapped the mempory with physical address or destination + * address as input. + * @handle_rsc: handle the vendor specific resource + * @config: configure the remoteproc to make it ready to load and run + * executable + * @start: kick the remoteproc to run application + * @stop: stop the remoteproc from running application, the resource such as + * memory may not be off. + * @shutdown: shutdown the remoteproc and release its resources. + * @notify: notify the remote + */ +struct remoteproc_ops { + struct remoteproc *(*init)(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *arg); + void (*remove)(struct remoteproc *rproc); + void *(*mmap)(struct remoteproc *rproc, + metal_phys_addr_t *pa, metal_phys_addr_t *da, + size_t size, unsigned int attribute, + struct metal_io_region **io); + int (*handle_rsc)(struct remoteproc *rproc, void *rsc, size_t len); + int (*config)(struct remoteproc *rproc, void *data); + int (*start)(struct remoteproc *rproc); + int (*stop)(struct remoteproc *rproc); + int (*shutdown)(struct remoteproc *rproc); + int (*notify)(struct remoteproc *rproc, uint32_t id); +}; + +/* Remoteproc error codes */ +#define RPROC_EBASE 0 +#define RPROC_ENOMEM (RPROC_EBASE + 1) +#define RPROC_EINVAL (RPROC_EBASE + 2) +#define RPROC_ENODEV (RPROC_EBASE + 3) +#define RPROC_EAGAIN (RPROC_EBASE + 4) +#define RPROC_ERR_RSC_TAB_TRUNC (RPROC_EBASE + 5) +#define RPROC_ERR_RSC_TAB_VER (RPROC_EBASE + 6) +#define RPROC_ERR_RSC_TAB_RSVD (RPROC_EBASE + 7) +#define RPROC_ERR_RSC_TAB_VDEV_NRINGS (RPROC_EBASE + 9) +#define RPROC_ERR_RSC_TAB_NP (RPROC_EBASE + 10) +#define RPROC_ERR_RSC_TAB_NS (RPROC_EBASE + 11) +#define RPROC_ERR_LOADER_STATE (RPROC_EBASE + 12) +#define RPROC_EMAX (RPROC_EBASE + 16) +#define RPROC_EPTR (void *)(-1) +#define RPROC_EOF (void *)(-1) + +static inline long RPROC_PTR_ERR(const void *ptr) +{ + return (long)ptr; +} + +static inline int RPROC_IS_ERR(const void *ptr) +{ + if ((unsigned long)ptr >= (unsigned long)(-RPROC_EMAX)) + return 1; + else + return 0; +} + +static inline void *RPROC_ERR_PTR(long error) +{ + return (void *)error; +} + +/** + * enum rproc_state - remote processor states + * @RPROC_OFFLINE: remote is offline + * @RPROC_READY: remote is ready to start + * @RPROC_RUNNING: remote is up and running + * @RPROC_SUSPENDED: remote is suspended + * @RPROC_ERROR: remote has error; need to recover + * @RPROC_STOPPED: remote is stopped + * @RPROC_LAST: just keep this one at the end + */ +enum remoteproc_state { + RPROC_OFFLINE = 0, + RPROC_CONFIGURED = 1, + RPROC_READY = 2, + RPROC_RUNNING = 3, + RPROC_SUSPENDED = 4, + RPROC_ERROR = 5, + RPROC_STOPPED = 6, + RPROC_LAST = 7, +}; + +/** + * remoteproc_init + * + * Initializes remoteproc resource. + * + * @rproc - pointer to remoteproc instance + * @ops - pointer to remoteproc operations + * @priv - pointer to private data + * + * @returns created remoteproc pointer + */ +struct remoteproc *remoteproc_init(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *priv); + +/** + * remoteproc_remove + * + * Remove remoteproc resource + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success, negative value for failure + */ +int remoteproc_remove(struct remoteproc *rproc); + +/** + * remoteproc_init_mem + * + * Initialize remoteproc memory + * + * @mem - pointer to remoteproc memory + * @char - memory name + * @pa - physcial address + * @da - device address + * @size - memory size + * @io - pointer to the I/O region + */ +static inline void +remoteproc_init_mem(struct remoteproc_mem *mem, const char *name, + metal_phys_addr_t pa, metal_phys_addr_t da, + size_t size, struct metal_io_region *io) +{ + if (!mem) + return; + if (name) + strncpy(mem->name, name, sizeof(mem->name)); + else + mem->name[0] = 0; + mem->pa = pa; + mem->da = da; + mem->io = io; + mem->size = size; +} + +/** + * remoteproc_add_mem + * + * Add remoteproc memory + * + * @rproc - pointer to remoteproc + * @mem - pointer to remoteproc memory + */ +static inline void +remoteproc_add_mem(struct remoteproc *rproc, struct remoteproc_mem *mem) +{ + if (!rproc || !mem) + return; + metal_list_add_tail(&rproc->mems, &mem->node); +} + +/** + * remoteproc_get_io_with_name + * + * get remoteproc memory I/O region with name + * + * @rproc - pointer to the remote processor + * @name - name of the shared memory + * @io - pointer to the pointer of the I/O region + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_name(struct remoteproc *rproc, + const char *name); + +/** + * remoteproc_get_io_with_pa + * + * get remoteproc memory I/O region with physical address + * + * @rproc - pointer to the remote processor + * @pa - physical address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_pa(struct remoteproc *rproc, + metal_phys_addr_t pa); + +/** + * remoteproc_get_io_with_da + * + * get remoteproc memory I/O region with device address + * + * @rproc - pointer to the remote processor + * @da - device address + * @offset - I/O region offset of the device address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_da(struct remoteproc *rproc, + metal_phys_addr_t da, + unsigned long *offset); + +/** + * remoteproc_get_io_with_va + * + * get remoteproc memory I/O region with virtual address + * + * @rproc - pointer to the remote processor + * @va - virtual address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_va(struct remoteproc *rproc, + void *va); + +/** + * remoteproc_mmap + * + * remoteproc mmap memory + * + * @rproc - pointer to the remote processor + * @pa - physical address pointer + * @da - device address pointer + * @size - size of the memory + * @attribute - memory attribute + * @io - pointer to the I/O region + * + * returns pointer to the memory + */ +void *remoteproc_mmap(struct remoteproc *rproc, + metal_phys_addr_t *pa, metal_phys_addr_t *da, + size_t size, unsigned int attribute, + struct metal_io_region **io); + +/** + * remoteproc_parse_rsc_table + * + * Parse resource table of remoteproc + * + * @rproc - pointer to remoteproc instance + * @rsc_table - pointer to resource table + * @rsc_size - resource table size + * + * returns 0 for success and negative value for errors + */ +int remoteproc_parse_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size); + +/** + * remoteproc_set_rsc_table + * + * Parse and set resource table of remoteproc + * + * @rproc - pointer to remoteproc instance + * @rsc_table - pointer to resource table + * @rsc_size - resource table size + * + * returns 0 for success and negative value for errors + */ +int remoteproc_set_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size); + +/** + * remoteproc_config + * + * This function configures the remote processor to get it + * ready to load and run executable. + * + * @rproc - pointer to remoteproc instance to start + * @data - configuration data + * + * returns 0 for success and negative value for errors + */ +int remoteproc_config(struct remoteproc *rproc, void *data); + +/** + * remoteproc_start + * + * This function starts the remote processor. + * It assumes the firmware is already loaded, + * + * @rproc - pointer to remoteproc instance to start + * + * returns 0 for success and negative value for errors + */ +int remoteproc_start(struct remoteproc *rproc); + +/** + * remoteproc_stop + * + * This function stops the remote processor but it + * will not release its resource. + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success and negative value for errors + */ +int remoteproc_stop(struct remoteproc *rproc); + +/** + * remoteproc_shutdown + * + * This function shutdown the remote processor and + * release its resources. + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success and negative value for errors + */ +int remoteproc_shutdown(struct remoteproc *rproc); + +/** + * remoteproc_load + * + * load executable, it expects the user application defines how to + * open the executable file and how to get data from the executable file + * and how to load data to the target memory. + * + * @rproc: pointer to the remoteproc instance + * @path: optional path to the image file + * @store: pointer to user defined image store argument + * @store_ops: pointer to image store operations + * @image_info: pointer to memory which stores image information used + * by remoteproc loader + * + * return 0 for success and negative value for failure + */ +int remoteproc_load(struct remoteproc *rproc, const char *path, + void *store, struct image_store_ops *store_ops, + void **img_info); + +/** + * remoteproc_load_noblock + * + * load executable, it expects the caller has loaded image data to local + * memory and passed to the this function. If the function needs more + * image data it will return the next expected image data offset and + * the next expected image data length. If the function requires the + * caller to download image data to the target memory, it will also + * return the target physical address besides the offset and length. + * This function can be used to load firmware in stream mode. In this + * mode, you cannot do seek to the executable file. If the executable + * is ELF, it cannot get the resource table section before it loads + * the full ELF file. Furthermore, application usually don't store + * the data which is loaded to local memory in streaming mode, and + * thus, in this mode, it will load the binrary to the target memory + * before it gets the resource table. And thus, when calling this funciton + * don't put the target exectuable memory in the resource table, as + * this function will parse the resource table after it loads the binary + * to target memory. + * + * @rproc: pointer to the remoteproc instance + * @img_data: pointer to image data for remoteproc loader to parse + * @offset: image data offset to the beginning of the image file + * @len: image data length + * @image_info: pointer to memory which stores image information used + * by remoteproc loader + * @pa: pointer to the target memory physical address. If the next expected + * data doesn't need to load to the target memory, the function will + * set it to ANY. + * @io: pointer to the target memory physical address. If the next expected + * data doesn't need to load to the target memory, the function will + * set it to ANY. + * @noffset: pointer to the next image data offset to the beginning of + * the image file needs to load to local or to the target + * memory. + * @nlen: pointer to the next image data length needs to load to local + * or to the target memory. + * @nmlen: pointer to the memory size. It is only used when the next + * expected data is going to be loaded to the target memory. E.g. + * in ELF, it is possible that loadable segment in memory is + * larger that the segment data in the ELF file. In this case, + * application will need to pad the rest of the memory with + * padding. + * @padding: pointer to the padding value. It is only used when the next + * expected data is going to be loaded to the target memory. + * and the target memory size is larger than the segment data in + * the executable file. + * + * return 0 for success and negative value for failure + */ +int remoteproc_load_noblock(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, + metal_phys_addr_t *pa, struct metal_io_region **io, + size_t *noffset, size_t *nlen, + size_t *nmlen, unsigned char *padding); + +/** + * remoteproc_allocate_id + * + * allocate notifyid for resource + * + * @rproc - pointer to the remoteproc instance + * @start - start of the id range + * @end - end of the id range + * + * return allocated notify id + */ +unsigned int remoteproc_allocate_id(struct remoteproc *rproc, + unsigned int start, + unsigned int end); + +/* remoteproc_create_virtio + * + * create virtio device, it returns pointer to the created virtio device. + * + * @rproc: pointer to the remoteproc instance + * @vdev_id: virtio device ID + * @role: virtio device role + * @rst_cb: virtio device reset callback + * + * return pointer to the created virtio device, NULL for failure. + */ +struct virtio_device * +remoteproc_create_virtio(struct remoteproc *rproc, + int vdev_id, unsigned int role, + void (*rst_cb)(struct virtio_device *vdev)); + +/* remoteproc_remove_virtio + * + * Remove virtio device + * + * @rproc: pointer to the remoteproc instance + * @vdev: pointer to the virtio device + * + */ +void remoteproc_remove_virtio(struct remoteproc *rproc, + struct virtio_device *vdev); + +/* remoteproc_get_notification + * + * remoteproc is got notified, it will check its subdevices + * for the notification + * + * @rproc - pointer to the remoteproc instance + * @notifyid - notificatin id + * + * return 0 for succeed, negative value for failure + */ +int remoteproc_get_notification(struct remoteproc *rproc, + uint32_t notifyid); +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_loader.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_loader.h new file mode 100644 index 0000000000..4409a1aa7a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_loader.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * remoteproc_loader.h + * + * COMPONENT + * + * OpenAMP stack. + * + * DESCRIPTION + * + * This file provides definitions for remoteproc loader + * + * + **************************************************************************/ +#ifndef REMOTEPROC_LOADER_H_ +#define REMOTEPROC_LOADER_H_ + +#include <metal/io.h> +#include <metal/list.h> +#include <metal/sys.h> +#include <openamp/remoteproc.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* Loader feature macros */ +#define SUPPORT_SEEK 1UL + +/* Remoteproc loader any address */ +#define RPROC_LOAD_ANYADDR ((metal_phys_addr_t)-1) + +/* Remoteproc loader Exectuable Image Parsing States */ +/* Remoteproc loader parser intial state */ +#define RPROC_LOADER_NOT_READY 0x0UL +/* Remoteproc loader ready to load, even it can be not finish parsing */ +#define RPROC_LOADER_READY_TO_LOAD 0x10000UL +/* Remoteproc loader post data load */ +#define RPROC_LOADER_POST_DATA_LOAD 0x20000UL +/* Remoteproc loader finished loading */ +#define RPROC_LOADER_LOAD_COMPLETE 0x40000UL +/* Remoteproc loader state mask */ +#define RPROC_LOADER_MASK 0x00FF0000UL +/* Remoteproc loader private mask */ +#define RPROC_LOADER_PRIVATE_MASK 0x0000FFFFUL +/* Remoteproc loader reserved mask */ +#define RPROC_LOADER_RESERVED_MASK 0x0F000000UL + +/** + * struct image_store_ops - user defined image store operations + * @open: user defined callback to open the "firmware" to prepare loading + * @close: user defined callback to close the "firmware" to clean up + * after loading + * @load: user defined callback to load the firmware contents to target + * memory or local memory + * @features: loader supported features. e.g. seek + */ +struct image_store_ops { + int (*open)(void *store, const char *path, const void **img_data); + void (*close)(void *store); + int (*load)(void *store, size_t offset, size_t size, + const void **data, + metal_phys_addr_t pa, + struct metal_io_region *io, char is_blocking); + unsigned int features; +}; + +/** + * struct loader_ops - loader oeprations + * @load_header: define how to get the executable headers + * @load_data: define how to load the target data + * @locate_rsc_table: define how to get the resource table target address, + * offset to the ELF image file and size of the resource + * table. + * @release: define how to release the loader + * @get_entry: get entry address + * @get_load_state: get load state from the image information + */ +struct loader_ops { + int (*load_header)(const void *img_data, size_t offset, size_t len, + void **img_info, int last_state, + size_t *noffset, size_t *nlen); + int (*load_data)(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize); + int (*locate_rsc_table)(void *img_info, metal_phys_addr_t *da, + size_t *offset, size_t *size); + void (*release)(void *img_info); + metal_phys_addr_t (*get_entry)(void *img_info); + int (*get_load_state)(void *img_info); +}; + +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_LOADER_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_virtio.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_virtio.h new file mode 100644 index 0000000000..b06b951c4d --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_virtio.h @@ -0,0 +1,150 @@ +/* + * Remoteproc Virtio Framework + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef REMOTEPROC_VIRTIO_H +#define REMOTEPROC_VIRTIO_H + +#include <metal/io.h> +#include <metal/list.h> +#include <openamp/virtio.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* define vdev notification funciton user should implement */ +typedef int (*rpvdev_notify_func)(void *priv, uint32_t id); + +/** + * struct remoteproc_virtio + * @priv pointer to private data + * @notifyid notification id + * @vdev_rsc address of vdev resource + * @vdev_rsc_io metal I/O region of vdev_info, can be NULL + * @notify notification function + * @vdev virtio device + * @node list node + */ +struct remoteproc_virtio { + void *priv; + uint32_t notify_id; + void *vdev_rsc; + struct metal_io_region *vdev_rsc_io; + rpvdev_notify_func notify; + struct virtio_device vdev; + struct metal_list node; +}; + +/** + * rproc_virtio_create_vdev + * + * Create rproc virtio vdev + * + * @role: 0 - virtio master, 1 - virtio slave + * @notifyid: virtio device notification id + * @rsc: pointer to the virtio device resource + * @rsc_io: pointer to the virtio device resource I/O region + * @priv: pointer to the private data + * @notify: vdev and virtqueue notification function + * @rst_cb: reset virtio device callback + * + * return pointer to the created virtio device for success, + * NULL for failure. + */ +struct virtio_device * +rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, + void *rsc, struct metal_io_region *rsc_io, + void *priv, + rpvdev_notify_func notify, + virtio_dev_reset_cb rst_cb); + +/** + * rproc_virtio_remove_vdev + * + * Create rproc virtio vdev + * + * @vdev - pointer to the virtio device + */ +void rproc_virtio_remove_vdev(struct virtio_device *vdev); + +/** + * rproc_virtio_create_vring + * + * Create rproc virtio vring + * + * @vdev: pointer to the virtio device + * @index: vring index in the virtio device + * @notifyid: remoteproc vring notification id + * @va: vring virtual address + * @io: pointer to vring I/O region + * @num_desc: number of descriptors + * @align: vring alignment + * + * return 0 for success, negative value for failure. + */ +int rproc_virtio_init_vring(struct virtio_device *vdev, unsigned int index, + unsigned int notifyid, void *va, + struct metal_io_region *io, + unsigned int num_descs, unsigned int align); + +/** + * rproc_virtio_notified + * + * remoteproc virtio is got notified + * + * @vdev - pointer to the virtio device + * @notifyid - notify id + * + * return 0 for successful, negative value for failure + */ +int rproc_virtio_notified(struct virtio_device *vdev, uint32_t notifyid); + +/** + * rproc_virtio_wait_remote_ready + * + * Blocking function, waiting for the remote core is ready to start + * communications. + * + * @vdev - pointer to the virtio device + * + * return true when remote processor is ready. + */ +void rproc_virtio_wait_remote_ready(struct virtio_device *vdev); + +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_VIRTIO_H */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg.h new file mode 100644 index 0000000000..983dcb094e --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg.h @@ -0,0 +1,358 @@ +/* + * Remote processor messaging + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2011 Google, Inc. + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RPMSG_H_ +#define _RPMSG_H_ + +#include <openamp/compiler.h> +#include <metal/mutex.h> +#include <metal/list.h> +#include <metal/utilities.h> +#include <string.h> +#include <stdbool.h> +#include <stdint.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* Configurable parameters */ +#define RPMSG_NAME_SIZE (32) +#define RPMSG_ADDR_BMP_SIZE (128) + +#define RPMSG_NS_EPT_ADDR (0x35) +#define RPMSG_ADDR_ANY 0xFFFFFFFF + +/* Error macros. */ +#define RPMSG_SUCCESS 0 +#define RPMSG_ERROR_BASE -2000 +#define RPMSG_ERR_NO_MEM (RPMSG_ERROR_BASE - 1) +#define RPMSG_ERR_NO_BUFF (RPMSG_ERROR_BASE - 2) +#define RPMSG_ERR_PARAM (RPMSG_ERROR_BASE - 3) +#define RPMSG_ERR_DEV_STATE (RPMSG_ERROR_BASE - 4) +#define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5) +#define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) +#define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) + +struct rpmsg_endpoint; +struct rpmsg_device; + +typedef int (*rpmsg_ept_cb)(struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, void *priv); +typedef void (*rpmsg_ns_unbind_cb)(struct rpmsg_endpoint *ept); +typedef void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev, + const char *name, uint32_t dest); + +/** + * struct rpmsg_endpoint - binds a local rpmsg address to its user + * @name:name of the service supported + * @rdev: pointer to the rpmsg device + * @addr: local address of the endpoint + * @dest_addr: address of the default remote endpoint binded. + * @cb: user rx callback, return value of this callback is reserved + * for future use, for now, only allow RPMSG_SUCCESS as return value. + * @ns_unbind_cb: end point service service unbind callback, called when remote + * ept is destroyed. + * @node: end point node. + * @addr: local rpmsg address + * @priv: private data for the driver's use + * + * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as + * it binds an rpmsg address with an rx callback handler. + */ +struct rpmsg_endpoint { + char name[RPMSG_NAME_SIZE]; + struct rpmsg_device *rdev; + uint32_t addr; + uint32_t dest_addr; + rpmsg_ept_cb cb; + rpmsg_ns_unbind_cb ns_unbind_cb; + struct metal_list node; + void *priv; +}; + +/** + * struct rpmsg_device_ops - RPMsg device operations + * @send_offchannel_raw: send RPMsg data + */ +struct rpmsg_device_ops { + int (*send_offchannel_raw)(struct rpmsg_device *rdev, + uint32_t src, uint32_t dst, + const void *data, int size, int wait); +}; + +/** + * struct rpmsg_device - representation of a RPMsg device + * @endpoints: list of endpoints + * @ns_ept: name service endpoint + * @bitmap: table endpoin address allocation. + * @lock: mutex lock for rpmsg management + * @ns_bind_cb: callback handler for name service announcement without local + * endpoints waiting to bind. + * @ops: RPMsg device operations + */ +struct rpmsg_device { + struct metal_list endpoints; + struct rpmsg_endpoint ns_ept; + unsigned long bitmap[metal_bitmap_longs(RPMSG_ADDR_BMP_SIZE)]; + metal_mutex_t lock; + rpmsg_ns_bind_cb ns_bind_cb; + struct rpmsg_device_ops ops; +}; + +/** + * rpmsg_send_offchannel_raw() - send a message across to the remote processor, + * specifying source and destination address. + * @ept: the rpmsg endpoint + * @data: payload of the message + * @len: length of the payload + * + * This function sends @data of length @len to the remote @dst address from + * the source @src address. + * The message will be sent to the remote processor which the channel belongs + * to. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + uint32_t dst, const void *data, int size, + int wait); + +/** + * rpmsg_send() - send a message across to the remote processor + * @ept: the rpmsg endpoint + * @data: payload of the message + * @len: length of the payload + * + * This function sends @data of length @len based on the @ept. + * The message will be sent to the remote processor which the channel belongs + * to, using @ept's source and destination addresses. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, + int len) +{ + if (ept->dest_addr == RPMSG_ADDR_ANY) + return RPMSG_ERR_ADDR; + return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, + len, true); +} + +/** + * rpmsg_sendto() - send a message across to the remote processor, specify dst + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * @dst: destination address + * + * This function sends @data of length @len to the remote @dst address. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source address. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_sendto(struct rpmsg_endpoint *ept, const void *data, + int len, uint32_t dst) +{ + return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, true); +} + +/** + * rpmsg_send_offchannel() - send a message using explicit src/dst addresses + * @ept: the rpmsg endpoint + * @src: source address + * @dst: destination address + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len to the remote @dst address, + * and uses @src as the source address. + * The message will be sent to the remote processor which the @ept + * channel belongs to. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, + uint32_t src, uint32_t dst, + const void *data, int len) +{ + return rpmsg_send_offchannel_raw(ept, src, dst, data, len, true); +} + +/** + * rpmsg_trysend() - send a message across to the remote processor + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len on the @ept channel. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source and destination addresses. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data, + int len) +{ + if (ept->dest_addr == RPMSG_ADDR_ANY) + return RPMSG_ERR_ADDR; + return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, + len, false); +} + +/** + * rpmsg_trysendto() - send a message across to the remote processor, + * specify dst + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * @dst: destination address + * + * This function sends @data of length @len to the remote @dst address. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source address. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysendto(struct rpmsg_endpoint *ept, const void *data, + int len, uint32_t dst) +{ + return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, false); +} + +/** + * rpmsg_trysend_offchannel() - send a message using explicit src/dst addresses + * @ept: the rpmsg endpoint + * @src: source address + * @dst: destination address + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len to the remote @dst address, + * and uses @src as the source address. + * The message will be sent to the remote processor which the @ept + * channel belongs to. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, + uint32_t src, uint32_t dst, + const void *data, int len) +{ + return rpmsg_send_offchannel_raw(ept, src, dst, data, len, false); +} + +/** + * rpmsg_init_ept - initialize rpmsg endpoint + * + * Initialize an RPMsg endpoint with a name, source address, + * remoteproc address, endpoitn callback, and destroy endpoint callback. + * + * @ept: pointer to rpmsg endpoint + * @name: service name associated to the endpoint + * @src: local address of the endpoint + * @dest: target address of the endpoint + * @cb: endpoint callback + * @ns_unbind_cb: end point service unbind callback, called when remote ept is + * destroyed. + */ +static inline void rpmsg_init_ept(struct rpmsg_endpoint *ept, + const char *name, + uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, + rpmsg_ns_unbind_cb ns_unbind_cb) +{ + strncpy(ept->name, name, sizeof(ept->name)); + ept->addr = src; + ept->dest_addr = dest; + ept->cb = cb; + ept->ns_unbind_cb = ns_unbind_cb; +} + +/** + * rpmsg_create_ept - create rpmsg endpoint and register it to rpmsg device + * + * Create a RPMsg endpoint, initialize it with a name, source address, + * remoteproc address, endpoitn callback, and destroy endpoint callback, + * and register it to the RPMsg device. + * + * @ept: pointer to rpmsg endpoint + * @name: service name associated to the endpoint + * @src: local address of the endpoint + * @dest: target address of the endpoint + * @cb: endpoint callback + * @ns_unbind_cb: end point service unbind callback, called when remote ept is + * destroyed. + * + * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as + * it binds an rpmsg address with an rx callback handler. + * + * Rpmsg client should create an endpoint to discuss with remote. rpmsg client + * provide at least a channel name, a callback for message notification and by + * default endpoint source address should be set to RPMSG_ADDR_ANY. + * + * As an option Some rpmsg clients can specify an endpoint with a specific + * source address. + */ + +int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + const char *name, uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, rpmsg_ns_unbind_cb ns_unbind_cb); + +/** + * rpmsg_destroy_ept - destroy rpmsg endpoint and unregister it from rpmsg + * device + * + * @ept: pointer to the rpmsg endpoint + * + * It unregisters the rpmsg endpoint from the rpmsg device and calls the + * destroy endpoint callback if it is provided. + */ +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept); + +/** + * is_rpmsg_ept_ready - check if the rpmsg endpoint ready to send + * + * @ept: pointer to rpmsg endpoint + * + * Returns 1 if the rpmsg endpoint has both local addr and destination + * addr set, 0 otherwise + */ +static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept) +{ + return (ept->dest_addr != RPMSG_ADDR_ANY && + ept->addr != RPMSG_ADDR_ANY); +} + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_retarget.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_retarget.h new file mode 100644 index 0000000000..5645e52ed6 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_retarget.h @@ -0,0 +1,119 @@ +#ifndef RPMSG_RETARGET_H +#define RPMSG_RETARGET_H + +#include <metal/mutex.h> +#include <openamp/open_amp.h> +#include <stdint.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* File Operations System call definitions */ +#define OPEN_SYSCALL_ID 0x1UL +#define CLOSE_SYSCALL_ID 0x2UL +#define WRITE_SYSCALL_ID 0x3UL +#define READ_SYSCALL_ID 0x4UL +#define ACK_STATUS_ID 0x5UL + +#define TERM_SYSCALL_ID 0x6UL + +#define DEFAULT_PROXY_ENDPOINT 0xFFUL + +struct rpmsg_rpc_data; + +typedef int (*rpmsg_rpc_poll)(void *arg); +typedef void (*rpmsg_rpc_shutdown_cb)(struct rpmsg_rpc_data *rpc); + +struct rpmsg_rpc_syscall_header { + int32_t int_field1; + int32_t int_field2; + uint32_t data_len; +}; + +struct rpmsg_rpc_syscall { + uint32_t id; + struct rpmsg_rpc_syscall_header args; +}; + +struct rpmsg_rpc_data { + struct rpmsg_endpoint ept; + int ept_destroyed; + atomic_int nacked; + void *respbuf; + size_t respbuf_len; + rpmsg_rpc_poll poll; + void *poll_arg; + rpmsg_rpc_shutdown_cb shutdown_cb; + metal_mutex_t lock; + struct metal_spinlock buflock; +}; + +/** + * rpmsg_rpc_init - initialize RPMsg remote procedure call + * + * This function is to intialize the remote procedure call + * global data. RPMsg RPC will send request to remote and + * wait for callback. + * + * @rpc: pointer to the global remote procedure call data + * @rdev: pointer to the rpmsg device + * @ept_name: name of the endpoint used by RPC + * @ept_addr: address of the endpoint used by RPC + * @ept_raddr: remote address of the endpoint used by RPC + * @poll_arg: pointer to poll function argument + * @poll: poll function + * @shutdown_cb: shutdown callback function + * + * return 0 for success, and negative value for failure. + */ +int rpmsg_rpc_init(struct rpmsg_rpc_data *rpc, + struct rpmsg_device *rdev, + const char *ept_name, uint32_t ept_addr, + uint32_t ept_raddr, + void *poll_arg, rpmsg_rpc_poll poll, + rpmsg_rpc_shutdown_cb shutdown_cb); + +/** + * rpmsg_rpc_release - release RPMsg remote procedure call + * + * This function is to release remoteproc procedure call + * global data. + * + * @rpc: pointer to the globacl remote procedure call + */ +void rpmsg_rpc_release(struct rpmsg_rpc_data *rpc); + +/** + * rpmsg_rpc_send - Request RPMsg RPC call + * + * This function sends RPC request it will return with the length + * of data and the response buffer. + * + * @rpc: pointer to remoteproc procedure call data struct + * @req: pointer to request buffer + * @len: length of the request data + * @resp: pointer to where store the response buffer + * @resp_len: length of the response buffer + * + * return length of the received response, negative value for failure. + */ +int rpmsg_rpc_send(struct rpmsg_rpc_data *rpc, + void *req, size_t len, + void *resp, size_t resp_len); + +/** + * rpmsg_set_default_rpc - set default RPMsg RPC data + * + * The default RPC data is used to redirect standard C file operations + * to RPMsg channels. + * + * @rpc: pointer to remoteproc procedure call data struct + */ +void rpmsg_set_default_rpc(struct rpmsg_rpc_data *rpc); + +#if defined __cplusplus +} +#endif + +#endif /* RPMSG_RETARGET_H */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_virtio.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_virtio.h new file mode 100644 index 0000000000..b1369cacb4 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_virtio.h @@ -0,0 +1,190 @@ +/* + * rpmsg based on virtio + * + * Copyright (C) 2018 Linaro, Inc. + * + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RPMSG_VIRTIO_H_ +#define _RPMSG_VIRTIO_H_ + +#include <metal/io.h> +#include <metal/mutex.h> +#include <openamp/rpmsg.h> +#include <openamp/virtio.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* Configurable parameters */ +#ifndef RPMSG_BUFFER_SIZE +#define RPMSG_BUFFER_SIZE (512) +#endif + +/* The feature bitmap for virtio rpmsg */ +#define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ + +struct rpmsg_virtio_shm_pool; +/** + * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers + * @get_buffer: function to get buffer from the pool + * @base: base address of the memory pool + * @avail: available memory size + * @size: total pool size + */ +struct rpmsg_virtio_shm_pool { + void *base; + size_t avail; + size_t size; +}; + +/** + * struct rpmsg_virtio_device - representation of a rpmsg device based on virtio + * @rdev: rpmsg device, first property in the struct + * @vdev: pointer to the virtio device + * @rvq: pointer to receive virtqueue + * @svq: pointer to send virtqueue + * @shbuf_io: pointer to the shared buffer I/O region + * @shpool: pointer to the shared buffers pool + * @endpoints: list of endpoints. + */ +struct rpmsg_virtio_device { + struct rpmsg_device rdev; + struct virtio_device *vdev; + struct virtqueue *rvq; + struct virtqueue *svq; + struct metal_io_region *shbuf_io; + struct rpmsg_virtio_shm_pool *shpool; +}; + +#define RPMSG_REMOTE VIRTIO_DEV_SLAVE +#define RPMSG_MASTER VIRTIO_DEV_MASTER +static inline unsigned int + rpmsg_virtio_get_role(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->role; +} + +static inline void rpmsg_virtio_set_status(struct rpmsg_virtio_device *rvdev, + uint8_t status) +{ + rvdev->vdev->func->set_status(rvdev->vdev, status); +} + +static inline uint8_t rpmsg_virtio_get_status(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->func->get_status(rvdev->vdev); +} + +static inline uint32_t + rpmsg_virtio_get_features(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->func->get_features(rvdev->vdev); +} + +static inline int + rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, + int flags, unsigned int nvqs, + const char *names[], + vq_callback * callbacks[]) +{ + return virtio_create_virtqueues(rvdev->vdev, flags, nvqs, names, + callbacks); +} + +/** + * rpmsg_virtio_get_buffer_size - get rpmsg virtio buffer size + * + * @rdev - pointer to the rpmsg device + * + * @return - next available buffer size for text, negative value for failure + */ +int rpmsg_virtio_get_buffer_size(struct rpmsg_device *rdev); + +/** + * rpmsg_init_vdev - initialize rpmsg virtio device + * Master side: + * Initialize RPMsg virtio queues and shared buffers, the address of shm can be + * ANY. In this case, function will get shared memory from system shared memory + * pools. If the vdev has RPMsg name service feature, this API will create an + * name service endpoint. + * + * Slave side: + * This API will not return until the driver ready is set by the master side. + * + * @param rvdev - pointer to the rpmsg virtio device + * @param vdev - pointer to the virtio device + * @param ns_bind_cb - callback handler for name service announcement without + * local endpoints waiting to bind. + * @param shm_io - pointer to the share memory I/O region. + * @param shpool - pointer to shared memory pool. rpmsg_virtio_init_shm_pool has + * to be called first to fill this structure. + * + * @return - status of function execution + */ +int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + struct virtio_device *vdev, + rpmsg_ns_bind_cb ns_bind_cb, + struct metal_io_region *shm_io, + struct rpmsg_virtio_shm_pool *shpool); + +/** + * rpmsg_deinit_vdev - deinitialize rpmsg virtio device + * + * @param rvdev - pointer to the rpmsg virtio device + */ +void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev); + +/** + * rpmsg_virtio_init_shm_pool - initialize default shared buffers pool + * + * RPMsg virtio has default shared buffers pool implementation. + * The memory assigned to this pool will be dedicated to the RPMsg + * virtio. This function has to be called before calling rpmsg_init_vdev, + * to initialize the rpmsg_virtio_shm_pool structure. + * + * @param shpool - pointer to the shared buffers pool structure + * @param shbuf - pointer to the beginning of shared buffers + * @param size - shared buffers total size + */ +void rpmsg_virtio_init_shm_pool(struct rpmsg_virtio_shm_pool *shpool, + void *shbuf, size_t size); + +/** + * rpmsg_virtio_get_rpmsg_device - get RPMsg device from RPMsg virtio device + * + * @param rvdev - pointer to RPMsg virtio device + * @return - RPMsg device pointed by RPMsg virtio device + */ +static inline struct rpmsg_device * +rpmsg_virtio_get_rpmsg_device(struct rpmsg_virtio_device *rvdev) +{ + return &rvdev->rdev; +} + +/** + * rpmsg_virtio_shm_pool_get_buffer - get buffer in the shared memory pool + * + * RPMsg virtio has default shared buffers pool implementation. + * The memory assigned to this pool will be dedicated to the RPMsg + * virtio. If you prefer to have other shared buffers allocation, + * you can implement your rpmsg_virtio_shm_pool_get_buffer function. + * + * @param shpool - pointer to the shared buffers pool + * @param size - shared buffers total size + * @return - buffer pointer if free buffer is available, NULL otherwise. + */ +metal_weak void * +rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool, + size_t size); + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_VIRTIO_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rsc_table_parser.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rsc_table_parser.h new file mode 100644 index 0000000000..b0aa27e2d8 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/rsc_table_parser.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RSC_TABLE_PARSER_H +#define RSC_TABLE_PARSER_H + +#include <openamp/remoteproc.h> + +#if defined __cplusplus +extern "C" { +#endif + +#define RSC_TAB_SUPPORTED_VERSION 1 +#define RSC_TAB_HEADER_SIZE 12 +#define RSC_TAB_MAX_VRINGS 2 + +/* Standard control request handling. */ +typedef int (*rsc_handler) (struct remoteproc *rproc, void *rsc); + +/** + * handle_rsc_table + * + * This function parses resource table. + * + * @param rproc - pointer to remote remoteproc + * @param rsc_table - resource table to parse + * @param size - size of rsc table + * @param io - pointer to the resource table I/O region + * It can be NULL if the resource table + * is in the local memory. + * + * @returns - execution status + * + */ +int handle_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, int len, + struct metal_io_region *io); +int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc); +int handle_trace_rsc(struct remoteproc *rproc, void *rsc); +int handle_vdev_rsc(struct remoteproc *rproc, void *rsc); +int handle_vendor_rsc(struct remoteproc *rproc, void *rsc); + +/** + * find_rsc + * + * find out location of a resource type in the resource table. + * + * @rsc_table - pointer to the resource table + * @rsc_type - type of the resource + * @index - index of the resource of the specified type + * + * return the offset to the resource on success, or 0 on failure + */ +size_t find_rsc(void *rsc_table, unsigned int rsc_type, unsigned int index); + +#if defined __cplusplus +} +#endif + +#endif /* RSC_TABLE_PARSER_H */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio.h new file mode 100644 index 0000000000..463079bf37 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio.h @@ -0,0 +1,176 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef _VIRTIO_H_ +#define _VIRTIO_H_ + +#include <openamp/virtqueue.h> +#include <metal/spinlock.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* TODO: define this as compiler flags */ +#ifndef VIRTIO_MAX_NUM_VRINGS +#define VIRTIO_MAX_NUM_VRINGS 2 +#endif + +/* VirtIO device IDs. */ +#define VIRTIO_ID_NETWORK 0x01UL +#define VIRTIO_ID_BLOCK 0x02UL +#define VIRTIO_ID_CONSOLE 0x03UL +#define VIRTIO_ID_ENTROPY 0x04UL +#define VIRTIO_ID_BALLOON 0x05UL +#define VIRTIO_ID_IOMEMORY 0x06UL +#define VIRTIO_ID_RPMSG 0x07UL /* remote processor messaging */ +#define VIRTIO_ID_SCSI 0x08UL +#define VIRTIO_ID_9P 0x09UL +#define VIRTIO_DEV_ANY_ID (-1)UL + +/* Status byte for guest to report progress. */ +#define VIRTIO_CONFIG_STATUS_ACK 0x01 +#define VIRTIO_CONFIG_STATUS_DRIVER 0x02 +#define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04 +#define VIRTIO_CONFIG_STATUS_NEEDS_RESET 0x40 +#define VIRTIO_CONFIG_STATUS_FAILED 0x80 + +/* Virtio device role */ +#define VIRTIO_DEV_MASTER 0UL +#define VIRTIO_DEV_SLAVE 1UL + +struct virtio_device_id { + uint32_t device; + uint32_t vendor; +}; + +/* + * Generate interrupt when the virtqueue ring is + * completely used, even if we've suppressed them. + */ +#define VIRTIO_F_NOTIFY_ON_EMPTY (1 << 24) + +/* + * The guest should never negotiate this feature; it + * is used to detect faulty drivers. + */ +#define VIRTIO_F_BAD_FEATURE (1 << 30) + +/* + * Some VirtIO feature bits (currently bits 28 through 31) are + * reserved for the transport being used (eg. virtio_ring), the + * rest are per-device feature bits. + */ +#define VIRTIO_TRANSPORT_F_START 28 +#define VIRTIO_TRANSPORT_F_END 32 + +typedef void (*virtio_dev_reset_cb)(struct virtio_device *vdev); + +struct virtio_dispatch; + +struct virtio_feature_desc { + uint32_t vfd_val; + const char *vfd_str; +}; + +/** + * struct proc_shm + * + * This structure is maintained by hardware interface layer for + * shared memory information. The shared memory provides buffers + * for use by the vring to exchange messages between the cores. + * + */ +struct virtio_buffer_info { + /* Start address of shared memory used for buffers. */ + void *vaddr; + /* Start physical address of shared memory used for buffers. */ + metal_phys_addr_t paddr; + /* sharmed memory I/O region */ + struct metal_io_region *io; + /* Size of shared memory. */ + unsigned long size; +}; + +/** + * struct remoteproc_vring - remoteproc vring structure + * @vq virtio queue + * @va logical address + * @notifyid vring notify id + * @num_descs number of descriptors + * @align vring alignment + * @io metal I/O region of the vring memory, can be NULL + */ +struct virtio_vring_info { + struct virtqueue *vq; + struct vring_alloc_info info; + uint32_t notifyid; + struct metal_io_region *io; +}; + +/* + * Structure definition for virtio devices for use by the + * applications/drivers + */ + +struct virtio_device { + uint32_t index; /**< unique position on the virtio bus */ + struct virtio_device_id id; /**< the device type identification + * (used to match it with a driver + */ + uint64_t features; /**< the features supported by both ends. */ + unsigned int role; /**< if it is virtio backend or front end. */ + virtio_dev_reset_cb reset_cb; /**< user registered device callback */ + const struct virtio_dispatch *func; /**< Virtio dispatch table */ + void *priv; /**< TODO: remove pointer to virtio_device private data */ + unsigned int vrings_num; /**< number of vrings */ + struct virtio_vring_info *vrings_info; +}; + +/* + * Helper functions. + */ +const char *virtio_dev_name(uint16_t devid); +void virtio_describe(struct virtio_device *dev, const char *msg, + uint32_t features, + struct virtio_feature_desc *feature_desc); + +/* + * Functions for virtio device configuration as defined in Rusty Russell's + * paper. + * Drivers are expected to implement these functions in their respective codes. + */ + +struct virtio_dispatch { + uint8_t (*get_status)(struct virtio_device *dev); + void (*set_status)(struct virtio_device *dev, uint8_t status); + uint32_t (*get_features)(struct virtio_device *dev); + void (*set_features)(struct virtio_device *dev, uint32_t feature); + uint32_t (*negotiate_features)(struct virtio_device *dev, + uint32_t features); + + /* + * Read/write a variable amount from the device specific (ie, network) + * configuration region. This region is encoded in the same endian as + * the guest. + */ + void (*read_config)(struct virtio_device *dev, uint32_t offset, + void *dst, int length); + void (*write_config)(struct virtio_device *dev, uint32_t offset, + void *src, int length); + void (*reset_device)(struct virtio_device *dev); + void (*notify)(struct virtqueue *vq); +}; + +int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, + unsigned int nvqs, const char *names[], + vq_callback *callbacks[]); + +#if defined __cplusplus +} +#endif + +#endif /* _VIRTIO_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio_ring.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio_ring.h new file mode 100644 index 0000000000..14e7b6b571 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio_ring.h @@ -0,0 +1,152 @@ +/* + * Copyright Rusty Russell IBM Corporation 2007. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef VIRTIO_RING_H +#define VIRTIO_RING_H + +#if defined __cplusplus +extern "C" { +#endif + +/* This marks a buffer as continuing via the next field. */ +#define VRING_DESC_F_NEXT 1 +/* This marks a buffer as write-only (otherwise read-only). */ +#define VRING_DESC_F_WRITE 2 +/* This means the buffer contains a list of buffer descriptors. */ +#define VRING_DESC_F_INDIRECT 4 + +/* The Host uses this in used->flags to advise the Guest: don't kick me + * when you add a buffer. It's unreliable, so it's simply an + * optimization. Guest will still kick if it's out of buffers. + */ +#define VRING_USED_F_NO_NOTIFY 1 +/* The Guest uses this in avail->flags to advise the Host: don't + * interrupt me when you consume a buffer. It's unreliable, so it's + * simply an optimization. + */ +#define VRING_AVAIL_F_NO_INTERRUPT 1 + +/* VirtIO ring descriptors: 16 bytes. + * These can chain together via "next". + */ +struct vring_desc { + /* Address (guest-physical). */ + uint64_t addr; + /* Length. */ + uint32_t len; + /* The flags as indicated above. */ + uint16_t flags; + /* We chain unused descriptors via this, too. */ + uint16_t next; +}; + +struct vring_avail { + uint16_t flags; + uint16_t idx; + uint16_t ring[0]; +}; + +/* uint32_t is used here for ids for padding reasons. */ +struct vring_used_elem { + /* Index of start of used descriptor chain. */ + uint32_t id; + /* Total length of the descriptor chain which was written to. */ + uint32_t len; +}; + +struct vring_used { + uint16_t flags; + uint16_t idx; + struct vring_used_elem ring[0]; +}; + +struct vring { + unsigned int num; + + struct vring_desc *desc; + struct vring_avail *avail; + struct vring_used *used; +}; + +/* The standard layout for the ring is a continuous chunk of memory which + * looks like this. We assume num is a power of 2. + * + * struct vring { + * // The actual descriptors (16 bytes each) + * struct vring_desc desc[num]; + * + * // A ring of available descriptor heads with free-running index. + * __u16 avail_flags; + * __u16 avail_idx; + * __u16 available[num]; + * __u16 used_event_idx; + * + * // Padding to the next align boundary. + * char pad[]; + * + * // A ring of used descriptor heads with free-running index. + * __u16 used_flags; + * __u16 used_idx; + * struct vring_used_elem used[num]; + * __u16 avail_event_idx; + * }; + * + * NOTE: for VirtIO PCI, align is 4096. + */ + +/* + * We publish the used event index at the end of the available ring, and vice + * versa. They are at the end for backwards compatibility. + */ +#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) +#define vring_avail_event(vr) ((vr)->used->ring[(vr)->num].id & 0xFFFF) + +static inline int vring_size(unsigned int num, unsigned long align) +{ + int size; + + size = num * sizeof(struct vring_desc); + size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)) + + sizeof(uint16_t); + size = (size + align - 1) & ~(align - 1); + size += sizeof(struct vring_used) + + (num * sizeof(struct vring_used_elem)) + sizeof(uint16_t); + + return size; +} + +static inline void +vring_init(struct vring *vr, unsigned int num, uint8_t *p, unsigned long align) +{ + vr->num = num; + vr->desc = (struct vring_desc *)p; + vr->avail = (struct vring_avail *)(p + num * sizeof(struct vring_desc)); + vr->used = (struct vring_used *) + (((unsigned long)&vr->avail->ring[num] + sizeof(uint16_t) + + align - 1) & ~(align - 1)); +} + +/* + * The following is used with VIRTIO_RING_F_EVENT_IDX. + * + * Assuming a given event_idx value from the other size, if we have + * just incremented index from old to new_idx, should we trigger an + * event? + */ +static inline int +vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) +{ + return (uint16_t)(new_idx - event_idx - 1) < + (uint16_t)(new_idx - old); +} + +#if defined __cplusplus +} +#endif + +#endif /* VIRTIO_RING_H */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtqueue.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtqueue.h new file mode 100644 index 0000000000..ad24749062 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/include/openamp/virtqueue.h @@ -0,0 +1,236 @@ +#ifndef VIRTQUEUE_H_ +#define VIRTQUEUE_H_ + +/*- + * Copyright (c) 2011, Bryan Venteicher <[email protected]> + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + * + * $FreeBSD$ + */ + +#include <stdbool.h> +#include <stdint.h> + +#if defined __cplusplus +extern "C" { +#endif + +typedef uint8_t boolean; + +#include <openamp/virtio_ring.h> +#include <metal/alloc.h> +#include <metal/io.h> + +/*Error Codes*/ +#define VQ_ERROR_BASE -3000 +#define ERROR_VRING_FULL (VQ_ERROR_BASE - 1) +#define ERROR_INVLD_DESC_IDX (VQ_ERROR_BASE - 2) +#define ERROR_EMPTY_RING (VQ_ERROR_BASE - 3) +#define ERROR_NO_MEM (VQ_ERROR_BASE - 4) +#define ERROR_VRING_MAX_DESC (VQ_ERROR_BASE - 5) +#define ERROR_VRING_ALIGN (VQ_ERROR_BASE - 6) +#define ERROR_VRING_NO_BUFF (VQ_ERROR_BASE - 7) +#define ERROR_VQUEUE_INVLD_PARAM (VQ_ERROR_BASE - 8) + +#define VQUEUE_SUCCESS 0 + +/* The maximum virtqueue size is 2^15. Use that value as the end of + * descriptor chain terminator since it will never be a valid index + * in the descriptor table. This is used to verify we are correctly + * handling vq_free_cnt. + */ +#define VQ_RING_DESC_CHAIN_END 32768 +#define VIRTQUEUE_FLAG_INDIRECT 0x0001 +#define VIRTQUEUE_FLAG_EVENT_IDX 0x0002 +#define VIRTQUEUE_MAX_NAME_SZ 32 + +/* Support for indirect buffer descriptors. */ +#define VIRTIO_RING_F_INDIRECT_DESC (1 << 28) + +/* Support to suppress interrupt until specific index is reached. */ +#define VIRTIO_RING_F_EVENT_IDX (1 << 29) + +struct virtqueue_buf { + void *buf; + int len; +}; + +struct virtqueue { + struct virtio_device *vq_dev; + const char *vq_name; + uint16_t vq_queue_index; + uint16_t vq_nentries; + uint32_t vq_flags; + void (*callback)(struct virtqueue *vq); + void (*notify)(struct virtqueue *vq); + struct vring vq_ring; + uint16_t vq_free_cnt; + uint16_t vq_queued_cnt; + void *shm_io; /* opaque pointer to data needed to allow v2p & p2v */ + + /* + * Head of the free chain in the descriptor table. If + * there are no free descriptors, this will be set to + * VQ_RING_DESC_CHAIN_END. + */ + uint16_t vq_desc_head_idx; + + /* + * Last consumed descriptor in the used table, + * trails vq_ring.used->idx. + */ + uint16_t vq_used_cons_idx; + + /* + * Last consumed descriptor in the available table - + * used by the consumer side. + */ + uint16_t vq_available_idx; + +#ifdef VQUEUE_DEBUG + boolean vq_inuse; +#endif + + /* + * Used by the host side during callback. Cookie + * holds the address of buffer received from other side. + * Other fields in this structure are not used currently. + */ + + struct vq_desc_extra { + void *cookie; + uint16_t ndescs; + } vq_descx[0]; +}; + +/* struct to hold vring specific information */ +struct vring_alloc_info { + void *vaddr; + uint32_t align; + uint16_t num_descs; + uint16_t pad; +}; + +typedef void vq_callback(struct virtqueue *); +typedef void vq_notify(struct virtqueue *); + +#ifdef VQUEUE_DEBUG +#include <metal/log.h> +#include <metal/assert.h> + +#define VQASSERT(_vq, _exp, _msg) \ + do { \ + if (!(_exp)) { \ + metal_log(METAL_LOG_EMERGENCY, \ + "%s: %s - _msg", __func__, (_vq)->vq_name); \ + metal_assert(_exp); \ + } \ + } while (0) + +#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) \ + VQASSERT((_vq), (_idx) < (_vq)->vq_nentries, "invalid ring index") + +#define VQ_RING_ASSERT_CHAIN_TERM(_vq) \ + VQASSERT((_vq), (_vq)->vq_desc_head_idx == \ + VQ_RING_DESC_CHAIN_END, \ + "full ring terminated incorrectly: invalid head") + +#define VQ_PARAM_CHK(condition, status_var, status_err) \ + do { \ + if (((status_var) == 0) && (condition)) { \ + status_var = status_err; \ + } \ + } while (0) + +#define VQUEUE_BUSY(vq) \ + do { \ + if (!(vq)->vq_inuse) \ + (vq)->vq_inuse = true; \ + else \ + VQASSERT(vq, !(vq)->vq_inuse,\ + "VirtQueue already in use") \ + } while (0) + +#define VQUEUE_IDLE(vq) ((vq)->vq_inuse = false) + +#else + +#define KASSERT(cond, str) +#define VQASSERT(_vq, _exp, _msg) +#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) +#define VQ_RING_ASSERT_CHAIN_TERM(_vq) +#define VQ_PARAM_CHK(condition, status_var, status_err) +#define VQUEUE_BUSY(vq) +#define VQUEUE_IDLE(vq) + +#endif + +int virtqueue_create(struct virtio_device *device, unsigned short id, + const char *name, struct vring_alloc_info *ring, + void (*callback)(struct virtqueue *vq), + void (*notify)(struct virtqueue *vq), + struct virtqueue *v_queue); + +/* + * virtqueue_set_shmem_io + * + * set virtqueue shared memory I/O region + * + * @vq - virt queue + * @io - pointer to the shared memory I/O region + */ +static inline void virtqueue_set_shmem_io(struct virtqueue *vq, + struct metal_io_region *io) +{ + vq->shm_io = io; +} + +int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list, + int readable, int writable, void *cookie); + +void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx); + +void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, + uint32_t *len); + +int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, + uint32_t len); + +void virtqueue_disable_cb(struct virtqueue *vq); + +int virtqueue_enable_cb(struct virtqueue *vq); + +void virtqueue_kick(struct virtqueue *vq); + +static inline struct virtqueue *virtqueue_allocate(unsigned int num_desc_extra) +{ + struct virtqueue *vqs; + uint32_t vq_size = sizeof(struct virtqueue) + + num_desc_extra * sizeof(struct vq_desc_extra); + + vqs = (struct virtqueue *)metal_allocate_memory(vq_size); + + if (vqs) { + memset(vqs, 0x00, vq_size); + } + + return vqs; +} + +void virtqueue_free(struct virtqueue *vq); + +void virtqueue_dump(struct virtqueue *vq); + +void virtqueue_notification(struct virtqueue *vq); + +uint32_t virtqueue_get_desc_size(struct virtqueue *vq); + +uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx); + +#if defined __cplusplus +} +#endif + +#endif /* VIRTQUEUE_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/elf_loader.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/elf_loader.c new file mode 100644 index 0000000000..e15a7843bb --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/elf_loader.c @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> +#include <metal/alloc.h> +#include <metal/log.h> +#include <openamp/elf_loader.h> +#include <openamp/remoteproc.h> + +static int elf_is_64(const void *elf_info) +{ + const unsigned char *tmp = elf_info; + + if (tmp[EI_CLASS] == ELFCLASS64) + return 1; + else + return 0; +} + +static size_t elf_ehdr_size(const void *elf_info) +{ + if (elf_info == NULL) + return sizeof(Elf64_Ehdr); + else if (elf_is_64(elf_info) != 0) + return sizeof(Elf64_Ehdr); + else + return sizeof(Elf32_Ehdr); +} + +static size_t elf_phoff(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phoff; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phoff; + } +} + +static size_t elf_phentsize(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phentsize; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phentsize; + } +} + +static int elf_phnum(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phnum; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phnum; + } +} + +static size_t elf_shoff(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shoff; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shoff; + } +} + +static size_t elf_shentsize(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shentsize; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shentsize; + } +} + +static int elf_shnum(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shnum; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shnum; + } +} + +static int elf_shstrndx(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shstrndx; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shstrndx; + } +} + +static void *elf_phtable_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return (void *)&einfo->phdrs; + } else { + struct elf64_info *einfo = elf_info; + + return (void *)&einfo->phdrs; + } +} + +static void *elf_shtable_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return (void *)(&einfo->shdrs); + } else { + struct elf64_info *einfo = elf_info; + + return (void *)(&einfo->shdrs); + } +} + +static void **elf_shstrtab_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return &einfo->shstrtab; + } else { + struct elf64_info *einfo = elf_info; + + return &einfo->shstrtab; + } +} + +static unsigned int *elf_load_state(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return &einfo->load_state; + } else { + struct elf64_info *einfo = elf_info; + + return &einfo->load_state; + } +} + +static void elf_parse_segment(void *elf_info, const void *elf_phdr, + unsigned int *p_type, size_t *p_offset, + metal_phys_addr_t *p_vaddr, + metal_phys_addr_t *p_paddr, + size_t *p_filesz, size_t *p_memsz) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Phdr *phdr = elf_phdr; + + if (p_type != NULL) + *p_type = (unsigned int)phdr->p_type; + if (p_offset != NULL) + *p_offset = (size_t)phdr->p_offset; + if (p_vaddr != NULL) + *p_vaddr = (metal_phys_addr_t)phdr->p_vaddr; + if (p_paddr != NULL) + *p_paddr = (metal_phys_addr_t)phdr->p_paddr; + if (p_filesz != NULL) + *p_filesz = (size_t)phdr->p_filesz; + if (p_memsz != NULL) + *p_memsz = (size_t)phdr->p_memsz; + } else { + const Elf64_Phdr *phdr = elf_phdr; + + if (p_type != NULL) + *p_type = (unsigned int)phdr->p_type; + if (p_offset != NULL) + *p_offset = (size_t)phdr->p_offset; + if (p_vaddr != NULL) + if (p_vaddr != NULL) + *p_vaddr = (metal_phys_addr_t)phdr->p_vaddr; + if (p_paddr != NULL) + *p_paddr = (metal_phys_addr_t)phdr->p_paddr; + if (p_filesz != NULL) + *p_filesz = (size_t)phdr->p_filesz; + if (p_memsz != NULL) + *p_memsz = (size_t)phdr->p_memsz; + } +} + +static const void *elf_get_segment_from_index(void *elf_info, int index) +{ + if (elf_is_64(elf_info) == 0) { + const struct elf32_info *einfo = elf_info; + const Elf32_Ehdr *ehdr = &einfo->ehdr; + const Elf32_Phdr *phdrs = einfo->phdrs; + + if (phdrs == NULL) + return NULL; + if (index < 0 || index > ehdr->e_phnum) + return NULL; + return &phdrs[index]; + } else { + const struct elf64_info *einfo = elf_info; + const Elf64_Ehdr *ehdr = &einfo->ehdr; + const Elf64_Phdr *phdrs = einfo->phdrs; + + if (phdrs == NULL) + return NULL; + if (index < 0 || index > ehdr->e_phnum) + return NULL; + return &phdrs[index]; + } +} + +static void *elf_get_section_from_name(void *elf_info, const char *name) +{ + unsigned int i; + const char *name_table; + + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + Elf32_Ehdr *ehdr = &einfo->ehdr; + Elf32_Shdr *shdr = einfo->shdrs; + + name_table = einfo->shstrtab; + if (shdr == NULL || name_table == NULL) + return NULL; + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + if (strcmp(name, name_table + shdr->sh_name)) + continue; + else + return shdr; + } + } else { + struct elf64_info *einfo = elf_info; + Elf64_Ehdr *ehdr = &einfo->ehdr; + Elf64_Shdr *shdr = einfo->shdrs; + + name_table = einfo->shstrtab; + if (shdr == NULL || name_table == NULL) + return NULL; + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + if (strcmp(name, name_table + shdr->sh_name)) + continue; + else + return shdr; + } + } + return NULL; +} + +static void *elf_get_section_from_index(void *elf_info, int index) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + Elf32_Ehdr *ehdr = &einfo->ehdr; + Elf32_Shdr *shdr = einfo->shdrs; + + if (shdr == NULL) + return NULL; + if (index > ehdr->e_shnum) + return NULL; + return &einfo->shdrs[index]; + } else { + struct elf64_info *einfo = elf_info; + Elf64_Ehdr *ehdr = &einfo->ehdr; + Elf64_Shdr *shdr = einfo->shdrs; + + if (shdr == NULL) + return NULL; + if (index > ehdr->e_shnum) + return NULL; + return &einfo->shdrs[index]; + } +} + +static void elf_parse_section(void *elf_info, void *elf_shdr, + unsigned int *sh_type, unsigned int *sh_flags, + metal_phys_addr_t *sh_addr, + size_t *sh_offset, size_t *sh_size, + unsigned int *sh_link, unsigned int *sh_info, + unsigned int *sh_addralign, + size_t *sh_entsize) +{ + if (elf_is_64(elf_info) == 0) { + Elf32_Shdr *shdr = elf_shdr; + + if (sh_type != NULL) + *sh_type = shdr->sh_type; + if (sh_flags != NULL) + *sh_flags = shdr->sh_flags; + if (sh_addr != NULL) + *sh_addr = (metal_phys_addr_t)shdr->sh_addr; + if (sh_offset != NULL) + *sh_offset = shdr->sh_offset; + if (sh_size != NULL) + *sh_size = shdr->sh_size; + if (sh_link != NULL) + *sh_link = shdr->sh_link; + if (sh_info != NULL) + *sh_info = shdr->sh_info; + if (sh_addralign != NULL) + *sh_addralign = shdr->sh_addralign; + if (sh_entsize != NULL) + *sh_entsize = shdr->sh_entsize; + } else { + Elf64_Shdr *shdr = elf_shdr; + + if (sh_type != NULL) + *sh_type = shdr->sh_type; + if (sh_flags != NULL) + *sh_flags = shdr->sh_flags; + if (sh_addr != NULL) + *sh_addr = (metal_phys_addr_t)(shdr->sh_addr & + (metal_phys_addr_t)(-1)); + if (sh_offset != NULL) + *sh_offset = shdr->sh_offset; + if (sh_size != NULL) + *sh_size = shdr->sh_size; + if (sh_link != NULL) + *sh_link = shdr->sh_link; + if (sh_info != NULL) + *sh_info = shdr->sh_info; + if (sh_addralign != NULL) + *sh_addralign = shdr->sh_addralign; + if (sh_entsize != NULL) + *sh_entsize = shdr->sh_entsize; + } +} + +static const void *elf_next_load_segment(void *elf_info, int *nseg, + metal_phys_addr_t *da, + size_t *noffset, size_t *nfsize, + size_t *nmsize) +{ + const void *phdr; + unsigned int p_type = PT_NULL; + + if (elf_info == NULL || nseg == NULL) + return NULL; + while(p_type != PT_LOAD) { + phdr = elf_get_segment_from_index(elf_info, *nseg); + if (phdr == NULL) + return NULL; + elf_parse_segment(elf_info, phdr, &p_type, noffset, + da, NULL, nfsize, nmsize); + *nseg = *nseg + 1; + } + return phdr; +} + +static size_t elf_info_size(const void *img_data) +{ + if (elf_is_64(img_data) == 0) + return sizeof(struct elf32_info); + else + return sizeof(struct elf64_info); +} + +int elf_identify(const void *img_data, size_t len) +{ + if (len < SELFMAG || img_data == NULL) + return -RPROC_EINVAL; + if (memcmp(img_data, ELFMAG, SELFMAG) != 0) + return -RPROC_EINVAL; + else + return 0; +} + +int elf_load_header(const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + size_t *noffset, size_t *nlen) +{ + unsigned int *load_state; + + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + /* Get ELF header */ + if (last_load_state == ELF_STATE_INIT) { + size_t tmpsize; + + metal_log(METAL_LOG_DEBUG, "Loading ELF headering\r\n"); + tmpsize = elf_ehdr_size(img_data); + if (len < tmpsize) { + *noffset = 0; + *nlen = tmpsize; + return ELF_STATE_INIT; + } else { + size_t infosize = elf_info_size(img_data); + + if (*img_info == NULL) { + *img_info = metal_allocate_memory(infosize); + if (*img_info == NULL) + return -ENOMEM; + memset(*img_info, 0, infosize); + } + memcpy(*img_info, img_data, tmpsize); + load_state = elf_load_state(*img_info); + *load_state = ELF_STATE_WAIT_FOR_PHDRS; + last_load_state = ELF_STATE_WAIT_FOR_PHDRS; + } + } + metal_assert(*img_info != NULL); + load_state = elf_load_state(*img_info); + if (last_load_state != (int)*load_state) + return -RPROC_EINVAL; + /* Get ELF program headers */ + if (*load_state == ELF_STATE_WAIT_FOR_PHDRS) { + size_t phdrs_size; + size_t phdrs_offset; + char **phdrs; + const void *img_phdrs; + + metal_log(METAL_LOG_DEBUG, "Loading ELF program header.\r\n"); + phdrs_offset = elf_phoff(*img_info); + phdrs_size = elf_phnum(*img_info) * elf_phentsize(*img_info); + if (offset > phdrs_offset || + offset + len < phdrs_offset + phdrs_size) { + *noffset = phdrs_offset; + *nlen = phdrs_size; + return (int)*load_state; + } + /* caculate the programs headers offset to the image_data */ + phdrs_offset -= offset; + img_phdrs = (const void *) + ((const char *)img_data + phdrs_offset); + phdrs = (char **)elf_phtable_ptr(*img_info); + (*phdrs) = metal_allocate_memory(phdrs_size); + if (*phdrs == NULL) + return -ENOMEM; + memcpy((void *)(*phdrs), img_phdrs, phdrs_size); + *load_state = ELF_STATE_WAIT_FOR_SHDRS | + RPROC_LOADER_READY_TO_LOAD; + } + /* Get ELF Section Headers */ + if ((*load_state & ELF_STATE_WAIT_FOR_SHDRS) != 0) { + size_t shdrs_size; + size_t shdrs_offset; + char **shdrs; + const void *img_shdrs; + + metal_log(METAL_LOG_DEBUG, "Loading ELF section header.\r\n"); + shdrs_offset = elf_shoff(*img_info); + if (elf_shnum(*img_info) == 0) { + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_HDRS_COMPLETE; + *nlen = 0; + return (int)*load_state; + } + shdrs_size = elf_shnum(*img_info) * elf_shentsize(*img_info); + if (offset > shdrs_offset || + offset + len < shdrs_offset + shdrs_size) { + *noffset = shdrs_offset; + *nlen = shdrs_size; + return (int)*load_state; + } + /* caculate the sections headers offset to the image_data */ + shdrs_offset -= offset; + img_shdrs = (const void *) + ((const char *)img_data + shdrs_offset); + shdrs = (char **)elf_shtable_ptr(*img_info); + (*shdrs) = metal_allocate_memory(shdrs_size); + if (*shdrs == NULL) + return -ENOMEM; + memcpy((void *)*shdrs, img_shdrs, shdrs_size); + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_WAIT_FOR_SHSTRTAB; + metal_log(METAL_LOG_DEBUG, + "Loading ELF section header complete.\r\n"); + } + /* Get ELF SHSTRTAB section */ + if ((*load_state & ELF_STATE_WAIT_FOR_SHSTRTAB) != 0) { + size_t shstrtab_size; + size_t shstrtab_offset; + int shstrndx; + void *shdr; + void **shstrtab; + + metal_log(METAL_LOG_DEBUG, "Loading ELF shstrtab.\r\n"); + shstrndx = elf_shstrndx(*img_info); + shdr = elf_get_section_from_index(*img_info, shstrndx); + if (shdr == NULL) + return -RPROC_EINVAL; + elf_parse_section(*img_info, shdr, NULL, NULL, + NULL, &shstrtab_offset, + &shstrtab_size, NULL, NULL, + NULL, NULL); + if (offset > shstrtab_offset || + offset + len < shstrtab_offset + shstrtab_size) { + *noffset = shstrtab_offset; + *nlen = shstrtab_size; + return (int)*load_state; + } + /* Caculate shstrtab section offset to the input image data */ + shstrtab_offset -= offset; + shstrtab = elf_shstrtab_ptr(*img_info); + *shstrtab = metal_allocate_memory(shstrtab_size); + if (*shstrtab == NULL) + return -ENOMEM; + memcpy(*shstrtab, + (const void *)((const char *)img_data + shstrtab_offset), + shstrtab_size); + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_HDRS_COMPLETE; + *nlen = 0; + return *load_state; + } + return last_load_state; +} + +int elf_load(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize) +{ + unsigned int *load_state; + const void *phdr; + + (void)rproc; + metal_assert(da != NULL); + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + if ((last_load_state & RPROC_LOADER_MASK) == RPROC_LOADER_NOT_READY) { + metal_log(METAL_LOG_DEBUG, + "%s, needs to load header first\r\n"); + last_load_state = elf_load_header(img_data, offset, len, + img_info, last_load_state, + noffset, nlen); + if ((last_load_state & RPROC_LOADER_MASK) == + RPROC_LOADER_NOT_READY) { + *da = RPROC_LOAD_ANYADDR; + return last_load_state; + } + } + metal_assert(img_info != NULL && *img_info != NULL); + load_state = elf_load_state(*img_info); + /* For ELF, segment padding value is 0 */ + if (padding != NULL) + *padding = 0; + if ((*load_state & RPROC_LOADER_READY_TO_LOAD) != 0) { + int nsegment; + size_t nsegmsize = 0; + size_t nsize = 0; + int phnums = 0; + + nsegment = (int)(*load_state & ELF_NEXT_SEGMENT_MASK); + phdr = elf_next_load_segment(*img_info, &nsegment, da, + noffset, &nsize, &nsegmsize); + if (phdr == NULL) { + metal_log(METAL_LOG_DEBUG, "cannot find more segement\r\n"); + *load_state = (*load_state & (~ELF_NEXT_SEGMENT_MASK)) | + (unsigned int)(nsegment & ELF_NEXT_SEGMENT_MASK); + return *load_state; + } + *nlen = nsize; + *nmemsize = nsegmsize; + phnums = elf_phnum(*img_info); + metal_log(METAL_LOG_DEBUG, "segment: %d, total segs %d\r\n", + nsegment, phnums); + if (nsegment == elf_phnum(*img_info)) { + *load_state = (*load_state & (~RPROC_LOADER_MASK)) | + RPROC_LOADER_POST_DATA_LOAD; + } + *load_state = (*load_state & (~ELF_NEXT_SEGMENT_MASK)) | + (unsigned int)(nsegment & ELF_NEXT_SEGMENT_MASK); + } else if ((*load_state & RPROC_LOADER_POST_DATA_LOAD) != 0) { + if ((*load_state & ELF_STATE_HDRS_COMPLETE) == 0) { + last_load_state = elf_load_header(img_data, offset, + len, img_info, + last_load_state, + noffset, nlen); + if (last_load_state < 0) + return last_load_state; + if ((last_load_state & ELF_STATE_HDRS_COMPLETE) != 0) { + *load_state = (*load_state & + (~RPROC_LOADER_MASK)) | + RPROC_LOADER_LOAD_COMPLETE; + *nlen = 0; + } + *da = RPROC_LOAD_ANYADDR; + } else { + /* TODO: will handle relocate later */ + *nlen = 0; + *load_state = (*load_state & + (~RPROC_LOADER_MASK)) | + RPROC_LOADER_LOAD_COMPLETE; + } + } + return *load_state; +} + +void elf_release(void *img_info) +{ + if (img_info == NULL) + return; + if (elf_is_64(img_info) == 0) { + struct elf32_info *elf_info = img_info; + + if (elf_info->phdrs != NULL) + metal_free_memory(elf_info->phdrs); + if (elf_info->shdrs != NULL) + metal_free_memory(elf_info->shdrs); + if (elf_info->shstrtab != NULL) + metal_free_memory(elf_info->shstrtab); + metal_free_memory(img_info); + + } else { + struct elf64_info *elf_info = img_info; + + if (elf_info->phdrs != NULL) + metal_free_memory(elf_info->phdrs); + if (elf_info->shdrs != NULL) + metal_free_memory(elf_info->shdrs); + if (elf_info->shstrtab != NULL) + metal_free_memory(elf_info->shstrtab); + metal_free_memory(img_info); + } +} + +metal_phys_addr_t elf_get_entry(void *elf_info) +{ + if (!elf_info) + return METAL_BAD_PHYS; + + if (elf_is_64(elf_info) == 0) { + Elf32_Ehdr *elf_ehdr = (Elf32_Ehdr *)elf_info; + Elf32_Addr e_entry; + + e_entry = elf_ehdr->e_entry; + return (metal_phys_addr_t)e_entry; + } else { + Elf64_Ehdr *elf_ehdr = (Elf64_Ehdr *)elf_info; + Elf64_Addr e_entry; + + e_entry = elf_ehdr->e_entry; + return (metal_phys_addr_t)(e_entry & (metal_phys_addr_t)(-1)); + } +} + +int elf_locate_rsc_table(void *elf_info, metal_phys_addr_t *da, + size_t *offset, size_t *size) +{ + char *sect_name = ".resource_table"; + void *shdr; + unsigned int *load_state; + + if (elf_info == NULL) + return -RPROC_EINVAL; + + load_state = elf_load_state(elf_info); + if ((*load_state & ELF_STATE_HDRS_COMPLETE) == 0) + return -RPROC_ERR_LOADER_STATE; + shdr = elf_get_section_from_name(elf_info, sect_name); + if (shdr == NULL) { + metal_assert(size != NULL); + *size = 0; + return 0; + } + elf_parse_section(elf_info, shdr, NULL, NULL, + da, offset, size, + NULL, NULL, NULL, NULL); + return 0; +} + +int elf_get_load_state(void *img_info) +{ + unsigned int *load_state; + + if (img_info == NULL) + return -RPROC_EINVAL; + load_state = elf_load_state(img_info); + return (int)(*load_state); +} + +struct loader_ops elf_ops = { + .load_header = elf_load_header, + .load_data = elf_load, + .locate_rsc_table = elf_locate_rsc_table, + .release = elf_release, + .get_entry = elf_get_entry, + .get_load_state = elf_get_load_state, +}; diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc.c new file mode 100644 index 0000000000..be9b869362 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc.c @@ -0,0 +1,963 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2015 Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/alloc.h> +#include <metal/log.h> +#include <metal/utilities.h> +#include <openamp/elf_loader.h> +#include <openamp/remoteproc.h> +#include <openamp/remoteproc_loader.h> +#include <openamp/remoteproc_virtio.h> +#include <openamp/rsc_table_parser.h> + +/****************************************************************************** + * static functions + *****************************************************************************/ +static struct loader_ops * +remoteproc_check_fw_format(const void *img_data, size_t img_len) +{ + if (img_len <= 0) + return NULL; + else if (elf_identify(img_data, img_len) == 0) + return &elf_ops; + else + return NULL; +} + +static struct remoteproc_mem * +remoteproc_get_mem(struct remoteproc *rproc, const char *name, + metal_phys_addr_t pa, metal_phys_addr_t da, + void *va, size_t size) +{ + struct metal_list *node; + struct remoteproc_mem *mem; + + metal_list_for_each(&rproc->mems, node) { + mem = metal_container_of(node, struct remoteproc_mem, node); + if (name) { + if (!strncmp(name, mem->name, sizeof(mem->name))) + return mem; + } else if (pa != METAL_BAD_PHYS) { + metal_phys_addr_t pa_start, pa_end; + + pa_start = mem->pa; + pa_end = pa_start + mem->size; + if (pa >= pa_start && (pa + size) <= pa_end) + return mem; + } else if (da != METAL_BAD_PHYS) { + metal_phys_addr_t da_start, da_end; + + da_start = mem->da; + da_end = da_start + mem->size; + if (da >= da_start && (da + size) <= da_end) + return mem; + } else if (va) { + if (metal_io_virt_to_offset(mem->io, va) != + METAL_BAD_OFFSET) + return mem; + + } else { + return NULL; + } + } + return NULL; +} + +static metal_phys_addr_t +remoteproc_datopa(struct remoteproc_mem *mem, metal_phys_addr_t da) +{ + metal_phys_addr_t pa; + + pa = mem->pa + da - mem->da; + return pa; +} + +static metal_phys_addr_t +remoteproc_patoda(struct remoteproc_mem *mem, metal_phys_addr_t pa) +{ + metal_phys_addr_t da; + + da = mem->da + pa - mem->pa; + return da; +} + +static void *remoteproc_get_rsc_table(struct remoteproc *rproc, + void *store, + struct image_store_ops *store_ops, + size_t offset, + size_t len) +{ + int ret; + void *rsc_table = NULL; + const void *img_data; + + /* Copy the resource table to local memory, + * the caller should be responsible to release the memory + */ + rsc_table = metal_allocate_memory(len); + if (!rsc_table) { + return RPROC_ERR_PTR(-RPROC_ENOMEM); + } + ret = store_ops->load(store, offset, len, &img_data, RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < 0 || ret < (int)len || img_data == NULL) { + metal_log(METAL_LOG_ERROR, + "get rsc failed: 0x%llx, 0x%llx\r\n", offset, len); + rsc_table = RPROC_ERR_PTR(-RPROC_EINVAL); + goto error; + } + memcpy(rsc_table, img_data, len); + + ret = handle_rsc_table(rproc, rsc_table, len, NULL); + if (ret < 0) { + rsc_table = RPROC_ERR_PTR(ret); + goto error; + } + return rsc_table; + +error: + metal_free_memory(rsc_table); + return rsc_table; +} + +int remoteproc_parse_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size) +{ + struct metal_io_region *io; + + io = remoteproc_get_io_with_va(rproc, (void *)rsc_table); + return handle_rsc_table(rproc, rsc_table, rsc_size, io); +} + +int remoteproc_set_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size) +{ + int ret; + struct metal_io_region *io; + + io = remoteproc_get_io_with_va(rproc, (void *)rsc_table); + if (!io) + return -EINVAL; + ret = remoteproc_parse_rsc_table(rproc, rsc_table, rsc_size); + if (!ret) { + rproc->rsc_table = rsc_table; + rproc->rsc_len = rsc_size; + rproc->rsc_io = io; + } + return ret; + +} + +struct remoteproc *remoteproc_init(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *priv) +{ + if (rproc) { + memset(rproc, 0, sizeof (*rproc)); + rproc->state = RPROC_OFFLINE; + metal_mutex_init(&rproc->lock); + metal_list_init(&rproc->mems); + metal_list_init(&rproc->vdevs); + } + rproc = ops->init(rproc, ops, priv); + return rproc; +} + +int remoteproc_remove(struct remoteproc *rproc) +{ + int ret; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_OFFLINE) + rproc->ops->remove(rproc); + else + ret = -EBUSY; + metal_mutex_release(&rproc->lock); + } else { + ret = -EINVAL; + } + return ret; +} + +int remoteproc_config(struct remoteproc *rproc, void *data) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_OFFLINE) { + /* configure operation is allowed if the state is + * offline or ready. This function can be called + * mulitple times before start the remote. + */ + if (rproc->ops->config) + ret = rproc->ops->config(rproc, data); + rproc->state = RPROC_READY; + } else { + ret = -RPROC_EINVAL; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_start(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_READY) { + ret = rproc->ops->start(rproc); + rproc->state = RPROC_RUNNING; + } else { + ret = -RPROC_EINVAL; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_stop(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state != RPROC_STOPPED && + rproc->state != RPROC_OFFLINE) { + if (rproc->ops->stop) + ret = rproc->ops->stop(rproc); + rproc->state = RPROC_STOPPED; + } else { + ret = 0; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_shutdown(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + ret = 0; + metal_mutex_acquire(&rproc->lock); + if (rproc->state != RPROC_OFFLINE) { + if (rproc->state != RPROC_STOPPED) { + if (rproc->ops->stop) + ret = rproc->ops->stop(rproc); + } + if (!ret) { + if (rproc->ops->shutdown) + ret = rproc->ops->shutdown(rproc); + if (!ret) { + rproc->state = RPROC_OFFLINE; + } + } + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +struct metal_io_region * +remoteproc_get_io_with_name(struct remoteproc *rproc, + const char *name) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, name, + METAL_BAD_PHYS, METAL_BAD_PHYS, NULL, 0); + if (mem) + return mem->io; + else + return NULL; +} + +struct metal_io_region * +remoteproc_get_io_with_pa(struct remoteproc *rproc, + metal_phys_addr_t pa) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, pa, METAL_BAD_PHYS, NULL, 0); + if (mem) + return mem->io; + else + return NULL; +} + +struct metal_io_region * +remoteproc_get_io_with_da(struct remoteproc *rproc, + metal_phys_addr_t da, + unsigned long *offset) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, da, NULL, 0); + if (mem) { + struct metal_io_region *io; + metal_phys_addr_t pa; + + io = mem->io; + pa = remoteproc_datopa(mem, da); + *offset = metal_io_phys_to_offset(io, pa); + return io; + } else { + return NULL; + } +} + +struct metal_io_region * +remoteproc_get_io_with_va(struct remoteproc *rproc, void *va) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, METAL_BAD_PHYS, + va, 0); + if (mem) + return mem->io; + else + return NULL; +} + +void *remoteproc_mmap(struct remoteproc *rproc, + metal_phys_addr_t *pa, metal_phys_addr_t *da, + size_t size, unsigned int attribute, + struct metal_io_region **io) +{ + void *va = NULL; + metal_phys_addr_t lpa, lda; + struct remoteproc_mem *mem; + + if (!rproc) + return NULL; + else if (!pa && !da) + return NULL; + if (pa) + lpa = *pa; + else + lpa = METAL_BAD_PHYS; + if (da) + lda = *da; + else + lda = METAL_BAD_PHYS; + mem = remoteproc_get_mem(rproc, NULL, lpa, lda, NULL, size); + if (mem) { + if (lpa != METAL_BAD_PHYS) + lda = remoteproc_patoda(mem, lpa); + else if (lda != METAL_BAD_PHYS) + lpa = remoteproc_datopa(mem, lda); + if (io) + *io = mem->io; + va = metal_io_phys_to_virt(mem->io, lpa); + } else if (rproc->ops->mmap) { + va = rproc->ops->mmap(rproc, &lpa, &lda, size, attribute, io); + } + + if (pa) + *pa = lpa; + if (da) + *da = lda; + return va; +} + +int remoteproc_load(struct remoteproc *rproc, const char *path, + void *store, struct image_store_ops *store_ops, + void **img_info) +{ + int ret; + struct loader_ops *loader; + const void *img_data; + void *limg_info = NULL; + size_t offset, noffset; + size_t len, nlen; + int last_load_state; + metal_phys_addr_t da, rsc_da; + int rsc_len; + size_t rsc_size; + void *rsc_table = NULL; + struct metal_io_region *io = NULL; + + if (!rproc) + return -RPROC_ENODEV; + + metal_mutex_acquire(&rproc->lock); + metal_log(METAL_LOG_DEBUG, "%s: check remoteproc status\r\n", __func__); + /* If remoteproc is not in ready state, cannot load executable */ + if (rproc->state != RPROC_READY && rproc->state != RPROC_CONFIGURED) { + metal_log(METAL_LOG_ERROR, + "load failure: invalid rproc state %d.\r\n", + rproc->state); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + if (!store_ops) { + metal_log(METAL_LOG_ERROR, + "load failure: loader ops is not set.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + /* Open exectuable to get ready to parse */ + metal_log(METAL_LOG_DEBUG, "%s: open exectuable image\r\n", __func__); + ret = store_ops->open(store, path, &img_data); + if (ret <= 0) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to open firmware %d.\n", + ret); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + len = ret; + metal_assert(img_data != NULL); + + /* Check executable format to select a parser */ + loader = rproc->loader; + if (!loader) { + metal_log(METAL_LOG_DEBUG, "%s: check loader\r\n", __func__); + loader = remoteproc_check_fw_format(img_data, len); + if (!loader) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to get store ops.\n"); + ret = -RPROC_EINVAL; + goto error1; + } + rproc->loader = loader; + } + + /* Load exectuable headers */ + metal_log(METAL_LOG_DEBUG, "%s: loading headers\r\n", __func__); + offset = 0; + last_load_state = RPROC_LOADER_NOT_READY; + while(1) { + ret = loader->load_header(img_data, offset, len, + &limg_info, last_load_state, + &noffset, &nlen); + last_load_state = (unsigned int)ret; + metal_log(METAL_LOG_DEBUG, + "%s, load header 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, noffset, nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load header failed 0x%lx,%d.\r\n", + offset, len); + + goto error2; + } else if ((ret & RPROC_LOADER_READY_TO_LOAD) != 0) { + if (nlen == 0) + break; + else if ((noffset > (offset + len)) && + (store_ops->features & SUPPORT_SEEK) == 0) { + /* Required data is not continued, however + * seek is not supported, stop to load + * headers such as ELF section headers which + * is usually located to the end of image. + * Continue to load binary data to target + * memory. + */ + break; + } + } + /* Continue to load headers image data */ + img_data = NULL; + ret = store_ops->load(store, noffset, nlen, + &img_data, + RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < (int)nlen) { + metal_log(METAL_LOG_ERROR, + "load image data failed 0x%x,%d\r\n", + noffset, nlen); + goto error2; + } + offset = noffset; + len = nlen; + } + ret = elf_locate_rsc_table(limg_info, &rsc_da, &offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + /* parse resource table */ + rsc_len = (int)rsc_size; + rsc_table = remoteproc_get_rsc_table(rproc, store, store_ops, + offset, rsc_len); + } else { + rsc_len = ret; + } + + /* load executable data */ + metal_log(METAL_LOG_DEBUG, "%s: load executable data\r\n", __func__); + offset = 0; + len = 0; + ret = -EINVAL; + while(1) { + unsigned char padding; + size_t nmemsize; + metal_phys_addr_t pa; + + da = RPROC_LOAD_ANYADDR; + nlen = 0; + nmemsize = 0; + noffset = 0; + ret = loader->load_data(rproc, img_data, offset, len, + &limg_info, last_load_state, &da, + &noffset, &nlen, &padding, &nmemsize); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load data failed,0x%lx,%d\r\n", + noffset, nlen); + goto error3; + } + metal_log(METAL_LOG_DEBUG, + "load data: da 0x%lx, offset 0x%lx, len = 0x%lx, memsize = 0x%lx, state 0x%x\r\n", + da, noffset, nlen, nmemsize, ret); + last_load_state = ret; + if (da != RPROC_LOAD_ANYADDR) { + /* Data is supposed to be loaded to target memory */ + img_data = NULL; + /* get the I/O region from remoteproc */ + pa = METAL_BAD_PHYS; + (void)remoteproc_mmap(rproc, &pa, &da, nmemsize, 0, &io); + if (pa == METAL_BAD_PHYS || io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed, no mapping for 0x%llx.\r\n", + da); + ret = -RPROC_EINVAL; + goto error3; + } + if (nlen > 0) { + ret = store_ops->load(store, noffset, nlen, + &img_data, pa, io, 1); + if (ret != (int)nlen) { + metal_log(METAL_LOG_ERROR, + "load data failed 0x%lx, 0x%lx, 0x%x\r\n", + pa, noffset, nlen); + ret = -RPROC_EINVAL; + goto error3; + } + } + if (nmemsize > nlen) { + size_t tmpoffset; + + tmpoffset = metal_io_phys_to_offset(io, + pa + nlen); + metal_io_block_set(io, tmpoffset, + padding, (nmemsize - nlen)); + } + } else if (nlen != 0) { + ret = store_ops->load(store, noffset, nlen, + &img_data, + RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < (int)nlen) { + if ((last_load_state & + RPROC_LOADER_POST_DATA_LOAD) != 0) { + metal_log(METAL_LOG_WARNING, + "not all the headers are loaded\r\n"); + break; + } + metal_log(METAL_LOG_ERROR, + "post-load image data failed 0x%x,%d\r\n", + noffset, nlen); + goto error3; + } + offset = noffset; + len = nlen; + } else { + /* (last_load_state & RPROC_LOADER_LOAD_COMPLETE) != 0 */ + break; + } + } + + if (rsc_len < 0) { + ret = elf_locate_rsc_table(limg_info, &rsc_da, + &offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + /* parse resource table */ + rsc_len = (int)rsc_size; + rsc_table = remoteproc_get_rsc_table(rproc, store, + store_ops, + offset, + rsc_len); + } + } + + /* Update resource table */ + if (rsc_len && rsc_da != METAL_BAD_PHYS) { + void *rsc_table_cp = rsc_table; + + metal_log(METAL_LOG_DEBUG, + "%s, update resource table\r\n", __func__); + rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da, + rsc_len, 0, &io); + if (rsc_table) { + size_t rsc_io_offset; + + /* Update resource table */ + rsc_io_offset = metal_io_virt_to_offset(io, rsc_table); + ret = metal_io_block_write(io, rsc_io_offset, + rsc_table_cp, rsc_len); + if (ret != rsc_len) { + metal_log(METAL_LOG_WARNING, + "load: failed to update rsc\r\n"); + } + rproc->rsc_table = rsc_table; + rproc->rsc_len = rsc_len; + } else { + metal_log(METAL_LOG_WARNING, + "load: not able to update rsc table.\n"); + } + metal_free_memory(rsc_table_cp); + /* So that the rsc_table will not get released */ + rsc_table = NULL; + } + + metal_log(METAL_LOG_DEBUG, "%s: successfully load firmware\r\n", + __func__); + /* get entry point from the firmware */ + rproc->bootaddr = loader->get_entry(limg_info); + rproc->state = RPROC_READY; + + metal_mutex_release(&rproc->lock); + if (img_info) + *img_info = limg_info; + else + loader->release(limg_info); + store_ops->close(store); + return 0; + +error3: + if (rsc_table) + metal_free_memory(rsc_table); +error2: + loader->release(limg_info); +error1: + store_ops->close(store); + metal_mutex_release(&rproc->lock); + return ret; +} + +int remoteproc_load_noblock(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, + metal_phys_addr_t *pa, struct metal_io_region **io, + size_t *noffset, size_t *nlen, + size_t *nmlen, unsigned char *padding) +{ + int ret; + struct loader_ops *loader; + void *limg_info = NULL; + int last_load_state; + metal_phys_addr_t da, rsc_da; + size_t rsc_size; + void *rsc_table = NULL, *lrsc_table = NULL; + + if (!rproc) + return -RPROC_ENODEV; + + metal_assert(pa != NULL); + metal_assert(io != NULL); + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + metal_assert(nmlen != NULL); + metal_assert(padding != NULL); + + metal_mutex_acquire(&rproc->lock); + metal_log(METAL_LOG_DEBUG, "%s: check remoteproc status\r\n", __func__); + /* If remoteproc is not in ready state, cannot load executable */ + if (rproc->state != RPROC_READY) { + metal_log(METAL_LOG_ERROR, + "load failure: invalid rproc state %d.\r\n", + rproc->state); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + /* Check executable format to select a parser */ + loader = rproc->loader; + if (!loader) { + metal_log(METAL_LOG_DEBUG, "%s: check loader\r\n", __func__); + if (img_data == NULL || offset != 0 || len == 0) { + metal_log(METAL_LOG_ERROR, + "load failure, invalid inputs, not able to identify image.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + loader = remoteproc_check_fw_format(img_data, len); + if (!loader) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to identify image.\n"); + ret = -RPROC_EINVAL; + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + rproc->loader = loader; + } + if (img_info == NULL || *img_info == NULL ) { + last_load_state = 0; + } else { + limg_info = *img_info; + last_load_state = loader->get_load_state(limg_info); + if (last_load_state < 0) { + metal_log(METAL_LOG_ERROR, + "load failure, not able get load state.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + } + da = RPROC_LOAD_ANYADDR; + *nlen = 0; + if ((last_load_state & RPROC_LOADER_READY_TO_LOAD) == 0 && + (last_load_state & RPROC_LOADER_LOAD_COMPLETE) == 0) { + /* Get the mandatory executable headers */ + ret = loader->load_header(img_data, offset, len, + &limg_info, last_load_state, + noffset, nlen); + last_load_state = (unsigned int)ret; + metal_log(METAL_LOG_DEBUG, + "%s, load header 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, *noffset, *nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load header failed 0x%lx,%d.\r\n", + offset, len); + + goto error1; + } + last_load_state = loader->get_load_state(limg_info); + if (*nlen != 0 && + (last_load_state & RPROC_LOADER_READY_TO_LOAD) == 0) + goto out; + } + if ((last_load_state & RPROC_LOADER_READY_TO_LOAD) != 0 || + (last_load_state & RPROC_LOADER_POST_DATA_LOAD) != 0) { + /* Enough information to know which target memory for + * which data. + */ + ret = loader->load_data(rproc, img_data, offset, len, + &limg_info, last_load_state, &da, + noffset, nlen, padding, nmlen); + metal_log(METAL_LOG_DEBUG, + "%s, load data 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, *noffset, *nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load data failed,0x%lx,%d\r\n", + offset, len); + goto error1; + } + if (da != RPROC_LOAD_ANYADDR) { + /* get the I/O region from remoteproc */ + *pa = METAL_BAD_PHYS; + (void)remoteproc_mmap(rproc, pa, &da, *nmlen, 0, io); + if (*pa == METAL_BAD_PHYS || io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed, no mapping for 0x%llx.\r\n", + da); + ret = -RPROC_EINVAL; + goto error1; + } + } + if (*nlen != 0) + goto out; + else + last_load_state = loader->get_load_state(limg_info); + } + if ((last_load_state & RPROC_LOADER_LOAD_COMPLETE) != 0) { + /* Get resource table */ + size_t rsc_offset; + size_t rsc_io_offset; + + ret = elf_locate_rsc_table(limg_info, &rsc_da, + &rsc_offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + lrsc_table = metal_allocate_memory(rsc_size); + if (lrsc_table == NULL) { + ret = -RPROC_ENOMEM; + goto error1; + } + rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da, + rsc_size, 0, io); + if (*io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to mmap rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + rsc_io_offset = metal_io_virt_to_offset(*io, rsc_table); + ret = metal_io_block_read(*io, rsc_io_offset, + lrsc_table, (int)rsc_size); + if (ret != (int)rsc_size) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to get rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + /* parse resource table */ + ret = remoteproc_parse_rsc_table(rproc, lrsc_table, + rsc_size); + if (ret == (int)rsc_size) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to parse rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + /* Update resource table */ + ret = metal_io_block_write(*io, rsc_io_offset, + lrsc_table, (int)rsc_size); + if (ret != (int)rsc_size) { + metal_log(METAL_LOG_WARNING, + "load exectuable, failed to update rsc\r\n"); + } + rproc->rsc_table = rsc_table; + rproc->rsc_len = (int)rsc_size; + metal_free_memory(lrsc_table); + } + } +out: + if (img_info != NULL) + *img_info = limg_info; + else + loader->release(limg_info); + metal_mutex_release(&rproc->lock); + return 0; + +error1: + loader->release(limg_info); + metal_mutex_release(&rproc->lock); + return ret; +} + +unsigned int remoteproc_allocate_id(struct remoteproc *rproc, + unsigned int start, + unsigned int end) +{ + unsigned int notifyid; + + if (start == RSC_NOTIFY_ID_ANY) + start = 0; + if (end == RSC_NOTIFY_ID_ANY) + end = METAL_BITS_PER_ULONG; + notifyid = metal_bitmap_next_set_bit(&rproc->bitmap, + start, end); + if (notifyid != end) + metal_bitmap_set_bit(&rproc->bitmap, notifyid); + return notifyid; +} + +static int remoteproc_virtio_notify(void *priv, uint32_t id) +{ + struct remoteproc *rproc = priv; + + return rproc->ops->notify(rproc, id); +} + +struct virtio_device * +remoteproc_create_virtio(struct remoteproc *rproc, + int vdev_id, unsigned int role, + void (*rst_cb)(struct virtio_device *vdev)) +{ + char *rsc_table; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *vdev_rsc_io; + struct virtio_device *vdev; + struct remoteproc_virtio *rpvdev; + size_t vdev_rsc_offset; + unsigned int notifyid; + unsigned int num_vrings, i; + struct metal_list *node; + + metal_assert(rproc); + metal_mutex_acquire(&rproc->lock); + rsc_table = rproc->rsc_table; + vdev_rsc_io = rproc->rsc_io; + vdev_rsc_offset = find_rsc(rsc_table, RSC_VDEV, vdev_id); + if (!vdev_rsc_offset) { + metal_mutex_release(&rproc->lock); + return NULL; + } + vdev_rsc = (struct fw_rsc_vdev *)(rsc_table + vdev_rsc_offset); + notifyid = vdev_rsc->notifyid; + /* Check if the virtio device is already created */ + metal_list_for_each(&rproc->vdevs, node) { + rpvdev = metal_container_of(node, struct remoteproc_virtio, + node); + if (rpvdev->vdev.index == notifyid) + return &rpvdev->vdev; + } + vdev = rproc_virtio_create_vdev(role, notifyid, + vdev_rsc, vdev_rsc_io, rproc, + remoteproc_virtio_notify, + rst_cb); + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_list_add_tail(&rproc->vdevs, &rpvdev->node); + num_vrings = vdev_rsc->num_of_vrings; + /* set the notification id for vrings */ + for (i = 0; i < num_vrings; i++) { + struct fw_rsc_vdev_vring *vring_rsc; + metal_phys_addr_t da; + unsigned int num_descs, align; + struct metal_io_region *io; + void *va; + size_t size; + int ret; + + vring_rsc = &vdev_rsc->vring[i]; + notifyid = vring_rsc->notifyid; + da = vring_rsc->da; + num_descs = vring_rsc->num; + align = vring_rsc->align; + size = vring_size(num_descs, align); + va = remoteproc_mmap(rproc, NULL, &da, size, 0, &io); + if (!va) + goto err1; + ret = rproc_virtio_init_vring(vdev, i, notifyid, + va, io, num_descs, align); + if (ret) + goto err1; + } + metal_mutex_release(&rproc->lock); + return vdev; + +err1: + remoteproc_remove_virtio(rproc, vdev); + metal_mutex_release(&rproc->lock); + return NULL; +} + +void remoteproc_remove_virtio(struct remoteproc *rproc, + struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + + (void)rproc; + metal_assert(vdev); + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_list_del(&rpvdev->node); + rproc_virtio_remove_vdev(&rpvdev->vdev); +} + +int remoteproc_get_notification(struct remoteproc *rproc, uint32_t notifyid) +{ + struct remoteproc_virtio *rpvdev; + struct metal_list *node; + int ret; + + metal_list_for_each(&rproc->vdevs, node) { + rpvdev = metal_container_of(node, struct remoteproc_virtio, + node); + ret = rproc_virtio_notified(&rpvdev->vdev, notifyid); + if (ret) + return ret; + } + return 0; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc_virtio.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc_virtio.c new file mode 100644 index 0000000000..0059718dc1 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc_virtio.c @@ -0,0 +1,330 @@ +/* + * Remoteproc Virtio Framework Implementation + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <openamp/remoteproc.h> +#include <openamp/remoteproc_virtio.h> +#include <openamp/virtqueue.h> +#include <metal/utilities.h> +#include <metal/alloc.h> + +static void rproc_virtio_virtqueue_notify(struct virtqueue *vq) +{ + struct remoteproc_virtio *rpvdev; + struct virtio_vring_info *vring_info; + struct virtio_device *vdev; + unsigned int vq_id = vq->vq_queue_index; + + vdev = vq->vq_dev; + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_assert(vq_id <= vdev->vrings_num); + vring_info = &vdev->vrings_info[vq_id]; + rpvdev->notify(rpvdev->priv, vring_info->notifyid); +} + +static unsigned char rproc_virtio_get_status(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + char status; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + status = metal_io_read8(io, + metal_io_virt_to_offset(io, &vdev_rsc->status)); + return status; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_set_status(struct virtio_device *vdev, + unsigned char status) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + metal_io_write8(io, + metal_io_virt_to_offset(io, &vdev_rsc->status), + status); + rpvdev->notify(rpvdev->priv, vdev->index); +} +#endif + +static uint32_t rproc_virtio_get_features(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + uint32_t features; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + /* TODO: shall we get features based on the role ? */ + features = metal_io_read32(io, + metal_io_virt_to_offset(io, &vdev_rsc->dfeatures)); + + return features; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_set_features(struct virtio_device *vdev, + uint32_t features) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + /* TODO: shall we set features based on the role ? */ + metal_io_write32(io, + metal_io_virt_to_offset(io, &vdev_rsc->dfeatures), + features); + rpvdev->notify(rpvdev->priv, vdev->index); +} +#endif + +static uint32_t rproc_virtio_negotiate_features(struct virtio_device *vdev, + uint32_t features) +{ + (void)vdev; + (void)features; + + return 0; +} + +static void rproc_virtio_read_config(struct virtio_device *vdev, + uint32_t offset, void *dst, int length) +{ + (void)vdev; + (void)offset; + (void)dst; + (void)length; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_write_config(struct virtio_device *vdev, + uint32_t offset, void *src, int length) +{ + (void)vdev; + (void)offset; + (void)src; + (void)length; +} + +static void rproc_virtio_reset_device(struct virtio_device *vdev) +{ + if (vdev->role == VIRTIO_DEV_MASTER) + rproc_virtio_set_status(vdev, + VIRTIO_CONFIG_STATUS_NEEDS_RESET); +} +#endif + +const struct virtio_dispatch remoteproc_virtio_dispatch_funcs = { + .get_status = rproc_virtio_get_status, + .get_features = rproc_virtio_get_features, + .read_config = rproc_virtio_read_config, + .notify = rproc_virtio_virtqueue_notify, + .negotiate_features = rproc_virtio_negotiate_features, +#ifndef VIRTIO_SLAVE_ONLY + /* + * We suppose here that the vdev is in a shared memory so that can + * be access only by one core: the master. In this case salve core has + * only read access right. + */ + .set_status = rproc_virtio_set_status, + .set_features = rproc_virtio_set_features, + .write_config = rproc_virtio_write_config, + .reset_device = rproc_virtio_reset_device, +#endif +}; + +struct virtio_device * +rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, + void *rsc, struct metal_io_region *rsc_io, + void *priv, + rpvdev_notify_func notify, + virtio_dev_reset_cb rst_cb) +{ + struct remoteproc_virtio *rpvdev; + struct virtio_vring_info *vrings_info; + struct fw_rsc_vdev *vdev_rsc = rsc; + struct virtio_device *vdev; + unsigned int num_vrings = vdev_rsc->num_of_vrings; + unsigned int i; + + rpvdev = metal_allocate_memory(sizeof(*rpvdev)); + if (!rpvdev) + return NULL; + vrings_info = metal_allocate_memory(sizeof(*vrings_info) * num_vrings); + if (!vrings_info) + goto err0; + memset(rpvdev, 0, sizeof(*rpvdev)); + memset(vrings_info, 0, sizeof(*vrings_info)); + vdev = &rpvdev->vdev; + + for (i = 0; i < num_vrings; i++) { + struct virtqueue *vq; + struct fw_rsc_vdev_vring *vring_rsc; + unsigned int num_extra_desc = 0; + + vring_rsc = &vdev_rsc->vring[i]; + if (role == VIRTIO_DEV_MASTER) { + num_extra_desc = vring_rsc->num; + } + vq = virtqueue_allocate(num_extra_desc); + if (!vq) + goto err1; + vrings_info[i].vq = vq; + } + + /* FIXME commended as seems not nedded, already stored in vdev */ + //rpvdev->notifyid = notifyid; + rpvdev->notify = notify; + rpvdev->priv = priv; + vdev->vrings_info = vrings_info; + /* Assuming the shared memory has been mapped and registered if + * necessary + */ + rpvdev->vdev_rsc = vdev_rsc; + rpvdev->vdev_rsc_io = rsc_io; + + vdev->index = notifyid; + vdev->role = role; + vdev->reset_cb = rst_cb; + vdev->vrings_num = num_vrings; + vdev->func = &remoteproc_virtio_dispatch_funcs; + /* TODO: Shall we set features here ? */ + + return &rpvdev->vdev; + +err1: + for (i = 0; i < num_vrings; i++) { + if (vrings_info[i].vq) + metal_free_memory(vrings_info[i].vq); + } + metal_free_memory(vrings_info); +err0: + metal_free_memory(rpvdev); + return NULL; +} + +void rproc_virtio_remove_vdev(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + unsigned int i; + + if (!vdev) + return; + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + for (i = 0; i < vdev->vrings_num; i++) { + struct virtqueue *vq; + + vq = vdev->vrings_info[i].vq; + if (vq) + metal_free_memory(vq); + } + metal_free_memory(vdev->vrings_info); + metal_free_memory(rpvdev); +} + +int rproc_virtio_init_vring(struct virtio_device *vdev, unsigned int index, + unsigned int notifyid, void *va, + struct metal_io_region *io, + unsigned int num_descs, unsigned int align) +{ + struct virtio_vring_info *vring_info; + unsigned int num_vrings; + + num_vrings = vdev->vrings_num; + if (index >= num_vrings) + return -RPROC_EINVAL; + vring_info = &vdev->vrings_info[index]; + vring_info->io = io; + vring_info->notifyid = notifyid; + vring_info->info.vaddr = va; + vring_info->info.num_descs = num_descs; + vring_info->info.align = align; + + return 0; +} + +int rproc_virtio_notified(struct virtio_device *vdev, uint32_t notifyid) +{ + unsigned int num_vrings, i; + struct virtio_vring_info *vring_info; + struct virtqueue *vq; + + if (!vdev) + return -EINVAL; + /* We do nothing for vdev notification in this implementation */ + if (vdev->index == notifyid) + return 0; + num_vrings = vdev->vrings_num; + for (i = 0; i < num_vrings; i++) { + vring_info = &vdev->vrings_info[i]; + if (vring_info->notifyid == notifyid || + notifyid == RSC_NOTIFY_ID_ANY) { + vq = vring_info->vq; + virtqueue_notification(vq); + } + } + return 0; +} + +void rproc_virtio_wait_remote_ready(struct virtio_device *vdev) +{ + uint8_t status; + + /* + * No status available for slave. As Master has not to wait + * slave action, we can return. Behavior should be updated + * in future if a slave status is added. + */ + if (vdev->role == VIRTIO_DEV_MASTER) + return; + + while (1) { + status = rproc_virtio_get_status(vdev); + if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK) + return; + } +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/rsc_table_parser.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/rsc_table_parser.c new file mode 100644 index 0000000000..37c6478011 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/remoteproc/rsc_table_parser.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * Copyright (c) 2018, Xilinx Inc. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/io.h> +#include <openamp/rsc_table_parser.h> + +static int handle_dummy_rsc(struct remoteproc *rproc, void *rsc); + +/* Resources handler */ +rsc_handler rsc_handler_table[] = { + handle_carve_out_rsc, /**< carved out resource */ + handle_dummy_rsc, /**< IOMMU dev mem resource */ + handle_trace_rsc, /**< trace buffer resource */ + handle_vdev_rsc, /**< virtio resource */ + handle_dummy_rsc, /**< rproc shared memory resource */ + handle_dummy_rsc, /**< firmware checksum resource */ +}; + +int handle_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, int size, + struct metal_io_region *io) +{ + char *rsc_start; + unsigned int rsc_type; + unsigned int idx, offset; + int status = 0; + + /* Validate rsc table header fields */ + + /* Minimum rsc table size */ + if (sizeof(struct resource_table) > (unsigned int)size) { + return -RPROC_ERR_RSC_TAB_TRUNC; + } + + /* Supported version */ + if (rsc_table->ver != RSC_TAB_SUPPORTED_VERSION) { + return -RPROC_ERR_RSC_TAB_VER; + } + + /* Offset array */ + offset = sizeof(struct resource_table) + + rsc_table->num * sizeof(rsc_table->offset[0]); + + if (offset > (unsigned int)size) { + return -RPROC_ERR_RSC_TAB_TRUNC; + } + + /* Reserved fields - must be zero */ + if ((rsc_table->reserved[0] != 0 || rsc_table->reserved[1]) != 0) { + return -RPROC_ERR_RSC_TAB_RSVD; + } + + /* Loop through the offset array and parse each resource entry */ + for (idx = 0; idx < rsc_table->num; idx++) { + rsc_start = (char *)rsc_table; + rsc_start += rsc_table->offset[idx]; + if (io && + metal_io_virt_to_offset(io, rsc_start) == METAL_BAD_OFFSET) + return -RPROC_ERR_RSC_TAB_TRUNC; + rsc_type = *((uint32_t *)rsc_start); + if (rsc_type < RSC_LAST) + status = rsc_handler_table[rsc_type](rproc, + rsc_start); + else if (rsc_type >= RSC_VENDOR_START && + rsc_type <= RSC_VENDOR_END) + status = handle_vendor_rsc(rproc, rsc_start); + if (status == -RPROC_ERR_RSC_TAB_NS) { + status = 0; + continue; + } + else if (status) + break; + } + + return status; +} + +/** + * handle_carve_out_rsc + * + * Carveout resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to carveout resource + * + * @returns - 0 for success, or negative value for failure + * + */ +int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_carveout *carve_rsc = (struct fw_rsc_carveout *)rsc; + metal_phys_addr_t da; + metal_phys_addr_t pa; + size_t size; + unsigned int attribute; + + /* Validate resource fields */ + if (!carve_rsc) { + return -RPROC_ERR_RSC_TAB_NP; + } + + if (carve_rsc->reserved) { + return -RPROC_ERR_RSC_TAB_RSVD; + } + pa = carve_rsc->pa; + da = carve_rsc->da; + size = carve_rsc->len; + attribute = carve_rsc->flags; + if (remoteproc_mmap(rproc, &pa, &da, size, attribute, NULL)) + return 0; + else + return -RPROC_EINVAL; +} + +int handle_vendor_rsc(struct remoteproc *rproc, void *rsc) +{ + if (rproc && rproc->ops->handle_rsc) { + struct fw_rsc_vendor *vend_rsc = rsc; + size_t len = vend_rsc->len; + + return rproc->ops->handle_rsc(rproc, rsc, len); + } + return -RPROC_ERR_RSC_TAB_NS; +} + +int handle_vdev_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_vdev *vdev_rsc = (struct fw_rsc_vdev *)rsc; + unsigned int notifyid, i, num_vrings; + + /* only assign notification IDs but do not initialize vdev */ + notifyid = vdev_rsc->notifyid; + if (notifyid == RSC_NOTIFY_ID_ANY) { + notifyid = remoteproc_allocate_id(rproc, + notifyid, notifyid + 1); + vdev_rsc->notifyid = notifyid; + } + + num_vrings = vdev_rsc->num_of_vrings; + for (i = 0; i < num_vrings; i++) { + struct fw_rsc_vdev_vring *vring_rsc; + + vring_rsc = &vdev_rsc->vring[i]; + notifyid = vring_rsc->notifyid; + if (notifyid == RSC_NOTIFY_ID_ANY) { + notifyid = remoteproc_allocate_id(rproc, + notifyid, + notifyid + 1); + vdev_rsc->notifyid = notifyid; + } + } + + return 0; +} + +/** + * handle_trace_rsc + * + * trace resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to trace resource + * + * @returns - no service error + * + */ +int handle_trace_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_trace *vdev_rsc = (struct fw_rsc_trace *)rsc; + (void)rproc; + + if (vdev_rsc->da != FW_RSC_U32_ADDR_ANY && vdev_rsc->len != 0) + return 0; + /* FIXME: master should allocated a memory used by slave */ + + return -RPROC_ERR_RSC_TAB_NS; +} + +/** + * handle_dummy_rsc + * + * dummy resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to trace resource + * + * @returns - no service error + * + */ +static int handle_dummy_rsc(struct remoteproc *rproc, void *rsc) +{ + (void)rproc; + (void)rsc; + + return -RPROC_ERR_RSC_TAB_NS; +} + +size_t find_rsc(void *rsc_table, unsigned int rsc_type, unsigned int index) +{ + struct resource_table *r_table = rsc_table; + unsigned int i, rsc_index; + unsigned int lrsc_type; + char *rsc_start; + + metal_assert(r_table); + /* Loop through the offset array and parse each resource entry */ + rsc_index = 0; + for (i = 0; i < r_table->num; i++) { + rsc_start = (char *)r_table; + rsc_start += r_table->offset[i]; + lrsc_type = *((uint32_t *)rsc_start); + if (lrsc_type == rsc_type) { + if (rsc_index++ == index) + return r_table->offset[i]; + } + } + return 0; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/CMakeLists.txt b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/CMakeLists.txt new file mode 100644 index 0000000000..e2bd8d8051 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/CMakeLists.txt @@ -0,0 +1,2 @@ +collect (PROJECT_LIB_SOURCES rpmsg.c) +collect (PROJECT_LIB_SOURCES rpmsg_virtio.c) diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg.c new file mode 100644 index 0000000000..0638a4f2e3 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * Copyright (c) 2018 Linaro, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <openamp/rpmsg.h> +#include <metal/alloc.h> + +#include "rpmsg_internal.h" + +/** + * rpmsg_get_address + * + * This function provides unique 32 bit address. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * + * return - a unique address + */ +static uint32_t rpmsg_get_address(unsigned long *bitmap, int size) +{ + unsigned int addr = RPMSG_ADDR_ANY; + unsigned int nextbit; + + nextbit = metal_bitmap_next_clear_bit(bitmap, 0, size); + if (nextbit < (uint32_t)size) { + addr = nextbit; + metal_bitmap_set_bit(bitmap, nextbit); + } + + return addr; +} + +/** + * rpmsg_release_address + * + * Frees the given address. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + */ +static void rpmsg_release_address(unsigned long *bitmap, int size, + int addr) +{ + if (addr < size) + metal_bitmap_clear_bit(bitmap, addr); +} + +/** + * rpmsg_is_address_set + * + * Checks whether address is used or free. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + * + * return - TRUE/FALSE + */ +static int rpmsg_is_address_set(unsigned long *bitmap, int size, int addr) +{ + if (addr < size) + return metal_bitmap_is_bit_set(bitmap, addr); + else + return RPMSG_ERR_PARAM; +} + +/** + * rpmsg_set_address + * + * Marks the address as consumed. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + * + * return - none + */ +static int rpmsg_set_address(unsigned long *bitmap, int size, int addr) +{ + if (addr < size) { + metal_bitmap_set_bit(bitmap, addr); + return RPMSG_SUCCESS; + } else { + return RPMSG_ERR_PARAM; + } +} + +/** + * This function sends rpmsg "message" to remote device. + * + * @param ept - pointer to end point + * @param src - source address of channel + * @param dst - destination address of channel + * @param data - data to transmit + * @param size - size of data + * @param wait - boolean, wait or not for buffer to become + * available + * + * @return - size of data sent or negative value for failure. + * + */ +int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + uint32_t dst, const void *data, int size, + int wait) +{ + struct rpmsg_device *rdev; + + if (!ept || !ept->rdev || !data || dst == RPMSG_ADDR_ANY) + return RPMSG_ERR_PARAM; + + rdev = ept->rdev; + + if (rdev->ops.send_offchannel_raw) + return rdev->ops.send_offchannel_raw(rdev, src, dst, data, + size, wait); + + return RPMSG_ERR_PARAM; +} + +int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags) +{ + struct rpmsg_ns_msg ns_msg; + int ret; + + ns_msg.flags = flags; + ns_msg.addr = ept->addr; + strncpy(ns_msg.name, ept->name, sizeof(ns_msg.name)); + ret = rpmsg_send_offchannel_raw(ept, ept->addr, + RPMSG_NS_EPT_ADDR, + &ns_msg, sizeof(ns_msg), true); + if (ret < 0) + return ret; + else + return RPMSG_SUCCESS; +} + +struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rdev, + const char *name, uint32_t addr, + uint32_t dest_addr) +{ + struct metal_list *node; + struct rpmsg_endpoint *ept; + + metal_list_for_each(&rdev->endpoints, node) { + int name_match = 0; + + ept = metal_container_of(node, struct rpmsg_endpoint, node); + /* try to get by local address only */ + if (addr != RPMSG_ADDR_ANY && ept->addr == addr) + return ept; + /* try to find match on local end remote address */ + if (addr == ept->addr && dest_addr == ept->dest_addr) + return ept; + /* else use name service and destination address */ + if (name) + name_match = !strncmp(ept->name, name, + sizeof(ept->name)); + if (!name || !name_match) + continue; + /* destination address is known, equal to ept remote address*/ + if (dest_addr != RPMSG_ADDR_ANY && ept->dest_addr == dest_addr) + return ept; + /* ept is registered but not associated to remote ept*/ + if (addr == RPMSG_ADDR_ANY && ept->dest_addr == RPMSG_ADDR_ANY) + return ept; + } + return NULL; +} + +static void rpmsg_unregister_endpoint(struct rpmsg_endpoint *ept) +{ + struct rpmsg_device *rdev; + + if (!ept) + return; + + rdev = ept->rdev; + + if (ept->addr != RPMSG_ADDR_ANY) + rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, + ept->addr); + metal_list_del(&ept->node); +} + +int rpmsg_register_endpoint(struct rpmsg_device *rdev, + struct rpmsg_endpoint *ept) +{ + ept->rdev = rdev; + + metal_list_add_tail(&rdev->endpoints, &ept->node); + return RPMSG_SUCCESS; +} + +int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + const char *name, uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, rpmsg_ns_unbind_cb unbind_cb) +{ + int status; + uint32_t addr = src; + + if (!ept) + return RPMSG_ERR_PARAM; + + metal_mutex_acquire(&rdev->lock); + if (src != RPMSG_ADDR_ANY) { + status = rpmsg_is_address_set(rdev->bitmap, + RPMSG_ADDR_BMP_SIZE, src); + if (!status) { + /* Mark the address as used in the address bitmap. */ + rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, + src); + } else if (status > 0) { + status = RPMSG_SUCCESS; + goto ret_status; + } else { + goto ret_status; + } + } else { + addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE); + } + + rpmsg_init_ept(ept, name, addr, dest, cb, unbind_cb); + + status = rpmsg_register_endpoint(rdev, ept); + if (status < 0) + rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr); + + if (!status && ept->dest_addr == RPMSG_ADDR_ANY) { + /* Send NS announcement to remote processor */ + metal_mutex_release(&rdev->lock); + status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE); + metal_mutex_acquire(&rdev->lock); + if (status) + rpmsg_unregister_endpoint(ept); + } + +ret_status: + metal_mutex_release(&rdev->lock); + return status; +} + +/** + * rpmsg_destroy_ept + * + * This function deletes rpmsg endpoint and performs cleanup. + * + * @param ept - pointer to endpoint to destroy + * + */ +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) +{ + struct rpmsg_device *rdev; + + if (!ept) + return; + + rdev = ept->rdev; + if (ept->addr != RPMSG_NS_EPT_ADDR) + (void)rpmsg_send_ns_message(ept, RPMSG_NS_DESTROY); + metal_mutex_acquire(&rdev->lock); + rpmsg_unregister_endpoint(ept); + metal_mutex_release(&rdev->lock); +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_internal.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_internal.h new file mode 100644 index 0000000000..e1b82086c9 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_internal.h @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef _RPMSG_INTERNAL_H_ +#define _RPMSG_INTERNAL_H_ + +#include <stdint.h> +#include <openamp/rpmsg.h> + +#if defined __cplusplus +extern "C" { +#endif + +#ifdef RPMSG_DEBUG +#define RPMSG_ASSERT(_exp, _msg) do { \ + if (!(_exp)) { \ + openamp_print("FATAL: %s - _msg", __func__); \ + while (1) { \ + ; \ + } \ + } \ + } while (0) +#else +#define RPMSG_ASSERT(_exp, _msg) do { \ + if (!(_exp)) \ + while (1) { \ + ; \ + } \ + } while (0) +#endif + +#define RPMSG_LOCATE_DATA(p) ((unsigned char *)(p) + sizeof(struct rpmsg_hdr)) +/** + * enum rpmsg_ns_flags - dynamic name service announcement flags + * + * @RPMSG_NS_CREATE: a new remote service was just created + * @RPMSG_NS_DESTROY: a known remote service was just destroyed + * @RPMSG_NS_CREATE_WITH_ACK: a new remote service was just created waiting + * acknowledgment. + */ +enum rpmsg_ns_flags { + RPMSG_NS_CREATE = 0, + RPMSG_NS_DESTROY = 1, +}; + +/** + * struct rpmsg_hdr - common header for all rpmsg messages + * @src: source address + * @dst: destination address + * @reserved: reserved for future use + * @len: length of payload (in bytes) + * @flags: message flags + * + * Every message sent(/received) on the rpmsg bus begins with this header. + */ +OPENAMP_PACKED_BEGIN +struct rpmsg_hdr { + uint32_t src; + uint32_t dst; + uint32_t reserved; + uint16_t len; + uint16_t flags; +} OPENAMP_PACKED_END; + +/** + * struct rpmsg_ns_msg - dynamic name service announcement message + * @name: name of remote service that is published + * @addr: address of remote service that is published + * @flags: indicates whether service is created or destroyed + * + * This message is sent across to publish a new service, or announce + * about its removal. When we receive these messages, an appropriate + * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe() + * or ->remove() handler of the appropriate rpmsg driver will be invoked + * (if/as-soon-as one is registered). + */ +OPENAMP_PACKED_BEGIN +struct rpmsg_ns_msg { + char name[RPMSG_NAME_SIZE]; + uint32_t addr; + uint32_t flags; +} OPENAMP_PACKED_END; + +int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags); + +struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rvdev, + const char *name, uint32_t addr, + uint32_t dest_addr); +int rpmsg_register_endpoint(struct rpmsg_device *rdev, + struct rpmsg_endpoint *ept); + +static inline struct rpmsg_endpoint * +rpmsg_get_ept_from_addr(struct rpmsg_device *rdev, uint32_t addr) +{ + return rpmsg_get_endpoint(rdev, NULL, addr, RPMSG_ADDR_ANY); +} + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_INTERNAL_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_virtio.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_virtio.c new file mode 100644 index 0000000000..8ae41089fe --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_virtio.c @@ -0,0 +1,692 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * Copyright (c) 2018 Linaro, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/alloc.h> +#include <metal/cache.h> +#include <metal/sleep.h> +#include <metal/utilities.h> +#include <openamp/rpmsg_virtio.h> +#include <openamp/virtqueue.h> + +#include "rpmsg_internal.h" + +#define RPMSG_NUM_VRINGS (2) + +/* Total tick count for 15secs - 1msec tick. */ +#define RPMSG_TICK_COUNT 15000 + +/* Time to wait - In multiple of 10 msecs. */ +#define RPMSG_TICKS_PER_INTERVAL 10 + +#define WORD_SIZE sizeof(unsigned long) +#define WORD_ALIGN(a) ((((a) & (WORD_SIZE - 1)) != 0) ? \ + (((a) & (~(WORD_SIZE - 1))) + WORD_SIZE) : (a)) + +#ifndef VIRTIO_SLAVE_ONLY +metal_weak void * +rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool, + size_t size) +{ + void *buffer; + + if (shpool->avail < size) + return NULL; + buffer = (void *)((char *)shpool->base + shpool->size - shpool->avail); + shpool->avail -= size; + + return buffer; +} +#endif /*!VIRTIO_SLAVE_ONLY*/ + +void rpmsg_virtio_init_shm_pool(struct rpmsg_virtio_shm_pool *shpool, + void *shb, size_t size) +{ + if (!shpool) + return; + shpool->base = shb; + shpool->size = WORD_ALIGN(size); + shpool->avail = WORD_ALIGN(size); +} + +/** + * rpmsg_virtio_return_buffer + * + * Places the used buffer back on the virtqueue. + * + * @param rvdev - pointer to remote core + * @param buffer - buffer pointer + * @param len - buffer length + * @param idx - buffer index + * + */ +static void rpmsg_virtio_return_buffer(struct rpmsg_virtio_device *rvdev, + void *buffer, unsigned long len, + unsigned short idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + + (void)idx; + /* Initialize buffer node */ + vqbuf.buf = buffer; + vqbuf.len = len; + virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1, buffer); + } +#endif /*VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + (void)buffer; + virtqueue_add_consumed_buffer(rvdev->rvq, idx, len); + } +#endif /*VIRTIO_MASTER_ONLY*/ +} + +/** + * rpmsg_virtio_enqueue_buffer + * + * Places buffer on the virtqueue for consumption by the other side. + * + * @param rvdev - pointer to rpmsg virtio + * @param buffer - buffer pointer + * @param len - buffer length + * @param idx - buffer index + * + * @return - status of function execution + */ +static int rpmsg_virtio_enqueue_buffer(struct rpmsg_virtio_device *rvdev, + void *buffer, unsigned long len, + unsigned short idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + (void)idx; + + /* Initialize buffer node */ + vqbuf.buf = buffer; + vqbuf.len = len; + return virtqueue_add_buffer(rvdev->svq, &vqbuf, 0, 1, buffer); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + (void)buffer; + return virtqueue_add_consumed_buffer(rvdev->svq, idx, len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + return 0; +} + +/** + * rpmsg_virtio_get_tx_buffer + * + * Provides buffer to transmit messages. + * + * @param rvdev - pointer to rpmsg device + * @param len - length of returned buffer + * @param idx - buffer index + * + * return - pointer to buffer. + */ +static void *rpmsg_virtio_get_tx_buffer(struct rpmsg_virtio_device *rvdev, + unsigned long *len, + unsigned short *idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + void *data = NULL; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + data = virtqueue_get_buffer(rvdev->svq, (uint32_t *)len, idx); + if (data == NULL) { + data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool, + RPMSG_BUFFER_SIZE); + *len = RPMSG_BUFFER_SIZE; + } + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + data = virtqueue_get_available_buffer(rvdev->svq, idx, + (uint32_t *)len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + return data; +} + +/** + * rpmsg_virtio_get_rx_buffer + * + * Retrieves the received buffer from the virtqueue. + * + * @param rvdev - pointer to rpmsg device + * @param len - size of received buffer + * @param idx - index of buffer + * + * @return - pointer to received buffer + * + */ +static void *rpmsg_virtio_get_rx_buffer(struct rpmsg_virtio_device *rvdev, + unsigned long *len, + unsigned short *idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + void *data = NULL; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + data = virtqueue_get_buffer(rvdev->rvq, (uint32_t *)len, idx); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + data = + virtqueue_get_available_buffer(rvdev->rvq, idx, + (uint32_t *)len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + if (data) { + /* FIX ME: library should not worry about if it needs + * to flush/invalidate cache, it is shared memory. + * The shared memory should be mapped properly before + * using it. + */ + metal_cache_invalidate(data, (unsigned int)(*len)); + } + + return data; +} + +#ifndef VIRTIO_MASTER_ONLY +/** + * check if the remote is ready to start RPMsg communication + */ +static int rpmsg_virtio_wait_remote_ready(struct rpmsg_virtio_device *rvdev) +{ + uint8_t status; + + while (1) { + status = rpmsg_virtio_get_status(rvdev); + /* Busy wait until the remote is ready */ + if (status & VIRTIO_CONFIG_STATUS_NEEDS_RESET) { + rpmsg_virtio_set_status(rvdev, 0); + /* TODO notify remote processor */ + } else if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK) { + return true; + } + /* TODO: clarify metal_cpu_yield usage*/ + metal_cpu_yield(); + } + + return false; +} +#endif /*!VIRTIO_MASTER_ONLY*/ + +/** + * _rpmsg_virtio_get_buffer_size + * + * Returns buffer size available for sending messages. + * + * @param channel - pointer to rpmsg channel + * + * @return - buffer size + * + */ +static int _rpmsg_virtio_get_buffer_size(struct rpmsg_virtio_device *rvdev) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + int length = 0; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + /* + * If device role is Remote then buffers are provided by us + * (RPMSG Master), so just provide the macro. + */ + length = RPMSG_BUFFER_SIZE - sizeof(struct rpmsg_hdr); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + /* + * If other core is Master then buffers are provided by it, + * so get the buffer size from the virtqueue. + */ + length = + (int)virtqueue_get_desc_size(rvdev->svq) - + sizeof(struct rpmsg_hdr); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + return length; +} + +/** + * This function sends rpmsg "message" to remote device. + * + * @param rdev - pointer to rpmsg device + * @param src - source address of channel + * @param dst - destination address of channel + * @param data - data to transmit + * @param size - size of data + * @param wait - boolean, wait or not for buffer to become + * available + * + * @return - size of data sent or negative value for failure. + * + */ +static int rpmsg_virtio_send_offchannel_raw(struct rpmsg_device *rdev, + uint32_t src, uint32_t dst, + const void *data, + int size, int wait) +{ + struct rpmsg_virtio_device *rvdev; + struct rpmsg_hdr rp_hdr; + void *buffer = NULL; + unsigned short idx; + int tick_count = 0; + unsigned long buff_len; + int status; + struct metal_io_region *io; + + /* Get the associated remote device for channel. */ + rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); + + status = rpmsg_virtio_get_status(rvdev); + /* Validate device state */ + if (!(status & VIRTIO_CONFIG_STATUS_DRIVER_OK)) { + return RPMSG_ERR_DEV_STATE; + } + + if (wait) + tick_count = RPMSG_TICK_COUNT / RPMSG_TICKS_PER_INTERVAL; + else + tick_count = 0; + + while (1) { + int avail_size; + + /* Lock the device to enable exclusive access to virtqueues */ + metal_mutex_acquire(&rdev->lock); + avail_size = _rpmsg_virtio_get_buffer_size(rvdev); + if (size <= avail_size) + buffer = rpmsg_virtio_get_tx_buffer(rvdev, &buff_len, + &idx); + metal_mutex_release(&rdev->lock); + if (buffer || !tick_count) + break; + if (avail_size != 0) + return RPMSG_ERR_BUFF_SIZE; + metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); + tick_count--; + } + if (!buffer) + return RPMSG_ERR_NO_BUFF; + + /* Initialize RPMSG header. */ + rp_hdr.dst = dst; + rp_hdr.src = src; + rp_hdr.len = size; + rp_hdr.reserved = 0; + + /* Copy data to rpmsg buffer. */ + io = rvdev->shbuf_io; + status = metal_io_block_write(io, metal_io_virt_to_offset(io, buffer), + &rp_hdr, sizeof(rp_hdr)); + RPMSG_ASSERT(status == sizeof(rp_hdr), "failed to write header\n"); + + status = metal_io_block_write(io, + metal_io_virt_to_offset(io, + RPMSG_LOCATE_DATA(buffer)), + data, size); + RPMSG_ASSERT(status == size, "failed to write buffer\n"); + metal_mutex_acquire(&rdev->lock); + + /* Enqueue buffer on virtqueue. */ + status = rpmsg_virtio_enqueue_buffer(rvdev, buffer, buff_len, idx); + RPMSG_ASSERT(status == VQUEUE_SUCCESS, "failed to enqueue buffer\n"); + /* Let the other side know that there is a job to process. */ + virtqueue_kick(rvdev->svq); + + metal_mutex_release(&rdev->lock); + + return size; +} + +/** + * rpmsg_virtio_tx_callback + * + * Tx callback function. + * + * @param vq - pointer to virtqueue on which Tx is has been + * completed. + * + */ +static void rpmsg_virtio_tx_callback(struct virtqueue *vq) +{ + (void)vq; +} + +/** + * rpmsg_virtio_rx_callback + * + * Rx callback function. + * + * @param vq - pointer to virtqueue on which messages is received + * + */ +static void rpmsg_virtio_rx_callback(struct virtqueue *vq) +{ + struct virtio_device *vdev = vq->vq_dev; + struct rpmsg_virtio_device *rvdev = vdev->priv; + struct rpmsg_device *rdev = &rvdev->rdev; + struct rpmsg_endpoint *ept; + struct rpmsg_hdr *rp_hdr; + unsigned long len; + unsigned short idx; + int status; + + metal_mutex_acquire(&rdev->lock); + + /* Process the received data from remote node */ + rp_hdr = (struct rpmsg_hdr *)rpmsg_virtio_get_rx_buffer(rvdev, + &len, &idx); + + metal_mutex_release(&rdev->lock); + + while (rp_hdr) { + /* Get the channel node from the remote device channels list. */ + metal_mutex_acquire(&rdev->lock); + ept = rpmsg_get_ept_from_addr(rdev, rp_hdr->dst); + metal_mutex_release(&rdev->lock); + + if (!ept) + /* Fatal error no endpoint for the given dst addr. */ + return; + + if (ept->dest_addr == RPMSG_ADDR_ANY) { + /* + * First message received from the remote side, + * update channel destination address + */ + ept->dest_addr = rp_hdr->src; + } + status = ept->cb(ept, (void *)RPMSG_LOCATE_DATA(rp_hdr), + rp_hdr->len, ept->addr, ept->priv); + + RPMSG_ASSERT(status == RPMSG_SUCCESS, + "unexpected callback status\n"); + metal_mutex_acquire(&rdev->lock); + + /* Return used buffers. */ + rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx); + + rp_hdr = (struct rpmsg_hdr *) + rpmsg_virtio_get_rx_buffer(rvdev, &len, &idx); + metal_mutex_release(&rdev->lock); + } +} + +/** + * rpmsg_virtio_ns_callback + * + * This callback handles name service announcement from the remote device + * and creates/deletes rpmsg channels. + * + * @param server_chnl - pointer to server channel control block. + * @param data - pointer to received messages + * @param len - length of received data + * @param priv - any private data + * @param src - source address + * + * @return - rpmag endpoint callback handled + */ + +#if defined (__GNUC__) && ! defined (__CC_ARM) +#pragma GCC push_options +#pragma GCC optimize ("O0") +#elif defined (__CC_ARM) +#pragma push +#pragma O0 +#endif +static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, void *priv) +{ + struct rpmsg_device *rdev = ept->rdev; + struct rpmsg_virtio_device *rvdev = (struct rpmsg_virtio_device *)rdev; + struct metal_io_region *io = rvdev->shbuf_io; + struct rpmsg_endpoint *_ept; + struct rpmsg_ns_msg *ns_msg; + uint32_t dest; + char name[RPMSG_NAME_SIZE]; + + (void)priv; + (void)src; + + ns_msg = (struct rpmsg_ns_msg *)data; + if (len != sizeof(*ns_msg)) + /* Returns as the message is corrupted */ + return RPMSG_SUCCESS; + metal_io_block_read(io, + metal_io_virt_to_offset(io, ns_msg->name), + &name, sizeof(name)); + dest = ns_msg->addr; + + /* check if a Ept has been locally registered */ + metal_mutex_acquire(&rdev->lock); + _ept = rpmsg_get_endpoint(rdev, name, RPMSG_ADDR_ANY, dest); + + if (ns_msg->flags & RPMSG_NS_DESTROY) { + if (_ept) + _ept->dest_addr = RPMSG_ADDR_ANY; + metal_mutex_release(&rdev->lock); + if (_ept && _ept->ns_unbind_cb) + _ept->ns_unbind_cb(ept); + } else { + if (!_ept) { + /* + * send callback to application, that can + * - create the associated endpoints. + * - store information for future use. + * - just ignore the request as service not supported. + */ + metal_mutex_release(&rdev->lock); + if (rdev->ns_bind_cb) + rdev->ns_bind_cb(rdev, name, dest); + } else { + _ept->dest_addr = dest; + metal_mutex_release(&rdev->lock); + } + } + + return RPMSG_SUCCESS; +} +#if defined (__GNUC__) && ! defined (__CC_ARM) +#pragma GCC pop_options +#elif defined (__CC_ARM) +#pragma pop +#endif + +int rpmsg_virtio_get_buffer_size(struct rpmsg_device *rdev) +{ + int size; + struct rpmsg_virtio_device *rvdev; + + if (!rdev) + return RPMSG_ERR_PARAM; + metal_mutex_acquire(&rdev->lock); + rvdev = (struct rpmsg_virtio_device *)rdev; + size = _rpmsg_virtio_get_buffer_size(rvdev); + metal_mutex_release(&rdev->lock); + return size; +} + +int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + struct virtio_device *vdev, + rpmsg_ns_bind_cb ns_bind_cb, + struct metal_io_region *shm_io, + struct rpmsg_virtio_shm_pool *shpool) +{ + struct rpmsg_device *rdev; + const char *vq_names[RPMSG_NUM_VRINGS]; + typedef void (*vqcallback)(struct virtqueue *vq); + vqcallback callback[RPMSG_NUM_VRINGS]; + unsigned long dev_features; + int status; + unsigned int i, role; + + rdev = &rvdev->rdev; + memset(rdev, 0, sizeof(*rdev)); + metal_mutex_init(&rdev->lock); + rvdev->vdev = vdev; + rdev->ns_bind_cb = ns_bind_cb; + vdev->priv = rvdev; + rdev->ops.send_offchannel_raw = rpmsg_virtio_send_offchannel_raw; + role = rpmsg_virtio_get_role(rvdev); + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + /* + * Since device is RPMSG Remote so we need to manage the + * shared buffers. Create shared memory pool to handle buffers. + */ + if (!shpool) + return RPMSG_ERR_PARAM; + if (!shpool->size) + return RPMSG_ERR_NO_BUFF; + rvdev->shpool = shpool; + + vq_names[0] = "rx_vq"; + vq_names[1] = "tx_vq"; + callback[0] = rpmsg_virtio_rx_callback; + callback[1] = rpmsg_virtio_tx_callback; + rvdev->rvq = vdev->vrings_info[0].vq; + rvdev->svq = vdev->vrings_info[1].vq; + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + (void)shpool; + if (role == RPMSG_REMOTE) { + vq_names[0] = "tx_vq"; + vq_names[1] = "rx_vq"; + callback[0] = rpmsg_virtio_tx_callback; + callback[1] = rpmsg_virtio_rx_callback; + rvdev->rvq = vdev->vrings_info[1].vq; + rvdev->svq = vdev->vrings_info[0].vq; + } +#endif /*!VIRTIO_MASTER_ONLY*/ + rvdev->shbuf_io = shm_io; + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + /* wait synchro with the master */ + rpmsg_virtio_wait_remote_ready(rvdev); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + /* Create virtqueues for remote device */ + status = rpmsg_virtio_create_virtqueues(rvdev, 0, RPMSG_NUM_VRINGS, + vq_names, callback); + if (status != RPMSG_SUCCESS) + return status; + + /* TODO: can have a virtio function to set the shared memory I/O */ + for (i = 0; i < RPMSG_NUM_VRINGS; i++) { + struct virtqueue *vq; + + vq = vdev->vrings_info[i].vq; + vq->shm_io = shm_io; + } + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + unsigned int idx; + void *buffer; + + vqbuf.len = RPMSG_BUFFER_SIZE; + for (idx = 0; idx < rvdev->rvq->vq_nentries; idx++) { + /* Initialize TX virtqueue buffers for remote device */ + buffer = rpmsg_virtio_shm_pool_get_buffer(shpool, + RPMSG_BUFFER_SIZE); + + if (!buffer) { + return RPMSG_ERR_NO_BUFF; + } + + vqbuf.buf = buffer; + + metal_io_block_set(shm_io, + metal_io_virt_to_offset(shm_io, + buffer), + 0x00, RPMSG_BUFFER_SIZE); + status = + virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1, + buffer); + + if (status != RPMSG_SUCCESS) { + return status; + } + } + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + + /* Initialize channels and endpoints list */ + metal_list_init(&rdev->endpoints); + + dev_features = rpmsg_virtio_get_features(rvdev); + + /* + * Create name service announcement endpoint if device supports name + * service announcement feature. + */ + if ((dev_features & (1 << VIRTIO_RPMSG_F_NS))) { + rpmsg_init_ept(&rdev->ns_ept, "NS", + RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR, + rpmsg_virtio_ns_callback, NULL); + (void)rpmsg_register_endpoint(rdev, &rdev->ns_ept); + } + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) + rpmsg_virtio_set_status(rvdev, VIRTIO_CONFIG_STATUS_DRIVER_OK); +#endif /*!VIRTIO_SLAVE_ONLY*/ + + return status; +} + +void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev) +{ + struct metal_list *node; + struct rpmsg_device *rdev; + struct rpmsg_endpoint *ept; + + rdev = &rvdev->rdev; + while (!metal_list_is_empty(&rdev->endpoints)) { + node = rdev->endpoints.next; + ept = metal_container_of(node, struct rpmsg_endpoint, node); + rpmsg_destroy_ept(ept); + } + + rvdev->rvq = 0; + rvdev->svq = 0; + + metal_mutex_deinit(&rdev->lock); +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/virtio/virtio.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/virtio/virtio.c new file mode 100644 index 0000000000..5cf87222b6 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/virtio/virtio.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2011, Bryan Venteicher <[email protected]> + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include <openamp/virtio.h> + +static const char *virtio_feature_name(unsigned long feature, + const struct virtio_feature_desc *); + +//TODO : This structure may change depending on the types of devices we support. +static const struct virtio_ident { + unsigned short devid; + const char *name; +} virtio_ident_table[] = { + { + VIRTIO_ID_NETWORK, "Network"}, { + VIRTIO_ID_BLOCK, "Block"}, { + VIRTIO_ID_CONSOLE, "Console"}, { + VIRTIO_ID_ENTROPY, "Entropy"}, { + VIRTIO_ID_BALLOON, "Balloon"}, { + VIRTIO_ID_IOMEMORY, "IOMemory"}, { + VIRTIO_ID_SCSI, "SCSI"}, { + VIRTIO_ID_9P, "9P Transport"}, { + 0, NULL} +}; + +/* Device independent features. */ +static const struct virtio_feature_desc virtio_common_feature_desc[] = { + {VIRTIO_F_NOTIFY_ON_EMPTY, "NotifyOnEmpty"}, + {VIRTIO_RING_F_INDIRECT_DESC, "RingIndirect"}, + {VIRTIO_RING_F_EVENT_IDX, "EventIdx"}, + {VIRTIO_F_BAD_FEATURE, "BadFeature"}, + + {0, NULL} +}; + +const char *virtio_dev_name(unsigned short devid) +{ + const struct virtio_ident *ident; + + for (ident = virtio_ident_table; ident->name != NULL; ident++) { + if (ident->devid == devid) + return (ident->name); + } + + return (NULL); +} + +static const char *virtio_feature_name(unsigned long val, + const struct virtio_feature_desc *desc) +{ + int i, j; + const struct virtio_feature_desc *descs[2] = { desc, + virtio_common_feature_desc + }; + + for (i = 0; i < 2; i++) { + if (!descs[i]) + continue; + + for (j = 0; descs[i][j].vfd_val != 0; j++) { + if (val == descs[i][j].vfd_val) + return (descs[i][j].vfd_str); + } + } + + return (NULL); +} + +void virtio_describe(struct virtio_device *dev, const char *msg, + uint32_t features, struct virtio_feature_desc *desc) +{ + (void)dev; + (void)msg; + (void)features; + + // TODO: Not used currently - keeping it for future use + virtio_feature_name(0, desc); +} + +int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, + unsigned int nvqs, const char *names[], + vq_callback *callbacks[]) +{ + struct virtio_vring_info *vring_info; + struct vring_alloc_info *vring_alloc; + unsigned int num_vrings, i; + int ret; + (void)flags; + + num_vrings = vdev->vrings_num; + if (nvqs > num_vrings) + return -ERROR_VQUEUE_INVLD_PARAM; + /* Initialize virtqueue for each vring */ + for (i = 0; i < nvqs; i++) { + vring_info = &vdev->vrings_info[i]; + + vring_alloc = &vring_info->info; +#ifndef VIRTIO_SLAVE_ONLY + if (vdev->role == VIRTIO_DEV_MASTER) { + size_t offset; + struct metal_io_region *io = vring_info->io; + + offset = metal_io_virt_to_offset(io, + vring_alloc->vaddr); + metal_io_block_set(io, offset, 0, + vring_size(vring_alloc->num_descs, + vring_alloc->align)); + } +#endif + ret = virtqueue_create(vdev, i, names[i], vring_alloc, + callbacks[i], vdev->func->notify, + vring_info->vq); + if (ret) + return ret; + } + return 0; +} + diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/virtio/virtqueue.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/virtio/virtqueue.c new file mode 100644 index 0000000000..e90a6940b0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/open-amp/lib/virtio/virtqueue.c @@ -0,0 +1,618 @@ +/*- + * Copyright (c) 2011, Bryan Venteicher <[email protected]> + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <string.h> +#include <openamp/virtqueue.h> +#include <metal/atomic.h> +#include <metal/log.h> +#include <metal/alloc.h> + +/* Prototype for internal functions. */ +static void vq_ring_init(struct virtqueue *, void *, int); +static void vq_ring_update_avail(struct virtqueue *, uint16_t); +static uint16_t vq_ring_add_buffer(struct virtqueue *, struct vring_desc *, + uint16_t, struct virtqueue_buf *, int, int); +static int vq_ring_enable_interrupt(struct virtqueue *, uint16_t); +static void vq_ring_free_chain(struct virtqueue *, uint16_t); +static int vq_ring_must_notify_host(struct virtqueue *vq); +static void vq_ring_notify_host(struct virtqueue *vq); +static int virtqueue_nused(struct virtqueue *vq); + +/* Default implementation of P2V based on libmetal */ +static inline void *virtqueue_phys_to_virt(struct virtqueue *vq, + metal_phys_addr_t phys) +{ + struct metal_io_region *io = vq->shm_io; + + return metal_io_phys_to_virt(io, phys); +} + +/* Default implementation of V2P based on libmetal */ +static inline metal_phys_addr_t virtqueue_virt_to_phys(struct virtqueue *vq, + void *buf) +{ + struct metal_io_region *io = vq->shm_io; + + return metal_io_virt_to_phys(io, buf); +} + +/** + * virtqueue_create - Creates new VirtIO queue + * + * @param device - Pointer to VirtIO device + * @param id - VirtIO queue ID , must be unique + * @param name - Name of VirtIO queue + * @param ring - Pointer to vring_alloc_info control block + * @param callback - Pointer to callback function, invoked + * when message is available on VirtIO queue + * @param notify - Pointer to notify function, used to notify + * other side that there is job available for it + * @param vq - Created VirtIO queue. + * + * @return - Function status + */ +int virtqueue_create(struct virtio_device *virt_dev, unsigned short id, + const char *name, struct vring_alloc_info *ring, + void (*callback)(struct virtqueue *vq), + void (*notify)(struct virtqueue *vq), + struct virtqueue *vq) +{ + int status = VQUEUE_SUCCESS; + + VQ_PARAM_CHK(ring == NULL, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(ring->num_descs == 0, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(ring->num_descs & (ring->num_descs - 1), status, + ERROR_VRING_ALIGN); + VQ_PARAM_CHK(vq == NULL, status, ERROR_NO_MEM); + + if (status == VQUEUE_SUCCESS) { + vq->vq_dev = virt_dev; + vq->vq_name = name; + vq->vq_queue_index = id; + vq->vq_nentries = ring->num_descs; + vq->vq_free_cnt = vq->vq_nentries; + vq->callback = callback; + vq->notify = notify; + + /* Initialize vring control block in virtqueue. */ + vq_ring_init(vq, (void *)ring->vaddr, ring->align); + + /* Disable callbacks - will be enabled by the application + * once initialization is completed. + */ + virtqueue_disable_cb(vq); + } + + return (status); +} + +/** + * virtqueue_add_buffer() - Enqueues new buffer in vring for consumption + * by other side. Readable buffers are always + * inserted before writable buffers + * + * @param vq - Pointer to VirtIO queue control block. + * @param buf_list - Pointer to a list of virtqueue buffers. + * @param readable - Number of readable buffers + * @param writable - Number of writable buffers + * @param cookie - Pointer to hold call back data + * + * @return - Function status + */ +int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list, + int readable, int writable, void *cookie) +{ + struct vq_desc_extra *dxp = NULL; + int status = VQUEUE_SUCCESS; + uint16_t head_idx; + uint16_t idx; + int needed; + + needed = readable + writable; + + VQ_PARAM_CHK(vq == NULL, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(needed < 1, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(vq->vq_free_cnt == 0, status, ERROR_VRING_FULL); + + VQUEUE_BUSY(vq); + + if (status == VQUEUE_SUCCESS) { + VQASSERT(vq, cookie != NULL, "enqueuing with no cookie"); + + head_idx = vq->vq_desc_head_idx; + VQ_RING_ASSERT_VALID_IDX(vq, head_idx); + dxp = &vq->vq_descx[head_idx]; + + VQASSERT(vq, dxp->cookie == NULL, + "cookie already exists for index"); + + dxp->cookie = cookie; + dxp->ndescs = needed; + + /* Enqueue buffer onto the ring. */ + idx = vq_ring_add_buffer(vq, vq->vq_ring.desc, head_idx, + buf_list, readable, writable); + + vq->vq_desc_head_idx = idx; + vq->vq_free_cnt -= needed; + + if (vq->vq_free_cnt == 0) { + VQ_RING_ASSERT_CHAIN_TERM(vq); + } else { + VQ_RING_ASSERT_VALID_IDX(vq, idx); + } + + /* + * Update vring_avail control block fields so that other + * side can get buffer using it. + */ + vq_ring_update_avail(vq, head_idx); + } + + VQUEUE_IDLE(vq); + + return status; +} + +/** + * virtqueue_get_buffer - Returns used buffers from VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param len - Length of conumed buffer + * @param idx - index of the buffer + * + * @return - Pointer to used buffer + */ +void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx) +{ + struct vring_used_elem *uep; + void *cookie; + uint16_t used_idx, desc_idx; + + if (!vq || vq->vq_used_cons_idx == vq->vq_ring.used->idx) + return (NULL); + + VQUEUE_BUSY(vq); + + used_idx = vq->vq_used_cons_idx++ & (vq->vq_nentries - 1); + uep = &vq->vq_ring.used->ring[used_idx]; + + atomic_thread_fence(memory_order_seq_cst); + + desc_idx = (uint16_t)uep->id; + if (len) + *len = uep->len; + + vq_ring_free_chain(vq, desc_idx); + + cookie = vq->vq_descx[desc_idx].cookie; + vq->vq_descx[desc_idx].cookie = NULL; + + if (idx) + *idx = used_idx; + VQUEUE_IDLE(vq); + + return cookie; +} + +uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx) +{ + return vq->vq_ring.desc[idx].len; +} + +/** + * virtqueue_free - Frees VirtIO queue resources + * + * @param vq - Pointer to VirtIO queue control block + * + */ +void virtqueue_free(struct virtqueue *vq) +{ + if (vq) { + if (vq->vq_free_cnt != vq->vq_nentries) { + metal_log(METAL_LOG_WARNING, + "%s: freeing non-empty virtqueue\r\n", + vq->vq_name); + } + + metal_free_memory(vq); + } +} + +/** + * virtqueue_get_available_buffer - Returns buffer available for use in the + * VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param avail_idx - Pointer to index used in vring desc table + * @param len - Length of buffer + * + * @return - Pointer to available buffer + */ +void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, + uint32_t *len) +{ + uint16_t head_idx = 0; + void *buffer; + + atomic_thread_fence(memory_order_seq_cst); + if (vq->vq_available_idx == vq->vq_ring.avail->idx) { + return NULL; + } + + VQUEUE_BUSY(vq); + + head_idx = vq->vq_available_idx++ & (vq->vq_nentries - 1); + *avail_idx = vq->vq_ring.avail->ring[head_idx]; + + buffer = virtqueue_phys_to_virt(vq, vq->vq_ring.desc[*avail_idx].addr); + *len = vq->vq_ring.desc[*avail_idx].len; + + VQUEUE_IDLE(vq); + + return buffer; +} + +/** + * virtqueue_add_consumed_buffer - Returns consumed buffer back to VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param head_idx - Index of vring desc containing used buffer + * @param len - Length of buffer + * + * @return - Function status + */ +int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, + uint32_t len) +{ + struct vring_used_elem *used_desc = NULL; + uint16_t used_idx; + + if (head_idx > vq->vq_nentries) { + return ERROR_VRING_NO_BUFF; + } + + VQUEUE_BUSY(vq); + + used_idx = vq->vq_ring.used->idx & (vq->vq_nentries - 1); + used_desc = &vq->vq_ring.used->ring[used_idx]; + used_desc->id = head_idx; + used_desc->len = len; + + atomic_thread_fence(memory_order_seq_cst); + + vq->vq_ring.used->idx++; + + VQUEUE_IDLE(vq); + + return VQUEUE_SUCCESS; +} + +/** + * virtqueue_enable_cb - Enables callback generation + * + * @param vq - Pointer to VirtIO queue control block + * + * @return - Function status + */ +int virtqueue_enable_cb(struct virtqueue *vq) +{ + return vq_ring_enable_interrupt(vq, 0); +} + +/** + * virtqueue_enable_cb - Disables callback generation + * + * @param vq - Pointer to VirtIO queue control block + * + */ +void virtqueue_disable_cb(struct virtqueue *vq) +{ + VQUEUE_BUSY(vq); + + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + vring_used_event(&vq->vq_ring) = + vq->vq_used_cons_idx - vq->vq_nentries - 1; + } else { + vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; + } + + VQUEUE_IDLE(vq); +} + +/** + * virtqueue_kick - Notifies other side that there is buffer available for it. + * + * @param vq - Pointer to VirtIO queue control block + */ +void virtqueue_kick(struct virtqueue *vq) +{ + VQUEUE_BUSY(vq); + + /* Ensure updated avail->idx is visible to host. */ + atomic_thread_fence(memory_order_seq_cst); + + if (vq_ring_must_notify_host(vq)) + vq_ring_notify_host(vq); + + vq->vq_queued_cnt = 0; + + VQUEUE_IDLE(vq); +} + +/** + * virtqueue_dump Dumps important virtqueue fields , use for debugging purposes + * + * @param vq - Pointer to VirtIO queue control block + */ +void virtqueue_dump(struct virtqueue *vq) +{ + if (!vq) + return; + + metal_log(METAL_LOG_DEBUG, + "VQ: %s - size=%d; free=%d; used=%d; queued=%d; " + "desc_head_idx=%d; avail.idx=%d; used_cons_idx=%d; " + "used.idx=%d; avail.flags=0x%x; used.flags=0x%x\r\n", + vq->vq_name, vq->vq_nentries, vq->vq_free_cnt, + virtqueue_nused(vq), vq->vq_queued_cnt, vq->vq_desc_head_idx, + vq->vq_ring.avail->idx, vq->vq_used_cons_idx, + vq->vq_ring.used->idx, vq->vq_ring.avail->flags, + vq->vq_ring.used->flags); +} + +/** + * virtqueue_get_desc_size - Returns vring descriptor size + * + * @param vq - Pointer to VirtIO queue control block + * + * @return - Descriptor length + */ +uint32_t virtqueue_get_desc_size(struct virtqueue *vq) +{ + uint16_t head_idx = 0; + uint16_t avail_idx = 0; + uint32_t len = 0; + + if (vq->vq_available_idx == vq->vq_ring.avail->idx) { + return 0; + } + + VQUEUE_BUSY(vq); + + head_idx = vq->vq_available_idx & (vq->vq_nentries - 1); + avail_idx = vq->vq_ring.avail->ring[head_idx]; + len = vq->vq_ring.desc[avail_idx].len; + + VQUEUE_IDLE(vq); + + return len; +} + +/************************************************************************** + * Helper Functions * + **************************************************************************/ + +/** + * + * vq_ring_add_buffer + * + */ +static uint16_t vq_ring_add_buffer(struct virtqueue *vq, + struct vring_desc *desc, uint16_t head_idx, + struct virtqueue_buf *buf_list, int readable, + int writable) +{ + struct vring_desc *dp; + int i, needed; + uint16_t idx; + + (void)vq; + + needed = readable + writable; + + for (i = 0, idx = head_idx; i < needed; i++, idx = dp->next) { + VQASSERT(vq, idx != VQ_RING_DESC_CHAIN_END, + "premature end of free desc chain"); + + dp = &desc[idx]; + dp->addr = virtqueue_virt_to_phys(vq, buf_list[i].buf); + dp->len = buf_list[i].len; + dp->flags = 0; + + if (i < needed - 1) + dp->flags |= VRING_DESC_F_NEXT; + + /* + * Readable buffers are inserted into vring before the + * writable buffers. + */ + if (i >= readable) + dp->flags |= VRING_DESC_F_WRITE; + } + + return (idx); +} + +/** + * + * vq_ring_free_chain + * + */ +static void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) +{ + struct vring_desc *dp; + struct vq_desc_extra *dxp; + + VQ_RING_ASSERT_VALID_IDX(vq, desc_idx); + dp = &vq->vq_ring.desc[desc_idx]; + dxp = &vq->vq_descx[desc_idx]; + + if (vq->vq_free_cnt == 0) { + VQ_RING_ASSERT_CHAIN_TERM(vq); + } + + vq->vq_free_cnt += dxp->ndescs; + dxp->ndescs--; + + if ((dp->flags & VRING_DESC_F_INDIRECT) == 0) { + while (dp->flags & VRING_DESC_F_NEXT) { + VQ_RING_ASSERT_VALID_IDX(vq, dp->next); + dp = &vq->vq_ring.desc[dp->next]; + dxp->ndescs--; + } + } + + VQASSERT(vq, (dxp->ndescs == 0), + "failed to free entire desc chain, remaining"); + + /* + * We must append the existing free chain, if any, to the end of + * newly freed chain. If the virtqueue was completely used, then + * head would be VQ_RING_DESC_CHAIN_END (ASSERTed above). + */ + dp->next = vq->vq_desc_head_idx; + vq->vq_desc_head_idx = desc_idx; +} + +/** + * + * vq_ring_init + * + */ +static void vq_ring_init(struct virtqueue *vq, void *ring_mem, int alignment) +{ + struct vring *vr; + int i, size; + + size = vq->vq_nentries; + vr = &vq->vq_ring; + + vring_init(vr, size, (unsigned char *)ring_mem, alignment); + + for (i = 0; i < size - 1; i++) + vr->desc[i].next = i + 1; + vr->desc[i].next = VQ_RING_DESC_CHAIN_END; +} + +/** + * + * vq_ring_update_avail + * + */ +static void vq_ring_update_avail(struct virtqueue *vq, uint16_t desc_idx) +{ + uint16_t avail_idx; + + /* + * Place the head of the descriptor chain into the next slot and make + * it usable to the host. The chain is made available now rather than + * deferring to virtqueue_notify() in the hopes that if the host is + * currently running on another CPU, we can keep it processing the new + * descriptor. + */ + avail_idx = vq->vq_ring.avail->idx & (vq->vq_nentries - 1); + vq->vq_ring.avail->ring[avail_idx] = desc_idx; + + atomic_thread_fence(memory_order_seq_cst); + + vq->vq_ring.avail->idx++; + + /* Keep pending count until virtqueue_notify(). */ + vq->vq_queued_cnt++; +} + +/** + * + * vq_ring_enable_interrupt + * + */ +static int vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc) +{ + /* + * Enable interrupts, making sure we get the latest index of + * what's already been consumed. + */ + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx + ndesc; + } else { + vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; + } + + atomic_thread_fence(memory_order_seq_cst); + + /* + * Enough items may have already been consumed to meet our threshold + * since we last checked. Let our caller know so it processes the new + * entries. + */ + if (virtqueue_nused(vq) > ndesc) { + return 1; + } + + return 0; +} + +/** + * + * virtqueue_interrupt + * + */ +void virtqueue_notification(struct virtqueue *vq) +{ + atomic_thread_fence(memory_order_seq_cst); + if (vq->callback) + vq->callback(vq); +} + +/** + * + * vq_ring_must_notify_host + * + */ +static int vq_ring_must_notify_host(struct virtqueue *vq) +{ + uint16_t new_idx, prev_idx, event_idx; + + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + new_idx = vq->vq_ring.avail->idx; + prev_idx = new_idx - vq->vq_queued_cnt; + event_idx = vring_avail_event(&vq->vq_ring); + + return (vring_need_event(event_idx, new_idx, prev_idx) != 0); + } + + return ((vq->vq_ring.used->flags & VRING_USED_F_NO_NOTIFY) == 0); +} + +/** + * + * vq_ring_notify_host + * + */ +static void vq_ring_notify_host(struct virtqueue *vq) +{ + if (vq->notify) + vq->notify(vq); +} + +/** + * + * virtqueue_nused + * + */ +static int virtqueue_nused(struct virtqueue *vq) +{ + uint16_t used_idx, nused; + + used_idx = vq->vq_ring.used->idx; + + nused = (uint16_t)(used_idx - vq->vq_used_cons_idx); + VQASSERT(vq, nused <= vq->vq_nentries, "used more than available"); + + return nused; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/virtual_driver/virt_uart.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/virtual_driver/virt_uart.c new file mode 100644 index 0000000000..d50aeac63b --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/virtual_driver/virt_uart.c @@ -0,0 +1,126 @@ +/** + ****************************************************************************** + * @file virt_uart.c + * @author MCD Application Team + * @brief UART HAL module driver. + * This file provides firmware functions to manage an rpmsg endpoint + * from user application + * + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + The VIRTUAL UART driver can be used as follows: + (#) Initialize the Virtual UART by calling the VIRT_UART_Init() API. + (++) create an endpoint. listener on the OpenAMP-rpmsg channel is now enabled. + Receive data is now possible if user registers a callback to this VIRTUAL UART instance + by calling in providing a callback function when a message is received from + remote processor (VIRT_UART_read_cb) + OpenAMP MW deals with memory allocation/free and signal events + (#) Transmit data on the created rpmsg channel by calling the VIRT_UART_Transmit() + (#) Receive data in calling VIRT_UART_RegisterCallback to register user callback + + + @endverbatim + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "virt_uart.h" +#include "metal/utilities.h" + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* this string will be sent to remote processor */ +#define RPMSG_SERVICE_NAME "rpmsg-tty-channel" + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +static int VIRT_UART_read_cb(struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, void *priv) +{ + VIRT_UART_HandleTypeDef *huart = metal_container_of(ept, VIRT_UART_HandleTypeDef, ept); + (void)src; + + huart->pRxBuffPtr = data; + huart->RxXferSize = len; + if (huart->RxCpltCallback != NULL) { + huart->RxCpltCallback(huart); + } + + return 0; +} + +VIRT_UART_StatusTypeDef VIRT_UART_Init(VIRT_UART_HandleTypeDef *huart) +{ + + int status; + + /* Create a endpoint for rmpsg communication */ + + status = OPENAMP_create_endpoint(&huart->ept, RPMSG_SERVICE_NAME, RPMSG_ADDR_ANY, + VIRT_UART_read_cb, NULL); + + if(status < 0) { + return VIRT_UART_ERROR; + } + + return VIRT_UART_OK; +} + +VIRT_UART_StatusTypeDef VIRT_UART_DeInit (VIRT_UART_HandleTypeDef *huart) +{ + OPENAMP_destroy_ept(&huart->ept); + + return VIRT_UART_OK; +} + +VIRT_UART_StatusTypeDef VIRT_UART_RegisterCallback(VIRT_UART_HandleTypeDef *huart, + VIRT_UART_CallbackIDTypeDef CallbackID, + void (* pCallback)(VIRT_UART_HandleTypeDef *_huart)) +{ + VIRT_UART_StatusTypeDef status = VIRT_UART_OK; + + switch (CallbackID) + { + case VIRT_UART_RXCPLT_CB_ID : + huart->RxCpltCallback = pCallback; + break; + + default : + /* Return error status */ + status = VIRT_UART_ERROR; + break; + } + return status; +} + +VIRT_UART_StatusTypeDef VIRT_UART_Transmit(VIRT_UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + int res; + + if (Size > (RPMSG_BUFFER_SIZE-16)) + return VIRT_UART_ERROR; + + res = OPENAMP_send(&huart->ept, pData, Size); + if (res <0) { + return VIRT_UART_ERROR; + } + + return VIRT_UART_OK; +} diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/virtual_driver/virt_uart.h b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/virtual_driver/virt_uart.h new file mode 100644 index 0000000000..c368bfdbe9 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/OpenAMP/virtual_driver/virt_uart.h @@ -0,0 +1,76 @@ +/** + ****************************************************************************** + * @file virt_uart.h + * @author MCD Application Team + * @brief Header file of UART VIRT module. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 __VIRT_UART_H +#define __VIRT_UART_H + + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "openamp.h" + +/* Exported structures --------------------------------------------------------*/ +typedef struct __VIRT_UART_HandleTypeDef +{ + struct rpmsg_endpoint ept; /*!< rpmsg endpoint */ + struct rpmsg_virtio_device *rvdev; /*< pointer to the rpmsg virtio device */ + uint8_t *pRxBuffPtr; /*!< Pointer to VIRTUAL UART Rx transfer Buffer */ + uint16_t RxXferSize; /*!< VIRTUAL UART Rx Transfer size */ + void (* RxCpltCallback)( struct __VIRT_UART_HandleTypeDef * hppp); /*!< RX CPLT callback */ +}VIRT_UART_HandleTypeDef; + + +typedef enum +{ + VIRT_UART_OK = 0x00U, + VIRT_UART_ERROR = 0x01U, + VIRT_UART_BUSY = 0x02U, + VIRT_UART_TIMEOUT = 0x03U +} VIRT_UART_StatusTypeDef; + + +typedef enum +{ + VIRT_UART_RXCPLT_CB_ID = 0x00U, /*!< PPP event 1 callback ID */ +}VIRT_UART_CallbackIDTypeDef; + + +/* Exported functions --------------------------------------------------------*/ +/* Initialization and de-initialization functions ****************************/ +VIRT_UART_StatusTypeDef VIRT_UART_Init(VIRT_UART_HandleTypeDef *huart); +VIRT_UART_StatusTypeDef VIRT_UART_DeInit (VIRT_UART_HandleTypeDef *huart); +VIRT_UART_StatusTypeDef VIRT_UART_RegisterCallback(VIRT_UART_HandleTypeDef *huart, + VIRT_UART_CallbackIDTypeDef CallbackID, + void (* pCallback)(VIRT_UART_HandleTypeDef *_huart)); + +/* IO operation functions *****************************************************/ +VIRT_UART_StatusTypeDef VIRT_UART_Transmit(VIRT_UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VIRT_UART_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_lptim.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_lptim.c index 5ba7513af2..82f66e9916 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_lptim.c +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_lptim.c @@ -22,6 +22,8 @@ #define LED7_PIN GET_PIN(H, 7) LPTIM_HandleTypeDef hlptim1; +extern int lptim_stop(void); + void LPTIM1_IRQHandler(void) { /* enter interrupt */ @@ -39,6 +41,12 @@ void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim) { HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_7); } + + /* All level of ITs can interrupt */ + __set_BASEPRI(0U); + + lptim_stop(); + rt_kprintf("system returns to normal!\n"); } static int lptim_control(uint8_t pre_value) @@ -49,32 +57,36 @@ static int lptim_control(uint8_t pre_value) } hlptim1.Instance->CFGR &= ~(7 << 9); /* clear PRESC[2:0] */ hlptim1.Instance->CFGR |= pre_value << 9; /* set PRESC[2:0] */ - + rt_kprintf("set lptim pre value [0x%x] success!\n", pre_value); + return RT_EOK; } -static int lptim_start(void) +int lptim_start(void) { - /* ### Start counting in interrupt mode ############################# */ if (HAL_LPTIM_Counter_Start_IT(&hlptim1, 32767) != HAL_OK) { - LOG_D("lptim1 start Counting Error!\n"); + LOG_D("lptim1 start counting failed!\n"); return -RT_ERROR; } + LOG_D("lptim1 start counting success!\n"); + return RT_EOK; } -static int lptim_stop() +int lptim_stop(void) { if (HAL_LPTIM_Counter_Stop_IT(&hlptim1) != HAL_OK) { - LOG_D("lptim1 stop Error!\n"); + LOG_D("lptim1 stop failed!\n"); return -RT_ERROR; } - - return RT_EOK; + + LOG_D("lptim1 stop counting success!\n"); + + return RT_EOK; } int lptim_init(void) @@ -94,9 +106,10 @@ int lptim_init(void) hlptim1.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO; if (HAL_LPTIM_Init(&hlptim1) != HAL_OK) { - LOG_D("LPTIM Init Error!\n"); + LOG_D("lptim init failed!\n"); return -RT_ERROR; } + LOG_D("lptim init success!\n"); return RT_EOK; } diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_pmic.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_pmic.c index 1abc53b59a..95e385f1b8 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_pmic.c +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_pmic.c @@ -906,7 +906,34 @@ static int pmic_init(void) return RT_EOK; } - INIT_PREV_EXPORT(pmic_init); +static int i2c_sample(int argc, char *argv[]) +{ + rt_uint8_t id = 0; + + if (argc > 1) + { + if (!rt_strcmp(argv[1], "read")) + { + rt_kprintf("i2c read pmic version id\n"); + id = stpmu1_read_reg(VERSION_STATUS_REG); + rt_kprintf("version id : 0x%02x\n", id); + return RT_EOK; + } + else + { + goto _exit; + } + } +_exit: + { + rt_kprintf("Usage:\n"); + rt_kprintf("i2c_sample read - read pmic verison id\n"); + } + + return RT_ERROR; +} +MSH_CMD_EXPORT(i2c_sample, i2c sample); + #endif diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_pwr.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_pwr.c index 1ea3ddfcb8..3aac57603d 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_pwr.c +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/drv_pwr.c @@ -13,6 +13,9 @@ #define LOG_TAG "drv.pwr" #include <drv_log.h> +extern int lptim_start(void); +extern int lptim_stop(void); + static RCC_ClkInitTypeDef RCC_ClkInit = {0}; #define __WAIT_EVENT_TIMEOUT(__CONDITION__, __TIMEOUT_VAL__) \ @@ -38,7 +41,7 @@ static void backup_cm4_clocks(void) } /* Restore the CM4 clock source muxer and the CM4 prescaler. */ -static rt_err_t restore_cm4_clock(void) +rt_err_t restore_cm4_clock(void) { /* Update SystemCoreClock variable */ SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq(); @@ -90,18 +93,18 @@ static rt_err_t restore_cm4_clock(void) return RT_EOK; } - + void RCC_WAKEUP_IRQHandler(void) { /* enter interrupt */ rt_interrupt_enter(); - + HAL_RCC_WAKEUP_IRQHandler(); - + /* leave interrupt */ rt_interrupt_leave(); } - + void HAL_RCC_WAKEUP_Callback() { if (__HAL_PWR_GET_FLAG(PWR_FLAG_STOP) == 1U) @@ -111,13 +114,23 @@ void HAL_RCC_WAKEUP_Callback() restore_cm4_clock(); /* All level of ITs can interrupt */ - __set_BASEPRI(0U); + __set_BASEPRI(0U); + rt_kprintf("system exit stop mode success!\n"); } +static void enter_sleep_mode(void) +{ + __set_BASEPRI((1) << (8 - __NVIC_PRIO_BITS)); + + lptim_start(); + + HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI); +} + static void enter_stop_mode(void) { - /* + /* * Only the IT with the highest priority (0 value) can interrupt. * RCC_WAKEUP_IRQn IT is intended to have the highest priority and to be the * only one IT having this value @@ -125,15 +138,16 @@ static void enter_stop_mode(void) * CSTOP (protection mechanism) */ __set_BASEPRI((1) << (8 - __NVIC_PRIO_BITS)); - backup_cm4_clocks(); + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOP); + backup_cm4_clocks(); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); } static void pm_wackup_key_init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; - + __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_13; @@ -141,29 +155,35 @@ static void pm_wackup_key_init(void) GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - + HAL_NVIC_SetPriority(EXTI13_IRQn, 0x01, 0); HAL_NVIC_EnableIRQ(EXTI13_IRQn); } - + int drv_pm_hw_init(void) { pm_wackup_key_init(); - + return RT_EOK; } INIT_BOARD_EXPORT(drv_pm_hw_init); - + static int pwr_sample(int argc, char *argv[]) { if (argc > 1) { if (!rt_strcmp(argv[1], "stop")) - { + { rt_kprintf("system will enter stop mode! you can press USER2 button to exit this mode\n"); enter_stop_mode(); return RT_EOK; - + + } + else if (!rt_strcmp(argv[1], "sleep")) + { + rt_kprintf("system will enter sleep mode! lptim1 will wake up the system\n"); + enter_sleep_mode(); + return RT_EOK; } else { @@ -174,6 +194,7 @@ _exit: { rt_kprintf("Usage:\n"); rt_kprintf("pwr_sample stop - system enter stop mode\n"); + rt_kprintf("pwr_sample sleep - system enter sleep mode\n"); } return -RT_ERROR; diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/spi_sample.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/spi_sample.c new file mode 100644 index 0000000000..1a4c91ac24 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/spi_sample.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-09-15 thread-liu first version + */ + +#include "board.h" + +#if defined(BSP_USING_SPI5) +#include <drv_spi.h> + +#define SPI_NAME "spi50" +static struct rt_spi_device *spi_dev = RT_NULL; + +/* attach spi5 device */ +static int rt_spi_device_init(void) +{ + struct rt_spi_configuration cfg; + + rt_hw_spi_device_attach("spi5", "spi50", NULL, NULL); + + cfg.data_width = 8; + cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB | RT_SPI_NO_CS; + cfg.max_hz = 1 *1000 *1000; + + spi_dev = (struct rt_spi_device *)rt_device_find(SPI_NAME); + + if (RT_NULL == spi_dev) + { + rt_kprintf("spi sample run failed! can't find %s device!\n", SPI_NAME); + return RT_ERROR; + } + + rt_spi_configure(spi_dev, &cfg); + + return RT_EOK; +} +INIT_APP_EXPORT(rt_spi_device_init); + +/* spi5 loopback mode test case */ +static int spi_sample(int argc, char **argv) +{ + rt_uint8_t t_buf[8], r_buf[8]; + int i = 0; + static struct rt_spi_message msg1; + + if (argc != 9) + { + rt_kprintf("Usage:\n"); + rt_kprintf("spi_sample 1 2 3 4 5 6 7 8\n"); + return -RT_ERROR; + } + + for (i = 0; i < 8; i++) + { + t_buf[i] = atoi(argv[i+1]); + } + + msg1.send_buf = &t_buf; + msg1.recv_buf = &r_buf; + msg1.length = sizeof(t_buf); + msg1.cs_take = 1; + msg1.cs_release = 0; + msg1.next = RT_NULL; + + rt_spi_transfer_message(spi_dev, &msg1); + + rt_kprintf("spi rbuf : "); + for (i = 0; i < sizeof(t_buf); i++) + { + rt_kprintf("%x ", r_buf[i]); + } + + rt_kprintf("\nspi loopback mode test over!\n"); + + return RT_EOK; +} +MSH_CMD_EXPORT(spi_sample, spi loopback test); + +#endif /* BSP_USING_SPI5 */ diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/timer_sample.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/timer_sample.c index b387325a67..fdbc721c8d 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/ports/timer_sample.c +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/timer_sample.c @@ -9,15 +9,30 @@ */ #include <board.h> + +#if defined(BSP_USING_TIM14) && defined(BSP_USING_ADC2) + #include <rtthread.h> #include <rtdevice.h> #define HWTIMER_DEV_NAME "timer14" +#define HWADC_DEV_NAME "adc2" +#define REFER_VOLTAGE 330 /* voltage reference */ +#define CONVERT_BITS (1 << 12) /* Conversion digit */ +#define ADC_DEV_CHANNEL 6 + +static rt_adc_device_t adc_dev = RT_NULL; static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size) { - rt_kprintf("this is hwtimer timeout callback fucntion!\n"); - rt_kprintf("tick is :%d !\n", rt_tick_get()); + rt_uint32_t value = 0 , vol = 0; + + /* read adc value */ + value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL); + rt_kprintf("the value is :%d \n", value); + + vol = value * REFER_VOLTAGE / CONVERT_BITS; + rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100); return 0; } @@ -41,6 +56,9 @@ static int hwtimer_stop(void) return ret; } + /* close adc channel */ + ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL); + return ret; } @@ -49,8 +67,9 @@ static int hwtimer_start(void) rt_err_t ret = RT_EOK; rt_hwtimerval_t timeout_s; rt_device_t hw_dev = RT_NULL; + rt_hwtimer_mode_t mode; - + hw_dev = rt_device_find(HWTIMER_DEV_NAME); if (hw_dev == RT_NULL) { @@ -58,6 +77,14 @@ static int hwtimer_start(void) return RT_ERROR; } + /* find adc dev */ + adc_dev = (rt_adc_device_t)rt_device_find(HWADC_DEV_NAME); + if (adc_dev == RT_NULL) + { + rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWADC_DEV_NAME); + return RT_ERROR; + } + /* Open the device in read/write mode */ ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR); if (ret != RT_EOK) @@ -91,7 +118,10 @@ static int hwtimer_start(void) rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s)); rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec); - + + /* enable adc channel */ + ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL); + return ret; } @@ -125,5 +155,6 @@ _exit: return RT_ERROR; } - MSH_CMD_EXPORT(tim_sample, tim sample); + +#endif diff --git a/bsp/stm32/stm32mp157a-st-discovery/project.ewp b/bsp/stm32/stm32mp157a-st-discovery/project.ewp index 766d8f563c..43d24dc2c8 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/project.ewp +++ b/bsp/stm32/stm32mp157a-st-discovery/project.ewp @@ -370,7 +370,6 @@ <state>$PROJ_DIR$\board</state>
<state>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\CMSIS\Include</state>
<state>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Inc</state>
- <state>$PROJ_DIR$\..\..\..\components\libc\compilers\common</state>
<state>$PROJ_DIR$\..\..\..\include</state>
<state>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Include</state>
<state>$PROJ_DIR$\..\libraries\HAL_Drivers</state>
@@ -728,7 +727,7 @@ </option>
<option>
<name>IlinkOutputFile</name>
- <state>project.out</state>
+ <state>RT-Thread-STM32MP1_CM4.elf</state>
</option>
<option>
<name>IlinkDebugInfoEnable</name>
@@ -1446,7 +1445,6 @@ <state>$PROJ_DIR$\board</state>
<state>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\CMSIS\Include</state>
<state>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Inc</state>
- <state>$PROJ_DIR$\..\..\..\components\libc\compilers\common</state>
<state>$PROJ_DIR$\..\..\..\include</state>
<state>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Include</state>
<state>$PROJ_DIR$\..\libraries\HAL_Drivers</state>
@@ -2179,18 +2177,6 @@ <group>
<name>DeviceDrivers</name>
<file>
- <name>$PROJ_DIR$\..\..\..\components\drivers\hwtimer\hwtimer.c</name>
- </file>
- <file>
- <name>$PROJ_DIR$\..\..\..\components\drivers\i2c\i2c_core.c</name>
- </file>
- <file>
- <name>$PROJ_DIR$\..\..\..\components\drivers\i2c\i2c_dev.c</name>
- </file>
- <file>
- <name>$PROJ_DIR$\..\..\..\components\drivers\i2c\i2c-bit-ops.c</name>
- </file>
- <file>
<name>$PROJ_DIR$\..\..\..\components\drivers\misc\pin.c</name>
</file>
<file>
@@ -2230,9 +2216,6 @@ <name>$PROJ_DIR$\board\CubeMX_Config\CM4\Src\stm32mp1xx_hal_msp.c</name>
</file>
<file>
- <name>$PROJ_DIR$\board\ports\timer_sample.c</name>
- </file>
- <file>
<name>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Source\Templates\iar\startup_stm32mp15xx.s</name>
</file>
<file>
@@ -2242,9 +2225,6 @@ <name>$PROJ_DIR$\..\libraries\HAL_Drivers\drv_usart.c</name>
</file>
<file>
- <name>$PROJ_DIR$\..\libraries\HAL_Drivers\drv_hwtimer.c</name>
- </file>
- <file>
<name>$PROJ_DIR$\..\libraries\HAL_Drivers\drv_common.c</name>
</file>
</group>
@@ -2336,9 +2316,6 @@ </file>
</group>
<group>
- <name>libc</name>
- </group>
- <group>
<name>STM32_HAL</name>
<file>
<name>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal.c</name>
diff --git a/bsp/stm32/stm32mp157a-st-discovery/project.uvoptx b/bsp/stm32/stm32mp157a-st-discovery/project.uvoptx index 49d2bfcd80..cd7d5cc09b 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/project.uvoptx +++ b/bsp/stm32/stm32mp157a-st-discovery/project.uvoptx @@ -119,33 +119,13 @@ <TargetDriverDllRegistry> <SetRegEntry> <Number>0</Number> - <Key>DLGUARM</Key> - <Name>(105=-1,-1,-1,-1,0)</Name> - </SetRegEntry> - <SetRegEntry> - <Number>0</Number> - <Key>ARMRTXEVENTFLAGS</Key> - <Name>-L70 -Z18 -C0 -M0 -T1</Name> - </SetRegEntry> - <SetRegEntry> - <Number>0</Number> - <Key>DLGTARM</Key> - <Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)</Name> - </SetRegEntry> - <SetRegEntry> - <Number>0</Number> - <Key>ARMDBGFLAGS</Key> - <Name></Name> - </SetRegEntry> - <SetRegEntry> - <Number>0</Number> <Key>UL2CM3</Key> <Name>UL2CM3(-S0 -C0 -P0 ) -FC1000 -FD10020000</Name> </SetRegEntry> <SetRegEntry> <Number>0</Number> <Key>ST-LINKIII-KEIL_SWO</Key> - <Name>-U066DFF343339415043182234 -O206 -SF10000 -C0 -A2 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP") -D00(6BA02477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8004 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD10020000 -FC1000 -FN0</Name> + <Name>-U066DFF343339415043182234 -O206 -SF10000 -C0 -A2 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(6BA02477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD10020000 -FC1000 -FN0</Name> </SetRegEntry> </TargetDriverDllRegistry> <Breakpoint/> @@ -155,12 +135,12 @@ <DebugFlag> <trace>0</trace> <periodic>0</periodic> - <aLwin>1</aLwin> + <aLwin>0</aLwin> <aCover>0</aCover> <aSer1>0</aSer1> <aSer2>0</aSer2> <aPa>0</aPa> - <viewmode>1</viewmode> + <viewmode>0</viewmode> <vrSel>0</vrSel> <aSym>0</aSym> <aTbox>0</aTbox> @@ -202,935 +182,11 @@ </Target> <Group> - <GroupName>Applications</GroupName> - <tvExp>1</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <cbSel>0</cbSel> - <RteFlg>0</RteFlg> - <File> - <GroupNumber>1</GroupNumber> - <FileNumber>1</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>applications\main.c</PathWithFileName> - <FilenameWithoutPath>main.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - </Group> - - <Group> - <GroupName>cpu</GroupName> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <cbSel>0</cbSel> - <RteFlg>0</RteFlg> - <File> - <GroupNumber>2</GroupNumber> - <FileNumber>2</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\libcpu\arm\common\backtrace.c</PathWithFileName> - <FilenameWithoutPath>backtrace.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>2</GroupNumber> - <FileNumber>3</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\libcpu\arm\common\div0.c</PathWithFileName> - <FilenameWithoutPath>div0.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>2</GroupNumber> - <FileNumber>4</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\libcpu\arm\common\showmem.c</PathWithFileName> - <FilenameWithoutPath>showmem.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>2</GroupNumber> - <FileNumber>5</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\libcpu\arm\cortex-m4\cpuport.c</PathWithFileName> - <FilenameWithoutPath>cpuport.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>2</GroupNumber> - <FileNumber>6</FileNumber> - <FileType>2</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\libcpu\arm\cortex-m4\context_rvds.S</PathWithFileName> - <FilenameWithoutPath>context_rvds.S</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - </Group> - - <Group> - <GroupName>DeviceDrivers</GroupName> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <cbSel>0</cbSel> - <RteFlg>0</RteFlg> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>7</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\misc\pin.c</PathWithFileName> - <FilenameWithoutPath>pin.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>8</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\serial\serial.c</PathWithFileName> - <FilenameWithoutPath>serial.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>9</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\src\completion.c</PathWithFileName> - <FilenameWithoutPath>completion.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>10</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\src\dataqueue.c</PathWithFileName> - <FilenameWithoutPath>dataqueue.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>11</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\src\pipe.c</PathWithFileName> - <FilenameWithoutPath>pipe.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>12</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\src\ringblk_buf.c</PathWithFileName> - <FilenameWithoutPath>ringblk_buf.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>13</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\src\ringbuffer.c</PathWithFileName> - <FilenameWithoutPath>ringbuffer.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>14</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\src\waitqueue.c</PathWithFileName> - <FilenameWithoutPath>waitqueue.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>3</GroupNumber> - <FileNumber>15</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\drivers\src\workqueue.c</PathWithFileName> - <FilenameWithoutPath>workqueue.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - </Group> - - <Group> - <GroupName>Drivers</GroupName> - <tvExp>1</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <cbSel>0</cbSel> - <RteFlg>0</RteFlg> - <File> - <GroupNumber>4</GroupNumber> - <FileNumber>16</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>board\board.c</PathWithFileName> - <FilenameWithoutPath>board.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>4</GroupNumber> - <FileNumber>17</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>board\CubeMX_Config\Common\System\system_stm32mp1xx.c</PathWithFileName> - <FilenameWithoutPath>system_stm32mp1xx.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>4</GroupNumber> - <FileNumber>18</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>board\CubeMX_Config\CM4\Src\stm32mp1xx_hal_msp.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_msp.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>4</GroupNumber> - <FileNumber>19</FileNumber> - <FileType>2</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Source\Templates\arm\startup_stm32mp15xx.s</PathWithFileName> - <FilenameWithoutPath>startup_stm32mp15xx.s</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>4</GroupNumber> - <FileNumber>20</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\HAL_Drivers\drv_gpio.c</PathWithFileName> - <FilenameWithoutPath>drv_gpio.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>4</GroupNumber> - <FileNumber>21</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\HAL_Drivers\drv_usart.c</PathWithFileName> - <FilenameWithoutPath>drv_usart.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>4</GroupNumber> - <FileNumber>22</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\HAL_Drivers\drv_common.c</PathWithFileName> - <FilenameWithoutPath>drv_common.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - </Group> - - <Group> - <GroupName>finsh</GroupName> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <cbSel>0</cbSel> - <RteFlg>0</RteFlg> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>23</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\shell.c</PathWithFileName> - <FilenameWithoutPath>shell.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>24</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\cmd.c</PathWithFileName> - <FilenameWithoutPath>cmd.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>25</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\msh.c</PathWithFileName> - <FilenameWithoutPath>msh.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>26</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_compiler.c</PathWithFileName> - <FilenameWithoutPath>finsh_compiler.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>27</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_error.c</PathWithFileName> - <FilenameWithoutPath>finsh_error.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>28</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_heap.c</PathWithFileName> - <FilenameWithoutPath>finsh_heap.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>29</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_init.c</PathWithFileName> - <FilenameWithoutPath>finsh_init.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>30</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_node.c</PathWithFileName> - <FilenameWithoutPath>finsh_node.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>31</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_ops.c</PathWithFileName> - <FilenameWithoutPath>finsh_ops.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>32</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_parser.c</PathWithFileName> - <FilenameWithoutPath>finsh_parser.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>33</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_var.c</PathWithFileName> - <FilenameWithoutPath>finsh_var.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>34</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_vm.c</PathWithFileName> - <FilenameWithoutPath>finsh_vm.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>5</GroupNumber> - <FileNumber>35</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\components\finsh\finsh_token.c</PathWithFileName> - <FilenameWithoutPath>finsh_token.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - </Group> - - <Group> - <GroupName>Kernel</GroupName> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <cbSel>0</cbSel> - <RteFlg>0</RteFlg> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>36</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\clock.c</PathWithFileName> - <FilenameWithoutPath>clock.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>37</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\components.c</PathWithFileName> - <FilenameWithoutPath>components.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>38</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\device.c</PathWithFileName> - <FilenameWithoutPath>device.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>39</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\idle.c</PathWithFileName> - <FilenameWithoutPath>idle.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>40</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\ipc.c</PathWithFileName> - <FilenameWithoutPath>ipc.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>41</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\irq.c</PathWithFileName> - <FilenameWithoutPath>irq.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>42</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\kservice.c</PathWithFileName> - <FilenameWithoutPath>kservice.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>43</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\memheap.c</PathWithFileName> - <FilenameWithoutPath>memheap.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>44</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\mempool.c</PathWithFileName> - <FilenameWithoutPath>mempool.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>45</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\object.c</PathWithFileName> - <FilenameWithoutPath>object.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>46</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\scheduler.c</PathWithFileName> - <FilenameWithoutPath>scheduler.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>47</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\signal.c</PathWithFileName> - <FilenameWithoutPath>signal.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>48</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\thread.c</PathWithFileName> - <FilenameWithoutPath>thread.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>6</GroupNumber> - <FileNumber>49</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\..\..\src\timer.c</PathWithFileName> - <FilenameWithoutPath>timer.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - </Group> - - <Group> - <GroupName>STM32_HAL</GroupName> + <GroupName>Source Group 1</GroupName> <tvExp>0</tvExp> <tvExpOptDlg>0</tvExpOptDlg> <cbSel>0</cbSel> <RteFlg>0</RteFlg> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>50</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>51</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_hsem.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_hsem.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>52</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_exti.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_exti.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>53</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_ipcc.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_ipcc.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>54</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_cortex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_cortex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>55</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_dma.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_dma.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>56</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_dma_ex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_dma_ex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>57</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_mdma.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_mdma.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>58</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_pwr.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_pwr.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>59</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_pwr_ex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_pwr_ex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>60</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_rcc.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_rcc.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>61</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_rcc_ex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_rcc_ex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>62</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_gpio.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_gpio.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>63</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_adc.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_adc.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>64</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_adc_ex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_adc_ex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>65</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_dac.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_dac.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>66</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_dac_ex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_dac_ex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>67</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_i2c.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_i2c.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>68</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_i2c_ex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_i2c_ex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>69</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_spi.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_spi.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>70</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_tim.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_tim.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>71</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_tim_ex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_tim_ex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>72</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_uart.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_uart.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> - <File> - <GroupNumber>7</GroupNumber> - <FileNumber>73</FileNumber> - <FileType>1</FileType> - <tvExp>0</tvExp> - <tvExpOptDlg>0</tvExpOptDlg> - <bDave2>0</bDave2> - <PathWithFileName>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_uart_ex.c</PathWithFileName> - <FilenameWithoutPath>stm32mp1xx_hal_uart_ex.c</FilenameWithoutPath> - <RteFlg>0</RteFlg> - <bShared>0</bShared> - </File> </Group> </ProjectOpt> diff --git a/bsp/stm32/stm32mp157a-st-discovery/project.uvprojx b/bsp/stm32/stm32mp157a-st-discovery/project.uvprojx index 9277544d59..3dddb0d7dc 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/project.uvprojx +++ b/bsp/stm32/stm32mp157a-st-discovery/project.uvprojx @@ -1,10 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="no" ?> <Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd"> - <SchemaVersion>2.1</SchemaVersion> - <Header>### uVision Project, (C) Keil Software</Header> - <Targets> <Target> <TargetName>rt-thread</TargetName> @@ -19,28 +16,28 @@ <PackID>Keil.STM32MP1xx_DFP.1.3.0</PackID> <PackURL>http://www.keil.com/pack/</PackURL> <Cpu>IRAM(0x10020000,0x00020000) IRAM2(0x10040000,0x00020000) IROM(0x10000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000)</Cpu> - <FlashUtilSpec></FlashUtilSpec> - <StartupFile></StartupFile> + <FlashUtilSpec /> + <StartupFile /> <FlashDriverDll>UL2CM3(-S0 -C0 -P0 -FD10020000 -FC1000)</FlashDriverDll> <DeviceId>0</DeviceId> <RegisterFile>$$Device:STM32MP157AACx$Drivers\CMSIS\Device\ST\STM32MP1xx\Include\stm32mp157axx_cm4.h</RegisterFile> - <MemoryEnv></MemoryEnv> - <Cmp></Cmp> - <Asm></Asm> - <Linker></Linker> - <OHString></OHString> - <InfinionOptionDll></InfinionOptionDll> - <SLE66CMisc></SLE66CMisc> - <SLE66AMisc></SLE66AMisc> - <SLE66LinkerMisc></SLE66LinkerMisc> + <MemoryEnv /> + <Cmp /> + <Asm /> + <Linker /> + <OHString /> + <InfinionOptionDll /> + <SLE66CMisc /> + <SLE66AMisc /> + <SLE66LinkerMisc /> <SFDFile>$$Device:STM32MP157AACx$SVD\STM32MP157x.svd</SFDFile> <bCustSvd>0</bCustSvd> <UseEnv>0</UseEnv> - <BinPath></BinPath> - <IncludePath></IncludePath> - <LibPath></LibPath> - <RegisterFilePath></RegisterFilePath> - <DBRegisterFilePath></DBRegisterFilePath> + <BinPath /> + <IncludePath /> + <LibPath /> + <RegisterFilePath /> + <DBRegisterFilePath /> <TargetStatus> <Error>0</Error> <ExitCodeStop>0</ExitCodeStop> @@ -62,8 +59,8 @@ <BeforeCompile> <RunUserProg1>0</RunUserProg1> <RunUserProg2>0</RunUserProg2> - <UserProg1Name></UserProg1Name> - <UserProg2Name></UserProg2Name> + <UserProg1Name /> + <UserProg2Name /> <UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode> <nStopU1X>0</nStopU1X> @@ -72,8 +69,8 @@ <BeforeMake> <RunUserProg1>0</RunUserProg1> <RunUserProg2>0</RunUserProg2> - <UserProg1Name></UserProg1Name> - <UserProg2Name></UserProg2Name> + <UserProg1Name /> + <UserProg2Name /> <UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode> <nStopB1X>0</nStopB1X> @@ -83,14 +80,14 @@ <RunUserProg1>1</RunUserProg1> <RunUserProg2>0</RunUserProg2> <UserProg1Name>fromelf --bin !L --output rtthread.bin</UserProg1Name> - <UserProg2Name></UserProg2Name> + <UserProg2Name /> <UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode> <nStopA1X>0</nStopA1X> <nStopA2X>0</nStopA2X> </AfterMake> <SelectedForBatchBuild>0</SelectedForBatchBuild> - <SVCSIdString></SVCSIdString> + <SVCSIdString /> </TargetCommonOption> <CommonProperty> <UseCPPCompiler>0</UseCPPCompiler> @@ -104,8 +101,8 @@ <AssembleAssemblyFile>0</AssembleAssemblyFile> <PublicsOnly>0</PublicsOnly> <StopOnExitCode>3</StopOnExitCode> - <CustomArgument></CustomArgument> - <IncludeLibraryModules></IncludeLibraryModules> + <CustomArgument /> + <IncludeLibraryModules /> <ComprImg>1</ComprImg> </CommonProperty> <DllOption> @@ -138,11 +135,11 @@ </Flash1> <bUseTDR>1</bUseTDR> <Flash2>BIN\UL2CM3.DLL</Flash2> - <Flash3>"" ()</Flash3> - <Flash4></Flash4> - <pFcarmOut></pFcarmOut> - <pFcarmGrp></pFcarmGrp> - <pFcArmRoot></pFcArmRoot> + <Flash3 /> + <Flash4 /> + <pFcarmOut /> + <pFcarmGrp /> + <pFcArmRoot /> <FcArmLst>0</FcArmLst> </Utilities> <TargetArmAds> @@ -175,7 +172,7 @@ <RvctClst>0</RvctClst> <GenPPlst>0</GenPPlst> <AdsCpuType>"Cortex-M4"</AdsCpuType> - <RvctDeviceName></RvctDeviceName> + <RvctDeviceName /> <mOS>0</mOS> <uocRom>0</uocRom> <uocRam>0</uocRam> @@ -309,7 +306,7 @@ <Size>0x20000</Size> </OCR_RVCT10> </OnChipMemories> - <RvctStartVector></RvctStartVector> + <RvctStartVector /> </ArmAdsMisc> <Cads> <interw>1</interw> @@ -326,7 +323,7 @@ <uThumb>0</uThumb> <uSurpInc>0</uSurpInc> <uC99>1</uC99> - <uGnu>1</uGnu> + <uGnu>0</uGnu> <useXO>0</useXO> <v6Lang>1</v6Lang> <v6LangP>1</v6LangP> @@ -336,10 +333,10 @@ <v6WtE>0</v6WtE> <v6Rtti>0</v6Rtti> <VariousControls> - <MiscControls></MiscControls> + <MiscControls /> <Define>CORE_CM4, __LOG_TRACE_IO_, METAL_MAX_DEVICE_REGIONS=2, VIRTIO_SLAVE_ONLY, NO_ATOMIC_64_SUPPORT, STM32MP157Axx, METAL_INTERNAL, USE_HAL_DRIVER</Define> - <Undefine></Undefine> - <IncludePath>applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\CM4\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Inc;..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Include;..\libraries\STM32MPxx_HAL\CMSIS\Core\Include;..\libraries\STM32MPxx_HAL\CMSIS\Include</IncludePath> + <Undefine /> + <IncludePath>applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\CM4\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Inc;..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Include;..\libraries\STM32MPxx_HAL\CMSIS\Core\Include;..\libraries\STM32MPxx_HAL\CMSIS\Include</IncludePath> </VariousControls> </Cads> <Aads> @@ -354,10 +351,10 @@ <useXO>0</useXO> <ClangAsOpt>4</ClangAsOpt> <VariousControls> - <MiscControls></MiscControls> - <Define></Define> - <Undefine></Undefine> - <IncludePath></IncludePath> + <MiscControls /> + <Define /> + <Undefine /> + <IncludePath /> </VariousControls> </Aads> <LDads> @@ -367,15 +364,15 @@ <noStLib>0</noStLib> <RepFail>1</RepFail> <useFile>0</useFile> - <TextAddressRange></TextAddressRange> - <DataAddressRange></DataAddressRange> - <pXoBase></pXoBase> + <TextAddressRange /> + <DataAddressRange /> + <pXoBase /> <ScatterFile>.\board\linker_scripts\link.sct</ScatterFile> - <IncludeLibs></IncludeLibs> - <IncludeLibsPath></IncludeLibsPath> - <Misc></Misc> - <LinkerInputFile></LinkerInputFile> - <DisabledWarnings></DisabledWarnings> + <IncludeLibs /> + <IncludeLibsPath /> + <Misc /> + <LinkerInputFile /> + <DisabledWarnings /> </LDads> </TargetArmAds> </TargetOption> @@ -398,21 +395,29 @@ <FileType>1</FileType> <FilePath>..\..\..\libcpu\arm\common\backtrace.c</FilePath> </File> + </Files> + <Files> <File> <FileName>div0.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\libcpu\arm\common\div0.c</FilePath> </File> + </Files> + <Files> <File> <FileName>showmem.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\libcpu\arm\common\showmem.c</FilePath> </File> + </Files> + <Files> <File> <FileName>cpuport.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\libcpu\arm\cortex-m4\cpuport.c</FilePath> </File> + </Files> + <Files> <File> <FileName>context_rvds.S</FileName> <FileType>2</FileType> @@ -428,41 +433,57 @@ <FileType>1</FileType> <FilePath>..\..\..\components\drivers\misc\pin.c</FilePath> </File> + </Files> + <Files> <File> <FileName>serial.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\drivers\serial\serial.c</FilePath> </File> + </Files> + <Files> <File> <FileName>completion.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\drivers\src\completion.c</FilePath> </File> + </Files> + <Files> <File> <FileName>dataqueue.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\drivers\src\dataqueue.c</FilePath> </File> + </Files> + <Files> <File> <FileName>pipe.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\drivers\src\pipe.c</FilePath> </File> + </Files> + <Files> <File> <FileName>ringblk_buf.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\drivers\src\ringblk_buf.c</FilePath> </File> + </Files> + <Files> <File> <FileName>ringbuffer.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\drivers\src\ringbuffer.c</FilePath> </File> + </Files> + <Files> <File> <FileName>waitqueue.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\drivers\src\waitqueue.c</FilePath> </File> + </Files> + <Files> <File> <FileName>workqueue.c</FileName> <FileType>1</FileType> @@ -478,31 +499,43 @@ <FileType>1</FileType> <FilePath>board\board.c</FilePath> </File> + </Files> + <Files> <File> <FileName>system_stm32mp1xx.c</FileName> <FileType>1</FileType> <FilePath>board\CubeMX_Config\Common\System\system_stm32mp1xx.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_msp.c</FileName> <FileType>1</FileType> <FilePath>board\CubeMX_Config\CM4\Src\stm32mp1xx_hal_msp.c</FilePath> </File> + </Files> + <Files> <File> <FileName>startup_stm32mp15xx.s</FileName> <FileType>2</FileType> <FilePath>..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Source\Templates\arm\startup_stm32mp15xx.s</FilePath> </File> + </Files> + <Files> <File> <FileName>drv_gpio.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\HAL_Drivers\drv_gpio.c</FilePath> </File> + </Files> + <Files> <File> <FileName>drv_usart.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\HAL_Drivers\drv_usart.c</FilePath> </File> + </Files> + <Files> <File> <FileName>drv_common.c</FileName> <FileType>1</FileType> @@ -518,61 +551,85 @@ <FileType>1</FileType> <FilePath>..\..\..\components\finsh\shell.c</FilePath> </File> + </Files> + <Files> <File> <FileName>cmd.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\cmd.c</FilePath> </File> + </Files> + <Files> <File> <FileName>msh.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\msh.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_compiler.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_compiler.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_error.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_error.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_heap.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_heap.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_init.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_init.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_node.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_node.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_ops.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_ops.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_parser.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_parser.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_var.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_var.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_vm.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\components\finsh\finsh_vm.c</FilePath> </File> + </Files> + <Files> <File> <FileName>finsh_token.c</FileName> <FileType>1</FileType> @@ -588,66 +645,92 @@ <FileType>1</FileType> <FilePath>..\..\..\src\clock.c</FilePath> </File> + </Files> + <Files> <File> <FileName>components.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\components.c</FilePath> </File> + </Files> + <Files> <File> <FileName>device.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\device.c</FilePath> </File> + </Files> + <Files> <File> <FileName>idle.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\idle.c</FilePath> </File> + </Files> + <Files> <File> <FileName>ipc.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\ipc.c</FilePath> </File> + </Files> + <Files> <File> <FileName>irq.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\irq.c</FilePath> </File> + </Files> + <Files> <File> <FileName>kservice.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\kservice.c</FilePath> </File> + </Files> + <Files> <File> <FileName>memheap.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\memheap.c</FilePath> </File> + </Files> + <Files> <File> <FileName>mempool.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\mempool.c</FilePath> </File> + </Files> + <Files> <File> <FileName>object.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\object.c</FilePath> </File> + </Files> + <Files> <File> <FileName>scheduler.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\scheduler.c</FilePath> </File> + </Files> + <Files> <File> <FileName>signal.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\signal.c</FilePath> </File> + </Files> + <Files> <File> <FileName>thread.c</FileName> <FileType>1</FileType> <FilePath>..\..\..\src\thread.c</FilePath> </File> + </Files> + <Files> <File> <FileName>timer.c</FileName> <FileType>1</FileType> @@ -663,116 +746,162 @@ <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_hsem.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_hsem.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_exti.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_exti.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_ipcc.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_ipcc.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_cortex.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_cortex.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_dma.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_dma.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_dma_ex.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_dma_ex.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_mdma.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_mdma.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_pwr.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_pwr.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_pwr_ex.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_pwr_ex.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_rcc.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_rcc.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_rcc_ex.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_rcc_ex.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_gpio.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_gpio.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_adc.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_adc.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_adc_ex.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_adc_ex.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_dac.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_dac.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_dac_ex.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_dac_ex.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_i2c.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_i2c.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_i2c_ex.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_i2c_ex.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_spi.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_spi.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_tim.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_tim.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_tim_ex.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_tim_ex.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_uart.c</FileName> <FileType>1</FileType> <FilePath>..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_uart.c</FilePath> </File> + </Files> + <Files> <File> <FileName>stm32mp1xx_hal_uart_ex.c</FileName> <FileType>1</FileType> @@ -783,26 +912,23 @@ </Groups> </Target> </Targets> - <RTE> - <apis/> - <components/> - <files/> + <apis /> + <components /> + <files /> </RTE> - <LayerInfo> <Layers> <Layer> <LayName><Project Info></LayName> - <LayDesc></LayDesc> - <LayUrl></LayUrl> - <LayKeys></LayKeys> - <LayCat></LayCat> - <LayLic></LayLic> + <LayDesc /> + <LayUrl /> + <LayKeys /> + <LayCat /> + <LayLic /> <LayTarg>0</LayTarg> <LayPrjMark>1</LayPrjMark> </Layer> </Layers> </LayerInfo> - </Project> diff --git a/bsp/stm32/stm32mp157a-st-discovery/rtconfig.h b/bsp/stm32/stm32mp157a-st-discovery/rtconfig.h index ec904bcfb6..aa6a51bb86 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/rtconfig.h +++ b/bsp/stm32/stm32mp157a-st-discovery/rtconfig.h @@ -151,12 +151,6 @@ /* samples: kernel and components samples */ - -/* Privated Packages of RealThread */ - - -/* Network Utilities */ - #define SOC_FAMILY_STM32 #define SOC_SERIES_STM32MP1 diff --git a/bsp/stm32/stm32mp157a-st-discovery/template.ewp b/bsp/stm32/stm32mp157a-st-discovery/template.ewp index fa05f0555b..e6c552086d 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/template.ewp +++ b/bsp/stm32/stm32mp157a-st-discovery/template.ewp @@ -704,7 +704,7 @@ </option>
<option>
<name>IlinkOutputFile</name>
- <state>project.out</state>
+ <state>RT-Thread-STM32MP1_CM4.elf</state>
</option>
<option>
<name>IlinkDebugInfoEnable</name>
diff --git a/bsp/stm32/stm32mp157a-st-discovery/template.uvprojx b/bsp/stm32/stm32mp157a-st-discovery/template.uvprojx index 1c1afdaf71..bc7e6847ac 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/template.uvprojx +++ b/bsp/stm32/stm32mp157a-st-discovery/template.uvprojx @@ -326,7 +326,7 @@ <uThumb>0</uThumb> <uSurpInc>0</uSurpInc> <uC99>1</uC99> - <uGnu>1</uGnu> + <uGnu>0</uGnu> <useXO>0</useXO> <v6Lang>1</v6Lang> <v6LangP>1</v6LangP> diff --git a/bsp/stm32/stm32mp157a-st-discovery/tools/rt-thread-shell.py b/bsp/stm32/stm32mp157a-st-discovery/tools/rt-thread-shell.py new file mode 100644 index 0000000000..b245d17c69 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-discovery/tools/rt-thread-shell.py @@ -0,0 +1,26 @@ +import os +import time + +def main(): + if (os.path.exists("/tmp/RT-Thread-STM32MP1_CM4.elf")): + os.system("mv /tmp/RT-Thread-STM32MP1_CM4.elf /lib/firmware/") + os.system("echo stop > /sys/class/remoteproc/remoteproc0/state") + os.system("echo RT-Thread-STM32MP1_CM4.elf > /sys/class/remoteproc/remoteproc0/firmware") + os.system("echo start > /sys/class/remoteproc/remoteproc0/state") + os.system("stty -onlcr -echo -F /dev/ttyRPMSG0") + os.system("cat /dev/ttyRPMSG0 &") + time.sleep(1) + print("\nYou can input \"exit\" to quit rt-thread shell!\n") + os.system("echo version >/dev/ttyRPMSG0") + + while True: + a = input() + if a == "exit": + os.system("echo stop > /sys/class/remoteproc/remoteproc0/state") + return + + os.system("echo {0} >/dev/ttyRPMSG0".format(a)) + + +if __name__ == "__main__": + main() diff --git a/bsp/stm32/stm32mp157a-st-ev1/.config b/bsp/stm32/stm32mp157a-st-ev1/.config index 4f6a2ab164..8886fca66a 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/.config +++ b/bsp/stm32/stm32mp157a-st-ev1/.config @@ -422,12 +422,14 @@ CONFIG_SOC_STM32MP157A=y # Onboard Peripheral Drivers # CONFIG_BSP_USING_STLINK_TO_USART=y +# CONFIG_BSP_USING_PMIC is not set +# CONFIG_BSP_USING_NAND is not set +# CONFIG_BSP_USING_OPENAMP is not set # # On-chip Peripheral Drivers # CONFIG_BSP_USING_GPIO=y -# CONFIG_BSP_USING_WWDG is not set CONFIG_BSP_USING_UART=y # CONFIG_BSP_USING_UART3 is not set # CONFIG_BSP_UART3_RX_USING_DMA is not set @@ -435,11 +437,10 @@ CONFIG_BSP_USING_UART4=y # CONFIG_BSP_UART4_RX_USING_DMA is not set # CONFIG_BSP_UART4_TX_USING_DMA is not set # CONFIG_BSP_USING_TIM is not set -# CONFIG_BSP_USING_LPTIM is not set # CONFIG_BSP_USING_PWM is not set # CONFIG_BSP_USING_ADC is not set # CONFIG_BSP_USING_DAC is not set -# CONFIG_BSP_USING_I2C1 is not set +# CONFIG_BSP_USING_I2C is not set # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_CRC is not set # CONFIG_BSP_USING_RNG is not set diff --git a/bsp/stm32/stm32mp157a-st-ev1/.cproject b/bsp/stm32/stm32mp157a-st-ev1/.cproject index 942edf4226..f21f6d8902 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/.cproject +++ b/bsp/stm32/stm32mp157a-st-ev1/.cproject @@ -67,15 +67,14 @@ <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board/CubeMX_Config/CM4/Inc}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board/ports}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/HAL_Drivers/config}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/HAL_Drivers}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Core/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Inc}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/HAL_Drivers/config}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/HAL_Drivers}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Core/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Inc}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/include}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/finsh}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/libc/compilers/newlib}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/include}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/libcpu/arm/common}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/libcpu/arm/cortex-m4}"" /> @@ -159,15 +158,14 @@ <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board/CubeMX_Config/CM4/Inc}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board/ports}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//board}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/HAL_Drivers/config}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/HAL_Drivers}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Core/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/CMSIS/Include}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Inc}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/HAL_Drivers/config}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/HAL_Drivers}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Core/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Include}"" /> + <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Inc}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/include}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/finsh}"" /> - <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/libc/compilers/newlib}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/include}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/libcpu/arm/common}"" /> <listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/libcpu/arm/cortex-m4}"" /> @@ -180,7 +178,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="//board/CubeMX_Config/CM4/Src/main.c|//board/CubeMX_Config/CM4/Src/stm32mp1xx_it.c|//board/ports|//libraries/HAL_Drivers/drv_adc.c|//libraries/HAL_Drivers/drv_can.c|//libraries/HAL_Drivers/drv_crypto.c|//libraries/HAL_Drivers/drv_dac.c|//libraries/HAL_Drivers/drv_eth.c|//libraries/HAL_Drivers/drv_flash|//libraries/HAL_Drivers/drv_hwtimer.c|//libraries/HAL_Drivers/drv_lcd.c|//libraries/HAL_Drivers/drv_lcd_mipi.c|//libraries/HAL_Drivers/drv_lptim.c|//libraries/HAL_Drivers/drv_pm.c|//libraries/HAL_Drivers/drv_pulse_encoder.c|//libraries/HAL_Drivers/drv_pwm.c|//libraries/HAL_Drivers/drv_qspi.c|//libraries/HAL_Drivers/drv_rtc.c|//libraries/HAL_Drivers/drv_sdio.c|//libraries/HAL_Drivers/drv_sdram.c|//libraries/HAL_Drivers/drv_soft_i2c.c|//libraries/HAL_Drivers/drv_spi.c|//libraries/HAL_Drivers/drv_usbd.c|//libraries/HAL_Drivers/drv_usbh.c|//libraries/HAL_Drivers/drv_wdt.c|//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/arm|//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/iar|//libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/system_stm32mp1xx.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cec.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_crc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_crc_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cryp.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cryp_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dcmi.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_fdcan.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_hash.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_hash_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_lptim.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_mdios.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_msp_template.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_qspi.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rng.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rtc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rtc_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_smbus.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spdifrx.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spi_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sram.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_timebase_tim_template.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_usart.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_usart_ex.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_wwdg.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_adc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_delayblock.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_dma.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_exti.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_fmc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_gpio.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_i2c.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_lptim.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_pwr.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_rcc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_rtc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_sdmmc.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_spi.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_tim.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_usart.c|//libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_utils.c|//rt-thread/components/cplusplus|//rt-thread/components/dfs|//rt-thread/components/drivers/audio|//rt-thread/components/drivers/can|//rt-thread/components/drivers/cputime|//rt-thread/components/drivers/hwcrypto|//rt-thread/components/drivers/hwtimer|//rt-thread/components/drivers/i2c|//rt-thread/components/drivers/misc/adc.c|//rt-thread/components/drivers/misc/dac.c|//rt-thread/components/drivers/misc/pulse_encoder.c|//rt-thread/components/drivers/misc/rt_drv_pwm.c|//rt-thread/components/drivers/misc/rt_inputcapture.c|//rt-thread/components/drivers/mtd|//rt-thread/components/drivers/pm|//rt-thread/components/drivers/rtc|//rt-thread/components/drivers/sdio|//rt-thread/components/drivers/sensors|//rt-thread/components/drivers/spi|//rt-thread/components/drivers/touch|//rt-thread/components/drivers/usb|//rt-thread/components/drivers/watchdog|//rt-thread/components/drivers/wlan|//rt-thread/components/finsh/msh_file.c|//rt-thread/components/finsh/symbol.c|//rt-thread/components/libc/aio|//rt-thread/components/libc/compilers/armlibc|//rt-thread/components/libc/compilers/common|//rt-thread/components/libc/compilers/dlib|//rt-thread/components/libc/compilers/minilibc|//rt-thread/components/libc/libdl|//rt-thread/components/libc/mmap|//rt-thread/components/libc/pthreads|//rt-thread/components/libc/signal|//rt-thread/components/libc/termios|//rt-thread/components/libc/time|//rt-thread/components/lwp|//rt-thread/components/net|//rt-thread/components/utilities|//rt-thread/components/vbus|//rt-thread/components/vmm|//rt-thread/libcpu/arm/AT91SAM7S|//rt-thread/libcpu/arm/AT91SAM7X|//rt-thread/libcpu/arm/am335x|//rt-thread/libcpu/arm/arm926|//rt-thread/libcpu/arm/armv6|//rt-thread/libcpu/arm/common/divsi3.S|//rt-thread/libcpu/arm/cortex-a|//rt-thread/libcpu/arm/cortex-m0|//rt-thread/libcpu/arm/cortex-m23|//rt-thread/libcpu/arm/cortex-m3|//rt-thread/libcpu/arm/cortex-m33|//rt-thread/libcpu/arm/cortex-m4/context_iar.S|//rt-thread/libcpu/arm/cortex-m4/context_rvds.S|//rt-thread/libcpu/arm/cortex-m7|//rt-thread/libcpu/arm/cortex-r4|//rt-thread/libcpu/arm/dm36x|//rt-thread/libcpu/arm/lpc214x|//rt-thread/libcpu/arm/lpc24xx|//rt-thread/libcpu/arm/realview-a8-vmm|//rt-thread/libcpu/arm/s3c24x0|//rt-thread/libcpu/arm/s3c44b0|//rt-thread/libcpu/arm/sep4020|//rt-thread/libcpu/arm/zynq7000|//rt-thread/src/cpu.c|//rt-thread/src/mem.c|//rt-thread/src/slab.c|//rt-thread/tools" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" /> + <entry excluding="//board/CubeMX_Config/CM4/Src/main.c|//board/CubeMX_Config/CM4/Src/mbox_ipcc.c|//board/CubeMX_Config/CM4/Src/openamp.c|//board/CubeMX_Config/CM4/Src/openamp_log.c|//board/CubeMX_Config/CM4/Src/rsc_table.c|//board/CubeMX_Config/CM4/Src/stm32mp1xx_it.c|//board/ports|//rt-thread/bsp/CME_M7|//rt-thread/bsp/allwinner_tina|//rt-thread/bsp/amebaz|//rt-thread/bsp/apollo2|//rt-thread/bsp/asm9260t|//rt-thread/bsp/at32|//rt-thread/bsp/at91sam9260|//rt-thread/bsp/at91sam9g45|//rt-thread/bsp/avr32uc3b0|//rt-thread/bsp/beaglebone|//rt-thread/bsp/bf533|//rt-thread/bsp/ck802|//rt-thread/bsp/cypress|//rt-thread/bsp/dm365|//rt-thread/bsp/efm32|//rt-thread/bsp/essemi|//rt-thread/bsp/fh8620|//rt-thread/bsp/frdm-k64f|//rt-thread/bsp/gd32303e-eval|//rt-thread/bsp/gd32450z-eval|//rt-thread/bsp/gd32e230k-start|//rt-thread/bsp/gd32vf103v-eval|//rt-thread/bsp/gkipc|//rt-thread/bsp/hifive1|//rt-thread/bsp/imx6sx|//rt-thread/bsp/imx6ul|//rt-thread/bsp/imxrt|//rt-thread/bsp/k210|//rt-thread/bsp/lm3s8962|//rt-thread/bsp/lm3s9b9x|//rt-thread/bsp/lm4f232|//rt-thread/bsp/lpc1114|//rt-thread/bsp/lpc176x|//rt-thread/bsp/lpc178x|//rt-thread/bsp/lpc2148|//rt-thread/bsp/lpc2478|//rt-thread/bsp/lpc408x|//rt-thread/bsp/lpc43xx|//rt-thread/bsp/lpc5410x|//rt-thread/bsp/lpc54114-lite|//rt-thread/bsp/lpc54608-LPCXpresso|//rt-thread/bsp/lpc55sxx|//rt-thread/bsp/lpc824|//rt-thread/bsp/ls1bdev|//rt-thread/bsp/ls1cdev|//rt-thread/bsp/ls2kdev|//rt-thread/bsp/m16c62p|//rt-thread/bsp/mb9bf500r|//rt-thread/bsp/mb9bf506r|//rt-thread/bsp/mb9bf568r|//rt-thread/bsp/mb9bf618s|//rt-thread/bsp/microblaze|//rt-thread/bsp/mini2440|//rt-thread/bsp/mini4020|//rt-thread/bsp/mipssim|//rt-thread/bsp/mm32l07x|//rt-thread/bsp/mm32l3xx|//rt-thread/bsp/nios_ii|//rt-thread/bsp/nrf51822|//rt-thread/bsp/nrf52832|//rt-thread/bsp/nrf5x|//rt-thread/bsp/nuclei|//rt-thread/bsp/nuvoton|//rt-thread/bsp/nv32f100x|//rt-thread/bsp/pic32ethernet|//rt-thread/bsp/qemu-vexpress-a9|//rt-thread/bsp/qemu-vexpress-gemini|//rt-thread/bsp/raspberry-pi|//rt-thread/bsp/realview-a8|//rt-thread/bsp/rm48x50|//rt-thread/bsp/rv32m1_vega|//rt-thread/bsp/rx|//rt-thread/bsp/sam7x|//rt-thread/bsp/samd21|//rt-thread/bsp/sep6200|//rt-thread/bsp/simulator|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_adc.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_can.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_crypto.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_dac.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_eth.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_flash|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_hwtimer.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_lcd_mipi.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_lptim.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_pm.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_pulse_encoder.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_pwm.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_qspi.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_rtc.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_sdio.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_sdram.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_soft_i2c.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_spi.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_usbd.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_usbh.c|//rt-thread/bsp/stm32/libraries/HAL_Drivers/drv_wdt.c|//rt-thread/bsp/stm32/libraries/STM32F0xx_HAL|//rt-thread/bsp/stm32/libraries/STM32F1xx_HAL|//rt-thread/bsp/stm32/libraries/STM32F2xx_HAL|//rt-thread/bsp/stm32/libraries/STM32F4xx_HAL|//rt-thread/bsp/stm32/libraries/STM32F7xx_HAL|//rt-thread/bsp/stm32/libraries/STM32G0xx_HAL|//rt-thread/bsp/stm32/libraries/STM32G4xx_HAL|//rt-thread/bsp/stm32/libraries/STM32H7xx_HAL|//rt-thread/bsp/stm32/libraries/STM32L0xx_HAL|//rt-thread/bsp/stm32/libraries/STM32L1xx_HAL|//rt-thread/bsp/stm32/libraries/STM32L4xx_HAL|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/arm|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/iar|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/CMSIS/Device/ST/STM32MP1xx/Source/Templates/system_stm32mp1xx.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cec.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_crc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_crc_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cryp.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_cryp_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dcmi.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dfsdm_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_fdcan.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_hash.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_hash_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_lptim.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_mdios.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_msp_template.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_qspi.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rng.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rtc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_rtc_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sai_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_smbus.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spdifrx.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_spi_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sram.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_timebase_tim_template.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_usart.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_usart_ex.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_wwdg.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_adc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_delayblock.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_dma.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_exti.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_fmc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_gpio.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_i2c.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_lptim.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_pwr.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_rcc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_rtc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_sdmmc.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_spi.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_tim.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_usart.c|//rt-thread/bsp/stm32/libraries/STM32MPxx_HAL/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_utils.c|//rt-thread/bsp/stm32/libraries/templates|//rt-thread/bsp/stm32/stm32f072-st-nucleo|//rt-thread/bsp/stm32/stm32f091-st-nucleo|//rt-thread/bsp/stm32/stm32f103-atk-nano|//rt-thread/bsp/stm32/stm32f103-atk-warshipv3|//rt-thread/bsp/stm32/stm32f103-dofly-M3S|//rt-thread/bsp/stm32/stm32f103-dofly-lyc8|//rt-thread/bsp/stm32/stm32f103-fire-arbitrary|//rt-thread/bsp/stm32/stm32f103-gizwits-gokitv21|//rt-thread/bsp/stm32/stm32f103-hw100k-ibox|//rt-thread/bsp/stm32/stm32f103-mini-system|//rt-thread/bsp/stm32/stm32f103-onenet-nbiot|//rt-thread/bsp/stm32/stm32f103-yf-ufun|//rt-thread/bsp/stm32/stm32f107-uc-eval|//rt-thread/bsp/stm32/stm32f401-st-nucleo|//rt-thread/bsp/stm32/stm32f405-smdz-breadfruit|//rt-thread/bsp/stm32/stm32f407-atk-explorer|//rt-thread/bsp/stm32/stm32f407-st-discovery|//rt-thread/bsp/stm32/stm32f410-st-nucleo|//rt-thread/bsp/stm32/stm32f411-atk-nano|//rt-thread/bsp/stm32/stm32f411-st-nucleo|//rt-thread/bsp/stm32/stm32f411-weact-MiniF4|//rt-thread/bsp/stm32/stm32f412-st-nucleo|//rt-thread/bsp/stm32/stm32f413-st-nucleo|//rt-thread/bsp/stm32/stm32f427-robomaster-a|//rt-thread/bsp/stm32/stm32f429-armfly-v6|//rt-thread/bsp/stm32/stm32f429-atk-apollo|//rt-thread/bsp/stm32/stm32f429-fire-challenger|//rt-thread/bsp/stm32/stm32f429-st-disco|//rt-thread/bsp/stm32/stm32f446-st-nucleo|//rt-thread/bsp/stm32/stm32f469-st-disco|//rt-thread/bsp/stm32/stm32f746-st-disco|//rt-thread/bsp/stm32/stm32f767-atk-apollo|//rt-thread/bsp/stm32/stm32f767-fire-challenger|//rt-thread/bsp/stm32/stm32f767-st-nucleo|//rt-thread/bsp/stm32/stm32f769-st-disco|//rt-thread/bsp/stm32/stm32g070-st-nucleo|//rt-thread/bsp/stm32/stm32g071-st-nucleo|//rt-thread/bsp/stm32/stm32g431-st-nucleo|//rt-thread/bsp/stm32/stm32h743-atk-apollo|//rt-thread/bsp/stm32/stm32h743-st-nucleo|//rt-thread/bsp/stm32/stm32h747-st-discovery|//rt-thread/bsp/stm32/stm32h750-armfly-h7-tool|//rt-thread/bsp/stm32/stm32l010-st-nucleo|//rt-thread/bsp/stm32/stm32l053-st-nucleo|//rt-thread/bsp/stm32/stm32l412-st-nucleo|//rt-thread/bsp/stm32/stm32l432-st-nucleo|//rt-thread/bsp/stm32/stm32l433-st-nucleo|//rt-thread/bsp/stm32/stm32l452-st-nucleo|//rt-thread/bsp/stm32/stm32l475-atk-pandora|//rt-thread/bsp/stm32/stm32l475-st-discovery|//rt-thread/bsp/stm32/stm32l476-st-nucleo|//rt-thread/bsp/stm32/stm32l496-ali-developer|//rt-thread/bsp/stm32/stm32l496-st-nucleo|//rt-thread/bsp/stm32/stm32l4r5-st-nucleo|//rt-thread/bsp/stm32/stm32l4r9-st-eval|//rt-thread/bsp/stm32/stm32mp157a-st-discovery|//rt-thread/bsp/stm32f20x|//rt-thread/bsp/swm320-lq100|//rt-thread/bsp/synopsys|//rt-thread/bsp/taihu|//rt-thread/bsp/tm4c123bsp|//rt-thread/bsp/tm4c129x|//rt-thread/bsp/tms320f28379d|//rt-thread/bsp/upd70f3454|//rt-thread/bsp/w60x|//rt-thread/bsp/wh44b0|//rt-thread/bsp/x86|//rt-thread/bsp/xplorer4330|//rt-thread/bsp/zynq7000|//rt-thread/components/cplusplus|//rt-thread/components/dfs|//rt-thread/components/drivers/audio|//rt-thread/components/drivers/can|//rt-thread/components/drivers/cputime|//rt-thread/components/drivers/hwcrypto|//rt-thread/components/drivers/hwtimer|//rt-thread/components/drivers/i2c|//rt-thread/components/drivers/misc/adc.c|//rt-thread/components/drivers/misc/dac.c|//rt-thread/components/drivers/misc/pulse_encoder.c|//rt-thread/components/drivers/misc/rt_drv_pwm.c|//rt-thread/components/drivers/misc/rt_inputcapture.c|//rt-thread/components/drivers/mtd|//rt-thread/components/drivers/pm|//rt-thread/components/drivers/rtc|//rt-thread/components/drivers/sdio|//rt-thread/components/drivers/sensors|//rt-thread/components/drivers/spi|//rt-thread/components/drivers/touch|//rt-thread/components/drivers/usb|//rt-thread/components/drivers/watchdog|//rt-thread/components/drivers/wlan|//rt-thread/components/finsh/msh_file.c|//rt-thread/components/finsh/symbol.c|//rt-thread/components/libc|//rt-thread/components/lwp|//rt-thread/components/net|//rt-thread/components/utilities|//rt-thread/components/vbus|//rt-thread/components/vmm|//rt-thread/examples|//rt-thread/libcpu/aarch64|//rt-thread/libcpu/arc|//rt-thread/libcpu/arm/AT91SAM7S|//rt-thread/libcpu/arm/AT91SAM7X|//rt-thread/libcpu/arm/am335x|//rt-thread/libcpu/arm/arm926|//rt-thread/libcpu/arm/armv6|//rt-thread/libcpu/arm/common/divsi3.S|//rt-thread/libcpu/arm/cortex-a|//rt-thread/libcpu/arm/cortex-m0|//rt-thread/libcpu/arm/cortex-m23|//rt-thread/libcpu/arm/cortex-m3|//rt-thread/libcpu/arm/cortex-m33|//rt-thread/libcpu/arm/cortex-m4/context_iar.S|//rt-thread/libcpu/arm/cortex-m4/context_rvds.S|//rt-thread/libcpu/arm/cortex-m7|//rt-thread/libcpu/arm/cortex-r4|//rt-thread/libcpu/arm/dm36x|//rt-thread/libcpu/arm/lpc214x|//rt-thread/libcpu/arm/lpc24xx|//rt-thread/libcpu/arm/realview-a8-vmm|//rt-thread/libcpu/arm/s3c24x0|//rt-thread/libcpu/arm/s3c44b0|//rt-thread/libcpu/arm/sep4020|//rt-thread/libcpu/arm/zynq7000|//rt-thread/libcpu/avr32|//rt-thread/libcpu/blackfin|//rt-thread/libcpu/c-sky|//rt-thread/libcpu/ia32|//rt-thread/libcpu/m16c|//rt-thread/libcpu/mips|//rt-thread/libcpu/nios|//rt-thread/libcpu/ppc|//rt-thread/libcpu/risc-v|//rt-thread/libcpu/rx|//rt-thread/libcpu/sim|//rt-thread/libcpu/ti-dsp|//rt-thread/libcpu/unicore32|//rt-thread/libcpu/v850|//rt-thread/libcpu/xilinx|//rt-thread/src/cpu.c|//rt-thread/src/mem.c|//rt-thread/src/slab.c|//rt-thread/tools" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" /> </sourceEntries> </configuration> </storageModule> diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/ipcc.h b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/ipcc.h new file mode 100644 index 0000000000..3f07bf7536 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/ipcc.h @@ -0,0 +1,58 @@ +/** + ****************************************************************************** + * File Name : IPCC.h + * Description : This file provides code for the configuration + * of the IPCC instances. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.</center></h2> + * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __ipcc_H +#define __ipcc_H +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +extern IPCC_HandleTypeDef hipcc; + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_IPCC_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif +#endif /*__ ipcc_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/mbox_ipcc.h b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/mbox_ipcc.h new file mode 100644 index 0000000000..0e605cc919 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/mbox_ipcc.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * @file mbox_ipcc.h + * @author MCD Application Team + * @brief Header for mbox_ipcc.c module + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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_ + +/* 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_Notify(void *priv, uint32_t id); +int MAILBOX_Init(void); +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 /* MBOX_IPCC_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp.h b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp.h new file mode 100644 index 0000000000..3589f3bdd1 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp.h @@ -0,0 +1,58 @@ +/** + ****************************************************************************** + * @file openamp.h + * @brief Header for openamp applications + * @author MCD Application Team + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 __cplusplus + extern "C" { +#endif + +#include "openamp/open_amp.h" +#include "openamp_conf.h" + +#define OPENAMP_send rpmsg_send +#define OPENAMP_destroy_ept rpmsg_destroy_ept + +/* Initialize the openamp framework*/ +int MX_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 /*__openamp_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp_conf.h b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp_conf.h new file mode 100644 index 0000000000..e6c32798dd --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp_conf.h @@ -0,0 +1,242 @@ +/** + ****************************************************************************** + * @file openamp_conf.h + * @author MCD Application Team + * @brief Configuration file for OpenAMP MW + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 __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 */ + + /* ########################## Linux Master Selection ############################## */ + /** + * @brief Due to Linux compatibility, it's important to distinguish if the MASTER is Linux or not. + * In that case, the LINUX_RPROC_MASTER define is required + */ +#define LINUX_RPROC_MASTER + +/* 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 LINUX_RPROC_MASTER +#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 0x10040000 /* allocated by Master processor: CA7 */ +#define VRING_TX_ADDRESS 0x10040400 /* allocated by Master processor: CA7 */ +#define VRING_BUFF_ADDRESS 0x10040800 /* allocated by Master processor: CA7 */ +#define VRING_ALIGNMENT 16 /* fixed to match with 4k page alignement requested by linux */ +#define VRING_NUM_BUFFS 16 /* number of rpmsg buffer */ +#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 /* __OPENAMP_CONF__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp_log.h b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp_log.h new file mode 100644 index 0000000000..60c3f2af58 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/openamp_log.h @@ -0,0 +1,134 @@ +/** + ****************************************************************************** + * @file log.h + * @author MCD Application Team + * @brief logging services + ****************************************************************************** + * + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32MP1xx_Log_Includes + * @{ + */ +#include "stm32mp1xx_hal.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 /*__LOG_STM32MP1XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/rsc_table.h b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/rsc_table.h new file mode 100644 index 0000000000..aaf818355c --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/rsc_table.h @@ -0,0 +1,43 @@ +/* + * 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_ + +#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 /* RSC_TABLE_H_ */ + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/mbox_ipcc.c b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/mbox_ipcc.c new file mode 100644 index 0000000000..475f3a22cf --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/mbox_ipcc.c @@ -0,0 +1,182 @@ +/** + ****************************************************************************** + * @file mbox_ipcc.c + * @author MCD Application Team + * @brief This file provides code for the configuration + * of the mailbox_ipcc_if.c MiddleWare. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 + * + ****************************************************************************** + */ + +/* + * Channel direction and usage: + * + * ======== <-- new msg ---=============--------<------ ======= + * || || || CHANNEL 1 || || || + * || A7 || ------->-------=============--- buf free--> || M4 || + * || || || || + * ||master|| <-- buf free---=============--------<------ ||slave|| + * || || || CHANNEL 2 || || || + * ======== ------->-------=============----new msg --> ======= + */ + +/* Includes ------------------------------------------------------------------*/ +#include "openamp/open_amp.h" +#include "stm32mp1xx_hal.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 */ + +/* 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) +{ + + if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_1, IPCC_CHANNEL_DIR_RX, + IPCC_channel1_callback) != HAL_OK) { + OPENAMP_log_err("%s: ch_1 RX fail\n", __func__); + return -1; + } + + if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_2, IPCC_CHANNEL_DIR_RX, + IPCC_channel2_callback) != HAL_OK) { + OPENAMP_log_err("%s: ch_2 RX fail\n", __func__); + 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; + OPENAMP_log_dbg("Send msg on ch_1\r\n"); + } + else if (id == VRING1_ID) { + /* Note: the OpenAMP framework never notifies this */ + channel = IPCC_CHANNEL_2; + OPENAMP_log_dbg("Send 'buff free' on ch_2\r\n"); + } + else { + OPENAMP_log_err("invalid vring (%d)\r\n", (int)id); + 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) { + OPENAMP_log_dbg("Waiting for channel to be freed\r\n"); + 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 */ + OPENAMP_log_dbg("Ack 'buff free' message on ch1\r\n"); + 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); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/openamp.c b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/openamp.c new file mode 100644 index 0000000000..08ef2d4c02 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/openamp.c @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file openamp.c + * @author MCD Application Team + * @brief Code for openamp applications + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 + * + ****************************************************************************** + */ + +#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 MX_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); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/openamp_log.c b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/openamp_log.c new file mode 100644 index 0000000000..7ce1ba6a2a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/openamp_log.c @@ -0,0 +1,102 @@ +/** + ****************************************************************************** + * @file log.c + * @author MCD Application Team + * @brief Ressource table + * + * This file provides services for logging + * + ****************************************************************************** + * + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 + * @{ + */ + +/** @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 + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/rsc_table.c b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/rsc_table.c new file mode 100644 index 0000000000..581636ddca --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/rsc_table.c @@ -0,0 +1,174 @@ +/** + ****************************************************************************** + * @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 + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 RSC_TABLE + * @{ + */ + +/** @addtogroup resource_table + * @{ + */ + +/** @addtogroup resource_table_Private_Includes + * @{ + */ + +#if defined(__ICCARM__) || defined (__CC_ARM) +#include <stddef.h> /* 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 (LINUX_RPROC_MASTER) + #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 (LINUX_RPROC_MASTER) + +/* 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 (LINUX_RPROC_MASTER) + .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 (LINUX_RPROC_MASTER) +#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/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c index 9361ca70b1..5e6a4a3d34 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c @@ -73,7 +73,14 @@ void HAL_MspInit(void) /* System interrupt init*/ /* USER CODE BEGIN MspInit 1 */ - +#if !defined(BSP_USING_OPENAMP) + __HAL_RCC_SYSRAM_CLK_ENABLE(); + __HAL_RCC_RETRAM_CLK_ENABLE(); +#endif + + HAL_NVIC_SetPriority(RCC_WAKEUP_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(RCC_WAKEUP_IRQn); + __HAL_RCC_ENABLE_IT(RCC_IT_WKUP); /* USER CODE END MspInit 1 */ } diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/Kconfig b/bsp/stm32/stm32mp157a-st-ev1/board/Kconfig index 10a58a6b8b..e52a1601fe 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/Kconfig +++ b/bsp/stm32/stm32mp157a-st-ev1/board/Kconfig @@ -28,6 +28,11 @@ menu "Onboard Peripheral Drivers" select RT_MTD_NAND_DEBUG default n + config BSP_USING_OPENAMP + bool "Enable OpenAMP" + select RT_USING_OPENAMP + default n + endmenu menu "On-chip Peripheral Drivers" diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/SConscript b/bsp/stm32/stm32mp157a-st-ev1/board/SConscript index 29b406616d..15e6070c81 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/SConscript +++ b/bsp/stm32/stm32mp157a-st-ev1/board/SConscript @@ -19,10 +19,32 @@ if GetDepend(['BSP_USING_PMIC']): if GetDepend(['BSP_USING_NAND']): src += Glob('ports/drv_nand.c') +if GetDepend(['BSP_USING_OPENAMP']): + src += Glob('CubeMX_Config/CM4/Src/ipcc.c') + src += Glob('CubeMX_Config/CM4/Src/openamp.c') + src += Glob('CubeMX_Config/CM4/Src/openamp_log.c') + src += Glob('CubeMX_Config/CM4/Src/mbox_ipcc.c') + src += Glob('CubeMX_Config/CM4/Src/rsc_table.c') + src += Glob('ports/OpenAMP/libmetal/lib/*.c') + src += Glob('ports/OpenAMP/libmetal/lib/system/generic/*.c') + src += Glob('ports/OpenAMP/libmetal/lib/system/generic/cortexm/*.c') + src += Glob('ports/OpenAMP/open-amp/lib/rpmsg/*.c') + src += Glob('ports/OpenAMP/open-amp/lib/remoteproc/*.c') + src += Glob('ports/OpenAMP/open-amp/lib/virtio/*.c') + src += Glob('ports/OpenAMP/virtual_driver/*.c') + src += Glob('ports/OpenAMP/drv_openamp.c') + path = [cwd] path += [cwd + '/CubeMX_Config/CM4/Inc'] path += [cwd + '/ports'] +if GetDepend(['BSP_USING_OPENAMP']): + path += [cwd + '/ports/OpenAMP'] + path += [cwd + '/ports/OpenAMP/open-amp/lib/include'] + path += [cwd + '/ports/OpenAMP/libmetal/lib/include'] + path += [cwd + '/ports/OpenAMP/virtual_driver'] + path += [cwd + '/CubeMX_Config/CM4/Inc'] + startup_path_prefix = SDK_LIB if rtconfig.CROSS_TOOL == 'gcc': @@ -34,7 +56,7 @@ elif rtconfig.CROSS_TOOL == 'iar': src = list(set(src)) -CPPDEFINES = ['CORE_CM4', 'STM32MP157Axx', 'USE_HAL_DRIVER'] +CPPDEFINES = ['CORE_CM4','NO_ATOMIC_64_SUPPORT','METAL_INTERNAL','METAL_MAX_DEVICE_REGIONS=2','VIRTIO_SLAVE_ONLY','STM32MP157Axx','__LOG_TRACE_IO_'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/board.h b/bsp/stm32/stm32mp157a-st-ev1/board/board.h index b23b83ee30..84e097714a 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/board.h +++ b/bsp/stm32/stm32mp157a-st-ev1/board/board.h @@ -22,25 +22,25 @@ extern "C" { #endif -#define STM32_FLASH_START_ADRESS ((uint32_t)0x10000000) -#define STM32_FLASH_SIZE (256 * 1024) +#define STM32_FLASH_START_ADRESS ((uint32_t)0x10000000) +#if defined(BSP_USING_OPENAMP) +#define STM32_FLASH_SIZE (64 * 1024) +#else +#define STM32_FLASH_SIZE (256 * 1024) +#endif #define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE)) -#define STM32_SRAM_SIZE (128) -#define STM32_SRAM_END ((uint32_t)0x10040000 + (STM32_SRAM_SIZE * 1024)) - -#if defined(__CC_ARM) || defined(__CLANG_ARM) -extern int Image$$RW_IRAM1$$ZI$$Limit; -#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) -#elif __ICCARM__ -#pragma section="CSTACK" -#define HEAP_BEGIN (__segment_end("CSTACK")) + +#if defined(BSP_USING_OPENAMP) +#define STM32_SRAM_BEGIN (uint32_t)0x10020000 #else -extern int __bss_end__; -#define HEAP_BEGIN (0x10040000 + 64 * 1024) +#define STM32_SRAM_BEGIN (uint32_t)0x2FFF0000 #endif +#define STM32_SRAM_SIZE (64) +#define STM32_SRAM_END (STM32_SRAM_BEGIN + (STM32_SRAM_SIZE * 1024)) -#define HEAP_END STM32_SRAM_END +#define HEAP_BEGIN STM32_SRAM_BEGIN +#define HEAP_END STM32_SRAM_END void SystemClock_Config(void); diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/linker_scripts/link.icf b/bsp/stm32/stm32mp157a-st-ev1/board/linker_scripts/link.icf index 9aa4aad24e..ee4ff6ade6 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/linker_scripts/link.icf +++ b/bsp/stm32/stm32mp157a-st-ev1/board/linker_scripts/link.icf @@ -4,33 +4,42 @@ /*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
-define symbol __ICFEDIT_region_ROM_start__ = 0x10000000;
-define symbol __ICFEDIT_region_ROM_end__ = 0x1003FFFF;
-define symbol __ICFEDIT_region_RAM_start__ = 0x10050000;
-define symbol __ICFEDIT_region_RAM_end__ = 0x1005FFFF;
-
+define symbol __ICFEDIT_region_text_start__ = 0x10000000;
+define symbol __ICFEDIT_region_text_end__ = 0x1001FFFF;
+define symbol __ICFEDIT_region_data_start__ = 0x10030000;
+define symbol __ICFEDIT_region_data_end__ = 0x1003FFFF;
/*-Sizes-*/
-define symbol __ICFEDIT_size_cstack__ = 0x0400;
-define symbol __ICFEDIT_size_heap__ = 0x0000;
+define symbol __ICFEDIT_size_cstack__ = 0x400;
+define symbol __ICFEDIT_size_heap__ = 0x000;
/**** End of ICF editor section. ###ICF###*/
-define memory mem with size = 4G;
-define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
-define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
-define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define memory mem with size = 4G;
+define region text_region = mem:[from __ICFEDIT_region_text_start__ to __ICFEDIT_region_text_end__];
+define region data_region = mem:[from __ICFEDIT_region_data_start__ to __ICFEDIT_region_data_end__];
-initialize by copy { readwrite };
-do not initialize { section .noinit };
+keep { section .resource_table };
+".resource_table" : place in data_region {section .resource_table};
/* Create region for OPENAMP */
/* !!! These 4 lines can be commented if OPENAMP is not used !!!*/
-define symbol __OPENAMP_region_start__ = 0x10040000;
+define symbol __OPENAMP_region_start__ = 0x10040000;
define symbol __OPENAMP_region_size__ = 0x8000;
export symbol __OPENAMP_region_start__;
export symbol __OPENAMP_region_size__;
-place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+define symbol __SDMMC_region_start__ = 0x10048000;
+define symbol __SDMMC_region_size__ = 0x1FFFF;
+export symbol __SDMMC_region_start__;
+export symbol __SDMMC_region_size__;
-place in ROM_region { readonly };
-place in RAM_region { readwrite, last block CSTACK};
\ No newline at end of file +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+initialize by copy { readwrite };
+do not initialize { section .noinit};
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+place in text_region { readonly };
+place in data_region { readwrite,
+ block CSTACK, block HEAP};
diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/drv_openamp.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/drv_openamp.c new file mode 100644 index 0000000000..2705f068a3 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/drv_openamp.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-24 thread-liu first version + */ + +#include <board.h> + +#ifdef BSP_USING_OPENAMP + +#include <drv_openamp.h> +#include <openamp.h> +#include <virt_uart.h> +#include <openamp/rpmsg_virtio.h> + +//#define DRV_DEBUG +#define LOG_TAG "drv.openamp" +#include <drv_log.h> + +IPCC_HandleTypeDef hipcc; +static VIRT_UART_HandleTypeDef huart0; + +static rt_uint8_t rx_buffer[MAX_BUFFER_SIZE]; +static rt_uint8_t tx_buffer[MAX_BUFFER_SIZE]; + +struct rthw_openamp +{ + struct rt_device parent; + struct rt_openamp serial; + struct rt_semaphore sema; +}; +static struct rthw_openamp dev_openamp; + +void IPCC_RX1_IRQHandler(void) +{ + rt_interrupt_enter(); + + HAL_IPCC_RX_IRQHandler(&hipcc); + + rt_interrupt_leave(); +} + +void IPCC_TX1_IRQHandler(void) +{ + rt_interrupt_enter(); + + HAL_IPCC_TX_IRQHandler(&hipcc); + + rt_interrupt_leave(); +} + +void VIRT_UART0_RxCpltCallback(VIRT_UART_HandleTypeDef *huart) +{ + rt_uint16_t rx_size = 0, i = 0; + rt_size_t count, size, offset; + rt_uint8_t *buf = RT_NULL; + + struct rthw_openamp *device; + device = (struct rthw_openamp *)rt_device_find("openamp"); + RT_ASSERT(device != RT_NULL); + + buf = device->serial.rbuf; + count = device->serial.rbuf_count; + size = device->serial.rbuf_size; + offset = device->serial.rbuf_start + count; + + rt_sem_take(&device->sema, RT_WAITING_FOREVER); + + rx_size = (huart->RxXferSize < MAX_BUFFER_SIZE) ? huart->RxXferSize : MAX_BUFFER_SIZE - 1; + + if (count < size) + { + if (offset >= size) + { + offset -= size; + } + + for (i = 0; i < rx_size; i++) + { + buf[offset++] = huart->pRxBuffPtr[i]; + count++; + } + } + + device->serial.rbuf_count = count; + + rt_sem_release(&device->sema); +} + +static rt_err_t _init(struct rt_device *dev) +{ + struct rthw_openamp *device; + device = (struct rthw_openamp *)dev; + RT_ASSERT(device != RT_NULL); + + device->serial.rbuf_start = 0; + device->serial.rbuf_count = 0; + device->serial.tbuf_start = 0; + device->serial.tbuf_count = 0; + device->serial.rbuf_size = MAX_BUFFER_SIZE; + device->serial.tbuf_size = MAX_BUFFER_SIZE; + device->serial.rbuf = rx_buffer; + device->serial.tbuf = tx_buffer; + + if (rt_sem_init(&device->sema, "openamplock", 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + return RT_ERROR; + } + + return RT_EOK; +} + +static rt_size_t _read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_size_t count, rbsize, offset; + rt_uint8_t *buf = RT_NULL; + rt_uint8_t *pBuffer = RT_NULL; + rt_uint16_t i = 0; + + struct rthw_openamp *device; + device = (struct rthw_openamp *)dev; + RT_ASSERT(device != RT_NULL); + + pBuffer = (unsigned char*)buffer; + count = device->serial.rbuf_count; + buf = device->serial.rbuf; + + if (count == 0) + { + return -RT_ERROR; + } + + rt_sem_take(&device->sema, RT_WAITING_FOREVER); + + if (count >= size) + { + count = size; + } + + offset = device->serial.rbuf_start; + rbsize = device->serial.rbuf_size; + + for (i = 0; i < count; i++) + { + *pBuffer++ = buf[offset++]; + if (offset > rbsize) + { + offset = 0; + } + } + + device->serial.rbuf_start = offset; + device->serial.rbuf_count -= count; + + rt_sem_release(&device->sema); + + return count; +} + +static rt_size_t _write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_err_t result = VIRT_UART_OK; + + struct rthw_openamp *device; + device = (struct rthw_openamp *)dev; + RT_ASSERT(device != RT_NULL); + + rt_sem_take(&device->sema, RT_WAITING_FOREVER); + result = VIRT_UART_Transmit(&huart0, (uint8_t *)buffer, size); + rt_sem_release(&device->sema); + + if (result != VIRT_UART_OK) + { + return -RT_ERROR; + } + + return size; +} + +static rt_err_t rt_hw_openamp_register(struct rthw_openamp *openamp, const char *name, rt_uint32_t flag, void *data) +{ + struct rt_device *device; + RT_ASSERT(openamp != RT_NULL); + + device = &(openamp->parent); + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + + device->init = _init; + device->open = RT_NULL; + device->close = RT_NULL; + device->read = _read; + device->write = _write; + device->control = RT_NULL; + device->user_data = data; + + /* register a character device */ + return rt_device_register(device, name, flag); +} + +static int openamp_init(void) +{ + extern int MX_OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb); + + /* IPCC init */ + hipcc.Instance = IPCC; + if (HAL_IPCC_Init(&hipcc) != HAL_OK) + { + return RT_ERROR; + } + /* openamp slave device */ + MX_OPENAMP_Init(RPMSG_REMOTE, NULL); + + if (VIRT_UART_Init(&huart0) != VIRT_UART_OK) + { + return RT_ERROR; + } + if (VIRT_UART_RegisterCallback(&huart0, VIRT_UART_RXCPLT_CB_ID, VIRT_UART0_RxCpltCallback) != VIRT_UART_OK) + { + return RT_ERROR; + } + + return RT_EOK; +} + +int rt_hw_openamp_init(void) +{ + openamp_init(); + + rt_hw_openamp_register(&dev_openamp, "openamp", 0, NULL); + + rt_console_set_device("openamp"); + + return RT_EOK; +} +INIT_PREV_EXPORT(rt_hw_openamp_init); + +static void openamp_thread_entry(void *parameter) +{ + rt_size_t size = 0; + struct rthw_openamp *device = RT_NULL; + + device = (struct rthw_openamp *)rt_device_find("openamp"); + RT_ASSERT(device != RT_NULL); + + for (;;) + { + OPENAMP_check_for_message(); + + size = device->serial.rbuf_count; + if (size > 0) + { + if (device->parent.rx_indicate != RT_NULL) + { + device->parent.rx_indicate(&device->parent, size); + } + } + + rt_thread_mdelay(1); + } +} + +static int creat_openamp_thread(void) +{ + rt_thread_t tid = RT_NULL; + + tid = rt_thread_create("OpenAMP", + openamp_thread_entry, + RT_NULL, + OPENAMP_THREAD_STACK_SIZE, + OPENAMP_THREAD_PRIORITY, + OPENAMP_THREAD_TIMESLICE); + + if (tid == RT_NULL) + { + LOG_E("openamp thread create failed!"); + return RT_ERROR; + } + + rt_thread_startup(tid); + + return RT_EOK; +} +INIT_APP_EXPORT(creat_openamp_thread); + +#endif diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/drv_openamp.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/drv_openamp.h new file mode 100644 index 0000000000..df1533b38b --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/drv_openamp.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-24 thread-liu first version + */ + +#ifndef __DRV_OPENAMP_H__ +#define __DRV_OPENAMP_H__ + +#include "board.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct rt_openamp +{ + rt_uint8_t *rbuf; + rt_uint8_t *tbuf; + volatile rt_uint16_t rbuf_size; + volatile rt_uint16_t tbuf_size; + volatile rt_uint16_t rbuf_start; + volatile rt_uint16_t rbuf_count; + volatile rt_uint16_t tbuf_start; + volatile rt_uint16_t tbuf_count; +}; + +#define OPENAMP_THREAD_STACK_SIZE 512 +#define OPENAMP_THREAD_PRIORITY 5 +#define OPENAMP_THREAD_TIMESLICE 10 + +#define MAX_BUFFER_SIZE 256 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/dma.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/dma.c new file mode 100644 index 0000000000..baeb21bd2a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/dma.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/errno.h> +#include <string.h> +#include <metal/device.h> +#include <metal/log.h> +#include <metal/dma.h> +#include <metal/atomic.h> + +int metal_dma_map(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out) +{ + int nents_out; + + if (!dev || !sg_in || !sg_out) + return -EINVAL; + if (!dev->bus->ops.dev_dma_map) + return -ENODEV; + + /* memory barrier */ + if (dir == METAL_DMA_DEV_R) + /* If it is device read, apply memory write fence. */ + atomic_thread_fence(memory_order_release); + else + /* If it is device write or device r/w, + apply memory r/w fence. */ + atomic_thread_fence(memory_order_acq_rel); + nents_out = dev->bus->ops.dev_dma_map(dev->bus, + dev, dir, sg_in, nents_in, sg_out); + return nents_out; +} + +void metal_dma_unmap(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg, + int nents) +{ + /* memory barrier */ + if (dir == METAL_DMA_DEV_R) + /* If it is device read, apply memory write fence. */ + atomic_thread_fence(memory_order_release); + else + /* If it is device write or device r/w, + apply memory r/w fence. */ + atomic_thread_fence(memory_order_acq_rel); + + if (!dev || !dev->bus->ops.dev_dma_unmap || !sg) + return; + dev->bus->ops.dev_dma_unmap(dev->bus, + dev, dir, sg, nents); +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/alloc.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/alloc.h new file mode 100644 index 0000000000..0e2d070c9b --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/alloc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file alloc.h + * @brief Memory allocation handling primitives for libmetal. + */ + +#ifndef __METAL_ALLOC__H__ +#define __METAL_ALLOC__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup Memory Allocation Interfaces + * @{ */ + +/** + * @brief allocate requested memory size + * return a pointer to the allocated memory + * + * @param[in] size size in byte of requested memory + * @return memory pointer, or 0 if it failed to allocate + */ +static inline void *metal_allocate_memory(unsigned int size); + +/** + * @brief free the memory previously allocated + * + * @param[in] ptr pointer to memory + */ +static inline void metal_free_memory(void *ptr); + +#include <metal/system/generic/alloc.h> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_ALLOC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/assert.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/assert.h new file mode 100644 index 0000000000..4476b641ae --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/assert.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file assert.h + * @brief Assertion support. + */ + +#ifndef __METAL_ASSERT__H__ +#define __METAL_ASSERT__H__ + +#include <metal/system/generic/assert.h> + +/** + * @brief Assertion macro. + * @param cond Condition to test. + */ +#define metal_assert(cond) metal_sys_assert(cond) + +#endif /* __METAL_ASSERT_H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/atomic.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/atomic.h new file mode 100644 index 0000000000..f80c2971cd --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/atomic.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file atomic.h + * @brief Atomic primitives for libmetal. + */ + +#ifndef __METAL_ATOMIC__H__ +#define __METAL_ATOMIC__H__ + +#include <metal/config.h> + +#if defined(HAVE_STDATOMIC_H) && !defined (__CC_ARM) && \ + !defined(__STDC_NO_ATOMICS__) && !defined(__cplusplus) + +# include <stdatomic.h> + +#ifndef atomic_thread_fence +#define atomic_thread_fence(order) +#endif + +#elif defined(__GNUC__) +# include <metal/compiler/gcc/atomic.h> +#else +# include <metal/processor/arm/atomic.h> +#endif + +#endif /* __METAL_ATOMIC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/cache.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/cache.h new file mode 100644 index 0000000000..31a94abe2b --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/cache.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cache.h + * @brief CACHE operation primitives for libmetal. + */ + +#ifndef __METAL_CACHE__H__ +#define __METAL_CACHE__H__ + +#include <metal/system/generic/cache.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \defgroup cache CACHE Interfaces + * @{ */ + +/** + * @brief flush specified data cache + * + * @param[in] addr start memory logical address + * @param[in] len length of memory + * If addr is NULL, and len is 0, + * It will flush the whole data cache. + */ +static inline void metal_cache_flush(void *addr, unsigned int len) +{ + __metal_cache_flush(addr, len); +} + +/** + * @brief invalidate specified data cache + * + * @param[in] addr start memory logical address + * @param[in] len length of memory + * If addr is NULL, and len is 0, + * It will invalidate the whole data cache. + */ +static inline void metal_cache_invalidate(void *addr, unsigned int len) +{ + __metal_cache_invalidate(addr, len); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CACHE__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler.h new file mode 100644 index 0000000000..c581d4dc4f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file compiler.h + * @brief Compiler specific primitives for libmetal. + */ + +#ifndef __METAL_COMPILER__H__ +#define __METAL_COMPILER__H__ + +#if defined(__GNUC__) +# include <metal/compiler/gcc/compiler.h> +#elif defined(__ICCARM__) +# include <metal/compiler/iar/compiler.h> +#elif defined (__CC_ARM) +# error "MDK-ARM ARMCC compiler requires the GNU extentions to work correctly" +#else +# error "Missing compiler support" +#endif + +#endif /* __METAL_COMPILER__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/atomic.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/atomic.h new file mode 100644 index 0000000000..9d046785c8 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/atomic.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file gcc/atomic.h + * @brief GCC specific atomic primitives for libmetal. + */ + +#ifndef __METAL_GCC_ATOMIC__H__ +#define __METAL_GCC_ATOMIC__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int atomic_flag; +typedef char atomic_char; +typedef unsigned char atomic_uchar; +typedef short atomic_short; +typedef unsigned short atomic_ushort; +typedef int atomic_int; +typedef unsigned int atomic_uint; +typedef long atomic_long; +typedef unsigned long atomic_ulong; +typedef long long atomic_llong; +typedef unsigned long long atomic_ullong; + +#define ATOMIC_FLAG_INIT 0 +#define ATOMIC_VAR_INIT(VAL) (VAL) + +typedef enum { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst, +} memory_order; + +#define atomic_flag_test_and_set(FLAG) \ + __sync_lock_test_and_set((FLAG), 1) +#define atomic_flag_test_and_set_explicit(FLAG, MO) \ + atomic_flag_test_and_set(FLAG) +#define atomic_flag_clear(FLAG) \ + __sync_lock_release((FLAG)) +#define atomic_flag_clear_explicit(FLAG, MO) \ + atomic_flag_clear(FLAG) +#define atomic_init(OBJ, VAL) \ + do { *(OBJ) = (VAL); } while (0) +#define atomic_is_lock_free(OBJ) \ + (sizeof(*(OBJ)) <= sizeof(long)) +#define atomic_store(OBJ, VAL) \ + do { *(OBJ) = (VAL); __sync_synchronize(); } while (0) +#define atomic_store_explicit(OBJ, VAL, MO) \ + atomic_store((OBJ), (VAL)) +#define atomic_load(OBJ) \ + ({ __sync_synchronize(); *(OBJ); }) +#define atomic_load_explicit(OBJ, MO) \ + atomic_load(OBJ) +#define atomic_exchange(OBJ, DES) \ + ({ \ + typeof(OBJ) obj = (OBJ); \ + typeof(*obj) des = (DES); \ + typeof(*obj) expval; \ + typeof(*obj) oldval = atomic_load(obj); \ + do { \ + expval = oldval; \ + oldval = __sync_val_compare_and_swap( \ + obj, expval, des); \ + } while (oldval != expval); \ + oldval; \ + }) +#define atomic_exchange_explicit(OBJ, DES, MO) \ + atomic_exchange((OBJ), (DES)) +#define atomic_compare_exchange_strong(OBJ, EXP, DES) \ + ({ \ + typeof(OBJ) obj = (OBJ); \ + typeof(EXP) exp = (EXP); \ + typeof(*obj) expval = *exp; \ + typeof(*obj) oldval = __sync_val_compare_and_swap( \ + obj, expval, (DES)); \ + *exp = oldval; \ + oldval == expval; \ + }) +#define atomic_compare_exchange_strong_explicit(OBJ, EXP, DES, MO) \ + atomic_compare_exchange_strong((OBJ), (EXP), (DES)) +#define atomic_compare_exchange_weak(OBJ, EXP, DES) \ + atomic_compare_exchange_strong((OBJ), (EXP), (DES)) +#define atomic_compare_exchange_weak_explicit(OBJ, EXP, DES, MO) \ + atomic_compare_exchange_weak((OBJ), (EXP), (DES)) +#define atomic_fetch_add(OBJ, VAL) \ + __sync_fetch_and_add((OBJ), (VAL)) +#define atomic_fetch_add_explicit(OBJ, VAL, MO) \ + atomic_fetch_add((OBJ), (VAL)) +#define atomic_fetch_sub(OBJ, VAL) \ + __sync_fetch_and_sub((OBJ), (VAL)) +#define atomic_fetch_sub_explicit(OBJ, VAL, MO) \ + atomic_fetch_sub((OBJ), (VAL)) +#define atomic_fetch_or(OBJ, VAL) \ + __sync_fetch_and_or((OBJ), (VAL)) +#define atomic_fetch_or_explicit(OBJ, VAL, MO) \ + atomic_fetch_or((OBJ), (VAL)) +#define atomic_fetch_xor(OBJ, VAL) \ + __sync_fetch_and_xor((OBJ), (VAL)) +#define atomic_fetch_xor_explicit(OBJ, VAL, MO) \ + atomic_fetch_xor((OBJ), (VAL)) +#define atomic_fetch_and(OBJ, VAL) \ + __sync_fetch_and_and((OBJ), (VAL)) +#define atomic_fetch_and_explicit(OBJ, VAL, MO) \ + atomic_fetch_and((OBJ), (VAL)) +#define atomic_thread_fence(MO) \ + __sync_synchronize() +#define atomic_signal_fence(MO) \ + __sync_synchronize() + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GCC_ATOMIC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/compiler.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/compiler.h new file mode 100644 index 0000000000..fe6a11552f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/gcc/compiler.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file gcc/compiler.h + * @brief GCC specific primitives for libmetal. + */ + +#ifndef __METAL_GCC_COMPILER__H__ +#define __METAL_GCC_COMPILER__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define restrict __restrict__ +#define metal_align(n) __attribute__((aligned(n))) +#define metal_weak __attribute__((weak)) + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GCC_COMPILER__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/compiler.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/compiler.h new file mode 100644 index 0000000000..618ba2cc16 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/compiler.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, ST Microelectronics. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file iar/compiler.h + * @brief IAR specific primitives for libmetal. + */ + +#ifndef __METAL_IAR_COMPILER__H__ +#define __METAL_IAR_COMPILER__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define restrict __restrict__ +#define metal_align(n) __attribute__((aligned(n))) +#define metal_weak __attribute__((weak)) + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_IAR_COMPILER__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/errno.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/errno.h new file mode 100644 index 0000000000..d05461c073 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/iar/errno.h @@ -0,0 +1,289 @@ +/* + * * Copyright (c) 2019 STMicroelectronics. All rights reserved. + * * + * * Copyright (c) 1982, 1986, 1989, 1993 + * * The Regents of the University of California. All rights reserved. + * * Copyright (c) 1982, 1986, 1989, 1993 + * * The Regents of the University of California. All rights reserved. + * * (c) UNIX System Laboratories, Inc. + * * All or some portions of this file are derived from material licensed + * * to the University of California by American Telephone and Telegraph + * * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * * the permission of UNIX System Laboratories, Inc. + * + * * SPDX-License-Identifier: BSD-3-Clause + * */ + +#ifndef __METAL_ERRNO__H__ +#error "Include metal/errno.h instead of metal/iar/errno.h" +#endif + +#ifndef _ERRNO_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _ERRNO_H_ + + +#ifndef EPERM +#define EPERM 1 /* Not owner */ +#endif +#ifndef ENOENT +#define ENOENT 2 /* No such file or directory */ +#endif +#ifndef ESRCH +#define ESRCH 3 /* No such process */ +#endif +#ifndef EINTR +#define EINTR 4 /* Interrupted system call */ +#endif +#ifndef EIO +#define EIO 5 /* I/O error */ +#endif +#ifndef ENXIO +#define ENXIO 6 /* No such device or address */ +#endif +#ifndef E2BIG +#define E2BIG 7 /* Arg list too long */ +#endif +#ifndef ENOEXEC +#define ENOEXEC 8 /* Exec format error */ +#endif +#ifndef EBADF +#define EBADF 9 /* Bad file number */ +#endif +#ifndef ECHILD +#define ECHILD 10 /* No children */ +#endif +#ifndef EAGAIN +#define EAGAIN 11 /* No more processes */ +#endif +#ifndef ENOMEM +#define ENOMEM 12 /* Not enough space */ +#endif +#ifndef EACCES +#define EACCES 13 /* Permission denied */ +#endif +#ifndef EFAULT +#define EFAULT 14 /* Bad address */ +#endif +#ifndef EBUSY +#define EBUSY 16 /* Device or resource busy */ +#endif +#ifndef EEXIST +#define EEXIST 17 /* File exists */ +#endif +#ifndef EXDEV +#define EXDEV 18 /* Cross-device link */ +#endif +#ifndef ENODEV +#define ENODEV 19 /* No such device */ +#endif +#ifndef ENOTDIR +#define ENOTDIR 20 /* Not a directory */ +#endif +#ifndef EISDIR +#define EISDIR 21 /* Is a directory */ +#endif +#ifndef EINVAL +#define EINVAL 22 /* Invalid argument */ +#endif +#ifndef ENFILE +#define ENFILE 23 /* Too many open files in system */ +#endif +#ifndef EMFILE +#define EMFILE 24 /* File descriptor value too large */ +#endif +#ifndef ENOTTY +#define ENOTTY 25 /* Not a character device */ +#endif +#ifndef ETXTBSY +#define ETXTBSY 26 /* Text file busy */ +#endif +#ifndef EFBIG +#define EFBIG 27 /* File too large */ +#endif +#ifndef ENOSPC +#define ENOSPC 28 /* No space left on device */ +#endif +#ifndef ESPIPE +#define ESPIPE 29 /* Illegal seek */ +#endif +#ifndef EROFS +#define EROFS 30 /* Read-only file system */ +#endif +#ifndef EMLINK +#define EMLINK 31 /* Too many links */ +#endif +#ifndef EPIPE +#define EPIPE 32 /* Broken pipe */ +#endif +#ifndef EDOM +#define EDOM 33 /* Mathematics argument out of domain of function */ +#endif +#ifndef ERANGE +#define ERANGE 34 /* Result too large */ +#endif +#ifndef ENOMSG +#define ENOMSG 35 /* No message of desired type */ +#endif +#ifndef EIDRM +#define EIDRM 36 /* Identifier removed */ +#endif +#ifndef EDEADLK +#define EDEADLK 45 /* Deadlock */ +#endif +#ifndef ENOLCK +#define ENOLCK 46 /* No lock */ +#endif +#ifndef ENOSTR +#define ENOSTR 60 /* Not a stream */ +#endif +#ifndef ENODATA +#define ENODATA 61 /* No data (for no delay io) */ +#endif +#ifndef ETIME +#define ETIME 62 /* Stream ioctl timeout */ +#endif +#ifndef ENOSR +#define ENOSR 63 /* No stream resources */ +#endif +#ifndef ENOLINK +#define ENOLINK 67 /* Virtual circuit is gone */ +#endif +#ifndef EPROTO +#define EPROTO 71 /* Protocol error */ +#endif +#ifndef EMULTIHOP +#define EMULTIHOP 74 /* Multihop attempted */ +#endif +#ifndef EBADMSG +#define EBADMSG 77 /* Bad message */ +#endif +#ifndef EFTYPE +#define EFTYPE 79 /* Inappropriate file type or format */ +#endif +#ifndef ENOSYS +#define ENOSYS 88 /* Function not implemented */ +#endif +#ifndef ENOTEMPTY +#define ENOTEMPTY 90 /* Directory not empty */ +#endif +#ifndef ENAMETOOLONG +#define ENAMETOOLONG 91 /* File or path name too long */ +#endif +#ifndef ELOOP +#define ELOOP 92 /* Too many symbolic links */ +#endif +#ifndef EOPNOTSUPP +#define EOPNOTSUPP 95 /* Operation not supported on socket */ +#endif +#ifndef EPFNOSUPPORT +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#endif +#ifndef ECONNRESET +#define ECONNRESET 104 /* Connection reset by peer */ +#endif +#ifndef ENOBUFS +#define ENOBUFS 105 /* No buffer space available */ +#endif +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */ +#endif +#ifndef EPROTOTYPE +#define EPROTOTYPE 107 /* Protocol wrong type for socket */ +#endif +#ifndef ENOTSOCK +#define ENOTSOCK 108 /* Socket operation on non-socket */ +#endif +#ifndef ENOPROTOOPT +#define ENOPROTOOPT 109 /* Protocol not available */ +#endif +#ifndef ECONNREFUSED +#define ECONNREFUSED 111 /* Connection refused */ +#endif +#ifndef EADDRINUSE +#define EADDRINUSE 112 /* Address already in use */ +#endif +#ifndef ECONNABORTED +#define ECONNABORTED 113 /* Software caused connection abort */ +#endif +#ifndef ENETUNREACH +#define ENETUNREACH 114 /* Network is unreachable */ +#endif +#ifndef ENETDOWN +#define ENETDOWN 115 /* Network interface is not configured */ +#endif +#ifndef ETIMEDOUT +#define ETIMEDOUT 116 /* Connection timed out */ +#endif +#ifndef EHOSTDOWN +#define EHOSTDOWN 117 /* Host is down */ +#endif +#ifndef EHOSTUNREACH +#define EHOSTUNREACH 118 /* Host is unreachable */ +#endif +#ifndef EINPROGRESS +#define EINPROGRESS 119 /* Connection already in progress */ +#endif +#ifndef EALREADY +#define EALREADY 120 /* Socket already connected */ +#endif +#ifndef EDESTADDRREQ +#define EDESTADDRREQ 121 /* Destination address required */ +#endif +#ifndef EMSGSIZE +#define EMSGSIZE 122 /* Message too long */ +#endif +#ifndef EPROTONOSUPPORT +#define EPROTONOSUPPORT 123 /* Unknown protocol */ +#endif +#ifndef EADDRNOTAVAIL +#define EADDRNOTAVAIL 125 /* Address not available */ +#endif +#ifndef ENETRESET +#define ENETRESET 126 /* Connection aborted by network */ +#endif +#ifndef EISCONN +#define EISCONN 127 /* Socket is already connected */ +#endif +#ifndef ENOTCONN +#define ENOTCONN 128 /* Socket is not connected */ +#endif +#ifndef ETOOMANYREFS +#define ETOOMANYREFS 129 +#endif +#ifndef EDQUOT +#define EDQUOT 132 +#endif +#ifndef ESTALE +#define ESTALE 133 +#endif +#ifndef ENOTSUP +#define ENOTSUP 134 /* Not supported */ +#endif +#ifndef EILSEQ +#define EILSEQ 138 /* Illegal byte sequence */ +#endif +#ifndef EOVERFLOW +#define EOVERFLOW 139 /* Value too large for defined data type */ +#endif +#ifndef ECANCELED +#define ECANCELED 140 /* Operation canceled */ +#endif +#ifndef ENOTRECOVERABLE +#define ENOTRECOVERABLE 141 /* State not recoverable */ +#endif +#ifndef EOWNERDEAD +#define EOWNERDEAD 142 /* Previous owner died */ +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#endif + +#define __ELASTERROR 2000 /* Users can add values starting here */ + +#ifdef __cplusplus +} +#endif +#endif /* _ERRNO_H */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/mdk-arm/errno.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/mdk-arm/errno.h new file mode 100644 index 0000000000..5fc060eabb --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/compiler/mdk-arm/errno.h @@ -0,0 +1,137 @@ +/* + * * Copyright (c) 2019 STMicroelectronics. All rights reserved. + * * + * * Copyright (c) 1982, 1986, 1989, 1993 + * * The Regents of the University of California. All rights reserved. + * * Copyright (c) 1982, 1986, 1989, 1993 + * * The Regents of the University of California. All rights reserved. + * * (c) UNIX System Laboratories, Inc. + * * All or some portions of this file are derived from material licensed + * * to the University of California by American Telephone and Telegraph + * * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * * the permission of UNIX System Laboratories, Inc. + * + * * SPDX-License-Identifier: BSD-3-Clause + * */ + + +#ifndef __METAL_ERRNO__H__ +#error "Include metal/errno.h instead of metal/mdk-arm/errno.h" +#endif + +#ifndef _ERRNO_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _ERRNO_H_ + +#define EPERM 1 /* Not owner */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No children */ +#define EAGAIN 11 /* No more processes */ +#ifdef ENOMEM +#undef ENOMEM +#endif +#define ENOMEM 12 /* Not enough space */ + +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#ifdef EINVAL +#undef EINVAL +#endif +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* File descriptor value too large */ +#define ENOTTY 25 /* Not a character device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#ifdef EDOM +#undef EDOM +#endif +#define EDOM 33 /* Mathematics argument out of domain of function */ + +#ifdef ERANGE +#undef ERANGE +#endif +#define ERANGE 34 /* Result too large */ + +#define ENOMSG 35 /* No message of desired type */ +#define EIDRM 36 /* Identifier removed */ +#define EDEADLK 45 /* Deadlock */ +#define ENOLCK 46 /* No lock */ +#define ENOSTR 60 /* Not a stream */ +#define ENODATA 61 /* No data (for no delay io) */ +#define ETIME 62 /* Stream ioctl timeout */ +#define ENOSR 63 /* No stream resources */ +#define ENOLINK 67 /* Virtual circuit is gone */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 74 /* Multihop attempted */ +#define EBADMSG 77 /* Bad message */ +#define EFTYPE 79 /* Inappropriate file type or format */ +#define ENOSYS 88 /* Function not implemented */ +#define ENOTEMPTY 90 /* Directory not empty */ +#define ENAMETOOLONG 91 /* File or path name too long */ +#define ELOOP 92 /* Too many symbolic links */ +#define EOPNOTSUPP 95 /* Operation not supported on socket */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */ +#define EPROTOTYPE 107 /* Protocol wrong type for socket */ +#define ENOTSOCK 108 /* Socket operation on non-socket */ +#define ENOPROTOOPT 109 /* Protocol not available */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EADDRINUSE 112 /* Address already in use */ +#define ECONNABORTED 113 /* Software caused connection abort */ +#define ENETUNREACH 114 /* Network is unreachable */ +#define ENETDOWN 115 /* Network interface is not configured */ +#define ETIMEDOUT 116 /* Connection timed out */ +#define EHOSTDOWN 117 /* Host is down */ +#define EHOSTUNREACH 118 /* Host is unreachable */ +#define EINPROGRESS 119 /* Connection already in progress */ +#define EALREADY 120 /* Socket already connected */ +#define EDESTADDRREQ 121 /* Destination address required */ +#define EMSGSIZE 122 /* Message too long */ +#define EPROTONOSUPPORT 123 /* Unknown protocol */ +#define EADDRNOTAVAIL 125 /* Address not available */ +#define ENETRESET 126 /* Connection aborted by network */ +#define EISCONN 127 /* Socket is already connected */ +#define ENOTCONN 128 /* Socket is not connected */ +#define ETOOMANYREFS 129 +#define EDQUOT 132 +#define ESTALE 133 +#define ENOTSUP 134 /* Not supported */ +#ifdef EILSEQ +#undef EILSEQ +#endif +#define EILSEQ 138 /* Illegal byte sequence */ +#define EOVERFLOW 139 /* Value too large for defined data type */ +#define ECANCELED 140 /* Operation canceled */ +#define ENOTRECOVERABLE 141 /* State not recoverable */ +#define EOWNERDEAD 142 /* Previous owner died */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ + +#define __ELASTERROR 2000 /* Users can add values starting here */ + +#ifdef __cplusplus +} +#endif +#endif /* _ERRNO_H */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/condition.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/condition.h new file mode 100644 index 0000000000..fc0cc0dcab --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/condition.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file condition.h + * @brief Condition variable for libmetal. + */ + +#ifndef __METAL_CONDITION__H__ +#define __METAL_CONDITION__H__ + +#include <metal/mutex.h> +#include <metal/utilities.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup condition Condition Variable Interfaces + * @{ */ + +/** Opaque libmetal condition variable data structure. */ +struct metal_condition; + +/** + * @brief Initialize a libmetal condition variable. + * @param[in] cv condition variable to initialize. + */ +static inline void metal_condition_init(struct metal_condition *cv); + +/** + * @brief Notify one waiter. + * Before calling this function, the caller + * should have acquired the mutex. + * @param[in] cv condition variable + * @return zero on no errors, non-zero on errors + * @see metal_condition_wait, metal_condition_broadcast + */ +static inline int metal_condition_signal(struct metal_condition *cv); + +/** + * @brief Notify all waiters. + * Before calling this function, the caller + * should have acquired the mutex. + * @param[in] cv condition variable + * @return zero on no errors, non-zero on errors + * @see metal_condition_wait, metal_condition_signal + */ +static inline int metal_condition_broadcast(struct metal_condition *cv); + +/** + * @brief Block until the condition variable is notified. + * Before calling this function, the caller should + * have acquired the mutex. + * @param[in] cv condition variable + * @param[in] m mutex + * @return 0 on success, non-zero on failure. + * @see metal_condition_signal + */ +int metal_condition_wait(struct metal_condition *cv, metal_mutex_t *m); + +#include <metal/system/generic/condition.h> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CONDITION__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/config.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/config.h new file mode 100644 index 0000000000..256efa3861 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/config.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file config.h + * @brief Generated configuration settings for libmetal. + */ + +#ifndef __METAL_CONFIG__H__ +#define __METAL_CONFIG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Library major version number. */ +#define METAL_VER_MAJOR 0 + +/** Library minor version number. */ +#define METAL_VER_MINOR 1 + +/** Library patch level. */ +#define METAL_VER_PATCH 0 + +/** Library version string. */ +#define METAL_VER "0.1.0" + +/** System type (linux, generic, ...). */ +#define METAL_SYSTEM "generic" +#define METAL_SYSTEM_GENERIC + +/** Processor type (arm, x86_64, ...). */ +#define METAL_PROCESSOR "arm" +#define METAL_PROCESSOR_ARM + +/** Machine type (zynq, zynqmp, ...). */ +#define METAL_MACHINE "cortexm" +#define METAL_MACHINE_CORTEXM + +#define HAVE_STDATOMIC_H +/* #undef HAVE_FUTEX_H */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CONFIG__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/cpu.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/cpu.h new file mode 100644 index 0000000000..26dbaa2af7 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/cpu.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cpu.h + * @brief CPU primitives for libmetal. + */ + +#ifndef __METAL_CPU__H__ +#define __METAL_CPU__H__ + +# include <metal/processor/arm/cpu.h> + +#endif /* __METAL_CPU__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/device.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/device.h new file mode 100644 index 0000000000..5ed43d63b7 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/device.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file device.h + * @brief Bus abstraction for libmetal. + */ + +#ifndef __METAL_BUS__H__ +#define __METAL_BUS__H__ + +#include <stdint.h> +#include <metal/io.h> +#include <metal/list.h> +#include <metal/dma.h> +#include <metal/sys.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup device Bus Abstraction + * @{ */ + +#ifndef METAL_MAX_DEVICE_REGIONS +#define METAL_MAX_DEVICE_REGIONS 32 +#endif + +struct metal_bus; +struct metal_device; + +/** Bus operations. */ +struct metal_bus_ops { + void (*bus_close)(struct metal_bus *bus); + int (*dev_open)(struct metal_bus *bus, + const char *dev_name, + struct metal_device **device); + void (*dev_close)(struct metal_bus *bus, + struct metal_device *device); + void (*dev_irq_ack)(struct metal_bus *bus, + struct metal_device *device, + int irq); + int (*dev_dma_map)(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); + void (*dev_dma_unmap)(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents); +}; + +/** Libmetal bus structure. */ +struct metal_bus { + const char *name; + struct metal_bus_ops ops; + struct metal_list devices; + struct metal_list node; +}; + +/** Libmetal generic bus. */ +extern struct metal_bus metal_generic_bus; + +/** Libmetal device structure. */ +struct metal_device { + const char *name; /**< Device name */ + struct metal_bus *bus; /**< Bus that contains device */ + unsigned num_regions; /**< Number of I/O regions in + device */ + struct metal_io_region regions[METAL_MAX_DEVICE_REGIONS]; /**< Array of + I/O regions in device*/ + struct metal_list node; /**< Node on bus' list of devices */ + int irq_num; /**< Number of IRQs per device */ + void *irq_info; /**< IRQ ID */ +}; + +/** + * @brief Register a libmetal bus. + * @param[in] bus Pre-initialized bus structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_register(struct metal_bus *bus); + +/** + * @brief Unregister a libmetal bus. + * @param[in] bus Pre-registered bus structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_unregister(struct metal_bus *bus); + +/** + * @brief Find a libmetal bus by name. + * @param[in] name Bus name. + * @param[out] bus Returned bus handle. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_find(const char *name, struct metal_bus **bus); + +/** + * @brief Statically register a generic libmetal device. + * + * In non-Linux systems, devices are always required to be statically + * registered at application initialization. + * In Linux system, devices can be dynamically opened via sysfs or libfdt based + * enumeration at runtime. + * This interface is used for static registration of devices. Subsequent calls + * to metal_device_open() look up in this list of pre-registered devices on the + * "generic" bus. + * "generic" bus is used on non-Linux system to group the memory mapped devices. + * + * @param[in] device Generic device. + * @return 0 on success, or -errno on failure. + */ +extern int metal_register_generic_device(struct metal_device *device); + +/** + * @brief Open a libmetal device by name. + * @param[in] bus_name Bus name. + * @param[in] dev_name Device name. + * @param[out] device Returned device handle. + * @return 0 on success, or -errno on failure. + */ +extern int metal_device_open(const char *bus_name, const char *dev_name, + struct metal_device **device); + +/** + * @brief Close a libmetal device. + * @param[in] device Device handle. + */ +extern void metal_device_close(struct metal_device *device); + +/** + * @brief Get an I/O region accessor for a device region. + * + * @param[in] device Device handle. + * @param[in] index Region index. + * @return I/O accessor handle, or NULL on failure. + */ +static inline struct metal_io_region * +metal_device_io_region(struct metal_device *device, unsigned index) +{ + return (index < device->num_regions + ? &device->regions[index] + : NULL); +} + +/** @} */ + +#ifdef METAL_INTERNAL +extern int metal_generic_dev_sys_open(struct metal_device *dev); +extern int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name, + struct metal_device **device); +extern int metal_generic_dev_dma_map(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); +extern void metal_generic_dev_dma_unmap(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents); +#endif /* METAL_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_BUS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/dma.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/dma.h new file mode 100644 index 0000000000..6675adc347 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/dma.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file dma.h + * @brief DMA primitives for libmetal. + */ + +#ifndef __METAL_DMA__H__ +#define __METAL_DMA__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup dma DMA Interfaces + * @{ */ + +#include <stdint.h> +#include <metal/sys.h> + +#define METAL_DMA_DEV_R 1 /**< DMA direction, device read */ +#define METAL_DMA_DEV_W 2 /**< DMA direction, device write */ +#define METAL_DMA_DEV_WR 3 /**< DMA direction, device read/write */ + +/** + * @brief scatter/gather list element structure + */ +struct metal_sg { + void *virt; /**< CPU virtual address */ + struct metal_io_region *io; /**< IO region */ + int len; /**< length */ +}; + +struct metal_device; + +/** + * @brief Map memory for DMA transaction. + * After the memory is DMA mapped, the memory should be + * accessed by the DMA device but not the CPU. + * + * @param[in] dev DMA device + * @param[in] dir DMA direction + * @param[in] sg_in sg list of memory to map + * @param[in] nents_in number of sg list entries of memory to map + * @param[out] sg_out sg list of mapped memory + * @return number of mapped sg entries, -error on failure. + */ +int metal_dma_map(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); + +/** + * @brief Unmap DMA memory + * After the memory is DMA unmapped, the memory should + * be accessed by the CPU but not the DMA device. + * + * @param[in] dev DMA device + * @param[in] dir DMA direction + * @param[in] sg sg list of mapped DMA memory + * @param[in] nents number of sg list entries of DMA memory + */ +void metal_dma_unmap(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg, + int nents); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_DMA__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/errno.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/errno.h new file mode 100644 index 0000000000..1d1b677c9d --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/errno.h @@ -0,0 +1,24 @@ +/* + * * Copyright (c) 2019 STMicrolectonics , Xilinx Inc. and Contributors. All rights reserved. + * * + * * SPDX-License-Identifier: BSD-3-Clause + * */ + +/* + * * @file metal/errno.h + * * @brief error specific primitives for libmetal. + * */ + +#ifndef __METAL_ERRNO__H__ +#define __METAL_ERRNO__H__ + +#if defined (__CC_ARM) +# include <metal/compiler/mdk-arm/errno.h> +#elif defined (__ICCARM__) +# include <metal/compiler/iar/errno.h> +#else +#include <errno.h> +#endif + +#endif /* __METAL_ERRNO__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/io.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/io.h new file mode 100644 index 0000000000..6aeafc4969 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/io.h @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2015 - 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file io.h + * @brief I/O access primitives for libmetal. + */ + +#ifndef __METAL_IO__H__ +#define __METAL_IO__H__ + +#include <limits.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <metal/assert.h> +#include <metal/compiler.h> +#include <metal/atomic.h> +#include <metal/sys.h> +#include <metal/cpu.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup io IO Interfaces + * @{ */ + +#ifdef __MICROBLAZE__ +#define NO_ATOMIC_64_SUPPORT +#endif + +struct metal_io_region; + +/** Generic I/O operations. */ +struct metal_io_ops { + uint64_t (*read)(struct metal_io_region *io, + unsigned long offset, + memory_order order, + int width); + void (*write)(struct metal_io_region *io, + unsigned long offset, + uint64_t value, + memory_order order, + int width); + int (*block_read)(struct metal_io_region *io, + unsigned long offset, + void *restrict dst, + memory_order order, + int len); + int (*block_write)(struct metal_io_region *io, + unsigned long offset, + const void *restrict src, + memory_order order, + int len); + void (*block_set)(struct metal_io_region *io, + unsigned long offset, + unsigned char value, + memory_order order, + int len); + void (*close)(struct metal_io_region *io); +}; + +/** Libmetal I/O region structure. */ +struct metal_io_region { + void *virt; /**< base virtual address */ + const metal_phys_addr_t *physmap; /**< table of base physical address + of each of the pages in the I/O + region */ + size_t size; /**< size of the I/O region */ + unsigned long page_shift; /**< page shift of I/O region */ + metal_phys_addr_t page_mask; /**< page mask of I/O region */ + unsigned int mem_flags; /**< memory attribute of the + I/O region */ + struct metal_io_ops ops; /**< I/O region operations */ +}; + +/** + * @brief Open a libmetal I/O region. + * + * @param[in, out] io I/O region handle. + * @param[in] virt Virtual address of region. + * @param[in] physmap Array of physical addresses per page. + * @param[in] size Size of region. + * @param[in] page_shift Log2 of page size (-1 for single page). + * @param[in] mem_flags Memory flags + * @param[in] ops ops + */ +void +metal_io_init(struct metal_io_region *io, void *virt, + const metal_phys_addr_t *physmap, size_t size, + unsigned page_shift, unsigned int mem_flags, + const struct metal_io_ops *ops); + +/** + * @brief Close a libmetal shared memory segment. + * @param[in] io I/O region handle. + */ +static inline void metal_io_finish(struct metal_io_region *io) +{ + if (io->ops.close) + (*io->ops.close)(io); + memset(io, 0, sizeof(*io)); +} + +/** + * @brief Get size of I/O region. + * + * @param[in] io I/O region handle. + * @return Size of I/O region. + */ +static inline size_t metal_io_region_size(struct metal_io_region *io) +{ + return io->size; +} + +/** + * @brief Get virtual address for a given offset into the I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into shared memory segment. + * @return NULL if offset is out of range, or pointer to offset. + */ +static inline void * +metal_io_virt(struct metal_io_region *io, unsigned long offset) +{ + return (io->virt != METAL_BAD_VA && offset <= io->size + ? (uint8_t *)io->virt + offset + : NULL); +} + +/** + * @brief Convert a virtual address to offset within I/O region. + * @param[in] io I/O region handle. + * @param[in] virt Virtual address within segment. + * @return METAL_BAD_OFFSET if out of range, or offset. + */ +static inline unsigned long +metal_io_virt_to_offset(struct metal_io_region *io, void *virt) +{ + size_t offset = (uint8_t *)virt - (uint8_t *)io->virt; + return (offset < io->size ? offset : METAL_BAD_OFFSET); +} + +/** + * @brief Get physical address for a given offset into the I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into shared memory segment. + * @return METAL_BAD_PHYS if offset is out of range, or physical address + * of offset. + */ +static inline metal_phys_addr_t +metal_io_phys(struct metal_io_region *io, unsigned long offset) +{ + unsigned long page = (io->page_shift >= + sizeof(offset) * CHAR_BIT ? + 0 : offset >> io->page_shift); + return (io->physmap != NULL && offset <= io->size + ? io->physmap[page] + (offset & io->page_mask) + : METAL_BAD_PHYS); +} + +/** + * @brief Convert a physical address to offset within I/O region. + * @param[in] io I/O region handle. + * @param[in] phys Physical address within segment. + * @return METAL_BAD_OFFSET if out of range, or offset. + */ +static inline unsigned long +metal_io_phys_to_offset(struct metal_io_region *io, metal_phys_addr_t phys) +{ + unsigned long offset = + (io->page_mask == (metal_phys_addr_t)(-1) ? + phys - io->physmap[0] : phys & io->page_mask); + do { + if (metal_io_phys(io, offset) == phys) + return offset; + offset += io->page_mask + 1; + } while (offset < io->size); + return METAL_BAD_OFFSET; +} + +/** + * @brief Convert a physical address to virtual address. + * @param[in] io Shared memory segment handle. + * @param[in] phys Physical address within segment. + * @return NULL if out of range, or corresponding virtual address. + */ +static inline void * +metal_io_phys_to_virt(struct metal_io_region *io, metal_phys_addr_t phys) +{ + return metal_io_virt(io, metal_io_phys_to_offset(io, phys)); +} + +/** + * @brief Convert a virtual address to physical address. + * @param[in] io Shared memory segment handle. + * @param[in] virt Virtual address within segment. + * @return METAL_BAD_PHYS if out of range, or corresponding + * physical address. + */ +static inline metal_phys_addr_t +metal_io_virt_to_phys(struct metal_io_region *io, void *virt) +{ + return metal_io_phys(io, metal_io_virt_to_offset(io, virt)); +} + +/** + * @brief Read a value from an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] order Memory ordering. + * @param[in] width Width in bytes of datatype to read. This must be 1, 2, + * 4, or 8, and a compile time constant for this function + * to inline cleanly. + * @return Value. + */ +static inline uint64_t +metal_io_read(struct metal_io_region *io, unsigned long offset, + memory_order order, int width) +{ + void *ptr = metal_io_virt(io, offset); + + if (io->ops.read) + return (*io->ops.read)(io, offset, order, width); + else if (ptr && sizeof(atomic_uchar) == width) + return atomic_load_explicit((atomic_uchar *)ptr, order); + else if (ptr && sizeof(atomic_ushort) == width) + return atomic_load_explicit((atomic_ushort *)ptr, order); + else if (ptr && sizeof(atomic_uint) == width) + return atomic_load_explicit((atomic_uint *)ptr, order); + else if (ptr && sizeof(atomic_ulong) == width) + return atomic_load_explicit((atomic_ulong *)ptr, order); +#ifndef NO_ATOMIC_64_SUPPORT + else if (ptr && sizeof(atomic_ullong) == width) + return atomic_load_explicit((atomic_ullong *)ptr, order); +#endif + metal_assert(0); + return 0; /* quiet compiler */ +} + +/** + * @brief Write a value into an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] value Value to write. + * @param[in] order Memory ordering. + * @param[in] width Width in bytes of datatype to read. This must be 1, 2, + * 4, or 8, and a compile time constant for this function + * to inline cleanly. + */ +static inline void +metal_io_write(struct metal_io_region *io, unsigned long offset, + uint64_t value, memory_order order, int width) +{ + void *ptr = metal_io_virt(io, offset); + if (io->ops.write) + (*io->ops.write)(io, offset, value, order, width); + else if (ptr && sizeof(atomic_uchar) == width) + atomic_store_explicit((atomic_uchar *)ptr, value, order); + else if (ptr && sizeof(atomic_ushort) == width) + atomic_store_explicit((atomic_ushort *)ptr, value, order); + else if (ptr && sizeof(atomic_uint) == width) + atomic_store_explicit((atomic_uint *)ptr, value, order); + else if (ptr && sizeof(atomic_ulong) == width) + atomic_store_explicit((atomic_ulong *)ptr, value, order); +#ifndef NO_ATOMIC_64_SUPPORT + else if (ptr && sizeof(atomic_ullong) == width) + atomic_store_explicit((atomic_ullong *)ptr, value, order); +#endif + else + metal_assert (0); +} + +#define metal_io_read8_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 1) +#define metal_io_read8(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 1) +#define metal_io_write8_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 1) +#define metal_io_write8(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 1) + +#define metal_io_read16_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 2) +#define metal_io_read16(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 2) +#define metal_io_write16_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 2) +#define metal_io_write16(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 2) + +#define metal_io_read32_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 4) +#define metal_io_read32(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 4) +#define metal_io_write32_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 4) +#define metal_io_write32(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 4) + +#define metal_io_read64_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 8) +#define metal_io_read64(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 8) +#define metal_io_write64_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 8) +#define metal_io_write64(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 8) + +/** + * @brief Read a block from an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] dst destination to store the read data. + * @param[in] len length in bytes to read. + * @return On success, number of bytes read. On failure, negative value + */ +int metal_io_block_read(struct metal_io_region *io, unsigned long offset, + void *restrict dst, int len); + +/** + * @brief Write a block into an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] src source to write. + * @param[in] len length in bytes to write. + * @return On success, number of bytes written. On failure, negative value + */ +int metal_io_block_write(struct metal_io_region *io, unsigned long offset, + const void *restrict src, int len); + +/** + * @brief fill a block of an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] value value to fill into the block + * @param[in] len length in bytes to fill. + * @return On success, number of bytes filled. On failure, negative value + */ +int metal_io_block_set(struct metal_io_region *io, unsigned long offset, + unsigned char value, int len); + +#include <metal/system/generic/io.h> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_IO__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/irq.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/irq.h new file mode 100644 index 0000000000..e8c92f9f18 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/irq.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file irq.h + * @brief Interrupt handling primitives for libmetal. + */ + +#ifndef __METAL_IRQ__H__ +#define __METAL_IRQ__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup irq Interrupt Handling Interfaces + * @{ */ + +#include <stdlib.h> + +/** IRQ handled status */ +#define METAL_IRQ_NOT_HANDLED 0 +#define METAL_IRQ_HANDLED 1 + +/** + * @brief type of interrupt handler + * @param[in] irq interrupt id + * @param[in] priv private data + * @return irq handled status + */ +typedef int (*metal_irq_handler) (int irq, void *priv); + +struct metal_device; + +/** + * @brief Register interrupt handler for driver ID/device. + * + * @param[in] irq interrupt id + * @param[in] irq_handler interrupt handler + * @param[in] dev metal device this irq belongs to (can be NULL). + * @param[in] drv_id driver id is a unique interrupt handler identifier. + * It can also be used for driver data. + * @return 0 for success, non-zero on failure + */ +int metal_irq_register(int irq, + metal_irq_handler irq_handler, + struct metal_device *dev, + void *drv_id); + +/** + * @brief Unregister interrupt handler for driver ID and/or device. + * + * If interrupt handler (hd), driver ID (drv_id) and device (dev) + * are NULL, unregister all handlers for this interrupt. + * + * If interrupt handler (hd), device (dev) or driver ID (drv_id), + * are not NULL, unregister handlers matching non NULL criterias. + * e.g: when call is made with drv_id and dev non NULL, + * all handlers matching both are unregistered. + * + * If interrupt is not found, or other criterias not matching, + * return -ENOENT + * + * @param[in] irq interrupt id + * @param[in] irq_handler interrupt handler + * @param[in] dev metal device this irq belongs to + * @param[in] drv_id driver id. It can be used for driver data. + * @return 0 for success, non-zero on failure + */ +int metal_irq_unregister(int irq, + metal_irq_handler irq_handler, + struct metal_device *dev, + void *drv_id); + +/** + * @brief disable interrupts + * @return interrupts state + */ +unsigned int metal_irq_save_disable(void); + +/** + * @brief restore interrupts to their previous state + * @param[in] flags previous interrupts state + */ +void metal_irq_restore_enable(unsigned int flags); + +/** + * @brief metal_irq_enable + * + * Enables the given interrupt + * + * @param vector - interrupt vector number + */ +void metal_irq_enable(unsigned int vector); + +/** + * @brief metal_irq_disable + * + * Disables the given interrupt + * + * @param vector - interrupt vector number + */ +void metal_irq_disable(unsigned int vector); + +#include <metal/system/generic/irq.h> + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_IRQ__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/list.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/list.h new file mode 100644 index 0000000000..554aebfdb6 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/list.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file list.h + * @brief List primitives for libmetal. + */ + +#ifndef __METAL_LIST__H__ +#define __METAL_LIST__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup list List Primitives + * @{ */ + +struct metal_list { + struct metal_list *next, *prev; +}; + +/* + * METAL_INIT_LIST - used for initializing an list elmenet in a static struct + * or global + */ +#define METAL_INIT_LIST(name) { .next = &name, .prev = &name } +/* + * METAL_DECLARE_LIST - used for defining and initializing a global or + * static singleton list + */ +#define METAL_DECLARE_LIST(name) \ + struct metal_list name = METAL_INIT_LIST(name) + +static inline void metal_list_init(struct metal_list *list) +{ + list->next = list->prev = list; +} + +static inline void metal_list_add_before(struct metal_list *node, + struct metal_list *new_node) +{ + new_node->prev = node->prev; + new_node->next = node; + new_node->next->prev = new_node; + new_node->prev->next = new_node; +} + +static inline void metal_list_add_after(struct metal_list *node, + struct metal_list *new_node) +{ + new_node->prev = node; + new_node->next = node->next; + new_node->next->prev = new_node; + new_node->prev->next = new_node; +} + +static inline void metal_list_add_head(struct metal_list *list, + struct metal_list *node) +{ + metal_list_add_after(list, node); +} + +static inline void metal_list_add_tail(struct metal_list *list, + struct metal_list *node) +{ + metal_list_add_before(list, node); +} + +static inline int metal_list_is_empty(struct metal_list *list) +{ + return list->next == list; +} + +static inline void metal_list_del(struct metal_list *node) +{ + node->next->prev = node->prev; + node->prev->next = node->next; + node->next = node->prev = node; +} + +static inline struct metal_list *metal_list_first(struct metal_list *list) +{ + return metal_list_is_empty(list) ? NULL : list->next; +} + +#define metal_list_for_each(list, node) \ + for ((node) = (list)->next; \ + (node) != (list); \ + (node) = (node)->next) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_LIST__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/log.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/log.h new file mode 100644 index 0000000000..3807bbbef4 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/log.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file log.h + * @brief Logging support for libmetal. + */ + +#ifndef __METAL_METAL_LOG__H__ +#define __METAL_METAL_LOG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup logging Library Logging Interfaces + * @{ */ + +/** Log message priority levels for libmetal. */ +enum metal_log_level { + METAL_LOG_EMERGENCY, /**< system is unusable. */ + METAL_LOG_ALERT, /**< action must be taken immediately. */ + METAL_LOG_CRITICAL, /**< critical conditions. */ + METAL_LOG_ERROR, /**< error conditions. */ + METAL_LOG_WARNING, /**< warning conditions. */ + METAL_LOG_NOTICE, /**< normal but significant condition. */ + METAL_LOG_INFO, /**< informational messages. */ + METAL_LOG_DEBUG, /**< debug-level messages. */ +}; + +/** Log message handler type. */ +typedef void (*metal_log_handler)(enum metal_log_level level, + const char *format, ...); + +/** + * @brief Set libmetal log handler. + * @param[in] handler log message handler. + * @return 0 on success, or -errno on failure. + */ +extern void metal_set_log_handler(metal_log_handler handler); + +/** + * @brief Get the current libmetal log handler. + * @return Current log handler. + */ +extern metal_log_handler metal_get_log_handler(void); + +/** + * @brief Set the level for libmetal logging. + * @param[in] level log message level. + */ +extern void metal_set_log_level(enum metal_log_level level); + +/** + * @brief Get the current level for libmetal logging. + * @return Current log level. + */ +extern enum metal_log_level metal_get_log_level(void); + +/** + * @brief Default libmetal log handler. This handler prints libmetal log + * mesages to stderr. + * @param[in] level log message level. + * @param[in] format log message format string. + * @return 0 on success, or -errno on failure. + */ +extern void metal_default_log_handler(enum metal_log_level level, + const char *format, ...); + + +/** + * Emit a log message if the log level permits. + * + * @param level Log level. + * @param ... Format string and arguments. + */ +#define metal_log(level, ...) \ + ((level <= _metal.common.log_level && _metal.common.log_handler) \ + ? (void)_metal.common.log_handler(level, __VA_ARGS__) \ + : (void)0) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#include <metal/system/generic/log.h> + +#endif /* __METAL_METAL_LOG__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/mutex.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/mutex.h new file mode 100644 index 0000000000..053f679200 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/mutex.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file mutex.h + * @brief Mutex primitives for libmetal. + */ + +#ifndef __METAL_MUTEX__H__ +#define __METAL_MUTEX__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup mutex Mutex Interfaces + * @{ */ + +#include <metal/system/generic/mutex.h> + +/** + * @brief Initialize a libmetal mutex. + * @param[in] mutex Mutex to initialize. + */ +static inline void metal_mutex_init(metal_mutex_t *mutex) +{ + __metal_mutex_init(mutex); +} + +/** + * @brief Deinitialize a libmetal mutex. + * @param[in] mutex Mutex to deinitialize. + */ +static inline void metal_mutex_deinit(metal_mutex_t *mutex) +{ + __metal_mutex_deinit(mutex); +} + +/** + * @brief Try to acquire a mutex + * @param[in] mutex Mutex to mutex. + * @return 0 on failure to acquire, non-zero on success. + */ +static inline int metal_mutex_try_acquire(metal_mutex_t *mutex) +{ + return __metal_mutex_try_acquire(mutex); +} + +/** + * @brief Acquire a mutex + * @param[in] mutex Mutex to mutex. + */ +static inline void metal_mutex_acquire(metal_mutex_t *mutex) +{ + __metal_mutex_acquire(mutex); +} + +/** + * @brief Release a previously acquired mutex. + * @param[in] mutex Mutex to mutex. + * @see metal_mutex_try_acquire, metal_mutex_acquire + */ +static inline void metal_mutex_release(metal_mutex_t *mutex) +{ + __metal_mutex_release(mutex); +} + +/** + * @brief Checked if a mutex has been acquired. + * @param[in] mutex mutex to check. + * @see metal_mutex_try_acquire, metal_mutex_acquire + */ +static inline int metal_mutex_is_acquired(metal_mutex_t *mutex) +{ + return __metal_mutex_is_acquired(mutex); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_MUTEX__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/atomic.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/atomic.h new file mode 100644 index 0000000000..3a577e378d --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/atomic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file arm/atomic.h + * @brief ARM specific atomic primitives for libmetal. + */ + +#ifndef __METAL_ARM_ATOMIC__H__ +#define __METAL_ARM_ATOMIC__H__ + +#endif /* __METAL_ARM_ATOMIC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/cpu.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/cpu.h new file mode 100644 index 0000000000..2141fb3982 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/processor/arm/cpu.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cpu.h + * @brief CPU specific primatives + */ + +#ifndef __METAL_ARM_CPU__H__ +#define __METAL_ARM_CPU__H__ + +#define metal_cpu_yield() + +#endif /* __METAL_ARM_CPU__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/shmem.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/shmem.h new file mode 100644 index 0000000000..17e9d2067e --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/shmem.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file shmem.h + * @brief Shared memory primitives for libmetal. + */ + +#ifndef __METAL_SHMEM__H__ +#define __METAL_SHMEM__H__ + +#include <metal/io.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup shmem Shared Memory Interfaces + * @{ */ + +/** Generic shared memory data structure. */ +struct metal_generic_shmem { + const char *name; + struct metal_io_region io; + struct metal_list node; +}; + +/** + * @brief Open a libmetal shared memory segment. + * + * Open a shared memory segment. + * + * @param[in] name Name of segment to open. + * @param[in] size Size of segment. + * @param[out] io I/O region handle, if successful. + * @return 0 on success, or -errno on failure. + * + * @see metal_shmem_create + */ +extern int metal_shmem_open(const char *name, size_t size, + struct metal_io_region **io); + +/** + * @brief Statically register a generic shared memory region. + * + * Shared memory regions may be statically registered at application + * initialization, or may be dynamically opened. This interface is used for + * static registration of regions. Subsequent calls to metal_shmem_open() look + * up in this list of pre-registered regions. + * + * @param[in] shmem Generic shmem structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_shmem_register_generic(struct metal_generic_shmem *shmem); + +#ifdef METAL_INTERNAL + +/** + * @brief Open a statically registered shmem segment. + * + * This interface is meant for internal libmetal use within system specific + * shmem implementations. + * + * @param[in] name Name of segment to open. + * @param[in] size Size of segment. + * @param[out] io I/O region handle, if successful. + * @return 0 on success, or -errno on failure. + */ +int metal_shmem_open_generic(const char *name, size_t size, + struct metal_io_region **result); + +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SHMEM__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/sleep.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/sleep.h new file mode 100644 index 0000000000..1131934655 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/sleep.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file sleep.h + * @brief Sleep primitives for libmetal. + */ + +#ifndef __METAL_SLEEP__H__ +#define __METAL_SLEEP__H__ + +#include <metal/system/generic/sleep.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup sleep Sleep Interfaces + * @{ */ + +/** + * @brief delay in microseconds + * delay the next execution in the calling thread + * fo usec microseconds. + * + * @param[in] usec microsecond intervals + * @return 0 on success, non-zero for failures + */ +static inline int metal_sleep_usec(unsigned int usec) +{ + return __metal_sleep_usec(usec); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SLEEP__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/spinlock.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/spinlock.h new file mode 100644 index 0000000000..ebd4cae4ef --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/spinlock.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file spinlock.h + * @brief Spinlock primitives for libmetal. + */ + +#ifndef __METAL_SPINLOCK__H__ +#define __METAL_SPINLOCK__H__ + +#include <metal/atomic.h> +#include <metal/cpu.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup spinlock Spinlock Interfaces + * @{ */ +struct metal_spinlock { + union{ + atomic_int v; + atomic_flag w; + }; +}; + +/** Static metal spinlock initialization. */ +#define METAL_SPINLOCK_INIT {ATOMIC_VAR_INIT(0)} + +/** + * @brief Initialize a libmetal spinlock. + * @param[in] slock Spinlock to initialize. + */ +static inline void metal_spinlock_init(struct metal_spinlock *slock) +{ + atomic_store(&slock->v, 0); +} + +/** + * @brief Acquire a spinlock. + * @param[in] slock Spinlock to acquire. + * @see metal_spinlock_release + */ +static inline void metal_spinlock_acquire(struct metal_spinlock *slock) +{ + while (atomic_flag_test_and_set(&slock->w)) { + metal_cpu_yield(); + } +} + +/** + * @brief Release a previously acquired spinlock. + * @param[in] slock Spinlock to release. + * @see metal_spinlock_acquire + */ +static inline void metal_spinlock_release(struct metal_spinlock *slock) +{ + atomic_flag_clear(&slock->w); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SPINLOCK__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/sys.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/sys.h new file mode 100644 index 0000000000..908f796740 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/sys.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file sys.h + * @brief System primitives for libmetal. + * @brief Top level include internal to libmetal library code. + */ + +#ifndef __METAL_SYS__H__ +#define __METAL_SYS__H__ + +#include <stdlib.h> + +#include <metal/log.h> +#include <metal/list.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup system Top Level Interfaces + * @{ */ + +/** Physical address type. */ +typedef unsigned long metal_phys_addr_t; + +/** Interrupt request number. */ +typedef int metal_irq_t; + +/** Bad offset into shared memory or I/O region. */ +#define METAL_BAD_OFFSET ((unsigned long)-1) + +/** Bad physical address value. */ +#define METAL_BAD_PHYS ((metal_phys_addr_t)-1) + +/** Bad virtual address value. */ +#define METAL_BAD_VA ((void *)-1) + +/** Bad IRQ. */ +#define METAL_BAD_IRQ ((metal_irq_t)-1) + +/** + * Initialization configuration for libmetal. + */ +struct metal_init_params { + + /** log message handler (defaults to stderr). */ + metal_log_handler log_handler; + + /** default log message level (defaults to emergency). */ + enum metal_log_level log_level; +}; + +/** + * System independent runtime state for libmetal. This is part of a system + * specific singleton data structure (@see _metal). + */ +struct metal_common_state { + /** Current log level. */ + enum metal_log_level log_level; + + /** Current log handler (null for none). */ + metal_log_handler log_handler; + + /** List of registered buses. */ + struct metal_list bus_list; + + /** Generic statically defined shared memory segments. */ + struct metal_list generic_shmem_list; + + /** Generic statically defined devices. */ + struct metal_list generic_device_list; +}; + +struct metal_state; + +#include <metal/system/generic/sys.h> + +#ifndef METAL_INIT_DEFAULTS +#define METAL_INIT_DEFAULTS \ +{ \ + .log_handler = metal_default_log_handler, \ + .log_level = METAL_LOG_INFO, \ +} +#endif + +/** System specific runtime data. */ +extern struct metal_state _metal; + +/** + * @brief Initialize libmetal. + * + * Initialize the libmetal library. + * + * @param[in] params Initialization params (@see metal_init_params). + * + * @return 0 on success, or -errno on failure. + * + * @see metal_finish + */ +extern int metal_init(const struct metal_init_params *params); + +/** + * @brief Shutdown libmetal. + * + * Shutdown the libmetal library, and release all reserved resources. + * + * @see metal_init + */ +extern void metal_finish(void); + +#ifdef METAL_INTERNAL + +/** + * @brief libmetal system initialization. + * + * This function initializes libmetal on Linux or Generic platforms. This + * involves obtaining necessary pieces of system information (sysfs mount path, + * page size, etc.). + * + * @param[in] params Initialization parameters (@see metal_init_params). + * @return 0 on success, or -errno on failure. + */ +extern int metal_sys_init(const struct metal_init_params *params); + +/** + * @brief libmetal system shutdown. + * + * This function shuts down and releases resources held by libmetal Linux or + * Generic platform layers. + * + * @see metal_sys_init + */ +extern void metal_sys_finish(void); + +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/alloc.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/alloc.h new file mode 100644 index 0000000000..bcceba61a0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/alloc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/alloc.c + * @brief generic libmetal memory allocattion definitions. + */ + +#ifndef __METAL_ALLOC__H__ +#error "Include metal/alloc.h instead of metal/generic/alloc.h" +#endif + +#ifndef __METAL_GENERIC_ALLOC__H__ +#define __METAL_GENERIC_ALLOC__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void *metal_allocate_memory(unsigned int size) +{ + return (malloc(size)); +} + +static inline void metal_free_memory(void *ptr) +{ + free(ptr); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_ALLOC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/assert.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/assert.h new file mode 100644 index 0000000000..97f88ee5a5 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/assert.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file assert.h + * @brief Generic assertion support. + */ + +#ifndef __METAL_ASSERT__H__ +#error "Include metal/assert.h instead of metal/generic/assert.h" +#endif + +#ifndef __METAL_GENERIC_ASSERT__H__ +#define __METAL_GENERIC_ASSERT__H__ + +#include <assert.h> + +/** + * @brief Assertion macro for bare-metal applications. + * @param cond Condition to evaluate. + */ +#define metal_sys_assert(cond) assert(cond) + +#endif /* __METAL_GENERIC_ASSERT__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cache.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cache.h new file mode 100644 index 0000000000..962ffccfa9 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cache.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/cache.h + * @brief generic cache operation primitives for libmetal. + */ + +#ifndef __METAL_CACHE__H__ +#error "Include metal/cache.h instead of metal/generic/cache.h" +#endif + +#ifndef __METAL_GENERIC_CACHE__H__ +#define __METAL_GENERIC_CACHE__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void metal_machine_cache_flush(void *addr, unsigned int len); +extern void metal_machine_cache_invalidate(void *addr, unsigned int len); + +static inline void __metal_cache_flush(void *addr, unsigned int len) +{ + metal_machine_cache_flush(addr, len); +} + +static inline void __metal_cache_invalidate(void *addr, unsigned int len) +{ + metal_machine_cache_invalidate(addr, len); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_CACHE__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/condition.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/condition.h new file mode 100644 index 0000000000..5202f3345f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/condition.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/condition.h + * @brief Generic condition variable primitives for libmetal. + */ + +#ifndef __METAL_CONDITION__H__ +#error "Include metal/condition.h instead of metal/generic/condition.h" +#endif + +#ifndef __METAL_GENERIC_CONDITION__H__ +#define __METAL_GENERIC_CONDITION__H__ + +#if defined (__CC_ARM) +#include <stdio.h> +#endif +#include <metal/atomic.h> +#include <stdint.h> +#include <limits.h> +#include <metal/errno.h> + + + +#ifdef __cplusplus +extern "C" { +#endif + +struct metal_condition { + metal_mutex_t *m; /**< mutex. + The condition variable is attached to + this mutex when it is waiting. + It is also used to check correctness + in case there are multiple waiters. */ + + atomic_int v; /**< condition variable value. */ +}; + +/** Static metal condition variable initialization. */ +#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) } + +static inline void metal_condition_init(struct metal_condition *cv) +{ + cv->m = NULL; + atomic_init(&cv->v, 0); +} + +static inline int metal_condition_signal(struct metal_condition *cv) +{ + if (!cv) + return -EINVAL; + + /** wake up waiters if there are any. */ + atomic_fetch_add(&cv->v, 1); + return 0; +} + +static inline int metal_condition_broadcast(struct metal_condition *cv) +{ + return metal_condition_signal(cv); +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_CONDITION__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cortexm/sys.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cortexm/sys.h new file mode 100644 index 0000000000..f506887783 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/cortexm/sys.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/mp1_m4/sys.h + * @brief generic mp1_m4 system primitives for libmetal. + */ + +#ifndef __METAL_GENERIC_SYS__H__ +#error "Include metal/sys.h instead of metal/generic/cortexm/sys.h" +#endif + +#ifndef __METAL_GENERIC_MP1_M4_SYS__H__ +#define __METAL_GENERIC_MP1_M4_SYS__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MAX_IRQS) +#define MAX_IRQS 8 /**< maximum number of irqs */ +#endif + +static inline void sys_irq_enable(unsigned int vector) +{ + (void)vector; +} + +static inline void sys_irq_disable(unsigned int vector) +{ + (void)vector; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_MP1_M4_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/io.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/io.h new file mode 100644 index 0000000000..adbbc44774 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/io.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/io.h + * @brief Generic specific io definitions. + */ + +#ifndef __METAL_IO__H__ +#error "Include metal/io.h instead of metal/generic/io.h" +#endif + +#ifndef __METAL_GENERIC_IO__H__ +#define __METAL_GENERIC_IO__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef METAL_INTERNAL + +/** + * @brief memory mapping for an I/O region + */ +void metal_sys_io_mem_map(struct metal_io_region *io); + +/** + * @brief memory mapping + */ +void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa, + size_t size, unsigned int flags); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_IO__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/irq.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/irq.h new file mode 100644 index 0000000000..c618c87fde --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/irq.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/irq.c + * @brief Generic libmetal irq definitions. + */ + +#ifndef __METAL_IRQ__H__ +#error "Include metal/irq.h instead of metal/generic/irq.h" +#endif + +#ifndef __METAL_GENERIC_IRQ__H__ +#define __METAL_GENERIC_IRQ__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief default interrupt handler + * @param[in] vector interrupt vector + */ +void metal_irq_isr(unsigned int vector); + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_IRQ__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/log.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/log.h new file mode 100644 index 0000000000..32611288ad --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/log.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Linaro nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/log.h + * @brief Generic libmetal log handler definition. + */ + +#ifndef __METAL_METAL_LOG__H__ +#error "Include metal/log.h instead of metal/generic/log.h" +#endif + +#ifndef __METAL_GENERIC_LOG__H__ +#define __METAL_GENERIC_LOG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_LOG__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/mutex.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/mutex.h new file mode 100644 index 0000000000..3613c194d1 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/mutex.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/mutex.h + * @brief Generic mutex primitives for libmetal. + */ + +#ifndef __METAL_MUTEX__H__ +#error "Include metal/mutex.h instead of metal/generic/mutex.h" +#endif + +#ifndef __METAL_GENERIC_MUTEX__H__ +#define __METAL_GENERIC_MUTEX__H__ + +#include <metal/atomic.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + union{ + atomic_int v; + atomic_flag w; + }; +} metal_mutex_t; + +/* + * METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct + * or global + */ +#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) } +/* + * METAL_MUTEX_DEFINE - used for defining and initializing a global or + * static singleton mutex + */ +#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m) + +static inline void __metal_mutex_init(metal_mutex_t *mutex) +{ + atomic_store(&mutex->v, 0); +} + +static inline void __metal_mutex_deinit(metal_mutex_t *mutex) +{ + (void)mutex; +} + +static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex) +{ + return 1 - atomic_flag_test_and_set(&mutex->w); +} + +static inline void __metal_mutex_acquire(metal_mutex_t *mutex) +{ + while (atomic_flag_test_and_set(&mutex->w)) { + ; + } +} + +static inline void __metal_mutex_release(metal_mutex_t *mutex) +{ + atomic_flag_clear(&mutex->w); +} + +static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex) +{ + return atomic_load(&mutex->v); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_MUTEX__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sleep.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sleep.h new file mode 100644 index 0000000000..aa86df492e --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sleep.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/sleep.h + * @brief Generic sleep primitives for libmetal. + */ + +#ifndef __METAL_SLEEP__H__ +#error "Include metal/sleep.h instead of metal/generic/sleep.h" +#endif + +#ifndef __METAL_GENERIC_SLEEP__H__ +#define __METAL_GENERIC_SLEEP__H__ + +#include <metal/utilities.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline int __metal_sleep_usec(unsigned int usec) +{ + metal_unused(usec); + /* Fix me */ + return 0; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_SLEEP__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sys.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sys.h new file mode 100644 index 0000000000..6f6143a4ce --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/system/generic/sys.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/sys.h + * @brief Generic system primitives for libmetal. + */ + +#ifndef __METAL_SYS__H__ +#error "Include metal/sys.h instead of metal/generic/sys.h" +#endif + +#ifndef __METAL_GENERIC_SYS__H__ +#define __METAL_GENERIC_SYS__H__ + +#include <metal/errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "./cortexm/sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef METAL_MAX_DEVICE_REGIONS +#define METAL_MAX_DEVICE_REGIONS 1 +#endif + +/** Structure of generic libmetal runtime state. */ +struct metal_state { + + /** Common (system independent) data. */ + struct metal_common_state common; +}; + +#ifdef METAL_INTERNAL + +/** + * @brief restore interrupts to state before disable_global_interrupt() + */ +void sys_irq_restore_enable(unsigned int flags); + +/** + * @brief disable all interrupts + */ +unsigned int sys_irq_save_disable(void); + +#endif /* METAL_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/time.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/time.h new file mode 100644 index 0000000000..0da6821783 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/time.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file time.h + * @brief Time primitives for libmetal. + */ + +#ifndef __METAL_TIME__H__ +#define __METAL_TIME__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup time TIME Interfaces + * @{ */ + +#include <stdint.h> +#include <metal/sys.h> + +/** + * @brief get timestamp + * This function returns the timestampe as unsigned long long + * value. + * + * @return timestamp + */ +unsigned long long metal_get_timestamp(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_TIME__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/utilities.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/utilities.h new file mode 100644 index 0000000000..eb540d2f0a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/utilities.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file utilities.h + * @brief Utility routines for libmetal. + */ + +#ifndef __METAL_UTILITIES__H__ +#define __METAL_UTILITIES__H__ + +#include <stdint.h> +#include <metal/assert.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup utilities Simple Utilities + * @{ */ + +/** Marker for unused function arguments/variables. */ +#define metal_unused(x) do { (x) = (x); } while (0) + +/** Figure out number of elements in an array. */ +#define metal_dim(x) (sizeof(x) / sizeof(x[0])) + +/** Minimum of two numbers (warning: multiple evaluation!). */ +#define metal_min(x, y) ((x) < (y) ? (x) : (y)) + +/** Maximum of two numbers (warning: multiple evaluation!). */ +#define metal_max(x, y) ((x) > (y) ? (x) : (y)) + +/** Sign of a number [-1, 0, or 1] (warning: multiple evaluation!). */ +#define metal_sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0)) + +/** Align 'size' down to a multiple of 'align' (must be a power of two). */ +#define metal_align_down(size, align) \ + ((size) & ~((align) - 1)) + +/** Align 'size' up to a multiple of 'align' (must be a power of two). */ +#define metal_align_up(size, align) \ + metal_align_down((size) + (align) - 1, align) + +/** Divide (and round down). */ +#define metal_div_round_down(num, den) \ + ((num) / (den)) + +/** Divide (and round up). */ +#define metal_div_round_up(num, den) \ + metal_div_round_down((num) + (den) - 1, (den)) + +/** Align 'ptr' down to a multiple of 'align' (must be a power of two). */ +#define metal_ptr_align_down(ptr, align) \ + (void *)(metal_align_down((uintptr_t)(ptr), (uintptr_t)(align))) + +/** Align 'ptr' up to a multiple of 'align' (must be a power of two). */ +#define metal_ptr_align_up(ptr, align) \ + (void *)(metal_align_up((uintptr_t)(ptr), (uintptr_t)(align))) + +/** Compute offset of a field within a structure. */ +#define metal_offset_of(structure, member) \ + ((uintptr_t) &(((structure *) 0)->member)) + +/** Compute pointer to a structure given a pointer to one of its fields. */ +#define metal_container_of(ptr, structure, member) \ + (void *)((uintptr_t)(ptr) - metal_offset_of(structure, member)) + +#define METAL_BITS_PER_ULONG (8 * sizeof(unsigned long)) + +#define metal_bit(bit) (1UL << (bit)) + +#define metal_bitmap_longs(x) metal_div_round_up((x), METAL_BITS_PER_ULONG) + +static inline void metal_bitmap_set_bit(unsigned long *bitmap, int bit) +{ + bitmap[bit / METAL_BITS_PER_ULONG] |= + metal_bit(bit & (METAL_BITS_PER_ULONG - 1)); +} + +static inline int metal_bitmap_is_bit_set(unsigned long *bitmap, int bit) +{ + return bitmap[bit / METAL_BITS_PER_ULONG] & + metal_bit(bit & (METAL_BITS_PER_ULONG - 1)); +} + +static inline void metal_bitmap_clear_bit(unsigned long *bitmap, int bit) +{ + bitmap[bit / METAL_BITS_PER_ULONG] &= + ~metal_bit(bit & (METAL_BITS_PER_ULONG - 1)); +} + +static inline int metal_bitmap_is_bit_clear(unsigned long *bitmap, int bit) +{ + return !metal_bitmap_is_bit_set(bitmap, bit); +} + +static inline unsigned int +metal_bitmap_next_set_bit(unsigned long *bitmap, unsigned int start, + unsigned int max) +{ + unsigned int bit; + for (bit = start; + bit < max && !metal_bitmap_is_bit_set(bitmap, bit); + bit ++) + ; + return bit; +} + +#define metal_bitmap_for_each_set_bit(bitmap, bit, max) \ + for ((bit) = metal_bitmap_next_set_bit((bitmap), 0, (max)); \ + (bit) < (max); \ + (bit) = metal_bitmap_next_set_bit((bitmap), (bit), (max))) + +static inline unsigned int +metal_bitmap_next_clear_bit(unsigned long *bitmap, unsigned int start, + unsigned int max) +{ + unsigned int bit; + for (bit = start; + bit < max && !metal_bitmap_is_bit_clear(bitmap, bit); + bit ++) + ; + return bit; +} + +#define metal_bitmap_for_each_clear_bit(bitmap, bit, max) \ + for ((bit) = metal_bitmap_next_clear_bit((bitmap), 0, (max)); \ + (bit) < (max); \ + (bit) = metal_bitmap_next_clear_bit((bitmap), (bit), (max))) + +static inline unsigned long metal_log2(unsigned long in) +{ + unsigned long result; + + metal_assert((in & (in - 1)) == 0); + + for (result = 0; (1UL << result) < in; result ++) + ; + return result; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_UTILITIES__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/version.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/version.h new file mode 100644 index 0000000000..f093c51201 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/include/metal/version.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file version.h + * @brief Library version information for libmetal. + */ + +#ifndef __METAL_VERSION__H__ +#define __METAL_VERSION__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup versions Library Version Interfaces + * @{ */ + +/** + * @brief Library major version number. + * + * Return the major version number of the library linked into the application. + * This is required to match the value of METAL_VER_MAJOR, which is the major + * version of the library that the application was compiled against. + * + * @return Library major version number. + * @see METAL_VER_MAJOR + */ +extern int metal_ver_major(void); + +/** + * @brief Library minor version number. + * + * Return the minor version number of the library linked into the application. + * This could differ from the value of METAL_VER_MINOR, which is the minor + * version of the library that the application was compiled against. + * + * @return Library minor version number. + * @see METAL_VER_MINOR + */ +extern int metal_ver_minor(void); + +/** + * @brief Library patch level. + * + * Return the patch level of the library linked into the application. This + * could differ from the value of METAL_VER_PATCH, which is the patch level of + * the library that the application was compiled against. + * + * @return Library patch level. + * @see METAL_VER_PATCH + */ +extern int metal_ver_patch(void); + +/** + * @brief Library version string. + * + * Return the version string of the library linked into the application. This + * could differ from the value of METAL_VER, which is the version string of + * the library that the application was compiled against. + * + * @return Library version string. + * @see METAL_VER + */ +extern const char *metal_ver(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_VERSION__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/init.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/init.c new file mode 100644 index 0000000000..315217741f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/init.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> +#include <metal/sys.h> + +int metal_init(const struct metal_init_params *params) +{ + int error = 0; + + memset(&_metal, 0, sizeof(_metal)); + + _metal.common.log_handler = params->log_handler; + _metal.common.log_level = params->log_level; + + metal_list_init(&_metal.common.bus_list); + metal_list_init(&_metal.common.generic_shmem_list); + metal_list_init(&_metal.common.generic_device_list); + + error = metal_sys_init(params); + if (error) + return error; + + return error; +} + +void metal_finish(void) +{ + metal_sys_finish(); + memset(&_metal, 0, sizeof(_metal)); +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/io.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/io.c new file mode 100644 index 0000000000..fccf1100e0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/io.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/errno.h> +#include <limits.h> +#include <metal/io.h> +#include <metal/sys.h> + +void metal_io_init(struct metal_io_region *io, void *virt, + const metal_phys_addr_t *physmap, size_t size, + unsigned page_shift, unsigned int mem_flags, + const struct metal_io_ops *ops) +{ + const struct metal_io_ops nops = {NULL, NULL, NULL, NULL, NULL, NULL}; + + io->virt = virt; + io->physmap = physmap; + io->size = size; + io->page_shift = page_shift; + if (page_shift >= sizeof(io->page_mask) * CHAR_BIT) + /* avoid overflow */ + io->page_mask = -1UL; + else + io->page_mask = (1UL << page_shift) - 1UL; + io->mem_flags = mem_flags; + io->ops = ops ? *ops : nops; + metal_sys_io_mem_map(io); +} + +int metal_io_block_read(struct metal_io_region *io, unsigned long offset, + void *restrict dst, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + unsigned char *dest = dst; + int retlen; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_read) { + retlen = (*io->ops.block_read)( + io, offset, dst, memory_order_seq_cst, len); + } else { + atomic_thread_fence(memory_order_seq_cst); + while ( len && ( + ((uintptr_t)dest % sizeof(int)) || + ((uintptr_t)ptr % sizeof(int)))) { + *(unsigned char *)dest = + *(const unsigned char *)ptr; + dest++; + ptr++; + len--; + } + for (; len >= (int)sizeof(int); dest += sizeof(int), + ptr += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)dest = *(const unsigned int *)ptr; + for (; len != 0; dest++, ptr++, len--) + *(unsigned char *)dest = + *(const unsigned char *)ptr; + } + return retlen; +} + +int metal_io_block_write(struct metal_io_region *io, unsigned long offset, + const void *restrict src, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + const unsigned char *source = src; + int retlen; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_write) { + retlen = (*io->ops.block_write)( + io, offset, src, memory_order_seq_cst, len); + } else { + while ( len && ( + ((uintptr_t)ptr % sizeof(int)) || + ((uintptr_t)source % sizeof(int)))) { + *(unsigned char *)ptr = + *(const unsigned char *)source; + ptr++; + source++; + len--; + } + for (; len >= (int)sizeof(int); ptr += sizeof(int), + source += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)ptr = *(const unsigned int *)source; + for (; len != 0; ptr++, source++, len--) + *(unsigned char *)ptr = + *(const unsigned char *)source; + atomic_thread_fence(memory_order_seq_cst); + } + return retlen; +} + +int metal_io_block_set(struct metal_io_region *io, unsigned long offset, + unsigned char value, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + int retlen = len; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_set) { + (*io->ops.block_set)( + io, offset, value, memory_order_seq_cst, len); + } else { + unsigned int cint = value; + unsigned int i; + + for (i = 1; i < sizeof(int); i++) + cint |= ((unsigned int)value << (8 * i)); + + for (; len && ((uintptr_t)ptr % sizeof(int)); ptr++, len--) + *(unsigned char *)ptr = (unsigned char) value; + for (; len >= (int)sizeof(int); ptr += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)ptr = cint; + for (; len != 0; ptr++, len--) + *(unsigned char *)ptr = (unsigned char) value; + atomic_thread_fence(memory_order_seq_cst); + } + return retlen; +} + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/log.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/log.c new file mode 100644 index 0000000000..83bec1f6d0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/log.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdarg.h> +#include <stdio.h> + +#include <metal/log.h> +#include <metal/sys.h> + +void metal_default_log_handler(enum metal_log_level level, + const char *format, ...) +{ +#ifdef DEFAULT_LOGGER_ON + char msg[1024]; + va_list args; + static const char *level_strs[] = { + "metal: emergency: ", + "metal: alert: ", + "metal: critical: ", + "metal: error: ", + "metal: warning: ", + "metal: notice: ", + "metal: info: ", + "metal: debug: ", + }; + + va_start(args, format); + vsnprintf(msg, sizeof(msg), format, args); + va_end(args); + + if (level <= METAL_LOG_EMERGENCY || level > METAL_LOG_DEBUG) + level = METAL_LOG_EMERGENCY; + + fprintf(stderr, "%s%s", level_strs[level], msg); +#else + (void)level; + (void)format; +#endif +} + +void metal_set_log_handler(metal_log_handler handler) +{ + _metal.common.log_handler = handler; +} + +metal_log_handler metal_get_log_handler(void) +{ + return _metal.common.log_handler; +} + +void metal_set_log_level(enum metal_log_level level) +{ + _metal.common.log_level = level; +} + +enum metal_log_level metal_get_log_level(void) +{ + return _metal.common.log_level; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/shmem.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/shmem.c new file mode 100644 index 0000000000..5ead8e755d --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/shmem.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/shmem.c + * @brief Generic libmetal shared memory handling. + */ + +#include <metal/errno.h> +#include <metal/assert.h> +#include <metal/shmem.h> +#include <metal/sys.h> +#include <metal/utilities.h> + +int metal_shmem_register_generic(struct metal_generic_shmem *shmem) +{ + /* Make sure that we can be found. */ + metal_assert(shmem->name && strlen(shmem->name) != 0); + + /* Statically registered shmem regions cannot have a destructor. */ + metal_assert(!shmem->io.ops.close); + + metal_list_add_tail(&_metal.common.generic_shmem_list, + &shmem->node); + return 0; +} + +int metal_shmem_open_generic(const char *name, size_t size, + struct metal_io_region **result) +{ + struct metal_generic_shmem *shmem; + struct metal_list *node; + + metal_list_for_each(&_metal.common.generic_shmem_list, node) { + shmem = metal_container_of(node, struct metal_generic_shmem, node); + if (strcmp(shmem->name, name) != 0) + continue; + if (size > metal_io_region_size(&shmem->io)) + continue; + *result = &shmem->io; + return 0; + } + + return -ENOENT; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/st_device.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/st_device.c new file mode 100644 index 0000000000..a3bc12caf3 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/st_device.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> +#include <metal/errno.h> +#include <metal/assert.h> +#include <metal/device.h> +#include <metal/list.h> +#include <metal/log.h> +#include <metal/sys.h> +#include <metal/utilities.h> +#include <metal/dma.h> +#include <metal/cache.h> + +int metal_bus_register(struct metal_bus *bus) +{ + if (!bus || !bus->name || !strlen(bus->name)) + return -EINVAL; + if (metal_bus_find(bus->name, NULL) == 0) + return -EEXIST; + metal_list_init(&bus->devices); + metal_list_add_tail(&_metal.common.bus_list, &bus->node); + metal_log(METAL_LOG_DEBUG, "registered %s bus\n", bus->name); + return 0; +} + +int metal_bus_unregister(struct metal_bus *bus) +{ + metal_list_del(&bus->node); + if (bus->ops.bus_close) + bus->ops.bus_close(bus); + metal_log(METAL_LOG_DEBUG, "unregistered %s bus\n", bus->name); + return 0; +} + +int metal_bus_find(const char *name, struct metal_bus **result) +{ + struct metal_list *node; + struct metal_bus *bus; + + metal_list_for_each(&_metal.common.bus_list, node) { + bus = metal_container_of(node, struct metal_bus, node); + if (strcmp(bus->name, name) != 0) + continue; + if (result) + *result = bus; + return 0; + } + return -ENOENT; +} + +int metal_device_open(const char *bus_name, const char *dev_name, + struct metal_device **device) +{ + struct metal_bus *bus; + int error; + + if (!bus_name || !strlen(bus_name) || + !dev_name || !strlen(dev_name) || + !device) + return -EINVAL; + + error = metal_bus_find(bus_name, &bus); + if (error) + return error; + + if (!bus->ops.dev_open) + return -ENODEV; + + error = (*bus->ops.dev_open)(bus, dev_name, device); + if (error) + return error; + + return 0; +} + +void metal_device_close(struct metal_device *device) +{ + metal_assert(device && device->bus); + if (device->bus->ops.dev_close) + device->bus->ops.dev_close(device->bus, device); +} + +int metal_register_generic_device(struct metal_device *device) +{ + if (!device->name || !strlen(device->name) || + device->num_regions > METAL_MAX_DEVICE_REGIONS) + return -EINVAL; + + device->bus = &metal_generic_bus; + metal_list_add_tail(&_metal.common.generic_device_list, + &device->node); + return 0; +} + +int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name, + struct metal_device **device) +{ + struct metal_list *node; + struct metal_device *dev; + + (void)bus; + + metal_list_for_each(&_metal.common.generic_device_list, node) { + dev = metal_container_of(node, struct metal_device, node); + if (strcmp(dev->name, dev_name) != 0) + continue; + *device = dev; + return metal_generic_dev_sys_open(dev); + } + + return -ENODEV; +} + +int metal_generic_dev_dma_map(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out) +{ + (void)bus; + (void)device; + int i; + + if (sg_out != sg_in) + memcpy(sg_out, sg_in, nents_in*(sizeof(struct metal_sg))); + for (i = 0; i < nents_in; i++) { + if (dir == METAL_DMA_DEV_W) { + metal_cache_flush(sg_out[i].virt, sg_out[i].len); + } + metal_cache_invalidate(sg_out[i].virt, sg_out[i].len); + } + + return nents_in; +} + +void metal_generic_dev_dma_unmap(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents) +{ + (void)bus; + (void)device; + (void)dir; + int i; + + for (i = 0; i < nents; i++) { + metal_cache_invalidate(sg[i].virt, sg[i].len); + } +} + +struct metal_bus metal_weak metal_generic_bus = { + .name = "generic", + .ops = { + .bus_close = NULL, + .dev_open = metal_generic_dev_open, + .dev_close = NULL, + .dev_irq_ack = NULL, + .dev_dma_map = metal_generic_dev_dma_map, + .dev_dma_unmap = metal_generic_dev_dma_unmap, + }, +}; diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/alloc.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/alloc.h new file mode 100644 index 0000000000..bcceba61a0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/alloc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/alloc.c + * @brief generic libmetal memory allocattion definitions. + */ + +#ifndef __METAL_ALLOC__H__ +#error "Include metal/alloc.h instead of metal/generic/alloc.h" +#endif + +#ifndef __METAL_GENERIC_ALLOC__H__ +#define __METAL_GENERIC_ALLOC__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void *metal_allocate_memory(unsigned int size) +{ + return (malloc(size)); +} + +static inline void metal_free_memory(void *ptr) +{ + free(ptr); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_ALLOC__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/assert.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/assert.h new file mode 100644 index 0000000000..97f88ee5a5 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/assert.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file assert.h + * @brief Generic assertion support. + */ + +#ifndef __METAL_ASSERT__H__ +#error "Include metal/assert.h instead of metal/generic/assert.h" +#endif + +#ifndef __METAL_GENERIC_ASSERT__H__ +#define __METAL_GENERIC_ASSERT__H__ + +#include <assert.h> + +/** + * @brief Assertion macro for bare-metal applications. + * @param cond Condition to evaluate. + */ +#define metal_sys_assert(cond) assert(cond) + +#endif /* __METAL_GENERIC_ASSERT__H__ */ + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cache.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cache.h new file mode 100644 index 0000000000..962ffccfa9 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cache.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/cache.h + * @brief generic cache operation primitives for libmetal. + */ + +#ifndef __METAL_CACHE__H__ +#error "Include metal/cache.h instead of metal/generic/cache.h" +#endif + +#ifndef __METAL_GENERIC_CACHE__H__ +#define __METAL_GENERIC_CACHE__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void metal_machine_cache_flush(void *addr, unsigned int len); +extern void metal_machine_cache_invalidate(void *addr, unsigned int len); + +static inline void __metal_cache_flush(void *addr, unsigned int len) +{ + metal_machine_cache_flush(addr, len); +} + +static inline void __metal_cache_invalidate(void *addr, unsigned int len) +{ + metal_machine_cache_invalidate(addr, len); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_CACHE__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/condition.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/condition.c new file mode 100644 index 0000000000..493af6fc23 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/condition.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/condition.c + * @brief Generic libmetal condition variable handling. + */ + +#include <metal/condition.h> +#include <metal/irq.h> + +extern void metal_generic_default_poll(void); + +int metal_condition_wait(struct metal_condition *cv, + metal_mutex_t *m) +{ + metal_mutex_t *tmpm = 0; + int v; + unsigned int flags; + + /* Check if the mutex has been acquired */ + if (!cv || !m || !metal_mutex_is_acquired(m)) + return -EINVAL; + + if (!atomic_compare_exchange_strong(&cv->m->v, &tmpm->v, m->v)) { + if (m != tmpm) + return -EINVAL; + } + + v = atomic_load(&cv->v); + + /* Release the mutex first. */ + metal_mutex_release(m); + do { + flags = metal_irq_save_disable(); + if (atomic_load(&cv->v) != v) { + metal_irq_restore_enable(flags); + break; + } + metal_generic_default_poll(); + metal_irq_restore_enable(flags); + } while(1); + /* Acquire the mutex again. */ + metal_mutex_acquire(m); + return 0; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/condition.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/condition.h new file mode 100644 index 0000000000..abb2e8c73c --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/condition.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/condition.h + * @brief Generic condition variable primitives for libmetal. + */ + +#ifndef __METAL_CONDITION__H__ +#error "Include metal/condition.h instead of metal/generic/condition.h" +#endif + +#ifndef __METAL_GENERIC_CONDITION__H__ +#define __METAL_GENERIC_CONDITION__H__ + +#include <unistd.h> +#include <metal/atomic.h> +#include <stdint.h> +#include <limits.h> +#include <metal/errno.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct metal_condition { + metal_mutex_t *m; /**< mutex. + The condition variable is attached to + this mutex when it is waiting. + It is also used to check correctness + in case there are multiple waiters. */ + + atomic_int v; /**< condition variable value. */ +}; + +/** Static metal condition variable initialization. */ +#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) } + +static inline void metal_condition_init(struct metal_condition *cv) +{ + cv->m = NULL; + atomic_init(&cv->v, 0); +} + +static inline int metal_condition_signal(struct metal_condition *cv) +{ + if (!cv) + return -EINVAL; + + /** wake up waiters if there are any. */ + atomic_fetch_add(&cv->v, 1); + return 0; +} + +static inline int metal_condition_broadcast(struct metal_condition *cv) +{ + return metal_condition_signal(cv); +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_CONDITION__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.c new file mode 100644 index 0000000000..7b0b3856fe --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/sys.c + * @brief machine specific system primitives implementation. + */ + + +#include "metal/io.h" +#include "metal/sys.h" + +void sys_irq_restore_enable(unsigned int flags) +{ +} + +unsigned int sys_irq_save_disable(void) +{ + return 0; +} + +void metal_machine_cache_flush(void *addr, unsigned int len) +{ + (void)addr; + (void)len; +} + +void metal_machine_cache_invalidate(void *addr, unsigned int len) +{ + (void)addr; + (void)len; +} + +/** + * @brief poll function until some event happens + */ +void __attribute__((weak)) metal_generic_default_poll(void) +{ +} + +void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa, + size_t size, unsigned int flags) +{ + (void)va; + (void)pa; + (void)size; + (void)flags; + + return va; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.h new file mode 100644 index 0000000000..7fd8144cbf --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/cortexm/sys.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/mp1_m4/sys.h + * @brief generic mp1_m4 system primitives for libmetal. + */ + +#ifndef __METAL_GENERIC_SYS__H__ +#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h" +#endif + +#ifndef __METAL_GENERIC_MP1_M4_SYS__H__ +#define __METAL_GENERIC_MP1_M4_SYS__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MAX_IRQS) +#define MAX_IRQS 8 /**< maximum number of irqs */ +#endif + +static inline void sys_irq_enable(unsigned int vector) +{ + (void)vector; +} + +static inline void sys_irq_disable(unsigned int vector) +{ + (void)vector; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_MP1_M4_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_device.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_device.c new file mode 100644 index 0000000000..d01fd3cd75 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_device.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/device.c + * @brief Generic libmetal device operations. + */ + +#include <metal/device.h> +#include <metal/io.h> +#include <metal/sys.h> +#include <metal/utilities.h> + +int metal_generic_dev_sys_open(struct metal_device *dev) +{ + struct metal_io_region *io; + unsigned i; + + /* map I/O memory regions */ + for (i = 0; i < dev->num_regions; i++) { + io = &dev->regions[i]; + if (!io->size) + break; + metal_sys_io_mem_map(io); + } + + return 0; +} + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_init.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_init.c new file mode 100644 index 0000000000..833b1cd341 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_init.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/init.c + * @brief Generic libmetal initialization. + */ + +#include <metal/sys.h> +#include <metal/utilities.h> +#include <metal/device.h> + +struct metal_state _metal; + +int metal_sys_init(const struct metal_init_params *params) +{ + metal_unused(params); + metal_bus_register(&metal_generic_bus); + return 0; +} + +void metal_sys_finish(void) +{ + metal_bus_unregister(&metal_generic_bus); +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_io.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_io.c new file mode 100644 index 0000000000..670f239d5a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_io.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/io.c + * @brief Generic libmetal io operations + */ + +#include <metal/io.h> + +void metal_sys_io_mem_map(struct metal_io_region *io) +{ + unsigned long p; + size_t psize; + size_t *va; + + va = (size_t *)io->virt; + psize = io->size; + if (psize) { + if (psize >> io->page_shift) + psize = (size_t)1 << io->page_shift; + for (p = 0; p <= (io->size >> io->page_shift); p++) { + metal_machine_io_mem_map(va, io->physmap[p], + psize, io->mem_flags); + va += psize; + } + } +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.c new file mode 100644 index 0000000000..e61bc7e836 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2016 - 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/irq.c + * @brief generic libmetal irq definitions. + */ + +#include <metal/errno.h> +#include <metal/irq.h> +#include <metal/sys.h> +#include <metal/log.h> +#include <metal/mutex.h> +#include <metal/list.h> +#include <metal/utilities.h> +#include <metal/alloc.h> + +/** IRQ handlers descriptor structure */ +struct metal_irq_hddesc { + metal_irq_handler hd; /**< irq handler */ + void *drv_id; /**< id to identify the driver + of the irq handler */ + struct metal_device *dev; /**< device identifier */ + struct metal_list node; /**< node on irq handlers list */ +}; + +/** IRQ descriptor structure */ +struct metal_irq_desc { + int irq; /**< interrupt number */ + struct metal_list hdls; /**< interrupt handlers */ + struct metal_list node; /**< node on irqs list */ +}; + +/** IRQ state structure */ +struct metal_irqs_state { + struct metal_list irqs; /**< interrupt descriptors */ + metal_mutex_t irq_lock; /**< access lock */ +}; + +static struct metal_irqs_state _irqs = { + .irqs = METAL_INIT_LIST(_irqs.irqs), + .irq_lock = METAL_MUTEX_INIT(_irqs.irq_lock), +}; + +int metal_irq_register(int irq, + metal_irq_handler hd, + struct metal_device *dev, + void *drv_id) +{ + struct metal_irq_desc *irq_p = NULL; + struct metal_irq_hddesc *hdl_p; + struct metal_list *node; + unsigned int irq_flags_save; + + if (irq < 0) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d need to be a positive number\n", + __func__, irq); + return -EINVAL; + } + + if ((drv_id == NULL) || (hd == NULL)) { + metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n", + __func__, irq); + return -EINVAL; + } + + /* Search for irq in list */ + metal_mutex_acquire(&_irqs.irq_lock); + metal_list_for_each(&_irqs.irqs, node) { + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if (irq_p->irq == irq) { + struct metal_list *h_node; + + /* Check if drv_id already exist */ + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + /* if drv_id already exist reject */ + if ((hdl_p->drv_id == drv_id) && + ((dev == NULL) || (hdl_p->dev == dev))) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d already registered." + "Will not register again.\n", + __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return -EINVAL; + } + } + /* irq found and drv_id not used, get out of metal_list_for_each */ + break; + } + } + + /* Either need to add handler to an existing list or to a new one */ + hdl_p = metal_allocate_memory(sizeof(struct metal_irq_hddesc)); + if (hdl_p == NULL) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d cannot allocate mem for drv_id %d.\n", + __func__, irq, drv_id); + metal_mutex_release(&_irqs.irq_lock); + return -ENOMEM; + } + hdl_p->hd = hd; + hdl_p->drv_id = drv_id; + hdl_p->dev = dev; + + /* interrupt already registered, add handler to existing list*/ + if ((irq_p != NULL) && (irq_p->irq == irq)) { + irq_flags_save = metal_irq_save_disable(); + metal_list_add_tail(&irq_p->hdls, &hdl_p->node); + metal_irq_restore_enable(irq_flags_save); + + metal_log(METAL_LOG_DEBUG, "%s: success, irq %d add drv_id %p \n", + __func__, irq, drv_id); + metal_mutex_release(&_irqs.irq_lock); + return 0; + } + + /* interrupt was not already registered, add */ + irq_p = metal_allocate_memory(sizeof(struct metal_irq_desc)); + if (irq_p == NULL) { + metal_log(METAL_LOG_ERROR, "%s: irq %d cannot allocate mem.\n", + __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return -ENOMEM; + } + irq_p->irq = irq; + metal_list_init(&irq_p->hdls); + metal_list_add_tail(&irq_p->hdls, &hdl_p->node); + + irq_flags_save = metal_irq_save_disable(); + metal_list_add_tail(&_irqs.irqs, &irq_p->node); + metal_irq_restore_enable(irq_flags_save); + + metal_log(METAL_LOG_DEBUG, "%s: success, added irq %d\n", __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return 0; +} + +/* helper function for metal_irq_unregister() */ +static void metal_irq_delete_node(struct metal_list *node, void *p_to_free) +{ + unsigned int irq_flags_save; + + irq_flags_save=metal_irq_save_disable(); + metal_list_del(node); + metal_irq_restore_enable(irq_flags_save); + metal_free_memory(p_to_free); +} + +int metal_irq_unregister(int irq, + metal_irq_handler hd, + struct metal_device *dev, + void *drv_id) +{ + struct metal_irq_desc *irq_p; + struct metal_list *node; + + if (irq < 0) { + metal_log(METAL_LOG_ERROR, "%s: irq %d need to be a positive number\n", + __func__, irq); + return -EINVAL; + } + + /* Search for irq in list */ + metal_mutex_acquire(&_irqs.irq_lock); + metal_list_for_each(&_irqs.irqs, node) { + + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if (irq_p->irq == irq) { + struct metal_list *h_node, *h_prenode; + struct metal_irq_hddesc *hdl_p; + unsigned int delete_count = 0; + + metal_log(METAL_LOG_DEBUG, "%s: found irq %d\n", + __func__, irq); + + /* Search through handlers */ + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + if (((hd == NULL) || (hdl_p->hd == hd)) && + ((drv_id == NULL) || (hdl_p->drv_id == drv_id)) && + ((dev == NULL) || (hdl_p->dev == dev))) { + metal_log(METAL_LOG_DEBUG, + "%s: unregister hd=%p drv_id=%p dev=%p\n", + __func__, hdl_p->hd, hdl_p->drv_id, hdl_p->dev); + h_prenode = h_node->prev; + metal_irq_delete_node(h_node, hdl_p); + h_node = h_prenode; + delete_count++; + } + } + + /* we did not find any handler to delete */ + if (!delete_count) { + metal_log(METAL_LOG_DEBUG, "%s: No matching entry\n", + __func__); + metal_mutex_release(&_irqs.irq_lock); + return -ENOENT; + + } + + /* if interrupt handlers list is empty, unregister interrupt */ + if (metal_list_is_empty(&irq_p->hdls)) { + metal_log(METAL_LOG_DEBUG, + "%s: handlers list empty, unregister interrupt\n", + __func__); + metal_irq_delete_node(node, irq_p); + } + + metal_log(METAL_LOG_DEBUG, "%s: success\n", __func__); + + metal_mutex_release(&_irqs.irq_lock); + return 0; + } + } + + metal_log(METAL_LOG_DEBUG, "%s: No matching IRQ entry\n", __func__); + + metal_mutex_release(&_irqs.irq_lock); + return -ENOENT; +} + +unsigned int metal_irq_save_disable(void) +{ + return sys_irq_save_disable(); +} + +void metal_irq_restore_enable(unsigned int flags) +{ + sys_irq_restore_enable(flags); +} + +void metal_irq_enable(unsigned int vector) +{ + sys_irq_enable(vector); +} + +void metal_irq_disable(unsigned int vector) +{ + sys_irq_disable(vector); +} + +/** + * @brief default handler + */ +void metal_irq_isr(unsigned int vector) +{ + struct metal_list *node; + struct metal_irq_desc *irq_p; + + metal_list_for_each(&_irqs.irqs, node) { + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if ((unsigned int)irq_p->irq == vector) { + struct metal_list *h_node; + struct metal_irq_hddesc *hdl_p; + + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + (hdl_p->hd)(vector, hdl_p->drv_id); + } + } + } +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.h new file mode 100644 index 0000000000..5744275dc6 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_irq.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/irq.c + * @brief Generic libmetal irq definitions. + */ + +#ifndef __METAL_IRQ__H__ +#error "Include metal/irq.h instead of metal/generic/irq.h" +#endif + +#ifndef __METAL_GENERIC_IRQ__H__ +#define __METAL_GENERIC_IRQ__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief default interrupt handler + * @param[in] vector interrupt vector + */ +void metal_irq_isr(unsigned int vector); + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_IRQ__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_shmem.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_shmem.c new file mode 100644 index 0000000000..8a28d8ae19 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_shmem.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/shmem.c + * @brief Generic libmetal shared memory handling. + */ + +#include <metal/shmem.h> + +int metal_shmem_open(const char *name, size_t size, + struct metal_io_region **io) +{ + return metal_shmem_open_generic(name, size, io); +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_time.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_time.c new file mode 100644 index 0000000000..fff76192aa --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/generic_time.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/time.c + * @brief Generic libmetal time handling. + */ + +#include <metal/time.h> + +unsigned long long metal_get_timestamp(void) +{ + /* TODO: Implement timestamp for generic system */ + return 0; +} + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/io.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/io.h new file mode 100644 index 0000000000..adbbc44774 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/io.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/io.h + * @brief Generic specific io definitions. + */ + +#ifndef __METAL_IO__H__ +#error "Include metal/io.h instead of metal/generic/io.h" +#endif + +#ifndef __METAL_GENERIC_IO__H__ +#define __METAL_GENERIC_IO__H__ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef METAL_INTERNAL + +/** + * @brief memory mapping for an I/O region + */ +void metal_sys_io_mem_map(struct metal_io_region *io); + +/** + * @brief memory mapping + */ +void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa, + size_t size, unsigned int flags); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_IO__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/log.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/log.h new file mode 100644 index 0000000000..32611288ad --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/log.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Linaro nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/log.h + * @brief Generic libmetal log handler definition. + */ + +#ifndef __METAL_METAL_LOG__H__ +#error "Include metal/log.h instead of metal/generic/log.h" +#endif + +#ifndef __METAL_GENERIC_LOG__H__ +#define __METAL_GENERIC_LOG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_LOG__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/mutex.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/mutex.h new file mode 100644 index 0000000000..3613c194d1 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/mutex.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/mutex.h + * @brief Generic mutex primitives for libmetal. + */ + +#ifndef __METAL_MUTEX__H__ +#error "Include metal/mutex.h instead of metal/generic/mutex.h" +#endif + +#ifndef __METAL_GENERIC_MUTEX__H__ +#define __METAL_GENERIC_MUTEX__H__ + +#include <metal/atomic.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + union{ + atomic_int v; + atomic_flag w; + }; +} metal_mutex_t; + +/* + * METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct + * or global + */ +#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) } +/* + * METAL_MUTEX_DEFINE - used for defining and initializing a global or + * static singleton mutex + */ +#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m) + +static inline void __metal_mutex_init(metal_mutex_t *mutex) +{ + atomic_store(&mutex->v, 0); +} + +static inline void __metal_mutex_deinit(metal_mutex_t *mutex) +{ + (void)mutex; +} + +static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex) +{ + return 1 - atomic_flag_test_and_set(&mutex->w); +} + +static inline void __metal_mutex_acquire(metal_mutex_t *mutex) +{ + while (atomic_flag_test_and_set(&mutex->w)) { + ; + } +} + +static inline void __metal_mutex_release(metal_mutex_t *mutex) +{ + atomic_flag_clear(&mutex->w); +} + +static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex) +{ + return atomic_load(&mutex->v); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_MUTEX__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/sleep.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/sleep.h new file mode 100644 index 0000000000..aa86df492e --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/sleep.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/sleep.h + * @brief Generic sleep primitives for libmetal. + */ + +#ifndef __METAL_SLEEP__H__ +#error "Include metal/sleep.h instead of metal/generic/sleep.h" +#endif + +#ifndef __METAL_GENERIC_SLEEP__H__ +#define __METAL_GENERIC_SLEEP__H__ + +#include <metal/utilities.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline int __metal_sleep_usec(unsigned int usec) +{ + metal_unused(usec); + /* Fix me */ + return 0; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_SLEEP__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/sys.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/sys.h new file mode 100644 index 0000000000..320af6b0b7 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/system/generic/sys.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/sys.h + * @brief Generic system primitives for libmetal. + */ + +#ifndef __METAL_SYS__H__ +#error "Include metal/sys.h instead of metal/generic/sys.h" +#endif + +#ifndef __METAL_GENERIC_SYS__H__ +#define __METAL_GENERIC_SYS__H__ + +#include <metal/errno.h> +#include <fcntl.h> +#include <libgen.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "./@PROJECT_MACHINE@/sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef METAL_MAX_DEVICE_REGIONS +#define METAL_MAX_DEVICE_REGIONS 1 +#endif + +/** Structure of generic libmetal runtime state. */ +struct metal_state { + + /** Common (system independent) data. */ + struct metal_common_state common; +}; + +#ifdef METAL_INTERNAL + +/** + * @brief restore interrupts to state before disable_global_interrupt() + */ +void sys_irq_restore_enable(unsigned int flags); + +/** + * @brief disable all interrupts + */ +unsigned int sys_irq_save_disable(void); + +#endif /* METAL_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GENERIC_SYS__H__ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/version.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/version.c new file mode 100644 index 0000000000..9595a85f37 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/libmetal/lib/version.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/config.h> + +int metal_ver_major(void) +{ + return METAL_VER_MAJOR; +} + +int metal_ver_minor(void) +{ + return METAL_VER_MINOR; +} + +int metal_ver_patch(void) +{ + return METAL_VER_PATCH; +} + +const char *metal_ver(void) +{ + return METAL_VER; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/compiler.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/compiler.h new file mode 100644 index 0000000000..acb4c9b369 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/compiler.h @@ -0,0 +1,71 @@ +#ifndef _COMPILER_H_ +#define _COMPILER_H_ + +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * compiler.h + * + * DESCRIPTION + * + * This file defines compiler-specific macros. + * + ***************************************************************************/ +#if defined __cplusplus +extern "C" { +#endif + +/* IAR ARM build tools */ +#if defined(__ICCARM__) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN __packed +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END +#endif + +/* GNUC */ +#elif defined(__GNUC__) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END __attribute__((__packed__)) +#endif + +/* ARM GCC */ +#elif defined(__CC_ARM) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN _Pragma("pack(1U)") +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END _Pragma("pack()") +#endif + +#else +/* + * There is no default definition here to avoid wrong structures packing in case + * of not supported compiler + */ +#error Please implement the structure packing macros for your compiler here! +#endif + +#if defined __cplusplus +} +#endif + +#endif /* _COMPILER_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/elf_loader.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/elf_loader.h new file mode 100644 index 0000000000..3c6ec4af15 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/elf_loader.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ELF_LOADER_H_ +#define ELF_LOADER_H_ + +#include <openamp/remoteproc.h> +#include <openamp/remoteproc_loader.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* ELF32 base types - 32-bit. */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* ELF64 base types - 64-bit. */ +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Size of ELF identifier field in the ELF file header. */ +#define EI_NIDENT 16 + +/* ELF32 file header */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* ELF64 file header */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* e_ident */ +#define ET_NONE 0 +#define ET_REL 1 /* Re-locatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOOS 0xfe00 /* Operating system-specific */ +#define ET_HIOS 0xfeff /* Operating system-specific */ +#define ET_LOPROC 0xff00 /* remote_proc-specific */ +#define ET_HIPROC 0xffff /* remote_proc-specific */ + +/* e_machine */ +#define EM_ARM 40 /* ARM/Thumb Architecture */ + +/* e_version */ +#define EV_CURRENT 1 /* Current version */ + +/* e_ident[] Identification Indexes */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class */ +#define EI_DATA 5 /* Data encoding */ +#define EI_VERSION 6 /* File version */ +#define EI_OSABI 7 /* Operating system/ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* Start of padding bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +/* + * EI_MAG0 to EI_MAG3 - A file's first 4 bytes hold amagic number, identifying + * the file as an ELF object file + */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +/* + * EI_CLASS - The next byte, e_ident[EI_CLASS], identifies the file's class, or + * capacity. + */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +/* + * EI_DATA - Byte e_ident[EI_DATA] specifies the data encoding of the + * remote_proc-specific data in the object file. The following encodings are + * currently defined. + */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* See Data encodings, below */ +#define ELFDATA2MSB 2 /* See Data encodings, below */ + +/* EI_OSABI - We do not define an OS specific ABI */ +#define ELFOSABI_NONE 0 + +/* ELF32 program header */ +typedef struct elf32_phdr{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* ELF64 program header */ +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +/* segment types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* ELF32 section header. */ +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* ELF64 section header. */ +typedef struct { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_LOOS 0x60000000 +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* Relocation entry (without addend) */ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + +} Elf32_Rel; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; + +} Elf64_Rel; + +/* Relocation entry with addend */ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; + +} Elf32_Rela; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +/* Macros to extract information from 'r_info' field of relocation entries */ +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) + +/* Symbol table entry */ +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; + +} Elf32_Sym; + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +/* ARM specific dynamic relocation codes */ +#define R_ARM_GLOB_DAT 21 /* 0x15 */ +#define R_ARM_JUMP_SLOT 22 /* 0x16 */ +#define R_ARM_RELATIVE 23 /* 0x17 */ +#define R_ARM_ABS32 2 /* 0x02 */ + +/* ELF decoding information */ +struct elf32_info { + Elf32_Ehdr ehdr; + unsigned int load_state; + Elf32_Phdr *phdrs; + Elf32_Shdr *shdrs; + void *shstrtab; +}; + +struct elf64_info { + Elf64_Ehdr ehdr; + unsigned int load_state; + Elf64_Phdr *phdrs; + Elf64_Shdr *shdrs; + void *shstrtab; +}; + +#define ELF_STATE_INIT 0x0UL +#define ELF_STATE_WAIT_FOR_PHDRS 0x100UL +#define ELF_STATE_WAIT_FOR_SHDRS 0x200UL +#define ELF_STATE_WAIT_FOR_SHSTRTAB 0x400UL +#define ELF_STATE_HDRS_COMPLETE 0x800UL +#define ELF_STATE_MASK 0xFF00UL +#define ELF_NEXT_SEGMENT_MASK 0x00FFUL + +extern struct loader_ops elf_ops; + +/** + * elf_identify - check if it is an ELF file + * + * It will check if the input image header is an ELF header. + * + * @img_data: firmware private data which will be passed to user defined loader + * operations + * @len: firmware header length + * + * return 0 for success or negative value for failure. + */ +int elf_identify(const void *img_data, size_t len); + +/** + * elf_load_header - Load ELF headers + * + * It will get the ELF header, the program header, and the section header. + * + * @img_data: image data + * @offset: input image data offset to the start of image file + * @len: input image data length + * @img_info: pointer to store image information data + * @last_load_state: last state return by this function + * @noffset: pointer to next offset required by loading ELF header + * @nlen: pointer to next data length required by loading ELF header + * + * return ELF loading header state, or negative value for failure + */ +int elf_load_header(const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + size_t *noffset, size_t *nlen); + +/** + * elf_load - load ELF data + * + * It will parse the ELF image and return the target device address, + * offset to the start of the ELF image of the data to load and the + * length of the data to load. + * + * @rproc: pointer to remoteproc instance + * @img_data: image data which will passed to the function. + * it can be NULL, if image data doesn't need to be handled + * by the load function. E.g. binary data which was + * loaded to the target memory. + * @offset: last loaded image data offset to the start of image file + * @len: last loaded image data length + * @img_info: pointer to store image information data + * @last_load_state: the returned state of the last function call. + * @da: target device address, if the data to load is not for target memory + * the da will be set to ANY. + * @noffset: pointer to next offset required by loading ELF header + * @nlen: pointer to next data length required by loading ELF header + * @padding: value to pad it is possible that a size of a segment in memory + * is larger than what it is in the ELF image. e.g. a segment + * can have stack section .bss. It doesn't need to copy image file + * space, in this case, it will be packed with 0. + * @nmemsize: pointer to next data target memory size. The size of a segment + * in the target memory can be larger than the its size in the + * image file. + * + * return 0 for success, otherwise negative value for failure + */ +int elf_load(struct remoteproc *rproc, const void *img_data, + size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize); + +/** + * elf_release - Release ELF image information + * + * It will release ELF image information data. + * + * @img_info: pointer to ELF image information + */ +void elf_release(void *img_info); + +/** + * elf_get_entry - Get entry point + * + * It will return entry point specified in the ELF file. + * + * @img_info: pointer to ELF image information + * + * return entry address + */ +metal_phys_addr_t elf_get_entry(void *img_info); + +/** + * elf_locate_rsc_table - locate the resource table information + * + * It will return the length of the resource table, and the device address of + * the resource table. + * + * @img_info: pointer to ELF image information + * @da: pointer to the device address + * @offset: pointer to the offset to in the ELF image of the resource + * table section. + * @size: pointer to the size of the resource table section. + * + * return 0 if successfully locate the resource table, negative value for + * failure. + */ +int elf_locate_rsc_table(void *img_info, metal_phys_addr_t *da, + size_t *offset, size_t *size); + +#if defined __cplusplus +} +#endif + +#endif /* ELF_LOADER_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/open_amp.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/open_amp.h new file mode 100644 index 0000000000..1a01688a9f --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/open_amp.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OPEN_AMP_H_ +#define OPEN_AMP_H_ + +#include <openamp/rpmsg.h> +#include <openamp/rpmsg_virtio.h> +#include <openamp/remoteproc.h> +#include <openamp/remoteproc_virtio.h> + + +#endif /* OPEN_AMP_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc.h new file mode 100644 index 0000000000..90d908729c --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc.h @@ -0,0 +1,871 @@ +/* + * Remoteproc Framework + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REMOTEPROC_H +#define REMOTEPROC_H + +#include <metal/io.h> +#include <metal/mutex.h> +#include <openamp/compiler.h> + +#if defined __cplusplus +extern "C" { +#endif + +#define RSC_NOTIFY_ID_ANY 0xFFFFFFFFUL + +/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote remote_proc. It may also include configuration entries. + * If needed, the remote remote_proc firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * Some resources entries are mere announcements, where the host is informed + * of specific remoteproc configuration. Other entries require the host to + * do something (e.g. allocate a system resource). Sometimes a negotiation + * is expected, where the firmware requests a resource, and once allocated, + * the host should provide back its details (e.g. address of an allocated + * memory region). + * + * The header of the resource table, as expressed by this structure, + * contains a version number (should we need to change this format in the + * future), the number of available resource entries, and their offsets + * in the table. + * + * Immediately following this header are the resource entries themselves, + * each of which begins with a resource entry header (as described below). + */ +OPENAMP_PACKED_BEGIN +struct resource_table { + uint32_t ver; + uint32_t num; + uint32_t reserved[2]; + uint32_t offset[0]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_hdr - firmware resource entry header + * @type: resource type + * @data: resource data + * + * Every resource entry begins with a 'struct fw_rsc_hdr' header providing + * its @type. The content of the entry itself will immediately follow + * this header, and it should be parsed according to the resource type. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_hdr { + uint32_t type; + uint8_t data[0]; +} OPENAMP_PACKED_END; + +/** + * enum fw_resource_type - types of resource entries + * + * @RSC_CARVEOUT: request for allocation of a physically contiguous + * memory region. + * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. + * @RSC_TRACE: announces the availability of a trace buffer into which + * the remote remote_proc will be writing logs. + * @RSC_VDEV: declare support for a virtio device, and serve as its + * virtio header. + * @RSC_VENDOR_START: start of the vendor specific resource types range + * @RSC_VENDOR_END : end of the vendor specific resource types range + * @RSC_LAST: just keep this one at the end + * + * For more details regarding a specific resource type, please see its + * dedicated structure below. + * + * Please note that these values are used as indices to the rproc_handle_rsc + * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to + * check the validity of an index before the lookup table is accessed, so + * please update it as needed. + */ +enum fw_resource_type { + RSC_CARVEOUT = 0, + RSC_DEVMEM = 1, + RSC_TRACE = 2, + RSC_VDEV = 3, + RSC_RPROC_MEM = 4, + RSC_FW_CHKSUM = 5, + RSC_LAST = 6, + RSC_VENDOR_START = 128, + RSC_VENDOR_END = 512, +}; + +#define FW_RSC_ADDR_ANY (0xFFFFFFFFFFFFFFFF) +#define FW_RSC_U32_ADDR_ANY (0xFFFFFFFF) + +/** + * struct fw_rsc_carveout - physically contiguous memory request + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @flags: iommu protection flags + * @reserved: reserved (must be zero) + * @name: human-readable name of the requested memory region + * + * This resource entry requests the host to allocate a physically contiguous + * memory region. + * + * These request entries should precede other firmware resource entries, + * as other entries might request placing other data objects inside + * these memory regions (e.g. data/code segments, trace resource entries, ...). + * + * Allocating memory this way helps utilizing the reserved physical memory + * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries + * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB + * pressure is important; it may have a substantial impact on performance. + * + * If the firmware is compiled with static addresses, then @da should specify + * the expected device address of this memory region. If @da is set to + * FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then + * overwrite @da with the dynamically allocated address. + * + * We will always use @da to negotiate the device addresses, even if it + * isn't using an iommu. In that case, though, it will obviously contain + * physical addresses. + * + * Some remote remote_procs needs to know the allocated physical address + * even if they do use an iommu. This is needed, e.g., if they control + * hardware accelerators which access the physical memory directly (this + * is the case with OMAP4 for instance). In that case, the host will + * overwrite @pa with the dynamically allocated physical address. + * Generally we don't want to expose physical addresses if we don't have to + * (remote remote_procs are generally _not_ trusted), so we might want to + * change this to happen _only_ when explicitly required by the hardware. + * + * @flags is used to provide IOMMU protection flags, and @name should + * (optionally) contain a human readable name of this carveout region + * (mainly for debugging purposes). + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_carveout { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t flags; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_devmem - iommu mapping request + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @flags: iommu protection flags + * @reserved: reserved (must be zero) + * @name: human-readable name of the requested region to be mapped + * + * This resource entry requests the host to iommu map a physically contiguous + * memory region. This is needed in case the remote remote_proc requires + * access to certain memory-based peripherals; _never_ use it to access + * regular memory. + * + * This is obviously only needed if the remote remote_proc is accessing memory + * via an iommu. + * + * @da should specify the required device address, @pa should specify + * the physical address we want to map, @len should specify the size of + * the mapping and @flags is the IOMMU protection flags. As always, @name may + * (optionally) contain a human readable name of this mapping (mainly for + * debugging purposes). + * + * Note: at this point we just "trust" those devmem entries to contain valid + * physical addresses, but this isn't safe and will be changed: eventually we + * want remoteproc implementations to provide us ranges of physical addresses + * the firmware is allowed to request, and not allow firmwares to request + * access to physical addresses that are outside those ranges. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_devmem { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t flags; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_trace - trace buffer declaration + * @da: device address + * @len: length (in bytes) + * @reserved: reserved (must be zero) + * @name: human-readable name of the trace buffer + * + * This resource entry provides the host information about a trace buffer + * into which the remote remote_proc will write log messages. + * + * @da specifies the device address of the buffer, @len specifies + * its size, and @name may contain a human readable name of the trace buffer. + * + * After booting the remote remote_proc, the trace buffers are exposed to the + * user via debugfs entries (called trace0, trace1, etc..). + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_trace { + uint32_t type; + uint32_t da; + uint32_t len; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vdev_vring - vring descriptor entry + * @da: device address + * @align: the alignment between the consumer and producer parts of the vring + * @num: num of buffers supported by this vring (must be power of two) + * @notifyid is a unique rproc-wide notify index for this vring. This notify + * index is used when kicking a remote remote_proc, to let it know that this + * vring is triggered. + * @reserved: reserved (must be zero) + * + * This descriptor is not a resource entry by itself; it is part of the + * vdev resource type (see below). + * + * Note that @da should either contain the device address where + * the remote remote_proc is expecting the vring, or indicate that + * dynamically allocation of the vring's device address is supported. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vdev_vring { + uint32_t da; + uint32_t align; + uint32_t num; + uint32_t notifyid; + uint32_t reserved; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vdev - virtio device header + * @id: virtio device id (as in virtio_ids.h) + * @notifyid is a unique rproc-wide notify index for this vdev. This notify + * index is used when kicking a remote remote_proc, to let it know that the + * status/features of this vdev have changes. + * @dfeatures specifies the virtio device features supported by the firmware + * @gfeatures is a place holder used by the host to write back the + * negotiated features that are supported by both sides. + * @config_len is the size of the virtio config space of this vdev. The config + * space lies in the resource table immediate after this vdev header. + * @status is a place holder where the host will indicate its virtio progress. + * @num_of_vrings indicates how many vrings are described in this vdev header + * @reserved: reserved (must be zero) + * @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'. + * + * This resource is a virtio device header: it provides information about + * the vdev, and is then used by the host and its peer remote remote_procs + * to negotiate and share certain virtio properties. + * + * By providing this resource entry, the firmware essentially asks remoteproc + * to statically allocate a vdev upon registration of the rproc (dynamic vdev + * allocation is not yet supported). + * + * Note: unlike virtualization systems, the term 'host' here means + * the Linux side which is running remoteproc to control the remote + * remote_procs. We use the name 'gfeatures' to comply with virtio's terms, + * though there isn't really any virtualized guest OS here: it's the host + * which is responsible for negotiating the final features. + * Yeah, it's a bit confusing. + * + * Note: immediately following this structure is the virtio config space for + * this vdev (which is specific to the vdev; for more info, read the virtio + * spec). the size of the config space is specified by @config_len. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vdev { + uint32_t type; + uint32_t id; + uint32_t notifyid; + uint32_t dfeatures; + uint32_t gfeatures; + uint32_t config_len; + uint8_t status; + uint8_t num_of_vrings; + uint8_t reserved[2]; + struct fw_rsc_vdev_vring vring[0]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vendor - remote processor vendor specific resource + * @len: length of the resource + * + * This resource entry tells the host the vendor specific resource + * required by the remote. + * + * These request entries should precede other shared resource entries + * such as vdevs, vrings. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vendor { + uint32_t type; + uint32_t len; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_rproc_mem - remote processor memory + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @reserved: reserved (must be zero) + * + * This resource entry tells the host to the remote processor + * memory that the host can be used as shared memory. + * + * These request entries should precede other shared resource entries + * such as vdevs, vrings. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_rproc_mem { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t reserved; +} OPENAMP_PACKED_END; + +/* + * struct fw_rsc_fw_chksum - firmware checksum + * @algo: algorithm to generate the cheksum + * @chksum: checksum of the firmware loadable sections. + * + * This resource entry provides checksum for the firmware loadable sections. + * It is used to check if the remote already runs with the expected firmware to + * decide if it needs to start the remote if the remote is already running. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_fw_chksum { + uint32_t type; + uint8_t algo[16]; + uint8_t chksum[64]; +} OPENAMP_PACKED_END; + +struct loader_ops; +struct image_store_ops; +struct remoteproc_ops; + +/** + * struct remoteproc_mem + * + * This structure presents the memory used by the remote processor + * + * @da: device memory + * @pa: physical memory + * @size: size of the memory + * @io: pointer to the I/O region + * @node: list node + */ +struct remoteproc_mem { + metal_phys_addr_t da; + metal_phys_addr_t pa; + size_t size; + char name[32]; + struct metal_io_region *io; + struct metal_list node; +}; + +/** + * struct remoteproc + * + * This structure is maintained by the remoteproc to represent the remote + * processor instance. This structure acts as a prime parameter to use + * the remoteproc APIs. + * + * @bootadd: boot address + * @loader: executable loader + * @lock: mutext lock + * @ops: remoteproc operations + * @rsc_table: pointer to resource table + * @rsc_len: length of resource table + * @rsc_io: metal I/O region of resource table + * @mems: remoteproc memories + * @vdevs: remoteproc virtio devices + * @bitmap: bitmap for notify IDs for remoteproc subdevices + * @state: remote processor state + * @priv: private data + */ +struct remoteproc { + metal_mutex_t lock; + void *rsc_table; + size_t rsc_len; + struct metal_io_region *rsc_io; + struct metal_list mems; + struct metal_list vdevs; + unsigned long bitmap; + struct remoteproc_ops *ops; + metal_phys_addr_t bootaddr; + struct loader_ops *loader; + unsigned int state; + void *priv; +}; + +/** + * struct remoteproc_ops + * + * remoteproc operations needs to be implemented by each remoteproc driver + * + * @init: initialize the remoteproc instance + * @remove: remove the remoteproc instance + * @mmap: memory mapped the mempory with physical address or destination + * address as input. + * @handle_rsc: handle the vendor specific resource + * @config: configure the remoteproc to make it ready to load and run + * executable + * @start: kick the remoteproc to run application + * @stop: stop the remoteproc from running application, the resource such as + * memory may not be off. + * @shutdown: shutdown the remoteproc and release its resources. + * @notify: notify the remote + */ +struct remoteproc_ops { + struct remoteproc *(*init)(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *arg); + void (*remove)(struct remoteproc *rproc); + void *(*mmap)(struct remoteproc *rproc, + metal_phys_addr_t *pa, metal_phys_addr_t *da, + size_t size, unsigned int attribute, + struct metal_io_region **io); + int (*handle_rsc)(struct remoteproc *rproc, void *rsc, size_t len); + int (*config)(struct remoteproc *rproc, void *data); + int (*start)(struct remoteproc *rproc); + int (*stop)(struct remoteproc *rproc); + int (*shutdown)(struct remoteproc *rproc); + int (*notify)(struct remoteproc *rproc, uint32_t id); +}; + +/* Remoteproc error codes */ +#define RPROC_EBASE 0 +#define RPROC_ENOMEM (RPROC_EBASE + 1) +#define RPROC_EINVAL (RPROC_EBASE + 2) +#define RPROC_ENODEV (RPROC_EBASE + 3) +#define RPROC_EAGAIN (RPROC_EBASE + 4) +#define RPROC_ERR_RSC_TAB_TRUNC (RPROC_EBASE + 5) +#define RPROC_ERR_RSC_TAB_VER (RPROC_EBASE + 6) +#define RPROC_ERR_RSC_TAB_RSVD (RPROC_EBASE + 7) +#define RPROC_ERR_RSC_TAB_VDEV_NRINGS (RPROC_EBASE + 9) +#define RPROC_ERR_RSC_TAB_NP (RPROC_EBASE + 10) +#define RPROC_ERR_RSC_TAB_NS (RPROC_EBASE + 11) +#define RPROC_ERR_LOADER_STATE (RPROC_EBASE + 12) +#define RPROC_EMAX (RPROC_EBASE + 16) +#define RPROC_EPTR (void *)(-1) +#define RPROC_EOF (void *)(-1) + +static inline long RPROC_PTR_ERR(const void *ptr) +{ + return (long)ptr; +} + +static inline int RPROC_IS_ERR(const void *ptr) +{ + if ((unsigned long)ptr >= (unsigned long)(-RPROC_EMAX)) + return 1; + else + return 0; +} + +static inline void *RPROC_ERR_PTR(long error) +{ + return (void *)error; +} + +/** + * enum rproc_state - remote processor states + * @RPROC_OFFLINE: remote is offline + * @RPROC_READY: remote is ready to start + * @RPROC_RUNNING: remote is up and running + * @RPROC_SUSPENDED: remote is suspended + * @RPROC_ERROR: remote has error; need to recover + * @RPROC_STOPPED: remote is stopped + * @RPROC_LAST: just keep this one at the end + */ +enum remoteproc_state { + RPROC_OFFLINE = 0, + RPROC_CONFIGURED = 1, + RPROC_READY = 2, + RPROC_RUNNING = 3, + RPROC_SUSPENDED = 4, + RPROC_ERROR = 5, + RPROC_STOPPED = 6, + RPROC_LAST = 7, +}; + +/** + * remoteproc_init + * + * Initializes remoteproc resource. + * + * @rproc - pointer to remoteproc instance + * @ops - pointer to remoteproc operations + * @priv - pointer to private data + * + * @returns created remoteproc pointer + */ +struct remoteproc *remoteproc_init(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *priv); + +/** + * remoteproc_remove + * + * Remove remoteproc resource + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success, negative value for failure + */ +int remoteproc_remove(struct remoteproc *rproc); + +/** + * remoteproc_init_mem + * + * Initialize remoteproc memory + * + * @mem - pointer to remoteproc memory + * @char - memory name + * @pa - physcial address + * @da - device address + * @size - memory size + * @io - pointer to the I/O region + */ +static inline void +remoteproc_init_mem(struct remoteproc_mem *mem, const char *name, + metal_phys_addr_t pa, metal_phys_addr_t da, + size_t size, struct metal_io_region *io) +{ + if (!mem) + return; + if (name) + strncpy(mem->name, name, sizeof(mem->name)); + else + mem->name[0] = 0; + mem->pa = pa; + mem->da = da; + mem->io = io; + mem->size = size; +} + +/** + * remoteproc_add_mem + * + * Add remoteproc memory + * + * @rproc - pointer to remoteproc + * @mem - pointer to remoteproc memory + */ +static inline void +remoteproc_add_mem(struct remoteproc *rproc, struct remoteproc_mem *mem) +{ + if (!rproc || !mem) + return; + metal_list_add_tail(&rproc->mems, &mem->node); +} + +/** + * remoteproc_get_io_with_name + * + * get remoteproc memory I/O region with name + * + * @rproc - pointer to the remote processor + * @name - name of the shared memory + * @io - pointer to the pointer of the I/O region + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_name(struct remoteproc *rproc, + const char *name); + +/** + * remoteproc_get_io_with_pa + * + * get remoteproc memory I/O region with physical address + * + * @rproc - pointer to the remote processor + * @pa - physical address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_pa(struct remoteproc *rproc, + metal_phys_addr_t pa); + +/** + * remoteproc_get_io_with_da + * + * get remoteproc memory I/O region with device address + * + * @rproc - pointer to the remote processor + * @da - device address + * @offset - I/O region offset of the device address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_da(struct remoteproc *rproc, + metal_phys_addr_t da, + unsigned long *offset); + +/** + * remoteproc_get_io_with_va + * + * get remoteproc memory I/O region with virtual address + * + * @rproc - pointer to the remote processor + * @va - virtual address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_va(struct remoteproc *rproc, + void *va); + +/** + * remoteproc_mmap + * + * remoteproc mmap memory + * + * @rproc - pointer to the remote processor + * @pa - physical address pointer + * @da - device address pointer + * @size - size of the memory + * @attribute - memory attribute + * @io - pointer to the I/O region + * + * returns pointer to the memory + */ +void *remoteproc_mmap(struct remoteproc *rproc, + metal_phys_addr_t *pa, metal_phys_addr_t *da, + size_t size, unsigned int attribute, + struct metal_io_region **io); + +/** + * remoteproc_parse_rsc_table + * + * Parse resource table of remoteproc + * + * @rproc - pointer to remoteproc instance + * @rsc_table - pointer to resource table + * @rsc_size - resource table size + * + * returns 0 for success and negative value for errors + */ +int remoteproc_parse_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size); + +/** + * remoteproc_set_rsc_table + * + * Parse and set resource table of remoteproc + * + * @rproc - pointer to remoteproc instance + * @rsc_table - pointer to resource table + * @rsc_size - resource table size + * + * returns 0 for success and negative value for errors + */ +int remoteproc_set_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size); + +/** + * remoteproc_config + * + * This function configures the remote processor to get it + * ready to load and run executable. + * + * @rproc - pointer to remoteproc instance to start + * @data - configuration data + * + * returns 0 for success and negative value for errors + */ +int remoteproc_config(struct remoteproc *rproc, void *data); + +/** + * remoteproc_start + * + * This function starts the remote processor. + * It assumes the firmware is already loaded, + * + * @rproc - pointer to remoteproc instance to start + * + * returns 0 for success and negative value for errors + */ +int remoteproc_start(struct remoteproc *rproc); + +/** + * remoteproc_stop + * + * This function stops the remote processor but it + * will not release its resource. + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success and negative value for errors + */ +int remoteproc_stop(struct remoteproc *rproc); + +/** + * remoteproc_shutdown + * + * This function shutdown the remote processor and + * release its resources. + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success and negative value for errors + */ +int remoteproc_shutdown(struct remoteproc *rproc); + +/** + * remoteproc_load + * + * load executable, it expects the user application defines how to + * open the executable file and how to get data from the executable file + * and how to load data to the target memory. + * + * @rproc: pointer to the remoteproc instance + * @path: optional path to the image file + * @store: pointer to user defined image store argument + * @store_ops: pointer to image store operations + * @image_info: pointer to memory which stores image information used + * by remoteproc loader + * + * return 0 for success and negative value for failure + */ +int remoteproc_load(struct remoteproc *rproc, const char *path, + void *store, struct image_store_ops *store_ops, + void **img_info); + +/** + * remoteproc_load_noblock + * + * load executable, it expects the caller has loaded image data to local + * memory and passed to the this function. If the function needs more + * image data it will return the next expected image data offset and + * the next expected image data length. If the function requires the + * caller to download image data to the target memory, it will also + * return the target physical address besides the offset and length. + * This function can be used to load firmware in stream mode. In this + * mode, you cannot do seek to the executable file. If the executable + * is ELF, it cannot get the resource table section before it loads + * the full ELF file. Furthermore, application usually don't store + * the data which is loaded to local memory in streaming mode, and + * thus, in this mode, it will load the binrary to the target memory + * before it gets the resource table. And thus, when calling this funciton + * don't put the target exectuable memory in the resource table, as + * this function will parse the resource table after it loads the binary + * to target memory. + * + * @rproc: pointer to the remoteproc instance + * @img_data: pointer to image data for remoteproc loader to parse + * @offset: image data offset to the beginning of the image file + * @len: image data length + * @image_info: pointer to memory which stores image information used + * by remoteproc loader + * @pa: pointer to the target memory physical address. If the next expected + * data doesn't need to load to the target memory, the function will + * set it to ANY. + * @io: pointer to the target memory physical address. If the next expected + * data doesn't need to load to the target memory, the function will + * set it to ANY. + * @noffset: pointer to the next image data offset to the beginning of + * the image file needs to load to local or to the target + * memory. + * @nlen: pointer to the next image data length needs to load to local + * or to the target memory. + * @nmlen: pointer to the memory size. It is only used when the next + * expected data is going to be loaded to the target memory. E.g. + * in ELF, it is possible that loadable segment in memory is + * larger that the segment data in the ELF file. In this case, + * application will need to pad the rest of the memory with + * padding. + * @padding: pointer to the padding value. It is only used when the next + * expected data is going to be loaded to the target memory. + * and the target memory size is larger than the segment data in + * the executable file. + * + * return 0 for success and negative value for failure + */ +int remoteproc_load_noblock(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, + metal_phys_addr_t *pa, struct metal_io_region **io, + size_t *noffset, size_t *nlen, + size_t *nmlen, unsigned char *padding); + +/** + * remoteproc_allocate_id + * + * allocate notifyid for resource + * + * @rproc - pointer to the remoteproc instance + * @start - start of the id range + * @end - end of the id range + * + * return allocated notify id + */ +unsigned int remoteproc_allocate_id(struct remoteproc *rproc, + unsigned int start, + unsigned int end); + +/* remoteproc_create_virtio + * + * create virtio device, it returns pointer to the created virtio device. + * + * @rproc: pointer to the remoteproc instance + * @vdev_id: virtio device ID + * @role: virtio device role + * @rst_cb: virtio device reset callback + * + * return pointer to the created virtio device, NULL for failure. + */ +struct virtio_device * +remoteproc_create_virtio(struct remoteproc *rproc, + int vdev_id, unsigned int role, + void (*rst_cb)(struct virtio_device *vdev)); + +/* remoteproc_remove_virtio + * + * Remove virtio device + * + * @rproc: pointer to the remoteproc instance + * @vdev: pointer to the virtio device + * + */ +void remoteproc_remove_virtio(struct remoteproc *rproc, + struct virtio_device *vdev); + +/* remoteproc_get_notification + * + * remoteproc is got notified, it will check its subdevices + * for the notification + * + * @rproc - pointer to the remoteproc instance + * @notifyid - notificatin id + * + * return 0 for succeed, negative value for failure + */ +int remoteproc_get_notification(struct remoteproc *rproc, + uint32_t notifyid); +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_loader.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_loader.h new file mode 100644 index 0000000000..4409a1aa7a --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_loader.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * remoteproc_loader.h + * + * COMPONENT + * + * OpenAMP stack. + * + * DESCRIPTION + * + * This file provides definitions for remoteproc loader + * + * + **************************************************************************/ +#ifndef REMOTEPROC_LOADER_H_ +#define REMOTEPROC_LOADER_H_ + +#include <metal/io.h> +#include <metal/list.h> +#include <metal/sys.h> +#include <openamp/remoteproc.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* Loader feature macros */ +#define SUPPORT_SEEK 1UL + +/* Remoteproc loader any address */ +#define RPROC_LOAD_ANYADDR ((metal_phys_addr_t)-1) + +/* Remoteproc loader Exectuable Image Parsing States */ +/* Remoteproc loader parser intial state */ +#define RPROC_LOADER_NOT_READY 0x0UL +/* Remoteproc loader ready to load, even it can be not finish parsing */ +#define RPROC_LOADER_READY_TO_LOAD 0x10000UL +/* Remoteproc loader post data load */ +#define RPROC_LOADER_POST_DATA_LOAD 0x20000UL +/* Remoteproc loader finished loading */ +#define RPROC_LOADER_LOAD_COMPLETE 0x40000UL +/* Remoteproc loader state mask */ +#define RPROC_LOADER_MASK 0x00FF0000UL +/* Remoteproc loader private mask */ +#define RPROC_LOADER_PRIVATE_MASK 0x0000FFFFUL +/* Remoteproc loader reserved mask */ +#define RPROC_LOADER_RESERVED_MASK 0x0F000000UL + +/** + * struct image_store_ops - user defined image store operations + * @open: user defined callback to open the "firmware" to prepare loading + * @close: user defined callback to close the "firmware" to clean up + * after loading + * @load: user defined callback to load the firmware contents to target + * memory or local memory + * @features: loader supported features. e.g. seek + */ +struct image_store_ops { + int (*open)(void *store, const char *path, const void **img_data); + void (*close)(void *store); + int (*load)(void *store, size_t offset, size_t size, + const void **data, + metal_phys_addr_t pa, + struct metal_io_region *io, char is_blocking); + unsigned int features; +}; + +/** + * struct loader_ops - loader oeprations + * @load_header: define how to get the executable headers + * @load_data: define how to load the target data + * @locate_rsc_table: define how to get the resource table target address, + * offset to the ELF image file and size of the resource + * table. + * @release: define how to release the loader + * @get_entry: get entry address + * @get_load_state: get load state from the image information + */ +struct loader_ops { + int (*load_header)(const void *img_data, size_t offset, size_t len, + void **img_info, int last_state, + size_t *noffset, size_t *nlen); + int (*load_data)(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize); + int (*locate_rsc_table)(void *img_info, metal_phys_addr_t *da, + size_t *offset, size_t *size); + void (*release)(void *img_info); + metal_phys_addr_t (*get_entry)(void *img_info); + int (*get_load_state)(void *img_info); +}; + +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_LOADER_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_virtio.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_virtio.h new file mode 100644 index 0000000000..b06b951c4d --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/remoteproc_virtio.h @@ -0,0 +1,150 @@ +/* + * Remoteproc Virtio Framework + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef REMOTEPROC_VIRTIO_H +#define REMOTEPROC_VIRTIO_H + +#include <metal/io.h> +#include <metal/list.h> +#include <openamp/virtio.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* define vdev notification funciton user should implement */ +typedef int (*rpvdev_notify_func)(void *priv, uint32_t id); + +/** + * struct remoteproc_virtio + * @priv pointer to private data + * @notifyid notification id + * @vdev_rsc address of vdev resource + * @vdev_rsc_io metal I/O region of vdev_info, can be NULL + * @notify notification function + * @vdev virtio device + * @node list node + */ +struct remoteproc_virtio { + void *priv; + uint32_t notify_id; + void *vdev_rsc; + struct metal_io_region *vdev_rsc_io; + rpvdev_notify_func notify; + struct virtio_device vdev; + struct metal_list node; +}; + +/** + * rproc_virtio_create_vdev + * + * Create rproc virtio vdev + * + * @role: 0 - virtio master, 1 - virtio slave + * @notifyid: virtio device notification id + * @rsc: pointer to the virtio device resource + * @rsc_io: pointer to the virtio device resource I/O region + * @priv: pointer to the private data + * @notify: vdev and virtqueue notification function + * @rst_cb: reset virtio device callback + * + * return pointer to the created virtio device for success, + * NULL for failure. + */ +struct virtio_device * +rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, + void *rsc, struct metal_io_region *rsc_io, + void *priv, + rpvdev_notify_func notify, + virtio_dev_reset_cb rst_cb); + +/** + * rproc_virtio_remove_vdev + * + * Create rproc virtio vdev + * + * @vdev - pointer to the virtio device + */ +void rproc_virtio_remove_vdev(struct virtio_device *vdev); + +/** + * rproc_virtio_create_vring + * + * Create rproc virtio vring + * + * @vdev: pointer to the virtio device + * @index: vring index in the virtio device + * @notifyid: remoteproc vring notification id + * @va: vring virtual address + * @io: pointer to vring I/O region + * @num_desc: number of descriptors + * @align: vring alignment + * + * return 0 for success, negative value for failure. + */ +int rproc_virtio_init_vring(struct virtio_device *vdev, unsigned int index, + unsigned int notifyid, void *va, + struct metal_io_region *io, + unsigned int num_descs, unsigned int align); + +/** + * rproc_virtio_notified + * + * remoteproc virtio is got notified + * + * @vdev - pointer to the virtio device + * @notifyid - notify id + * + * return 0 for successful, negative value for failure + */ +int rproc_virtio_notified(struct virtio_device *vdev, uint32_t notifyid); + +/** + * rproc_virtio_wait_remote_ready + * + * Blocking function, waiting for the remote core is ready to start + * communications. + * + * @vdev - pointer to the virtio device + * + * return true when remote processor is ready. + */ +void rproc_virtio_wait_remote_ready(struct virtio_device *vdev); + +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_VIRTIO_H */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg.h new file mode 100644 index 0000000000..983dcb094e --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg.h @@ -0,0 +1,358 @@ +/* + * Remote processor messaging + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2011 Google, Inc. + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RPMSG_H_ +#define _RPMSG_H_ + +#include <openamp/compiler.h> +#include <metal/mutex.h> +#include <metal/list.h> +#include <metal/utilities.h> +#include <string.h> +#include <stdbool.h> +#include <stdint.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* Configurable parameters */ +#define RPMSG_NAME_SIZE (32) +#define RPMSG_ADDR_BMP_SIZE (128) + +#define RPMSG_NS_EPT_ADDR (0x35) +#define RPMSG_ADDR_ANY 0xFFFFFFFF + +/* Error macros. */ +#define RPMSG_SUCCESS 0 +#define RPMSG_ERROR_BASE -2000 +#define RPMSG_ERR_NO_MEM (RPMSG_ERROR_BASE - 1) +#define RPMSG_ERR_NO_BUFF (RPMSG_ERROR_BASE - 2) +#define RPMSG_ERR_PARAM (RPMSG_ERROR_BASE - 3) +#define RPMSG_ERR_DEV_STATE (RPMSG_ERROR_BASE - 4) +#define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5) +#define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) +#define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) + +struct rpmsg_endpoint; +struct rpmsg_device; + +typedef int (*rpmsg_ept_cb)(struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, void *priv); +typedef void (*rpmsg_ns_unbind_cb)(struct rpmsg_endpoint *ept); +typedef void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev, + const char *name, uint32_t dest); + +/** + * struct rpmsg_endpoint - binds a local rpmsg address to its user + * @name:name of the service supported + * @rdev: pointer to the rpmsg device + * @addr: local address of the endpoint + * @dest_addr: address of the default remote endpoint binded. + * @cb: user rx callback, return value of this callback is reserved + * for future use, for now, only allow RPMSG_SUCCESS as return value. + * @ns_unbind_cb: end point service service unbind callback, called when remote + * ept is destroyed. + * @node: end point node. + * @addr: local rpmsg address + * @priv: private data for the driver's use + * + * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as + * it binds an rpmsg address with an rx callback handler. + */ +struct rpmsg_endpoint { + char name[RPMSG_NAME_SIZE]; + struct rpmsg_device *rdev; + uint32_t addr; + uint32_t dest_addr; + rpmsg_ept_cb cb; + rpmsg_ns_unbind_cb ns_unbind_cb; + struct metal_list node; + void *priv; +}; + +/** + * struct rpmsg_device_ops - RPMsg device operations + * @send_offchannel_raw: send RPMsg data + */ +struct rpmsg_device_ops { + int (*send_offchannel_raw)(struct rpmsg_device *rdev, + uint32_t src, uint32_t dst, + const void *data, int size, int wait); +}; + +/** + * struct rpmsg_device - representation of a RPMsg device + * @endpoints: list of endpoints + * @ns_ept: name service endpoint + * @bitmap: table endpoin address allocation. + * @lock: mutex lock for rpmsg management + * @ns_bind_cb: callback handler for name service announcement without local + * endpoints waiting to bind. + * @ops: RPMsg device operations + */ +struct rpmsg_device { + struct metal_list endpoints; + struct rpmsg_endpoint ns_ept; + unsigned long bitmap[metal_bitmap_longs(RPMSG_ADDR_BMP_SIZE)]; + metal_mutex_t lock; + rpmsg_ns_bind_cb ns_bind_cb; + struct rpmsg_device_ops ops; +}; + +/** + * rpmsg_send_offchannel_raw() - send a message across to the remote processor, + * specifying source and destination address. + * @ept: the rpmsg endpoint + * @data: payload of the message + * @len: length of the payload + * + * This function sends @data of length @len to the remote @dst address from + * the source @src address. + * The message will be sent to the remote processor which the channel belongs + * to. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + uint32_t dst, const void *data, int size, + int wait); + +/** + * rpmsg_send() - send a message across to the remote processor + * @ept: the rpmsg endpoint + * @data: payload of the message + * @len: length of the payload + * + * This function sends @data of length @len based on the @ept. + * The message will be sent to the remote processor which the channel belongs + * to, using @ept's source and destination addresses. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, + int len) +{ + if (ept->dest_addr == RPMSG_ADDR_ANY) + return RPMSG_ERR_ADDR; + return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, + len, true); +} + +/** + * rpmsg_sendto() - send a message across to the remote processor, specify dst + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * @dst: destination address + * + * This function sends @data of length @len to the remote @dst address. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source address. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_sendto(struct rpmsg_endpoint *ept, const void *data, + int len, uint32_t dst) +{ + return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, true); +} + +/** + * rpmsg_send_offchannel() - send a message using explicit src/dst addresses + * @ept: the rpmsg endpoint + * @src: source address + * @dst: destination address + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len to the remote @dst address, + * and uses @src as the source address. + * The message will be sent to the remote processor which the @ept + * channel belongs to. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, + uint32_t src, uint32_t dst, + const void *data, int len) +{ + return rpmsg_send_offchannel_raw(ept, src, dst, data, len, true); +} + +/** + * rpmsg_trysend() - send a message across to the remote processor + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len on the @ept channel. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source and destination addresses. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data, + int len) +{ + if (ept->dest_addr == RPMSG_ADDR_ANY) + return RPMSG_ERR_ADDR; + return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, + len, false); +} + +/** + * rpmsg_trysendto() - send a message across to the remote processor, + * specify dst + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * @dst: destination address + * + * This function sends @data of length @len to the remote @dst address. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source address. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysendto(struct rpmsg_endpoint *ept, const void *data, + int len, uint32_t dst) +{ + return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, false); +} + +/** + * rpmsg_trysend_offchannel() - send a message using explicit src/dst addresses + * @ept: the rpmsg endpoint + * @src: source address + * @dst: destination address + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len to the remote @dst address, + * and uses @src as the source address. + * The message will be sent to the remote processor which the @ept + * channel belongs to. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, + uint32_t src, uint32_t dst, + const void *data, int len) +{ + return rpmsg_send_offchannel_raw(ept, src, dst, data, len, false); +} + +/** + * rpmsg_init_ept - initialize rpmsg endpoint + * + * Initialize an RPMsg endpoint with a name, source address, + * remoteproc address, endpoitn callback, and destroy endpoint callback. + * + * @ept: pointer to rpmsg endpoint + * @name: service name associated to the endpoint + * @src: local address of the endpoint + * @dest: target address of the endpoint + * @cb: endpoint callback + * @ns_unbind_cb: end point service unbind callback, called when remote ept is + * destroyed. + */ +static inline void rpmsg_init_ept(struct rpmsg_endpoint *ept, + const char *name, + uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, + rpmsg_ns_unbind_cb ns_unbind_cb) +{ + strncpy(ept->name, name, sizeof(ept->name)); + ept->addr = src; + ept->dest_addr = dest; + ept->cb = cb; + ept->ns_unbind_cb = ns_unbind_cb; +} + +/** + * rpmsg_create_ept - create rpmsg endpoint and register it to rpmsg device + * + * Create a RPMsg endpoint, initialize it with a name, source address, + * remoteproc address, endpoitn callback, and destroy endpoint callback, + * and register it to the RPMsg device. + * + * @ept: pointer to rpmsg endpoint + * @name: service name associated to the endpoint + * @src: local address of the endpoint + * @dest: target address of the endpoint + * @cb: endpoint callback + * @ns_unbind_cb: end point service unbind callback, called when remote ept is + * destroyed. + * + * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as + * it binds an rpmsg address with an rx callback handler. + * + * Rpmsg client should create an endpoint to discuss with remote. rpmsg client + * provide at least a channel name, a callback for message notification and by + * default endpoint source address should be set to RPMSG_ADDR_ANY. + * + * As an option Some rpmsg clients can specify an endpoint with a specific + * source address. + */ + +int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + const char *name, uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, rpmsg_ns_unbind_cb ns_unbind_cb); + +/** + * rpmsg_destroy_ept - destroy rpmsg endpoint and unregister it from rpmsg + * device + * + * @ept: pointer to the rpmsg endpoint + * + * It unregisters the rpmsg endpoint from the rpmsg device and calls the + * destroy endpoint callback if it is provided. + */ +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept); + +/** + * is_rpmsg_ept_ready - check if the rpmsg endpoint ready to send + * + * @ept: pointer to rpmsg endpoint + * + * Returns 1 if the rpmsg endpoint has both local addr and destination + * addr set, 0 otherwise + */ +static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept) +{ + return (ept->dest_addr != RPMSG_ADDR_ANY && + ept->addr != RPMSG_ADDR_ANY); +} + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_retarget.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_retarget.h new file mode 100644 index 0000000000..5645e52ed6 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_retarget.h @@ -0,0 +1,119 @@ +#ifndef RPMSG_RETARGET_H +#define RPMSG_RETARGET_H + +#include <metal/mutex.h> +#include <openamp/open_amp.h> +#include <stdint.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* File Operations System call definitions */ +#define OPEN_SYSCALL_ID 0x1UL +#define CLOSE_SYSCALL_ID 0x2UL +#define WRITE_SYSCALL_ID 0x3UL +#define READ_SYSCALL_ID 0x4UL +#define ACK_STATUS_ID 0x5UL + +#define TERM_SYSCALL_ID 0x6UL + +#define DEFAULT_PROXY_ENDPOINT 0xFFUL + +struct rpmsg_rpc_data; + +typedef int (*rpmsg_rpc_poll)(void *arg); +typedef void (*rpmsg_rpc_shutdown_cb)(struct rpmsg_rpc_data *rpc); + +struct rpmsg_rpc_syscall_header { + int32_t int_field1; + int32_t int_field2; + uint32_t data_len; +}; + +struct rpmsg_rpc_syscall { + uint32_t id; + struct rpmsg_rpc_syscall_header args; +}; + +struct rpmsg_rpc_data { + struct rpmsg_endpoint ept; + int ept_destroyed; + atomic_int nacked; + void *respbuf; + size_t respbuf_len; + rpmsg_rpc_poll poll; + void *poll_arg; + rpmsg_rpc_shutdown_cb shutdown_cb; + metal_mutex_t lock; + struct metal_spinlock buflock; +}; + +/** + * rpmsg_rpc_init - initialize RPMsg remote procedure call + * + * This function is to intialize the remote procedure call + * global data. RPMsg RPC will send request to remote and + * wait for callback. + * + * @rpc: pointer to the global remote procedure call data + * @rdev: pointer to the rpmsg device + * @ept_name: name of the endpoint used by RPC + * @ept_addr: address of the endpoint used by RPC + * @ept_raddr: remote address of the endpoint used by RPC + * @poll_arg: pointer to poll function argument + * @poll: poll function + * @shutdown_cb: shutdown callback function + * + * return 0 for success, and negative value for failure. + */ +int rpmsg_rpc_init(struct rpmsg_rpc_data *rpc, + struct rpmsg_device *rdev, + const char *ept_name, uint32_t ept_addr, + uint32_t ept_raddr, + void *poll_arg, rpmsg_rpc_poll poll, + rpmsg_rpc_shutdown_cb shutdown_cb); + +/** + * rpmsg_rpc_release - release RPMsg remote procedure call + * + * This function is to release remoteproc procedure call + * global data. + * + * @rpc: pointer to the globacl remote procedure call + */ +void rpmsg_rpc_release(struct rpmsg_rpc_data *rpc); + +/** + * rpmsg_rpc_send - Request RPMsg RPC call + * + * This function sends RPC request it will return with the length + * of data and the response buffer. + * + * @rpc: pointer to remoteproc procedure call data struct + * @req: pointer to request buffer + * @len: length of the request data + * @resp: pointer to where store the response buffer + * @resp_len: length of the response buffer + * + * return length of the received response, negative value for failure. + */ +int rpmsg_rpc_send(struct rpmsg_rpc_data *rpc, + void *req, size_t len, + void *resp, size_t resp_len); + +/** + * rpmsg_set_default_rpc - set default RPMsg RPC data + * + * The default RPC data is used to redirect standard C file operations + * to RPMsg channels. + * + * @rpc: pointer to remoteproc procedure call data struct + */ +void rpmsg_set_default_rpc(struct rpmsg_rpc_data *rpc); + +#if defined __cplusplus +} +#endif + +#endif /* RPMSG_RETARGET_H */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_virtio.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_virtio.h new file mode 100644 index 0000000000..b1369cacb4 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rpmsg_virtio.h @@ -0,0 +1,190 @@ +/* + * rpmsg based on virtio + * + * Copyright (C) 2018 Linaro, Inc. + * + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RPMSG_VIRTIO_H_ +#define _RPMSG_VIRTIO_H_ + +#include <metal/io.h> +#include <metal/mutex.h> +#include <openamp/rpmsg.h> +#include <openamp/virtio.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* Configurable parameters */ +#ifndef RPMSG_BUFFER_SIZE +#define RPMSG_BUFFER_SIZE (512) +#endif + +/* The feature bitmap for virtio rpmsg */ +#define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ + +struct rpmsg_virtio_shm_pool; +/** + * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers + * @get_buffer: function to get buffer from the pool + * @base: base address of the memory pool + * @avail: available memory size + * @size: total pool size + */ +struct rpmsg_virtio_shm_pool { + void *base; + size_t avail; + size_t size; +}; + +/** + * struct rpmsg_virtio_device - representation of a rpmsg device based on virtio + * @rdev: rpmsg device, first property in the struct + * @vdev: pointer to the virtio device + * @rvq: pointer to receive virtqueue + * @svq: pointer to send virtqueue + * @shbuf_io: pointer to the shared buffer I/O region + * @shpool: pointer to the shared buffers pool + * @endpoints: list of endpoints. + */ +struct rpmsg_virtio_device { + struct rpmsg_device rdev; + struct virtio_device *vdev; + struct virtqueue *rvq; + struct virtqueue *svq; + struct metal_io_region *shbuf_io; + struct rpmsg_virtio_shm_pool *shpool; +}; + +#define RPMSG_REMOTE VIRTIO_DEV_SLAVE +#define RPMSG_MASTER VIRTIO_DEV_MASTER +static inline unsigned int + rpmsg_virtio_get_role(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->role; +} + +static inline void rpmsg_virtio_set_status(struct rpmsg_virtio_device *rvdev, + uint8_t status) +{ + rvdev->vdev->func->set_status(rvdev->vdev, status); +} + +static inline uint8_t rpmsg_virtio_get_status(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->func->get_status(rvdev->vdev); +} + +static inline uint32_t + rpmsg_virtio_get_features(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->func->get_features(rvdev->vdev); +} + +static inline int + rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, + int flags, unsigned int nvqs, + const char *names[], + vq_callback * callbacks[]) +{ + return virtio_create_virtqueues(rvdev->vdev, flags, nvqs, names, + callbacks); +} + +/** + * rpmsg_virtio_get_buffer_size - get rpmsg virtio buffer size + * + * @rdev - pointer to the rpmsg device + * + * @return - next available buffer size for text, negative value for failure + */ +int rpmsg_virtio_get_buffer_size(struct rpmsg_device *rdev); + +/** + * rpmsg_init_vdev - initialize rpmsg virtio device + * Master side: + * Initialize RPMsg virtio queues and shared buffers, the address of shm can be + * ANY. In this case, function will get shared memory from system shared memory + * pools. If the vdev has RPMsg name service feature, this API will create an + * name service endpoint. + * + * Slave side: + * This API will not return until the driver ready is set by the master side. + * + * @param rvdev - pointer to the rpmsg virtio device + * @param vdev - pointer to the virtio device + * @param ns_bind_cb - callback handler for name service announcement without + * local endpoints waiting to bind. + * @param shm_io - pointer to the share memory I/O region. + * @param shpool - pointer to shared memory pool. rpmsg_virtio_init_shm_pool has + * to be called first to fill this structure. + * + * @return - status of function execution + */ +int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + struct virtio_device *vdev, + rpmsg_ns_bind_cb ns_bind_cb, + struct metal_io_region *shm_io, + struct rpmsg_virtio_shm_pool *shpool); + +/** + * rpmsg_deinit_vdev - deinitialize rpmsg virtio device + * + * @param rvdev - pointer to the rpmsg virtio device + */ +void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev); + +/** + * rpmsg_virtio_init_shm_pool - initialize default shared buffers pool + * + * RPMsg virtio has default shared buffers pool implementation. + * The memory assigned to this pool will be dedicated to the RPMsg + * virtio. This function has to be called before calling rpmsg_init_vdev, + * to initialize the rpmsg_virtio_shm_pool structure. + * + * @param shpool - pointer to the shared buffers pool structure + * @param shbuf - pointer to the beginning of shared buffers + * @param size - shared buffers total size + */ +void rpmsg_virtio_init_shm_pool(struct rpmsg_virtio_shm_pool *shpool, + void *shbuf, size_t size); + +/** + * rpmsg_virtio_get_rpmsg_device - get RPMsg device from RPMsg virtio device + * + * @param rvdev - pointer to RPMsg virtio device + * @return - RPMsg device pointed by RPMsg virtio device + */ +static inline struct rpmsg_device * +rpmsg_virtio_get_rpmsg_device(struct rpmsg_virtio_device *rvdev) +{ + return &rvdev->rdev; +} + +/** + * rpmsg_virtio_shm_pool_get_buffer - get buffer in the shared memory pool + * + * RPMsg virtio has default shared buffers pool implementation. + * The memory assigned to this pool will be dedicated to the RPMsg + * virtio. If you prefer to have other shared buffers allocation, + * you can implement your rpmsg_virtio_shm_pool_get_buffer function. + * + * @param shpool - pointer to the shared buffers pool + * @param size - shared buffers total size + * @return - buffer pointer if free buffer is available, NULL otherwise. + */ +metal_weak void * +rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool, + size_t size); + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_VIRTIO_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rsc_table_parser.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rsc_table_parser.h new file mode 100644 index 0000000000..b0aa27e2d8 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/rsc_table_parser.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RSC_TABLE_PARSER_H +#define RSC_TABLE_PARSER_H + +#include <openamp/remoteproc.h> + +#if defined __cplusplus +extern "C" { +#endif + +#define RSC_TAB_SUPPORTED_VERSION 1 +#define RSC_TAB_HEADER_SIZE 12 +#define RSC_TAB_MAX_VRINGS 2 + +/* Standard control request handling. */ +typedef int (*rsc_handler) (struct remoteproc *rproc, void *rsc); + +/** + * handle_rsc_table + * + * This function parses resource table. + * + * @param rproc - pointer to remote remoteproc + * @param rsc_table - resource table to parse + * @param size - size of rsc table + * @param io - pointer to the resource table I/O region + * It can be NULL if the resource table + * is in the local memory. + * + * @returns - execution status + * + */ +int handle_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, int len, + struct metal_io_region *io); +int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc); +int handle_trace_rsc(struct remoteproc *rproc, void *rsc); +int handle_vdev_rsc(struct remoteproc *rproc, void *rsc); +int handle_vendor_rsc(struct remoteproc *rproc, void *rsc); + +/** + * find_rsc + * + * find out location of a resource type in the resource table. + * + * @rsc_table - pointer to the resource table + * @rsc_type - type of the resource + * @index - index of the resource of the specified type + * + * return the offset to the resource on success, or 0 on failure + */ +size_t find_rsc(void *rsc_table, unsigned int rsc_type, unsigned int index); + +#if defined __cplusplus +} +#endif + +#endif /* RSC_TABLE_PARSER_H */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio.h new file mode 100644 index 0000000000..463079bf37 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio.h @@ -0,0 +1,176 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef _VIRTIO_H_ +#define _VIRTIO_H_ + +#include <openamp/virtqueue.h> +#include <metal/spinlock.h> + +#if defined __cplusplus +extern "C" { +#endif + +/* TODO: define this as compiler flags */ +#ifndef VIRTIO_MAX_NUM_VRINGS +#define VIRTIO_MAX_NUM_VRINGS 2 +#endif + +/* VirtIO device IDs. */ +#define VIRTIO_ID_NETWORK 0x01UL +#define VIRTIO_ID_BLOCK 0x02UL +#define VIRTIO_ID_CONSOLE 0x03UL +#define VIRTIO_ID_ENTROPY 0x04UL +#define VIRTIO_ID_BALLOON 0x05UL +#define VIRTIO_ID_IOMEMORY 0x06UL +#define VIRTIO_ID_RPMSG 0x07UL /* remote processor messaging */ +#define VIRTIO_ID_SCSI 0x08UL +#define VIRTIO_ID_9P 0x09UL +#define VIRTIO_DEV_ANY_ID (-1)UL + +/* Status byte for guest to report progress. */ +#define VIRTIO_CONFIG_STATUS_ACK 0x01 +#define VIRTIO_CONFIG_STATUS_DRIVER 0x02 +#define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04 +#define VIRTIO_CONFIG_STATUS_NEEDS_RESET 0x40 +#define VIRTIO_CONFIG_STATUS_FAILED 0x80 + +/* Virtio device role */ +#define VIRTIO_DEV_MASTER 0UL +#define VIRTIO_DEV_SLAVE 1UL + +struct virtio_device_id { + uint32_t device; + uint32_t vendor; +}; + +/* + * Generate interrupt when the virtqueue ring is + * completely used, even if we've suppressed them. + */ +#define VIRTIO_F_NOTIFY_ON_EMPTY (1 << 24) + +/* + * The guest should never negotiate this feature; it + * is used to detect faulty drivers. + */ +#define VIRTIO_F_BAD_FEATURE (1 << 30) + +/* + * Some VirtIO feature bits (currently bits 28 through 31) are + * reserved for the transport being used (eg. virtio_ring), the + * rest are per-device feature bits. + */ +#define VIRTIO_TRANSPORT_F_START 28 +#define VIRTIO_TRANSPORT_F_END 32 + +typedef void (*virtio_dev_reset_cb)(struct virtio_device *vdev); + +struct virtio_dispatch; + +struct virtio_feature_desc { + uint32_t vfd_val; + const char *vfd_str; +}; + +/** + * struct proc_shm + * + * This structure is maintained by hardware interface layer for + * shared memory information. The shared memory provides buffers + * for use by the vring to exchange messages between the cores. + * + */ +struct virtio_buffer_info { + /* Start address of shared memory used for buffers. */ + void *vaddr; + /* Start physical address of shared memory used for buffers. */ + metal_phys_addr_t paddr; + /* sharmed memory I/O region */ + struct metal_io_region *io; + /* Size of shared memory. */ + unsigned long size; +}; + +/** + * struct remoteproc_vring - remoteproc vring structure + * @vq virtio queue + * @va logical address + * @notifyid vring notify id + * @num_descs number of descriptors + * @align vring alignment + * @io metal I/O region of the vring memory, can be NULL + */ +struct virtio_vring_info { + struct virtqueue *vq; + struct vring_alloc_info info; + uint32_t notifyid; + struct metal_io_region *io; +}; + +/* + * Structure definition for virtio devices for use by the + * applications/drivers + */ + +struct virtio_device { + uint32_t index; /**< unique position on the virtio bus */ + struct virtio_device_id id; /**< the device type identification + * (used to match it with a driver + */ + uint64_t features; /**< the features supported by both ends. */ + unsigned int role; /**< if it is virtio backend or front end. */ + virtio_dev_reset_cb reset_cb; /**< user registered device callback */ + const struct virtio_dispatch *func; /**< Virtio dispatch table */ + void *priv; /**< TODO: remove pointer to virtio_device private data */ + unsigned int vrings_num; /**< number of vrings */ + struct virtio_vring_info *vrings_info; +}; + +/* + * Helper functions. + */ +const char *virtio_dev_name(uint16_t devid); +void virtio_describe(struct virtio_device *dev, const char *msg, + uint32_t features, + struct virtio_feature_desc *feature_desc); + +/* + * Functions for virtio device configuration as defined in Rusty Russell's + * paper. + * Drivers are expected to implement these functions in their respective codes. + */ + +struct virtio_dispatch { + uint8_t (*get_status)(struct virtio_device *dev); + void (*set_status)(struct virtio_device *dev, uint8_t status); + uint32_t (*get_features)(struct virtio_device *dev); + void (*set_features)(struct virtio_device *dev, uint32_t feature); + uint32_t (*negotiate_features)(struct virtio_device *dev, + uint32_t features); + + /* + * Read/write a variable amount from the device specific (ie, network) + * configuration region. This region is encoded in the same endian as + * the guest. + */ + void (*read_config)(struct virtio_device *dev, uint32_t offset, + void *dst, int length); + void (*write_config)(struct virtio_device *dev, uint32_t offset, + void *src, int length); + void (*reset_device)(struct virtio_device *dev); + void (*notify)(struct virtqueue *vq); +}; + +int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, + unsigned int nvqs, const char *names[], + vq_callback *callbacks[]); + +#if defined __cplusplus +} +#endif + +#endif /* _VIRTIO_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio_ring.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio_ring.h new file mode 100644 index 0000000000..14e7b6b571 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtio_ring.h @@ -0,0 +1,152 @@ +/* + * Copyright Rusty Russell IBM Corporation 2007. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef VIRTIO_RING_H +#define VIRTIO_RING_H + +#if defined __cplusplus +extern "C" { +#endif + +/* This marks a buffer as continuing via the next field. */ +#define VRING_DESC_F_NEXT 1 +/* This marks a buffer as write-only (otherwise read-only). */ +#define VRING_DESC_F_WRITE 2 +/* This means the buffer contains a list of buffer descriptors. */ +#define VRING_DESC_F_INDIRECT 4 + +/* The Host uses this in used->flags to advise the Guest: don't kick me + * when you add a buffer. It's unreliable, so it's simply an + * optimization. Guest will still kick if it's out of buffers. + */ +#define VRING_USED_F_NO_NOTIFY 1 +/* The Guest uses this in avail->flags to advise the Host: don't + * interrupt me when you consume a buffer. It's unreliable, so it's + * simply an optimization. + */ +#define VRING_AVAIL_F_NO_INTERRUPT 1 + +/* VirtIO ring descriptors: 16 bytes. + * These can chain together via "next". + */ +struct vring_desc { + /* Address (guest-physical). */ + uint64_t addr; + /* Length. */ + uint32_t len; + /* The flags as indicated above. */ + uint16_t flags; + /* We chain unused descriptors via this, too. */ + uint16_t next; +}; + +struct vring_avail { + uint16_t flags; + uint16_t idx; + uint16_t ring[0]; +}; + +/* uint32_t is used here for ids for padding reasons. */ +struct vring_used_elem { + /* Index of start of used descriptor chain. */ + uint32_t id; + /* Total length of the descriptor chain which was written to. */ + uint32_t len; +}; + +struct vring_used { + uint16_t flags; + uint16_t idx; + struct vring_used_elem ring[0]; +}; + +struct vring { + unsigned int num; + + struct vring_desc *desc; + struct vring_avail *avail; + struct vring_used *used; +}; + +/* The standard layout for the ring is a continuous chunk of memory which + * looks like this. We assume num is a power of 2. + * + * struct vring { + * // The actual descriptors (16 bytes each) + * struct vring_desc desc[num]; + * + * // A ring of available descriptor heads with free-running index. + * __u16 avail_flags; + * __u16 avail_idx; + * __u16 available[num]; + * __u16 used_event_idx; + * + * // Padding to the next align boundary. + * char pad[]; + * + * // A ring of used descriptor heads with free-running index. + * __u16 used_flags; + * __u16 used_idx; + * struct vring_used_elem used[num]; + * __u16 avail_event_idx; + * }; + * + * NOTE: for VirtIO PCI, align is 4096. + */ + +/* + * We publish the used event index at the end of the available ring, and vice + * versa. They are at the end for backwards compatibility. + */ +#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) +#define vring_avail_event(vr) ((vr)->used->ring[(vr)->num].id & 0xFFFF) + +static inline int vring_size(unsigned int num, unsigned long align) +{ + int size; + + size = num * sizeof(struct vring_desc); + size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)) + + sizeof(uint16_t); + size = (size + align - 1) & ~(align - 1); + size += sizeof(struct vring_used) + + (num * sizeof(struct vring_used_elem)) + sizeof(uint16_t); + + return size; +} + +static inline void +vring_init(struct vring *vr, unsigned int num, uint8_t *p, unsigned long align) +{ + vr->num = num; + vr->desc = (struct vring_desc *)p; + vr->avail = (struct vring_avail *)(p + num * sizeof(struct vring_desc)); + vr->used = (struct vring_used *) + (((unsigned long)&vr->avail->ring[num] + sizeof(uint16_t) + + align - 1) & ~(align - 1)); +} + +/* + * The following is used with VIRTIO_RING_F_EVENT_IDX. + * + * Assuming a given event_idx value from the other size, if we have + * just incremented index from old to new_idx, should we trigger an + * event? + */ +static inline int +vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) +{ + return (uint16_t)(new_idx - event_idx - 1) < + (uint16_t)(new_idx - old); +} + +#if defined __cplusplus +} +#endif + +#endif /* VIRTIO_RING_H */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtqueue.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtqueue.h new file mode 100644 index 0000000000..ad24749062 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/include/openamp/virtqueue.h @@ -0,0 +1,236 @@ +#ifndef VIRTQUEUE_H_ +#define VIRTQUEUE_H_ + +/*- + * Copyright (c) 2011, Bryan Venteicher <[email protected]> + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + * + * $FreeBSD$ + */ + +#include <stdbool.h> +#include <stdint.h> + +#if defined __cplusplus +extern "C" { +#endif + +typedef uint8_t boolean; + +#include <openamp/virtio_ring.h> +#include <metal/alloc.h> +#include <metal/io.h> + +/*Error Codes*/ +#define VQ_ERROR_BASE -3000 +#define ERROR_VRING_FULL (VQ_ERROR_BASE - 1) +#define ERROR_INVLD_DESC_IDX (VQ_ERROR_BASE - 2) +#define ERROR_EMPTY_RING (VQ_ERROR_BASE - 3) +#define ERROR_NO_MEM (VQ_ERROR_BASE - 4) +#define ERROR_VRING_MAX_DESC (VQ_ERROR_BASE - 5) +#define ERROR_VRING_ALIGN (VQ_ERROR_BASE - 6) +#define ERROR_VRING_NO_BUFF (VQ_ERROR_BASE - 7) +#define ERROR_VQUEUE_INVLD_PARAM (VQ_ERROR_BASE - 8) + +#define VQUEUE_SUCCESS 0 + +/* The maximum virtqueue size is 2^15. Use that value as the end of + * descriptor chain terminator since it will never be a valid index + * in the descriptor table. This is used to verify we are correctly + * handling vq_free_cnt. + */ +#define VQ_RING_DESC_CHAIN_END 32768 +#define VIRTQUEUE_FLAG_INDIRECT 0x0001 +#define VIRTQUEUE_FLAG_EVENT_IDX 0x0002 +#define VIRTQUEUE_MAX_NAME_SZ 32 + +/* Support for indirect buffer descriptors. */ +#define VIRTIO_RING_F_INDIRECT_DESC (1 << 28) + +/* Support to suppress interrupt until specific index is reached. */ +#define VIRTIO_RING_F_EVENT_IDX (1 << 29) + +struct virtqueue_buf { + void *buf; + int len; +}; + +struct virtqueue { + struct virtio_device *vq_dev; + const char *vq_name; + uint16_t vq_queue_index; + uint16_t vq_nentries; + uint32_t vq_flags; + void (*callback)(struct virtqueue *vq); + void (*notify)(struct virtqueue *vq); + struct vring vq_ring; + uint16_t vq_free_cnt; + uint16_t vq_queued_cnt; + void *shm_io; /* opaque pointer to data needed to allow v2p & p2v */ + + /* + * Head of the free chain in the descriptor table. If + * there are no free descriptors, this will be set to + * VQ_RING_DESC_CHAIN_END. + */ + uint16_t vq_desc_head_idx; + + /* + * Last consumed descriptor in the used table, + * trails vq_ring.used->idx. + */ + uint16_t vq_used_cons_idx; + + /* + * Last consumed descriptor in the available table - + * used by the consumer side. + */ + uint16_t vq_available_idx; + +#ifdef VQUEUE_DEBUG + boolean vq_inuse; +#endif + + /* + * Used by the host side during callback. Cookie + * holds the address of buffer received from other side. + * Other fields in this structure are not used currently. + */ + + struct vq_desc_extra { + void *cookie; + uint16_t ndescs; + } vq_descx[0]; +}; + +/* struct to hold vring specific information */ +struct vring_alloc_info { + void *vaddr; + uint32_t align; + uint16_t num_descs; + uint16_t pad; +}; + +typedef void vq_callback(struct virtqueue *); +typedef void vq_notify(struct virtqueue *); + +#ifdef VQUEUE_DEBUG +#include <metal/log.h> +#include <metal/assert.h> + +#define VQASSERT(_vq, _exp, _msg) \ + do { \ + if (!(_exp)) { \ + metal_log(METAL_LOG_EMERGENCY, \ + "%s: %s - _msg", __func__, (_vq)->vq_name); \ + metal_assert(_exp); \ + } \ + } while (0) + +#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) \ + VQASSERT((_vq), (_idx) < (_vq)->vq_nentries, "invalid ring index") + +#define VQ_RING_ASSERT_CHAIN_TERM(_vq) \ + VQASSERT((_vq), (_vq)->vq_desc_head_idx == \ + VQ_RING_DESC_CHAIN_END, \ + "full ring terminated incorrectly: invalid head") + +#define VQ_PARAM_CHK(condition, status_var, status_err) \ + do { \ + if (((status_var) == 0) && (condition)) { \ + status_var = status_err; \ + } \ + } while (0) + +#define VQUEUE_BUSY(vq) \ + do { \ + if (!(vq)->vq_inuse) \ + (vq)->vq_inuse = true; \ + else \ + VQASSERT(vq, !(vq)->vq_inuse,\ + "VirtQueue already in use") \ + } while (0) + +#define VQUEUE_IDLE(vq) ((vq)->vq_inuse = false) + +#else + +#define KASSERT(cond, str) +#define VQASSERT(_vq, _exp, _msg) +#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) +#define VQ_RING_ASSERT_CHAIN_TERM(_vq) +#define VQ_PARAM_CHK(condition, status_var, status_err) +#define VQUEUE_BUSY(vq) +#define VQUEUE_IDLE(vq) + +#endif + +int virtqueue_create(struct virtio_device *device, unsigned short id, + const char *name, struct vring_alloc_info *ring, + void (*callback)(struct virtqueue *vq), + void (*notify)(struct virtqueue *vq), + struct virtqueue *v_queue); + +/* + * virtqueue_set_shmem_io + * + * set virtqueue shared memory I/O region + * + * @vq - virt queue + * @io - pointer to the shared memory I/O region + */ +static inline void virtqueue_set_shmem_io(struct virtqueue *vq, + struct metal_io_region *io) +{ + vq->shm_io = io; +} + +int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list, + int readable, int writable, void *cookie); + +void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx); + +void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, + uint32_t *len); + +int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, + uint32_t len); + +void virtqueue_disable_cb(struct virtqueue *vq); + +int virtqueue_enable_cb(struct virtqueue *vq); + +void virtqueue_kick(struct virtqueue *vq); + +static inline struct virtqueue *virtqueue_allocate(unsigned int num_desc_extra) +{ + struct virtqueue *vqs; + uint32_t vq_size = sizeof(struct virtqueue) + + num_desc_extra * sizeof(struct vq_desc_extra); + + vqs = (struct virtqueue *)metal_allocate_memory(vq_size); + + if (vqs) { + memset(vqs, 0x00, vq_size); + } + + return vqs; +} + +void virtqueue_free(struct virtqueue *vq); + +void virtqueue_dump(struct virtqueue *vq); + +void virtqueue_notification(struct virtqueue *vq); + +uint32_t virtqueue_get_desc_size(struct virtqueue *vq); + +uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx); + +#if defined __cplusplus +} +#endif + +#endif /* VIRTQUEUE_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/elf_loader.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/elf_loader.c new file mode 100644 index 0000000000..e15a7843bb --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/elf_loader.c @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> +#include <metal/alloc.h> +#include <metal/log.h> +#include <openamp/elf_loader.h> +#include <openamp/remoteproc.h> + +static int elf_is_64(const void *elf_info) +{ + const unsigned char *tmp = elf_info; + + if (tmp[EI_CLASS] == ELFCLASS64) + return 1; + else + return 0; +} + +static size_t elf_ehdr_size(const void *elf_info) +{ + if (elf_info == NULL) + return sizeof(Elf64_Ehdr); + else if (elf_is_64(elf_info) != 0) + return sizeof(Elf64_Ehdr); + else + return sizeof(Elf32_Ehdr); +} + +static size_t elf_phoff(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phoff; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phoff; + } +} + +static size_t elf_phentsize(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phentsize; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phentsize; + } +} + +static int elf_phnum(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phnum; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phnum; + } +} + +static size_t elf_shoff(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shoff; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shoff; + } +} + +static size_t elf_shentsize(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shentsize; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shentsize; + } +} + +static int elf_shnum(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shnum; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shnum; + } +} + +static int elf_shstrndx(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shstrndx; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shstrndx; + } +} + +static void *elf_phtable_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return (void *)&einfo->phdrs; + } else { + struct elf64_info *einfo = elf_info; + + return (void *)&einfo->phdrs; + } +} + +static void *elf_shtable_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return (void *)(&einfo->shdrs); + } else { + struct elf64_info *einfo = elf_info; + + return (void *)(&einfo->shdrs); + } +} + +static void **elf_shstrtab_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return &einfo->shstrtab; + } else { + struct elf64_info *einfo = elf_info; + + return &einfo->shstrtab; + } +} + +static unsigned int *elf_load_state(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return &einfo->load_state; + } else { + struct elf64_info *einfo = elf_info; + + return &einfo->load_state; + } +} + +static void elf_parse_segment(void *elf_info, const void *elf_phdr, + unsigned int *p_type, size_t *p_offset, + metal_phys_addr_t *p_vaddr, + metal_phys_addr_t *p_paddr, + size_t *p_filesz, size_t *p_memsz) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Phdr *phdr = elf_phdr; + + if (p_type != NULL) + *p_type = (unsigned int)phdr->p_type; + if (p_offset != NULL) + *p_offset = (size_t)phdr->p_offset; + if (p_vaddr != NULL) + *p_vaddr = (metal_phys_addr_t)phdr->p_vaddr; + if (p_paddr != NULL) + *p_paddr = (metal_phys_addr_t)phdr->p_paddr; + if (p_filesz != NULL) + *p_filesz = (size_t)phdr->p_filesz; + if (p_memsz != NULL) + *p_memsz = (size_t)phdr->p_memsz; + } else { + const Elf64_Phdr *phdr = elf_phdr; + + if (p_type != NULL) + *p_type = (unsigned int)phdr->p_type; + if (p_offset != NULL) + *p_offset = (size_t)phdr->p_offset; + if (p_vaddr != NULL) + if (p_vaddr != NULL) + *p_vaddr = (metal_phys_addr_t)phdr->p_vaddr; + if (p_paddr != NULL) + *p_paddr = (metal_phys_addr_t)phdr->p_paddr; + if (p_filesz != NULL) + *p_filesz = (size_t)phdr->p_filesz; + if (p_memsz != NULL) + *p_memsz = (size_t)phdr->p_memsz; + } +} + +static const void *elf_get_segment_from_index(void *elf_info, int index) +{ + if (elf_is_64(elf_info) == 0) { + const struct elf32_info *einfo = elf_info; + const Elf32_Ehdr *ehdr = &einfo->ehdr; + const Elf32_Phdr *phdrs = einfo->phdrs; + + if (phdrs == NULL) + return NULL; + if (index < 0 || index > ehdr->e_phnum) + return NULL; + return &phdrs[index]; + } else { + const struct elf64_info *einfo = elf_info; + const Elf64_Ehdr *ehdr = &einfo->ehdr; + const Elf64_Phdr *phdrs = einfo->phdrs; + + if (phdrs == NULL) + return NULL; + if (index < 0 || index > ehdr->e_phnum) + return NULL; + return &phdrs[index]; + } +} + +static void *elf_get_section_from_name(void *elf_info, const char *name) +{ + unsigned int i; + const char *name_table; + + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + Elf32_Ehdr *ehdr = &einfo->ehdr; + Elf32_Shdr *shdr = einfo->shdrs; + + name_table = einfo->shstrtab; + if (shdr == NULL || name_table == NULL) + return NULL; + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + if (strcmp(name, name_table + shdr->sh_name)) + continue; + else + return shdr; + } + } else { + struct elf64_info *einfo = elf_info; + Elf64_Ehdr *ehdr = &einfo->ehdr; + Elf64_Shdr *shdr = einfo->shdrs; + + name_table = einfo->shstrtab; + if (shdr == NULL || name_table == NULL) + return NULL; + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + if (strcmp(name, name_table + shdr->sh_name)) + continue; + else + return shdr; + } + } + return NULL; +} + +static void *elf_get_section_from_index(void *elf_info, int index) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + Elf32_Ehdr *ehdr = &einfo->ehdr; + Elf32_Shdr *shdr = einfo->shdrs; + + if (shdr == NULL) + return NULL; + if (index > ehdr->e_shnum) + return NULL; + return &einfo->shdrs[index]; + } else { + struct elf64_info *einfo = elf_info; + Elf64_Ehdr *ehdr = &einfo->ehdr; + Elf64_Shdr *shdr = einfo->shdrs; + + if (shdr == NULL) + return NULL; + if (index > ehdr->e_shnum) + return NULL; + return &einfo->shdrs[index]; + } +} + +static void elf_parse_section(void *elf_info, void *elf_shdr, + unsigned int *sh_type, unsigned int *sh_flags, + metal_phys_addr_t *sh_addr, + size_t *sh_offset, size_t *sh_size, + unsigned int *sh_link, unsigned int *sh_info, + unsigned int *sh_addralign, + size_t *sh_entsize) +{ + if (elf_is_64(elf_info) == 0) { + Elf32_Shdr *shdr = elf_shdr; + + if (sh_type != NULL) + *sh_type = shdr->sh_type; + if (sh_flags != NULL) + *sh_flags = shdr->sh_flags; + if (sh_addr != NULL) + *sh_addr = (metal_phys_addr_t)shdr->sh_addr; + if (sh_offset != NULL) + *sh_offset = shdr->sh_offset; + if (sh_size != NULL) + *sh_size = shdr->sh_size; + if (sh_link != NULL) + *sh_link = shdr->sh_link; + if (sh_info != NULL) + *sh_info = shdr->sh_info; + if (sh_addralign != NULL) + *sh_addralign = shdr->sh_addralign; + if (sh_entsize != NULL) + *sh_entsize = shdr->sh_entsize; + } else { + Elf64_Shdr *shdr = elf_shdr; + + if (sh_type != NULL) + *sh_type = shdr->sh_type; + if (sh_flags != NULL) + *sh_flags = shdr->sh_flags; + if (sh_addr != NULL) + *sh_addr = (metal_phys_addr_t)(shdr->sh_addr & + (metal_phys_addr_t)(-1)); + if (sh_offset != NULL) + *sh_offset = shdr->sh_offset; + if (sh_size != NULL) + *sh_size = shdr->sh_size; + if (sh_link != NULL) + *sh_link = shdr->sh_link; + if (sh_info != NULL) + *sh_info = shdr->sh_info; + if (sh_addralign != NULL) + *sh_addralign = shdr->sh_addralign; + if (sh_entsize != NULL) + *sh_entsize = shdr->sh_entsize; + } +} + +static const void *elf_next_load_segment(void *elf_info, int *nseg, + metal_phys_addr_t *da, + size_t *noffset, size_t *nfsize, + size_t *nmsize) +{ + const void *phdr; + unsigned int p_type = PT_NULL; + + if (elf_info == NULL || nseg == NULL) + return NULL; + while(p_type != PT_LOAD) { + phdr = elf_get_segment_from_index(elf_info, *nseg); + if (phdr == NULL) + return NULL; + elf_parse_segment(elf_info, phdr, &p_type, noffset, + da, NULL, nfsize, nmsize); + *nseg = *nseg + 1; + } + return phdr; +} + +static size_t elf_info_size(const void *img_data) +{ + if (elf_is_64(img_data) == 0) + return sizeof(struct elf32_info); + else + return sizeof(struct elf64_info); +} + +int elf_identify(const void *img_data, size_t len) +{ + if (len < SELFMAG || img_data == NULL) + return -RPROC_EINVAL; + if (memcmp(img_data, ELFMAG, SELFMAG) != 0) + return -RPROC_EINVAL; + else + return 0; +} + +int elf_load_header(const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + size_t *noffset, size_t *nlen) +{ + unsigned int *load_state; + + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + /* Get ELF header */ + if (last_load_state == ELF_STATE_INIT) { + size_t tmpsize; + + metal_log(METAL_LOG_DEBUG, "Loading ELF headering\r\n"); + tmpsize = elf_ehdr_size(img_data); + if (len < tmpsize) { + *noffset = 0; + *nlen = tmpsize; + return ELF_STATE_INIT; + } else { + size_t infosize = elf_info_size(img_data); + + if (*img_info == NULL) { + *img_info = metal_allocate_memory(infosize); + if (*img_info == NULL) + return -ENOMEM; + memset(*img_info, 0, infosize); + } + memcpy(*img_info, img_data, tmpsize); + load_state = elf_load_state(*img_info); + *load_state = ELF_STATE_WAIT_FOR_PHDRS; + last_load_state = ELF_STATE_WAIT_FOR_PHDRS; + } + } + metal_assert(*img_info != NULL); + load_state = elf_load_state(*img_info); + if (last_load_state != (int)*load_state) + return -RPROC_EINVAL; + /* Get ELF program headers */ + if (*load_state == ELF_STATE_WAIT_FOR_PHDRS) { + size_t phdrs_size; + size_t phdrs_offset; + char **phdrs; + const void *img_phdrs; + + metal_log(METAL_LOG_DEBUG, "Loading ELF program header.\r\n"); + phdrs_offset = elf_phoff(*img_info); + phdrs_size = elf_phnum(*img_info) * elf_phentsize(*img_info); + if (offset > phdrs_offset || + offset + len < phdrs_offset + phdrs_size) { + *noffset = phdrs_offset; + *nlen = phdrs_size; + return (int)*load_state; + } + /* caculate the programs headers offset to the image_data */ + phdrs_offset -= offset; + img_phdrs = (const void *) + ((const char *)img_data + phdrs_offset); + phdrs = (char **)elf_phtable_ptr(*img_info); + (*phdrs) = metal_allocate_memory(phdrs_size); + if (*phdrs == NULL) + return -ENOMEM; + memcpy((void *)(*phdrs), img_phdrs, phdrs_size); + *load_state = ELF_STATE_WAIT_FOR_SHDRS | + RPROC_LOADER_READY_TO_LOAD; + } + /* Get ELF Section Headers */ + if ((*load_state & ELF_STATE_WAIT_FOR_SHDRS) != 0) { + size_t shdrs_size; + size_t shdrs_offset; + char **shdrs; + const void *img_shdrs; + + metal_log(METAL_LOG_DEBUG, "Loading ELF section header.\r\n"); + shdrs_offset = elf_shoff(*img_info); + if (elf_shnum(*img_info) == 0) { + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_HDRS_COMPLETE; + *nlen = 0; + return (int)*load_state; + } + shdrs_size = elf_shnum(*img_info) * elf_shentsize(*img_info); + if (offset > shdrs_offset || + offset + len < shdrs_offset + shdrs_size) { + *noffset = shdrs_offset; + *nlen = shdrs_size; + return (int)*load_state; + } + /* caculate the sections headers offset to the image_data */ + shdrs_offset -= offset; + img_shdrs = (const void *) + ((const char *)img_data + shdrs_offset); + shdrs = (char **)elf_shtable_ptr(*img_info); + (*shdrs) = metal_allocate_memory(shdrs_size); + if (*shdrs == NULL) + return -ENOMEM; + memcpy((void *)*shdrs, img_shdrs, shdrs_size); + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_WAIT_FOR_SHSTRTAB; + metal_log(METAL_LOG_DEBUG, + "Loading ELF section header complete.\r\n"); + } + /* Get ELF SHSTRTAB section */ + if ((*load_state & ELF_STATE_WAIT_FOR_SHSTRTAB) != 0) { + size_t shstrtab_size; + size_t shstrtab_offset; + int shstrndx; + void *shdr; + void **shstrtab; + + metal_log(METAL_LOG_DEBUG, "Loading ELF shstrtab.\r\n"); + shstrndx = elf_shstrndx(*img_info); + shdr = elf_get_section_from_index(*img_info, shstrndx); + if (shdr == NULL) + return -RPROC_EINVAL; + elf_parse_section(*img_info, shdr, NULL, NULL, + NULL, &shstrtab_offset, + &shstrtab_size, NULL, NULL, + NULL, NULL); + if (offset > shstrtab_offset || + offset + len < shstrtab_offset + shstrtab_size) { + *noffset = shstrtab_offset; + *nlen = shstrtab_size; + return (int)*load_state; + } + /* Caculate shstrtab section offset to the input image data */ + shstrtab_offset -= offset; + shstrtab = elf_shstrtab_ptr(*img_info); + *shstrtab = metal_allocate_memory(shstrtab_size); + if (*shstrtab == NULL) + return -ENOMEM; + memcpy(*shstrtab, + (const void *)((const char *)img_data + shstrtab_offset), + shstrtab_size); + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_HDRS_COMPLETE; + *nlen = 0; + return *load_state; + } + return last_load_state; +} + +int elf_load(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize) +{ + unsigned int *load_state; + const void *phdr; + + (void)rproc; + metal_assert(da != NULL); + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + if ((last_load_state & RPROC_LOADER_MASK) == RPROC_LOADER_NOT_READY) { + metal_log(METAL_LOG_DEBUG, + "%s, needs to load header first\r\n"); + last_load_state = elf_load_header(img_data, offset, len, + img_info, last_load_state, + noffset, nlen); + if ((last_load_state & RPROC_LOADER_MASK) == + RPROC_LOADER_NOT_READY) { + *da = RPROC_LOAD_ANYADDR; + return last_load_state; + } + } + metal_assert(img_info != NULL && *img_info != NULL); + load_state = elf_load_state(*img_info); + /* For ELF, segment padding value is 0 */ + if (padding != NULL) + *padding = 0; + if ((*load_state & RPROC_LOADER_READY_TO_LOAD) != 0) { + int nsegment; + size_t nsegmsize = 0; + size_t nsize = 0; + int phnums = 0; + + nsegment = (int)(*load_state & ELF_NEXT_SEGMENT_MASK); + phdr = elf_next_load_segment(*img_info, &nsegment, da, + noffset, &nsize, &nsegmsize); + if (phdr == NULL) { + metal_log(METAL_LOG_DEBUG, "cannot find more segement\r\n"); + *load_state = (*load_state & (~ELF_NEXT_SEGMENT_MASK)) | + (unsigned int)(nsegment & ELF_NEXT_SEGMENT_MASK); + return *load_state; + } + *nlen = nsize; + *nmemsize = nsegmsize; + phnums = elf_phnum(*img_info); + metal_log(METAL_LOG_DEBUG, "segment: %d, total segs %d\r\n", + nsegment, phnums); + if (nsegment == elf_phnum(*img_info)) { + *load_state = (*load_state & (~RPROC_LOADER_MASK)) | + RPROC_LOADER_POST_DATA_LOAD; + } + *load_state = (*load_state & (~ELF_NEXT_SEGMENT_MASK)) | + (unsigned int)(nsegment & ELF_NEXT_SEGMENT_MASK); + } else if ((*load_state & RPROC_LOADER_POST_DATA_LOAD) != 0) { + if ((*load_state & ELF_STATE_HDRS_COMPLETE) == 0) { + last_load_state = elf_load_header(img_data, offset, + len, img_info, + last_load_state, + noffset, nlen); + if (last_load_state < 0) + return last_load_state; + if ((last_load_state & ELF_STATE_HDRS_COMPLETE) != 0) { + *load_state = (*load_state & + (~RPROC_LOADER_MASK)) | + RPROC_LOADER_LOAD_COMPLETE; + *nlen = 0; + } + *da = RPROC_LOAD_ANYADDR; + } else { + /* TODO: will handle relocate later */ + *nlen = 0; + *load_state = (*load_state & + (~RPROC_LOADER_MASK)) | + RPROC_LOADER_LOAD_COMPLETE; + } + } + return *load_state; +} + +void elf_release(void *img_info) +{ + if (img_info == NULL) + return; + if (elf_is_64(img_info) == 0) { + struct elf32_info *elf_info = img_info; + + if (elf_info->phdrs != NULL) + metal_free_memory(elf_info->phdrs); + if (elf_info->shdrs != NULL) + metal_free_memory(elf_info->shdrs); + if (elf_info->shstrtab != NULL) + metal_free_memory(elf_info->shstrtab); + metal_free_memory(img_info); + + } else { + struct elf64_info *elf_info = img_info; + + if (elf_info->phdrs != NULL) + metal_free_memory(elf_info->phdrs); + if (elf_info->shdrs != NULL) + metal_free_memory(elf_info->shdrs); + if (elf_info->shstrtab != NULL) + metal_free_memory(elf_info->shstrtab); + metal_free_memory(img_info); + } +} + +metal_phys_addr_t elf_get_entry(void *elf_info) +{ + if (!elf_info) + return METAL_BAD_PHYS; + + if (elf_is_64(elf_info) == 0) { + Elf32_Ehdr *elf_ehdr = (Elf32_Ehdr *)elf_info; + Elf32_Addr e_entry; + + e_entry = elf_ehdr->e_entry; + return (metal_phys_addr_t)e_entry; + } else { + Elf64_Ehdr *elf_ehdr = (Elf64_Ehdr *)elf_info; + Elf64_Addr e_entry; + + e_entry = elf_ehdr->e_entry; + return (metal_phys_addr_t)(e_entry & (metal_phys_addr_t)(-1)); + } +} + +int elf_locate_rsc_table(void *elf_info, metal_phys_addr_t *da, + size_t *offset, size_t *size) +{ + char *sect_name = ".resource_table"; + void *shdr; + unsigned int *load_state; + + if (elf_info == NULL) + return -RPROC_EINVAL; + + load_state = elf_load_state(elf_info); + if ((*load_state & ELF_STATE_HDRS_COMPLETE) == 0) + return -RPROC_ERR_LOADER_STATE; + shdr = elf_get_section_from_name(elf_info, sect_name); + if (shdr == NULL) { + metal_assert(size != NULL); + *size = 0; + return 0; + } + elf_parse_section(elf_info, shdr, NULL, NULL, + da, offset, size, + NULL, NULL, NULL, NULL); + return 0; +} + +int elf_get_load_state(void *img_info) +{ + unsigned int *load_state; + + if (img_info == NULL) + return -RPROC_EINVAL; + load_state = elf_load_state(img_info); + return (int)(*load_state); +} + +struct loader_ops elf_ops = { + .load_header = elf_load_header, + .load_data = elf_load, + .locate_rsc_table = elf_locate_rsc_table, + .release = elf_release, + .get_entry = elf_get_entry, + .get_load_state = elf_get_load_state, +}; diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc.c new file mode 100644 index 0000000000..be9b869362 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc.c @@ -0,0 +1,963 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2015 Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/alloc.h> +#include <metal/log.h> +#include <metal/utilities.h> +#include <openamp/elf_loader.h> +#include <openamp/remoteproc.h> +#include <openamp/remoteproc_loader.h> +#include <openamp/remoteproc_virtio.h> +#include <openamp/rsc_table_parser.h> + +/****************************************************************************** + * static functions + *****************************************************************************/ +static struct loader_ops * +remoteproc_check_fw_format(const void *img_data, size_t img_len) +{ + if (img_len <= 0) + return NULL; + else if (elf_identify(img_data, img_len) == 0) + return &elf_ops; + else + return NULL; +} + +static struct remoteproc_mem * +remoteproc_get_mem(struct remoteproc *rproc, const char *name, + metal_phys_addr_t pa, metal_phys_addr_t da, + void *va, size_t size) +{ + struct metal_list *node; + struct remoteproc_mem *mem; + + metal_list_for_each(&rproc->mems, node) { + mem = metal_container_of(node, struct remoteproc_mem, node); + if (name) { + if (!strncmp(name, mem->name, sizeof(mem->name))) + return mem; + } else if (pa != METAL_BAD_PHYS) { + metal_phys_addr_t pa_start, pa_end; + + pa_start = mem->pa; + pa_end = pa_start + mem->size; + if (pa >= pa_start && (pa + size) <= pa_end) + return mem; + } else if (da != METAL_BAD_PHYS) { + metal_phys_addr_t da_start, da_end; + + da_start = mem->da; + da_end = da_start + mem->size; + if (da >= da_start && (da + size) <= da_end) + return mem; + } else if (va) { + if (metal_io_virt_to_offset(mem->io, va) != + METAL_BAD_OFFSET) + return mem; + + } else { + return NULL; + } + } + return NULL; +} + +static metal_phys_addr_t +remoteproc_datopa(struct remoteproc_mem *mem, metal_phys_addr_t da) +{ + metal_phys_addr_t pa; + + pa = mem->pa + da - mem->da; + return pa; +} + +static metal_phys_addr_t +remoteproc_patoda(struct remoteproc_mem *mem, metal_phys_addr_t pa) +{ + metal_phys_addr_t da; + + da = mem->da + pa - mem->pa; + return da; +} + +static void *remoteproc_get_rsc_table(struct remoteproc *rproc, + void *store, + struct image_store_ops *store_ops, + size_t offset, + size_t len) +{ + int ret; + void *rsc_table = NULL; + const void *img_data; + + /* Copy the resource table to local memory, + * the caller should be responsible to release the memory + */ + rsc_table = metal_allocate_memory(len); + if (!rsc_table) { + return RPROC_ERR_PTR(-RPROC_ENOMEM); + } + ret = store_ops->load(store, offset, len, &img_data, RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < 0 || ret < (int)len || img_data == NULL) { + metal_log(METAL_LOG_ERROR, + "get rsc failed: 0x%llx, 0x%llx\r\n", offset, len); + rsc_table = RPROC_ERR_PTR(-RPROC_EINVAL); + goto error; + } + memcpy(rsc_table, img_data, len); + + ret = handle_rsc_table(rproc, rsc_table, len, NULL); + if (ret < 0) { + rsc_table = RPROC_ERR_PTR(ret); + goto error; + } + return rsc_table; + +error: + metal_free_memory(rsc_table); + return rsc_table; +} + +int remoteproc_parse_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size) +{ + struct metal_io_region *io; + + io = remoteproc_get_io_with_va(rproc, (void *)rsc_table); + return handle_rsc_table(rproc, rsc_table, rsc_size, io); +} + +int remoteproc_set_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size) +{ + int ret; + struct metal_io_region *io; + + io = remoteproc_get_io_with_va(rproc, (void *)rsc_table); + if (!io) + return -EINVAL; + ret = remoteproc_parse_rsc_table(rproc, rsc_table, rsc_size); + if (!ret) { + rproc->rsc_table = rsc_table; + rproc->rsc_len = rsc_size; + rproc->rsc_io = io; + } + return ret; + +} + +struct remoteproc *remoteproc_init(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *priv) +{ + if (rproc) { + memset(rproc, 0, sizeof (*rproc)); + rproc->state = RPROC_OFFLINE; + metal_mutex_init(&rproc->lock); + metal_list_init(&rproc->mems); + metal_list_init(&rproc->vdevs); + } + rproc = ops->init(rproc, ops, priv); + return rproc; +} + +int remoteproc_remove(struct remoteproc *rproc) +{ + int ret; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_OFFLINE) + rproc->ops->remove(rproc); + else + ret = -EBUSY; + metal_mutex_release(&rproc->lock); + } else { + ret = -EINVAL; + } + return ret; +} + +int remoteproc_config(struct remoteproc *rproc, void *data) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_OFFLINE) { + /* configure operation is allowed if the state is + * offline or ready. This function can be called + * mulitple times before start the remote. + */ + if (rproc->ops->config) + ret = rproc->ops->config(rproc, data); + rproc->state = RPROC_READY; + } else { + ret = -RPROC_EINVAL; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_start(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_READY) { + ret = rproc->ops->start(rproc); + rproc->state = RPROC_RUNNING; + } else { + ret = -RPROC_EINVAL; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_stop(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state != RPROC_STOPPED && + rproc->state != RPROC_OFFLINE) { + if (rproc->ops->stop) + ret = rproc->ops->stop(rproc); + rproc->state = RPROC_STOPPED; + } else { + ret = 0; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_shutdown(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + ret = 0; + metal_mutex_acquire(&rproc->lock); + if (rproc->state != RPROC_OFFLINE) { + if (rproc->state != RPROC_STOPPED) { + if (rproc->ops->stop) + ret = rproc->ops->stop(rproc); + } + if (!ret) { + if (rproc->ops->shutdown) + ret = rproc->ops->shutdown(rproc); + if (!ret) { + rproc->state = RPROC_OFFLINE; + } + } + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +struct metal_io_region * +remoteproc_get_io_with_name(struct remoteproc *rproc, + const char *name) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, name, + METAL_BAD_PHYS, METAL_BAD_PHYS, NULL, 0); + if (mem) + return mem->io; + else + return NULL; +} + +struct metal_io_region * +remoteproc_get_io_with_pa(struct remoteproc *rproc, + metal_phys_addr_t pa) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, pa, METAL_BAD_PHYS, NULL, 0); + if (mem) + return mem->io; + else + return NULL; +} + +struct metal_io_region * +remoteproc_get_io_with_da(struct remoteproc *rproc, + metal_phys_addr_t da, + unsigned long *offset) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, da, NULL, 0); + if (mem) { + struct metal_io_region *io; + metal_phys_addr_t pa; + + io = mem->io; + pa = remoteproc_datopa(mem, da); + *offset = metal_io_phys_to_offset(io, pa); + return io; + } else { + return NULL; + } +} + +struct metal_io_region * +remoteproc_get_io_with_va(struct remoteproc *rproc, void *va) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, METAL_BAD_PHYS, + va, 0); + if (mem) + return mem->io; + else + return NULL; +} + +void *remoteproc_mmap(struct remoteproc *rproc, + metal_phys_addr_t *pa, metal_phys_addr_t *da, + size_t size, unsigned int attribute, + struct metal_io_region **io) +{ + void *va = NULL; + metal_phys_addr_t lpa, lda; + struct remoteproc_mem *mem; + + if (!rproc) + return NULL; + else if (!pa && !da) + return NULL; + if (pa) + lpa = *pa; + else + lpa = METAL_BAD_PHYS; + if (da) + lda = *da; + else + lda = METAL_BAD_PHYS; + mem = remoteproc_get_mem(rproc, NULL, lpa, lda, NULL, size); + if (mem) { + if (lpa != METAL_BAD_PHYS) + lda = remoteproc_patoda(mem, lpa); + else if (lda != METAL_BAD_PHYS) + lpa = remoteproc_datopa(mem, lda); + if (io) + *io = mem->io; + va = metal_io_phys_to_virt(mem->io, lpa); + } else if (rproc->ops->mmap) { + va = rproc->ops->mmap(rproc, &lpa, &lda, size, attribute, io); + } + + if (pa) + *pa = lpa; + if (da) + *da = lda; + return va; +} + +int remoteproc_load(struct remoteproc *rproc, const char *path, + void *store, struct image_store_ops *store_ops, + void **img_info) +{ + int ret; + struct loader_ops *loader; + const void *img_data; + void *limg_info = NULL; + size_t offset, noffset; + size_t len, nlen; + int last_load_state; + metal_phys_addr_t da, rsc_da; + int rsc_len; + size_t rsc_size; + void *rsc_table = NULL; + struct metal_io_region *io = NULL; + + if (!rproc) + return -RPROC_ENODEV; + + metal_mutex_acquire(&rproc->lock); + metal_log(METAL_LOG_DEBUG, "%s: check remoteproc status\r\n", __func__); + /* If remoteproc is not in ready state, cannot load executable */ + if (rproc->state != RPROC_READY && rproc->state != RPROC_CONFIGURED) { + metal_log(METAL_LOG_ERROR, + "load failure: invalid rproc state %d.\r\n", + rproc->state); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + if (!store_ops) { + metal_log(METAL_LOG_ERROR, + "load failure: loader ops is not set.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + /* Open exectuable to get ready to parse */ + metal_log(METAL_LOG_DEBUG, "%s: open exectuable image\r\n", __func__); + ret = store_ops->open(store, path, &img_data); + if (ret <= 0) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to open firmware %d.\n", + ret); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + len = ret; + metal_assert(img_data != NULL); + + /* Check executable format to select a parser */ + loader = rproc->loader; + if (!loader) { + metal_log(METAL_LOG_DEBUG, "%s: check loader\r\n", __func__); + loader = remoteproc_check_fw_format(img_data, len); + if (!loader) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to get store ops.\n"); + ret = -RPROC_EINVAL; + goto error1; + } + rproc->loader = loader; + } + + /* Load exectuable headers */ + metal_log(METAL_LOG_DEBUG, "%s: loading headers\r\n", __func__); + offset = 0; + last_load_state = RPROC_LOADER_NOT_READY; + while(1) { + ret = loader->load_header(img_data, offset, len, + &limg_info, last_load_state, + &noffset, &nlen); + last_load_state = (unsigned int)ret; + metal_log(METAL_LOG_DEBUG, + "%s, load header 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, noffset, nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load header failed 0x%lx,%d.\r\n", + offset, len); + + goto error2; + } else if ((ret & RPROC_LOADER_READY_TO_LOAD) != 0) { + if (nlen == 0) + break; + else if ((noffset > (offset + len)) && + (store_ops->features & SUPPORT_SEEK) == 0) { + /* Required data is not continued, however + * seek is not supported, stop to load + * headers such as ELF section headers which + * is usually located to the end of image. + * Continue to load binary data to target + * memory. + */ + break; + } + } + /* Continue to load headers image data */ + img_data = NULL; + ret = store_ops->load(store, noffset, nlen, + &img_data, + RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < (int)nlen) { + metal_log(METAL_LOG_ERROR, + "load image data failed 0x%x,%d\r\n", + noffset, nlen); + goto error2; + } + offset = noffset; + len = nlen; + } + ret = elf_locate_rsc_table(limg_info, &rsc_da, &offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + /* parse resource table */ + rsc_len = (int)rsc_size; + rsc_table = remoteproc_get_rsc_table(rproc, store, store_ops, + offset, rsc_len); + } else { + rsc_len = ret; + } + + /* load executable data */ + metal_log(METAL_LOG_DEBUG, "%s: load executable data\r\n", __func__); + offset = 0; + len = 0; + ret = -EINVAL; + while(1) { + unsigned char padding; + size_t nmemsize; + metal_phys_addr_t pa; + + da = RPROC_LOAD_ANYADDR; + nlen = 0; + nmemsize = 0; + noffset = 0; + ret = loader->load_data(rproc, img_data, offset, len, + &limg_info, last_load_state, &da, + &noffset, &nlen, &padding, &nmemsize); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load data failed,0x%lx,%d\r\n", + noffset, nlen); + goto error3; + } + metal_log(METAL_LOG_DEBUG, + "load data: da 0x%lx, offset 0x%lx, len = 0x%lx, memsize = 0x%lx, state 0x%x\r\n", + da, noffset, nlen, nmemsize, ret); + last_load_state = ret; + if (da != RPROC_LOAD_ANYADDR) { + /* Data is supposed to be loaded to target memory */ + img_data = NULL; + /* get the I/O region from remoteproc */ + pa = METAL_BAD_PHYS; + (void)remoteproc_mmap(rproc, &pa, &da, nmemsize, 0, &io); + if (pa == METAL_BAD_PHYS || io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed, no mapping for 0x%llx.\r\n", + da); + ret = -RPROC_EINVAL; + goto error3; + } + if (nlen > 0) { + ret = store_ops->load(store, noffset, nlen, + &img_data, pa, io, 1); + if (ret != (int)nlen) { + metal_log(METAL_LOG_ERROR, + "load data failed 0x%lx, 0x%lx, 0x%x\r\n", + pa, noffset, nlen); + ret = -RPROC_EINVAL; + goto error3; + } + } + if (nmemsize > nlen) { + size_t tmpoffset; + + tmpoffset = metal_io_phys_to_offset(io, + pa + nlen); + metal_io_block_set(io, tmpoffset, + padding, (nmemsize - nlen)); + } + } else if (nlen != 0) { + ret = store_ops->load(store, noffset, nlen, + &img_data, + RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < (int)nlen) { + if ((last_load_state & + RPROC_LOADER_POST_DATA_LOAD) != 0) { + metal_log(METAL_LOG_WARNING, + "not all the headers are loaded\r\n"); + break; + } + metal_log(METAL_LOG_ERROR, + "post-load image data failed 0x%x,%d\r\n", + noffset, nlen); + goto error3; + } + offset = noffset; + len = nlen; + } else { + /* (last_load_state & RPROC_LOADER_LOAD_COMPLETE) != 0 */ + break; + } + } + + if (rsc_len < 0) { + ret = elf_locate_rsc_table(limg_info, &rsc_da, + &offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + /* parse resource table */ + rsc_len = (int)rsc_size; + rsc_table = remoteproc_get_rsc_table(rproc, store, + store_ops, + offset, + rsc_len); + } + } + + /* Update resource table */ + if (rsc_len && rsc_da != METAL_BAD_PHYS) { + void *rsc_table_cp = rsc_table; + + metal_log(METAL_LOG_DEBUG, + "%s, update resource table\r\n", __func__); + rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da, + rsc_len, 0, &io); + if (rsc_table) { + size_t rsc_io_offset; + + /* Update resource table */ + rsc_io_offset = metal_io_virt_to_offset(io, rsc_table); + ret = metal_io_block_write(io, rsc_io_offset, + rsc_table_cp, rsc_len); + if (ret != rsc_len) { + metal_log(METAL_LOG_WARNING, + "load: failed to update rsc\r\n"); + } + rproc->rsc_table = rsc_table; + rproc->rsc_len = rsc_len; + } else { + metal_log(METAL_LOG_WARNING, + "load: not able to update rsc table.\n"); + } + metal_free_memory(rsc_table_cp); + /* So that the rsc_table will not get released */ + rsc_table = NULL; + } + + metal_log(METAL_LOG_DEBUG, "%s: successfully load firmware\r\n", + __func__); + /* get entry point from the firmware */ + rproc->bootaddr = loader->get_entry(limg_info); + rproc->state = RPROC_READY; + + metal_mutex_release(&rproc->lock); + if (img_info) + *img_info = limg_info; + else + loader->release(limg_info); + store_ops->close(store); + return 0; + +error3: + if (rsc_table) + metal_free_memory(rsc_table); +error2: + loader->release(limg_info); +error1: + store_ops->close(store); + metal_mutex_release(&rproc->lock); + return ret; +} + +int remoteproc_load_noblock(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, + metal_phys_addr_t *pa, struct metal_io_region **io, + size_t *noffset, size_t *nlen, + size_t *nmlen, unsigned char *padding) +{ + int ret; + struct loader_ops *loader; + void *limg_info = NULL; + int last_load_state; + metal_phys_addr_t da, rsc_da; + size_t rsc_size; + void *rsc_table = NULL, *lrsc_table = NULL; + + if (!rproc) + return -RPROC_ENODEV; + + metal_assert(pa != NULL); + metal_assert(io != NULL); + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + metal_assert(nmlen != NULL); + metal_assert(padding != NULL); + + metal_mutex_acquire(&rproc->lock); + metal_log(METAL_LOG_DEBUG, "%s: check remoteproc status\r\n", __func__); + /* If remoteproc is not in ready state, cannot load executable */ + if (rproc->state != RPROC_READY) { + metal_log(METAL_LOG_ERROR, + "load failure: invalid rproc state %d.\r\n", + rproc->state); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + /* Check executable format to select a parser */ + loader = rproc->loader; + if (!loader) { + metal_log(METAL_LOG_DEBUG, "%s: check loader\r\n", __func__); + if (img_data == NULL || offset != 0 || len == 0) { + metal_log(METAL_LOG_ERROR, + "load failure, invalid inputs, not able to identify image.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + loader = remoteproc_check_fw_format(img_data, len); + if (!loader) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to identify image.\n"); + ret = -RPROC_EINVAL; + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + rproc->loader = loader; + } + if (img_info == NULL || *img_info == NULL ) { + last_load_state = 0; + } else { + limg_info = *img_info; + last_load_state = loader->get_load_state(limg_info); + if (last_load_state < 0) { + metal_log(METAL_LOG_ERROR, + "load failure, not able get load state.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + } + da = RPROC_LOAD_ANYADDR; + *nlen = 0; + if ((last_load_state & RPROC_LOADER_READY_TO_LOAD) == 0 && + (last_load_state & RPROC_LOADER_LOAD_COMPLETE) == 0) { + /* Get the mandatory executable headers */ + ret = loader->load_header(img_data, offset, len, + &limg_info, last_load_state, + noffset, nlen); + last_load_state = (unsigned int)ret; + metal_log(METAL_LOG_DEBUG, + "%s, load header 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, *noffset, *nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load header failed 0x%lx,%d.\r\n", + offset, len); + + goto error1; + } + last_load_state = loader->get_load_state(limg_info); + if (*nlen != 0 && + (last_load_state & RPROC_LOADER_READY_TO_LOAD) == 0) + goto out; + } + if ((last_load_state & RPROC_LOADER_READY_TO_LOAD) != 0 || + (last_load_state & RPROC_LOADER_POST_DATA_LOAD) != 0) { + /* Enough information to know which target memory for + * which data. + */ + ret = loader->load_data(rproc, img_data, offset, len, + &limg_info, last_load_state, &da, + noffset, nlen, padding, nmlen); + metal_log(METAL_LOG_DEBUG, + "%s, load data 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, *noffset, *nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load data failed,0x%lx,%d\r\n", + offset, len); + goto error1; + } + if (da != RPROC_LOAD_ANYADDR) { + /* get the I/O region from remoteproc */ + *pa = METAL_BAD_PHYS; + (void)remoteproc_mmap(rproc, pa, &da, *nmlen, 0, io); + if (*pa == METAL_BAD_PHYS || io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed, no mapping for 0x%llx.\r\n", + da); + ret = -RPROC_EINVAL; + goto error1; + } + } + if (*nlen != 0) + goto out; + else + last_load_state = loader->get_load_state(limg_info); + } + if ((last_load_state & RPROC_LOADER_LOAD_COMPLETE) != 0) { + /* Get resource table */ + size_t rsc_offset; + size_t rsc_io_offset; + + ret = elf_locate_rsc_table(limg_info, &rsc_da, + &rsc_offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + lrsc_table = metal_allocate_memory(rsc_size); + if (lrsc_table == NULL) { + ret = -RPROC_ENOMEM; + goto error1; + } + rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da, + rsc_size, 0, io); + if (*io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to mmap rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + rsc_io_offset = metal_io_virt_to_offset(*io, rsc_table); + ret = metal_io_block_read(*io, rsc_io_offset, + lrsc_table, (int)rsc_size); + if (ret != (int)rsc_size) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to get rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + /* parse resource table */ + ret = remoteproc_parse_rsc_table(rproc, lrsc_table, + rsc_size); + if (ret == (int)rsc_size) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to parse rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + /* Update resource table */ + ret = metal_io_block_write(*io, rsc_io_offset, + lrsc_table, (int)rsc_size); + if (ret != (int)rsc_size) { + metal_log(METAL_LOG_WARNING, + "load exectuable, failed to update rsc\r\n"); + } + rproc->rsc_table = rsc_table; + rproc->rsc_len = (int)rsc_size; + metal_free_memory(lrsc_table); + } + } +out: + if (img_info != NULL) + *img_info = limg_info; + else + loader->release(limg_info); + metal_mutex_release(&rproc->lock); + return 0; + +error1: + loader->release(limg_info); + metal_mutex_release(&rproc->lock); + return ret; +} + +unsigned int remoteproc_allocate_id(struct remoteproc *rproc, + unsigned int start, + unsigned int end) +{ + unsigned int notifyid; + + if (start == RSC_NOTIFY_ID_ANY) + start = 0; + if (end == RSC_NOTIFY_ID_ANY) + end = METAL_BITS_PER_ULONG; + notifyid = metal_bitmap_next_set_bit(&rproc->bitmap, + start, end); + if (notifyid != end) + metal_bitmap_set_bit(&rproc->bitmap, notifyid); + return notifyid; +} + +static int remoteproc_virtio_notify(void *priv, uint32_t id) +{ + struct remoteproc *rproc = priv; + + return rproc->ops->notify(rproc, id); +} + +struct virtio_device * +remoteproc_create_virtio(struct remoteproc *rproc, + int vdev_id, unsigned int role, + void (*rst_cb)(struct virtio_device *vdev)) +{ + char *rsc_table; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *vdev_rsc_io; + struct virtio_device *vdev; + struct remoteproc_virtio *rpvdev; + size_t vdev_rsc_offset; + unsigned int notifyid; + unsigned int num_vrings, i; + struct metal_list *node; + + metal_assert(rproc); + metal_mutex_acquire(&rproc->lock); + rsc_table = rproc->rsc_table; + vdev_rsc_io = rproc->rsc_io; + vdev_rsc_offset = find_rsc(rsc_table, RSC_VDEV, vdev_id); + if (!vdev_rsc_offset) { + metal_mutex_release(&rproc->lock); + return NULL; + } + vdev_rsc = (struct fw_rsc_vdev *)(rsc_table + vdev_rsc_offset); + notifyid = vdev_rsc->notifyid; + /* Check if the virtio device is already created */ + metal_list_for_each(&rproc->vdevs, node) { + rpvdev = metal_container_of(node, struct remoteproc_virtio, + node); + if (rpvdev->vdev.index == notifyid) + return &rpvdev->vdev; + } + vdev = rproc_virtio_create_vdev(role, notifyid, + vdev_rsc, vdev_rsc_io, rproc, + remoteproc_virtio_notify, + rst_cb); + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_list_add_tail(&rproc->vdevs, &rpvdev->node); + num_vrings = vdev_rsc->num_of_vrings; + /* set the notification id for vrings */ + for (i = 0; i < num_vrings; i++) { + struct fw_rsc_vdev_vring *vring_rsc; + metal_phys_addr_t da; + unsigned int num_descs, align; + struct metal_io_region *io; + void *va; + size_t size; + int ret; + + vring_rsc = &vdev_rsc->vring[i]; + notifyid = vring_rsc->notifyid; + da = vring_rsc->da; + num_descs = vring_rsc->num; + align = vring_rsc->align; + size = vring_size(num_descs, align); + va = remoteproc_mmap(rproc, NULL, &da, size, 0, &io); + if (!va) + goto err1; + ret = rproc_virtio_init_vring(vdev, i, notifyid, + va, io, num_descs, align); + if (ret) + goto err1; + } + metal_mutex_release(&rproc->lock); + return vdev; + +err1: + remoteproc_remove_virtio(rproc, vdev); + metal_mutex_release(&rproc->lock); + return NULL; +} + +void remoteproc_remove_virtio(struct remoteproc *rproc, + struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + + (void)rproc; + metal_assert(vdev); + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_list_del(&rpvdev->node); + rproc_virtio_remove_vdev(&rpvdev->vdev); +} + +int remoteproc_get_notification(struct remoteproc *rproc, uint32_t notifyid) +{ + struct remoteproc_virtio *rpvdev; + struct metal_list *node; + int ret; + + metal_list_for_each(&rproc->vdevs, node) { + rpvdev = metal_container_of(node, struct remoteproc_virtio, + node); + ret = rproc_virtio_notified(&rpvdev->vdev, notifyid); + if (ret) + return ret; + } + return 0; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc_virtio.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc_virtio.c new file mode 100644 index 0000000000..0059718dc1 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/remoteproc_virtio.c @@ -0,0 +1,330 @@ +/* + * Remoteproc Virtio Framework Implementation + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <openamp/remoteproc.h> +#include <openamp/remoteproc_virtio.h> +#include <openamp/virtqueue.h> +#include <metal/utilities.h> +#include <metal/alloc.h> + +static void rproc_virtio_virtqueue_notify(struct virtqueue *vq) +{ + struct remoteproc_virtio *rpvdev; + struct virtio_vring_info *vring_info; + struct virtio_device *vdev; + unsigned int vq_id = vq->vq_queue_index; + + vdev = vq->vq_dev; + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_assert(vq_id <= vdev->vrings_num); + vring_info = &vdev->vrings_info[vq_id]; + rpvdev->notify(rpvdev->priv, vring_info->notifyid); +} + +static unsigned char rproc_virtio_get_status(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + char status; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + status = metal_io_read8(io, + metal_io_virt_to_offset(io, &vdev_rsc->status)); + return status; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_set_status(struct virtio_device *vdev, + unsigned char status) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + metal_io_write8(io, + metal_io_virt_to_offset(io, &vdev_rsc->status), + status); + rpvdev->notify(rpvdev->priv, vdev->index); +} +#endif + +static uint32_t rproc_virtio_get_features(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + uint32_t features; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + /* TODO: shall we get features based on the role ? */ + features = metal_io_read32(io, + metal_io_virt_to_offset(io, &vdev_rsc->dfeatures)); + + return features; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_set_features(struct virtio_device *vdev, + uint32_t features) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + /* TODO: shall we set features based on the role ? */ + metal_io_write32(io, + metal_io_virt_to_offset(io, &vdev_rsc->dfeatures), + features); + rpvdev->notify(rpvdev->priv, vdev->index); +} +#endif + +static uint32_t rproc_virtio_negotiate_features(struct virtio_device *vdev, + uint32_t features) +{ + (void)vdev; + (void)features; + + return 0; +} + +static void rproc_virtio_read_config(struct virtio_device *vdev, + uint32_t offset, void *dst, int length) +{ + (void)vdev; + (void)offset; + (void)dst; + (void)length; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_write_config(struct virtio_device *vdev, + uint32_t offset, void *src, int length) +{ + (void)vdev; + (void)offset; + (void)src; + (void)length; +} + +static void rproc_virtio_reset_device(struct virtio_device *vdev) +{ + if (vdev->role == VIRTIO_DEV_MASTER) + rproc_virtio_set_status(vdev, + VIRTIO_CONFIG_STATUS_NEEDS_RESET); +} +#endif + +const struct virtio_dispatch remoteproc_virtio_dispatch_funcs = { + .get_status = rproc_virtio_get_status, + .get_features = rproc_virtio_get_features, + .read_config = rproc_virtio_read_config, + .notify = rproc_virtio_virtqueue_notify, + .negotiate_features = rproc_virtio_negotiate_features, +#ifndef VIRTIO_SLAVE_ONLY + /* + * We suppose here that the vdev is in a shared memory so that can + * be access only by one core: the master. In this case salve core has + * only read access right. + */ + .set_status = rproc_virtio_set_status, + .set_features = rproc_virtio_set_features, + .write_config = rproc_virtio_write_config, + .reset_device = rproc_virtio_reset_device, +#endif +}; + +struct virtio_device * +rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, + void *rsc, struct metal_io_region *rsc_io, + void *priv, + rpvdev_notify_func notify, + virtio_dev_reset_cb rst_cb) +{ + struct remoteproc_virtio *rpvdev; + struct virtio_vring_info *vrings_info; + struct fw_rsc_vdev *vdev_rsc = rsc; + struct virtio_device *vdev; + unsigned int num_vrings = vdev_rsc->num_of_vrings; + unsigned int i; + + rpvdev = metal_allocate_memory(sizeof(*rpvdev)); + if (!rpvdev) + return NULL; + vrings_info = metal_allocate_memory(sizeof(*vrings_info) * num_vrings); + if (!vrings_info) + goto err0; + memset(rpvdev, 0, sizeof(*rpvdev)); + memset(vrings_info, 0, sizeof(*vrings_info)); + vdev = &rpvdev->vdev; + + for (i = 0; i < num_vrings; i++) { + struct virtqueue *vq; + struct fw_rsc_vdev_vring *vring_rsc; + unsigned int num_extra_desc = 0; + + vring_rsc = &vdev_rsc->vring[i]; + if (role == VIRTIO_DEV_MASTER) { + num_extra_desc = vring_rsc->num; + } + vq = virtqueue_allocate(num_extra_desc); + if (!vq) + goto err1; + vrings_info[i].vq = vq; + } + + /* FIXME commended as seems not nedded, already stored in vdev */ + //rpvdev->notifyid = notifyid; + rpvdev->notify = notify; + rpvdev->priv = priv; + vdev->vrings_info = vrings_info; + /* Assuming the shared memory has been mapped and registered if + * necessary + */ + rpvdev->vdev_rsc = vdev_rsc; + rpvdev->vdev_rsc_io = rsc_io; + + vdev->index = notifyid; + vdev->role = role; + vdev->reset_cb = rst_cb; + vdev->vrings_num = num_vrings; + vdev->func = &remoteproc_virtio_dispatch_funcs; + /* TODO: Shall we set features here ? */ + + return &rpvdev->vdev; + +err1: + for (i = 0; i < num_vrings; i++) { + if (vrings_info[i].vq) + metal_free_memory(vrings_info[i].vq); + } + metal_free_memory(vrings_info); +err0: + metal_free_memory(rpvdev); + return NULL; +} + +void rproc_virtio_remove_vdev(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + unsigned int i; + + if (!vdev) + return; + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + for (i = 0; i < vdev->vrings_num; i++) { + struct virtqueue *vq; + + vq = vdev->vrings_info[i].vq; + if (vq) + metal_free_memory(vq); + } + metal_free_memory(vdev->vrings_info); + metal_free_memory(rpvdev); +} + +int rproc_virtio_init_vring(struct virtio_device *vdev, unsigned int index, + unsigned int notifyid, void *va, + struct metal_io_region *io, + unsigned int num_descs, unsigned int align) +{ + struct virtio_vring_info *vring_info; + unsigned int num_vrings; + + num_vrings = vdev->vrings_num; + if (index >= num_vrings) + return -RPROC_EINVAL; + vring_info = &vdev->vrings_info[index]; + vring_info->io = io; + vring_info->notifyid = notifyid; + vring_info->info.vaddr = va; + vring_info->info.num_descs = num_descs; + vring_info->info.align = align; + + return 0; +} + +int rproc_virtio_notified(struct virtio_device *vdev, uint32_t notifyid) +{ + unsigned int num_vrings, i; + struct virtio_vring_info *vring_info; + struct virtqueue *vq; + + if (!vdev) + return -EINVAL; + /* We do nothing for vdev notification in this implementation */ + if (vdev->index == notifyid) + return 0; + num_vrings = vdev->vrings_num; + for (i = 0; i < num_vrings; i++) { + vring_info = &vdev->vrings_info[i]; + if (vring_info->notifyid == notifyid || + notifyid == RSC_NOTIFY_ID_ANY) { + vq = vring_info->vq; + virtqueue_notification(vq); + } + } + return 0; +} + +void rproc_virtio_wait_remote_ready(struct virtio_device *vdev) +{ + uint8_t status; + + /* + * No status available for slave. As Master has not to wait + * slave action, we can return. Behavior should be updated + * in future if a slave status is added. + */ + if (vdev->role == VIRTIO_DEV_MASTER) + return; + + while (1) { + status = rproc_virtio_get_status(vdev); + if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK) + return; + } +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/rsc_table_parser.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/rsc_table_parser.c new file mode 100644 index 0000000000..37c6478011 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/remoteproc/rsc_table_parser.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * Copyright (c) 2018, Xilinx Inc. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/io.h> +#include <openamp/rsc_table_parser.h> + +static int handle_dummy_rsc(struct remoteproc *rproc, void *rsc); + +/* Resources handler */ +rsc_handler rsc_handler_table[] = { + handle_carve_out_rsc, /**< carved out resource */ + handle_dummy_rsc, /**< IOMMU dev mem resource */ + handle_trace_rsc, /**< trace buffer resource */ + handle_vdev_rsc, /**< virtio resource */ + handle_dummy_rsc, /**< rproc shared memory resource */ + handle_dummy_rsc, /**< firmware checksum resource */ +}; + +int handle_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, int size, + struct metal_io_region *io) +{ + char *rsc_start; + unsigned int rsc_type; + unsigned int idx, offset; + int status = 0; + + /* Validate rsc table header fields */ + + /* Minimum rsc table size */ + if (sizeof(struct resource_table) > (unsigned int)size) { + return -RPROC_ERR_RSC_TAB_TRUNC; + } + + /* Supported version */ + if (rsc_table->ver != RSC_TAB_SUPPORTED_VERSION) { + return -RPROC_ERR_RSC_TAB_VER; + } + + /* Offset array */ + offset = sizeof(struct resource_table) + + rsc_table->num * sizeof(rsc_table->offset[0]); + + if (offset > (unsigned int)size) { + return -RPROC_ERR_RSC_TAB_TRUNC; + } + + /* Reserved fields - must be zero */ + if ((rsc_table->reserved[0] != 0 || rsc_table->reserved[1]) != 0) { + return -RPROC_ERR_RSC_TAB_RSVD; + } + + /* Loop through the offset array and parse each resource entry */ + for (idx = 0; idx < rsc_table->num; idx++) { + rsc_start = (char *)rsc_table; + rsc_start += rsc_table->offset[idx]; + if (io && + metal_io_virt_to_offset(io, rsc_start) == METAL_BAD_OFFSET) + return -RPROC_ERR_RSC_TAB_TRUNC; + rsc_type = *((uint32_t *)rsc_start); + if (rsc_type < RSC_LAST) + status = rsc_handler_table[rsc_type](rproc, + rsc_start); + else if (rsc_type >= RSC_VENDOR_START && + rsc_type <= RSC_VENDOR_END) + status = handle_vendor_rsc(rproc, rsc_start); + if (status == -RPROC_ERR_RSC_TAB_NS) { + status = 0; + continue; + } + else if (status) + break; + } + + return status; +} + +/** + * handle_carve_out_rsc + * + * Carveout resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to carveout resource + * + * @returns - 0 for success, or negative value for failure + * + */ +int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_carveout *carve_rsc = (struct fw_rsc_carveout *)rsc; + metal_phys_addr_t da; + metal_phys_addr_t pa; + size_t size; + unsigned int attribute; + + /* Validate resource fields */ + if (!carve_rsc) { + return -RPROC_ERR_RSC_TAB_NP; + } + + if (carve_rsc->reserved) { + return -RPROC_ERR_RSC_TAB_RSVD; + } + pa = carve_rsc->pa; + da = carve_rsc->da; + size = carve_rsc->len; + attribute = carve_rsc->flags; + if (remoteproc_mmap(rproc, &pa, &da, size, attribute, NULL)) + return 0; + else + return -RPROC_EINVAL; +} + +int handle_vendor_rsc(struct remoteproc *rproc, void *rsc) +{ + if (rproc && rproc->ops->handle_rsc) { + struct fw_rsc_vendor *vend_rsc = rsc; + size_t len = vend_rsc->len; + + return rproc->ops->handle_rsc(rproc, rsc, len); + } + return -RPROC_ERR_RSC_TAB_NS; +} + +int handle_vdev_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_vdev *vdev_rsc = (struct fw_rsc_vdev *)rsc; + unsigned int notifyid, i, num_vrings; + + /* only assign notification IDs but do not initialize vdev */ + notifyid = vdev_rsc->notifyid; + if (notifyid == RSC_NOTIFY_ID_ANY) { + notifyid = remoteproc_allocate_id(rproc, + notifyid, notifyid + 1); + vdev_rsc->notifyid = notifyid; + } + + num_vrings = vdev_rsc->num_of_vrings; + for (i = 0; i < num_vrings; i++) { + struct fw_rsc_vdev_vring *vring_rsc; + + vring_rsc = &vdev_rsc->vring[i]; + notifyid = vring_rsc->notifyid; + if (notifyid == RSC_NOTIFY_ID_ANY) { + notifyid = remoteproc_allocate_id(rproc, + notifyid, + notifyid + 1); + vdev_rsc->notifyid = notifyid; + } + } + + return 0; +} + +/** + * handle_trace_rsc + * + * trace resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to trace resource + * + * @returns - no service error + * + */ +int handle_trace_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_trace *vdev_rsc = (struct fw_rsc_trace *)rsc; + (void)rproc; + + if (vdev_rsc->da != FW_RSC_U32_ADDR_ANY && vdev_rsc->len != 0) + return 0; + /* FIXME: master should allocated a memory used by slave */ + + return -RPROC_ERR_RSC_TAB_NS; +} + +/** + * handle_dummy_rsc + * + * dummy resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to trace resource + * + * @returns - no service error + * + */ +static int handle_dummy_rsc(struct remoteproc *rproc, void *rsc) +{ + (void)rproc; + (void)rsc; + + return -RPROC_ERR_RSC_TAB_NS; +} + +size_t find_rsc(void *rsc_table, unsigned int rsc_type, unsigned int index) +{ + struct resource_table *r_table = rsc_table; + unsigned int i, rsc_index; + unsigned int lrsc_type; + char *rsc_start; + + metal_assert(r_table); + /* Loop through the offset array and parse each resource entry */ + rsc_index = 0; + for (i = 0; i < r_table->num; i++) { + rsc_start = (char *)r_table; + rsc_start += r_table->offset[i]; + lrsc_type = *((uint32_t *)rsc_start); + if (lrsc_type == rsc_type) { + if (rsc_index++ == index) + return r_table->offset[i]; + } + } + return 0; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/CMakeLists.txt b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/CMakeLists.txt new file mode 100644 index 0000000000..e2bd8d8051 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/CMakeLists.txt @@ -0,0 +1,2 @@ +collect (PROJECT_LIB_SOURCES rpmsg.c) +collect (PROJECT_LIB_SOURCES rpmsg_virtio.c) diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg.c new file mode 100644 index 0000000000..0638a4f2e3 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * Copyright (c) 2018 Linaro, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <openamp/rpmsg.h> +#include <metal/alloc.h> + +#include "rpmsg_internal.h" + +/** + * rpmsg_get_address + * + * This function provides unique 32 bit address. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * + * return - a unique address + */ +static uint32_t rpmsg_get_address(unsigned long *bitmap, int size) +{ + unsigned int addr = RPMSG_ADDR_ANY; + unsigned int nextbit; + + nextbit = metal_bitmap_next_clear_bit(bitmap, 0, size); + if (nextbit < (uint32_t)size) { + addr = nextbit; + metal_bitmap_set_bit(bitmap, nextbit); + } + + return addr; +} + +/** + * rpmsg_release_address + * + * Frees the given address. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + */ +static void rpmsg_release_address(unsigned long *bitmap, int size, + int addr) +{ + if (addr < size) + metal_bitmap_clear_bit(bitmap, addr); +} + +/** + * rpmsg_is_address_set + * + * Checks whether address is used or free. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + * + * return - TRUE/FALSE + */ +static int rpmsg_is_address_set(unsigned long *bitmap, int size, int addr) +{ + if (addr < size) + return metal_bitmap_is_bit_set(bitmap, addr); + else + return RPMSG_ERR_PARAM; +} + +/** + * rpmsg_set_address + * + * Marks the address as consumed. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + * + * return - none + */ +static int rpmsg_set_address(unsigned long *bitmap, int size, int addr) +{ + if (addr < size) { + metal_bitmap_set_bit(bitmap, addr); + return RPMSG_SUCCESS; + } else { + return RPMSG_ERR_PARAM; + } +} + +/** + * This function sends rpmsg "message" to remote device. + * + * @param ept - pointer to end point + * @param src - source address of channel + * @param dst - destination address of channel + * @param data - data to transmit + * @param size - size of data + * @param wait - boolean, wait or not for buffer to become + * available + * + * @return - size of data sent or negative value for failure. + * + */ +int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + uint32_t dst, const void *data, int size, + int wait) +{ + struct rpmsg_device *rdev; + + if (!ept || !ept->rdev || !data || dst == RPMSG_ADDR_ANY) + return RPMSG_ERR_PARAM; + + rdev = ept->rdev; + + if (rdev->ops.send_offchannel_raw) + return rdev->ops.send_offchannel_raw(rdev, src, dst, data, + size, wait); + + return RPMSG_ERR_PARAM; +} + +int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags) +{ + struct rpmsg_ns_msg ns_msg; + int ret; + + ns_msg.flags = flags; + ns_msg.addr = ept->addr; + strncpy(ns_msg.name, ept->name, sizeof(ns_msg.name)); + ret = rpmsg_send_offchannel_raw(ept, ept->addr, + RPMSG_NS_EPT_ADDR, + &ns_msg, sizeof(ns_msg), true); + if (ret < 0) + return ret; + else + return RPMSG_SUCCESS; +} + +struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rdev, + const char *name, uint32_t addr, + uint32_t dest_addr) +{ + struct metal_list *node; + struct rpmsg_endpoint *ept; + + metal_list_for_each(&rdev->endpoints, node) { + int name_match = 0; + + ept = metal_container_of(node, struct rpmsg_endpoint, node); + /* try to get by local address only */ + if (addr != RPMSG_ADDR_ANY && ept->addr == addr) + return ept; + /* try to find match on local end remote address */ + if (addr == ept->addr && dest_addr == ept->dest_addr) + return ept; + /* else use name service and destination address */ + if (name) + name_match = !strncmp(ept->name, name, + sizeof(ept->name)); + if (!name || !name_match) + continue; + /* destination address is known, equal to ept remote address*/ + if (dest_addr != RPMSG_ADDR_ANY && ept->dest_addr == dest_addr) + return ept; + /* ept is registered but not associated to remote ept*/ + if (addr == RPMSG_ADDR_ANY && ept->dest_addr == RPMSG_ADDR_ANY) + return ept; + } + return NULL; +} + +static void rpmsg_unregister_endpoint(struct rpmsg_endpoint *ept) +{ + struct rpmsg_device *rdev; + + if (!ept) + return; + + rdev = ept->rdev; + + if (ept->addr != RPMSG_ADDR_ANY) + rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, + ept->addr); + metal_list_del(&ept->node); +} + +int rpmsg_register_endpoint(struct rpmsg_device *rdev, + struct rpmsg_endpoint *ept) +{ + ept->rdev = rdev; + + metal_list_add_tail(&rdev->endpoints, &ept->node); + return RPMSG_SUCCESS; +} + +int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + const char *name, uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, rpmsg_ns_unbind_cb unbind_cb) +{ + int status; + uint32_t addr = src; + + if (!ept) + return RPMSG_ERR_PARAM; + + metal_mutex_acquire(&rdev->lock); + if (src != RPMSG_ADDR_ANY) { + status = rpmsg_is_address_set(rdev->bitmap, + RPMSG_ADDR_BMP_SIZE, src); + if (!status) { + /* Mark the address as used in the address bitmap. */ + rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, + src); + } else if (status > 0) { + status = RPMSG_SUCCESS; + goto ret_status; + } else { + goto ret_status; + } + } else { + addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE); + } + + rpmsg_init_ept(ept, name, addr, dest, cb, unbind_cb); + + status = rpmsg_register_endpoint(rdev, ept); + if (status < 0) + rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr); + + if (!status && ept->dest_addr == RPMSG_ADDR_ANY) { + /* Send NS announcement to remote processor */ + metal_mutex_release(&rdev->lock); + status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE); + metal_mutex_acquire(&rdev->lock); + if (status) + rpmsg_unregister_endpoint(ept); + } + +ret_status: + metal_mutex_release(&rdev->lock); + return status; +} + +/** + * rpmsg_destroy_ept + * + * This function deletes rpmsg endpoint and performs cleanup. + * + * @param ept - pointer to endpoint to destroy + * + */ +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) +{ + struct rpmsg_device *rdev; + + if (!ept) + return; + + rdev = ept->rdev; + if (ept->addr != RPMSG_NS_EPT_ADDR) + (void)rpmsg_send_ns_message(ept, RPMSG_NS_DESTROY); + metal_mutex_acquire(&rdev->lock); + rpmsg_unregister_endpoint(ept); + metal_mutex_release(&rdev->lock); +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_internal.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_internal.h new file mode 100644 index 0000000000..e1b82086c9 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_internal.h @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef _RPMSG_INTERNAL_H_ +#define _RPMSG_INTERNAL_H_ + +#include <stdint.h> +#include <openamp/rpmsg.h> + +#if defined __cplusplus +extern "C" { +#endif + +#ifdef RPMSG_DEBUG +#define RPMSG_ASSERT(_exp, _msg) do { \ + if (!(_exp)) { \ + openamp_print("FATAL: %s - _msg", __func__); \ + while (1) { \ + ; \ + } \ + } \ + } while (0) +#else +#define RPMSG_ASSERT(_exp, _msg) do { \ + if (!(_exp)) \ + while (1) { \ + ; \ + } \ + } while (0) +#endif + +#define RPMSG_LOCATE_DATA(p) ((unsigned char *)(p) + sizeof(struct rpmsg_hdr)) +/** + * enum rpmsg_ns_flags - dynamic name service announcement flags + * + * @RPMSG_NS_CREATE: a new remote service was just created + * @RPMSG_NS_DESTROY: a known remote service was just destroyed + * @RPMSG_NS_CREATE_WITH_ACK: a new remote service was just created waiting + * acknowledgment. + */ +enum rpmsg_ns_flags { + RPMSG_NS_CREATE = 0, + RPMSG_NS_DESTROY = 1, +}; + +/** + * struct rpmsg_hdr - common header for all rpmsg messages + * @src: source address + * @dst: destination address + * @reserved: reserved for future use + * @len: length of payload (in bytes) + * @flags: message flags + * + * Every message sent(/received) on the rpmsg bus begins with this header. + */ +OPENAMP_PACKED_BEGIN +struct rpmsg_hdr { + uint32_t src; + uint32_t dst; + uint32_t reserved; + uint16_t len; + uint16_t flags; +} OPENAMP_PACKED_END; + +/** + * struct rpmsg_ns_msg - dynamic name service announcement message + * @name: name of remote service that is published + * @addr: address of remote service that is published + * @flags: indicates whether service is created or destroyed + * + * This message is sent across to publish a new service, or announce + * about its removal. When we receive these messages, an appropriate + * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe() + * or ->remove() handler of the appropriate rpmsg driver will be invoked + * (if/as-soon-as one is registered). + */ +OPENAMP_PACKED_BEGIN +struct rpmsg_ns_msg { + char name[RPMSG_NAME_SIZE]; + uint32_t addr; + uint32_t flags; +} OPENAMP_PACKED_END; + +int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags); + +struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rvdev, + const char *name, uint32_t addr, + uint32_t dest_addr); +int rpmsg_register_endpoint(struct rpmsg_device *rdev, + struct rpmsg_endpoint *ept); + +static inline struct rpmsg_endpoint * +rpmsg_get_ept_from_addr(struct rpmsg_device *rdev, uint32_t addr) +{ + return rpmsg_get_endpoint(rdev, NULL, addr, RPMSG_ADDR_ANY); +} + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_INTERNAL_H_ */ diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_virtio.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_virtio.c new file mode 100644 index 0000000000..8ae41089fe --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/rpmsg/rpmsg_virtio.c @@ -0,0 +1,692 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * Copyright (c) 2018 Linaro, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <metal/alloc.h> +#include <metal/cache.h> +#include <metal/sleep.h> +#include <metal/utilities.h> +#include <openamp/rpmsg_virtio.h> +#include <openamp/virtqueue.h> + +#include "rpmsg_internal.h" + +#define RPMSG_NUM_VRINGS (2) + +/* Total tick count for 15secs - 1msec tick. */ +#define RPMSG_TICK_COUNT 15000 + +/* Time to wait - In multiple of 10 msecs. */ +#define RPMSG_TICKS_PER_INTERVAL 10 + +#define WORD_SIZE sizeof(unsigned long) +#define WORD_ALIGN(a) ((((a) & (WORD_SIZE - 1)) != 0) ? \ + (((a) & (~(WORD_SIZE - 1))) + WORD_SIZE) : (a)) + +#ifndef VIRTIO_SLAVE_ONLY +metal_weak void * +rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool, + size_t size) +{ + void *buffer; + + if (shpool->avail < size) + return NULL; + buffer = (void *)((char *)shpool->base + shpool->size - shpool->avail); + shpool->avail -= size; + + return buffer; +} +#endif /*!VIRTIO_SLAVE_ONLY*/ + +void rpmsg_virtio_init_shm_pool(struct rpmsg_virtio_shm_pool *shpool, + void *shb, size_t size) +{ + if (!shpool) + return; + shpool->base = shb; + shpool->size = WORD_ALIGN(size); + shpool->avail = WORD_ALIGN(size); +} + +/** + * rpmsg_virtio_return_buffer + * + * Places the used buffer back on the virtqueue. + * + * @param rvdev - pointer to remote core + * @param buffer - buffer pointer + * @param len - buffer length + * @param idx - buffer index + * + */ +static void rpmsg_virtio_return_buffer(struct rpmsg_virtio_device *rvdev, + void *buffer, unsigned long len, + unsigned short idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + + (void)idx; + /* Initialize buffer node */ + vqbuf.buf = buffer; + vqbuf.len = len; + virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1, buffer); + } +#endif /*VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + (void)buffer; + virtqueue_add_consumed_buffer(rvdev->rvq, idx, len); + } +#endif /*VIRTIO_MASTER_ONLY*/ +} + +/** + * rpmsg_virtio_enqueue_buffer + * + * Places buffer on the virtqueue for consumption by the other side. + * + * @param rvdev - pointer to rpmsg virtio + * @param buffer - buffer pointer + * @param len - buffer length + * @param idx - buffer index + * + * @return - status of function execution + */ +static int rpmsg_virtio_enqueue_buffer(struct rpmsg_virtio_device *rvdev, + void *buffer, unsigned long len, + unsigned short idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + (void)idx; + + /* Initialize buffer node */ + vqbuf.buf = buffer; + vqbuf.len = len; + return virtqueue_add_buffer(rvdev->svq, &vqbuf, 0, 1, buffer); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + (void)buffer; + return virtqueue_add_consumed_buffer(rvdev->svq, idx, len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + return 0; +} + +/** + * rpmsg_virtio_get_tx_buffer + * + * Provides buffer to transmit messages. + * + * @param rvdev - pointer to rpmsg device + * @param len - length of returned buffer + * @param idx - buffer index + * + * return - pointer to buffer. + */ +static void *rpmsg_virtio_get_tx_buffer(struct rpmsg_virtio_device *rvdev, + unsigned long *len, + unsigned short *idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + void *data = NULL; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + data = virtqueue_get_buffer(rvdev->svq, (uint32_t *)len, idx); + if (data == NULL) { + data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool, + RPMSG_BUFFER_SIZE); + *len = RPMSG_BUFFER_SIZE; + } + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + data = virtqueue_get_available_buffer(rvdev->svq, idx, + (uint32_t *)len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + return data; +} + +/** + * rpmsg_virtio_get_rx_buffer + * + * Retrieves the received buffer from the virtqueue. + * + * @param rvdev - pointer to rpmsg device + * @param len - size of received buffer + * @param idx - index of buffer + * + * @return - pointer to received buffer + * + */ +static void *rpmsg_virtio_get_rx_buffer(struct rpmsg_virtio_device *rvdev, + unsigned long *len, + unsigned short *idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + void *data = NULL; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + data = virtqueue_get_buffer(rvdev->rvq, (uint32_t *)len, idx); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + data = + virtqueue_get_available_buffer(rvdev->rvq, idx, + (uint32_t *)len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + if (data) { + /* FIX ME: library should not worry about if it needs + * to flush/invalidate cache, it is shared memory. + * The shared memory should be mapped properly before + * using it. + */ + metal_cache_invalidate(data, (unsigned int)(*len)); + } + + return data; +} + +#ifndef VIRTIO_MASTER_ONLY +/** + * check if the remote is ready to start RPMsg communication + */ +static int rpmsg_virtio_wait_remote_ready(struct rpmsg_virtio_device *rvdev) +{ + uint8_t status; + + while (1) { + status = rpmsg_virtio_get_status(rvdev); + /* Busy wait until the remote is ready */ + if (status & VIRTIO_CONFIG_STATUS_NEEDS_RESET) { + rpmsg_virtio_set_status(rvdev, 0); + /* TODO notify remote processor */ + } else if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK) { + return true; + } + /* TODO: clarify metal_cpu_yield usage*/ + metal_cpu_yield(); + } + + return false; +} +#endif /*!VIRTIO_MASTER_ONLY*/ + +/** + * _rpmsg_virtio_get_buffer_size + * + * Returns buffer size available for sending messages. + * + * @param channel - pointer to rpmsg channel + * + * @return - buffer size + * + */ +static int _rpmsg_virtio_get_buffer_size(struct rpmsg_virtio_device *rvdev) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + int length = 0; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + /* + * If device role is Remote then buffers are provided by us + * (RPMSG Master), so just provide the macro. + */ + length = RPMSG_BUFFER_SIZE - sizeof(struct rpmsg_hdr); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + /* + * If other core is Master then buffers are provided by it, + * so get the buffer size from the virtqueue. + */ + length = + (int)virtqueue_get_desc_size(rvdev->svq) - + sizeof(struct rpmsg_hdr); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + return length; +} + +/** + * This function sends rpmsg "message" to remote device. + * + * @param rdev - pointer to rpmsg device + * @param src - source address of channel + * @param dst - destination address of channel + * @param data - data to transmit + * @param size - size of data + * @param wait - boolean, wait or not for buffer to become + * available + * + * @return - size of data sent or negative value for failure. + * + */ +static int rpmsg_virtio_send_offchannel_raw(struct rpmsg_device *rdev, + uint32_t src, uint32_t dst, + const void *data, + int size, int wait) +{ + struct rpmsg_virtio_device *rvdev; + struct rpmsg_hdr rp_hdr; + void *buffer = NULL; + unsigned short idx; + int tick_count = 0; + unsigned long buff_len; + int status; + struct metal_io_region *io; + + /* Get the associated remote device for channel. */ + rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); + + status = rpmsg_virtio_get_status(rvdev); + /* Validate device state */ + if (!(status & VIRTIO_CONFIG_STATUS_DRIVER_OK)) { + return RPMSG_ERR_DEV_STATE; + } + + if (wait) + tick_count = RPMSG_TICK_COUNT / RPMSG_TICKS_PER_INTERVAL; + else + tick_count = 0; + + while (1) { + int avail_size; + + /* Lock the device to enable exclusive access to virtqueues */ + metal_mutex_acquire(&rdev->lock); + avail_size = _rpmsg_virtio_get_buffer_size(rvdev); + if (size <= avail_size) + buffer = rpmsg_virtio_get_tx_buffer(rvdev, &buff_len, + &idx); + metal_mutex_release(&rdev->lock); + if (buffer || !tick_count) + break; + if (avail_size != 0) + return RPMSG_ERR_BUFF_SIZE; + metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); + tick_count--; + } + if (!buffer) + return RPMSG_ERR_NO_BUFF; + + /* Initialize RPMSG header. */ + rp_hdr.dst = dst; + rp_hdr.src = src; + rp_hdr.len = size; + rp_hdr.reserved = 0; + + /* Copy data to rpmsg buffer. */ + io = rvdev->shbuf_io; + status = metal_io_block_write(io, metal_io_virt_to_offset(io, buffer), + &rp_hdr, sizeof(rp_hdr)); + RPMSG_ASSERT(status == sizeof(rp_hdr), "failed to write header\n"); + + status = metal_io_block_write(io, + metal_io_virt_to_offset(io, + RPMSG_LOCATE_DATA(buffer)), + data, size); + RPMSG_ASSERT(status == size, "failed to write buffer\n"); + metal_mutex_acquire(&rdev->lock); + + /* Enqueue buffer on virtqueue. */ + status = rpmsg_virtio_enqueue_buffer(rvdev, buffer, buff_len, idx); + RPMSG_ASSERT(status == VQUEUE_SUCCESS, "failed to enqueue buffer\n"); + /* Let the other side know that there is a job to process. */ + virtqueue_kick(rvdev->svq); + + metal_mutex_release(&rdev->lock); + + return size; +} + +/** + * rpmsg_virtio_tx_callback + * + * Tx callback function. + * + * @param vq - pointer to virtqueue on which Tx is has been + * completed. + * + */ +static void rpmsg_virtio_tx_callback(struct virtqueue *vq) +{ + (void)vq; +} + +/** + * rpmsg_virtio_rx_callback + * + * Rx callback function. + * + * @param vq - pointer to virtqueue on which messages is received + * + */ +static void rpmsg_virtio_rx_callback(struct virtqueue *vq) +{ + struct virtio_device *vdev = vq->vq_dev; + struct rpmsg_virtio_device *rvdev = vdev->priv; + struct rpmsg_device *rdev = &rvdev->rdev; + struct rpmsg_endpoint *ept; + struct rpmsg_hdr *rp_hdr; + unsigned long len; + unsigned short idx; + int status; + + metal_mutex_acquire(&rdev->lock); + + /* Process the received data from remote node */ + rp_hdr = (struct rpmsg_hdr *)rpmsg_virtio_get_rx_buffer(rvdev, + &len, &idx); + + metal_mutex_release(&rdev->lock); + + while (rp_hdr) { + /* Get the channel node from the remote device channels list. */ + metal_mutex_acquire(&rdev->lock); + ept = rpmsg_get_ept_from_addr(rdev, rp_hdr->dst); + metal_mutex_release(&rdev->lock); + + if (!ept) + /* Fatal error no endpoint for the given dst addr. */ + return; + + if (ept->dest_addr == RPMSG_ADDR_ANY) { + /* + * First message received from the remote side, + * update channel destination address + */ + ept->dest_addr = rp_hdr->src; + } + status = ept->cb(ept, (void *)RPMSG_LOCATE_DATA(rp_hdr), + rp_hdr->len, ept->addr, ept->priv); + + RPMSG_ASSERT(status == RPMSG_SUCCESS, + "unexpected callback status\n"); + metal_mutex_acquire(&rdev->lock); + + /* Return used buffers. */ + rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx); + + rp_hdr = (struct rpmsg_hdr *) + rpmsg_virtio_get_rx_buffer(rvdev, &len, &idx); + metal_mutex_release(&rdev->lock); + } +} + +/** + * rpmsg_virtio_ns_callback + * + * This callback handles name service announcement from the remote device + * and creates/deletes rpmsg channels. + * + * @param server_chnl - pointer to server channel control block. + * @param data - pointer to received messages + * @param len - length of received data + * @param priv - any private data + * @param src - source address + * + * @return - rpmag endpoint callback handled + */ + +#if defined (__GNUC__) && ! defined (__CC_ARM) +#pragma GCC push_options +#pragma GCC optimize ("O0") +#elif defined (__CC_ARM) +#pragma push +#pragma O0 +#endif +static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, void *priv) +{ + struct rpmsg_device *rdev = ept->rdev; + struct rpmsg_virtio_device *rvdev = (struct rpmsg_virtio_device *)rdev; + struct metal_io_region *io = rvdev->shbuf_io; + struct rpmsg_endpoint *_ept; + struct rpmsg_ns_msg *ns_msg; + uint32_t dest; + char name[RPMSG_NAME_SIZE]; + + (void)priv; + (void)src; + + ns_msg = (struct rpmsg_ns_msg *)data; + if (len != sizeof(*ns_msg)) + /* Returns as the message is corrupted */ + return RPMSG_SUCCESS; + metal_io_block_read(io, + metal_io_virt_to_offset(io, ns_msg->name), + &name, sizeof(name)); + dest = ns_msg->addr; + + /* check if a Ept has been locally registered */ + metal_mutex_acquire(&rdev->lock); + _ept = rpmsg_get_endpoint(rdev, name, RPMSG_ADDR_ANY, dest); + + if (ns_msg->flags & RPMSG_NS_DESTROY) { + if (_ept) + _ept->dest_addr = RPMSG_ADDR_ANY; + metal_mutex_release(&rdev->lock); + if (_ept && _ept->ns_unbind_cb) + _ept->ns_unbind_cb(ept); + } else { + if (!_ept) { + /* + * send callback to application, that can + * - create the associated endpoints. + * - store information for future use. + * - just ignore the request as service not supported. + */ + metal_mutex_release(&rdev->lock); + if (rdev->ns_bind_cb) + rdev->ns_bind_cb(rdev, name, dest); + } else { + _ept->dest_addr = dest; + metal_mutex_release(&rdev->lock); + } + } + + return RPMSG_SUCCESS; +} +#if defined (__GNUC__) && ! defined (__CC_ARM) +#pragma GCC pop_options +#elif defined (__CC_ARM) +#pragma pop +#endif + +int rpmsg_virtio_get_buffer_size(struct rpmsg_device *rdev) +{ + int size; + struct rpmsg_virtio_device *rvdev; + + if (!rdev) + return RPMSG_ERR_PARAM; + metal_mutex_acquire(&rdev->lock); + rvdev = (struct rpmsg_virtio_device *)rdev; + size = _rpmsg_virtio_get_buffer_size(rvdev); + metal_mutex_release(&rdev->lock); + return size; +} + +int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + struct virtio_device *vdev, + rpmsg_ns_bind_cb ns_bind_cb, + struct metal_io_region *shm_io, + struct rpmsg_virtio_shm_pool *shpool) +{ + struct rpmsg_device *rdev; + const char *vq_names[RPMSG_NUM_VRINGS]; + typedef void (*vqcallback)(struct virtqueue *vq); + vqcallback callback[RPMSG_NUM_VRINGS]; + unsigned long dev_features; + int status; + unsigned int i, role; + + rdev = &rvdev->rdev; + memset(rdev, 0, sizeof(*rdev)); + metal_mutex_init(&rdev->lock); + rvdev->vdev = vdev; + rdev->ns_bind_cb = ns_bind_cb; + vdev->priv = rvdev; + rdev->ops.send_offchannel_raw = rpmsg_virtio_send_offchannel_raw; + role = rpmsg_virtio_get_role(rvdev); + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + /* + * Since device is RPMSG Remote so we need to manage the + * shared buffers. Create shared memory pool to handle buffers. + */ + if (!shpool) + return RPMSG_ERR_PARAM; + if (!shpool->size) + return RPMSG_ERR_NO_BUFF; + rvdev->shpool = shpool; + + vq_names[0] = "rx_vq"; + vq_names[1] = "tx_vq"; + callback[0] = rpmsg_virtio_rx_callback; + callback[1] = rpmsg_virtio_tx_callback; + rvdev->rvq = vdev->vrings_info[0].vq; + rvdev->svq = vdev->vrings_info[1].vq; + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + (void)shpool; + if (role == RPMSG_REMOTE) { + vq_names[0] = "tx_vq"; + vq_names[1] = "rx_vq"; + callback[0] = rpmsg_virtio_tx_callback; + callback[1] = rpmsg_virtio_rx_callback; + rvdev->rvq = vdev->vrings_info[1].vq; + rvdev->svq = vdev->vrings_info[0].vq; + } +#endif /*!VIRTIO_MASTER_ONLY*/ + rvdev->shbuf_io = shm_io; + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + /* wait synchro with the master */ + rpmsg_virtio_wait_remote_ready(rvdev); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + /* Create virtqueues for remote device */ + status = rpmsg_virtio_create_virtqueues(rvdev, 0, RPMSG_NUM_VRINGS, + vq_names, callback); + if (status != RPMSG_SUCCESS) + return status; + + /* TODO: can have a virtio function to set the shared memory I/O */ + for (i = 0; i < RPMSG_NUM_VRINGS; i++) { + struct virtqueue *vq; + + vq = vdev->vrings_info[i].vq; + vq->shm_io = shm_io; + } + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + unsigned int idx; + void *buffer; + + vqbuf.len = RPMSG_BUFFER_SIZE; + for (idx = 0; idx < rvdev->rvq->vq_nentries; idx++) { + /* Initialize TX virtqueue buffers for remote device */ + buffer = rpmsg_virtio_shm_pool_get_buffer(shpool, + RPMSG_BUFFER_SIZE); + + if (!buffer) { + return RPMSG_ERR_NO_BUFF; + } + + vqbuf.buf = buffer; + + metal_io_block_set(shm_io, + metal_io_virt_to_offset(shm_io, + buffer), + 0x00, RPMSG_BUFFER_SIZE); + status = + virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1, + buffer); + + if (status != RPMSG_SUCCESS) { + return status; + } + } + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + + /* Initialize channels and endpoints list */ + metal_list_init(&rdev->endpoints); + + dev_features = rpmsg_virtio_get_features(rvdev); + + /* + * Create name service announcement endpoint if device supports name + * service announcement feature. + */ + if ((dev_features & (1 << VIRTIO_RPMSG_F_NS))) { + rpmsg_init_ept(&rdev->ns_ept, "NS", + RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR, + rpmsg_virtio_ns_callback, NULL); + (void)rpmsg_register_endpoint(rdev, &rdev->ns_ept); + } + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) + rpmsg_virtio_set_status(rvdev, VIRTIO_CONFIG_STATUS_DRIVER_OK); +#endif /*!VIRTIO_SLAVE_ONLY*/ + + return status; +} + +void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev) +{ + struct metal_list *node; + struct rpmsg_device *rdev; + struct rpmsg_endpoint *ept; + + rdev = &rvdev->rdev; + while (!metal_list_is_empty(&rdev->endpoints)) { + node = rdev->endpoints.next; + ept = metal_container_of(node, struct rpmsg_endpoint, node); + rpmsg_destroy_ept(ept); + } + + rvdev->rvq = 0; + rvdev->svq = 0; + + metal_mutex_deinit(&rdev->lock); +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/virtio/virtio.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/virtio/virtio.c new file mode 100644 index 0000000000..5cf87222b6 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/virtio/virtio.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2011, Bryan Venteicher <[email protected]> + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include <openamp/virtio.h> + +static const char *virtio_feature_name(unsigned long feature, + const struct virtio_feature_desc *); + +//TODO : This structure may change depending on the types of devices we support. +static const struct virtio_ident { + unsigned short devid; + const char *name; +} virtio_ident_table[] = { + { + VIRTIO_ID_NETWORK, "Network"}, { + VIRTIO_ID_BLOCK, "Block"}, { + VIRTIO_ID_CONSOLE, "Console"}, { + VIRTIO_ID_ENTROPY, "Entropy"}, { + VIRTIO_ID_BALLOON, "Balloon"}, { + VIRTIO_ID_IOMEMORY, "IOMemory"}, { + VIRTIO_ID_SCSI, "SCSI"}, { + VIRTIO_ID_9P, "9P Transport"}, { + 0, NULL} +}; + +/* Device independent features. */ +static const struct virtio_feature_desc virtio_common_feature_desc[] = { + {VIRTIO_F_NOTIFY_ON_EMPTY, "NotifyOnEmpty"}, + {VIRTIO_RING_F_INDIRECT_DESC, "RingIndirect"}, + {VIRTIO_RING_F_EVENT_IDX, "EventIdx"}, + {VIRTIO_F_BAD_FEATURE, "BadFeature"}, + + {0, NULL} +}; + +const char *virtio_dev_name(unsigned short devid) +{ + const struct virtio_ident *ident; + + for (ident = virtio_ident_table; ident->name != NULL; ident++) { + if (ident->devid == devid) + return (ident->name); + } + + return (NULL); +} + +static const char *virtio_feature_name(unsigned long val, + const struct virtio_feature_desc *desc) +{ + int i, j; + const struct virtio_feature_desc *descs[2] = { desc, + virtio_common_feature_desc + }; + + for (i = 0; i < 2; i++) { + if (!descs[i]) + continue; + + for (j = 0; descs[i][j].vfd_val != 0; j++) { + if (val == descs[i][j].vfd_val) + return (descs[i][j].vfd_str); + } + } + + return (NULL); +} + +void virtio_describe(struct virtio_device *dev, const char *msg, + uint32_t features, struct virtio_feature_desc *desc) +{ + (void)dev; + (void)msg; + (void)features; + + // TODO: Not used currently - keeping it for future use + virtio_feature_name(0, desc); +} + +int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, + unsigned int nvqs, const char *names[], + vq_callback *callbacks[]) +{ + struct virtio_vring_info *vring_info; + struct vring_alloc_info *vring_alloc; + unsigned int num_vrings, i; + int ret; + (void)flags; + + num_vrings = vdev->vrings_num; + if (nvqs > num_vrings) + return -ERROR_VQUEUE_INVLD_PARAM; + /* Initialize virtqueue for each vring */ + for (i = 0; i < nvqs; i++) { + vring_info = &vdev->vrings_info[i]; + + vring_alloc = &vring_info->info; +#ifndef VIRTIO_SLAVE_ONLY + if (vdev->role == VIRTIO_DEV_MASTER) { + size_t offset; + struct metal_io_region *io = vring_info->io; + + offset = metal_io_virt_to_offset(io, + vring_alloc->vaddr); + metal_io_block_set(io, offset, 0, + vring_size(vring_alloc->num_descs, + vring_alloc->align)); + } +#endif + ret = virtqueue_create(vdev, i, names[i], vring_alloc, + callbacks[i], vdev->func->notify, + vring_info->vq); + if (ret) + return ret; + } + return 0; +} + diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/virtio/virtqueue.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/virtio/virtqueue.c new file mode 100644 index 0000000000..e90a6940b0 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/open-amp/lib/virtio/virtqueue.c @@ -0,0 +1,618 @@ +/*- + * Copyright (c) 2011, Bryan Venteicher <[email protected]> + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <string.h> +#include <openamp/virtqueue.h> +#include <metal/atomic.h> +#include <metal/log.h> +#include <metal/alloc.h> + +/* Prototype for internal functions. */ +static void vq_ring_init(struct virtqueue *, void *, int); +static void vq_ring_update_avail(struct virtqueue *, uint16_t); +static uint16_t vq_ring_add_buffer(struct virtqueue *, struct vring_desc *, + uint16_t, struct virtqueue_buf *, int, int); +static int vq_ring_enable_interrupt(struct virtqueue *, uint16_t); +static void vq_ring_free_chain(struct virtqueue *, uint16_t); +static int vq_ring_must_notify_host(struct virtqueue *vq); +static void vq_ring_notify_host(struct virtqueue *vq); +static int virtqueue_nused(struct virtqueue *vq); + +/* Default implementation of P2V based on libmetal */ +static inline void *virtqueue_phys_to_virt(struct virtqueue *vq, + metal_phys_addr_t phys) +{ + struct metal_io_region *io = vq->shm_io; + + return metal_io_phys_to_virt(io, phys); +} + +/* Default implementation of V2P based on libmetal */ +static inline metal_phys_addr_t virtqueue_virt_to_phys(struct virtqueue *vq, + void *buf) +{ + struct metal_io_region *io = vq->shm_io; + + return metal_io_virt_to_phys(io, buf); +} + +/** + * virtqueue_create - Creates new VirtIO queue + * + * @param device - Pointer to VirtIO device + * @param id - VirtIO queue ID , must be unique + * @param name - Name of VirtIO queue + * @param ring - Pointer to vring_alloc_info control block + * @param callback - Pointer to callback function, invoked + * when message is available on VirtIO queue + * @param notify - Pointer to notify function, used to notify + * other side that there is job available for it + * @param vq - Created VirtIO queue. + * + * @return - Function status + */ +int virtqueue_create(struct virtio_device *virt_dev, unsigned short id, + const char *name, struct vring_alloc_info *ring, + void (*callback)(struct virtqueue *vq), + void (*notify)(struct virtqueue *vq), + struct virtqueue *vq) +{ + int status = VQUEUE_SUCCESS; + + VQ_PARAM_CHK(ring == NULL, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(ring->num_descs == 0, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(ring->num_descs & (ring->num_descs - 1), status, + ERROR_VRING_ALIGN); + VQ_PARAM_CHK(vq == NULL, status, ERROR_NO_MEM); + + if (status == VQUEUE_SUCCESS) { + vq->vq_dev = virt_dev; + vq->vq_name = name; + vq->vq_queue_index = id; + vq->vq_nentries = ring->num_descs; + vq->vq_free_cnt = vq->vq_nentries; + vq->callback = callback; + vq->notify = notify; + + /* Initialize vring control block in virtqueue. */ + vq_ring_init(vq, (void *)ring->vaddr, ring->align); + + /* Disable callbacks - will be enabled by the application + * once initialization is completed. + */ + virtqueue_disable_cb(vq); + } + + return (status); +} + +/** + * virtqueue_add_buffer() - Enqueues new buffer in vring for consumption + * by other side. Readable buffers are always + * inserted before writable buffers + * + * @param vq - Pointer to VirtIO queue control block. + * @param buf_list - Pointer to a list of virtqueue buffers. + * @param readable - Number of readable buffers + * @param writable - Number of writable buffers + * @param cookie - Pointer to hold call back data + * + * @return - Function status + */ +int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list, + int readable, int writable, void *cookie) +{ + struct vq_desc_extra *dxp = NULL; + int status = VQUEUE_SUCCESS; + uint16_t head_idx; + uint16_t idx; + int needed; + + needed = readable + writable; + + VQ_PARAM_CHK(vq == NULL, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(needed < 1, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(vq->vq_free_cnt == 0, status, ERROR_VRING_FULL); + + VQUEUE_BUSY(vq); + + if (status == VQUEUE_SUCCESS) { + VQASSERT(vq, cookie != NULL, "enqueuing with no cookie"); + + head_idx = vq->vq_desc_head_idx; + VQ_RING_ASSERT_VALID_IDX(vq, head_idx); + dxp = &vq->vq_descx[head_idx]; + + VQASSERT(vq, dxp->cookie == NULL, + "cookie already exists for index"); + + dxp->cookie = cookie; + dxp->ndescs = needed; + + /* Enqueue buffer onto the ring. */ + idx = vq_ring_add_buffer(vq, vq->vq_ring.desc, head_idx, + buf_list, readable, writable); + + vq->vq_desc_head_idx = idx; + vq->vq_free_cnt -= needed; + + if (vq->vq_free_cnt == 0) { + VQ_RING_ASSERT_CHAIN_TERM(vq); + } else { + VQ_RING_ASSERT_VALID_IDX(vq, idx); + } + + /* + * Update vring_avail control block fields so that other + * side can get buffer using it. + */ + vq_ring_update_avail(vq, head_idx); + } + + VQUEUE_IDLE(vq); + + return status; +} + +/** + * virtqueue_get_buffer - Returns used buffers from VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param len - Length of conumed buffer + * @param idx - index of the buffer + * + * @return - Pointer to used buffer + */ +void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx) +{ + struct vring_used_elem *uep; + void *cookie; + uint16_t used_idx, desc_idx; + + if (!vq || vq->vq_used_cons_idx == vq->vq_ring.used->idx) + return (NULL); + + VQUEUE_BUSY(vq); + + used_idx = vq->vq_used_cons_idx++ & (vq->vq_nentries - 1); + uep = &vq->vq_ring.used->ring[used_idx]; + + atomic_thread_fence(memory_order_seq_cst); + + desc_idx = (uint16_t)uep->id; + if (len) + *len = uep->len; + + vq_ring_free_chain(vq, desc_idx); + + cookie = vq->vq_descx[desc_idx].cookie; + vq->vq_descx[desc_idx].cookie = NULL; + + if (idx) + *idx = used_idx; + VQUEUE_IDLE(vq); + + return cookie; +} + +uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx) +{ + return vq->vq_ring.desc[idx].len; +} + +/** + * virtqueue_free - Frees VirtIO queue resources + * + * @param vq - Pointer to VirtIO queue control block + * + */ +void virtqueue_free(struct virtqueue *vq) +{ + if (vq) { + if (vq->vq_free_cnt != vq->vq_nentries) { + metal_log(METAL_LOG_WARNING, + "%s: freeing non-empty virtqueue\r\n", + vq->vq_name); + } + + metal_free_memory(vq); + } +} + +/** + * virtqueue_get_available_buffer - Returns buffer available for use in the + * VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param avail_idx - Pointer to index used in vring desc table + * @param len - Length of buffer + * + * @return - Pointer to available buffer + */ +void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, + uint32_t *len) +{ + uint16_t head_idx = 0; + void *buffer; + + atomic_thread_fence(memory_order_seq_cst); + if (vq->vq_available_idx == vq->vq_ring.avail->idx) { + return NULL; + } + + VQUEUE_BUSY(vq); + + head_idx = vq->vq_available_idx++ & (vq->vq_nentries - 1); + *avail_idx = vq->vq_ring.avail->ring[head_idx]; + + buffer = virtqueue_phys_to_virt(vq, vq->vq_ring.desc[*avail_idx].addr); + *len = vq->vq_ring.desc[*avail_idx].len; + + VQUEUE_IDLE(vq); + + return buffer; +} + +/** + * virtqueue_add_consumed_buffer - Returns consumed buffer back to VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param head_idx - Index of vring desc containing used buffer + * @param len - Length of buffer + * + * @return - Function status + */ +int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, + uint32_t len) +{ + struct vring_used_elem *used_desc = NULL; + uint16_t used_idx; + + if (head_idx > vq->vq_nentries) { + return ERROR_VRING_NO_BUFF; + } + + VQUEUE_BUSY(vq); + + used_idx = vq->vq_ring.used->idx & (vq->vq_nentries - 1); + used_desc = &vq->vq_ring.used->ring[used_idx]; + used_desc->id = head_idx; + used_desc->len = len; + + atomic_thread_fence(memory_order_seq_cst); + + vq->vq_ring.used->idx++; + + VQUEUE_IDLE(vq); + + return VQUEUE_SUCCESS; +} + +/** + * virtqueue_enable_cb - Enables callback generation + * + * @param vq - Pointer to VirtIO queue control block + * + * @return - Function status + */ +int virtqueue_enable_cb(struct virtqueue *vq) +{ + return vq_ring_enable_interrupt(vq, 0); +} + +/** + * virtqueue_enable_cb - Disables callback generation + * + * @param vq - Pointer to VirtIO queue control block + * + */ +void virtqueue_disable_cb(struct virtqueue *vq) +{ + VQUEUE_BUSY(vq); + + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + vring_used_event(&vq->vq_ring) = + vq->vq_used_cons_idx - vq->vq_nentries - 1; + } else { + vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; + } + + VQUEUE_IDLE(vq); +} + +/** + * virtqueue_kick - Notifies other side that there is buffer available for it. + * + * @param vq - Pointer to VirtIO queue control block + */ +void virtqueue_kick(struct virtqueue *vq) +{ + VQUEUE_BUSY(vq); + + /* Ensure updated avail->idx is visible to host. */ + atomic_thread_fence(memory_order_seq_cst); + + if (vq_ring_must_notify_host(vq)) + vq_ring_notify_host(vq); + + vq->vq_queued_cnt = 0; + + VQUEUE_IDLE(vq); +} + +/** + * virtqueue_dump Dumps important virtqueue fields , use for debugging purposes + * + * @param vq - Pointer to VirtIO queue control block + */ +void virtqueue_dump(struct virtqueue *vq) +{ + if (!vq) + return; + + metal_log(METAL_LOG_DEBUG, + "VQ: %s - size=%d; free=%d; used=%d; queued=%d; " + "desc_head_idx=%d; avail.idx=%d; used_cons_idx=%d; " + "used.idx=%d; avail.flags=0x%x; used.flags=0x%x\r\n", + vq->vq_name, vq->vq_nentries, vq->vq_free_cnt, + virtqueue_nused(vq), vq->vq_queued_cnt, vq->vq_desc_head_idx, + vq->vq_ring.avail->idx, vq->vq_used_cons_idx, + vq->vq_ring.used->idx, vq->vq_ring.avail->flags, + vq->vq_ring.used->flags); +} + +/** + * virtqueue_get_desc_size - Returns vring descriptor size + * + * @param vq - Pointer to VirtIO queue control block + * + * @return - Descriptor length + */ +uint32_t virtqueue_get_desc_size(struct virtqueue *vq) +{ + uint16_t head_idx = 0; + uint16_t avail_idx = 0; + uint32_t len = 0; + + if (vq->vq_available_idx == vq->vq_ring.avail->idx) { + return 0; + } + + VQUEUE_BUSY(vq); + + head_idx = vq->vq_available_idx & (vq->vq_nentries - 1); + avail_idx = vq->vq_ring.avail->ring[head_idx]; + len = vq->vq_ring.desc[avail_idx].len; + + VQUEUE_IDLE(vq); + + return len; +} + +/************************************************************************** + * Helper Functions * + **************************************************************************/ + +/** + * + * vq_ring_add_buffer + * + */ +static uint16_t vq_ring_add_buffer(struct virtqueue *vq, + struct vring_desc *desc, uint16_t head_idx, + struct virtqueue_buf *buf_list, int readable, + int writable) +{ + struct vring_desc *dp; + int i, needed; + uint16_t idx; + + (void)vq; + + needed = readable + writable; + + for (i = 0, idx = head_idx; i < needed; i++, idx = dp->next) { + VQASSERT(vq, idx != VQ_RING_DESC_CHAIN_END, + "premature end of free desc chain"); + + dp = &desc[idx]; + dp->addr = virtqueue_virt_to_phys(vq, buf_list[i].buf); + dp->len = buf_list[i].len; + dp->flags = 0; + + if (i < needed - 1) + dp->flags |= VRING_DESC_F_NEXT; + + /* + * Readable buffers are inserted into vring before the + * writable buffers. + */ + if (i >= readable) + dp->flags |= VRING_DESC_F_WRITE; + } + + return (idx); +} + +/** + * + * vq_ring_free_chain + * + */ +static void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) +{ + struct vring_desc *dp; + struct vq_desc_extra *dxp; + + VQ_RING_ASSERT_VALID_IDX(vq, desc_idx); + dp = &vq->vq_ring.desc[desc_idx]; + dxp = &vq->vq_descx[desc_idx]; + + if (vq->vq_free_cnt == 0) { + VQ_RING_ASSERT_CHAIN_TERM(vq); + } + + vq->vq_free_cnt += dxp->ndescs; + dxp->ndescs--; + + if ((dp->flags & VRING_DESC_F_INDIRECT) == 0) { + while (dp->flags & VRING_DESC_F_NEXT) { + VQ_RING_ASSERT_VALID_IDX(vq, dp->next); + dp = &vq->vq_ring.desc[dp->next]; + dxp->ndescs--; + } + } + + VQASSERT(vq, (dxp->ndescs == 0), + "failed to free entire desc chain, remaining"); + + /* + * We must append the existing free chain, if any, to the end of + * newly freed chain. If the virtqueue was completely used, then + * head would be VQ_RING_DESC_CHAIN_END (ASSERTed above). + */ + dp->next = vq->vq_desc_head_idx; + vq->vq_desc_head_idx = desc_idx; +} + +/** + * + * vq_ring_init + * + */ +static void vq_ring_init(struct virtqueue *vq, void *ring_mem, int alignment) +{ + struct vring *vr; + int i, size; + + size = vq->vq_nentries; + vr = &vq->vq_ring; + + vring_init(vr, size, (unsigned char *)ring_mem, alignment); + + for (i = 0; i < size - 1; i++) + vr->desc[i].next = i + 1; + vr->desc[i].next = VQ_RING_DESC_CHAIN_END; +} + +/** + * + * vq_ring_update_avail + * + */ +static void vq_ring_update_avail(struct virtqueue *vq, uint16_t desc_idx) +{ + uint16_t avail_idx; + + /* + * Place the head of the descriptor chain into the next slot and make + * it usable to the host. The chain is made available now rather than + * deferring to virtqueue_notify() in the hopes that if the host is + * currently running on another CPU, we can keep it processing the new + * descriptor. + */ + avail_idx = vq->vq_ring.avail->idx & (vq->vq_nentries - 1); + vq->vq_ring.avail->ring[avail_idx] = desc_idx; + + atomic_thread_fence(memory_order_seq_cst); + + vq->vq_ring.avail->idx++; + + /* Keep pending count until virtqueue_notify(). */ + vq->vq_queued_cnt++; +} + +/** + * + * vq_ring_enable_interrupt + * + */ +static int vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc) +{ + /* + * Enable interrupts, making sure we get the latest index of + * what's already been consumed. + */ + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx + ndesc; + } else { + vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; + } + + atomic_thread_fence(memory_order_seq_cst); + + /* + * Enough items may have already been consumed to meet our threshold + * since we last checked. Let our caller know so it processes the new + * entries. + */ + if (virtqueue_nused(vq) > ndesc) { + return 1; + } + + return 0; +} + +/** + * + * virtqueue_interrupt + * + */ +void virtqueue_notification(struct virtqueue *vq) +{ + atomic_thread_fence(memory_order_seq_cst); + if (vq->callback) + vq->callback(vq); +} + +/** + * + * vq_ring_must_notify_host + * + */ +static int vq_ring_must_notify_host(struct virtqueue *vq) +{ + uint16_t new_idx, prev_idx, event_idx; + + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + new_idx = vq->vq_ring.avail->idx; + prev_idx = new_idx - vq->vq_queued_cnt; + event_idx = vring_avail_event(&vq->vq_ring); + + return (vring_need_event(event_idx, new_idx, prev_idx) != 0); + } + + return ((vq->vq_ring.used->flags & VRING_USED_F_NO_NOTIFY) == 0); +} + +/** + * + * vq_ring_notify_host + * + */ +static void vq_ring_notify_host(struct virtqueue *vq) +{ + if (vq->notify) + vq->notify(vq); +} + +/** + * + * virtqueue_nused + * + */ +static int virtqueue_nused(struct virtqueue *vq) +{ + uint16_t used_idx, nused; + + used_idx = vq->vq_ring.used->idx; + + nused = (uint16_t)(used_idx - vq->vq_used_cons_idx); + VQASSERT(vq, nused <= vq->vq_nentries, "used more than available"); + + return nused; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/virtual_driver/virt_uart.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/virtual_driver/virt_uart.c new file mode 100644 index 0000000000..d50aeac63b --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/virtual_driver/virt_uart.c @@ -0,0 +1,126 @@ +/** + ****************************************************************************** + * @file virt_uart.c + * @author MCD Application Team + * @brief UART HAL module driver. + * This file provides firmware functions to manage an rpmsg endpoint + * from user application + * + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + The VIRTUAL UART driver can be used as follows: + (#) Initialize the Virtual UART by calling the VIRT_UART_Init() API. + (++) create an endpoint. listener on the OpenAMP-rpmsg channel is now enabled. + Receive data is now possible if user registers a callback to this VIRTUAL UART instance + by calling in providing a callback function when a message is received from + remote processor (VIRT_UART_read_cb) + OpenAMP MW deals with memory allocation/free and signal events + (#) Transmit data on the created rpmsg channel by calling the VIRT_UART_Transmit() + (#) Receive data in calling VIRT_UART_RegisterCallback to register user callback + + + @endverbatim + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "virt_uart.h" +#include "metal/utilities.h" + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* this string will be sent to remote processor */ +#define RPMSG_SERVICE_NAME "rpmsg-tty-channel" + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +static int VIRT_UART_read_cb(struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, void *priv) +{ + VIRT_UART_HandleTypeDef *huart = metal_container_of(ept, VIRT_UART_HandleTypeDef, ept); + (void)src; + + huart->pRxBuffPtr = data; + huart->RxXferSize = len; + if (huart->RxCpltCallback != NULL) { + huart->RxCpltCallback(huart); + } + + return 0; +} + +VIRT_UART_StatusTypeDef VIRT_UART_Init(VIRT_UART_HandleTypeDef *huart) +{ + + int status; + + /* Create a endpoint for rmpsg communication */ + + status = OPENAMP_create_endpoint(&huart->ept, RPMSG_SERVICE_NAME, RPMSG_ADDR_ANY, + VIRT_UART_read_cb, NULL); + + if(status < 0) { + return VIRT_UART_ERROR; + } + + return VIRT_UART_OK; +} + +VIRT_UART_StatusTypeDef VIRT_UART_DeInit (VIRT_UART_HandleTypeDef *huart) +{ + OPENAMP_destroy_ept(&huart->ept); + + return VIRT_UART_OK; +} + +VIRT_UART_StatusTypeDef VIRT_UART_RegisterCallback(VIRT_UART_HandleTypeDef *huart, + VIRT_UART_CallbackIDTypeDef CallbackID, + void (* pCallback)(VIRT_UART_HandleTypeDef *_huart)) +{ + VIRT_UART_StatusTypeDef status = VIRT_UART_OK; + + switch (CallbackID) + { + case VIRT_UART_RXCPLT_CB_ID : + huart->RxCpltCallback = pCallback; + break; + + default : + /* Return error status */ + status = VIRT_UART_ERROR; + break; + } + return status; +} + +VIRT_UART_StatusTypeDef VIRT_UART_Transmit(VIRT_UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + int res; + + if (Size > (RPMSG_BUFFER_SIZE-16)) + return VIRT_UART_ERROR; + + res = OPENAMP_send(&huart->ept, pData, Size); + if (res <0) { + return VIRT_UART_ERROR; + } + + return VIRT_UART_OK; +} diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/virtual_driver/virt_uart.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/virtual_driver/virt_uart.h new file mode 100644 index 0000000000..c368bfdbe9 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/OpenAMP/virtual_driver/virt_uart.h @@ -0,0 +1,76 @@ +/** + ****************************************************************************** + * @file virt_uart.h + * @author MCD Application Team + * @brief Header file of UART VIRT module. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * 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 __VIRT_UART_H +#define __VIRT_UART_H + + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "openamp.h" + +/* Exported structures --------------------------------------------------------*/ +typedef struct __VIRT_UART_HandleTypeDef +{ + struct rpmsg_endpoint ept; /*!< rpmsg endpoint */ + struct rpmsg_virtio_device *rvdev; /*< pointer to the rpmsg virtio device */ + uint8_t *pRxBuffPtr; /*!< Pointer to VIRTUAL UART Rx transfer Buffer */ + uint16_t RxXferSize; /*!< VIRTUAL UART Rx Transfer size */ + void (* RxCpltCallback)( struct __VIRT_UART_HandleTypeDef * hppp); /*!< RX CPLT callback */ +}VIRT_UART_HandleTypeDef; + + +typedef enum +{ + VIRT_UART_OK = 0x00U, + VIRT_UART_ERROR = 0x01U, + VIRT_UART_BUSY = 0x02U, + VIRT_UART_TIMEOUT = 0x03U +} VIRT_UART_StatusTypeDef; + + +typedef enum +{ + VIRT_UART_RXCPLT_CB_ID = 0x00U, /*!< PPP event 1 callback ID */ +}VIRT_UART_CallbackIDTypeDef; + + +/* Exported functions --------------------------------------------------------*/ +/* Initialization and de-initialization functions ****************************/ +VIRT_UART_StatusTypeDef VIRT_UART_Init(VIRT_UART_HandleTypeDef *huart); +VIRT_UART_StatusTypeDef VIRT_UART_DeInit (VIRT_UART_HandleTypeDef *huart); +VIRT_UART_StatusTypeDef VIRT_UART_RegisterCallback(VIRT_UART_HandleTypeDef *huart, + VIRT_UART_CallbackIDTypeDef CallbackID, + void (* pCallback)(VIRT_UART_HandleTypeDef *_huart)); + +/* IO operation functions *****************************************************/ +VIRT_UART_StatusTypeDef VIRT_UART_Transmit(VIRT_UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VIRT_UART_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/bsp/stm32/stm32mp157a-st-ev1/project.ewp b/bsp/stm32/stm32mp157a-st-ev1/project.ewp index 6b140f0c65..2bb85bc33c 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/project.ewp +++ b/bsp/stm32/stm32mp157a-st-ev1/project.ewp @@ -226,8 +226,12 @@ <state />
<state>RT_USING_DLIBC</state>
<state>CORE_CM4</state>
+ <state>NO_ATOMIC_64_SUPPORT</state>
+ <state>METAL_INTERNAL</state>
+ <state>METAL_MAX_DEVICE_REGIONS=2</state>
+ <state>VIRTIO_SLAVE_ONLY</state>
<state>STM32MP157Axx</state>
- <state>USE_HAL_DRIVER</state>
+ <state>__LOG_TRACE_IO_</state>
<state>USE_HAL_DRIVER</state>
</option>
<option>
@@ -679,7 +683,7 @@ </option>
<option>
<name>OOCObjCopyEnable</name>
- <state>1</state>
+ <state>0</state>
</option>
</data>
</settings>
@@ -1300,8 +1304,12 @@ <state />
<state>RT_USING_DLIBC</state>
<state>CORE_CM4</state>
+ <state>NO_ATOMIC_64_SUPPORT</state>
+ <state>METAL_INTERNAL</state>
+ <state>METAL_MAX_DEVICE_REGIONS=2</state>
+ <state>VIRTIO_SLAVE_ONLY</state>
<state>STM32MP157Axx</state>
- <state>USE_HAL_DRIVER</state>
+ <state>__LOG_TRACE_IO_</state>
<state>USE_HAL_DRIVER</state>
</option>
<option>
@@ -2178,12 +2186,6 @@ <name>$PROJ_DIR$\..\..\..\components\drivers\misc\pin.c</name>
</file>
<file>
- <name>$PROJ_DIR$\..\..\..\components\drivers\misc\adc.c</name>
- </file>
- <file>
- <name>$PROJ_DIR$\..\..\..\components\drivers\misc\dac.c</name>
- </file>
- <file>
<name>$PROJ_DIR$\..\..\..\components\drivers\serial\serial.c</name>
</file>
<file>
@@ -2247,22 +2249,16 @@ <group>
<name>Drivers</name>
<file>
- <name>$PROJ_DIR$\board\board.c</name>
- </file>
- <file>
<name>$PROJ_DIR$\board\CubeMX_Config\Common\System\system_stm32mp1xx.c</name>
</file>
<file>
- <name>$PROJ_DIR$\board\CubeMX_Config\CM4\Src\stm32mp1xx_hal_msp.c</name>
- </file>
- <file>
- <name>$PROJ_DIR$\board\ports\drv_hard_i2c.c</name>
+ <name>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Source\Templates\iar\startup_stm32mp15xx.s</name>
</file>
<file>
- <name>$PROJ_DIR$\board\ports\stpmic.c</name>
+ <name>$PROJ_DIR$\board\CubeMX_Config\CM4\Src\stm32mp1xx_hal_msp.c</name>
</file>
<file>
- <name>$PROJ_DIR$\..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Source\Templates\iar\startup_stm32mp15xx.s</name>
+ <name>$PROJ_DIR$\board\board.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\libraries\HAL_Drivers\drv_gpio.c</name>
@@ -2271,12 +2267,6 @@ <name>$PROJ_DIR$\..\libraries\HAL_Drivers\drv_usart.c</name>
</file>
<file>
- <name>$PROJ_DIR$\..\libraries\HAL_Drivers\drv_adc.c</name>
- </file>
- <file>
- <name>$PROJ_DIR$\..\libraries\HAL_Drivers\drv_dac.c</name>
- </file>
- <file>
<name>$PROJ_DIR$\..\libraries\HAL_Drivers\drv_common.c</name>
</file>
</group>
diff --git a/bsp/stm32/stm32mp157a-st-ev1/project.uvprojx b/bsp/stm32/stm32mp157a-st-ev1/project.uvprojx index da44ecf507..850fba2c45 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/project.uvprojx +++ b/bsp/stm32/stm32mp157a-st-ev1/project.uvprojx @@ -323,7 +323,7 @@ <uThumb>0</uThumb> <uSurpInc>0</uSurpInc> <uC99>1</uC99> - <uGnu>1</uGnu> + <uGnu>0</uGnu> <useXO>0</useXO> <v6Lang>1</v6Lang> <v6LangP>1</v6LangP> @@ -334,7 +334,7 @@ <v6Rtti>0</v6Rtti> <VariousControls> <MiscControls /> - <Define>CORE_CM4, USE_HAL_DRIVER, STM32MP157Axx, RT_USING_ARM_LIBC</Define> + <Define>CORE_CM4, __LOG_TRACE_IO_, METAL_MAX_DEVICE_REGIONS=2, VIRTIO_SLAVE_ONLY, NO_ATOMIC_64_SUPPORT, STM32MP157Axx, METAL_INTERNAL, USE_HAL_DRIVER, RT_USING_ARM_LIBC</Define> <Undefine /> <IncludePath>applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\CubeMX_Config\CM4\Inc;board\ports;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\armlibc;..\..\..\components\libc\compilers\common;..\libraries\STM32MPxx_HAL\STM32MP1xx_HAL_Driver\Inc;..\libraries\STM32MPxx_HAL\CMSIS\Device\ST\STM32MP1xx\Include;..\libraries\STM32MPxx_HAL\CMSIS\Core\Include;..\libraries\STM32MPxx_HAL\CMSIS\Include</IncludePath> </VariousControls> diff --git a/bsp/stm32/stm32mp157a-st-ev1/rtconfig.h b/bsp/stm32/stm32mp157a-st-ev1/rtconfig.h index dfe6797581..65772b7eac 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/rtconfig.h +++ b/bsp/stm32/stm32mp157a-st-ev1/rtconfig.h @@ -152,12 +152,6 @@ /* samples: kernel and components samples */ - -/* Privated Packages of RealThread */ - - -/* Network Utilities */ - #define SOC_FAMILY_STM32 #define SOC_SERIES_STM32MP1 diff --git a/bsp/stm32/stm32mp157a-st-ev1/template.ewp b/bsp/stm32/stm32mp157a-st-ev1/template.ewp index 6d6c615d16..300f2db945 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/template.ewp +++ b/bsp/stm32/stm32mp157a-st-ev1/template.ewp @@ -657,7 +657,7 @@ </option>
<option>
<name>OOCObjCopyEnable</name>
- <state>1</state>
+ <state>0</state>
</option>
</data>
</settings>
diff --git a/bsp/stm32/stm32mp157a-st-ev1/template.uvprojx b/bsp/stm32/stm32mp157a-st-ev1/template.uvprojx index 67a2556f75..fc88195dc1 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/template.uvprojx +++ b/bsp/stm32/stm32mp157a-st-ev1/template.uvprojx @@ -326,7 +326,7 @@ <uThumb>0</uThumb> <uSurpInc>0</uSurpInc> <uC99>1</uC99> - <uGnu>1</uGnu> + <uGnu>0</uGnu> <useXO>0</useXO> <v6Lang>1</v6Lang> <v6LangP>1</v6LangP> diff --git a/bsp/stm32/stm32mp157a-st-ev1/tools/rt-thread-shell.py b/bsp/stm32/stm32mp157a-st-ev1/tools/rt-thread-shell.py new file mode 100644 index 0000000000..b245d17c69 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/tools/rt-thread-shell.py @@ -0,0 +1,26 @@ +import os +import time + +def main(): + if (os.path.exists("/tmp/RT-Thread-STM32MP1_CM4.elf")): + os.system("mv /tmp/RT-Thread-STM32MP1_CM4.elf /lib/firmware/") + os.system("echo stop > /sys/class/remoteproc/remoteproc0/state") + os.system("echo RT-Thread-STM32MP1_CM4.elf > /sys/class/remoteproc/remoteproc0/firmware") + os.system("echo start > /sys/class/remoteproc/remoteproc0/state") + os.system("stty -onlcr -echo -F /dev/ttyRPMSG0") + os.system("cat /dev/ttyRPMSG0 &") + time.sleep(1) + print("\nYou can input \"exit\" to quit rt-thread shell!\n") + os.system("echo version >/dev/ttyRPMSG0") + + while True: + a = input() + if a == "exit": + os.system("echo stop > /sys/class/remoteproc/remoteproc0/state") + return + + os.system("echo {0} >/dev/ttyRPMSG0".format(a)) + + +if __name__ == "__main__": + main() diff --git a/bsp/thead-smart/.config b/bsp/thead-smart/.config new file mode 100644 index 0000000000..d0dbd85a46 --- /dev/null +++ b/bsp/thead-smart/.config @@ -0,0 +1,417 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=512 +# CONFIG_RT_USING_TIMER_SOFT is not set +# CONFIG_RT_DEBUG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40003 + +# +# RT-Thread CPU arch and features +# +# CONFIG_ARCH_CSKY is not set + +# +# risc-v arch +# +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_RISCV_32=y +# CONFIG_ARCH_RISCV_64 is not set +CONFIG_ARCH_RISCV_FPU=y +CONFIG_ARCH_RISCV_FPU_S=y +# CONFIG_ARCH_RISCV_FPU_D is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=1 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=2048 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +CONFIG_FINSH_USING_MSH_ONLY=y +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +# CONFIG_RT_USING_PTHREADS is not set +# CONFIG_RT_LIBC_USING_TIME is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOTHUB is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set + +# +# multimedia packages +# +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_URLENCODE is not set + +# +# system packages +# +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_CMSIS is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_NUCLEI_SDK is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set + +# +# miscellaneous packages +# +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_UKAL is not set +CONFIG_SOC_THEAD_SMART=y +CONFIG_RT_USING_UART1=y diff --git a/bsp/thead-smart/Kconfig b/bsp/thead-smart/Kconfig new file mode 100644 index 0000000000..b2fde84dc0 --- /dev/null +++ b/bsp/thead-smart/Kconfig @@ -0,0 +1,36 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../.." + +# you can change the RTT_ROOT default "../.." to your rtthread_root, +# example : default "F:/git_repositories/rt-thread" + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" + +config SOC_THEAD_SMART + bool + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +if RT_USING_SERIAL + + config RT_USING_UART1 + bool "Using uart1" + default y + +endif diff --git a/bsp/thead-smart/README.md b/bsp/thead-smart/README.md new file mode 100644 index 0000000000..990818a606 --- /dev/null +++ b/bsp/thead-smart/README.md @@ -0,0 +1,45 @@ +# T-HEAD SMART-EVB Introduction +SMART-EVB is a development board provided by T-HEAD, based on FPGA to provide implementation, integrating T-HEAD's RISC-V CPU (eg. E902/E906/C906) and C-SKY CPU (eg. E805/E804/E803/E802 ), integrates basic peripheral resources such as GPIO/TIMER/UART/RAM. + +##The main resources on board are as follows: +1. SMART-EVB for E906/E906F/E906FD +| res | description | +| -- | -- | +|ISA | RISCV | +|CPU | E906 | +|FREQ| 20MHz | +|SRAM| 768KB | + + +2. SMART-EVB for E804/E804F/E804D +| res | description | +| -- | -- | +|ISA | C-SKY | +|CPU | E804 | +|FREQ| 20MHz | +|SRAM| 768KB | + + +# Compile T-HEAD BSP +SMART-EVB BSP supports GCC compiler, the version information is: +1. SMART-EVB for E906/E906F/E906FD +| IDE/Compiler| version| +| - | - | +| GCC | gcc version 8.4.0 (C-SKY RISCV Tools V1.9.6 B20200616) | + +# run smart-evb bsp +1. Connect JTAG +2. Connect the serial port +3. riscv64-unknown-elf-gdb rtthread-e906f.elf + +run log as follows: +``` + \ | / +- RT - Thread Operating System + / | \ 4.0.3 build Sep 2 2020 + 2006 - 2020 Copyright by rt-thread team +msh > +``` + + + diff --git a/bsp/thead-smart/SConscript b/bsp/thead-smart/SConscript new file mode 100644 index 0000000000..744d8d7821 --- /dev/null +++ b/bsp/thead-smart/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/thead-smart/SConstruct b/bsp/thead-smart/SConstruct new file mode 100644 index 0000000000..9a283c2884 --- /dev/null +++ b/bsp/thead-smart/SConstruct @@ -0,0 +1,33 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +from building import * + +TARGET = 'rtthread-' + rtconfig.CPU + '.' + rtconfig.TARGET_EXT + +env = Environment(tools = ['mingw'], +AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, +CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, +CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, +AR = rtconfig.AR, ARFLAGS = '-rc', +LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +# add --start-group and --end-group for GNU GCC +env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS -Wl,--start-group $_LIBFLAGS -Wl,--end-group' + +Export('RTT_ROOT') +Export('rtconfig') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/thead-smart/applications/SConscript b/bsp/thead-smart/applications/SConscript new file mode 100644 index 0000000000..b95023ca41 --- /dev/null +++ b/bsp/thead-smart/applications/SConscript @@ -0,0 +1,13 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = GetCurrentDir() + +CCFLAGS = ' -c -ffunction-sections' + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, CCFLAGS=CCFLAGS) + +Return('group') diff --git a/bsp/thead-smart/applications/main.c b/bsp/thead-smart/applications/main.c new file mode 100644 index 0000000000..61046f4a4b --- /dev/null +++ b/bsp/thead-smart/applications/main.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen first version + */ + +#include <rtthread.h> + +int main(void) +{ + + return 0; +} + +/*@}*/ diff --git a/bsp/thead-smart/drivers/SConscript b/bsp/thead-smart/drivers/SConscript new file mode 100644 index 0000000000..96f82751bb --- /dev/null +++ b/bsp/thead-smart/drivers/SConscript @@ -0,0 +1,13 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() + +# add the general drivers. +src = Glob("*.c") + Glob("*.cpp") + Glob("*.S") + +CPPPATH = [cwd] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/thead-smart/drivers/board.c b/bsp/thead-smart/drivers/board.c new file mode 100644 index 0000000000..386d40d3a5 --- /dev/null +++ b/bsp/thead-smart/drivers/board.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen add T-HEAD header file csi_core.h + */ + +#include <rthw.h> +#include <rtthread.h> + +#include "board.h" +#include "csi_core.h" +#include "drv_usart.h" + +extern int __bss_end__; +#define SYS_HEAP_BEGIN (&__bss_end__) + +#include "core_rv32.h" + + +extern usart_handle_t console_handle; +extern void ioreuse_initial(void); + + +/** + * This function will initial smartl-evb(e906) board. + */ +void rt_hw_board_init(void) +{ +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + /* initialize hardware usart */ + rt_hw_usart_init(); + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef RT_USING_HEAP + rt_system_heap_init((void *)SYS_HEAP_BEGIN, (void *)E906FD_IRAM_END); +#endif +} + +/*@}*/ diff --git a/bsp/thead-smart/drivers/board.h b/bsp/thead-smart/drivers/board.h new file mode 100644 index 0000000000..786246bd9a --- /dev/null +++ b/bsp/thead-smart/drivers/board.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen add E906 ram size + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#define APB_DEFAULT_FREQ 20000000 /* Hz */ +#define E906FD_IRAM_SIZE 128 +#define E906FD_IRAM_END (0x20000000 + E906FD_IRAM_SIZE * 1024) + +#endif /* __BOARD_H__ */ diff --git a/bsp/thead-smart/drivers/board_uart.c b/bsp/thead-smart/drivers/board_uart.c new file mode 100644 index 0000000000..d4f857f0bb --- /dev/null +++ b/bsp/thead-smart/drivers/board_uart.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen first implementation + */ + +#include <rtthread.h> + +#ifdef RT_USING_CONSOLE + +#include <rthw.h> +#include <rtdevice.h> + +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <stdbool.h> + +#include "board.h" +#include "soc.h" +#include "ck_usart.h" +#include "drv_usart.h" +#include "pin_name.h" + + + +__attribute__((isr)) void ck_usart0_irqhandler(void); + +struct +{ + uint32_t base; + uint32_t irq; + void *handler; +} +const sg_usart_config[CONFIG_USART_NUM] = +{ + {CSKY_UART_BASE, UART_IRQn, ck_usart0_irqhandler}, +}; + + +int32_t target_usart_init(int32_t idx, uint32_t *base, uint32_t *irq, void **handler) +{ + if (idx >= CONFIG_USART_NUM) + { + return -1; + } + + if (base != NULL) + { + *base = sg_usart_config[idx].base; + } + + if (irq != NULL) + { + *irq = sg_usart_config[idx].irq; + } + + if (handler != NULL) + { + *handler = sg_usart_config[idx].handler; + } + + return idx; +} + + +#ifdef RT_USING_UART1 +#define UART_TXD1 PA10_TXD1_PWM1_XX_SIROUT1 +#define UART_RXD1 PA11_RXD1_PWM2_XX_SIRIN1 + +static usart_handle_t uart1_handle; +static struct rt_serial_device serial1; + +__attribute__((isr)) void ck_usart0_irqhandler(void) +{ + rt_hw_serial_isr(&serial1,RT_SERIAL_EVENT_RX_IND); +} +#endif + +/* + * UART interface + */ +static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + int ret; + usart_handle_t uart; + + uint32_t bauds; + usart_mode_e mode; + usart_parity_e parity; + usart_stop_bits_e stopbits; + usart_data_bits_e databits; + + RT_ASSERT(serial != RT_NULL); + uart = (usart_handle_t)serial->parent.user_data; + RT_ASSERT(uart != RT_NULL); + + /* set baudrate parity...*/ + bauds = cfg->baud_rate; + mode = USART_MODE_ASYNCHRONOUS; + + if (cfg->parity == PARITY_EVEN) + parity = USART_PARITY_EVEN; + else if (cfg->parity == PARITY_ODD) + parity = USART_PARITY_ODD; + else + parity = USART_PARITY_NONE; + + stopbits = USART_STOP_BITS_1 ; + databits = USART_DATA_BITS_8; + + ret = csi_usart_config(uart, bauds, USART_MODE_ASYNCHRONOUS, parity, stopbits, databits); + + if (ret < 0) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + usart_handle_t uart; + + RT_ASSERT(serial != RT_NULL); + uart = (usart_handle_t)serial->parent.user_data; + RT_ASSERT(uart != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* Disable the UART Interrupt */ + ck_usart_clr_int_flag(uart,IER_RDA_INT_ENABLE); + break; + + case RT_DEVICE_CTRL_SET_INT: + /* Enable the UART Interrupt */ + ck_usart_set_int_flag(uart,IER_RDA_INT_ENABLE); + break; + } + + return (RT_EOK); +} + +static int uart_putc(struct rt_serial_device *serial, char c) +{ + usart_handle_t uart; + + RT_ASSERT(serial != RT_NULL); + uart = (usart_handle_t)serial->parent.user_data; + RT_ASSERT(uart != RT_NULL); + csi_usart_putchar(uart,c); + + return (1); +} + +static int uart_getc(struct rt_serial_device *serial) +{ + int ch; + usart_handle_t uart; + + RT_ASSERT(serial != RT_NULL); + uart = (usart_handle_t)serial->parent.user_data; + RT_ASSERT(uart != RT_NULL); + + + ch = csi_uart_getchar(uart); + + return ch; +} + +const struct rt_uart_ops _uart_ops = +{ + uart_configure, + uart_control, + uart_putc, + uart_getc, +}; + + +int rt_hw_usart_init(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef RT_USING_UART1 + serial1.ops = & _uart_ops; + serial1.config = config; + serial1.config.bufsz = 2048; + serial1.config.baud_rate = 115200; + + uart1_handle = csi_usart_initialize(0, NULL); + + rt_hw_serial_register(&serial1, + "uart1", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart1_handle); +#endif + + return 0; +} +INIT_BOARD_EXPORT(rt_hw_usart_init); +#endif diff --git a/bsp/thead-smart/drivers/ck_irq.c b/bsp/thead-smart/drivers/ck_irq.c new file mode 100644 index 0000000000..8863ec7580 --- /dev/null +++ b/bsp/thead-smart/drivers/ck_irq.c @@ -0,0 +1,88 @@ + +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen CSI Source File for IRQ Driver + */ + +#include <stdint.h> +#include <soc.h> +#include <csi_core.h> +#include <csi_config.h> + +extern void Default_Handler(void); +extern void (*g_irqvector[])(void); +extern void (*g_nmivector)(void); + +/** + \brief enable irq. + \param[in] irq_num Number of IRQ. + \return None. +*/ +void drv_irq_enable(uint32_t irq_num) +{ + if (NMI_EXPn != irq_num) + { + #ifdef CONFIG_SYSTEM_SECURE + csi_vic_enable_sirq(irq_num); + #else + csi_vic_enable_irq(irq_num); + #endif + } +} + +/** + \brief disable irq. + \param[in] irq_num Number of IRQ. + \return None. +*/ +void drv_irq_disable(uint32_t irq_num) +{ + if (NMI_EXPn != irq_num) + { + #ifdef CONFIG_SYSTEM_SECURE + csi_vic_disable_sirq(irq_num); + #else + csi_vic_disable_irq(irq_num); + #endif + } +} + +/** + \brief register irq handler. + \param[in] irq_num Number of IRQ. + \param[in] irq_handler IRQ Handler. + \return None. +*/ +void drv_irq_register(uint32_t irq_num, void *irq_handler) +{ + if (NMI_EXPn != irq_num) + { + g_irqvector[irq_num] = irq_handler; + } + else + { + g_nmivector = irq_handler; + } +} + +/** + \brief unregister irq handler. + \param[in] irq_num Number of IRQ. + \return None. +*/ +void drv_irq_unregister(uint32_t irq_num) +{ + if (NMI_EXPn != irq_num) + { + g_irqvector[irq_num] = (void *)Default_Handler; + } + else + { + g_nmivector = (void *)Default_Handler; + } +} diff --git a/bsp/thead-smart/drivers/ck_usart.c b/bsp/thead-smart/drivers/ck_usart.c new file mode 100644 index 0000000000..bedec214ab --- /dev/null +++ b/bsp/thead-smart/drivers/ck_usart.c @@ -0,0 +1,1141 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen CSI Source File for usart Driver + */ + +#include <csi_config.h> +#include <stdbool.h> +#include <string.h> +#include <drv_irq.h> +#include <drv_usart.h> +#include <ck_usart.h> +#include <soc.h> +#include <csi_core.h> + +#define ERR_USART(errno) (CSI_DRV_ERRNO_USART_BASE | errno) + +/* + * setting config may be accessed when the USART is not + * busy(USR[0]=0) and the DLAB bit(LCR[7]) is set. + */ + +#define WAIT_USART_IDLE(addr)\ + do { \ + int32_t timecount = 0; \ + while ((addr->USR & USR_UART_BUSY) && (timecount < UART_BUSY_TIMEOUT)) {\ + timecount++;\ + }\ + if (timecount >= UART_BUSY_TIMEOUT) {\ + return ERR_USART(DRV_ERROR_TIMEOUT);\ + } \ + } while(0) + +#define USART_NULL_PARAM_CHK(para) HANDLE_PARAM_CHK(para, ERR_USART(DRV_ERROR_PARAMETER)) + +typedef struct +{ + uint32_t base; + uint32_t irq; + usart_event_cb_t cb_event; ///< Event callback + uint32_t rx_total_num; + uint32_t tx_total_num; + uint8_t *rx_buf; + uint8_t *tx_buf; + volatile uint32_t rx_cnt; + volatile uint32_t tx_cnt; + volatile uint32_t tx_busy; + volatile uint32_t rx_busy; + uint32_t last_tx_num; + uint32_t last_rx_num; + int32_t idx; +} ck_usart_priv_t; + +extern int32_t target_usart_init(int32_t idx, uint32_t *base, uint32_t *irq, void **handler); + +static ck_usart_priv_t usart_instance[CONFIG_USART_NUM]; + +static const usart_capabilities_t usart_capabilities = +{ + .asynchronous = 1, /* supports USART (Asynchronous) mode */ + .synchronous_master = 0, /* supports Synchronous Master mode */ + .synchronous_slave = 0, /* supports Synchronous Slave mode */ + .single_wire = 0, /* supports USART Single-wire mode */ + .event_tx_complete = 1, /* Transmit completed event */ + .event_rx_timeout = 0, /* Signal receive character timeout event */ +}; + +/** + \brief set the bautrate of usart. + \param[in] addr usart base to operate. + \return error code +*/ +int32_t csi_usart_config_baudrate(usart_handle_t handle, uint32_t baud) +{ + USART_NULL_PARAM_CHK(handle); + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + + WAIT_USART_IDLE(addr); + + /* baudrate=(seriak clock freq)/(16*divisor); algorithm :rounding*/ + uint32_t divisor = ((drv_get_usart_freq(usart_priv->idx) * 10) / baud) >> 4; + + if ((divisor % 10) >= 5) + { + divisor = (divisor / 10) + 1; + } else + { + divisor = divisor / 10; + } + + addr->LCR |= LCR_SET_DLAB; + /* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/ + addr->DLL = divisor & 0xff; + addr->DLH = (divisor >> 8) & 0xff; + /* + * The DLAB must be cleared after the baudrate is setted + * to access other registers. + */ + addr->LCR &= (~LCR_SET_DLAB); + + return 0; +} + +/** + \brief config usart mode. + \param[in] handle usart handle to operate. + \param[in] mode \ref usart_mode_e + \return error code +*/ +int32_t csi_usart_config_mode(usart_handle_t handle, usart_mode_e mode) +{ + USART_NULL_PARAM_CHK(handle); + + if (mode == USART_MODE_ASYNCHRONOUS) + { + return 0; + } + + return ERR_USART(USART_ERROR_MODE); +} + +/** + \brief config usart parity. + \param[in] handle usart handle to operate. + \param[in] parity \ref usart_parity_e + \return error code +*/ +int32_t csi_usart_config_parity(usart_handle_t handle, usart_parity_e parity) +{ + USART_NULL_PARAM_CHK(handle); + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + WAIT_USART_IDLE(addr); + + switch (parity) + { + case USART_PARITY_NONE: + /*CLear the PEN bit(LCR[3]) to disable parity.*/ + addr->LCR &= (~LCR_PARITY_ENABLE); + break; + + case USART_PARITY_ODD: + /* Set PEN and clear EPS(LCR[4]) to set the ODD parity. */ + addr->LCR |= LCR_PARITY_ENABLE; + addr->LCR &= LCR_PARITY_ODD; + break; + + case USART_PARITY_EVEN: + /* Set PEN and EPS(LCR[4]) to set the EVEN parity.*/ + addr->LCR |= LCR_PARITY_ENABLE; + addr->LCR |= LCR_PARITY_EVEN; + break; + + default: + return ERR_USART(USART_ERROR_PARITY); + } + + return 0; +} + +/** + \brief config usart stop bit number. + \param[in] handle usart handle to operate. + \param[in] stopbits \ref usart_stop_bits_e + \return error code +*/ +int32_t csi_usart_config_stopbits(usart_handle_t handle, usart_stop_bits_e stopbit) +{ + USART_NULL_PARAM_CHK(handle); + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + WAIT_USART_IDLE(addr); + + switch (stopbit) + { + case USART_STOP_BITS_1: + /* Clear the STOP bit to set 1 stop bit*/ + addr->LCR &= LCR_STOP_BIT1; + break; + + case USART_STOP_BITS_2: + /* + * If the STOP bit is set "1",we'd gotten 1.5 stop + * bits when DLS(LCR[1:0]) is zero, else 2 stop bits. + */ + addr->LCR |= LCR_STOP_BIT2; + break; + + default: + return ERR_USART(USART_ERROR_STOP_BITS); + } + + return 0; +} + +/** + \brief config usart data length. + \param[in] handle usart handle to operate. + \param[in] databits \ref usart_data_bits_e + \return error code +*/ +int32_t csi_usart_config_databits(usart_handle_t handle, usart_data_bits_e databits) +{ + USART_NULL_PARAM_CHK(handle); + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + WAIT_USART_IDLE(addr); + /* The word size decides by the DLS bits(LCR[1:0]), and the + * corresponding relationship between them is: + * DLS word size + * 00 -- 5 bits + * 01 -- 6 bits + * 10 -- 7 bits + * 11 -- 8 bits + */ + + switch (databits) + { + case USART_DATA_BITS_5: + addr->LCR &= LCR_WORD_SIZE_5; + break; + + case USART_DATA_BITS_6: + addr->LCR &= 0xfd; + addr->LCR |= LCR_WORD_SIZE_6; + break; + + case USART_DATA_BITS_7: + addr->LCR &= 0xfe; + addr->LCR |= LCR_WORD_SIZE_7; + break; + + case USART_DATA_BITS_8: + addr->LCR |= LCR_WORD_SIZE_8; + break; + + default: + return ERR_USART(USART_ERROR_DATA_BITS); + } + + return 0; +} + + +int32_t ck_usart_set_int_flag(usart_handle_t handle,uint32_t flag) +{ + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + addr->IER |= flag; + + return 0; +} + +int32_t ck_usart_clr_int_flag(usart_handle_t handle,uint32_t flag) +{ + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + addr->IER &= ~flag; + + return 0; +} + + +/** + \brief get character in query mode. + \param[in] instance usart instance to operate. + \param[in] the pointer to the recieve charater. + \return error code +*/ +int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch) +{ + USART_NULL_PARAM_CHK(handle); + USART_NULL_PARAM_CHK(ch); + + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + while (!(addr->LSR & LSR_DATA_READY)); + + *ch = addr->RBR; + + return 0; +} + + +/** + \brief get character in query mode. + \param[in] instance usart instance to operate. + \param[in] the pointer to the recieve charater. + \return error code +*/ +int csi_uart_getchar(usart_handle_t handle) +{ + volatile int ch; + USART_NULL_PARAM_CHK(handle); + + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + ch = -1; + + if (addr->LSR & LSR_DATA_READY) + { + ch = addr->RBR & 0xff; + } + + return ch; +} + + +/** + \brief transmit character in query mode. + \param[in] instance usart instance to operate. + \param[in] ch the input charater + \return error code +*/ +int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch) +{ + USART_NULL_PARAM_CHK(handle); + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + uint32_t timecount = 0; + + while ((!(addr->LSR & DW_LSR_TRANS_EMPTY))) + { + timecount++; + + if (timecount >= UART_BUSY_TIMEOUT) + { + return ERR_USART(DRV_ERROR_TIMEOUT); + } + } + + addr->THR = ch; + + return 0; + +} + +/** + \brief interrupt service function for transmitter holding register empty. + \param[in] usart_priv usart private to operate. +*/ +void ck_usart_intr_threshold_empty(int32_t idx, ck_usart_priv_t *usart_priv) +{ + if (usart_priv->tx_total_num == 0) + { + return; + } + + volatile int i = 500; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + if (usart_priv->tx_cnt >= usart_priv->tx_total_num) + { + addr->IER &= (~IER_THRE_INT_ENABLE); + usart_priv->last_tx_num = usart_priv->tx_total_num; + + /* fix hardware bug */ + while (addr->USR & USR_UART_BUSY); + + i = 500; + + while (i--); + + usart_priv->tx_cnt = 0; + usart_priv->tx_busy = 0; + usart_priv->tx_buf = NULL; + usart_priv->tx_total_num = 0; + + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_SEND_COMPLETE); + } + } else + { + /* fix hardware bug */ + while (addr->USR & USR_UART_BUSY); + + i = 500; + + while (i--); + + addr->THR = *((uint8_t *)usart_priv->tx_buf); + usart_priv->tx_cnt++; + usart_priv->tx_buf++; + } +} + +/** + \brief interrupt service function for receiver data available. + \param[in] usart_priv usart private to operate. +*/ +static void ck_usart_intr_recv_data(int32_t idx, ck_usart_priv_t *usart_priv) +{ + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + uint8_t data = addr->RBR; + + *((uint8_t *)usart_priv->rx_buf) = data; + usart_priv->rx_cnt++; + usart_priv->rx_buf++; + + if (usart_priv->rx_cnt >= usart_priv->rx_total_num) + { + usart_priv->last_rx_num = usart_priv->rx_total_num; + usart_priv->rx_cnt = 0; + usart_priv->rx_buf = NULL; + usart_priv->rx_busy = 0; + usart_priv->rx_total_num = 0; + + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_RECEIVE_COMPLETE); + } + } + +} + +/** + \brief interrupt service function for receiver line. + \param[in] usart_priv usart private to operate. +*/ +static void ck_usart_intr_recv_line(int32_t idx, ck_usart_priv_t *usart_priv) +{ + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + uint32_t lsr_stat = addr->LSR; + + addr->IER &= (~IER_THRE_INT_ENABLE); + + uint32_t timecount = 0; + + while (addr->LSR & 0x1) + { + addr->RBR; + timecount++; + + if (timecount >= UART_BUSY_TIMEOUT) + { + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_RX_TIMEOUT); + } + + return; + } + } + + /** Break Interrupt bit. This is used to indicate the detection of a + * break sequence on the serial input data. + */ + if (lsr_stat & DW_LSR_BI) + { + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_RX_BREAK); + } + + return; + } + + /** Framing Error bit. This is used to indicate the occurrence of a + * framing error in the receiver. A framing error occurs when the receiver + * does not detect a valid STOP bit in the received data. + */ + if (lsr_stat & DW_LSR_FE) + { + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_RX_FRAMING_ERROR); + } + + return; + } + + /** Framing Error bit. This is used to indicate the occurrence of a + * framing error in the receiver. A framing error occurs when the + * receiver does not detect a valid STOP bit in the received data. + */ + if (lsr_stat & DW_LSR_PE) + { + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_RX_PARITY_ERROR); + } + + return; + } + + /** Overrun error bit. This is used to indicate the occurrence of an overrun error. + * This occurs if a new data character was received before the previous data was read. + */ + if (lsr_stat & DW_LSR_OE) + { + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_RX_OVERFLOW); + } + + return; + } +} +/** + \brief interrupt service function for character timeout. + \param[in] usart_priv usart private to operate. +*/ +static void ck_usart_intr_char_timeout(int32_t idx, ck_usart_priv_t *usart_priv) +{ + if ((usart_priv->rx_total_num != 0) && (usart_priv->rx_buf != NULL)) + { + ck_usart_intr_recv_data(idx, usart_priv); + return; + } + + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_RECEIVED); + } else + { + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + uint32_t timecount = 0; + + while (addr->LSR & 0x1) + { + addr->RBR; + timecount++; + + if (timecount >= UART_BUSY_TIMEOUT) + { + if (usart_priv->cb_event) + { + usart_priv->cb_event(idx, USART_EVENT_RX_TIMEOUT); + } + + return; + } + } + } +} + +/** + \brief the interrupt service function. + \param[in] index of usart instance. +*/ +void ck_usart_irqhandler(int32_t idx) +{ + ck_usart_priv_t *usart_priv = &usart_instance[idx]; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + uint8_t intr_state = addr->IIR & 0xf; + + switch (intr_state) + { + case DW_IIR_THR_EMPTY: /* interrupt source:transmitter holding register empty */ + ck_usart_intr_threshold_empty(idx, usart_priv); + break; + + case DW_IIR_RECV_DATA: /* interrupt source:receiver data available or receiver fifo trigger level reached */ + ck_usart_intr_char_timeout(idx, usart_priv); + //ck_usart_intr_recv_data(idx, usart_priv); + break; + + case DW_IIR_RECV_LINE: + ck_usart_intr_recv_line(idx, usart_priv); + break; + + case DW_IIR_CHAR_TIMEOUT: + ck_usart_intr_char_timeout(idx, usart_priv); + break; + + default: + break; + } +} + +/** + \brief Get driver capabilities. + \param[in] idx usart index + \return \ref usart_capabilities_t +*/ +usart_capabilities_t csi_usart_get_capabilities(int32_t idx) +{ + if (idx < 0 || idx >= CONFIG_USART_NUM) + { + usart_capabilities_t ret; + memset(&ret, 0, sizeof(usart_capabilities_t)); + return ret; + } + + return usart_capabilities; +} + +/** + \brief Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function + \param[in] idx usart index + \param[in] cb_event Pointer to \ref usart_event_cb_t + \return return usart handle if success +*/ +usart_handle_t csi_usart_initialize(int32_t idx, usart_event_cb_t cb_event) +{ + uint32_t base = 0u; + uint32_t irq = 0u; + void *handler; + + int32_t ret = target_usart_init(idx, &base, &irq, &handler); + + if (ret < 0 || ret >= CONFIG_USART_NUM) + { + return NULL; + } + + ck_usart_priv_t *usart_priv = &usart_instance[idx]; + usart_priv->base = base; + usart_priv->irq = irq; + usart_priv->cb_event = cb_event; + usart_priv->idx = idx; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + /* enable received data available */ + addr->IER = IER_RDA_INT_ENABLE | IIR_RECV_LINE_ENABLE; + drv_irq_register(usart_priv->irq, handler); + drv_irq_enable(usart_priv->irq); + + return usart_priv; +} + +/** + \brief De-initialize UART Interface. stops operation and releases the software resources used by the interface + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_uninitialize(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + + ck_usart_priv_t *usart_priv = handle; + + drv_irq_disable(usart_priv->irq); + drv_irq_unregister(usart_priv->irq); + usart_priv->cb_event = NULL; + + return 0; +} + +/** + \brief config usart mode. + \param[in] handle usart handle to operate. + \param[in] baud baud rate + \param[in] mode \ref usart_mode_e + \param[in] parity \ref usart_parity_e + \param[in] stopbits \ref usart_stop_bits_e + \param[in] bits \ref usart_data_bits_e + \return error code +*/ +int32_t csi_usart_config(usart_handle_t handle, + uint32_t baud, + usart_mode_e mode, + usart_parity_e parity, + usart_stop_bits_e stopbits, + usart_data_bits_e bits) +{ + int32_t ret; + + /* control the data_bit of the usart*/ + ret = csi_usart_config_baudrate(handle, baud); + + if (ret < 0) + { + return ret; + } + + /* control mode of the usart*/ + ret = csi_usart_config_mode(handle, mode); + + if (ret < 0) + { + return ret; + } + + /* control the parity of the usart*/ + ret = csi_usart_config_parity(handle, parity); + + if (ret < 0) + { + return ret; + } + + /* control the stopbit of the usart*/ + ret = csi_usart_config_stopbits(handle, stopbits); + + if (ret < 0) + { + return ret; + } + + ret = csi_usart_config_databits(handle, bits); + + if (ret < 0) + { + return ret; + } + + return 0; +} + + +/** + \brief Start sending data to UART transmitter,(received data is ignored). + The function is non-blocking,UART_EVENT_TRANSFER_COMPLETE is signaled when transfer completes. + csi_usart_get_status can indicates if transmission is still in progress or pending + \param[in] handle usart handle to operate. + \param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits, + \param[in] num Number of data items to send + \return error code +*/ +int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num) +{ + USART_NULL_PARAM_CHK(handle); + USART_NULL_PARAM_CHK(data); + + if (num == 0) + { + return ERR_USART(DRV_ERROR_PARAMETER); + } + + ck_usart_priv_t *usart_priv = handle; + + usart_priv->tx_buf = (uint8_t *)data; + usart_priv->tx_total_num = num; + usart_priv->tx_cnt = 0; + usart_priv->tx_busy = 1; + usart_priv->last_tx_num = 0; + + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + ck_usart_intr_threshold_empty(usart_priv->idx, usart_priv); + /* enable the interrupt*/ + addr->IER |= IER_THRE_INT_ENABLE; + return 0; +} + +/** + \brief Abort Send data to UART transmitter + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_send(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + ck_usart_priv_t *usart_priv = handle; + + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + addr->IER &= (~IER_THRE_INT_ENABLE); + + usart_priv->tx_cnt = usart_priv->tx_total_num; + usart_priv->tx_cnt = 0; + usart_priv->tx_busy = 0; + usart_priv->tx_buf = NULL; + usart_priv->tx_total_num = 0; + return 0; +} + +/** + \brief Start receiving data from UART receiver.transmits the default value as specified by csi_usart_set_default_tx_value + \param[in] handle usart handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver + \param[in] num Number of data items to receive + \return error code +*/ +int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num) +{ + USART_NULL_PARAM_CHK(handle); + USART_NULL_PARAM_CHK(data); + + ck_usart_priv_t *usart_priv = handle; + + usart_priv->rx_buf = (uint8_t *)data; // Save receive buffer usart + usart_priv->rx_total_num = num; // Save number of data to be received + usart_priv->rx_cnt = 0; + usart_priv->rx_busy = 1; + usart_priv->last_rx_num = 0; + + return 0; + +} + +/** + \brief query data from UART receiver FIFO. + \param[in] handle usart handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver + \param[in] num Number of data items to receive + \return receive fifo data num +*/ +int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num) +{ + USART_NULL_PARAM_CHK(handle); + USART_NULL_PARAM_CHK(data); + + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + int32_t recv_num = 0; + uint8_t *dest = (uint8_t *)data; + + while (addr->LSR & 0x1) + { + *dest++ = addr->RBR; + recv_num++; + + if (recv_num >= num) + { + break; + } + } + + return recv_num; + +} + +/** + \brief Abort Receive data from UART receiver + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_receive(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + ck_usart_priv_t *usart_priv = handle; + + usart_priv->rx_cnt = usart_priv->rx_total_num; + return 0; +} + +/** + \brief Start sending/receiving data to/from UART transmitter/receiver. + \param[in] handle usart handle to operate. + \param[in] data_out Pointer to buffer with data to send to USART transmitter + \param[out] data_in Pointer to buffer for data to receive from USART receiver + \param[in] num Number of data items to transfer + \return error code +*/ +int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(DRV_ERROR_UNSUPPORTED); +} + +/** + \brief abort sending/receiving data to/from USART transmitter/receiver. + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_transfer(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(DRV_ERROR_UNSUPPORTED); +} + +/** + \brief Get USART status. + \param[in] handle usart handle to operate. + \return USART status \ref usart_status_t +*/ +usart_status_t csi_usart_get_status(usart_handle_t handle) +{ + usart_status_t usart_status; + + memset(&usart_status, 0, sizeof(usart_status_t)); + + if (handle == NULL) + { + return usart_status; + } + + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + uint32_t line_status_reg = addr->LSR; + + usart_status.tx_busy = usart_priv->tx_busy; + usart_status.rx_busy = usart_priv->rx_busy; + + if (line_status_reg & DW_LSR_BI) + { + usart_status.rx_break = 1; + } + + if (line_status_reg & DW_LSR_FE) + { + usart_status.rx_framing_error = 1; + } + + if (line_status_reg & DW_LSR_PE) + { + usart_status.rx_parity_error = 1; + } + + usart_status.tx_enable = 1; + usart_status.rx_enable = 1; + + return usart_status; +} + +/** + \brief control the transmit. + \param[in] handle usart handle to operate. + \param[in] 1 - enable the transmitter. 0 - disable the transmitter + \return error code +*/ +int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable) +{ + USART_NULL_PARAM_CHK(handle); + return 0; +} + +/** + \brief control the receive. + \param[in] handle usart handle to operate. + \param[in] 1 - enable the receiver. 0 - disable the receiver + \return error code +*/ +int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable) +{ + USART_NULL_PARAM_CHK(handle); + return 0; +} + +/** + \brief control the break. + \param[in] handle usart handle to operate. + \param[in] 1- Enable continuous Break transmission,0 - disable continuous Break transmission + \return error code +*/ +int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(DRV_ERROR_UNSUPPORTED); +} + +/** + \brief flush receive/send data. + \param[in] handle usart handle to operate. + \param[in] type \ref usart_flush_type_e. + \return error code +*/ +int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type) +{ + USART_NULL_PARAM_CHK(handle); + + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + uint32_t timecount = 0; + + if (type == USART_FLUSH_WRITE) { + while ((!(addr->LSR & DW_LSR_TEMT))) + { + timecount++; + + if (timecount >= UART_BUSY_TIMEOUT) + { + return ERR_USART(DRV_ERROR_TIMEOUT); + } + } + } else if (type == USART_FLUSH_READ) + { + while (addr->LSR & 0x1) { + timecount++; + + if (timecount >= UART_BUSY_TIMEOUT) + { + return ERR_USART(DRV_ERROR_TIMEOUT); + } + } + } else + { + return ERR_USART(DRV_ERROR_PARAMETER); + } + + return 0; +} + +/** + \brief set interrupt mode. + \param[in] handle usart handle to operate. + \param[in] type \ref usart_intr_type_e. + \param[in] flag 0-OFF, 1-ON. + \return error code +*/ +int32_t csi_usart_set_interrupt(usart_handle_t handle, usart_intr_type_e type, int32_t flag) +{ + USART_NULL_PARAM_CHK(handle); + + ck_usart_priv_t *usart_priv = handle; + ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base); + + switch (type) + { + case USART_INTR_WRITE: + if (flag == 0) + { + addr->IER &= ~IER_THRE_INT_ENABLE; + } else if (flag == 1) + { + addr->IER |= IER_THRE_INT_ENABLE; + } else + { + return ERR_USART(DRV_ERROR_PARAMETER); + } + + break; + + case USART_INTR_READ: + if (flag == 0) + { + addr->IER &= ~IER_RDA_INT_ENABLE; + } else if (flag == 1) + { + addr->IER |= IER_RDA_INT_ENABLE; + } else + { + return ERR_USART(DRV_ERROR_PARAMETER); + } + + break; + + default: + return ERR_USART(DRV_ERROR_PARAMETER); + + } + + return 0; +} + +/** + \brief Get usart send data count. + \param[in] handle usart handle to operate. + \return number of currently transmitted data bytes +*/ +uint32_t csi_usart_get_tx_count(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + + ck_usart_priv_t *usart_priv = handle; + + if (usart_priv->tx_busy) + { + return usart_priv->tx_cnt; + } else + { + return usart_priv->last_tx_num; + } +} + +/** + \brief Get usart receive data count. + \param[in] handle usart handle to operate. + \return number of currently received data bytes +*/ +uint32_t csi_usart_get_rx_count(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + ck_usart_priv_t *usart_priv = handle; + + if (usart_priv->rx_busy) + { + return usart_priv->rx_cnt; + } else + { + return usart_priv->last_rx_num; + } +} + +/** + \brief control usart power. + \param[in] handle usart handle to operate. + \param[in] state power state.\ref csi_power_stat_e. + \return error code +*/ +int32_t csi_usart_power_control(usart_handle_t handle, csi_power_stat_e state) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(DRV_ERROR_UNSUPPORTED); +} + +/** + \brief config usart flow control type. + \param[in] handle usart handle to operate. + \param[in] flowctrl_type flow control type.\ref usart_flowctrl_type_e. + \return error code +*/ +int32_t csi_usart_config_flowctrl(usart_handle_t handle, + usart_flowctrl_type_e flowctrl_type) +{ + USART_NULL_PARAM_CHK(handle); + + switch (flowctrl_type) + { + case USART_FLOWCTRL_CTS: + return ERR_USART(DRV_ERROR_UNSUPPORTED); + + case USART_FLOWCTRL_RTS: + return ERR_USART(DRV_ERROR_UNSUPPORTED); + + case USART_FLOWCTRL_CTS_RTS: + return ERR_USART(DRV_ERROR_UNSUPPORTED); + break; + + case USART_FLOWCTRL_NONE: + return ERR_USART(DRV_ERROR_UNSUPPORTED); + break; + + default: + return ERR_USART(DRV_ERROR_UNSUPPORTED); + } + + return 0; +} + + +/** + \brief config usart clock Polarity and Phase. + \param[in] handle usart handle to operate. + \param[in] cpol Clock Polarity.\ref usart_cpol_e. + \param[in] cpha Clock Phase.\ref usart_cpha_e. + \return error code +*/ +int32_t csi_usart_config_clock(usart_handle_t handle, usart_cpol_e cpol, usart_cpha_e cpha) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(DRV_ERROR_UNSUPPORTED); +} + diff --git a/bsp/thead-smart/drivers/ck_usart.h b/bsp/thead-smart/drivers/ck_usart.h new file mode 100644 index 0000000000..bdaba45c4c --- /dev/null +++ b/bsp/thead-smart/drivers/ck_usart.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header file for usart driver + */ + +#ifndef __CK_USART_H +#define __CK_USART_H + +#include <stdio.h> +#include "errno.h" +#include "soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BAUDRATE_DEFAULT 19200 +#define UART_BUSY_TIMEOUT 1000000 +#define UART_RECEIVE_TIMEOUT 1000 +#define UART_TRANSMIT_TIMEOUT 1000 +#define UART_MAX_FIFO 0x10 +/* UART register bit definitions */ + +#define USR_UART_BUSY 0x01 +#define USR_UART_TFE 0x04 +#define USR_UART_RFNE 0x08 +#define LSR_DATA_READY 0x01 +#define LSR_THR_EMPTY 0x20 +#define IER_RDA_INT_ENABLE 0x01 +#define IER_THRE_INT_ENABLE 0x02 +#define IIR_RECV_LINE_ENABLE 0x04 +#define IIR_NO_ISQ_PEND 0x01 + +#define LCR_SET_DLAB 0x80 /* enable r/w DLR to set the baud rate */ +#define LCR_PARITY_ENABLE 0x08 /* parity enabled */ +#define LCR_PARITY_EVEN 0x10 /* Even parity enabled */ +#define LCR_PARITY_ODD 0xef /* Odd parity enabled */ +#define LCR_WORD_SIZE_5 0xfc /* the data length is 5 bits */ +#define LCR_WORD_SIZE_6 0x01 /* the data length is 6 bits */ +#define LCR_WORD_SIZE_7 0x02 /* the data length is 7 bits */ +#define LCR_WORD_SIZE_8 0x03 /* the data length is 8 bits */ +#define LCR_STOP_BIT1 0xfb /* 1 stop bit */ +#define LCR_STOP_BIT2 0x04 /* 1.5 stop bit */ + +#define DW_LSR_PFE 0x80 +#define DW_LSR_TEMT 0x40 +#define DW_LSR_THRE 0x40 +#define DW_LSR_BI 0x10 +#define DW_LSR_FE 0x08 +#define DW_LSR_PE 0x04 +#define DW_LSR_OE 0x02 +#define DW_LSR_DR 0x01 +#define DW_LSR_TRANS_EMPTY 0x20 + +#define DW_IIR_THR_EMPTY 0x02 /* threshold empty */ +#define DW_IIR_RECV_DATA 0x04 /* received data available */ +#define DW_IIR_RECV_LINE 0x06 /* receiver line status */ +#define DW_IIR_CHAR_TIMEOUT 0x0c /* character timeout */ + +typedef struct +{ + union + { + __IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */ + __OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */ + __IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */ + }; + union + { + __IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */ + __IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */ + }; + __IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */ + __IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */ + uint32_t RESERVED0; + __IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */ + __IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */ + uint32_t RESERVED1[24]; + __IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */ +} ck_usart_reg_t; + +#ifdef __cplusplus +} +#endif + +#endif /* __CK_USART_H */ + diff --git a/bsp/thead-smart/drivers/core_rv32.h b/bsp/thead-smart/drivers/core_rv32.h new file mode 100644 index 0000000000..87fccfba72 --- /dev/null +++ b/bsp/thead-smart/drivers/core_rv32.h @@ -0,0 +1,1130 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen CSI RV32 Core Peripheral Access Layer Header File + */ + +#ifndef __CORE_RV32_H_GENERIC +#define __CORE_RV32_H_GENERIC + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * CSI definitions + ******************************************************************************/ +/** + \ingroup RV32 + @{ + */ + +#ifndef __RV32 +#define __RV32 (0x01U) +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __GNUC__ ) +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_RV32_H_GENERIC */ + +#ifndef __CSI_GENERIC + +#ifndef __CORE_RV32_H_DEPENDANT +#define __CORE_RV32_H_DEPENDANT + +#ifdef __cplusplus +extern "C" { +#endif + +/* check device defines and use defaults */ +#ifndef __RV32_REV +#define __RV32_REV 0x0000U +#endif + +#ifndef __VIC_PRIO_BITS +#define __VIC_PRIO_BITS 2U +#endif + +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 1U +#endif + +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 1U +#endif + +#ifndef __ICACHE_PRESENT +#define __ICACHE_PRESENT 1U +#endif + +#ifndef __DCACHE_PRESENT +#define __DCACHE_PRESENT 1U +#endif + +#include <csi_rv32_gcc.h> + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CSI_glob_defs CSI Global Defines + + <strong>IO Type Qualifiers</strong> are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus +#define __I volatile /*!< Defines 'read only' permissions */ +#else +#define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group CK802 */ + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core CLIC Register + ******************************************************************************/ +/** + \defgroup CSI_core_register Defines and Type Definitions + \brief Type definitions and defines for CK80X processor based devices. +*/ + +/** + \ingroup CSI_core_register + \defgroup CSI_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \ingroup CSI_core_register + \defgroup CSI_CLIC Core-Local Interrupt Controller (CLIC) + \brief Type definitions for the CLIC Registers + @{ + */ + +/** + \brief Access to the structure of a vector interrupt controller. + */ +typedef struct +{ + __IOM uint8_t IP; /*!< Offset: 0x000 (R/W) Interrupt set pending register */ + __IOM uint8_t IE; /*!< Offset: 0x004 (R/W) Interrupt set enable register */ + __IOM uint8_t ATTR; /*!< Offset: 0x008 (R/W) Interrupt set attribute register */ + __IOM uint8_t CTL; /*!< Offset: 0x00C (R/W) Interrupt control register */ +} CLIC_INT_Control; + +typedef struct +{ + __IOM uint32_t CLICCFG:8; /*!< Offset: 0x000 (R/W) CLIC configure register */ + __IM uint32_t CLICINFO; + __IOM uint32_t MINTTHRESH; + uint32_t RESERVED[1021]; + CLIC_INT_Control CLICINT[4096]; +} CLIC_Type; + +#define CLIC_INFO_CLICINTCTLBITS_Pos 21U +#define CLIC_INFO_CLICINTCTLBITS_Msk (0xFUL << CLIC_INFO_CLICINTCTLBITS_Pos) + +#define CLIC_INTIP_IP_Pos 0U /*!< CLIC INTIP: IP Position */ +#define CLIC_INTIP_IP_Msk (0x1UL << CLIC_INTIP_IP_Pos) /*!< CLIC INTIP: IP Mask */ + +#define CLIC_INTIE_IE_Pos 0U /*!< CLIC INTIE: IE Position */ +#define CLIC_INTIE_IE_Msk (0x1UL << CLIC_INTIE_IE_Pos) /*!< CLIC INTIE: IE Mask */ + +#define CLIC_INTIE_T_Pos 7U /*!< CLIC INTIE: T Position */ +#define CLIC_INTIE_T_Msk (0x1UL << CLIC_INTIE_T_Pos) /*!< CLIC INTIE: T Mask */ + +#define CLIC_INTATTR_TRIG_Pos 1U /*!< CLIC INTATTR: TRIG Position */ +#define CLIC_INTATTR_TRIG_Msk (0x3UL << CLIC_INTATTR_TRIG_Pos) /*!< CLIC INTATTR: TRIG Mask */ + +#define CLIC_INTATTR_SHV_Pos 0U /*!< CLIC INTATTR: SHV Position */ +#define CLIC_INTATTR_SHV_Msk (0x1UL << CLIC_INTATTR_SHV_Pos) /*!< CLIC INTATTR: SHV Mask */ + +#define CLIC_INTCFG_NVBIT_Pos 5U /*!< CLIC INTCFG: NVBIT Position */ +#define CLIC_INTCFG_NVBIT_Msk (0x1UL << CLIC_INTCFG_NVBIT_Pos) /*!< CLIC INTCFG: NVBIT Mask */ + +#define CLIC_INTCFG_PRIO_Pos 5U /*!< CLIC INTCFG: INTCFG Position */ +#define CLIC_INTCFG_PRIO_Msk (0x7UL << CLIC_INTCFG_PRIO_Pos) /*!< CLIC INTCFG: INTCFG Mask */ + +#define CLIC_CLICCFG_NVBIT_Pos 0U /*!< CLIC CLICCFG: NVBIT Position */ +#define CLIC_CLICCFG_NVBIT_Msk (0x1UL << CLIC_CLICCFG_NVBIT_Pos) /*!< CLIC CLICCFG: NVBIT Mask */ + +#define CLIC_CLICCFG_NLBIT_Pos 1U /*!< CLIC CLICCFG: NLBIT Position */ +#define CLIC_CLICCFG_NLBIT_Msk (0xFUL << CLIC_CLICCFG_NLBIT_Pos) /*!< CLIC CLICCFG: NLBIT Mask */ + +#define CLIC_CLICCFG_NMBIT_Pos 5U /*!< CLIC CLICCFG: NMBIT Position */ +#define CLIC_CLICCFG_NMBIT_Msk (0x3UL << CLIC_CLICCFG_NMBIT_Pos) /*!< CLIC CLICCFG: NMBIT Mask */ + +/*@} end of group CSI_CLIC */ + +/** + \ingroup CSI_core_register + \defgroup CSI_PMP Physical Memory Protection (PMP) + \brief Type definitions for the PMP Registers + @{ + */ + +#define PMP_PMPCFG_R_Pos 0U /*!< PMP PMPCFG: R Position */ +#define PMP_PMPCFG_R_Msk (0x1UL << PMP_PMPCFG_R_Pos) /*!< PMP PMPCFG: R Mask */ + +#define PMP_PMPCFG_W_Pos 1U /*!< PMP PMPCFG: W Position */ +#define PMP_PMPCFG_W_Msk (0x1UL << PMP_PMPCFG_W_Pos) /*!< PMP PMPCFG: W Mask */ + +#define PMP_PMPCFG_X_Pos 2U /*!< PMP PMPCFG: X Position */ +#define PMP_PMPCFG_X_Msk (0x1UL << PMP_PMPCFG_X_Pos) /*!< PMP PMPCFG: X Mask */ + +#define PMP_PMPCFG_A_Pos 3U /*!< PMP PMPCFG: A Position */ +#define PMP_PMPCFG_A_Msk (0x3UL << PMP_PMPCFG_A_Pos) /*!< PMP PMPCFG: A Mask */ + +#define PMP_PMPCFG_L_Pos 7U /*!< PMP PMPCFG: L Position */ +#define PMP_PMPCFG_L_Msk (0x1UL << PMP_PMPCFG_L_Pos) /*!< PMP PMPCFG: L Mask */ + +typedef enum +{ + REGION_SIZE_4B = -1, + REGION_SIZE_8B = 0, + REGION_SIZE_16B = 1, + REGION_SIZE_32B = 2, + REGION_SIZE_64B = 3, + REGION_SIZE_128B = 4, + REGION_SIZE_256B = 5, + REGION_SIZE_512B = 6, + REGION_SIZE_1KB = 7, + REGION_SIZE_2KB = 8, + REGION_SIZE_4KB = 9, + REGION_SIZE_8KB = 10, + REGION_SIZE_16KB = 11, + REGION_SIZE_32KB = 12, + REGION_SIZE_64KB = 13, + REGION_SIZE_128KB = 14, + REGION_SIZE_256KB = 15, + REGION_SIZE_512KB = 16, + REGION_SIZE_1MB = 17, + REGION_SIZE_2MB = 18, + REGION_SIZE_4MB = 19, + REGION_SIZE_8MB = 20, + REGION_SIZE_16MB = 21, + REGION_SIZE_32MB = 22, + REGION_SIZE_64MB = 23, + REGION_SIZE_128MB = 24, + REGION_SIZE_256MB = 25, + REGION_SIZE_512MB = 26, + REGION_SIZE_1GB = 27, + REGION_SIZE_2GB = 28, + REGION_SIZE_4GB = 29, + REGION_SIZE_8GB = 30, + REGION_SIZE_16GB = 31 +} region_size_e; + +typedef enum +{ + ADDRESS_MATCHING_TOR = 1, + ADDRESS_MATCHING_NAPOT = 3 +} address_matching_e; + +typedef struct +{ + uint32_t r: 1; /* readable enable */ + uint32_t w: 1; /* writeable enable */ + uint32_t x: 1; /* execable enable */ + address_matching_e a: 2; /* address matching mode */ + uint32_t reserved: 2; /* reserved */ + uint32_t l: 1; /* lock enable */ +} mpu_region_attr_t; + +/*@} end of group CSI_PMP */ + +/* CACHE Register Definitions */ +#define CACHE_MHCR_L0BTB_Pos 12U /*!< CACHE MHCR: L0BTB Position */ +#define CACHE_MHCR_L0BTB_Msk (0x1UL << CACHE_MHCR_L0BTB_Pos) /*!< CACHE MHCR: WA Mask */ + +#define CACHE_MHCR_BPE_Pos 5U /*!< CACHE MHCR: BPE Position */ +#define CACHE_MHCR_BPE_Msk (0x1UL << CACHE_MHCR_BPE_Pos) /*!< CACHE MHCR: BPE Mask */ + +#define CACHE_MHCR_RS_Pos 4U /*!< CACHE MHCR: RS Position */ +#define CACHE_MHCR_RS_Msk (0x1UL << CACHE_MHCR_RS_Pos) /*!< CACHE MHCR: RS Mask */ + +#define CACHE_MHCR_WA_Pos 3U /*!< CACHE MHCR: WA Position */ +#define CACHE_MHCR_WA_Msk (0x1UL << CACHE_MHCR_WA_Pos) /*!< CACHE MHCR: WA Mask */ + +#define CACHE_MHCR_WB_Pos 2U /*!< CACHE MHCR: WB Position */ +#define CACHE_MHCR_WB_Msk (0x1UL << CACHE_MHCR_WB_Pos) /*!< CACHE MHCR: WB Mask */ + +#define CACHE_MHCR_DE_Pos 1U /*!< CACHE MHCR: DE Position */ +#define CACHE_MHCR_DE_Msk (0x1UL << CACHE_MHCR_DE_Pos) /*!< CACHE MHCR: DE Mask */ + +#define CACHE_MHCR_IE_Pos 0U /*!< CACHE MHCR: IE Position */ +#define CACHE_MHCR_IE_Msk (0x1UL << CACHE_MHCR_IE_Pos) /*!< CACHE MHCR: IE Mask */ + +#define CACHE_INV_ADDR_Pos 5U +#define CACHE_INV_ADDR_Msk (0xFFFFFFFFUL << CACHE_INV_ADDR_Pos) + +/*@} end of group CSI_CACHE */ + + +/** + \ingroup CSI_core_register + \defgroup CSI_SysTick System Tick Timer (CORET) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief The data structure of the access system timer. + */ +typedef struct +{ + __IOM unsigned long long MTIMECMP; /*!< Offset: 0x000 (R/W) Timer compare register */ + uint32_t RESERVED[8187]; + __IM unsigned long long MTIME; /*!< Offset: 0x7FFC (R) Timer current register */ +} CORET_Type; + +/*@} end of group CSI_SysTick */ + +/** + \ingroup CSI_core_register + \defgroup CSI_DCC + \brief Type definitions for the DCC. + @{ + */ + +/** + \brief Access to the data structure of DCC. + */ +typedef struct +{ + uint32_t RESERVED0[13U]; + __IOM uint32_t HCR; /*!< Offset: 0x034 (R/W) */ + __IM uint32_t EHSR; /*!< Offset: 0x03C (R/ ) */ + uint32_t RESERVED1[6U]; + union { + __IM uint32_t DERJW; /*!< Offset: 0x058 (R/ ) Data exchange register CPU read*/ + __OM uint32_t DERJR; /*!< Offset: 0x058 ( /W) Data exchange register CPU writer*/ + }; + +} DCC_Type; + +#define DCC_HCR_JW_Pos 18U /*!< DCC HCR: jw_int_en Position */ +#define DCC_HCR_JW_Msk (1UL << DCC_HCR_JW_Pos) /*!< DCC HCR: jw_int_en Mask */ + +#define DCC_HCR_JR_Pos 19U /*!< DCC HCR: jr_int_en Position */ +#define DCC_HCR_JR_Msk (1UL << DCC_HCR_JR_Pos) /*!< DCC HCR: jr_int_en Mask */ + +#define DCC_EHSR_JW_Pos 1U /*!< DCC EHSR: jw_vld Position */ +#define DCC_EHSR_JW_Msk (1UL << DCC_EHSR_JW_Pos) /*!< DCC EHSR: jw_vld Mask */ + +#define DCC_EHSR_JR_Pos 2U /*!< DCC EHSR: jr_vld Position */ +#define DCC_EHSR_JR_Msk (1UL << DCC_EHSR_JR_Pos) /*!< DCC EHSR: jr_vld Mask */ + +/*@} end of group CSI_DCC */ + + +/** + \ingroup CSI_core_register + \defgroup CSI_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CSI_core_bitfield */ + +/** + \ingroup CSI_core_register + \defgroup CSI_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of CK802 Hardware */ +#define TCIP_BASE (0xE000E000UL) /*!< Titly Coupled IP Base Address */ +#define CORET_BASE (0xE0004000UL) /*!< CORET Base Address */ +#define CLIC_BASE (0xE0800000UL) /*!< CLIC Base Address */ +#define DCC_BASE (0xE4010000UL) /*!< DCC Base Address */ +#define CACHE_BASE (TCIP_BASE + 0x1000UL) /*!< CACHE Base Address */ + +#define CORET ((CORET_Type *) CORET_BASE ) /*!< SysTick configuration struct */ +#define CLIC ((CLIC_Type *) CLIC_BASE ) /*!< CLIC configuration struct */ +#define DCC ((DCC_Type *) DCC_BASE ) /*!< DCC configuration struct */ +#define CACHE ((CACHE_Type *) CACHE_BASE ) /*!< cache configuration struct */ + +/*@} */ + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core VIC Functions + - Core CORET Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CSI_Core_FunctionInterface Functions and Instructions Reference +*/ + +/* ########################## VIC functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_VICFunctions VIC Functions + \brief Functions that manage interrupts and exceptions via the VIC. + @{ + */ + +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 5UL) ) +#define _IP2_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +/** + \brief Enable External Interrupt + \details Enable a device-specific interrupt in the VIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_enable_irq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IE |= CLIC_INTIE_IE_Msk; +} + +/** + \brief Disable External Interrupt + \details Disable a device-specific interrupt in the VIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_disable_irq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IE &= ~CLIC_INTIE_IE_Msk; +} + +/** + \brief Enable External Secure Interrupt + \details Enable a secure device-specific interrupt in the VIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_enable_sirq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IE |= (CLIC_INTIE_IE_Msk | CLIC_INTIE_T_Msk); +} + +/** + \brief Disable External Secure Interrupt + \details Disable a secure device-specific interrupt in the VIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_disable_sirq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IE &= ~(CLIC_INTIE_IE_Msk | CLIC_INTIE_T_Msk); +} + +/** + \brief Check Interrupt is Enabled or not + \details Read the enabled register in the VIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not enabled. + \return 1 Interrupt status is enabled. + */ +__STATIC_INLINE uint32_t csi_vic_get_enabled_irq(int32_t IRQn) +{ + return (uint32_t)(CLIC->CLICINT[IRQn].IE & CLIC_INTIE_IE_Msk); +} + +/** + \brief Check Interrupt is Pending or not + \details Read the pending register in the VIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t csi_vic_get_pending_irq(int32_t IRQn) +{ + return (uint32_t)(CLIC->CLICINT[IRQn].IP & CLIC_INTIP_IP_Msk); +} + +/** + \brief Set Pending Interrupt + \details Set the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_set_pending_irq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IP |= CLIC_INTIP_IP_Msk; +} + +/** + \brief Clear Pending Interrupt + \details Clear the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_clear_pending_irq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IP &= ~CLIC_INTIP_IP_Msk; +} + +/** + \brief Set Interrupt Priority + \details Set the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void csi_vic_set_prio(int32_t IRQn, uint32_t priority) +{ + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[IRQn].CTL = (CLIC->CLICINT[IRQn].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (priority << (8 - nlbits)); +} + +/** + \brief Get Interrupt Priority + \details Read the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t csi_vic_get_prio(int32_t IRQn) +{ + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + return CLIC->CLICINT[IRQn].CTL >> (8 - nlbits); +} + +/** + \brief Set interrupt handler + \details Set the interrupt handler according to the interrupt num, the handler will be filled in irq vectors. + \param [in] IRQn Interrupt number. + \param [in] handler Interrupt handler. + */ +__STATIC_INLINE void csi_vic_set_vector(int32_t IRQn, uint32_t handler) +{ + if (IRQn >= 0 && IRQn < 1024) { + uint32_t *vectors = (uint32_t *)__get_MTVT(); + vectors[IRQn] = handler; + } +} + +/** + \brief Get interrupt handler + \details Get the address of interrupt handler function. + \param [in] IRQn Interrupt number. + */ +__STATIC_INLINE uint32_t csi_vic_get_vector(int32_t IRQn) +{ + if (IRQn >= 0 && IRQn < 1024) { + uint32_t *vectors = (uint32_t *)__get_MTVT(); + return (uint32_t)vectors[IRQn]; + } + + return 0; +} + +/*@} end of CSI_Core_VICFunctions */ + +/* ########################## PMP functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_PMPFunctions PMP Functions + \brief Functions that manage interrupts and exceptions via the VIC. + @{ + */ + +/** + \brief configure memory protected region. + \details + \param [in] idx memory protected region (0, 1, 2, ..., 15). + \param [in] base_addr base address must be aligned with page size. + \param [in] size \ref region_size_e. memory protected region size. + \param [in] attr \ref region_size_t. memory protected region attribute. + \param [in] enable enable or disable memory protected region. + */ +__STATIC_INLINE void csi_mpu_config_region(uint32_t idx, uint32_t base_addr, region_size_e size, + mpu_region_attr_t attr, uint32_t enable) +{ + uint8_t pmpxcfg = 0; + uint32_t addr = 0; + + if (idx > 15) { + return; + } + + if (!enable) { + attr.a = 0; + } + + if (attr.a == ADDRESS_MATCHING_TOR) { + addr = base_addr >> 2; + } else { + if (size == REGION_SIZE_4B) { + addr = base_addr >> 2; + attr.a = 2; + } else { + addr = ((base_addr >> 2) & (0xFFFFFFFFU - ((1 << (size + 1)) - 1))) | ((1 << size) - 1); + } + } + + __set_PMPADDRx(idx, addr); + + pmpxcfg |= (attr.r << PMP_PMPCFG_R_Pos) | (attr.w << PMP_PMPCFG_W_Pos) | + (attr.x << PMP_PMPCFG_X_Pos) | (attr.a << PMP_PMPCFG_A_Pos) | + (attr.l << PMP_PMPCFG_L_Pos); + + __set_PMPxCFG(idx, pmpxcfg); +} + +/** + \brief disable mpu region by idx. + \details + \param [in] idx memory protected region (0, 1, 2, ..., 15). + */ +__STATIC_INLINE void csi_mpu_disable_region(uint32_t idx) +{ + __set_PMPxCFG(idx, __get_PMPxCFG(idx) & (~PMP_PMPCFG_A_Msk)); +} + +/*@} end of CSI_Core_PMPFunctions */ + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + + +/** + \brief CORE timer Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \param [in] IRQn core timer Interrupt number. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the + function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b> + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t csi_coret_config(uint32_t ticks, int32_t IRQn) +{ + if (CORET->MTIMECMP) { + CORET->MTIMECMP = CORET->MTIMECMP + ticks; + } else { + CORET->MTIMECMP = CORET->MTIME + ticks; + } + return (0UL); +} + +/** + \brief get CORE timer reload value + \return CORE timer counter value. + */ +__STATIC_INLINE uint32_t csi_coret_get_load(void) +{ + return CORET->MTIMECMP & 0xFFFFFFFF; +} + +/** + \brief get CORE timer reload high value + \return CORE timer counter value. + */ +__STATIC_INLINE uint32_t csi_coret_get_loadh(void) +{ + return (CORET->MTIMECMP >> 32) & 0xFFFFFFFF; +} + +/** + \brief get CORE timer counter value + \return CORE timer counter value. + */ +__STATIC_INLINE uint32_t csi_coret_get_value(void) +{ + return CORET->MTIME & 0xFFFFFFFF; +} + +/** + \brief get CORE timer counter high value + \return CORE timer counter value. + */ +__STATIC_INLINE uint32_t csi_coret_get_valueh(void) +{ + return (CORET->MTIME >> 32) & 0xFFFFFFFF; +} + +/*@} end of CSI_Core_SysTickFunctions */ + +/* ##################################### DCC function ########################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_core_DebugFunctions HAD Functions + \brief Functions that access the HAD debug interface. + @{ + */ + +/** + \brief HAD Send Character + \details Transmits a character via the HAD channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t csi_had_send_char(uint32_t ch) +{ + DCC->DERJR = (uint8_t)ch; + + return (ch); +} + + +/** + \brief HAD Receive Character + \details Inputs a character via the external variable \ref HAD_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t csi_had_receive_char(void) +{ + int32_t ch = -1; /* no character available */ + + if (_FLD2VAL(DCC_EHSR_JW, DCC->EHSR)) { + ch = DCC->DERJW; + } + + return (ch); +} + + +/** + \brief HAD Check Character + \details Check whether a character is pending for reading in the variable \ref HAD_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t csi_had_check_char(void) +{ + return _FLD2VAL(DCC_EHSR_JW, DCC->EHSR); /* no character available */ +} + +/*@} end of CSI_core_DebugFunctions */ + + +/* ########################## sleep and Reset functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_SleepAndResetFunctions Sleep and Reset Functions + \brief Functions that configure Sleep and Reset. + @{ + */ + + +/* MEXSTATUS Register Definitions */ +#define MEXSTATUS_RESET_Pos 0U +#define MEXSTATUS_RESET_Msk (0x3UL << MEXSTATUS_RESET_Pos) /*!< MEXSTATUS: RESET Position */ +#define MEXSTATUS_SLEEP_Pos 2U +#define MEXSTATUS_SLEEP_Msk (0x3UL << MEXSTATUS_SLEEP_Pos) /*!< MEXSTATUS: RESET Position */ +/*@} end of group CSI_MEXSTATUS */ + + + +/** + \brief CPU System Reset + \details Triggle CPU System Reset + */ +__STATIC_INLINE void csi_system_reset (void) +{ + uint32_t mexstatus; + mexstatus = __get_MEXSTATUS(); + mexstatus &= (~(MEXSTATUS_RESET_Msk)); + mexstatus |= (uint32_t)(0x2 << MEXSTATUS_RESET_Pos); + __set_MEXSTATUS(mexstatus); +} + +/** + \brief CPU Core Reset + \details Triggle CPU Core Reset + */ +__STATIC_INLINE void csi_core_reset (void) +{ + uint32_t mexstatus; + mexstatus = __get_MEXSTATUS(); + mexstatus &= (~(MEXSTATUS_RESET_Msk)); + mexstatus |= (uint32_t)(0x1 << MEXSTATUS_RESET_Pos); + __set_MEXSTATUS(mexstatus); +} + +/* ########################## Cache functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_INLINE void csi_icache_enable (void) +{ +#if (__ICACHE_PRESENT == 1U) + uint32_t cache; + __DSB(); + __ISB(); + __ICACHE_IALL(); + cache = __get_MHCR(); + cache |= CACHE_MHCR_IE_Msk; + __set_MHCR(cache); + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_INLINE void csi_icache_disable (void) +{ +#if (__ICACHE_PRESENT == 1U) + uint32_t cache; + __DSB(); + __ISB(); + cache = __get_MHCR(); + cache &= ~CACHE_MHCR_IE_Msk; /* disable icache */ + __set_MHCR(cache); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void csi_icache_invalid (void) +{ +#if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + \note I-Cache also turns on. + */ +__STATIC_INLINE void csi_dcache_enable (void) +{ +#if (__DCACHE_PRESENT == 1U) + uint32_t cache; + __DSB(); + __ISB(); + __DCACHE_IALL(); /* invalidate all dcache */ + cache = __get_MHCR(); + cache |= (CACHE_MHCR_DE_Msk | CACHE_MHCR_WB_Msk | CACHE_MHCR_WA_Msk | CACHE_MHCR_RS_Msk | CACHE_MHCR_BPE_Msk | CACHE_MHCR_L0BTB_Msk); /* enable all Cache */ + __set_MHCR(cache); + + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + \note I-Cache also turns off. + */ +__STATIC_INLINE void csi_dcache_disable (void) +{ +#if (__DCACHE_PRESENT == 1U) + uint32_t cache; + __DSB(); + __ISB(); + cache = __get_MHCR(); + cache &= ~(uint32_t)CACHE_MHCR_DE_Msk; /* disable all Cache */ + __set_MHCR(cache); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + \note I-Cache also invalid + */ +__STATIC_INLINE void csi_dcache_invalid (void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + \note I-Cache also cleans + */ +__STATIC_INLINE void csi_dcache_clean (void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_CALL(); /* clean all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + \note I-Cache also flush. + */ +__STATIC_INLINE void csi_dcache_clean_invalid (void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_CIALL(); /* clean and inv all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void csi_dcache_invalid_range (uint32_t *addr, int32_t dsize) +{ +#if (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize + (uint32_t)addr % 32; + uint32_t op_addr = (uint32_t)addr; + int32_t linesize = 32; + + __DSB(); + + while (op_size > 0) { + __DCACHE_IPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); +#endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void csi_dcache_clean_range (uint32_t *addr, int32_t dsize) +{ + +#if (__DCACHE_PRESENT == 1) + int32_t op_size = dsize + (uint32_t)addr % 32; + uint32_t op_addr = (uint32_t) addr & CACHE_INV_ADDR_Msk; + int32_t linesize = 32; + + __DSB(); + + while (op_size > 0) { + __DCACHE_CPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); +#endif + +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (aligned to 16-byte boundary) +*/ +__STATIC_INLINE void csi_dcache_clean_invalid_range (uint32_t *addr, int32_t dsize) +{ +#if (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize + (uint32_t)addr % 32; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32; + + __DSB(); + + while (op_size > 0) { + __DCACHE_CIPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); +#endif +} + +/** + \brief setup cacheable range Cache + \details setup Cache range + */ +__STATIC_INLINE void csi_cache_set_range (uint32_t index, uint32_t baseAddr, uint32_t size, uint32_t enable) +{ + ; +} + +/** + \brief Enable cache profile + \details Turns on Cache profile + */ +__STATIC_INLINE void csi_cache_enable_profile (void) +{ + ; +} + +/** + \brief Disable cache profile + \details Turns off Cache profile + */ +__STATIC_INLINE void csi_cache_disable_profile (void) +{ + ; +} + +/** + \brief Reset cache profile + \details Reset Cache profile + */ +__STATIC_INLINE void csi_cache_reset_profile (void) +{ + ; +} + +/** + \brief cache access times + \details Cache access times + \note every 256 access add 1. + \return cache access times, actual times should be multiplied by 256 + */ +__STATIC_INLINE uint32_t csi_cache_get_access_time (void) +{ + return 0; +} + +/** + \brief cache miss times + \details Cache miss times + \note every 256 miss add 1. + \return cache miss times, actual times should be multiplied by 256 + */ +__STATIC_INLINE uint32_t csi_cache_get_miss_time (void) +{ + return 0; +} + +/*@} end of CSI_Core_CacheFunctions */ + +/*@} end of CSI_core_DebugFunctions */ + +/* ################################## IRQ Functions ############################################ */ + +/** + \brief Save the Irq context + \details save the psr result before disable irq. + */ +__STATIC_INLINE uint32_t csi_irq_save(void) +{ + uint32_t result; + result = __get_MSTATUS(); + __disable_irq(); + return(result); +} + +/** + \brief Restore the Irq context + \details restore saved primask state. + \param [in] irq_state psr irq state. + */ +__STATIC_INLINE void csi_irq_restore(uint32_t irq_state) +{ + __set_MSTATUS(irq_state); +} + +/*@} end of IRQ Functions */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_RV32_H_DEPENDANT */ + +#endif /* __CSI_GENERIC */ diff --git a/bsp/thead-smart/drivers/csi_config.h b/bsp/thead-smart/drivers/csi_config.h new file mode 100644 index 0000000000..75185caff4 --- /dev/null +++ b/bsp/thead-smart/drivers/csi_config.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen config file + */ + +/* csi_config.h -- Autogenerated! Do not edit. */ + +#ifndef __CSI_CONFIG_H +#define __CSI_CONFIG_H + +#define CONFIG_ARCH_RV32 1 +#define CONFIG_CPU_E906FD 1 +#define CONFIG_RV32_CORETIM 1 +#define CONFIG_CHIP_SMARTL_RV32 1 +#define CONFIG_BOARD_SMARTL_E906_EVB 1 +#define CONFIG_BOARD_NAME_STR "smartl_e906_evb" +#define CONFIG_SUPPORT_TSPEND 1 +#define CONFIG_ARCH_INTERRUPTSTACK 4096 +#define CONFIG_NEWLIB_WRAP 1 +#define CONFIG_USER_DEFINED_LD_DIR_STR "" + +#define CONFIG_KERNEL_RTTHREAD 1 +#endif /* __CONFIG_H */ + diff --git a/bsp/thead-smart/drivers/csi_core.h b/bsp/thead-smart/drivers/csi_core.h new file mode 100644 index 0000000000..49659a499b --- /dev/null +++ b/bsp/thead-smart/drivers/csi_core.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen CSI Core Layer Header File + */ + + +#ifndef _CORE_H_ +#define _CORE_H_ + +#include <stdint.h> + +#if defined(__CK801__) || defined(__E801__) +#include <core_801.h> +#elif defined(__CK802__) || defined(__E802__) || defined(__E802T__) || defined(__S802__) || defined(__S802T__) +#include <core_802.h> +#elif defined(__CK804__) || defined(__E804D__) || defined(__E804DT__) || defined(__E804F__) || defined(__E804FT__) || defined (__E804DF__) || defined(__E804DFT__) +#include <core_804.h> +#elif defined(__CK803__) || defined(__E803__) || defined(__E803T__) || defined(__S803__) || defined(__S803T__) +#include <core_803.h> +#elif defined(__CK805__) || defined(__I805__) || defined(__I805F__) +#include <core_805.h> +#elif defined(__CK610__) +#include <core_ck610.h> +#elif defined(__CK810__) || defined(__C810__) || defined(__C810T__) || defined(__C810V__) || defined(__C810VT__) +#include <core_810.h> +#elif defined(__CK807__) || defined(__C807__) || defined(__C807F__) || defined(__C807FV__) || defined(__R807__) +#include <core_807.h> +#elif defined(__riscv) && defined(CONFIG_CSKY_CORETIM) +#include <core_rv32_old.h> +#elif defined(__riscv) +#include <core_rv32.h> +#endif + +#ifdef __riscv +#include <csi_rv32_gcc.h> +#else +#include <csi_gcc.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _CORE_H_ */ diff --git a/bsp/thead-smart/drivers/csi_rv32_gcc.h b/bsp/thead-smart/drivers/csi_rv32_gcc.h new file mode 100644 index 0000000000..bc52d66426 --- /dev/null +++ b/bsp/thead-smart/drivers/csi_rv32_gcc.h @@ -0,0 +1,2849 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen CSI Header File for GCC. + */ + +#ifndef _CSI_RV32_GCC_H_ +#define _CSI_RV32_GCC_H_ + +#include <stdlib.h> + +#ifndef __ASM +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#endif + +#ifndef __INLINE +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#endif + +#ifndef __ALWAYS_STATIC_INLINE +#define __ALWAYS_STATIC_INLINE __attribute__((always_inline)) static inline +#endif + +#ifndef __STATIC_INLINE +#define __STATIC_INLINE static inline +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_RegAccFunctions CSI Core Register Access Functions + @{ + */ +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by setting the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile("csrs mstatus, 8"); +} + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by clearing the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile("csrc mstatus, 8"); +} + +/** + \brief Get MXSTATUS + \details Returns the content of the MXSTATUS Register. + \return MXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MXSTATUS(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mxstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MXSTATUS + \details Writes the given value to the MXSTATUS Register. + \param [in] MXSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MXSTATUS(uint32_t mxstatus) +{ + __ASM volatile("csrw mxstatus, %0" : : "r"(mxstatus)); +} + +/** + \brief Get MEXSTATUS + \details Returns the content of the MEXSTATUS Register. + \return MEXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MEXSTATUS(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mexstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MEXSTATUS + \details Writes the given value to the MSTATUS Register. + \param [in] MEXSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEXSTATUS(uint32_t mexstatus) +{ + __ASM volatile("csrw mexstatus, %0" : : "r"(mexstatus)); +} + + +/** + \brief Get MRADDR + \details Returns the content of the MRADDR Register. + \return MRADDR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MRADDR(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mraddr" : "=r"(result)); + return (result); +} + +/** + \brief Get FXCR + \details Returns the content of the FXCR Register. + \return FXCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_FXCR(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, fxcr" : "=r"(result)); + return (result); +} + + +/** + \brief Set FXCR + \details Writes the given value to the FXCR Register. + \param [in] FXCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_FXCR(uint32_t fxcr) +{ + __ASM volatile("csrw fxcr, %0" : : "r"(fxcr)); +} + +/** + \brief Get MSTATUS + \details Returns the content of the MSTATUS Register. + \return MSTATUS Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MSTATUS(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MSTATUS + \details Writes the given value to the MSTATUS Register. + \param [in] mstatus MSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSTATUS(uint32_t mstatus) +{ + __ASM volatile("csrw mstatus, %0" : : "r"(mstatus)); +} + +/** + \brief Get MHCR + \details Returns the content of the MHCR Register. + \return MHCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MHCR(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mhcr" : "=r"(result)); + return (result); +} + +/** + \brief Set MHCR + \details Writes the given value to the MHCR Register. + \param [in] mstatus MHCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHCR(uint32_t mhcr) +{ + __ASM volatile("csrw mhcr, %0" : : "r"(mhcr)); +} + +/** + \brief Get MISA Register + \details Returns the content of the MISA Register. + \return MISA Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MISA(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, misa" : "=r"(result)); + return (result); +} + +/** + \brief Set MISA + \details Writes the given value to the MISA Register. + \param [in] misa MISA Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MISA(uint32_t misa) +{ + __ASM volatile("csrw misa, %0" : : "r"(misa)); +} + +/** + \brief Get MIE Register + \details Returns the content of the MIE Register. + \return MIE Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MIE(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mie" : "=r"(result)); + return (result); +} + +/** + \brief Set MIE + \details Writes the given value to the MIE Register. + \param [in] mie MIE Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIE(uint32_t mie) +{ + __ASM volatile("csrw mie, %0" : : "r"(mie)); +} + +/** + \brief Get MTVEC Register + \details Returns the content of the MTVEC Register. + \return MTVEC Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MTVEC(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mtvec" : "=r"(result)); + return (result); +} + +/** + \brief Set MTVEC + \details Writes the given value to the MTVEC Register. + \param [in] mtvec MTVEC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MTVEC(uint32_t mtvec) +{ + __ASM volatile("csrw mtvec, %0" : : "r"(mtvec)); +} + +/** + \brief Set MTVT + \details Writes the given value to the MTVT Register. + \param [in] mtvt MTVT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MTVT(uint32_t mtvt) +{ + __ASM volatile("csrw mtvt, %0" : : "r"(mtvt)); +} + +/** + \brief Get MTVT Register + \details Returns the content of the MTVT Register. + \return MTVT Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MTVT(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mtvt" : "=r"(result)); + return (result); +} + +/** + \brief Get SP + \details Returns the content of the SP Register. + \return SP Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_SP(void) +{ + uint32_t result; + + __ASM volatile("mv %0, sp" : "=r"(result)); + return (result); +} + +/** + \brief Set SP + \details Writes the given value to the SP Register. + \param [in] sp SP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_SP(uint32_t sp) +{ + __ASM volatile("mv sp, %0" : : "r"(sp): "sp"); +} + +/** + \brief Get MSCRATCH Register + \details Returns the content of the MSCRATCH Register. + \return MSCRATCH Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MSCRATCH(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mscratch" : "=r"(result)); + return (result); +} + +/** + \brief Set MSCRATCH + \details Writes the given value to the MSCRATCH Register. + \param [in] mscratch MSCRATCH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSCRATCH(uint32_t mscratch) +{ + __ASM volatile("csrw mscratch, %0" : : "r"(mscratch)); +} + +/** + \brief Get MEPC Register + \details Returns the content of the MEPC Register. + \return MEPC Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MEPC(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mepc" : "=r"(result)); + return (result); +} + +/** + \brief Set MEPC + \details Writes the given value to the MEPC Register. + \param [in] mepc MEPC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEPC(uint32_t mepc) +{ + __ASM volatile("csrw mepc, %0" : : "r"(mepc)); +} + +/** + \brief Get MCAUSE Register + \details Returns the content of the MCAUSE Register. + \return MCAUSE Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MCAUSE(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mcause" : "=r"(result)); + return (result); +} + +/** + \brief Get MNXTI Register + \details Returns the content of the MNXTI Register. + \return MNXTI Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MNXTI(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mnxti" : "=r"(result)); + return (result); +} + +/** + \brief Set MNXTI + \details Writes the given value to the MNXTI Register. + \param [in] mnxti MNXTI Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MNXTI(uint32_t mnxti) +{ + __ASM volatile("csrw mnxti, %0" : : "r"(mnxti)); +} + +/** + \brief Get MINTSTATUS Register + \details Returns the content of the MINTSTATUS Register. + \return MINTSTATUS Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MINTSTATUS(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mintstatus" : "=r"(result)); + return (result); +} + +/** + \brief Get MTVAL Register + \details Returns the content of the MTVAL Register. + \return MTVAL Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MTVAL(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mtval" : "=r"(result)); + return (result); +} + +/** + \brief Get MIP Register + \details Returns the content of the MIP Register. + \return MIP Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MIP(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mip" : "=r"(result)); + return (result); +} + +/** + \brief Set MIP + \details Writes the given value to the MIP Register. + \param [in] mip MIP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIP(uint32_t mip) +{ + __ASM volatile("csrw mip, %0" : : "r"(mip)); +} + +/** + \brief Get MCYCLEL Register + \details Returns the content of the MCYCLEL Register. + \return MCYCLE Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MCYCLE(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mcycle" : "=r"(result)); + return (result); +} + +/** + \brief Get MCYCLEH Register + \details Returns the content of the MCYCLEH Register. + \return MCYCLEH Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MCYCLEH(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mcycleh" : "=r"(result)); + return (result); +} + +/** + \brief Get MINSTRET Register + \details Returns the content of the MINSTRET Register. + \return MINSTRET Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MINSTRET(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, minstret" : "=r"(result)); + return (result); +} + +/** + \brief Get MINSTRETH Register + \details Returns the content of the MINSTRETH Register. + \return MINSTRETH Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MINSTRETH(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, minstreth" : "=r"(result)); + return (result); +} + +/** + \brief Get MVENDORID Register + \details Returns the content of the MVENDROID Register. + \return MVENDORID Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MVENDORID(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mvendorid" : "=r"(result)); + return (result); +} + +/** + \brief Get MARCHID Register + \details Returns the content of the MARCHID Register. + \return MARCHID Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MARCHID(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, marchid" : "=r"(result)); + return (result); +} + +/** + \brief Get MIMPID Register + \details Returns the content of the MIMPID Register. + \return MIMPID Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MIMPID(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mimpid" : "=r"(result)); + return (result); +} + +/** + \brief Get MHARTID Register + \details Returns the content of the MHARTID Register. + \return MHARTID Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MHARTID(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mhartid" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPCFGx Register + \details Returns the content of the PMPCFGx Register. + \return PMPCFGx Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_PMPCFG0(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpcfg0" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPCFG1(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpcfg1" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPCFG2(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpcfg2" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPCFG3(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpcfg3" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPxCFG Register by index + \details Returns the content of the PMPxCFG Register. + \param [in] idx PMP region index + \return PMPxCFG Register value + */ +__STATIC_INLINE uint8_t __get_PMPxCFG(uint32_t idx) +{ + uint32_t pmpcfgx = 0; + + if (idx < 4) { + pmpcfgx = __get_PMPCFG0(); + } else if (idx >=4 && idx < 8) { + idx -= 4; + pmpcfgx = __get_PMPCFG1(); + } else if (idx >=8 && idx < 12) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + } else if (idx >=12 && idx < 16) { + idx -= 12; + pmpcfgx = __get_PMPCFG3(); + } else { + return 0; + } + + return (uint8_t)((pmpcfgx & (0xFF << (idx << 3))) >> (idx << 3)); +} + +/** + \brief Set PMPCFGx + \details Writes the given value to the PMPCFGx Register. + \param [in] pmpcfg PMPCFGx Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PMPCFG0(uint32_t pmpcfg) +{ + __ASM volatile("csrw pmpcfg0, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG1(uint32_t pmpcfg) +{ + __ASM volatile("csrw pmpcfg1, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG2(uint32_t pmpcfg) +{ + __ASM volatile("csrw pmpcfg2, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG3(uint32_t pmpcfg) +{ + __ASM volatile("csrw pmpcfg3, %0" : : "r"(pmpcfg)); +} + +/** + \brief Set PMPxCFG by index + \details Writes the given value to the PMPxCFG Register. + \param [in] idx PMPx region index + \param [in] pmpxcfg PMPxCFG Register value to set + */ +__STATIC_INLINE void __set_PMPxCFG(uint32_t idx, uint8_t pmpxcfg) +{ + uint32_t pmpcfgx = 0; + + if (idx < 4) { + pmpcfgx = __get_PMPCFG0(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3)); + __set_PMPCFG0(pmpcfgx); + } else if (idx >=4 && idx < 8) { + idx -= 4; + pmpcfgx = __get_PMPCFG1(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3)); + __set_PMPCFG1(pmpcfgx); + } else if (idx >=8 && idx < 12) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3)); + __set_PMPCFG2(pmpcfgx); + } else if (idx >=12 && idx < 16) { + idx -= 12; + pmpcfgx = __get_PMPCFG3(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3)); + __set_PMPCFG3(pmpcfgx); + } else { + return; + } +} + +/** + \brief Get PMPADDRx Register + \details Returns the content of the PMPADDRx Register. + \return PMPADDRx Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR0(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr0" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR1(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr1" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR2(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr2" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR3(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr3" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR4(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr4" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR5(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr5" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR6(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr6" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR7(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr7" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR8(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr8" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR9(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr9" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR10(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr10" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR11(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr11" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR12(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr12" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR13(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr13" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR14(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr14" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_PMPADDR15(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, pmpaddr15" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPADDRx Register by index + \details Returns the content of the PMPADDRx Register. + \param [in] idx PMP region index + \return PMPADDRx Register value + */ +__STATIC_INLINE uint32_t __get_PMPADDRx(uint32_t idx) +{ + switch (idx) { + case 0: return __get_PMPADDR0(); + case 1: return __get_PMPADDR1(); + case 2: return __get_PMPADDR2(); + case 3: return __get_PMPADDR3(); + case 4: return __get_PMPADDR4(); + case 5: return __get_PMPADDR5(); + case 6: return __get_PMPADDR6(); + case 7: return __get_PMPADDR7(); + case 8: return __get_PMPADDR8(); + case 9: return __get_PMPADDR9(); + case 10: return __get_PMPADDR10(); + case 11: return __get_PMPADDR11(); + case 12: return __get_PMPADDR12(); + case 13: return __get_PMPADDR13(); + case 14: return __get_PMPADDR14(); + case 15: return __get_PMPADDR15(); + default: return 0; + } +} + +/** + \brief Set PMPADDRx + \details Writes the given value to the PMPADDRx Register. + \param [in] pmpaddr PMPADDRx Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PMPADDR0(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr0, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR1(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr1, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR2(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr2, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR3(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr3, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR4(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr4, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR5(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr5, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR6(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr6, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR7(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr7, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR8(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr8, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR9(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr9, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR10(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr10, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR11(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr11, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR12(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr12, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR13(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr13, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR14(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr14, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR15(uint32_t pmpaddr) +{ + __ASM volatile("csrw pmpaddr15, %0" : : "r"(pmpaddr)); +} + +/** + \brief Set PMPADDRx by index + \details Writes the given value to the PMPADDRx Register. + \param [in] idx PMP region index + \param [in] pmpaddr PMPADDRx Register value to set + */ +__STATIC_INLINE void __set_PMPADDRx(uint32_t idx, uint32_t pmpaddr) +{ + switch (idx) { + case 0: __set_PMPADDR0(pmpaddr); break; + case 1: __set_PMPADDR1(pmpaddr); break; + case 2: __set_PMPADDR2(pmpaddr); break; + case 3: __set_PMPADDR3(pmpaddr); break; + case 4: __set_PMPADDR4(pmpaddr); break; + case 5: __set_PMPADDR5(pmpaddr); break; + case 6: __set_PMPADDR6(pmpaddr); break; + case 7: __set_PMPADDR7(pmpaddr); break; + case 8: __set_PMPADDR8(pmpaddr); break; + case 9: __set_PMPADDR9(pmpaddr); break; + case 10: __set_PMPADDR10(pmpaddr); break; + case 11: __set_PMPADDR11(pmpaddr); break; + case 12: __set_PMPADDR12(pmpaddr); break; + case 13: __set_PMPADDR13(pmpaddr); break; + case 14: __set_PMPADDR14(pmpaddr); break; + case 15: __set_PMPADDR15(pmpaddr); break; + default: return; + } +} + +/** + \brief Enable interrupts and exceptions + \details Enables interrupts and exceptions by setting the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_excp_irq(void) +{ + __enable_irq(); +} + + +/** + \brief Disable interrupts and exceptions + \details Disables interrupts and exceptions by clearing the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_excp_irq(void) +{ + __disable_irq(); +} + +#define __CSI_GCC_OUT_REG(r) "=r" (r) +#define __CSI_GCC_USE_REG(r) "r" (r) + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__ALWAYS_STATIC_INLINE void __NOP(void) +{ + __ASM volatile("nop"); +} + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__ALWAYS_STATIC_INLINE void __WFI(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __WAIT(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Doze For Interrupt + \details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __DOZE(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Stop For Interrupt + \details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __STOP(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__ALWAYS_STATIC_INLINE void __ISB(void) +{ + __ASM volatile("fence"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__ALWAYS_STATIC_INLINE void __DSB(void) +{ + __ASM volatile("fence"); +} + +/** + \brief Invalid all icache + \details invalid all icache. + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IALL(void) +{ + __ASM volatile("icache.iall"); +} + +/** + \brief Invalid Icache by addr + \details Invalid Icache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IPA(uint32_t addr) +{ + __ASM volatile("icache.ipa %0" : : "r"(addr)); +} + +/** + \brief Invalid all dcache + \details invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IALL(void) +{ + __ASM volatile("dcache.iall"); +} + +/** + \brief Clear all dcache + \details clear all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CALL(void) +{ + __ASM volatile("dcache.call"); +} + +/** + \brief Clear&invalid all dcache + \details clear & invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIALL(void) +{ + __ASM volatile("dcache.ciall"); +} + +/** + \brief Invalid Dcache by addr + \details Invalid Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IPA(uint32_t addr) +{ + __ASM volatile("dcache.ipa %0" : : "r"(addr)); +} + +/** + \brief Clear Dcache by addr + \details Clear Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CPA(uint32_t addr) +{ + __ASM volatile("dcache.cpa %0" : : "r"(addr)); +} + +/** + \brief Clear & Invalid Dcache by addr + \details Clear & Invalid Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIPA(uint32_t addr) +{ + __ASM volatile("dcache.cipa %0" : : "r"(addr)); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__ALWAYS_STATIC_INLINE void __DMB(void) +{ + __ASM volatile("fence"); +} + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __REV(uint32_t value) +{ + return __builtin_bswap32(value); +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) | + ((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8); + + return (result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE int32_t __REVSH(int32_t value) +{ + return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8)); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + */ +__ALWAYS_STATIC_INLINE void __BKPT(void) +{ + __ASM volatile("ebreak"); +} + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + + for (value >>= 1U; value; value >>= 1U) { + result <<= 1U; + result |= value & 1U; + s--; + } + + result <<= s; /* shift when v's highest bits are zero */ + + return (result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz +/** + \details This function saturates a signed value. + \param [in] x Value to be saturated + \param [in] y Bit position to saturate to [1..32] + \return Saturated value. + */ +__ALWAYS_STATIC_INLINE int32_t __SSAT(int32_t x, uint32_t y) +{ + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + + for (i = 0; i < (y - 1); i++) { + posMax = posMax * 2; + } + + if (x > 0) { + posMax = (posMax - 1); + + if (x > posMax) { + x = posMax; + } + +// x &= (posMax * 2 + 1); + } else { + negMin = -posMax; + + if (x < negMin) { + x = negMin; + } + +// x &= (posMax * 2 - 1); + } + + return (x); +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE uint32_t __USAT(uint32_t value, uint32_t sat) +{ + uint32_t result; + + if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Unsigned Saturate for internal use + \details Saturates an unsigned value, should not call directly. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE uint32_t __IUSAT(uint32_t value, uint32_t sat) +{ + uint32_t result; + + if (value & 0x80000000) { /* only overflow set bit-31 */ + result = 0; + } else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Rotate Right with Extend + \details This function moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \note carry input will always 0. + \param [in] op1 Value to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE uint32_t __RRX(uint32_t op1) +{ + return 0; +} + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] addr Pointer to location + \return value of type uint8_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile("lb %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] addr Pointer to location + \return value of type uint16_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile("lh %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] addr Pointer to location + \return value of type uint32_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile("lw %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return (result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile("sb %1, 0(%0)" :: "r"(addr), "r"((uint32_t)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile("sh %1, 0(%0)" :: "r"(addr), "r"((uint32_t)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ + __ASM volatile("sw %1, 0(%0)" :: "r"(addr), "r"(value) : "memory"); +} + +/*@}*/ /* end of group CSI_Core_InstructionInterface */ + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CSI_SIMD_intrinsics CSI SIMD Intrinsics + Access to dedicated SIMD instructions \n + Single Instruction Multiple Data (SIMD) extensions are provided to simplify development of application software. SIMD extensions increase the processing capability without materially increasing the power consumption. The SIMD extensions are completely transparent to the operating system (OS), allowing existing OS ports to be used. + + @{ +*/ + +/** + \brief Halfword packing instruction. Combines bits[15:0] of val1 with bits[31:16] + of val2 levitated with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be left-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for left-shifting val2. Value range [0..31]. + \return the combination of halfwords. + \remark + res[15:0] = val1[15:0] \n + res[31:16] = val2[31:16] << val3 + */ +__ALWAYS_STATIC_INLINE uint32_t __PKHBT(uint32_t val1, uint32_t val2, uint32_t val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0x0000FFFF) | (((int32_t)(val2) << val3) & (int32_t)0xFFFF0000)); +} + +/** + \brief Halfword packing instruction. Combines bits[31:16] of val1 with bits[15:0] + of val2 right-shifted with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be right-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for right-shifting val2. Value range [1..32]. + \return the combination of halfwords. + \remark + res[15:0] = val2[15:0] >> val3 \n + res[31:16] = val1[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __PKHTB(uint32_t val1, uint32_t val2, uint32_t val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0xFFFF0000) | (((int32_t)(val2) >> val3) & (int32_t)0x0000FFFF)); +} + +/** + \brief Dual 16-bit signed saturate. + \details This function saturates a signed value. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the sum of the absolute differences of the following bytes, added to the accumulation value:\n + the signed saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the signed saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE uint32_t __SSAT16(int32_t x, const uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __SSAT((((int32_t)x << 16) >> 16), y) & (int32_t)0x0000FFFF; + s = __SSAT((((int32_t)x) >> 16), y) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturate. + \details This function enables you to saturate two signed 16-bit values to a selected unsigned range. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the saturation of the two signed 16-bit values, as non-negative values: + the saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE uint32_t __USAT16(uint32_t x, const uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT(((x << 16) >> 16), y) & 0x0000FFFF; + s = __IUSAT(((x) >> 16), y) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit saturating addition. + \details This function enables you to perform four 8-bit integer additions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __QADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) + (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating addition. + \details This function enables you to perform four unsigned 8-bit integer additions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) + ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) + ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) + ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) + ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed addition. + \details This function performs four 8-bit signed integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __SADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition. + \details This function performs four unsigned 8-bit integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) + ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) + ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) + ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) + ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit saturating subtract. + \details This function enables you to perform four 8-bit integer subtractions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) - (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating subtraction. + \details This function enables you to perform four unsigned 8-bit integer subtractions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit unsigned integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) - ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) - ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) - ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) - ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed subtraction. + \details This function enables you to perform four 8-bit signed integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtract. + \details This function enables you to perform four 8-bit unsigned integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __USUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences together, returning the result as a single unsigned integer. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.\n + The sum is returned as a single unsigned integer. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + res[31:0] = absdiff1 + absdiff2 + absdiff3 + absdiff4 + */ +__ALWAYS_STATIC_INLINE uint32_t __USAD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return (u + t + s + r); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference with 32-bit accumulate. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences to a 32-bit accumulate operand. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \param [in] sum accumulation value. + \return the sum of the absolute differences of the following bytes, added to the accumulation value: + the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + sum = absdiff1 + absdiff2 + absdiff3 + absdiff4 \n + res[31:0] = sum[31:0] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __USADA8(uint32_t x, uint32_t y, uint32_t sum) +{ + int32_t r, s, t, u; + +#ifdef __cplusplus + r = (abs((long long)((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs((long long)((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs((long long)((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs((long long)((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#else + r = (abs(((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs(((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs(((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs(((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#endif + return (u + t + s + r + sum); +} + +/** + \brief Dual 16-bit saturating addition. + \details This function enables you to perform two 16-bit integer arithmetic additions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __QADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition. + \details This function enables you to perform two unsigned 16-bit integer additions, saturating + the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The results are saturated to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT((((x << 16) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition. + \details This function enables you to perform two 16-bit signed integer additions. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __SADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition + \details This function enables you to perform two 16-bit unsigned integer additions. + \param [in] x first two 16-bit summands for each addition. + \param [in] y second two 16-bit summands for each addition. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = (((x << 16) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + + +/** + \brief Dual 16-bit signed addition with halved results. + \details This function enables you to perform two signed 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHADD16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition with halved results. + \details This function enables you to perform two unsigned 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHADD16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition with halved results. + \details This function enables you to perform four unsigned 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) + ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) + ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) + ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) + ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit saturating subtract. + \details This function enables you to perform two 16-bit integer subtractions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction. + \details This function enables you to perform two unsigned 16-bit integer subtractions, + saturating the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit operands for each subtraction. + \param [in] y second two 16-bit operands for each subtraction. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction. + \details This function enables you to perform two 16-bit signed integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtract. + \details This function enables you to perform two 16-bit unsigned integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __USUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction with halved results. + \details This function enables you to perform two signed 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction with halved results. + \details This function enables you to perform two unsigned 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtraction with halved results. + \details This function enables you to perform four unsigned 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) - ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) - ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) - ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) - ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit add and subtract with exchange. + \details This function enables you to exchange the halfwords of the one operand, + then add the high halfwords and subtract the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __QASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition and subtraction with exchange. + \details This function enables you to exchange the halfwords of the second operand and + perform one unsigned 16-bit integer addition and one unsigned 16-bit subtraction, + saturating the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit addition and subtraction with exchange. + \details It enables you to exchange the halfwords of the second operand, add the high halfwords + and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with exchange. + \details This function enables you to exchange the two halfwords of the second operand, + add the high halfwords and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition and subtraction with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one + signed 16-bit integer addition and one signed 16-bit subtraction, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + add the high halfwords and subtract the low halfwords, halving the results. + \param [in] x first operand for the subtraction in the low halfword, and + the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, and + the second operand for the addition in the low halfword. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit subtract and add with exchange. + \details This function enables you to exchange the halfwords of one operand, + then subtract the high halfwords and add the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction and addition with exchange. + \details This function enables you to exchange the halfwords of the second operand and perform + one unsigned 16-bit integer subtraction and one unsigned 16-bit addition, saturating + the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit unsigned subtract and add with exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __USAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) + ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction and addition with exchange. + \details This function enables you to exchange the two halfwords of one operand and perform one + 16-bit integer subtraction and one 16-bit addition. + \param [in] x first operand for the addition in the low halfword, and the first operand + for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and the second + operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + + +/** + \brief Dual 16-bit signed subtraction and addition with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one signed + 16-bit integer subtraction and one signed 16-bit addition, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction and addition with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords, halving the results. + \param [in] x first operand for the addition in the low halfword, and + the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and + the second operand for the subtraction in the low halfword. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed multiply with exchange returning difference. + \details This function enables you to perform two 16-bit signed multiplications, subtracting + one of the products from the other. The halfwords of the second operand are exchanged + before performing the arithmetic. This produces top * bottom and bottom * top multiplication. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUSDX(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + +/** + \brief Sum of dual 16-bit signed multiply with exchange. + \details This function enables you to perform two 16-bit signed multiplications with exchanged + halfwords of the second operand, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications with exchanged halfwords of the second operand. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUADX(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + + +/** + \brief Saturating add. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 + SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QADD(int32_t x, int32_t y) +{ + int32_t result; + + if (y >= 0) { + if ((int32_t)((uint32_t)x + (uint32_t)y) >= x) { + result = x + y; + } else { + result = 0x7FFFFFFF; + } + } else { + if ((int32_t)((uint32_t)x + (uint32_t)y) < x) { + result = x + y; + } else { + result = 0x80000000; + } + } + + return result; +} + +/** + \brief Saturating subtract. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 - SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QSUB(int32_t x, int32_t y) +{ + int64_t tmp; + int32_t result; + + tmp = (int64_t)x - (int64_t)y; + + if (tmp > 0x7fffffff) { + tmp = 0x7fffffff; + } else if (tmp < (-2147483647 - 1)) { + tmp = -2147483647 - 1; + } + + result = tmp; + return result; +} + +/** + \brief Dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, + adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLAD(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Pre-exchanged dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications with exchanged + halfwords of the second operand, adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication with exchanged halfwords of the second + operand added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLADX(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to perform two 16-bit signed multiplications, take the + difference of the products, subtracting the high halfword product from the low + halfword product, and add the difference to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLSD(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to exchange the halfwords in the second operand, then perform two 16-bit + signed multiplications. The difference of the products is added to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLSDX(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with single 64-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, adding both results + to a 64-bit accumulate operand. Overflow is only possible as a result of the 64-bit addition. + This overflow is not detected if it occurs. Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLALD(uint32_t x, uint32_t y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange with single 64-bit accumulator. + \details This function enables you to exchange the halfwords of the second operand, and perform two + signed 16-bit multiplications, adding both results to a 64-bit accumulate operand. Overflow + is only possible as a result of the 64-bit addition. This overflow is not detected if it occurs. + Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLALDX(uint32_t x, uint32_t y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief dual 16-bit signed multiply subtract with 64-bit accumulate. + \details This function It enables you to perform two 16-bit signed multiplications, take the difference + of the products, subtracting the high halfword product from the low halfword product, and add the + difference to a 64-bit accumulate operand. Overflow cannot occur during the multiplications or the + subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow is not + detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLSLD(uint32_t x, uint32_t y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 64-bit accumulate. + \details This function enables you to exchange the halfwords of the second operand, perform two 16-bit multiplications, + adding the difference of the products to a 64-bit accumulate operand. Overflow cannot occur during the + multiplications or the subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow + is not detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLSLDX(uint32_t x, uint32_t y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief 32-bit signed multiply with 32-bit truncated accumulator. + \details This function enables you to perform a signed 32-bit multiplications, adding the most + significant 32 bits of the 64-bit result to a 32-bit accumulate operand. + \param [in] x first operand for multiplication. + \param [in] y second operand for multiplication. + \param [in] sum accumulate value. + \return the product of multiplication (most significant 32 bits) is added to the accumulate value, as a 32-bit integer. + \remark + p = val1 * val2 \n + res[31:0] = p[63:32] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMMLA(int32_t x, int32_t y, int32_t sum) +{ + return (uint32_t)((int32_t)((int64_t)((int64_t)x * (int64_t)y) >> 32) + sum); +} + +/** + \brief Sum of dual 16-bit signed multiply. + \details This function enables you to perform two 16-bit signed multiplications, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUAD(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual 16-bit signed multiply returning difference. + \details This function enables you to perform two 16-bit signed multiplications, taking the difference + of the products by subtracting the high halfword product from the low halfword product. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUSD(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual extracted 8-bit to 16-bit signed addition. + \details This function enables you to extract two 8-bit values from the second operand (at bit positions + [7:0] and [23:16]), sign-extend them to 16-bits each, and add the results to the first operand. + \param [in] x values added to the sign-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and sign-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and sign-extended prior to the addition. + \remark + res[15:0] = val1[15:0] + SignExtended(val2[7:0]) \n + res[31:16] = val1[31:16] + SignExtended(val2[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __SXTAB16(uint32_t x, uint32_t y) +{ + return ((uint32_t)((((((int32_t)y << 24) >> 24) + (((int32_t)x << 16) >> 16)) & (int32_t)0x0000FFFF) | + (((((int32_t)y << 8) >> 8) + (((int32_t)x >> 16) << 16)) & (int32_t)0xFFFF0000))); +} + +/** + \brief Extracted 16-bit to 32-bit unsigned addition. + \details This function enables you to extract two 8-bit values from one operand, zero-extend + them to 16 bits each, and add the results to two 16-bit values from another operand. + \param [in] x values added to the zero-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and zero-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and zero-extended prior to the addition. + \remark + res[15:0] = ZeroExt(val2[7:0] to 16 bits) + val1[15:0] \n + res[31:16] = ZeroExt(val2[31:16] to 16 bits) + val1[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UXTAB16(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((y << 24) >> 24) + ((x << 16) >> 16)) & 0x0000FFFF) | + ((((y << 8) >> 8) + ((x >> 16) << 16)) & 0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and sign extend each to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and sign-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be sign-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __SXTB16(uint32_t x) +{ + return ((uint32_t)(((((int32_t)x << 24) >> 24) & (int32_t)0x0000FFFF) | + ((((int32_t)x << 8) >> 8) & (int32_t)0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and zero-extend to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and zero-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be zero-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __UXTB16(uint32_t x) +{ + return ((uint32_t)((((x << 24) >> 24) & 0x0000FFFF) | + (((x << 8) >> 8) & 0xFFFF0000))); +} + +#endif /* _CSI_RV32_GCC_H_ */ diff --git a/bsp/thead-smart/drivers/drv_common.h b/bsp/thead-smart/drivers/drv_common.h new file mode 100644 index 0000000000..bc43b11e2c --- /dev/null +++ b/bsp/thead-smart/drivers/drv_common.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen Header File for Common Driver + */ + +#ifndef _DRV_COMMON_H_ +#define _DRV_COMMON_H_ + +#include <stdint.h> +#include <drv_errno.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/// \details driver handle +typedef void *drv_handle_t; + +#ifndef CONFIG_PARAM_NOT_CHECK +#define HANDLE_PARAM_CHK(para, err) \ + do { \ + if ((int32_t)para == (int32_t)NULL) { \ + return (err); \ + } \ + } while (0) + +#define HANDLE_PARAM_CHK_NORETVAL(para, err) \ + do { \ + if ((int32_t)para == (int32_t)NULL) { \ + return; \ + } \ + } while (0) +#else +#define HANDLE_PARAM_CHK(para, err) +#define HANDLE_PARAM_CHK_NORETVAL(para, err) +#endif + +/** +\brief General power states +*/ +typedef enum +{ + DRV_POWER_OFF, ///< Power off: no operation possible + DRV_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events + DRV_POWER_FULL, ///< Power on: full operation at maximum performance + DRV_POWER_SUSPEND, ///< Power suspend: power saving operation +} csi_power_stat_e; + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_COMMON_H */ + diff --git a/bsp/thead-smart/drivers/drv_errno.h b/bsp/thead-smart/drivers/drv_errno.h new file mode 100644 index 0000000000..33fe6574de --- /dev/null +++ b/bsp/thead-smart/drivers/drv_errno.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header file for error num + */ + + +#ifndef _DRV_ERRNO_H_ +#define _DRV_ERRNO_H_ + +#include <errno.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define ERRNO_DRV_START 0X80 + +/* driver General error codes */ +typedef enum +{ + DRV_ERROR = ERRNO_DRV_START, ///< Unspecified error + DRV_ERROR_BUSY, ///< Driver is busy + DRV_ERROR_TIMEOUT, ///< Timeout occurred + DRV_ERROR_UNSUPPORTED, ///< Operation not supported + DRV_ERROR_PARAMETER, ///< Parameter error + DRV_ERROR_SPECIFIC ///< Start of driver specific errors +} drv_err_e; + + +/** Get error type */ +#define GET_ERROR_TYPE(errno) \ + (error & 0xFF000000 >> 24) +/** Get error module */ +#define GET_ERROR_MODULE(error) \ + (error & 0x00FF0000 >> 16) +/** Get error API */ +#define GET_ERROR_API(error) \ + (error & 0x0000FF00 >> 8) +/** Get errno */ +#define GET_ERROR_NUM(error) \ + (error & 0x000000FF) + +#ifndef CSI_DRV_ERRNO_BASE +#define CSI_DRV_ERRNO_BASE 0x81000000 +#endif + +/** driver module id definition*/ +#define CSI_DRV_ERRNO_GPIO_BASE 0x81010000 +#define CSI_DRV_ERRNO_USART_BASE 0x81020000 +#define CSI_DRV_ERRNO_SPI_BASE 0x81030000 +#define CSI_DRV_ERRNO_IIC_BASE 0x81040000 +#define CSI_DRV_ERRNO_PWM_BASE 0x81050000 +#define CSI_DRV_ERRNO_RTC_BASE 0x81060000 +#define CSI_DRV_ERRNO_TIMER_BASE 0x81070000 +#define CSI_DRV_ERRNO_WDT_BASE 0x81080000 +#define CSI_DRV_ERRNO_AES_BASE 0x81090000 +#define CSI_DRV_ERRNO_CRC_BASE 0x810A0000 +#define CSI_DRV_ERRNO_RSA_BASE 0x810B0000 +#define CSI_DRV_ERRNO_SHA_BASE 0x810C0000 +#define CSI_DRV_ERRNO_TRNG_BASE 0x810D0000 +#define CSI_DRV_ERRNO_EFLASH_BASE 0x810E0000 +#define CSI_DRV_ERRNO_DMA_BASE 0x810F0000 +#define CSI_DRV_ERRNO_NORFLASH_BASE 0x81100000 +#define CSI_DRV_ERRNO_INTC_BASE 0x81110000 +#define CSI_DRV_ERRNO_SPU_BASE 0x81120000 +#define CSI_DRV_ERRNO_ADC_BASE 0x81130000 +#define CSI_DRV_ERRNO_PMU_BASE 0x81140000 +#define CSI_DRV_ERRNO_BMU_BASE 0x81150000 +#define CSI_DRV_ERRNO_ETB_BASE 0x81160000 +#define CSI_DRV_ERRNO_I2S_BASE 0x81170000 +#define CSI_DRV_ERRNO_USI_BASE 0x81180000 +#define CSI_DRV_ERRNO_SPIFLASH_BASE 0x81190000 +#define CSI_DRV_ERRNO_ACMP_BASE 0x811A0000 +#define CSI_DRV_ERRNO_MAILBOX_BASE 0x811B0000 +#define CSI_DRV_ERRNO_EFUSEC_BASE 0x811C0000 +#define CSI_DRV_ERRNO_CODEC_BASE 0x811D0000 +#define CSI_DRV_ERRNO_DPU_BASE 0x811E0000 +#define CSI_DRV_ERRNO_VPU_BASE 0x811F0000 +#define CSI_DRV_ERRNO_CAMERA_BASE 0x81200000 +#define CSI_DRV_ERRNO_MIPI_CSI_BASE 0x81210000 +#define CSI_DRV_ERRNO_MIPI_CSI_READER_BASE 0x81220000 +#define CSI_DRV_ERRNO_GMAC_BASE 0x81230000 +#define CSI_DRV_ERRNO_ETHPHY_BASE 0x81240000 +#define CSI_DRV_ERRNO_QW_EFUSE_BASE 0x81250000 +#define CSI_DRV_ERRNO_RESET_BASE 0x81260000 + +#ifdef __cplusplus +} +#endif + +#endif /* CSI_DRV_ERRNO_H */ diff --git a/bsp/thead-smart/drivers/drv_gpio.h b/bsp/thead-smart/drivers/drv_gpio.h new file mode 100644 index 0000000000..1ee5944a69 --- /dev/null +++ b/bsp/thead-smart/drivers/drv_gpio.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header file for gpio driver + */ + +#ifndef _CSI_GPIO_H_ +#define _CSI_GPIO_H_ + + +#include <stdint.h> +#include <stdbool.h> +#include <drv_common.h> + +#ifdef __cplusplus +extern "C" { +#endif +/// definition for gpio pin handle. +typedef void *gpio_pin_handle_t; + +/****** GPIO specific error codes *****/ +typedef enum +{ + GPIO_ERROR_MODE = (DRV_ERROR_SPECIFIC + 1), ///< Specified Mode not supported + GPIO_ERROR_DIRECTION, ///< Specified direction not supported + GPIO_ERROR_IRQ_MODE, ///< Specified irq mode not supported +} gpio_error_e; + +/*----- GPIO Control Codes: Mode -----*/ +typedef enum +{ + GPIO_MODE_PULLNONE = 0, ///< pull none for input + GPIO_MODE_PULLUP, ///< pull up for input + GPIO_MODE_PULLDOWN, ///< pull down for input + GPIO_MODE_OPEN_DRAIN, ///< open drain mode for output + GPIO_MODE_PUSH_PULL, ///< push-pull mode for output +} gpio_mode_e; + +/*----- GPIO Control Codes: Mode Parameters: Data Bits -----*/ +typedef enum +{ + GPIO_DIRECTION_INPUT = 0, ///< gpio as input + GPIO_DIRECTION_OUTPUT, ///< gpio as output +} gpio_direction_e; + +/*----- GPIO Control Codes: Mode Parameters: Parity -----*/ +typedef enum +{ + GPIO_IRQ_MODE_RISING_EDGE = 0, ///< interrupt mode for rising edge + GPIO_IRQ_MODE_FALLING_EDGE, ///< interrupt mode for falling edge + GPIO_IRQ_MODE_DOUBLE_EDGE, ///< interrupt mode for double edge + GPIO_IRQ_MODE_LOW_LEVEL, ///< interrupt mode for low level + GPIO_IRQ_MODE_HIGH_LEVEL, ///< interrupt mode for high level +} gpio_irq_mode_e; + +typedef void (*gpio_event_cb_t)(int32_t idx); ///< gpio Event call back. + +/** + \brief Initialize GPIO handle. + \param[in] gpio_pin gpio pin idx. + \param[in] cb_event event callback function \ref gpio_event_cb_t + \return gpio_pin_handle +*/ +gpio_pin_handle_t csi_gpio_pin_initialize(int32_t gpio_pin, gpio_event_cb_t cb_event); + +/** + \brief De-initialize GPIO pin handle.stops operation and releases the software resources used by the handle. + \param[in] handle gpio pin handle to operate. + \return error code +*/ +int32_t csi_gpio_pin_uninitialize(gpio_pin_handle_t handle); + +/** + \brief control gpio power. + \param[in] handle gpio handle to operate. + \param[in] state power state.\ref csi_power_stat_e. + \return error code +*/ +int32_t csi_gpio_power_control(gpio_pin_handle_t handle, csi_power_stat_e state); + +/** + \brief config pin mode + \param[in] pin gpio pin handle to operate. + \param[in] mode \ref gpio_mode_e + \return error code +*/ +int32_t csi_gpio_pin_config_mode(gpio_pin_handle_t handle, + gpio_mode_e mode); + +/** + \brief config pin direction + \param[in] pin gpio pin handle to operate. + \param[in] dir \ref gpio_direction_e + \return error code +*/ +int32_t csi_gpio_pin_config_direction(gpio_pin_handle_t handle, + gpio_direction_e dir); + +/** + \brief config pin + \param[in] pin gpio pin handle to operate. + \param[in] mode \ref gpio_mode_e + \param[in] dir \ref gpio_direction_e + \return error code +*/ +int32_t csi_gpio_pin_config(gpio_pin_handle_t handle, + gpio_mode_e mode, + gpio_direction_e dir); + +/** + \brief Set one or zero to the selected GPIO pin. + \param[in] pin gpio pin handle to operate. + \param[in] value value to be set + \return error code +*/ +int32_t csi_gpio_pin_write(gpio_pin_handle_t handle, bool value); + +/** + \brief Get the value of selected GPIO pin. + \param[in] pin gpio pin handle to operate. + \param[out] value buffer to store the pin value + \return error code +*/ +int32_t csi_gpio_pin_read(gpio_pin_handle_t handle, bool *value); + +/** + \brief set GPIO interrupt mode. + \param[in] pin gpio pin handle to operate. + \param[in] mode irq mode to be set + \param[in] enable enable flag + \return error code +*/ +int32_t csi_gpio_pin_set_irq(gpio_pin_handle_t handle, gpio_irq_mode_e mode, bool enable); + + +#ifdef __cplusplus +} +#endif + +#endif /* _CSI_GPIO_H_ */ diff --git a/bsp/thead-smart/drivers/drv_irq.h b/bsp/thead-smart/drivers/drv_irq.h new file mode 100644 index 0000000000..80c2edddd9 --- /dev/null +++ b/bsp/thead-smart/drivers/drv_irq.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header File for IRQ Driver + */ + +#include <stdint.h> + +/** + \brief enable irq. + \param[in] irq_num Number of IRQ. + \return None. +*/ +void drv_irq_enable(uint32_t irq_num); + +/** + \brief disable irq. + \param[in] irq_num Number of IRQ. + \return None. +*/ +void drv_irq_disable(uint32_t irq_num); + +/** + \brief register irq handler. + \param[in] irq_num Number of IRQ. + \param[in] irq_handler IRQ Handler. + \return None. +*/ +void drv_irq_register(uint32_t irq_num, void *irq_handler); + +/** + \brief unregister irq handler. + \param[in] irq_num Number of IRQ. + \param[in] irq_handler IRQ Handler. + \return None. +*/ +void drv_irq_unregister(uint32_t irq_num); diff --git a/bsp/thead-smart/drivers/drv_timer.h b/bsp/thead-smart/drivers/drv_timer.h new file mode 100644 index 0000000000..12feda3c4c --- /dev/null +++ b/bsp/thead-smart/drivers/drv_timer.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen timer driver header file + */ + +/****************************************************************************** + * @file drv_timer.h + * @brief header file for timer driver + * @version V1.0 + * @date 02. June 2017 + * @model timer + ******************************************************************************/ + +#ifndef _CSI_TIMER_H_ +#define _CSI_TIMER_H_ + + +#include <stdint.h> +#include <drv_common.h> + +#ifdef __cplusplus +extern "C" { +#endif +/// definition for timer handle. +typedef void *timer_handle_t; + +/*----- TIMER Control Codes: Mode -----*/ +typedef enum +{ + TIMER_MODE_FREE_RUNNING = 0, ///< free running mode + TIMER_MODE_RELOAD ///< reload mode +} timer_mode_e; + +/** +\brief TIMER Status +*/ +typedef struct +{ + uint32_t active : 1; ///< timer active flag + uint32_t timeout : 1; ///< timeout flag +} timer_status_t; + +/** +\brief TIMER Event +*/ +typedef enum +{ + TIMER_EVENT_TIMEOUT = 0 ///< time out event +} timer_event_e; + +typedef void (*timer_event_cb_t)(int32_t idx, timer_event_e event); ///< Pointer to \ref timer_event_cb_t : TIMER Event call back. + +/** + \brief Initialize TIMER Interface. 1. Initializes the resources needed for the TIMER interface 2.registers event callback function + \param[in] idx timer index + \param[in] cb_event event call back function \ref timer_event_cb_t + \param[in] cb_arg arguments of cb_event + \return pointer to timer instance +*/ +timer_handle_t csi_timer_initialize(int32_t idx, timer_event_cb_t cb_event); + +/** + \brief De-initialize TIMER Interface. stops operation and releases the software resources used by the interface + \param[in] handle timer handle to operate. + \return error code +*/ +int32_t csi_timer_uninitialize(timer_handle_t handle); + +/** + \brief control timer power. + \param[in] handle timer handle to operate. + \param[in] state power state.\ref csi_power_stat_e. + \return error code +*/ +int32_t csi_timer_power_control(timer_handle_t handle, csi_power_stat_e state); + +/** + \brief config timer mode. + \param[in] handle timer handle to operate. + \param[in] mode \ref timer_mode_e + \return error code +*/ +int32_t csi_timer_config(timer_handle_t handle, timer_mode_e mode); + +/** + \brief Set timeout just for the reload mode. + \param[in] handle timer handle to operate. + \param[in] timeout the timeout value in microseconds(us). + \return error code +*/ +int32_t csi_timer_set_timeout(timer_handle_t handle, uint32_t timeout); + +/** + \brief Start timer. + \param[in] handle timer handle to operate. + \return error code +*/ +int32_t csi_timer_start(timer_handle_t handle); + +/** + \brief Stop timer. + \param[in] handle timer handle to operate. + \return error code +*/ +int32_t csi_timer_stop(timer_handle_t handle); + +/** + \brief suspend timer. + \param[in] handle timer handle to operate. + \return error code +*/ +int32_t csi_timer_suspend(timer_handle_t handle); + +/** + \brief resume timer. + \param[in] handle timer handle to operate. + \return error code +*/ +int32_t csi_timer_resume(timer_handle_t handle); + +/** + \brief get timer current value + \param[in] handle timer handle to operate. + \param[out] value timer current value + \return error code +*/ +int32_t csi_timer_get_current_value(timer_handle_t handle, uint32_t *value); + +/** + \brief Get TIMER status. + \param[in] handle timer handle to operate. + \return TIMER status \ref timer_status_t +*/ +timer_status_t csi_timer_get_status(timer_handle_t handle); + +/** + \brief get timer reload value + \param[in] handle timer handle to operate. + \param[out] value timer reload value + \return error code +*/ +int32_t csi_timer_get_load_value(timer_handle_t handle, uint32_t *value); + +#ifdef __cplusplus +} +#endif + +#endif /* _CSI_TIMER_H_ */ + diff --git a/bsp/thead-smart/drivers/drv_usart.h b/bsp/thead-smart/drivers/drv_usart.h new file mode 100644 index 0000000000..57a69fead6 --- /dev/null +++ b/bsp/thead-smart/drivers/drv_usart.h @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header file for usart driver + */ + +#ifndef _CSI_USART_H_ +#define _CSI_USART_H_ + + +#include <drv_common.h> + +#ifdef __cplusplus +extern "C" { +#endif +/// definition for usart handle. +typedef void *usart_handle_t; + +/****** USART specific error codes *****/ +typedef enum +{ + USART_ERROR_MODE = (DRV_ERROR_SPECIFIC + 1), ///< Specified Mode not supported + USART_ERROR_BAUDRATE, ///< Specified baudrate not supported + USART_ERROR_DATA_BITS, ///< Specified number of Data bits not supported + USART_ERROR_PARITY, ///< Specified Parity not supported + USART_ERROR_STOP_BITS, ///< Specified number of Stop bits not supported + USART_ERROR_FLOW_CONTROL, ///< Specified Flow Control not supported + USART_ERROR_CPOL, ///< Specified Clock Polarity not supported + USART_ERROR_CPHA ///< Specified Clock Phase not supported +} usart_error_e; + +/*----- USART Control Codes: Mode -----*/ +typedef enum +{ + USART_MODE_ASYNCHRONOUS = 0, ///< USART (Asynchronous) + USART_MODE_SYNCHRONOUS_MASTER, ///< Synchronous Master + USART_MODE_SYNCHRONOUS_SLAVE, ///< Synchronous Slave (external clock signal) + USART_MODE_SINGLE_WIRE, ///< USART Single-wire (half-duplex) + USART_MODE_SINGLE_IRDA, ///< UART IrDA + USART_MODE_SINGLE_SMART_CARD, ///< UART Smart Card +} usart_mode_e; + +/*----- USART Control Codes: Mode Parameters: Data Bits -----*/ +typedef enum +{ + USART_DATA_BITS_5 = 0, ///< 5 Data bits + USART_DATA_BITS_6, ///< 6 Data bit + USART_DATA_BITS_7, ///< 7 Data bits + USART_DATA_BITS_8, ///< 8 Data bits (default) + USART_DATA_BITS_9 ///< 9 Data bits +} usart_data_bits_e; + +/*----- USART Control Codes: Mode Parameters: Parity -----*/ +typedef enum +{ + USART_PARITY_NONE = 0, ///< No Parity (default) + USART_PARITY_EVEN, ///< Even Parity + USART_PARITY_ODD, ///< Odd Parity + USART_PARITY_1, ///< Parity forced to 1 + USART_PARITY_0 ///< Parity forced to 0 +} usart_parity_e; + +/*----- USART Control Codes: Mode Parameters: Stop Bits -----*/ +typedef enum +{ + USART_STOP_BITS_1 = 0, ///< 1 Stop bit (default) + USART_STOP_BITS_2, ///< 2 Stop bits + USART_STOP_BITS_1_5, ///< 1.5 Stop bits + USART_STOP_BITS_0_5 ///< 0.5 Stop bits +} usart_stop_bits_e; + +/*----- USART Control Codes: Mode Parameters: Clock Polarity (Synchronous mode) -----*/ +typedef enum +{ + USART_CPOL0 = 0, ///< CPOL = 0 (default). data are captured on rising edge (low->high transition) + USART_CPOL1 ///< CPOL = 1. data are captured on falling edge (high->lowh transition) +} usart_cpol_e; + +/*----- USART Control Codes: Mode Parameters: Clock Phase (Synchronous mode) -----*/ +typedef enum +{ + USART_CPHA0 = 0, ///< CPHA = 0 (default). sample on first (leading) edge + USART_CPHA1 ///< CPHA = 1. sample on second (trailing) edge +} usart_cpha_e; + +/*----- USART Control Codes: flush data type-----*/ +typedef enum +{ + USART_FLUSH_WRITE, + USART_FLUSH_READ +} usart_flush_type_e; + +/*----- USART Control Codes: flow control type-----*/ +typedef enum +{ + USART_FLOWCTRL_NONE, + USART_FLOWCTRL_CTS, + USART_FLOWCTRL_RTS, + USART_FLOWCTRL_CTS_RTS +} usart_flowctrl_type_e; + +/*----- USART Modem Control -----*/ +typedef enum +{ + USART_RTS_CLEAR, ///< Deactivate RTS + USART_RTS_SET, ///< Activate RTS + USART_DTR_CLEAR, ///< Deactivate DTR + USART_DTR_SET ///< Activate DTR +} usart_modem_ctrl_e; + +/*----- USART Modem Status -----*/ +typedef struct +{ + uint32_t cts : 1; ///< CTS state: 1=Active, 0=Inactive + uint32_t dsr : 1; ///< DSR state: 1=Active, 0=Inactive + uint32_t dcd : 1; ///< DCD state: 1=Active, 0=Inactive + uint32_t ri : 1; ///< RI state: 1=Active, 0=Inactive +} usart_modem_stat_t; + +/*----- USART Control Codes: on-off intrrupte type-----*/ +typedef enum +{ + USART_INTR_WRITE, + USART_INTR_READ +} usart_intr_type_e; + +/** +\brief USART Status +*/ +typedef struct { + uint32_t tx_busy : 1; ///< Transmitter busy flag + uint32_t rx_busy : 1; ///< Receiver busy flag + uint32_t tx_underflow : 1; ///< Transmit data underflow detected (cleared on start of next send operation)(Synchronous Slave) + uint32_t rx_overflow : 1; ///< Receive data overflow detected (cleared on start of next receive operation) + uint32_t rx_break : 1; ///< Break detected on receive (cleared on start of next receive operation) + uint32_t rx_framing_error : 1; ///< Framing error detected on receive (cleared on start of next receive operation) + uint32_t rx_parity_error : 1; ///< Parity error detected on receive (cleared on start of next receive operation) + uint32_t tx_enable : 1; ///< Transmitter enable flag + uint32_t rx_enable : 1; ///< Receiver enbale flag +} usart_status_t; + +/****** USART Event *****/ +typedef enum +{ + USART_EVENT_SEND_COMPLETE = 0, ///< Send completed; however USART may still transmit data + USART_EVENT_RECEIVE_COMPLETE = 1, ///< Receive completed + USART_EVENT_TRANSFER_COMPLETE = 2, ///< Transfer completed + USART_EVENT_TX_COMPLETE = 3, ///< Transmit completed (optional) + USART_EVENT_TX_UNDERFLOW = 4, ///< Transmit data not available (Synchronous Slave) + USART_EVENT_RX_OVERFLOW = 5, ///< Receive data overflow + USART_EVENT_RX_TIMEOUT = 6, ///< Receive character timeout (optional) + USART_EVENT_RX_BREAK = 7, ///< Break detected on receive + USART_EVENT_RX_FRAMING_ERROR = 8, ///< Framing error detected on receive + USART_EVENT_RX_PARITY_ERROR = 9, ///< Parity error detected on receive + USART_EVENT_CTS = 10, ///< CTS state changed (optional) + USART_EVENT_DSR = 11, ///< DSR state changed (optional) + USART_EVENT_DCD = 12, ///< DCD state changed (optional) + USART_EVENT_RI = 13, ///< RI state changed (optional) + USART_EVENT_RECEIVED = 14, ///< Data Received, only in usart fifo, call receive()/transfer() get the data +} usart_event_e; + +typedef void (*usart_event_cb_t)(int32_t idx, usart_event_e event); ///< Pointer to \ref usart_event_cb_t : USART Event call back. + +/** +\brief USART Driver Capabilities. +*/ +typedef struct { + uint32_t asynchronous : 1; ///< supports UART (Asynchronous) mode + uint32_t synchronous_master : 1; ///< supports Synchronous Master mode + uint32_t synchronous_slave : 1; ///< supports Synchronous Slave mode + uint32_t single_wire : 1; ///< supports UART Single-wire mode + uint32_t irda : 1; ///< supports UART IrDA mode + uint32_t smart_card : 1; ///< supports UART Smart Card mode + uint32_t smart_card_clock : 1; ///< Smart Card Clock generator available + uint32_t flow_control_rts : 1; ///< RTS Flow Control available + uint32_t flow_control_cts : 1; ///< CTS Flow Control available + uint32_t event_tx_complete : 1; ///< Transmit completed event: \ref USART_EVENT_TX_COMPLETE + uint32_t event_rx_timeout : 1; ///< Signal receive character timeout event: \ref USART_EVENT_RX_TIMEOUT + uint32_t rts : 1; ///< RTS Line: 0=not available, 1=available + uint32_t cts : 1; ///< CTS Line: 0=not available, 1=available + uint32_t dtr : 1; ///< DTR Line: 0=not available, 1=available + uint32_t dsr : 1; ///< DSR Line: 0=not available, 1=available + uint32_t dcd : 1; ///< DCD Line: 0=not available, 1=available + uint32_t ri : 1; ///< RI Line: 0=not available, 1=available + uint32_t event_cts : 1; ///< Signal CTS change event: \ref USART_EVENT_CTS + uint32_t event_dsr : 1; ///< Signal DSR change event: \ref USART_EVENT_DSR + uint32_t event_dcd : 1; ///< Signal DCD change event: \ref USART_EVENT_DCD + uint32_t event_ri : 1; ///< Signal RI change event: \ref USART_EVENT_RI +} usart_capabilities_t; + +/** + \brief Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function + \param[in] idx usart index + \param[in] cb_event event call back function \ref usart_event_cb_t + \return return usart handle if success +*/ +usart_handle_t csi_usart_initialize(int32_t idx, usart_event_cb_t cb_event); + +/** + \brief De-initialize USART Interface. stops operation and releases the software resources used by the interface + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_uninitialize(usart_handle_t handle); +/** + \brief Get driver capabilities. + \param[in] idx usart index + \return \ref usart_capabilities_t +*/ +usart_capabilities_t csi_usart_get_capabilities(int32_t idx); + +/** + \brief config usart mode. + \param[in] handle usart handle to operate. + \param[in] baud baud rate. + \param[in] mode \ref usart_mode_e . + \param[in] parity \ref usart_parity_e . + \param[in] stopbits \ref usart_stop_bits_e . + \param[in] bits \ref usart_data_bits_e . + \return error code +*/ +int32_t csi_usart_config(usart_handle_t handle, + uint32_t baud, + usart_mode_e mode, + usart_parity_e parity, + usart_stop_bits_e stopbits, + usart_data_bits_e bits); + + +/** + \brief Start sending data to USART transmitter,(received data is ignored). + This function is non-blocking,\ref usart_event_e is signaled when operation completes or error happens. + \ref csi_usart_get_status can get operation status. + \param[in] handle usart handle to operate. + \param[in] data Pointer to buffer with data to send to USART transmitter. data_type is : uint8_t for 5..8 data bits, uint16_t for 9 data bits + \param[in] num Number of data items to send + \return error code +*/ +int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num); + +/** + \brief Abort Send data to USART transmitter + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_send(usart_handle_t handle); + +/** + \brief Start receiving data from USART receiver. \n + This function is non-blocking,\ref usart_event_e is signaled when operation completes or error happens. + \ref csi_usart_get_status can get operation status. + \param[in] handle usart handle to operate. + \param[out] data Pointer to buffer for data to receive from USART receiver.data_type is : uint8_t for 5..8 data bits, uint16_t for 9 data bits + \param[in] num Number of data items to receive + \return error code +*/ +int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num); + +/** + \brief query data from UART receiver FIFO. + \param[in] handle usart handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver + \param[in] num Number of data items to receive + \return fifo data num to receive +*/ +int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num); + +/** + \brief Abort Receive data from USART receiver + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_receive(usart_handle_t handle); + +/** + \brief Start synchronously sends data to the USART transmitter and receives data from the USART receiver. used in synchronous mode + This function is non-blocking,\ref usart_event_e is signaled when operation completes or error happens. + \ref csi_usart_get_status can get operation status. + \param[in] handle usart handle to operate. + \param[in] data_out Pointer to buffer with data to send to USART transmitter.data_type is : uint8_t for 5..8 data bits, uint16_t for 9 data bits + \param[out] data_in Pointer to buffer for data to receive from USART receiver.data_type is : uint8_t for 5..8 data bits, uint16_t for 9 data bits + \param[in] num Number of data items to transfer + \return error code +*/ +int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num); + +/** + \brief abort sending/receiving data to/from USART transmitter/receiver. + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_transfer(usart_handle_t handle); + +/** + \brief Get USART status. + \param[in] handle usart handle to operate. + \return USART status \ref usart_status_t +*/ +usart_status_t csi_usart_get_status(usart_handle_t handle); + +/** + \brief flush receive/send data. + \param[in] handle usart handle to operate. + \param[in] type \ref usart_flush_type_e . + \return error code +*/ +int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type); + +/** + \brief set interrupt mode. + \param[in] handle usart handle to operate. + \param[in] type \ref usart_intr_type_e. + \param[in] flag 0-OFF, 1-ON. + \return error code +*/ +int32_t csi_usart_set_interrupt(usart_handle_t handle, usart_intr_type_e type, int32_t flag); + +/** + \brief set the baud rate of usart. + \param[in] baud usart base to operate. + \param[in] baudrate baud rate + \return error code +*/ +int32_t csi_usart_config_baudrate(usart_handle_t handle, uint32_t baud); + +/** + \brief config usart mode. + \param[in] handle usart handle to operate. + \param[in] mode \ref usart_mode_e + \return error code +*/ +int32_t csi_usart_config_mode(usart_handle_t handle, usart_mode_e mode); + +/** + \brief config usart parity. + \param[in] handle usart handle to operate. + \param[in] parity \ref usart_parity_e + \return error code +*/ +int32_t csi_usart_config_parity(usart_handle_t handle, usart_parity_e parity); + +/** + \brief config usart stop bit number. + \param[in] handle usart handle to operate. + \param[in] stopbits \ref usart_stop_bits_e + \return error code +*/ +int32_t csi_usart_config_stopbits(usart_handle_t handle, usart_stop_bits_e stopbit); + +/** + \brief config usart data length. + \param[in] handle usart handle to operate. + \param[in] databits \ref usart_data_bits_e + \return error code +*/ +int32_t csi_usart_config_databits(usart_handle_t handle, usart_data_bits_e databits); + +/** + \brief get character in query mode. + \param[in] handle usart handle to operate. + \param[out] ch the pointer to the received character. + \return error code +*/ +int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch); + +/** + \brief transmit character in query mode. + \param[in] handle usart handle to operate. + \param[in] ch the input character + \return error code +*/ +int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch); + +/** + \brief Get usart send data count. + \param[in] handle usart handle to operate. + \return number of currently transmitted data bytes +*/ +uint32_t csi_usart_get_tx_count(usart_handle_t handle); + +/** + \brief Get usart received data count. + \param[in] handle usart handle to operate. + \return number of currently received data bytes +*/ +uint32_t csi_usart_get_rx_count(usart_handle_t handle); + +/** + \brief control usart power. + \param[in] handle usart handle to operate. + \param[in] state power state.\ref csi_power_stat_e. + \return error code +*/ +int32_t csi_usart_power_control(usart_handle_t handle, csi_power_stat_e state); + +/** + \brief config usart flow control type. + \param[in] handle usart handle to operate. + \param[in] flowctrl_type flow control type.\ref usart_flowctrl_type_e. + \return error code +*/ +int32_t csi_usart_config_flowctrl(usart_handle_t handle, + usart_flowctrl_type_e flowctrl_type); + +/** + \brief config usart clock Polarity and Phase. + \param[in] handle usart handle to operate. + \param[in] cpol Clock Polarity.\ref usart_cpol_e. + \param[in] cpha Clock Phase.\ref usart_cpha_e. + \return error code +*/ +int32_t csi_usart_config_clock(usart_handle_t handle, usart_cpol_e cpol, usart_cpha_e cpha); + +/** + \brief control the transmitter. + \param[in] handle usart handle to operate. + \param[in] enable 1 - enable the transmitter. 0 - disable the transmitter + \return error code +*/ +int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable); + +/** + \brief control the receiver. + \param[in] handle usart handle to operate. + \param[in] enable 1 - enable the receiver. 0 - disable the receiver + \return error code +*/ +int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable); + +/** + \brief control the break. + \param[in] handle usart handle to operate. + \param[in] enable 1- Enable continuous Break transmission,0 - disable continuous Break transmission + \return error code +*/ +int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable); + +#ifdef __cplusplus +} +#endif + +#endif /* _CSI_USART_H_ */ diff --git a/bsp/thead-smart/drivers/dw_gpio.c b/bsp/thead-smart/drivers/dw_gpio.c new file mode 100644 index 0000000000..9ee3a3e429 --- /dev/null +++ b/bsp/thead-smart/drivers/dw_gpio.c @@ -0,0 +1,635 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen gpio driver + */ + +/****************************************************************************** + * @file dw_gpio.c + * @brief CSI Source File for GPIO Driver + * @version V1.0 + * @date 02. June 2017 + ******************************************************************************/ + +#include <csi_config.h> +#include <stdbool.h> +#include <stdio.h> +#include <drv_irq.h> +#include <drv_gpio.h> +#include <dw_gpio.h> +#include <csi_core.h> +#include <pin_name.h> + +extern int32_t drv_pin_config_mode(port_name_e port, uint8_t offset, gpio_mode_e pin_mode); + +#define ERR_GPIO(errno) (CSI_DRV_ERRNO_GPIO_BASE | errno) +#define GPIO_NULL_PARAM_CHK(para) HANDLE_PARAM_CHK(para, ERR_GPIO(DRV_ERROR_PARAMETER)) + +typedef void *gpio_port_handle_t; + +typedef struct +{ +#ifdef CONFIG_LPM + uint8_t gpio_power_status; + uint32_t gpio_regs_saved[7]; +#endif + uint32_t base; ///< handle register base + uint32_t irq; ///< irq of this handle + uint32_t pin_num; ///< pin number of this handle + gpio_mode_e mode; ///< gpio mode + gpio_direction_e dir; ///< gpio direction + uint32_t mask; ///< gpio mask bit + uint32_t value; ///< gpio value +} dw_gpio_priv_t; + +typedef struct +{ + uint8_t portidx; + uint8_t idx; + uint8_t offset; + gpio_event_cb_t cb; +} dw_gpio_pin_priv_t; + +extern int32_t target_gpio_port_init(port_name_e port, uint32_t *base, uint32_t *irq, void **handler, uint32_t *pin_num); +extern int32_t target_gpio_pin_init(int32_t gpio_pin, uint32_t *port_idx); + +static dw_gpio_priv_t gpio_handle[CONFIG_GPIO_NUM]; +static dw_gpio_pin_priv_t gpio_pin_handle[CONFIG_GPIO_PIN_NUM]; + +// +// Functions +// +static int32_t gpio_set_direction( + void *port, + gpio_direction_e direction +) +{ + dw_gpio_priv_t *gpio_priv = port; + dw_gpio_reg_t *gpio_reg = (dw_gpio_reg_t *)(gpio_priv->base); + + if (direction == GPIO_DIRECTION_INPUT) + { + gpio_reg->SWPORT_DDR &= (~gpio_priv->mask); + } else if (direction == GPIO_DIRECTION_OUTPUT) + { + gpio_reg->SWPORT_DDR |= gpio_priv->mask; + } else + { + return ERR_GPIO(GPIO_ERROR_DIRECTION); + } + + return 0; +} + +/* + * Read the statu of the Port choosed. + * Parameters: + * port: use to choose a I/O port among Port A, B, or C. + * return: the value of the corresponding Port. + */ + +static int32_t gpio_read(void *port, uint32_t *value) +{ + dw_gpio_priv_t *gpio_priv = port; + dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(gpio_priv->base + 0x30); + *value = gpio_control_reg->EXT_PORTA; + return 0; +} + + +/* + * Write an output value to corresponding Port. + * Parameters: + * port: use to choose a I/O port among Port A, B, or C. + * output: value that will be written to the corresponding Port. + * return: SUCCESS + */ + +static int32_t gpio_write(void *port, uint32_t mask) +{ + dw_gpio_priv_t *gpio_priv = port; + dw_gpio_reg_t *gpio_reg = (dw_gpio_reg_t *)(gpio_priv->base); + + uint32_t value = gpio_reg->SWPORT_DR; + + value &= ~(mask); + value |= gpio_priv->value; + gpio_reg->SWPORT_DR = value; + return 0; +} + +/** + * Configure a GPIO gpio_set_irq_mode. + * @param[in] pin the addr store the pin num. + * @param[in] _irqmode the irqmode of gpio + * @return zero on success. -1 on falure. + */ +static int32_t gpio_set_irq_mode(gpio_pin_handle_t pin, gpio_irq_mode_e irq_mode) +{ + dw_gpio_pin_priv_t *gpio_pin_priv = pin; + + /* convert portidx to port handle */ + dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx]; + + dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30); + uint32_t offset = gpio_pin_priv->idx; + uint32_t mask = 1 << offset; + + switch (irq_mode) + { + /* rising edge interrupt mode */ + case GPIO_IRQ_MODE_RISING_EDGE: + gpio_control_reg->INTTYPE_LEVEL |= mask; + gpio_control_reg->INT_POLARITY |= mask; + break; + + /* falling edge interrupt mode */ + case GPIO_IRQ_MODE_FALLING_EDGE: + gpio_control_reg->INTTYPE_LEVEL |= mask; + gpio_control_reg->INT_POLARITY &= (~mask); + break; + + /* low level interrupt mode */ + case GPIO_IRQ_MODE_LOW_LEVEL: + gpio_control_reg->INTTYPE_LEVEL &= (~mask); + gpio_control_reg->INT_POLARITY &= (~mask); + break; + + /* high level interrupt mode */ + case GPIO_IRQ_MODE_HIGH_LEVEL: + gpio_control_reg->INTTYPE_LEVEL &= (~mask); + gpio_control_reg->INT_POLARITY |= mask; + break; + + /* double edge interrupt mode */ + case GPIO_IRQ_MODE_DOUBLE_EDGE: + return ERR_GPIO(DRV_ERROR_UNSUPPORTED); + + default: + return ERR_GPIO(GPIO_ERROR_IRQ_MODE); + } + + return 0; +} + +/* + * Clear one or more interrupts of PortA. + * Parameters: + * pinno: + * return: SUCCESS. + */ + +static void gpio_irq_clear(gpio_pin_handle_t pin, uint32_t idx) +{ + dw_gpio_pin_priv_t *gpio_pin_priv = pin; + + /* convert portidx to port handle */ + dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx]; + + dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30); + + gpio_control_reg->PORTA_EOI = idx; +} + + +/* + * Enable one or more interrupts of PortA. + * Parameters: + * pinno: + * return: SUCCESS. + */ +static void gpio_irq_enable(gpio_pin_handle_t pin) +{ + dw_gpio_pin_priv_t *gpio_pin_priv = pin; + + /* convert portidx to port handle */ + dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx]; + + dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30); + uint32_t offset = gpio_pin_priv->idx; + uint32_t val = gpio_control_reg->INTEN; + val |= (1 << offset); + gpio_control_reg->INTEN = val; +} + + +/* + * Disable one or more interrupts of PortA. + * Parameters: + * pinno: + * return: SUCCESS. + */ + +static void gpio_irq_disable(gpio_pin_handle_t pin) +{ + dw_gpio_pin_priv_t *gpio_pin_priv = pin; + uint32_t offset = gpio_pin_priv->idx; + + /* convert portidx to port handle */ + dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx]; + + dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30); + uint32_t val = gpio_control_reg->INTEN; + val &= ~(1 << offset); + gpio_control_reg->INTEN = val; +} + +void dw_gpio_irqhandler(int idx) +{ + if (idx >= CONFIG_GPIO_NUM) + { + return; + } + + dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(gpio_handle[idx].base + 0x30); + + uint32_t value = gpio_control_reg->INTSTATUS; + uint8_t i; + + /* find the interrput pin */ + for (i = 0; i < 32; i++) + { + if (value & (1U << i)) + { + uint32_t pin_idx = i; + +#ifndef CONFIG_CHIP_DANICA + uint8_t j; + + if (idx > 0) + { + for (j = 0; j < idx; j++) + { + pin_idx += gpio_handle[j].pin_num; + } + } + + if (pin_idx >= CONFIG_GPIO_PIN_NUM) + { + return; + } + +#endif + dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)&gpio_pin_handle[pin_idx]; + + gpio_irq_clear(gpio_pin_priv, (1 << i)); //clear the gpio interrupt + + /* execute the callback function */ + if ((gpio_event_cb_t)(gpio_pin_priv->cb)) + { + ((gpio_event_cb_t)(gpio_pin_priv->cb))(gpio_pin_priv->offset); + } + } + } +} + +/** + \brief Initialize GPIO module. 1. Initializes the resources needed for the GPIO handle 2.registers event callback function + 3.get gpio_port_handle + \param[in] port port_name. + \return gpio_port_handle +*/ +gpio_port_handle_t csi_gpio_port_initialize(int32_t port) +{ + dw_gpio_priv_t *gpio_priv = NULL; + + /* obtain the gpio port information */ + uint32_t base = 0u; + uint32_t pin_num; + uint32_t irq; + void *handler; + int32_t idx = target_gpio_port_init(port, &base, &irq, &handler, &pin_num); + + if (idx < 0 || idx >= CONFIG_GPIO_NUM) + { + return NULL; + } + + gpio_priv = &gpio_handle[idx]; + + gpio_priv->base = base; + gpio_priv->irq = irq; + gpio_priv->pin_num = pin_num; + +#ifdef CONFIG_LPM + csi_gpio_power_control(gpio_priv, DRV_POWER_FULL); +#endif + + drv_irq_register(gpio_priv->irq, handler); + drv_irq_enable(gpio_priv->irq); + + return (gpio_port_handle_t)gpio_priv; +} + +/** + \brief De-initialize GPIO handle. stops operation and releases the software resources used by the handle + \param[in] handle gpio port handle to operate. + \return error code +*/ +int32_t csi_gpio_port_uninitialize(gpio_port_handle_t handle) +{ + GPIO_NULL_PARAM_CHK(handle); + + dw_gpio_priv_t *gpio_priv = handle; + + drv_irq_disable(gpio_priv->irq); + drv_irq_unregister(gpio_priv->irq); + +#ifdef CONFIG_LPM + csi_gpio_power_control(gpio_priv, DRV_POWER_OFF); +#endif + + return 0; +} + +#ifdef CONFIG_LPM +static void manage_clock(gpio_pin_handle_t handle, uint8_t enable) +{ + dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)handle; + uint8_t device[] = {CLOCK_MANAGER_GPIO0, CLOCK_MANAGER_GPIO1}; + + drv_clock_manager_config(device[gpio_pin_priv->portidx], enable); +} + +static void do_prepare_sleep_action(void *handle) +{ + dw_gpio_priv_t *gpio_handle = handle; + uint32_t *gbase = (uint32_t *)(gpio_handle->base); + uint32_t *control_base = (uint32_t *)(gpio_handle->base + 0x30); + registers_save(gpio_handle->gpio_regs_saved, gbase, 3); + registers_save(&gpio_handle->gpio_regs_saved[3], control_base, 4); +} + +static void do_wakeup_sleep_action(void *handle) +{ + dw_gpio_priv_t *gpio_handle = handle; + uint32_t *gbase = (uint32_t *)(gpio_handle->base); + uint32_t *control_base = (uint32_t *)(gpio_handle->base + 0x30); + registers_restore(gbase, gpio_handle->gpio_regs_saved, 3); + registers_restore(control_base, &gpio_handle->gpio_regs_saved[3], 4); +} +#endif + +/** + \brief Initialize GPIO handle. + \param[in] gpio_pin Pointer to the int32_t. + \param[in] cb_event Pointer to \ref gpio_event_cb_t. + \param[in] arg Pointer to \ref arg used for the callback. + \return gpio_pin_handle +*/ +gpio_pin_handle_t csi_gpio_pin_initialize(int32_t gpio_pin, gpio_event_cb_t cb_event) +{ + + if (gpio_pin < 0 || gpio_pin >= CONFIG_GPIO_PIN_NUM) + { + return NULL; + } + + uint32_t i; + + for (i = 0; i < CONFIG_GPIO_NUM; i++) + { + csi_gpio_port_initialize(i); + } + + /* obtain the gpio pin information */ + uint32_t port_idx; + int32_t pin_idx = target_gpio_pin_init(gpio_pin, &port_idx); + + if (pin_idx < 0) + { + return NULL; + } + + int32_t idx = pin_idx; + + for (i = 0; i < port_idx; i++) + { + idx += (gpio_handle[i].pin_num); + } + + dw_gpio_pin_priv_t *gpio_pin_priv = &(gpio_pin_handle[idx]); + gpio_pin_priv->portidx = port_idx; + + + gpio_pin_priv->idx = pin_idx; + gpio_pin_priv->cb = cb_event; + gpio_pin_priv->offset = gpio_pin; + + return (gpio_pin_handle_t)gpio_pin_priv; +} + +/** + \brief De-initialize GPIO pin handle. stops operation and releases the software resources used by the handle + \param[in] handle gpio pin handle to operate. + \return error code +*/ +int32_t csi_gpio_pin_uninitialize(gpio_pin_handle_t handle) +{ + if (handle == NULL) + { + return ERR_GPIO(DRV_ERROR_PARAMETER); + } + + dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)handle; + gpio_pin_priv->cb = NULL; + + gpio_irq_disable(handle); + + return 0; +} + +/** + \brief control gpio power. + \param[in] idx gpio index. + \param[in] state power state.\ref csi_power_stat_e. + \return error code +*/ +int32_t csi_gpio_power_control(gpio_pin_handle_t handle, csi_power_stat_e state) +{ + GPIO_NULL_PARAM_CHK(handle); + +#ifdef CONFIG_LPM + dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)handle; + power_cb_t callback = + { + .wakeup = do_wakeup_sleep_action, + .sleep = do_prepare_sleep_action, + .manage_clock = manage_clock + }; + return drv_soc_power_control(&gpio_handle[gpio_pin_priv->portidx], state, &callback); +#else + return ERR_GPIO(DRV_ERROR_UNSUPPORTED); +#endif +} + +/** + \brief config pin mode + \param[in] pin gpio pin handle to operate. + \param[in] mode \ref gpio_mode_e + \return error code +*/ +int32_t csi_gpio_pin_config_mode(gpio_pin_handle_t handle, + gpio_mode_e mode) +{ + GPIO_NULL_PARAM_CHK(handle); + + /* config the gpio pin mode direction mask bits */ + dw_gpio_pin_priv_t *gpio_pin_priv = handle; + + uint8_t offset = gpio_pin_priv->idx; + + int32_t ret = drv_pin_config_mode(gpio_pin_priv->portidx, offset, mode); + + return ret; +} +/** + \brief config pin direction + \param[in] pin gpio pin handle to operate. + \param[in] dir \ref gpio_direction_e + \return error code +*/ +int32_t csi_gpio_pin_config_direction(gpio_pin_handle_t handle, + gpio_direction_e dir) +{ + GPIO_NULL_PARAM_CHK(handle); + + /* config the gpio pin mode direction mask bits */ + dw_gpio_pin_priv_t *gpio_pin_priv = handle; + + /* convert portidx to port handle */ + dw_gpio_priv_t *gpio_priv = &gpio_handle[gpio_pin_priv->portidx]; + + gpio_priv->dir = dir; + gpio_priv->mask = 1 << gpio_pin_priv->idx; + + uint32_t ret = gpio_set_direction(gpio_priv, dir); + + if (ret) + { + return ret; + } + + return 0; +} + +/** + \brief config pin + \param[in] handle gpio pin handle to operate. + \param[in] mode \ref gpio_mode_e + \param[in] dir \ref gpio_direction_e + \return error code +*/ +int32_t csi_gpio_pin_config(gpio_pin_handle_t handle, + gpio_mode_e mode, + gpio_direction_e dir) +{ + GPIO_NULL_PARAM_CHK(handle); + + /* config the gpio pin mode direction mask bits */ + dw_gpio_pin_priv_t *gpio_pin_priv = handle; + + /* convert portidx to port handle */ + dw_gpio_priv_t *gpio_priv = &gpio_handle[gpio_pin_priv->portidx]; + + gpio_priv->mode = mode; + gpio_priv->dir = dir; + gpio_priv->mask = 1 << gpio_pin_priv->idx; + + uint32_t ret = gpio_set_direction(gpio_priv, dir); + + if (ret) + { + return ret; + } + + return 0; + +} + +/** + \brief Set one or zero to the selected GPIO pin. + \param[in] handle gpio pin handle to operate. + \param[in] value the value to be set + \return error code +*/ +int32_t csi_gpio_pin_write(gpio_pin_handle_t handle, bool value) +{ + GPIO_NULL_PARAM_CHK(handle); + + dw_gpio_pin_priv_t *gpio_pin_priv = handle; + + /* convert portidx to port handle */ + dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx]; + + uint8_t offset = gpio_pin_priv->idx; + uint32_t port_value = value << offset; + + port_handle->value = port_value; + gpio_write(port_handle, (1 << offset)); + + return 0; + +} + +/** + \brief Get the value of selected GPIO pin. + \param[in] handle gpio pin handle to operate. + \param[out] value buf to store the pin value + \return error code +*/ +int32_t csi_gpio_pin_read(gpio_pin_handle_t handle, bool *value) +{ + GPIO_NULL_PARAM_CHK(handle); + GPIO_NULL_PARAM_CHK(value); + + dw_gpio_pin_priv_t *gpio_pin_priv = handle; + uint32_t port_value; + uint8_t offset = gpio_pin_priv->idx; + + /* convert portidx to port handle */ + dw_gpio_priv_t *port_handle = &gpio_handle[gpio_pin_priv->portidx]; + + gpio_read(port_handle, &port_value); + *value = (port_value & (1 << offset)) >> offset; + + return 0; +} + +/** + \brief set GPIO interrupt mode. + \param[in] handle gpio pin handle to operate. + \param[in] mode the irq mode to be set + \param[in] enable the enable flag + \return error code +*/ +int32_t csi_gpio_pin_set_irq(gpio_pin_handle_t handle, gpio_irq_mode_e mode, bool enable) +{ + GPIO_NULL_PARAM_CHK(handle); + + uint32_t ret = 0; + + if (enable) + { + ret = gpio_set_irq_mode(handle, mode); + + if (ret) + { + return ret; + } + + gpio_irq_enable(handle); + + } else + { + gpio_irq_disable(handle); + + } + + return ret; +} + diff --git a/bsp/thead-smart/drivers/dw_gpio.h b/bsp/thead-smart/drivers/dw_gpio.h new file mode 100644 index 0000000000..768cdf1b1d --- /dev/null +++ b/bsp/thead-smart/drivers/dw_gpio.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header file for GPIO Driver + */ + +#ifndef _DW_GPIO_H_ +#define _DW_GPIO_H_ + +#include "drv_gpio.h" +#include "soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct +{ + __IOM uint32_t SWPORT_DR; /* Offset: 0x000 (W/R) PortA data register */ + __IOM uint32_t SWPORT_DDR; /* Offset: 0x004 (W/R) PortA data direction register */ + __IOM uint32_t PORT_CTL; /* Offset: 0x008 (W/R) PortA source register */ + +} dw_gpio_reg_t; + +typedef struct +{ + __IOM uint32_t INTEN; /* Offset: 0x000 (W/R) Interrupt enable register */ + __IOM uint32_t INTMASK; /* Offset: 0x004 (W/R) Interrupt mask register */ + __IOM uint32_t INTTYPE_LEVEL; /* Offset: 0x008 (W/R) Interrupt level register */ + __IOM uint32_t INT_POLARITY; /* Offset: 0x00c (W/R) Interrupt polarity register */ + __IM uint32_t INTSTATUS; /* Offset: 0x010 (R) Interrupt status of Port */ + __IM uint32_t RAWINTSTATUS; /* Offset: 0x014 (W/R) Raw interrupt status of Port */ + __IOM uint32_t revreg1; /* Offset: 0x018 (W/R) Reserve register */ + __OM uint32_t PORTA_EOI; /* Offset: 0x01c (W/R) Port clear interrupt register */ + __IM uint32_t EXT_PORTA; /* Offset: 0x020 (W/R) PortA external port register */ + __IM uint32_t EXT_PORTB; /* Offset: 0x024 (W/R) PortB external port register */ + __IOM uint32_t revreg2[2]; /* Offset: 0x028 (W/R) Reserve register */ + __IOM uint32_t LS_SYNC; /* Offset: 0x030 (W/R) Level-sensitive synchronization enable register */ + +} dw_gpio_control_reg_t; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/bsp/thead-smart/drivers/dw_timer.c b/bsp/thead-smart/drivers/dw_timer.c new file mode 100644 index 0000000000..5792d47a73 --- /dev/null +++ b/bsp/thead-smart/drivers/dw_timer.c @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen CSI Source File for timer Driver + */ + + +#include <csi_config.h> +#include <drv_irq.h> +#include <drv_timer.h> +#include <dw_timer.h> +#include <soc.h> +#include <csi_core.h> + +#define ERR_TIMER(errno) (CSI_DRV_ERRNO_TIMER_BASE | errno) + +#define TIMER_NULL_PARAM_CHK(para) HANDLE_PARAM_CHK(para, ERR_TIMER(DRV_ERROR_PARAMETER)) + +typedef struct +{ +#ifdef CONFIG_LPM + uint8_t timer_power_status; + uint32_t timer_regs_saved[2]; +#endif + uint8_t idx; + uint32_t base; + uint32_t irq; + timer_event_cb_t cb_event; + uint32_t timeout; ///< the set time (us) + uint32_t timeout_flag; +} dw_timer_priv_t; + +extern int32_t target_get_timer_count(void); +extern int32_t target_get_timer(int32_t idx, uint32_t *base, uint32_t *irq, void **handler); + +static dw_timer_priv_t timer_instance[CONFIG_TIMER_NUM]; +/** + \brief Make all the timers in the idle state. + \param[in] pointer to timer register base +*/ +static void timer_deactive_control(dw_timer_reg_t *addr) +{ + /* stop the corresponding timer */ + addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE; + /* Disable interrupt. */ + addr->TxControl |= DW_TIMER_TXCONTROL_INTMASK; +} + +void dw_timer_irqhandler(int idx) +{ + dw_timer_priv_t *timer_priv = &timer_instance[idx]; + timer_priv->timeout_flag = 1; + + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + addr->TxEOI; + + if (timer_priv->cb_event) + { + return timer_priv->cb_event(idx, TIMER_EVENT_TIMEOUT); + } + +} + +#ifdef CONFIG_LPM +static void manage_clock(timer_handle_t handle, uint8_t enable) +{ + if (handle == &timer_instance[0] || handle == &timer_instance[1]) + { + drv_clock_manager_config(CLOCK_MANAGER_TIM, enable); + } else if (handle == &timer_instance[3] || handle == &timer_instance[2]) + { + drv_clock_manager_config(CLOCK_MANAGER_TIM1, enable); + } +} + +static void do_prepare_sleep_action(timer_handle_t handle) +{ + dw_timer_priv_t *timer_priv = (dw_timer_priv_t *)handle; + uint32_t *tbase = (uint32_t *)(timer_priv->base); + registers_save(timer_priv->timer_regs_saved, tbase, 1); + registers_save(&timer_priv->timer_regs_saved[1], tbase + 2, 1); +} + +static void do_wakeup_sleep_action(timer_handle_t handle) +{ + dw_timer_priv_t *timer_priv = (dw_timer_priv_t *)handle; + uint32_t *tbase = (uint32_t *)(timer_priv->base); + registers_restore(tbase, timer_priv->timer_regs_saved, 1); + registers_restore(tbase + 2, &timer_priv->timer_regs_saved[1], 1); +} +#endif + +/** + \brief Initialize TIMER Interface. 1. Initializes the resources needed for the TIMER interface 2.registers event callback function + \param[in] idx instance timer index + \param[in] cb_event Pointer to \ref timer_event_cb_t + \return pointer to timer instance +*/ +timer_handle_t csi_timer_initialize(int32_t idx, timer_event_cb_t cb_event) +{ + if (idx < 0 || idx >= CONFIG_TIMER_NUM) + { + return NULL; + } + + uint32_t base = 0u; + uint32_t irq = 0u; + void *handler; + + int32_t real_idx = target_get_timer(idx, &base, &irq, &handler); + + if (real_idx != idx) + { + return NULL; + } + + dw_timer_priv_t *timer_priv = &timer_instance[idx]; + timer_priv->base = base; + timer_priv->irq = irq; + timer_priv->idx = idx; + + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + timer_priv->timeout = DW_TIMER_INIT_DEFAULT_VALUE; + +#ifdef CONFIG_LPM + csi_timer_power_control(timer_priv, DRV_POWER_FULL); +#endif + + timer_deactive_control(addr); + timer_priv->cb_event = cb_event; + + if (cb_event != NULL) + { + drv_irq_register(timer_priv->irq, handler); + drv_irq_enable(timer_priv->irq); + } + + return (timer_handle_t)timer_priv; +} + +/** + \brief De-initialize TIMER Interface. stops operation and releases the software resources used by the interface + \param[in] handle timer handle to operate. + \return error code +*/ +int32_t csi_timer_uninitialize(timer_handle_t handle) +{ + TIMER_NULL_PARAM_CHK(handle); + + dw_timer_priv_t *timer_priv = (dw_timer_priv_t *)handle; + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + timer_deactive_control(addr); + timer_priv->cb_event = NULL; + + drv_irq_disable(timer_priv->irq); + drv_irq_unregister(timer_priv->irq); + +#ifdef CONFIG_LPM + csi_timer_power_control(timer_priv, DRV_POWER_OFF); +#endif + + return 0; +} + +int32_t csi_timer_power_control(timer_handle_t handle, csi_power_stat_e state) +{ + TIMER_NULL_PARAM_CHK(handle); +#ifdef CONFIG_LPM + power_cb_t callback = + { + .wakeup = do_wakeup_sleep_action, + .sleep = do_prepare_sleep_action, + .manage_clock = manage_clock + }; + return drv_soc_power_control(handle, state, &callback); +#else + return ERR_TIMER(DRV_ERROR_UNSUPPORTED); +#endif +} + +/** + \brief config timer mode. + \param[in] handle timer handle to operate. + \param[in] mode \ref timer_mode_e + \return error code +*/ +int32_t csi_timer_config(timer_handle_t handle, timer_mode_e mode) +{ + TIMER_NULL_PARAM_CHK(handle); + + dw_timer_priv_t *timer_priv = handle; + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + switch (mode) + { + case TIMER_MODE_FREE_RUNNING: + addr->TxControl &= ~DW_TIMER_TXCONTROL_MODE; + break; + + case TIMER_MODE_RELOAD: + addr->TxControl |= DW_TIMER_TXCONTROL_MODE; + break; + + default: + return ERR_TIMER(DRV_ERROR_PARAMETER); + } + + addr->TxControl |= (DW_TIMER_TXCONTROL_TRIGGER); + + return 0; +} + +/** + \brief Set timer. + \param[in] instance timer instance to operate. + \param[in] timeout the timeout value in microseconds(us). + \return error code +*/ +int32_t csi_timer_set_timeout(timer_handle_t handle, uint32_t timeout) +{ + TIMER_NULL_PARAM_CHK(handle); + + dw_timer_priv_t *timer_priv = handle; + timer_priv->timeout = timeout; + return 0; +} + +/** + \brief Start timer. + \param[in] handle timer handle to operate. + \return error code +*/ + +int32_t csi_timer_start(timer_handle_t handle) +{ + TIMER_NULL_PARAM_CHK(handle); + + dw_timer_priv_t *timer_priv = handle; + + timer_priv->timeout_flag = 0; + + uint32_t min_us = drv_get_timer_freq(timer_priv->idx) / 1000000; + uint32_t load; + + if (((timer_priv->timeout * drv_get_timer_freq(timer_priv->idx)) / 1000000) > 0xffffffff) + { + return ERR_TIMER(DRV_ERROR_PARAMETER); + } + + if (min_us) + { + load = (uint32_t)(timer_priv->timeout * min_us); + } else + { + load = (uint32_t)(((uint64_t)(timer_priv->timeout) * drv_get_timer_freq(timer_priv->idx)) / 1000000); + } + + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + if (timer_priv->timeout == 0) { + addr->TxLoadCount = 0xffffffff; /* load time(us) */ + } else + { + if ((addr->TxControl | 0x2) == 0x2) { + addr->TxLoadCount = 0xffffffff; /* load time(us) */ + } else + { + addr->TxLoadCount = load; /* load time(us) */ + } + } + + addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE; /* disable the timer */ + addr->TxControl |= DW_TIMER_TXCONTROL_ENABLE; /* enable the corresponding timer */ + addr->TxControl &= ~DW_TIMER_TXCONTROL_INTMASK; /* enable interrupt */ + + /* avoid timer bug on yunvoice soc */ +#ifdef CONFIG_CHIP_YUNVOICE + + if (addr->TxCurrentValue > addr->TxLoadCount) { + addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE; /* disable the timer */ + addr->TxControl |= DW_TIMER_TXCONTROL_ENABLE; /* enable the corresponding timer */ + addr->TxControl &= ~DW_TIMER_TXCONTROL_INTMASK; /* enable interrupt */ + } + +#endif + + return 0; +} + +/** + \brief Stop timer. + \param[in] handle timer handle to operate. + \return error code +*/ +int32_t csi_timer_stop(timer_handle_t handle) +{ + TIMER_NULL_PARAM_CHK(handle); + + dw_timer_priv_t *timer_priv = handle; + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + addr->TxControl |= DW_TIMER_TXCONTROL_INTMASK; /* enable interrupt */ + addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE; /* disable the timer */ + + return 0; +} + +/** + \brief suspend timer. + \param[in] instance timer instance to operate. + \return error code +*/ +int32_t csi_timer_suspend(timer_handle_t handle) +{ + TIMER_NULL_PARAM_CHK(handle); + + return ERR_TIMER(DRV_ERROR_UNSUPPORTED); +} + +/** + \brief resume timer. + \param[in] handle timer handle to operate. + \return error code +*/ +int32_t csi_timer_resume(timer_handle_t handle) +{ + TIMER_NULL_PARAM_CHK(handle); + + dw_timer_priv_t *timer_priv = handle; + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE; /* stop the corresponding timer */ + addr->TxControl &= DW_TIMER_TXCONTROL_ENABLE; /* restart the corresponding timer */ + + return 0; +} + +/** + \brief get timer current value + \param[in] handle timer handle to operate. + \param[out] value timer current value + \return error code +*/ +int32_t csi_timer_get_current_value(timer_handle_t handle, uint32_t *value) +{ + TIMER_NULL_PARAM_CHK(handle); + TIMER_NULL_PARAM_CHK(value); + + dw_timer_priv_t *timer_priv = handle; + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + *value = addr->TxCurrentValue; + return 0; +} + +/** + \brief Get TIMER status. + \param[in] handle timer handle to operate. + \return TIMER status \ref timer_status_t +*/ +timer_status_t csi_timer_get_status(timer_handle_t handle) +{ + timer_status_t timer_status = {0}; + + if (handle == NULL) + { + return timer_status; + } + + dw_timer_priv_t *timer_priv = handle; + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + if (addr->TxControl & DW_TIMER_TXCONTROL_ENABLE) + { + timer_status.active = 1; + } + + if (timer_priv->timeout_flag == 1) + { + timer_status.timeout = 1; + } + + return timer_status; +} + +/** + \brief get timer reload value + \param[in] handle timer handle to operate. + \param[out] value timer reload value + \return error code +*/ +int32_t csi_timer_get_load_value(timer_handle_t handle, uint32_t *value) +{ + TIMER_NULL_PARAM_CHK(handle); + TIMER_NULL_PARAM_CHK(value); + + dw_timer_priv_t *timer_priv = handle; + dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base); + + *value = addr->TxLoadCount; + return 0; +} + diff --git a/bsp/thead-smart/drivers/dw_timer.h b/bsp/thead-smart/drivers/dw_timer.h new file mode 100644 index 0000000000..7b418cac70 --- /dev/null +++ b/bsp/thead-smart/drivers/dw_timer.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header file for timer driver + */ + +#ifndef __DW_TIMER_H +#define __DW_TIMER_H + +#include <stdio.h> +#include "soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * define the bits for TxControl + */ +#define DW_TIMER_TXCONTROL_ENABLE (1UL << 0) +#define DW_TIMER_TXCONTROL_MODE (1UL << 1) +#define DW_TIMER_TXCONTROL_INTMASK (1UL << 2) +#define DW_TIMER_TXCONTROL_TRIGGER (1UL << 4) + +#define DW_TIMER_INIT_DEFAULT_VALUE (0xffffffff / drv_get_timer_freq(0) * 1000000) + +typedef struct +{ + __IOM uint32_t TxLoadCount; /* Offset: 0x000 (R/W) Receive buffer register */ + __IM uint32_t TxCurrentValue; /* Offset: 0x004 (R) Transmission hold register */ + __IOM uint8_t TxControl: 5; /* Offset: 0x008 (R/W) Clock frequency division low section register */ + uint8_t RESERVED0[3]; + __IM uint8_t TxEOI: 1; /* Offset: 0x00c (R) Clock frequency division high section register */ + uint8_t RESERVED1[3]; + __IM uint8_t TxIntStatus: 1; /* Offset: 0x010 (R) Interrupt enable register */ + uint8_t RESERVED2[3]; +} dw_timer_reg_t; + +#ifdef __cplusplus +} +#endif + +#endif /* __DW_TIMER_H */ + diff --git a/bsp/thead-smart/drivers/isr.c b/bsp/thead-smart/drivers/isr.c new file mode 100644 index 0000000000..1a42a81bcf --- /dev/null +++ b/bsp/thead-smart/drivers/isr.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen source file for the interrupt server route + */ + +#include <drv_common.h> +#include <csi_config.h> +#include "soc.h" + +#ifndef CONFIG_SYSTICK_HZ +#define CONFIG_SYSTICK_HZ 100 +#endif + +extern volatile uint32_t rt_thread_switch_interrupt_flag; + +extern void ck_usart_irqhandler(int32_t idx); +extern void dw_timer_irqhandler(int32_t idx); +extern void dw_gpio_irqhandler(int32_t idx); +extern void systick_handler(void); +extern void xPortSysTickHandler(void); +extern void OSTimeTick(void); + +#define ATTRIBUTE_ISR + +#define readl(addr) \ + ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; }) + + +#if(CONFIG_KERNEL_RTTHREAD == 1) +#define CSI_INTRPT_ENTER() rt_interrupt_enter() +#define CSI_INTRPT_EXIT() rt_interrupt_leave() +#endif + + +void __attribute__((isr)) SysTick_Handler(void) +{ +#if(CONFIG_KERNEL_RTTHREAD == 1) + CSI_INTRPT_ENTER(); +#endif + + csi_coret_config(drv_get_sys_freq() / CONFIG_SYSTICK_HZ, CORET_IRQn); + +#if defined(CONFIG_KERNEL_RHINO) + systick_handler(); +#elif defined(CONFIG_KERNEL_FREERTOS) + xPortSysTickHandler(); +#elif defined(CONFIG_KERNEL_RTTHREAD) + rt_tick_increase(); +#elif defined(CONFIG_KERNEL_UCOS) + OSTimeTick(); +#endif + +#if(CONFIG_KERNEL_RTTHREAD == 1) + CSI_INTRPT_EXIT(); +#endif +} + +ATTRIBUTE_ISR void USART_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + ck_usart0_irqhandler(); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void TIM0_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(0); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void TIM1_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(1); + CSI_INTRPT_EXIT(); +} +ATTRIBUTE_ISR void TIM2_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(2); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void TIM3_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(3); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void TIM4_NMIHandler(void) +{ + dw_timer_irqhandler(4); +} + +ATTRIBUTE_ISR void TIM6_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(6); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void TIM7_IRQHandler(void) +{ + dw_timer_irqhandler(7); +} + +ATTRIBUTE_ISR void TIM8_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(8); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void TIM9_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(9); + CSI_INTRPT_EXIT(); +} +ATTRIBUTE_ISR void TIM10_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(10); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void TIM11_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_timer_irqhandler(11); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void GPIO0_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_gpio_irqhandler(0); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void GPIO1_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_gpio_irqhandler(1); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void GPIO2_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_gpio_irqhandler(2); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void GPIO3_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_gpio_irqhandler(3); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void GPIO4_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_gpio_irqhandler(4); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void GPIO5_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_gpio_irqhandler(5); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void GPIO6_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_gpio_irqhandler(6); + CSI_INTRPT_EXIT(); +} + +ATTRIBUTE_ISR void GPIO7_IRQHandler(void) +{ + CSI_INTRPT_ENTER(); + dw_gpio_irqhandler(7); + CSI_INTRPT_EXIT(); +} diff --git a/bsp/thead-smart/drivers/novic_irq_tbl.c b/bsp/thead-smart/drivers/novic_irq_tbl.c new file mode 100644 index 0000000000..cadfac5f98 --- /dev/null +++ b/bsp/thead-smart/drivers/novic_irq_tbl.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen novic table init + */ + +#include <csi_config.h> +#include <soc.h> + +extern void Default_Handler(void); +extern void SysTick_Handler(void); +extern void TIM4_NMIHandler(void); + +void (*g_irqvector[48])(void); +void (*g_nmivector)(void); + +void irq_vectors_init(void) +{ + int i; + + for (i = 0; i < 48; i++) + { + g_irqvector[i] = Default_Handler; + } + + g_irqvector[CORET_IRQn] = SysTick_Handler; + g_nmivector = TIM4_NMIHandler; +} diff --git a/bsp/thead-smart/drivers/pin_name.h b/bsp/thead-smart/drivers/pin_name.h new file mode 100644 index 0000000000..78aa4bc18a --- /dev/null +++ b/bsp/thead-smart/drivers/pin_name.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header file for the pin_name + */ + +#ifndef _PINNAMES_H +#define _PINNAMES_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum +{ + PA0 = 0, + PA1, + PA2, + PA3, + PA4, + PA5, + PA6, + PA7, + PAD_UART0_SIN, + PAD_UART0_SOUT +} +pin_name_e; + +typedef enum +{ + PORTA = 0, + PORTB = 1, + PORTC = 2, + PORTD = 3, + PORTE = 4, + PORTF = 5, + PORTG = 6, + PORTH = 7 +} port_name_e; + +typedef enum +{ + NONE = 0 +} pin_func_e; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/thead-smart/drivers/soc.h b/bsp/thead-smart/drivers/soc.h new file mode 100644 index 0000000000..656e944995 --- /dev/null +++ b/bsp/thead-smart/drivers/soc.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen CSI Core Peripheral Access Layer Header File for + * CSKYSOC Device Series + */ + +#ifndef _SOC_H_ +#define _SOC_H_ + +#include <stdint.h> +#include <csi_core.h> +#include <sys_freq.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef IHS_VALUE +#define IHS_VALUE (20000000) +#endif + +#ifndef EHS_VALUE +#define EHS_VALUE (20000000) +#endif + + +/* ------------------------- Interrupt Number Definition ------------------------ */ +typedef enum IRQn { + NMI_EXPn = -2, /* NMI Exception */ + /* ---------------------- SmartL Specific Interrupt Numbers --------------------- */ + Machine_Software_IRQn = 3, /* Machine software interrupt */ + User_Timer_IRQn = 4, /* User timer interrupt */ + Supervisor_Timer_IRQn = 5, /* Supervisor timer interrupt */ + CORET_IRQn = 7, /* core Timer Interrupt */ + Machine_External_IRQn = 11, /* Machine external interrupt */ + UART_IRQn = 16, /* uart Interrupt */ + TIM0_IRQn = 18, /* timer0 Interrupt */ + TIM1_IRQn = 19, /* timer1 Interrupt */ + TIM2_IRQn = 20, /* timer2 Interrupt */ + TIM3_IRQn = 21, /* timer3 Interrupt */ + GPIO0_IRQn = 23, /* gpio0 Interrupt */ + GPIO1_IRQn = 24, /* gpio1 Interrupt */ + GPIO2_IRQn = 25, /* gpio2 Interrupt */ + GPIO3_IRQn = 26, /* gpio3 Interrupt */ + GPIO4_IRQn = 27, /* gpio4 Interrupt */ + GPIO5_IRQn = 28, /* gpio5 Interrupt */ + GPIO6_IRQn = 29, /* gpio6 Interrupt */ + GPIO7_IRQn = 30, /* gpio7 Interrupt */ + STIM0_IRQn = 31, /* stimer0 Interrupt */ + STIM1_IRQn = 32, /* stimer1 Interrupt */ + STIM2_IRQn = 33, /* stimer2 Interrupt */ + STIM3_IRQn = 34, /* stimer3 Interrupt */ + PAD_IRQn = 35, /* pad Interrupt */ + TIM6_IRQn = 36, /* timer6 Interrupt */ + TIM7_IRQn = 37, /* timer7 Interrupt */ + TIM8_IRQn = 38, /* timer8 Interrupt */ + TIM9_IRQn = 39, /* timer9 Interrupt */ + TIM10_IRQn = 40, /* timer10 Interrupt */ + TIM11_IRQn = 41, /* timer11 Interrupt */ +} +IRQn_Type; + +/* ================================================================================ */ +/* ================ Device Specific Peripheral Section ================ */ +/* ================================================================================ */ + +#define CONFIG_TIMER_NUM 12 +#define CONFIG_USART_NUM 1 +#define CONFIG_GPIO_NUM 8 +#define CONFIG_GPIO_PIN_NUM 8 + +/* ================================================================================ */ +/* ================ Peripheral memory map ================ */ +/* ================================================================================ */ +/* -------------------------- CPU FPGA memory map ------------------------------- */ +#define CSKY_SRAM_BASE (0x20000000UL) + +#define CSKY_UART_BASE (0x40015000UL) +#define CSKY_PMU_BASE (0x40016000UL) +#define CSKY_TIMER0_BASE (0x40011000UL) +#define CSKY_TIMER1_BASE (0x40011014UL) +#define CSKY_TIMER2_BASE (0x40011028UL) +#define CSKY_TIMER3_BASE (0x4001103cUL) +#define CSKY_TIMER4_BASE (0x40021000UL) +#define CSKY_TIMER5_BASE (0x40021014UL) +#define CSKY_TIMER6_BASE (0x40021028UL) +#define CSKY_TIMER7_BASE (0x4002103cUL) +#define CSKY_TIMER8_BASE (0x40031000UL) +#define CSKY_TIMER9_BASE (0x40031014UL) +#define CSKY_TIMER10_BASE (0x40031028UL) +#define CSKY_TIMER11_BASE (0x4003103cUL) + +#define CSKY_TIMER_CONTROL_BASE (0x400110a0UL) +#define CSKY_CLK_GEN_BASE (0x40017000UL) +#define CSKY_STIMER0_BASE (0x40018000UL) +#define CSKY_STIMER1_BASE (0x40018014UL) +#define CSKY_STIMER2_BASE (0x40018028UL) +#define CSKY_STIMER3_BASE (0x4001803cUL) +#define CSKY_STIMER_CONTROL_BASE (0x400110a0UL) + +#define CSKY_GPIOA_BASE (0x40019000UL) +#define CSKY_GPIOA_CONTROL_BASE (0x40019030UL) +#define CSKY_SMPU_BASE (0x4001a000UL) + +/* ================================================================================ */ +/* ================ Peripheral declaration ================ */ +/* ================================================================================ */ +#define CSKY_UART (( CSKY_UART_TypeDef *) CSKY_UART_BASE) + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC_H_ */ diff --git a/bsp/thead-smart/drivers/startup_gcc.S b/bsp/thead-smart/drivers/startup_gcc.S new file mode 100644 index 0000000000..f71164c599 --- /dev/null +++ b/bsp/thead-smart/drivers/startup_gcc.S @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen startup file. Should use with + * GCC for T-HEAD Embedded Processors + */ + +#include <csi_config.h> + + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long PendSV_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .text + .align 2 +_start: + .text + .align 2 + .globl Reset_Handler + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + la a0, __Vectors + csrw mtvt, a0 + la sp, __StackTop + csrw mscratch, sp + + /* Load data section */ + la a0, __erodata + la a1, __data_start__ + la a2, __data_end__ + bgeu a1, a2, 2f +1: + lw t0, (a0) + sw t0, (a1) + addi a0, a0, 4 + addi a1, a1, 4 + bltu a1, a2, 1b +2: + + /* Clear bss section */ + la a0, __bss_start__ + la a1, __bss_end__ + bgeu a0, a1, 2f +1: + sw zero, (a0) + addi a0, a0, 4 + bltu a0, a1, 1b +2: + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal entry + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .bss + + .align 3 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: diff --git a/bsp/thead-smart/drivers/sys_freq.c b/bsp/thead-smart/drivers/sys_freq.c new file mode 100644 index 0000000000..7a3341d506 --- /dev/null +++ b/bsp/thead-smart/drivers/sys_freq.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen setting system frequency + */ + + +#include <stdint.h> +#include <soc.h> +#include <sys_freq.h> + +extern int g_system_clock; + +int32_t drv_get_cpu_freq(int32_t idx) +{ + return g_system_clock; +} + +int32_t drv_get_usi_freq(int32_t idx) +{ + return g_system_clock; +} + +int32_t drv_get_usart_freq(int32_t idx) +{ + return g_system_clock; +} + +int32_t drv_get_pwm_freq(int32_t idx) +{ + return g_system_clock; +} + +int32_t drv_get_i2s_freq(int32_t idx) +{ + return g_system_clock; +} + +int32_t drv_get_sys_freq(void) +{ + return g_system_clock; +} + +int32_t drv_get_rtc_freq(int32_t idx) +{ + return g_system_clock; +} + +int32_t drv_get_apb_freq(void) +{ + return g_system_clock; +} + +int32_t drv_get_timer_freq(int32_t idx) +{ + return g_system_clock; +} diff --git a/bsp/thead-smart/drivers/sys_freq.h b/bsp/thead-smart/drivers/sys_freq.h new file mode 100644 index 0000000000..5bf2086833 --- /dev/null +++ b/bsp/thead-smart/drivers/sys_freq.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen header file for setting system frequency + */ + +#ifndef _SYS_FREQ_H_ +#define _SYS_FREQ_H_ + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t drv_get_i2s_freq(int32_t idx); +int32_t drv_get_pwm_freq(int32_t idx); +int32_t drv_get_usart_freq(int32_t idx); +int32_t drv_get_usi_freq(int32_t idx); +int32_t drv_get_sys_freq(void); +int32_t drv_get_apb_freq(void); +int32_t drv_get_rtc_freq(int32_t idx); +int32_t drv_get_timer_freq(int32_t idx); + +int32_t drv_get_cpu_freq(int32_t idx); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FREQ_H_ */ + diff --git a/bsp/thead-smart/drivers/system.c b/bsp/thead-smart/drivers/system.c new file mode 100644 index 0000000000..31a05f1afa --- /dev/null +++ b/bsp/thead-smart/drivers/system.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen CSI Device System Source File + */ + +#include <csi_config.h> +#include <soc.h> +#include <csi_core.h> +#include <drv_irq.h> + +#ifndef CONFIG_SYSTICK_HZ +#define CONFIG_SYSTICK_HZ 100 +#endif + +int g_system_clock = IHS_VALUE; +extern int32_t g_top_irqstack; +extern void irq_vectors_init(void); +extern void mm_heap_initialize(void); + +int SystemCoreClock = IHS_VALUE; /* System Core Clock Frequency */ +extern int __Vectors; + +void SystemCoreClockUpdate(void) +{ + SystemCoreClock = IHS_VALUE; +} + + +static void _system_init_for_kernel(void) +{ + irq_vectors_init(); + + csi_coret_config(drv_get_sys_freq() / CONFIG_SYSTICK_HZ, CORET_IRQn); //10ms + drv_irq_enable(CORET_IRQn); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + int i; + /* enable mstatus FS */ +#if ((CONFIG_CPU_E906F==1) || (CONFIG_CPU_E906FD==1)) + uint32_t mstatus = __get_MSTATUS(); + mstatus |= (1 << 13); + __set_MSTATUS(mstatus); +#endif + + /* enable mxstatus THEADISAEE */ + uint32_t mxstatus = __get_MXSTATUS(); + mxstatus |= (1 << 22); + /* enable mxstatus MM */ +#if ((CONFIG_CPU_E906==1) || (CONFIG_CPU_E906F==1) || (CONFIG_CPU_E906FD==1)) + mxstatus |= (1 << 15); +#endif + __set_MXSTATUS(mxstatus); + + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) + { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + + csi_dcache_enable(); + csi_icache_enable(); + drv_irq_enable(Machine_Software_IRQn); + + _system_init_for_kernel(); +} diff --git a/bsp/thead-smart/drivers/trap_c.c b/bsp/thead-smart/drivers/trap_c.c new file mode 100644 index 0000000000..b236714100 --- /dev/null +++ b/bsp/thead-smart/drivers/trap_c.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen source file for the trap process + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <csi_config.h> +#include <csi_core.h> + +void (*trap_c_callback)(void); + +void trap_c(uint32_t *regs) +{ + int i; + uint32_t vec = 0; + + vec = __get_MCAUSE() & 0x3FF; + + printf("CPU Exception: NO.%d", vec); + printf("\n"); + + for (i = 0; i < 31; i++) + { + printf("x%d: %08x\t", i + 1, regs[i]); + + if ((i % 4) == 3) + { + printf("\n"); + } + } + + printf("\n"); + printf("mepc : %08x\n", regs[31]); + printf("mstatus: %08x\n", regs[32]); + + if (trap_c_callback) + { + trap_c_callback(); + } + + while (1); +} + diff --git a/bsp/thead-smart/drivers/vectors.S b/bsp/thead-smart/drivers/vectors.S new file mode 100644 index 0000000000..3bfa3c70b7 --- /dev/null +++ b/bsp/thead-smart/drivers/vectors.S @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2017-2019 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-20 zx.chen define default vector handlers. + */ + + +#include <csi_config.h> + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .bss + .align 2 + .globl g_trapstackalloc + .global g_trapstackbase + .global g_top_trapstack +g_trapstackalloc: +g_trapstackbase: + .space 768 +g_top_trapstack: + + .align 2 + .globl g_trap_sp + .type g_trap_sp, object +g_trap_sp: + .long 0 + .size g_trap_sp, .-g_trap_sp + +irq_nested_level: +.long 0 +#ifdef ARCH_RISCV_FPU +irq_mstatus_fs_flag: +.long 0 +#endif + +.text + + .align 2 + .global Default_IRQHandler + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + ipush + +#ifdef ARCH_RISCV_FPU + csrr t1, mstatus + srli t1, t1, 13 + andi t1, t1, 0x3 + la t3, irq_mstatus_fs_flag + sw t1, (t3) + li t0, 0x3 + bne t1, t0, .F_RegNotSave1 + + addi sp, sp, -(20 * FREGBYTES) + + FSTORE ft0, 0 * FREGBYTES(sp) + FSTORE ft1, 1 * FREGBYTES(sp) + FSTORE ft2, 2 * FREGBYTES(sp) + FSTORE ft3, 3 * FREGBYTES(sp) + FSTORE ft4, 4 * FREGBYTES(sp) + FSTORE ft5, 5 * FREGBYTES(sp) + FSTORE ft6, 6 * FREGBYTES(sp) + FSTORE ft7, 7 * FREGBYTES(sp) + FSTORE fa0, 8 * FREGBYTES(sp) + FSTORE fa1, 9 * FREGBYTES(sp) + FSTORE fa2, 10 * FREGBYTES(sp) + FSTORE fa3, 11 * FREGBYTES(sp) + FSTORE fa4, 12 * FREGBYTES(sp) + FSTORE fa5, 13 * FREGBYTES(sp) + FSTORE fa6, 14 * FREGBYTES(sp) + FSTORE fa7, 15 * FREGBYTES(sp) + FSTORE ft8, 16 * FREGBYTES(sp) + FSTORE ft9, 17 * FREGBYTES(sp) + FSTORE ft10, 18 * FREGBYTES(sp) + FSTORE ft11, 19 * FREGBYTES(sp) +.F_RegNotSave1: +#endif + + csrr t1, mcause + andi t1, t1, 0x3FF + slli t1, t1, 2 + la t0, g_irqvector + add t0, t0, t1 + lw t2, (t0) + jalr t2 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + +#ifdef ARCH_RISCV_FPU + la t0, irq_mstatus_fs_flag + lw t1, (t0) + li t0, 0x3 + bne t1, t0, .F_RegNotLoad + + FLOAD ft0, 0 * FREGBYTES(sp) + FLOAD ft1, 1 * FREGBYTES(sp) + FLOAD ft2, 2 * FREGBYTES(sp) + FLOAD ft3, 3 * FREGBYTES(sp) + FLOAD ft4, 4 * FREGBYTES(sp) + FLOAD ft5, 5 * FREGBYTES(sp) + FLOAD ft6, 6 * FREGBYTES(sp) + FLOAD ft7, 7 * FREGBYTES(sp) + FLOAD fa0, 8 * FREGBYTES(sp) + FLOAD fa1, 9 * FREGBYTES(sp) + FLOAD fa2, 10 * FREGBYTES(sp) + FLOAD fa3, 11 * FREGBYTES(sp) + FLOAD fa4, 12 * FREGBYTES(sp) + FLOAD fa5, 13 * FREGBYTES(sp) + FLOAD fa6, 14 * FREGBYTES(sp) + FLOAD fa7, 15 * FREGBYTES(sp) + FLOAD ft8, 16 * FREGBYTES(sp) + FLOAD ft9, 17 * FREGBYTES(sp) + FLOAD ft10,18 * FREGBYTES(sp) + FLOAD ft11,19 * FREGBYTES(sp) + + addi sp, sp, (20 * FREGBYTES) +.F_RegNotLoad: +#endif + ipop + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + /* Check for interrupt */ + addi sp, sp, -4 + sw t0, 0x0(sp) + csrr t0, mcause + blt t0, x0, .Lirq + addi sp, sp, 4 + la t0, g_trap_sp + + addi t0, t0, -132 + + sw x1, 0(t0) + sw x2, 4(t0) + sw x3, 8(t0) + sw x4, 12(t0) + sw x6, 20(t0) + sw x7, 24(t0) + sw x8, 28(t0) + sw x9, 32(t0) + sw x10, 36(t0) + sw x11, 40(t0) + sw x12, 44(t0) + sw x13, 48(t0) + sw x14, 52(t0) + sw x15, 56(t0) + sw x16, 60(t0) + sw x17, 64(t0) + sw x18, 68(t0) + sw x19, 72(t0) + sw x20, 76(t0) + sw x21, 80(t0) + sw x22, 84(t0) + sw x23, 88(t0) + sw x24, 92(t0) + sw x25, 96(t0) + sw x26, 100(t0) + sw x27, 104(t0) + sw x28, 108(t0) + sw x29, 112(t0) + sw x30, 116(t0) + sw x31, 120(t0) + + csrr a0, mepc + sw a0, 124(t0) + csrr a0, mstatus + sw a0, 128(t0) + + mv a0, t0 + lw t0, -4(sp) + mv sp, a0 + sw t0, 16(sp) + + jal trap_c + + +.Lirq: + lw t0, 0x0(sp) + addi sp, sp, 4 + j Default_IRQHandler + + .align 6 + .weak Default_Handler + .global Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap + +.NMI_Handler: + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + addi sp, sp, -64 + + sw ra, 0(sp) + sw t0, 4(sp) + sw t1, 8(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#ifdef ARCH_RISCV_FPU + addi sp, sp, -(20*FREGBYTES) + FSTORE ft0, 0 * FREGBYTES(sp) + FSTORE ft1, 1 * FREGBYTES(sp) + FSTORE ft2, 2 * FREGBYTES(sp) + FSTORE ft3, 3 * FREGBYTES(sp) + FSTORE ft4, 4 * FREGBYTES(sp) + FSTORE ft5, 5 * FREGBYTES(sp) + FSTORE ft6, 6 * FREGBYTES(sp) + FSTORE ft7, 7 * FREGBYTES(sp) + FSTORE fa0, 8 * FREGBYTES(sp) + FSTORE fa1, 9 * FREGBYTES(sp) + FSTORE fa2, 10 * FREGBYTES(sp) + FSTORE fa3, 11 * FREGBYTES(sp) + FSTORE fa4, 12 * FREGBYTES(sp) + FSTORE fa5, 13 * FREGBYTES(sp) + FSTORE fa6, 14 * FREGBYTES(sp) + FSTORE fa7, 15 * FREGBYTES(sp) + FSTORE ft8, 16 * FREGBYTES(sp) + FSTORE ft9, 17 * FREGBYTES(sp) + FSTORE ft10, 18 * FREGBYTES(sp) + FSTORE ft11, 19 * FREGBYTES(sp) +#endif + + la t0, g_nmivector + lw t0, (t0) + jalr t0 + +#ifdef ARCH_RISCV_FPU + FLOAD ft0, 0 * FREGBYTES(sp) + FLOAD ft1, 1 * FREGBYTES(sp) + FLOAD ft2, 2 * FREGBYTES(sp) + FLOAD ft3, 3 * FREGBYTES(sp) + FLOAD ft4, 4 * FREGBYTES(sp) + FLOAD ft5, 5 * FREGBYTES(sp) + FLOAD ft6, 6 * FREGBYTES(sp) + FLOAD ft7, 7 * FREGBYTES(sp) + FLOAD fa0, 8 * FREGBYTES(sp) + FLOAD fa1, 9 * FREGBYTES(sp) + FLOAD fa2, 10 * FREGBYTES(sp) + FLOAD fa3, 11 * FREGBYTES(sp) + FLOAD fa4, 12 * FREGBYTES(sp) + FLOAD fa5, 13 * FREGBYTES(sp) + FLOAD fa6, 14 * FREGBYTES(sp) + FLOAD fa7, 15 * FREGBYTES(sp) + FLOAD ft8, 16 * FREGBYTES(sp) + FLOAD ft9, 17 * FREGBYTES(sp) + FLOAD ft10, 18 * FREGBYTES(sp) + FLOAD ft11, 19 * FREGBYTES(sp) + + addi sp, sp, (20 * FREGBYTES) +#endif + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + + addi sp, sp, 64 + mret + + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .globl \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + def_irq_handler STIM0_IRQHandler + def_irq_handler STIM1_IRQHandler + def_irq_handler STIM2_IRQHandler + def_irq_handler STIM3_IRQHandler + def_irq_handler TIM0_IRQHandler + def_irq_handler TIM1_IRQHandler + def_irq_handler TIM2_IRQHandler + def_irq_handler TIM3_IRQHandler + def_irq_handler USART_IRQHandler + def_irq_handler GPIO0_IRQHandler + def_irq_handler GPIO1_IRQHandler + def_irq_handler GPIO2_IRQHandler + def_irq_handler GPIO3_IRQHandler + def_irq_handler GPIO4_IRQHandler + def_irq_handler GPIO5_IRQHandler + def_irq_handler GPIO6_IRQHandler + def_irq_handler GPIO7_IRQHandler + def_irq_handler PAD_IRQHandler + def_irq_handler TIM6_IRQHandler + def_irq_handler TIM7_IRQHandler + def_irq_handler TIM8_IRQHandler + def_irq_handler TIM9_IRQHandler + def_irq_handler TIM10_IRQHandler + def_irq_handler TIM11_IRQHandler + diff --git a/bsp/thead-smart/gcc_csky.ld b/bsp/thead-smart/gcc_csky.ld new file mode 100644 index 0000000000..a0303d19eb --- /dev/null +++ b/bsp/thead-smart/gcc_csky.ld @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************** + * @file gcc_csky.h + * @brief csky linker file for PHOBOS + * @version V1.0 + * @date 02. June 2017 + ******************************************************************************/ +MEMORY +{ + I-SRAM : ORIGIN = 0x0 , LENGTH = 0x40000 /* I-SRAM 256KB */ + D-SRAM : ORIGIN = 0x20000000 , LENGTH = 0xc0000 /* D-SRAM 768KB */ + O-SRAM : ORIGIN = 0x50000000 , LENGTH = 0x800000 /* off-chip SRAM 8MB */ + SRAM : ORIGIN = 0x60000000 , LENGTH = 0x20000 /* on-chip SRAM 128KB */ +} + +PROVIDE (__StackTop = 0x200c0000 - 0x8); +PROVIDE (Stack_Size = 0x1000); + +REGION_ALIAS("REGION_TEXT", I-SRAM); +REGION_ALIAS("REGION_RODATA", I-SRAM); +REGION_ALIAS("REGION_CUSTOM1", D-SRAM); +REGION_ALIAS("REGION_CUSTOM2", D-SRAM); +REGION_ALIAS("REGION_DATA", D-SRAM); +REGION_ALIAS("REGION_BSS", D-SRAM); + +ENTRY(Reset_Handler) +SECTIONS +{ + .text : AT(ADDR(.text)){ + . = ALIGN(0x4) ; + __stext = . ; + KEEP(*startup.o(*.text*)) + *(.text) + *(.text*) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.gnu.linkonce.t*) + *(.glue_7t) + *(.glue_7) + *(.jcr) + *(.init) + *(.fini) + . = ALIGN (4) ; + PROVIDE(__ctbp = .); + *(.call_table_data) + *(.call_table_text) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + . = ALIGN(0x10) ; + __etext = . ; + } > REGION_TEXT + .eh_frame_hdr : { + *(.eh_frame_hdr) + } > REGION_TEXT + .eh_frame : ONLY_IF_RO { + KEEP (*(.eh_frame)) + } > REGION_TEXT + .gcc_except_table : ONLY_IF_RO { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_TEXT + .rodata :{ + . = ALIGN(0x4) ; + __srodata = .; + *(.rdata) + *(.rdata*) + *(.rdata1) + *(.rdata.*) + *(.rodata) + *(.rodata1) + *(.rodata*) + *(.rodata.*) + *(.rodata.str1.4) + . = ALIGN(0x4) ; + __ctor_start__ = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __ctor_end__ = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __dtor_end__ = .; + . = ALIGN(0x4) ; + __erodata = .; + __rodata_end__ = .; + } > REGION_RODATA + .data : { + . = ALIGN(0x4) ; + __sdata = . ; + __data_start__ = . ; + data_start = . ; + KEEP(*startup.o(*.vectors*)) + *(.got.plt) + *(.got) + *(.gnu.linkonce.r*) + *(.data) + *(.data*) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + *(.data1) + *(.gcc_except_table) + *(.gcc_except_table*) + __start_init_call = .; + *(.initcall.init) + __stop_init_call = .; + __start_cmd = .; + *(.bootloaddata.cmd) + . = ALIGN(4) ; + __stop_cmd = .; + __global_pointer$ = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(__libc_atexit) + *(__libc_subinit) + *(__libc_subfreeres) + *(.note.ABI-tag) + __edata = .; + __data_end__ = .; + . = ALIGN(0x4) ; + + } > REGION_DATA AT > REGION_RODATA + .eh_frame : ONLY_IF_RW { + KEEP (*(.eh_frame)) + } > REGION_DATA AT > REGION_RODATA + .gcc_except_table : ONLY_IF_RW { + *(.gcc_except_table .gcc_except_table.*) + __edata = .; + __data_end__ = .; + } > REGION_DATA AT > REGION_RODATA + + + .bss : { + . = ALIGN(0x4) ; + __sbss = ALIGN(0x4) ; + __bss_start__ = . ; + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(0x4) ; + __ebss = . ; + __end = . ; + end = . ; + __bss_end__ = .; + } > REGION_BSS + /* End of uninitalized data segement */ + PROVIDE(end = .); +} diff --git a/bsp/thead-smart/rtconfig.h b/bsp/thead-smart/rtconfig.h new file mode 100644 index 0000000000..12e38cb703 --- /dev/null +++ b/bsp/thead-smart/rtconfig.h @@ -0,0 +1,158 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 1000 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 512 + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40003 + +/* RT-Thread CPU arch and features */ + + +/* risc-v arch */ + +#define ARCH_RISCV +#define ARCH_RISCV_32 +#define ARCH_RISCV_FPU +#define ARCH_RISCV_FPU_S + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 1 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 2048 +#define FINSH_CMD_SIZE 80 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_USING_MSH_ONLY +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + + +/* peripheral libraries and drivers */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + +#define SOC_THEAD_SMART +#define RT_USING_UART1 + +#endif diff --git a/bsp/thead-smart/rtconfig.py b/bsp/thead-smart/rtconfig.py new file mode 100644 index 0000000000..be45bc8e84 --- /dev/null +++ b/bsp/thead-smart/rtconfig.py @@ -0,0 +1,68 @@ +import os + +# toolchains options +ARCH ='risc-v' +CPU ='e906' +CPUNAME ='e906f' +VENDOR ='t-head' +CROSS_TOOL ='gcc' + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'/home/xinge/tools/riscv64-elf-x86_64-20200616-1.9.6/bin' +else: + print 'Please make sure your toolchains is GNU GCC!' + exit(0) + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +# BUILD = 'debug' +BUILD = 'release' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'riscv64-unknown-elf-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'g++' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + STRIP = PREFIX + 'strip' + + if CPUNAME == 'e906fd': + DEVICE = ' -march=rv32imafdcxthead -mabi=ilp32d' + if CPUNAME == 'e906f': + DEVICE = ' -march=rv32imafcxthead -mabi=ilp32f' + if CPUNAME == 'e906': + DEVICE = ' -march=rv32imacxthead -mabi=ilp32' + + CFLAGS = DEVICE + ' -c -g -ffunction-sections -fdata-sections -Wall -mcmodel=medlow' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' + LFLAGS = DEVICE + ' -nostartfiles -Wl,--no-whole-archive -T gcc_csky.ld -lm -lc -lgcc -Wl,-gc-sections -Wl,-zmax-page-size=1024' + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2 -g2' + + CXXFLAGS = CFLAGS + +# M_CFLAGS = DEVICE + ' -EL -G0 -O2 -mno-abicalls -fno-common -fno-exceptions -fno-omit-frame-pointer -mlong-calls -fno-pic ' + # M_CXXFLAGS = M_CFLAGS + # M_LFLAGS = DEVICE + ' -EL -r -Wl,--gc-sections,-z,max-page-size=0x4' +\ + # ' -nostartfiles -static-libgcc' + # M_POST_ACTION = STRIP + ' -R .hash $TARGET\n' + SIZE + ' $TARGET \n' + +DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n' +POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' |
