/* * Copyright (c) 2021 Arm Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * * 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. */ #include "hal.h" /* API */ #include "hal_config.h" /* HAL configuration */ #include "system_init.h" #include #include #if defined(ARM_NPU) #include "ethosu_driver.h" /* Arm Ethos-U55 driver header */ #include "timing_adapter.h" /* Arm Ethos-U55 timing adapter driver header */ #include "timing_adapter_settings.h" /* Arm Ethos-U55 timing adapter settings */ /** * @brief Initialises the Arm Ethos-U55 NPU * @return 0 if successful, error code otherwise **/ static int _arm_npu_init(void); #endif /* ARM_NPU */ int hal_init(hal_platform* platform, data_acq_module* data_acq, data_psn_module* data_psn, platform_timer* timer) { assert(platform && data_acq && data_psn); platform->data_acq = data_acq; platform->data_psn = data_psn; platform->timer = timer; platform->platform_init = system_init; platform->platform_release = system_release; system_name(platform->plat_name, sizeof(platform->plat_name)); return 0; } /** * @brief Local helper function to clean the slate for current platform. **/ static void _hal_platform_clear(hal_platform* platform) { assert(platform); platform->inited = 0; } int hal_platform_init(hal_platform* platform) { int state; assert(platform && platform->platform_init); _hal_platform_clear(platform); /* Initialise platform */ if (0 != (state = platform->platform_init())) { printf_err("failed to initialise platform %s\n", platform->plat_name); return state; } /* Initialise the data acquisition module */ if (0 != (state = data_acq_channel_init(platform->data_acq))) { if (!platform->data_acq->inited) { printf_err("failed to initialise data acq module: %s\n", platform->data_acq->system_name); } hal_platform_release(platform); return state; } /* Initialise the presentation module */ if (0 != (state = data_psn_system_init(platform->data_psn))) { printf_err("failed to initialise data psn module: %s\n", platform->data_psn->system_name); data_acq_channel_release(platform->data_acq); hal_platform_release(platform); return state; } #if defined(ARM_NPU) /* If Arm Ethos-U55 NPU is to be used, we initialise it here */ if (0 != (state = _arm_npu_init())) { return state; } #endif /* ARM_NPU */ /* followed by the timer module */ init_timer(platform->timer); info("%s platform initialised\n", platform->plat_name); debug("using %s module for data acquisition\n", platform->data_acq->system_name); debug("using %s module for data presentation\n", platform->data_psn->system_name); platform->inited = !state; return state; } void hal_platform_release(hal_platform *platform) { assert(platform && platform->platform_release); data_acq_channel_release(platform->data_acq); data_psn_system_release(platform->data_psn); _hal_platform_clear(platform); info("releasing platform %s\n", platform->plat_name); platform->platform_release(); } #if defined(ARM_NPU) /** * @brief Defines the Ethos-U interrupt handler: just a wrapper around the default * implementation. **/ static void _arm_npu_irq_handler(void) { /* Call the default interrupt handler from the NPU driver */ ethosu_irq_handler(); } /** * @brief Initialises the NPU IRQ **/ static void _arm_npu_irq_init(void) { const IRQn_Type ethosu_irqnum = (IRQn_Type)EthosU_IRQn; /* Register the EthosU IRQ handler in our vector table. * Note, this handler comes from the EthosU driver */ NVIC_SetVector(ethosu_irqnum, (uint32_t)_arm_npu_irq_handler); /* Enable the IRQ */ NVIC_EnableIRQ(ethosu_irqnum); debug("EthosU IRQ#: %u, Handler: 0x%p\n", ethosu_irqnum, _arm_npu_irq_handler); } static int _arm_npu_timing_adapter_init(void) { #if defined (TA0_BASE) struct timing_adapter ta_0; struct timing_adapter_settings ta_0_settings = { .maxr = TA0_MAXR, .maxw = TA0_MAXW, .maxrw = TA0_MAXRW, .rlatency = TA0_RLATENCY, .wlatency = TA0_WLATENCY, .pulse_on = TA0_PULSE_ON, .pulse_off = TA0_PULSE_OFF, .bwcap = TA0_BWCAP, .perfctrl = TA0_PERFCTRL, .perfcnt = TA0_PERFCNT, .mode = TA0_MODE, .maxpending = 0, /* This is a read-only parameter */ .histbin = TA0_HISTBIN, .histcnt = TA0_HISTCNT }; if (0 != ta_init(&ta_0, TA0_BASE)) { printf_err("TA0 initialisation failed\n"); return 1; } ta_set_all(&ta_0, &ta_0_settings); #endif /* defined (TA0_BASE) */ #if defined (TA1_BASE) struct timing_adapter ta_1; struct timing_adapter_settings ta_1_settings = { .maxr = TA1_MAXR, .maxw = TA1_MAXW, .maxrw = TA1_MAXRW, .rlatency = TA1_RLATENCY, .wlatency = TA1_WLATENCY, .pulse_on = TA1_PULSE_ON, .pulse_off = TA1_PULSE_OFF, .bwcap = TA1_BWCAP, .perfctrl = TA1_PERFCTRL, .perfcnt = TA1_PERFCNT, .mode = TA1_MODE, .maxpending = 0, /* This is a read-only parameter */ .histbin = TA1_HISTBIN, .histcnt = TA1_HISTCNT }; if (0 != ta_init(&ta_1, TA1_BASE)) { printf_err("TA1 initialisation failed\n"); return 1; } ta_set_all(&ta_1, &ta_1_settings); #endif /* defined (TA1_BASE) */ return 0; } static int _arm_npu_init(void) { int err = 0; /* If the platform has timing adapter blocks along with Ethos-U55 core * block, initialise them here. */ if (0 != (err = _arm_npu_timing_adapter_init())) { return err; } /* Initialise the IRQ */ _arm_npu_irq_init(); /* Initialise Ethos-U55 device */ const void * ethosu_base_address = (void *)(SEC_ETHOS_U55_BASE); if (0 != (err = ethosu_init_v3( ethosu_base_address, /* Ethos-U55's base address. */ NULL, /* Pointer to fast mem area - NULL for U55. */ 0, /* Fast mem region size. */ 1, /* Security enable. */ 1))) { /* Privilege enable. */ printf_err("failed to initalise Ethos-U55 device\n"); return err; } info("Ethos-U55 device initialised\n"); /* Get Ethos-U55 version */ struct ethosu_version version; if (0 != (err = ethosu_get_version(&version))) { printf_err("failed to fetch Ethos-U55 version info\n"); return err; } info("Ethos-U55 version info:\n"); info("\tArch: v%u.%u.%u\n", version.id.arch_major_rev, version.id.arch_minor_rev, version.id.arch_patch_rev); info("\tDriver: v%u.%u.%u\n", version.id.driver_major_rev, version.id.driver_minor_rev, version.id.driver_patch_rev); info("\tMACs/cc: %u\n", (1 << version.cfg.macs_per_cc)); info("\tCmd stream: v%u\n", version.cfg.cmd_stream_version); info("\tSHRAM size: %u\n", version.cfg.shram_size); return 0; } #endif /* ARM_NPU */