Hi all I've (also) been doing some work on getting Jetson-TK1 support for the jailhouse freertos cell.
This is fairly barebones, so 'test tasks' are made, queued and displayed onto UART. Mainly this involved stripping out the UART8250 specific code for the bananapi, and putting in tegra specific code for this to function. In addition I removed some test code (in freertos/Source/portable/GCC/ARM_A7jailhouse/port.c) that was causing the scheduler to hang in a busy loop. Despite some code being present for it, the main limitation is using the FPU is currently not supported. If enabled during hardware initialisation in main.c freeRTOS hangs and does not continue. For more information, commit 9e1a4abe in https://github.com/CodethinkLabs/freertos-cell may also be useful. If this is something that would be potentially useful, I can tidy up the code so that it isn't specific to only one device. For now, our work can be found here: https://github.com/CodethinkLabs/freertos-cell in the jetson-tk1 branch. And to see it in action, https://github.com/CodethinkLabs/jailhouse-tk1 is the place to go. Full diff between the fork and the jetson-tk1 branch is also below. Many thanks Chris ---- diff --git a/A15_asm/fpu.S b/A15_asm/fpu.S new file mode 100644 index 0000000..6f20bbe --- /dev/null +++ b/A15_asm/fpu.S @@ -0,0 +1,32 @@ + +/* + * This is used to enable the fpu in the cortex A15. This is gotten directly from the tech + * manual: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0438i/CDEDBHDD.html + * Section: Using the Advanced SIMD and VFP in Hyp mode + * + */ + + .section ".start" + .globl fpu_enable + +fpu_enable: + /* Enable Non-secure access to CP10 and CP11 and clear the NSASEDIS bit in the NSACR: */ + MRC p15, 0, r0, c1, c0, 2 + ORR r0, r0, #(3<<10) /* Enable Non-secure access to CP10 and CP11 */ + BIC r0, r0, #(3<<14) /* Clear the NSASEDIS bit */ + MCR p15, 0, r0, c1, c0, 2 + ISB + + /*Clear the TCP10, TCP11, and TASE bits in the HCPTR:*/ + MRC p15, 4, r0, c1, c0, 2 + BIC r0, r0, #(3<<10) /*Clear the TCP10 and TCP11 bits*/ + BIC r0, r0, #(3<<14); /*Clear the TASE bit*/ + MCR p15, 4, r0, c1, c0, 2 + ISB + + /* Set the FPEXC.EN bit to enable Advanced SIMD and VFP: */ + MOV r0, #0x40000000 + VMSR FPEXC, r0 + + bx lr + diff --git a/A15_asm/fpu.h b/A15_asm/fpu.h new file mode 100644 index 0000000..019f87f --- /dev/null +++ b/A15_asm/fpu.h @@ -0,0 +1 @@ +void fpu_enable(void); diff --git a/Makefile b/Makefile index d49c25f..6c23fcf 100644 --- a/Makefile +++ b/Makefile @@ -3,15 +3,15 @@ src = $(CURDIR) CROSS_COMPILE ?= arm-linux-gnueabihf- +INSTALL_DIR ?= /usr/local CC = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)ld AR = $(CROSS_COMPILE)ar OBJCOPY = $(CROSS_COMPILE)objcopy -CFLAGS += -mcpu=cortex-a7 -mtune=cortex-a7 -mfpu=vfpv4-d16 -mfloat-abi=hard -O2 -CFLAGS += -DCONFIG_MACH_SUN7I=1 -CFLAGS += -Wall -MMD -pipe +CFLAGS += -mcpu=cortex-a15 -mtune=cortex-a15 -mfloat-abi=hard -O2 +CFLAGS += -Wall -MMD -pipe -std=gnu99 CFLAGS += -I $(src) -I $(src)/freertos/Source/include -I $(src)/freertos-runtime -I $(src)/freertos/Source/portable/GCC/ARM_A7jailhouse LDFLAGS += -T lscript.lds @@ -27,7 +27,8 @@ FREERTOS_OBJS = freertos/Source/queue.o \ freertos/Source/portable/GCC/ARM_A7jailhouse/gic-v2.o \ freertos/Source/portable/GCC/ARM_A7jailhouse/portASM.o \ freertos/Source/timers.o \ - freertos/Source/tasks.o + freertos/Source/tasks.o \ + A15_asm/fpu.o FREERTOS_RUNTIME_OBJS = freertos-runtime/string.o \ freertos-runtime/serial.o \ @@ -55,6 +56,10 @@ $(RUNTIME_AR): $(RUNTIME_OBJS) clean: rm -f $(OBJS) $(EXE_STEM).elf $(EXE_STEM).bin $(RUNTIME_OBJS) $(RUNTIME_AR) +install: + mkdir -p $(INSTALL_DIR) + cp $(EXE_STEM).bin $(INSTALL_DIR) + distclean: clean rm -f $(DEPS) diff --git a/freertos-runtime/printf-stdarg.h b/freertos-runtime/printf-stdarg.h index 4d9ce1b..efd14ff 100644 --- a/freertos-runtime/printf-stdarg.h +++ b/freertos-runtime/printf-stdarg.h @@ -77,4 +77,16 @@ int puts(const char *s); int printf(const char *format, ...); int sprintf(char *out, const char *format, ...); int snprintf( char *buf, unsigned int count, const char *format, ... ); + + +//From http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing +#ifdef DEBUG +#define DEBUG_TEST 1 +#else +#define DEBUG_TEST 0 +#endif + +#define debug_print(fmt, ...) \ + do { if (DEBUG_TEST) printf(fmt, ## __VA_ARGS__); } while (0) + #endif diff --git a/freertos-runtime/serial.c b/freertos-runtime/serial.c index d2b4da0..0ebdd5f 100644 --- a/freertos-runtime/serial.c +++ b/freertos-runtime/serial.c @@ -77,13 +77,7 @@ #include <string.h> #include "serial.h" -#ifndef CONFIG_MACH_SUN7I -#error Only support for Banana Pi board at the moment -#endif - -#define UART7_BASE 0x01C29C00 -#define UART_CLOCK_REG ((void *)0x01c2006c) -#define UART_GATE_NR 23 +#define UART7_BASE 0x70006000 //This is for the TK1 #define UART_TX 0x0 #define UART_DLL 0x0 @@ -124,23 +118,10 @@ static void mmio_write32(void *addr, uint32_t val) sio_fd_t serial_open(void) { - unsigned divisor = DIV_ROUND_CLOSEST(UART_CLK, 16 * UART_BAUDRATE); sio_fd_t uart_base = (void*)UART7_BASE; - mmio_write32(UART_CLOCK_REG, - mmio_read32(UART_CLOCK_REG) | - (1 << UART_GATE_NR)); - - mmio_write32(uart_base + UART_LCR, UART_LCR_8N1); - mmio_write32(uart_base + UART_IER, 0); /* IRQ off */ - mmio_write32(uart_base + UART_FCR, 7); /* FIFO reset and enable */ - mmio_write32(uart_base + UART_MCR, 7); /* DTR + RTS on */ - /* Set Divisor Latch Access Bit */ - mmio_write32(uart_base + UART_LCR, UART_LCR_DLAB | mmio_read32(uart_base + UART_LCR)); - /* Program baudrate */ - mmio_write32(uart_base + UART_DLL, 0xff & divisor); /* Divisor Latch Low Register */ - mmio_write32(uart_base + UART_DLM, 0xff & (divisor >> 8)); /* Divisor Latch High Register */ - mmio_write32(uart_base + UART_LCR, ~UART_LCR_DLAB & mmio_read32(uart_base + UART_LCR)); + //Initialisation in uart_init in uart-tegra.h + uart_base += 0x300; return uart_base; } diff --git a/freertos/Source/portable/GCC/ARM_A7jailhouse/port.c b/freertos/Source/portable/GCC/ARM_A7jailhouse/port.c index dd739c3..e632abb 100644 --- a/freertos/Source/portable/GCC/ARM_A7jailhouse/port.c +++ b/freertos/Source/portable/GCC/ARM_A7jailhouse/port.c @@ -79,6 +79,7 @@ #include "task.h" #include "gic-v2.h" +#include "printf-stdarg.h" #ifndef configUNIQUE_INTERRUPT_PRIORITIES #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html @@ -322,41 +323,6 @@ extern void FreeRTOS_SWI_Handler(void); BaseType_t xPortStartScheduler( void ) { uint32_t ulAPSR; - - #if( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( gic_v2_gicd_get_address() + portINTERRUPT_PRIORITY_REGISTER_OFFSET ); - volatile uint8_t ucMaxPriorityValue; - - /* Determine how many priority bits are implemented in the GIC. - - Save the interrupt priority value that is about to be clobbered. */ - ulOriginalPriority = *pucFirstUserPriorityRegister; - - /* Determine the number of priority bits available. First write to - all possible bits. */ - *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; - - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; - - /* Shift to the least significant bits. */ - while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET ) - { - ucMaxPriorityValue >>= ( uint8_t ) 0x01; - } - - /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read - value. */ - configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY ); - - /* Restore the clobbered interrupt priority register to its original - value. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; - } - #endif /* conifgASSERT_DEFINED */ - ulICCIAR = ulICCEOIR = ulICCPMR = (uint32_t) gic_v2_gicc_get_address(); ulICCIAR += portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET; ulICCEOIR += portICCEOIR_END_OF_INTERRUPT_OFFSET; @@ -388,6 +354,7 @@ BaseType_t xPortStartScheduler( void ) configSETUP_TICK_INTERRUPT(); /* Start the first task executing. */ + debug_print("...Starting first task executing...\n"); vPortRestoreTaskContext(); } } @@ -397,6 +364,7 @@ BaseType_t xPortStartScheduler( void ) possible value. prvTaskExitError() is referenced to prevent a compiler warning about it being defined but not referenced in the case that the user defines their own exit address. */ + debug_print("....ERROR... prvTaskExitError\n"); ( void ) prvTaskExitError; return 0; } diff --git a/freertos/Source/portable/GCC/ARM_A7jailhouse/portASM.S b/freertos/Source/portable/GCC/ARM_A7jailhouse/portASM.S index ac6aa95..aadb02a 100644 --- a/freertos/Source/portable/GCC/ARM_A7jailhouse/portASM.S +++ b/freertos/Source/portable/GCC/ARM_A7jailhouse/portASM.S @@ -52,7 +52,7 @@ licensing and training services. */ -#define SUNXI_UART7_BASE 0x01c29c00 +#define TEGRA_UART_BASE 0x70006000 .text .arm @@ -191,8 +191,8 @@ vPortInstallFreeRTOSVectorTable: #if 0 push {r4,r5} - movw r4, #(SUNXI_UART7_BASE & 0xffff) - movt r4, #(SUNXI_UART7_BASE >> 16) + movw r4, #(TEGRA_UART_BASE & 0xffff) + movt r4, #(TEGRA_UART_BASE >> 16) mov r5, #'%' str r5, [r4] pop {r4,r5} diff --git a/jailhouse-configs/jetson-tk1-freertos.c b/jailhouse-configs/jetson-tk1-freertos.c new file mode 100644 index 0000000..0958980 --- /dev/null +++ b/jailhouse-configs/jetson-tk1-freertos.c @@ -0,0 +1,59 @@ + +#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[2]; + struct jailhouse_irqchip irqchips[2]; + } __attribute__((packed)) config = { + .cell = { + .signature = JAILHOUSE_CELL_DESC_SIGNATURE, + .name = "freeRTOS", + .flags = JAILHOUSE_CELL_PASSIVE_COMMREG, + + .cpu_set_size = sizeof(config.cpus), + .num_memory_regions = ARRAY_SIZE(config.mem_regions), + }, + + .cpus = { + 0x8, + }, + + .mem_regions = { + /* UART */ { + .phys_start = 0x70006000, + .virt_start = 0x70006000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_IO, + }, + /* RAM */ { + .phys_start = 0xfa000000, + .virt_start = 0, + .size = 0x01000000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE, + }, + }, + .irqchips = { + /* GIC */ { + .address = 0x50041000, + .pin_base = 32, + .pin_bitmap = { + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff + }, + }, + /* GIC */ { + .address = 0x50041000, + .pin_base = 160, + .pin_bitmap = { + 0xffffffff, 0xffffffff + }, + }, + }, + +}; diff --git a/main.c b/main.c index c07b6a6..bd1138c 100644 --- a/main.c +++ b/main.c @@ -85,6 +85,10 @@ #include "semphr.h" /* }}} */ +/* ASM includes */ +#include "A15_asm/fpu.h" + + /* {{{1 Defines */ #define TIMER_IRQ 27 #define BEATS_PER_SEC configTICK_RATE_HZ @@ -177,11 +181,12 @@ void __div0(void) /* {{{1 LED control */ static void led_toggle(void) { -#ifdef CONFIG_MACH_SUN7I -#define PIO_BASE ((void*)0x01c20800) - uint32_t *led_reg = PIO_BASE + 7*0x24 + 0x10; - *led_reg ^= 1<<24; -#endif + printf("I am 'blinking' on a FreeRTOS cell!\n"); +//#ifdef CONFIG_MACH_SUN7I +//#define PIO_BASE ((void*)0x01c20800) +// uint32_t *led_reg = PIO_BASE + 7*0x24 + 0x10; +// *led_reg ^= 1<<24; +//#endif } /* }}} */ @@ -415,19 +420,7 @@ static void floatTask( void *pvParameters ) /* {{{1 Hardware init */ static void hardware_fpu_enable(void) { - unsigned reg; - /* Enable the VFP */ - asm volatile("mrc p15, 0, %0, c1, c0, 2;" /* Read Coprocessor Access Control Register CPACR */ - "orr %0, %0, #(0x3 << 20);" /* Enable access to cp10 */ - "orr %0, %0, #(0x3 << 22);" /* Enable access to cp11 */ - "mcr p15, 0, %0, c1, c0, 2;" - "fmrx %0, FPEXC;" - "orr %0, %0, #(1<<30);" /* Set FPEXC.EN = 1 */ - "fmxr FPEXC, %0;" - : "=r" (reg) /* outputs */ - : /* No inputs */ - : /* clobbered */ - ); + //fpu_enable(); } static void hardware_cpu_cache_mmu_enable(void) @@ -564,16 +557,20 @@ static void prvSetupHardware(void) ser_dev = serial_open(); io_dev_map[0] = (unsigned long)ser_dev; show_cache_mmu_status("MMU/Cache status at entry"); - printf("Initializing the HW...\n"); + debug_print("Initializing the HW...\n"); if(USE_CACHE_MMU) hardware_cpu_caches_off(); io_dev_map[1] = (unsigned long)gic_v2_init(); if(USE_CACHE_MMU) hardware_mmu_ptable_setup(io_dev_map, ARRAY_SIZE(io_dev_map)); if(USE_CACHE_MMU) hardware_cpu_cache_mmu_enable(); /* Replace the exception vector table by a FreeRTOS variant */ + debug_print("...Installing FreeRTOS vector table...\n"); vPortInstallFreeRTOSVectorTable(); + debug_print("...Enabling hardware fpu...\n"); hardware_fpu_enable(); + debug_print("...Enabling UART IRQ...\n"); uart_irq_enable(); serial_irq_rx_enable(ser_dev); + debug_print("...Reading timer frequency...\n"); arm_read_sysreg(CNTFRQ, timer_frq); if(!timer_frq) { printf("Timer frequency is zero\n"); @@ -581,7 +578,7 @@ static void prvSetupHardware(void) } asm volatile ( "mrs %0, apsr" : "=r" ( apsr ) ); apsr &= 0x1f; - printf("FreeRTOS inmate cpu-mode=%x\n", apsr); + debug_print("...FreeRTOS inmate cpu-mode=%x\n...", apsr); show_cache_mmu_status("MMU/Cache status at runtime"); } /* }}} */ @@ -611,36 +608,7 @@ void inmate_main(void) prio, /* The priority assigned to the task. */ NULL ); /* The task handle is not required, so NULL is passed. */ } - - if(1) { /* Task notification test */ - TaskHandle_t recv_task_handle; - xTaskCreate( recvTask, /* The function that implements the task. */ - "receive", /* The text name assigned to the task - for debug only; not used by the kernel. */ - configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ - NULL, /* The parameter passed to the task */ - configMAX_PRIORITIES-2, /* The priority assigned to the task. */ - &recv_task_handle ); /* The task handle */ - xTaskCreate( sendTask, /* The function that implements the task. */ - "sender", /* The text name assigned to the task - for debug only; not used by the kernel. */ - configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ - recv_task_handle, /* The parameter passed to the task */ - configMAX_PRIORITIES-1, /* The priority assigned to the task. */ - NULL ); /* The task handle is not required, so NULL is passed. */ - } - xTaskCreate( blinkTask, /* The function that implements the task. */ - "blink", /* The text name assigned to the task - for debug only; not used by the kernel. */ - configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ - NULL, /* The parameter passed to the task */ - tskIDLE_PRIORITY, /* The priority assigned to the task. */ - NULL ); /* The task handle is not required, so NULL is passed. */ - if(1) for(i = 0; i < 2; i++) { - xTaskCreate( floatTask, /* The function that implements the task. */ - "float", /* The text name assigned to the task - for debug only; not used by the kernel. */ - configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ - (void*)i, /* The parameter passed to the task */ - tskIDLE_PRIORITY+1, /* The priority assigned to the task. */ - NULL ); /* The task handle is not required, so NULL is passed. */ - } + printf("vTaskStartScheduler goes active\n"); vTaskStartScheduler(); printf("vTaskStartScheduler terminated: strange!!!\n"); -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
