Hi there,
I'm working with Linux processor-sdk 05.02.00.10 and RTOS processor-sdk 4.03.00.05.
I'm using Jailhouse hypervisor on a AM5728 based custom board, on which I'm running Linux on A15 core0 and TI-RTOS on A15 core1.
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi there,
I'm working with Linux processor-sdk 05.02.00.10 and RTOS processor-sdk 4.03.00.05.
I'm using Jailhouse hypervisor on a AM5728 based custom board, on which I'm running Linux on A15 core0 and TI-RTOS on A15 core1.
Hi Nir, how are you measuring latency? Are you using Timestamp_get64()? if so, it is possible to use an scope with a GPIO?.. just to confirm jitter is actually high.. In the past we saw RTOS Timestamp_get64() being messed up as a consequence of CPU frequency changes.
It sounds that you took care of CPU frequency changes by setting scaling_min_freq=1500000 as mentioned in this E2E, but any how if you can add a GPIO/Scope to measure jitter it would be good.
Also, adding a OS aware tracer (ex: Lauterbach) could be helpful as you can get synchronized tracer in Linux/RTOS so you can see what is going on on both sides when the spike in jitter happens.
thank you,
Paula
Hi Paula,
I'm measuring the jitter with a scope and a GPIO toggle on the ISR.
I'm not familiar with Lauterbach, but I will learn the subject.
Anyway, can you give me pointers about what I should investigate in my system?
Can RCU or swapping be related?
How come executing "ls" on the Linux command line or even just a meaning less string can cause a spike in jitter on the TI-RTOS side?
Thanks for your help,
Nir
Nir, are you using OOB jailhouse example from Processor SDK? if not, or if modified (most likely) could you summarize DTS changes? I am not a Linux expert, I will loop one of my colleagues, but maybe something is miss-configured. Simple linux commands shouldn't spike TI-RTOS jitter, specially because you mentioned there are not resources shared between Linux-RTOS in you application.
A multi-core, multi-OS system is not that easy to debug. One way, is to have a tracer that is capable of gather information from both cores and can sync them. Those tracers are also not that simple to setup (you would need top prepare some scripts) but they gave a better visibility of the whole system.
Thank you,
Paula
Hi Paula,
I'm running our custom TI-RTOS app, not a TI supplied example.
For that matter, I made some modifications to am572x-idk-jailhouse-dtsi, mostly disabling components that are used by TI-RTOS.
From my memory, I disabled GPIO1, GPIO5, all SPIs, GPMC, UART10.
Also I skipped some MPU IRQs that are used by TI-RTOS (GPIO1, SPI2, PRU).
Later I will post the dtsi file and the root cell and inmate cell configuration files. Maybe you will be able to notice something.
I have a simple memory communication region between the 2 cells, not IVSHMEM.
Hi Nir, is it possible to reproduce the issue on TI's AM5728 board? if so, could you share an example application that triggers the issue?
thank you,
Paula
Hi Paula,
Attached are the root cell and the inmate cell configs, along with the dtsi.
I will make an attempt to reproduce the issue on the AM5728 evaluation board, but it's not simple because for months I've been developing on the custom board.
Could this be a kernel config issue?
Does it make sense to port Jailhouse Hypervisor to a newer version?
Thanks,
Nir.
/* * Jailhouse, a Linux-based partitioning hypervisor * * Copyright (c) Texas Insturments. Inc, 2016 * * Authors: * Vitaly Andrianov <vitalya@ti.com> * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. */ #include <jailhouse/types.h> #include <jailhouse/cell-config.h> #define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0]) struct { struct jailhouse_system header; __u64 cpus[1]; struct jailhouse_memory mem_regions[21]; struct jailhouse_irqchip irqchips[2]; } __attribute__((packed)) config = { .header = { .signature = JAILHOUSE_SYSTEM_SIGNATURE, .revision = JAILHOUSE_CONFIG_REVISION, .hypervisor_memory = { .phys_start = 0xAF000000, .size = 0x1000000, }, .debug_console = { .address = 0x4806A000, /* Hypervisor Debug Console - UART1 */ .size = 0x1000, /* .divider = 26, */ .flags = JAILHOUSE_CON1_TYPE_8250 | JAILHOUSE_CON1_ACCESS_MMIO | JAILHOUSE_CON1_REGDIST_4 | JAILHOUSE_CON2_TYPE_ROOTPAGE, }, .platform_info.arm = { .gic_version = 2, .gicd_base = 0x48211000, .gicc_base = 0x48212000, .gich_base = 0x48214000, .gicv_base = 0x48216000, .maintenance_irq = 25, }, .root_cell = { .name = "AM57XX-EVM", .cpu_set_size = sizeof(config.cpus), .num_memory_regions = ARRAY_SIZE(config.mem_regions), .num_irqchips = ARRAY_SIZE(config.irqchips), }, }, .cpus = { 0x3, }, .mem_regions = { /* PCI */ { .phys_start = 0x20000000, .virt_start = 0x20000000, .size = 0x10000000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* OCMCRAM */ { .phys_start = 0x40300000, .virt_start = 0x40300000, .size = 0x80000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* 0x40380000 - 0x48020000 */ { .phys_start = 0x40380000, .virt_start = 0x40380000, .size = 0x7CA0000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* GPIO 7,8,2,3,4,5,6 */ { .phys_start = 0x48051000, .virt_start = 0x48051000, .size = 0xE000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* Linux Serial Debug Console - UART1 */ { .phys_start = 0x4806A000, .virt_start = 0x4806A000, .size = 0x1000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* I2C1 */ { .phys_start = 0x48070000, .virt_start = 0x48070000, .size = 0x2000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* MMC2 */ { .phys_start = 0x480B4000, .virt_start = 0x480B4000, .size = 0x2000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* 0x48100000 - 0x48281000 */ { .phys_start = 0x48100000, .virt_start = 0x48100000, .size = 0x110000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* * Leave gap for GIC controller 0x48210000 - 0x41220000 */ /* 0x48220000 - 0x48281000 */ { .phys_start = 0x48220000, .virt_start = 0x48220000, .size = 0x610000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* OMAP WakeupGen */ { .phys_start = 0x48281000, .virt_start = 0x48281000, .size = 0x1000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* PRCM MPU */ { .phys_start = 0x48243000, .virt_start = 0x48243000, .size = 0x1000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* 0x48400000 - 0x48424000 */ { .phys_start = 0x48400000, .virt_start = 0x48400000, .size = 0x24000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* UART... */ { .phys_start = 0x48424000, .virt_start = 0x48424000, .size = 0x2000,//0x00001000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* 0x48426000 - 0x48826000 */ { .phys_start = 0x48426000, .virt_start = 0x48426000, .size = 0x400000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* 0x48826000 - 0x48828000 */ { .phys_start = 0x48826000, .virt_start = 0x48826000, .size = 0x2000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* 0x48828000 - 0x4B300000 */ { .phys_start = 0x48828000, .virt_start = 0x48828000, .size = 0x2AD8000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* 0x4B500000 - 0x58000000 */ { .phys_start = 0x4B500000, .virt_start = 0x4B500000, .size = 0xCB00000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* Display Subsystem & ...*/ { .phys_start = 0x58000000, .virt_start = 0x58000000, .size = 0x8000000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* RAM */ { .phys_start = 0x80000000, .virt_start = 0x80000000, .size = 0x2EF00000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_EXECUTE, }, /* communication region */ { .phys_start = 0xAEF00000, .virt_start = 0xAEF00000, .size = 0x00100000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO, }, /* * Leave hole for hypervisor * jh inmate: start 0xa0000000, size 0x0f000000 * hypervisor: start 0xaf000000, size 0x01000000 * End at 0xb0000000 * * RAM and comm region overlap with jh inmate, and that's the way it is * intended to be. The inmate cell configuration take care of that. */ /* RAM */ { .phys_start = 0xB0000000, .virt_start = 0xB0000000, .size = 0x10000000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_EXECUTE, }, }, .irqchips = { /* GIC */ { .address = 0x48211000, .pin_base = 32, .pin_bitmap = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, }, /* GIC */ { .address = 0x48211000, .pin_base = 160, .pin_bitmap = { 0xffffffff, 0, 0, 0 }, }, }, };
/* * Jailhouse, a Linux-based partitioning hypervisor * * Configuration for uart-demo inmate on AM57XX-EVM: * * Copyright (c) Texas Instruments, Inc. * * Authors: * Vitaly Andrianiov <vitalya@ti.com> * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. */ #include <jailhouse/types.h> #include <jailhouse/cell-config.h> #define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0]) struct { struct jailhouse_cell_desc cell; __u64 cpus[1]; struct jailhouse_memory mem_regions[16]; struct jailhouse_irqchip irqchips[2]; } __attribute__((packed)) config = { .cell = { .signature = JAILHOUSE_CELL_DESC_SIGNATURE, .revision = JAILHOUSE_CONFIG_REVISION, .name = "AM5728-RTOS-SHMEM", .flags = JAILHOUSE_CELL_PASSIVE_COMMREG, .num_irqchips = ARRAY_SIZE(config.irqchips), .cpu_set_size = sizeof(config.cpus), .num_memory_regions = ARRAY_SIZE(config.mem_regions), }, .cpus = { 0x2, }, .mem_regions = { /* GPMC */ { .phys_start = 0x08000000, .virt_start = 0x08000000, .size = 0x40000, /* 256 KiB */ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* SYS EDMA TPCC */ { .phys_start = 0x43300000, .virt_start = 0x43300000, .size = 0x100000, /* 1 MB */ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* UART... */ { .phys_start = 0x48020000, .virt_start = 0x48020000, .size = 0x1000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* GPIO, I2C */ { .phys_start = 0x48050000, .virt_start = 0x48050000, .size = 0x40000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* McSPI1 */ { .phys_start = 0x48098000, .virt_start = 0x48098000, .size = 0x1000, /* 4 KiB */ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* McSPI2 */ { .phys_start = 0x4809A000, .virt_start = 0x4809A000, .size = 0x1000, /* 4 KiB */ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* McSPI3 */ { .phys_start = 0x480B8000, .virt_start = 0x480B8000, .size = 0x1000, /* 4 KiB */ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* McSPI4 */ { .phys_start = 0x480BA000, .virt_start = 0x480BA000, .size = 0x1000, /* 4 KiB */ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* MMC1 */ { .phys_start = 0x4809C000, .virt_start = 0x4809C000, .size = 0x2000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* L4_CFG */ { .phys_start = 0x4a000000, .virt_start = 0x4a000000, .size = 0xE10000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* GPIO1 */ { .phys_start = 0x4ae10000, .virt_start = 0x4ae10000, .size = 0x40000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* PRUSS */ { .phys_start = 0x4b200000, .virt_start = 0x4b200000, .size = 0x100000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* GPMC Config registers */ { .phys_start = 0x50000000, .virt_start = 0x50000000, .size = 0x1000000, /* 16 MiB */ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, /* RAM loader */ { .phys_start = 0xad000000, .virt_start = 0x0, .size = 0x10000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE, }, /* RAM RTOS 224MB*/ { .phys_start = 0xa0000000, .virt_start = 0x80000000, .size = 0xd000000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE, }, /* communication region */ { .phys_start = 0xAEF00000, .virt_start = 0xAEF00000, .size = 0x00100000, .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED, }, }, .irqchips = { /* GIC */ { .address = 0x48211000, .pin_base = 32, .pin_bitmap = { 0x20000000, /* GPIO1_IRQ_1: 29 */ 0, 0x4, /* SPI2: 66 */ 0 }, }, /* GIC 2 */ { .address = 0x48211000, .pin_base = 160, .pin_bitmap = { 0x000003c0, /* PRU interrupts: 134 135 136 137 */ }, }, } };
/* * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ / { model = "TI AM5728 JAILHOUSE IDK"; reserved-memory { jailhouse: jailhouse@bec00000 { reg = <0x0 0xaf000000 0x0 0x1000000>; no-map; status = "okay"; }; jh_inmate: jh_inmate@afc00000 { reg = <0x0 0xa0000000 0x0 0xf000000>; no-map; status = "okay"; }; }; }; &timer2 { status = "disabled"; ti,no-idle; }; &timer8 { status = "disabled"; ti,no-idle; }; &uart10 { status = "disabled"; ti,no-idle; }; / { ocp { pruss1_eth { status = "disabled"; }; pruss2_eth { status = "disabled"; }; crossbar_mpu: crossbar@4a002a48 { ti,irqs-skip = <29 66 134 135 136 137>; /* * 29 - GPIO1 IRQ1 * 66 - SPI2 * 134 to 137 - PRU interrupts */ }; }; }; &pruss1 { status = "disabled"; ti,no-idle; }; &pru1_0 { status = "disabled"; ti,no-idle; }; &pru1_1 { status = "disabled"; ti,no-idle; }; &pruss2 { status = "disabled"; ti,no-idle; }; &pru2_0 { status = "disabled"; ti,no-idle; }; &pru2_1 { ti,no-idle; status = "disabled"; }; &pruss1_mdio { ti,no-idle; status = "disabled"; }; &pruss2_mdio { ti,no-idle; status = "disabled"; }; &gpio1 { ti,no-idle; ti,no-idle-on-init; ti,no-reset-on-init; status = "disabled"; }; /*&gpio3 { Currently used by vnetdevice. DO NOT DISABLE ti,no-idle; status = "disabled"; };*/ &gpio5 { ti,no-idle; status = "disabled"; }; &i2c1 { ti,no-idle; ti,no-reset-on-init; /*status = "disabled";*/ }; &mmc1 { ti,no-idle; status = "disabled"; }; &mcspi1 { ti,no-idle; status = "disabled"; }; &mcspi2 { ti,no-idle; status = "disabled"; }; &mcspi3 { ti,no-idle; status = "disabled"; }; &mcspi4 { ti,no-idle; status = "disabled"; }; &gpmc { ti,no-idle; status = "disable"; };
Hi Paula,
I'm able to reproduce the problem on the AM5728 evaluation board.
I can notice two problems.
First is interrupt latency of up to 6 usec when I invoke commands on the Linux command line.
The jitter can go up to 9 usec when copying a file with scp to the am5728 eval board storage device or extracting an rpm.
My high precision interrupt is running 31.25 usec cycle time, and 9 usec jitter is too high. If the cpus are truly isolated
we expect to have no jitter at all as a result of some activity on the Linux side. We suspect that 9 usec jitter implies a software
bug and not a hardware issue. Perhaps the kernel is blocking interrupts on core 1?
Second problem is task execution time jitter.
The timer ISR posts a semaphore that releases a task to perform 1 cycle. I measure the execution time with 32bit timestamp and I get clear
latency whenever I invoke commands on the Linux command line, 25% longer execution time and sometimes more.
Why is that?
The rtos inmate app configures a timer at 31.25 useconds. The ISR (mainTimerISR) is toggling GPIO 1_10 and releases a semaphore that allows the task gpio_test to perform 1 cycle. gpio_test is toggling GPIO 1_11 and takes timestamps at the beginning and ending of the code.
I'm using a scope to measure the two GPIOs timings.
pinmux is adjusted from Linux command line by a config script.
Jitter measurement is reset every 10 seconds to make it more noticeable.
GPIO1_10: J21/51 - AM57XX_GPMC_AD4
GPIO1_11: J21/53 - AM57XX_GPMC_AD5
The kernel is taken from git://git.ti.com/processor-sdk/processor-sdk-linux.git
branch processor-sdk-linux-rt-4.14.y
commit 28d73230daa45803af5fed792bf635fe40ee3dbd
Attached are the kernel config, the root cell configuration, inmate cell configuration and config and startup script, as well as the rtos app.
I'd appreciate it very much if you could reproduce the problem on your side and come up with a solution.
Thanks a lot.
Nir.
Hi Nir,
I'm starting to work on reproducing the problem. I'll keep you posted on my progress.
Since Jailhouse issues are complex, it may take some time to reproduce, debug, and fix the issue.
Regards,
Frank
Hi Frank,
Thank you for the effort.
One minor mistake, I added the wrong root cell config file to Interrupt_Latency_AM5728.zip
Actually, to reproduce the problem on the eval board I'm using the original am57xx-evm.c from Linux processor-sdk 05.02.00.10 without any modifications.
Thanks a lot,
Nir.
Hi Nir, I quick question, have you guys rule-out Linux is not going to low power mode?
thank you,
Paula
Nir, I would like to align with you on Linux PSDK versions. I believed you used PROCESSOR-SDK-LINUX-AM57X 05_02_00_10 and apply and RT patch, or did you use PROCESSOR-SDK-LINUX-RT-AM57X 05_02_00_10?
I believe is the first option but want to confirm. And if so, could you point me from where did you get the RT patch?
thank you,
Paula
Hi Paula,
To set up the SDK I was following http://software-dl.ti.com/processor-sdk-linux/esd/docs/latest/linux/Overview_Building_the_SDK.html.
At the time the latest version was processor-sdk-05.02.00.10.
When building the SDK I used ARAGO_RT_ENABLE=1 which uses linux-ti-staging-rt.
The kernel I got was:
git://git.ti.com/processor-sdk/processor-sdk-linux.git
branch processor-sdk-linux-rt-4.14.y
commit 28d73230daa45803af5fed792bf635fe40ee3dbd
Indeed, this kernel is already patched with RT-PREEMPT. I didn't apply the patch myself.
Thanks,
Nir.
Hi Paula, Frank,
In the jailhouse inmate example that I sent I found that using UART_printf() is extremely expensive, and it causes terrible task execution time jitter.
I removed it and the performance improved.
Still, using a scope I can observe clear 5 usec jitter in the timer interrupt service routine, and 8 usec jitter in task execution time.
This jitter is easily invoked by scp'ing a file to the system, or just executing some command in the linux command line.
I'm attaching the file with the changes I made to remove UART_printf() from the task.
Thanks a lot,
Nir.
/** * \file main.c * * \brief Example application main file. This application will toggle the led. * The led toggling will be done inside an callback function, which * will be called by Interrupt Service Routine. Interrupts are * triggered manually and no external source is used to trigger * interrupts. * */ /* * Copyright (C) 2014 - 2018 Texas Instruments Incorporated - http://www.ti.com/ * * 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 of Texas Instruments Incorporated 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. * */ #ifdef USE_BIOS /* XDCtools Header files */ #include <xdc/std.h> #include <xdc/runtime/System.h> #include <xdc/runtime/Error.h> #include <xdc/runtime/System.h> #include <ti/sysbios/knl/Task.h> #include <xdc/cfg/global.h> #include <ti/sysbios/knl/Semaphore.h> /* BIOS Header files */ #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Task.h> #if defined(SOC_AM65XX) || defined(SOC_J721E) #if defined (__aarch64__) #include <ti/sysbios/family/arm/v8a/Mmu.h> #endif #endif #endif /* #ifdef USE_BIOS */ #include <ti/drv/uart/UART.h> #include <ti/drv/uart/UART_stdio.h> #include <ti/drv/uart/soc/UART_soc.h> #ifdef __cplusplus //#define RT_FUNC(func_name) __attribute__ ((section("rtfunc"))) #define RT_FUNC(func_name) #else #define RT_FUNC(func_name) __attribute__ ((section("rtfunc"))) #endif /* __cplusplus */ #include <stdio.h> /* TI-RTOS Header files */ #include <ti/drv/gpio/GPIO.h> #include <ti/drv/gpio/soc/GPIO_soc.h> #include "GPIO_log.h" #include "GPIO_board.h" #include <ti/board/board.h> #include <ti/sysbios/family/arm/a15/TimestampProvider.h> #include <ti/sysbios/family/arm/systimer/Timer.h> #include <xdc/runtime/Types.h> #if defined(SOC_AM65XX) || defined(SOC_J721E) #include <ti/drv/sciclient/sciclient.h> #endif #include "Debug/configPkg/package/cfg/app_pa15fg.h" extern Board_STATUS Board_init_jh(Board_initCfg cfg); Semaphore_Handle semaphore0; Semaphore_Params semaphoreParams; /********************************************************************** ************************** Macros ************************************ **********************************************************************/ #define DELAY_VALUE (500U) /* 500 msec */ /********************************************************************** ************************** Internal functions ************************ **********************************************************************/ void mainTimerISR(UArg arg0); volatile uint32_t u32MTSTicksCounter = 0; static uint32_t u32_one_sec_rate = 0; static double d_micro_seconds_period = 0.0; /* Delay function */ void AppDelay(unsigned int delayVal); /* Callback function */ void AppGpioCallbackFxn(void); #if defined(idkAM574x) || defined(idkAM572x) || defined(idkAM571x) /* GPIO clock and pinmux configurations */ extern void AppGPIOInit(void); #endif #if defined(idkAM574x) || defined(idkAM572x) extern void GPIOApp_UpdateBoardInfo(void); extern void GPIOAppUpdateConfig(uint32_t *gpioBaseAddr, uint32_t *gpioPin); #endif #if defined(SOC_AM65XX) || defined(SOC_J721E) /* Main domain GPIO interrupt events */ #define MAIN_GPIO_INTRTR_GPIO0_BANK0_INT (0x000000C0) /* GPIO port 0 bank 0 interrupt event #, input to MAIN_GPIO_INTRTR */ #define MAIN_GPIO_INTRTR_GPIO1_BANK0_INT (0x000000C8) /* GPIO port 1 bank 0 interrupt event #, input to MAIN_GPIO_INTRTR */ /* Main domain GPIO interrupt events */ #define WKUP_GPIO_INTRTR_GPIO0_BANK0_INT (0x0000003C) /* GPIO port 0 bank 0 interrupt event #, input to WKUP_GPIO_INTRTR */ /* Main to MCU GPIO interrupt router mux output events */ #define CSL_MAIN2MCU_INTRTR_PLS_GPIOMUX_INT0_DFLT_PLS (0x00000000) #define CSL_MAIN2MCU_INTRTR_PLS_GPIOMUX_INT31_DFLT_PLS (0x0000001F) void GPIO_configIntRouter(uint32_t portNum, uint32_t pinNum, uint32_t gpioIntRtrOutIntNum, GPIO_v0_HwAttrs *cfg) { GPIO_IntCfg *intCfg; uint32_t bankNum; intCfg = cfg->intCfg; #if defined (am65xx_evm) || defined (am65xx_idk) || defined(j721e_sim) /* no main domain GPIO pins directly connected to LEDs on GP EVM, use WKUP domain GPIO pins which connected to LEDs on base board */ cfg->baseAddr = CSL_WKUP_GPIO0_BASE; bankNum = pinNum/16; /* Each GPIO bank has 16 pins */ /* WKUP GPIO int router input interrupt is the GPIO bank interrupt */ #if defined (__aarch64__) #if defined (SOC_AM65XX) intCfg[pinNum].intNum = CSL_GIC0_INTR_WKUP_GPIOMUX_INTRTR0_BUS_OUTP_0 + bankNum; #endif #if defined (SOC_J721E) intCfg[pinNum].intNum = CSLR_WKUP_GPIOMUX_INTRTR0_IN_WKUP_GPIO0_GPIO_BANK_0 + bankNum; #endif #else #if defined (SOC_AM65XX) intCfg[pinNum].intNum = CSL_MCU0_INTR_GPIOMUX_INTR0_OUTP_0 + bankNum; #endif #if defined (SOC_J721E) intCfg[pinNum].intNum = CSLR_ARMSS0_CPU0_INTR_GPIOMUX_INTRTR0_OUTP_16 + bankNum; #endif #endif intCfg[pinNum].eventId = 0; intCfg[pinNum].intcMuxNum = INVALID_INTC_MUX_NUM; intCfg[pinNum].intcMuxInEvent = 0; intCfg[pinNum].intcMuxOutEvent = 0; /* Setup interrupt router configuration for gpio port/pin */ #else /* Use main domain GPIO pins directly connected to IDK EVM */ bankNum = pinNum/16; /* Each GPIO bank has 16 pins */ if (portNum == 0) { /* MAIN GPIO int router input interrupt is the GPIO bank interrupt */ #if defined (__aarch64__) #if defined (SOC_AM65XX) intCfg[pinNum].intNum = CSL_GIC0_INTR_MAIN_GPIOMUX_INTROUTER_MAIN_GPIOMUX_INTROUTER_MAIN_0_BUS_OUTP_0 + bankNum; #endif #if defined (SOC_J721E) intCfg[pinNum].intNum = CSLR_COMPUTE_CLUSTER0_GIC_SPI_GPIOMUX_INTRTR0_OUTP_8 + bankNum; #endif #else #if defined (SOC_AM65XX) intCfg[pinNum].intNum = CSL_MCU0_INTR_MAIN2MCU_PULSE_INTR0_OUTP_0 + bankNum; #endif #if defined (SOC_J721E) intCfg[pinNum].intNum = CSLR_MCU_ARMSS0_CPU0_INTR_MAIN2MCU_PLS_INTRTR0_OUTP_0 + bankNum; #endif #endif } else { #if defined (__aarch64__) #if defined (SOC_AM65XX) intCfg[pinNum].intNum = CSL_GIC0_INTR_MAIN_GPIOMUX_INTROUTER_MAIN_GPIOMUX_INTROUTER_MAIN_0_BUS_OUTP_6 + bankNum; #endif #if defined (SOC_J721E) intCfg[pinNum].intNum = CSLR_COMPUTE_CLUSTER0_GIC_SPI_GPIOMUX_INTRTR0_OUTP_14 + bankNum; #endif #else #if defined (SOC_AM65XX) intCfg[pinNum].intNum = CSL_MCU0_INTR_MAIN2MCU_PULSE_INTR0_OUTP_6 + bankNum; #endif #if defined (SOC_J721E) intCfg[pinNum].intNum = CSLR_MCU_ARMSS0_CPU0_INTR_MAIN2MCU_PLS_INTRTR0_OUTP_6 + bankNum; #endif #endif } intCfg[pinNum].eventId = 0; intCfg[pinNum].intcMuxNum = INVALID_INTC_MUX_NUM; intCfg[pinNum].intcMuxInEvent = 0; intCfg[pinNum].intcMuxOutEvent = 0; #endif GPIO_log("\nIntConfig: portNum[%d],pinNum[%d],bankNum[%d], intNum[%d]",portNum,pinNum,bankNum,intCfg[pinNum].intNum); } #ifdef USE_BIOS #if defined (__aarch64__) Void InitMmu() { Mmu_MapAttrs attrs; Bool retVal; uint32_t mapIdx = 0; Mmu_initMapAttrs(&attrs); attrs.attrIndx = 0; retVal = Mmu_map(0x00100000, 0x00100000, 0x00900000, &attrs); /* Main MMR0 cfg */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x00400000, 0x00400000, 0x00001000, &attrs); /* PSC0 */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x01800000, 0x01800000, 0x00200000, &attrs); /* gicv3 */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x02400000, 0x02400000, 0x000c0000, &attrs); /* dmtimer */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x02800000, 0x02800000, 0x00040000, &attrs); /* uart */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x02000000, 0x02000000, 0x00100000, &attrs); /* main I2C */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x42120000, 0x42120000, 0x00001000, &attrs); /* Wkup I2C0 */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x02100000, 0x02100000, 0x00080000, &attrs); /* McSPI */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x00600000, 0x00600000, 0x00002000, &attrs); /* GPIO */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x42110000, 0x42110000, 0x00001000, &attrs); /* WKUP GPIO */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x00a00000, 0x00a00000, 0x00040000, &attrs); /* MAIN INTR_ROUTERs */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x42200000, 0x42200000, 0x00001000, &attrs); /* WKUP INTR_ROUTER */ if (retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x40f00000, 0x40f00000, 0x00020000, &attrs); /* MCU MMR0 CFG */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x40d00000, 0x40d00000, 0x00002000, &attrs); /* PLL0 CFG */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x43000000, 0x43000000, 0x00020000, &attrs); /* WKUP MMR0 cfg */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x02C40000, 0x02C40000, 0x00100000, &attrs); /* pinmux ctrl */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x2A430000, 0x2A430000, 0x00001000, &attrs); /* ctrcontrol0 */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x030000000, 0x030000000, 0x10000000, &attrs); /* NAVSS used by sciclient */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x42000000, 0x42000000, 0x00001000, &attrs); /* PSC WKUP */ if (retVal == FALSE) { goto mmu_exit; } attrs.attrIndx = 7; mapIdx++; retVal = Mmu_map(0x80000000, 0x80000000, 0x03000000, &attrs); /* ddr */ if(retVal == FALSE) { goto mmu_exit; } mapIdx++; retVal = Mmu_map(0x70000000, 0x70000000, 0x04000000, &attrs); /* msmc */ if(retVal == FALSE) { goto mmu_exit; } mmu_exit: if(retVal == FALSE) { System_printf("Mmu_map idx %d returned error %d", mapIdx, retVal); while(1); } return; } #endif /* #if defined (__aarch64__) */ #endif /* #ifdef USE_BIOS */ #endif /* #if defined(SOC_AM65XX) || defined(SOC_J721E) */ /* * ======== Board_initI2C ======== */ static void Board_initGPIO(void) { Board_initCfg boardCfg; #if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2E) || defined(SOC_K2L) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657) || defined(SOC_OMAPL137) || defined(SOC_OMAPL138) || defined(SOC_AM65XX) || defined(SOC_J721E) GPIO_v0_HwAttrs gpio_cfg; /* Get the default SPI init configurations */ GPIO_socGetInitCfg(GPIO_LED0_PORT_NUM, &gpio_cfg); #if defined(SOC_K2G) /* Setup GPIO interrupt configurations */ GPIO_socSetIntMux(GPIO_LED0_PORT_NUM, GPIO_LED0_PIN_NUM, NULL, GPIO_MUX_SEL); #endif #if defined(SOC_OMAPL137) || defined(SOC_OMAPL138) /* Setup GPIO interrupt configurations */ GPIO_socSetBankInt(GPIO_LED0_PORT_NUM, GPIO_LED0_PIN_NUM, NULL); #endif #endif #if defined(evmK2E) || defined(evmC6678) boardCfg = BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO; #else boardCfg = BOARD_INIT_PINMUX_CONFIG | BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO; #endif Board_init_jh(boardCfg); #if defined(idkAM572x) || defined(idkAM574x) GPIOApp_UpdateBoardInfo(); #endif /* Modify the default GPIO configurations if necessary */ #if defined (am65xx_evm) || defined (am65xx_idk) || defined (j721e_sim) GPIO_configIntRouter(GPIO_LED0_PORT_NUM, GPIO_LED0_PIN_NUM, 0, &gpio_cfg); /* Set the default GPIO init configurations */ GPIO_socSetInitCfg(GPIO_LED0_PORT_NUM, &gpio_cfg); #endif } /********************************************************************** ************************** Global Variables ************************** **********************************************************************/ uint32_t timeStampStart = 0; uint32_t deltaTicks = 0; uint32_t deltaTicksMax = 0; volatile uint32_t loop_counter = 0; /* * ======== test function ======== */ void gpio_test(UArg arg0, UArg arg1) { uint32_t ctr = 0; UART_printf("\nGPIO toggle starting\n"); while(1) { Semaphore_pend(semaphore0, BIOS_WAIT_FOREVER); /*timeStampStart = TimestampProvider_get32(); GPIO_toggle(USER_LED1); deltaTicks = TimestampProvider_get32() - timeStampStart; if(deltaTicksMax < deltaTicks) { deltaTicksMax = deltaTicks; UART_printf("\nJitter! deltaTicksMax = %u\n", deltaTicksMax); }*/ ++loop_counter; GPIO_toggle(USER_LED1); if(320000 == loop_counter) // approximately 10 seconds { if(loop_counter != u32MTSTicksCounter && ctr > 4) UART_printf("\nRestart jitter count. Task iterations %u, ISR iterations = %u\n", loop_counter, u32MTSTicksCounter); else ++ctr; loop_counter = 0; deltaTicksMax = 0; u32MTSTicksCounter = 0; } } } unsigned int wait_for_debugger = 0; #ifdef USE_BIOS /* * ======== main ======== */ int main(void) { Types_FreqHz freq; UART_HwAttrs uart_hwAttrs; Error_Block eb; while(wait_for_debugger) { // hop } #if defined(SOC_AM65XX) || defined(SOC_J721E) Sciclient_ConfigPrms_t sciClientCfg; #endif #if defined(SOC_AM65XX) || defined(SOC_J721E) Sciclient_configPrmsInit(&sciClientCfg); Sciclient_init(&sciClientCfg); #endif /* Make sure non-interrupt mode is used for UART */ /* Get the UART default configuration */ UART_socGetInitCfg(2, &uart_hwAttrs); /* Disabling interrupt mode, forcing UART to use the polling mode */ uart_hwAttrs.enableInterrupt = 0; /* Write back the config */ UART_socSetInitCfg(2, &uart_hwAttrs); /* Call board init functions */ Board_initGPIO(); #if defined(idkAM574x) || defined(idkAM572x) || defined(idkAM571x) AppGPIOInit(); #endif /* GPIO initialization */ GPIO_init(); UART_printf("Hi from SYS/BIOS jailhouse inmate !\n"); Error_init(&eb); Semaphore_Params_init(&semaphoreParams); semaphoreParams.mode = Semaphore_Mode_BINARY; semaphore0 = Semaphore_create(0, &semaphoreParams, &eb); if(NULL == semaphore0) { UART_printf("Semaphore_create failed!"); UART_printf(eb.msg); return (0); //BIOS_exit (0); } Timer_getFreq(mainTimer, &freq); d_micro_seconds_period = 1000000.0 / ((double)freq.lo / (double)Timer_getPeriod(mainTimer)); u32_one_sec_rate = (uint32_t)((double)1000000.0 / d_micro_seconds_period); Timer_start(mainTimer); /* Start BIOS */ BIOS_start(); return (0); } #endif /* * ======== AppDelay ======== */ void AppDelay(unsigned int delayVal) { Osal_delay(delayVal); } /* * ======== AppLoopDelay ======== */ void AppLoopDelay(uint32_t delayVal) { volatile uint32_t i; for (i = 0; i < (delayVal * 1000); i++) ; } /* * ======== Callback function ======== */ void AppGpioCallbackFxn(void) { /* Toggle LED1 */ GPIO_toggle(USER_LED1); AppLoopDelay(DELAY_VALUE); } /* * This ISR releases gpio_test to perform 1 cycle */ void mainTimerISR(UArg arg0) { u32MTSTicksCounter++; // increment every 31.25 uSec GPIO_toggle(USER_LED0); Semaphore_post(semaphore0); }
Hi Nir,
Please see the Jailhouse documentation here: http://software-dl.ti.com/processor-sdk-linux/esd/docs/06_00_00_07/linux/Foundational_Components_Virtualization.html?highlight=jailhouse#jailhouse-hypervisor.
As described in the section "Jailhouse Performance on AM5728"
Because of shared resources between core 0 & core 1, there will always be some interrupt latency introduced by Jailhouse. Your interrupt latency measurements are consistent with those presented in "Table: Interrupt latency of a bare metal inmate (core 1)".
An alternative to Jailhouse is to explore moving a portion of your RTOS-based real-time code to the DSPs or M4s on the AM57xx.
Regards,
Frank