[PATCH] beagle: pwm polishing
From: Punit Vara . added a README to pwm . added select_pwmss() to select pwmss-generic registers, as opposed to PWM-specific registers . added pwmss_clock_en_status() and pwmss_tb_clock_check() . other API improvements . style improvements --- c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h | 113 -- c/src/lib/libbsp/arm/beagle/preinstall.am | 4 + c/src/lib/libbsp/arm/beagle/pwm/README| 197 + c/src/lib/libbsp/arm/beagle/pwm/pwm.c | 563 ++ 4 files changed, 568 insertions(+), 309 deletions(-) create mode 100644 c/src/lib/libbsp/arm/beagle/pwm/README diff --git a/c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h b/c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h index ef016f0..cf5d6fe 100644 --- a/c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h +++ b/c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h @@ -3,11 +3,11 @@ * * @ingroup arm_beagle * - * @brief BeagleBone Black BSP definitions. + * @brief BeagleBone Black PWM support definitions. */ /** - * Copyright (c) 2016 Punit Vara + * Copyright (c) 2016 Punit Vara * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -31,43 +31,53 @@ extern "C" { #define BBB_CONTROL_CONF_GPMC_AD(n) (0x800 + (n * 4)) #define BBB_CONTROL_CONF_LCD_DATA(n) (0x8a0 + (n * 4)) -#define BBB_PWMSS_COUNT 3 -#define BBB_PWMSS0 0 -#define BBB_PWMSS1 1 -#define BBB_PWMSS2 2 - -#define BBB_P8_13_2B 3 -#define BBB_P8_19_2A 4 -#define BBB_P8_45_2A 5 -#define BBB_P8_46_2B 6 -#define BBB_P8_34_1B 7 -#define BBB_P8_36_1A 8 -#define BBB_P9_14_1A 9 -#define BBB_P9_16_1B 10 -#define BBB_P9_21_0B 11 -#define BBB_P9_22_0A 12 -#define BBB_P9_29_0B 13 -#define BBB_P9_31_0A 14 - -#define BBB_MUX0 0 -#define BBB_MUX1 1 -#define BBB_MUX2 2 -#define BBB_MUX3 3 -#define BBB_MUX4 4 -#define BBB_MUX5 5 -#define BBB_MUX6 6 -#define BBB_MUX7 7 - -#define BBB_EPWM1 1 -#define BBB_EPWM2 2 -#define BBB_EPWM0 0 +/** + * @brief The set of possible PWM subsystem module + * + * Enumerated type to define various instance of pwm module. + */ +typedef enum{ + BBB_PWMSS0 = 0, + BBB_PWMSS1, + BBB_PWMSS2, + BBB_PWMSS_COUNT +}BBB_PWMSS; + +typedef enum{ + BBB_P8_13_2B = 3, + BBB_P8_19_2A, + BBB_P8_45_2A, + BBB_P8_46_2B, + BBB_P8_34_1B, + BBB_P8_36_1A, + BBB_P9_14_1A, + BBB_P9_16_1B, + BBB_P9_21_0B, + BBB_P9_22_0A, + BBB_P9_29_0B, + BBB_P9_31_0A +}bbb_pwm_pin_t; + +#define BBB_P8_13_MUX_PWM 4 +#define BBB_P8_19_MUX_PWM 4 +#define BBB_P8_45_MUX_PWM 3 +#define BBB_P8_46_MUX_PWM 3 +#define BBB_P8_34_MUX_PWM 2 +#define BBB_P8_36_MUX_PWM 2 +#define BBB_P9_14_MUX_PWM 6 +#define BBB_P9_16_MUX_PWM 6 +#define BBB_P9_21_MUX_PWM 3 +#define BBB_P9_22_MUX_PWM 3 +#define BBB_P9_29_MUX_PWM 1 +#define BBB_P9_31_MUX_PWM 1 +#define BBB_PWM_FREQ_THRESHOLD 0.5f /** * @brief BeagleBone Black PWM API. */ /** - * @brief This function intilize clock and pinmuxing for pwm sub system. + * @brief This function intilizes clock for pwm sub system. * * @param PWMSS_ID It is the instance number of EPWM of pwm sub system. * @@ -75,20 +85,20 @@ extern "C" { * @return false if not successful * **/ -bool beagle_pwm_init(uint32_t pwmss_id); +bool beagle_pwm_init(BBB_PWMSS pwmss_id); /* PWMSS setting * set pulse argument of epwm module * * @param pwm_id: EPWMSS number , 0~2 * @param pwm_freq : frequency to be generated - * @param dutyA: Duty Cycle in ePWM A - * @param dutyB: Duty Cycle in ePWM B + * @param dutyA: Duty Cycle(in percentage) in PWM channel A + * @param dutyB: Duty Cycle(in percentage) in PWM channel B * * @return : 1 for success * @return : 0 for failed * - * @example: PWMSS_Setting(0 , 50.0f , 50.0f , 25.0f); // Generate 50HZ pwm in PWM0 , + * @example: beagle_pwm_configure(0 , 50.0f , 50.0f , 25.0f); // Generate 50HZ pwm in PWM0 , * // duty cycle is 50% for ePWM0A , 25% for ePWM0B * * @Note : @@ -105,12 +115,12 @@ bool beagle_pwm_init(uint32_t pwmss_id); * Divisor = CLKDIV * HSPCLKDIV * 1 TBPRD : 10 ns (default) * 65535 TBPRD : 655350 ns - * 65535 TBPRD : 655350 * Divisor ns = X TBPRD : Cyclens + * 65535 TBPRD : 655350 * Divisor ns = X TBPRD : Cycle * * accrooding to that , we must find a Divisor value , let X nearest 65535 . - * so , Divisor must Nearest Cyclens/655350 + * so , Divisor must Nearest Cycle/655350 */ -int beagle_pwmss_setting(uint32_t pwm_id, float pwm_freq, float dutyA, float dutyB); +int beagle_pwm_configure(BBB_PWMSS pwm_id, float pwm_freq, float dut
Re: Some doubts regarding U-Boot Config in Raspberry Pi.
Hello Deval Shah, there are more ways how U-boot can be configured. You can experiment from serial console the first. When you see "Hit any key to stop autoboot:", send enter for example to U-boot. Then you can start USB and scan for ethernet usb start You should see U-Boot> usb start starting USB... USB0: Core Release: 2.80a scanning bus 0 for devices... 3 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 1 Ethernet Device(s) found U-Boot> You can enter setenv autoload n dhcp The autoload=n ensures that there is not run directly attempt to load config file through PXE or value provided by DHCP server. Typical whole sequence can look as setenv autoload n setenv imgsrvip 192.168.1.10 usb start dhcp tftp ${kernel_addr_r} ${imgsrvip}:/rpi/rtems/app.img bootm ${kernel_addr_r} The application is packed as U-boot image. See the description for packing RTEMS application into U-boot image in my previous e-mail http://article.gmane.org/gmane.os.rtems.devel/9551 You should push commands line by line, the previous one has to finish before you enter new one. The U-boot serial driver (same as rest of U-boot) does not use interrupts so the input is mostly lost if previous command is busy. If you have tested command sequence which fits your needs, then you should automete setting. There are many options but I start with minimal one. U-boot executes content of "bootcmd" environment variable after startup. You can put all commands used manually to one line separated by semicolon and set environment variable for example by command setenv bootcmd 'mw.l 0x3f20 0x04a020; mw.l 0x3f28 0x65b6c0; usb start ; dhcp ; tftp ${kernel_addr_r} ${imgsrvip}:/rpi/rtems/app.img ; bootm ${kernel_addr_r}' Single quotes ensure that whole sequence is stored in variable. You can test the boot by "boot" command or even "run ${bootcmd}" commands. The environment has to be stored to SD card to ensure that it survives to next boot (power up). Use "saveenv" command. It reports some warning problem on my SD card, but works U-Boot> saveenv Saving Environment to FAT... writing uboot.env FAT: Misaligned buffer address (36b3dd70) done U-Boot> Other option is that you can prepare environment file content "uboot.env" on your host computer. See hints about included in previous post. mkenvimage -s 16384 -o uboot.env uboot-env.txt The assignment lines are by single equal sign in source file format. There is another "uEnv.txt" override mechanism available which allows to use plain text file for initial environment variable setup. But I am not sure if all U-boot builds parse that file. It is possible to boot directly binary and ELF files by U-boot as well. But for RTEMS .exe there is problem that executable entry point seems to not be set or correctly interpreted by U-boot and tries start application from address 0. Read elf reports correct address readelf --all app.exe Entry point address: 0x8080 But U-boot image has advantage that it is shorter (binary data only), compressed and provides consistency checking. So there is no reason to not use that. There is that complete system of extlinux available and PXE naming scheme support included in U-boot. So this is another option. But for more information, read Denx manuals, please. http://www.denx.de/wiki/view/DULG/UBoot I would need to do the same, I have not all in memory. Best wishes, Pavel On Sunday 17 of July 2016 15:31:39 Deval Shah wrote: > Hello, > I wanted to boot my test-suit keeping Ethernet on. And what I learned from > the files which you provided for the raspberry pi, is that it looks for > tftp files after the boot menu appears. So is there a way to turn ethernet > in the Uboot itself ? or how to change the config to look for the test-suit > which I will have on my laptop for the tftp mode ? (currently it is looking > for > /extlinux/pxelinux.cfg how can I change that ?) > Thank you in advance. > Deval Shah ___ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel
[PATCH 0/6] Update of cache maintenance for ARM and Raspberry Pi specially, generic libdl correction.
From: Pavel Pisa The changes correct libdl operation on targets which do not snoop data change during instruction cache fill. Text section/the first 1 MB of data has been noncacheable after VideoCore support inclusion. Enabling cache of this area has revealed problem with stalled data left by loader in the cache. Cache manager updates overcomes these troubles. The changes lead to 40x speedup of dhrystones test on RPi2 and 20x on RPi1. There is still some problem with VideoCore graphic support. VideoCore mailbox seems to work correctly for other simpler operation but some parameters during graphic setup lead to error. Pavel Pisa (6): arm/raspberrypi: cache manager can be used for mailbox synchronization now. Remove workarounds. bsps/arm: do not disable MMU during translation table management operations. arm/bsps: CP15 and basic cache support entire cache clean for more architecture variants now. arm/raspberrypi: use cache manager operations to flush/invalidate all cache levels. arm/raspberrypi: reorder and update MMU config table to nor force RW section later to RO. libdl/rtl-obj.c: synchronize cache after code relocation. c/src/lib/libbsp/arm/raspberrypi/misc/vc.c | 35 +-- .../libbsp/arm/raspberrypi/startup/bspstarthooks.c | 14 ++--- .../arm/raspberrypi/startup/mm_config_table.c | 31 +++--- .../libbsp/arm/shared/arm-cp15-set-ttb-entries.c | 50 +--- .../arm/shared/armv467ar-basic-cache/cache_.h | 22 ++- c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h | 6 +- c/src/lib/libcpu/arm/shared/include/arm-cp15.h | 60 ++- cpukit/libdl/rtl-elf.c | 3 + cpukit/libdl/rtl-obj.c | 67 +- cpukit/libdl/rtl-obj.h | 9 +++ cpukit/libdl/rtl-rap.c | 3 + 11 files changed, 235 insertions(+), 65 deletions(-) -- 1.9.1 ___ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel
[PATCH 4/6] arm/raspberrypi: use cache manager operations to flush/invalidate all cache levels.
From: Pavel Pisa This fix strange behavior where some stale content has been stored in level 2 cache before RTEMS has been start from U-boot which has reappeared after MMU enable and shadow vector table at start of SDRAM. --- c/src/lib/libbsp/arm/raspberrypi/startup/bspstarthooks.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/c/src/lib/libbsp/arm/raspberrypi/startup/bspstarthooks.c b/c/src/lib/libbsp/arm/raspberrypi/startup/bspstarthooks.c index 0a90e7a..5b14e10 100644 --- a/c/src/lib/libbsp/arm/raspberrypi/startup/bspstarthooks.c +++ b/c/src/lib/libbsp/arm/raspberrypi/startup/bspstarthooks.c @@ -48,18 +48,18 @@ void BSP_START_TEXT_SECTION bsp_start_hook_0(void) * If the data cache is on then ensure that it is clean * before switching off to be extra carefull. */ - arm_cp15_drain_write_buffer(); - arm_cp15_data_cache_clean_and_invalidate(); + rtems_cache_flush_entire_data(); + rtems_cache_invalidate_entire_data(); } arm_cp15_flush_prefetch_buffer(); sctlr_val &= ~(ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M | ARM_CP15_CTRL_A); arm_cp15_set_control(sctlr_val); - -arm_cp15_tlb_invalidate(); -arm_cp15_flush_prefetch_buffer(); -arm_cp15_data_cache_invalidate(); -arm_cp15_instruction_cache_invalidate(); } + rtems_cache_invalidate_entire_data(); + rtems_cache_invalidate_entire_instruction(); + arm_cp15_branch_predictor_invalidate_all(); + arm_cp15_tlb_invalidate(); + arm_cp15_flush_prefetch_buffer(); /* Clear Translation Table Base Control Register */ arm_cp15_set_translation_table_base_control_register(0); -- 1.9.1 ___ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel
[PATCH 6/6] libdl/rtl-obj.c: synchronize cache after code relocation.
From: Pavel Pisa Memory content changes caused by relocation has to be propagated to memory/cache level which is used/snooped during instruction cache fill. --- cpukit/libdl/rtl-elf.c | 3 +++ cpukit/libdl/rtl-obj.c | 67 -- cpukit/libdl/rtl-obj.h | 9 +++ cpukit/libdl/rtl-rap.c | 3 +++ 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c index 0eee540..85853be 100644 --- a/cpukit/libdl/rtl-elf.c +++ b/cpukit/libdl/rtl-elf.c @@ -941,6 +941,9 @@ rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd) if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr)) return false; + if (!rtems_rtl_obj_synchronize_cache (obj)) +return false; + rtems_rtl_symbol_obj_erase_local (obj); if (!rtems_rtl_elf_load_details (obj)) diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index 00a1c6e..dba661d 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -558,6 +558,71 @@ rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj, return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data); } +/** + * Cache synchronization after runtime object load (dlopen) + */ +typedef struct +{ + uint32_t mask; + void *start_va; + void *end_va; +} rtems_rtl_obj_sect_sync_ctx_t; + +static bool +rtems_rtl_obj_sect_sync_handler (rtems_chain_node* node, void* data) +{ + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + rtems_rtl_obj_sect_sync_ctx_t* sync_ctx = data; + uintptr_t old_end; + uintptr_t new_start; + + if ( !(sect->flags & sync_ctx->mask) || !sect->size) +return true; + + if (sync_ctx->end_va == sync_ctx->start_va) { +sync_ctx->start_va = sect->base; + } else { +old_end = (uintptr_t)sync_ctx->end_va & ~(CPU_CACHE_LINE_BYTES - 1); +new_start = (uintptr_t)sect->base & ~(CPU_CACHE_LINE_BYTES - 1); +if ( (sect->base < sync_ctx->start_va) || + (new_start - old_end > CPU_CACHE_LINE_BYTES) ) { + rtems_cache_instruction_sync_after_code_change(sync_ctx->start_va, + sync_ctx->end_va - sync_ctx->start_va + 1); + sync_ctx->start_va = sect->base; +} + } + + sync_ctx->end_va = sect->base + sect->size; + + return true; +} + +bool +rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t*obj) +{ + rtems_rtl_obj_sect_sync_ctx_t sync_ctx; + + if (CPU_CACHE_LINE_BYTES == 0) +return true; + + sync_ctx.mask = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST | + RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_BSS | + RTEMS_RTL_OBJ_SECT_EXEC; + + sync_ctx.start_va = 0; + sync_ctx.end_va = sync_ctx.start_va; + rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_obj_sect_sync_handler, + &sync_ctx); + + if (sync_ctx.end_va != sync_ctx.start_va) { +rtems_cache_instruction_sync_after_code_change(sync_ctx.start_va, + sync_ctx.end_va - sync_ctx.start_va); + } + + return true; +} + bool rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj, int fd, @@ -618,8 +683,6 @@ rtems_rtl_obj_sections_loader (uint32_t mask, first = false; } -rtems_cache_instruction_sync_after_code_change(base, base_offset); - node = rtems_chain_next (node); } diff --git a/cpukit/libdl/rtl-obj.h b/cpukit/libdl/rtl-obj.h index 1202fd5..b1cb1d5 100644 --- a/cpukit/libdl/rtl-obj.h +++ b/cpukit/libdl/rtl-obj.h @@ -494,6 +494,15 @@ bool rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj, void*data); /** + * Synchronize caches to make code visible to CPU(s) + * + * @param obj The object file's descriptor. + * @retval true Cache synchronization succeed. + * @retval false Cache synchronization failed. + */ +bool rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t*obj); + +/** * Relocate an object file's unresolved reference. * * @param rec The unresolved relocation record. diff --git a/cpukit/libdl/rtl-rap.c b/cpukit/libdl/rtl-rap.c index 439eb20..0cb169e 100644 --- a/cpukit/libdl/rtl-rap.c +++ b/cpukit/libdl/rtl-rap.c @@ -970,6 +970,9 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd) if (!rtems_rtl_rap_relocate (&rap, obj)) return false; + if (!rtems_rtl_obj_synchronize_cache (obj)) +return false; + return true; } -- 1.9.1 ___ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel
[PATCH 1/6] arm/raspberrypi: cache manager can be used for mailbox synchronization now. Remove workarounds.
From: Pavel Pisa Signed-off-by: Pavel Pisa --- c/src/lib/libbsp/arm/raspberrypi/misc/vc.c | 35 ++ 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/c/src/lib/libbsp/arm/raspberrypi/misc/vc.c b/c/src/lib/libbsp/arm/raspberrypi/misc/vc.c index 0bec0c2..a3753cc 100644 --- a/c/src/lib/libbsp/arm/raspberrypi/misc/vc.c +++ b/c/src/lib/libbsp/arm/raspberrypi/misc/vc.c @@ -56,39 +56,8 @@ static inline void bcm2835_mailbox_buffer_flush_and_invalidate( size_t size ) { - uint32_t sctlr_val; - - sctlr_val = arm_cp15_get_control(); - - RTEMS_COMPILER_MEMORY_BARRIER(); - arm_cp15_drain_write_buffer(); - - if ( sctlr_val & ( ARM_CP15_CTRL_C | ARM_CP15_CTRL_M ) ) { -#if 0 -/* - These architecture independent RTEMS API functions should be - used there but CPU_DATA_CACHE_ALIGNMENT is not defined - for ARM architecture version used on RPi and functions - are dummy for now and do not provide required synchronization - */ -rtems_cache_flush_multiple_data_lines( buf, size ); -rtems_cache_invalidate_multiple_data_lines( buf, size ); -#elif 0 -/* Flush complete data cache, does not work on RPi2 for some reason */ -arm_cp15_data_cache_clean_and_invalidate(); -#else -/* - * This is temporal workaround for missing cache meanager - * which works on RPi2 - */ -size += (uintptr_t)buf & ~63; -size = (size + 63) & ~63; -while ( size ) { - size -= 32; - arm_cp15_data_cache_clean_and_invalidate_line(buf); -} -#endif - } + rtems_cache_flush_multiple_data_lines( buf, size ); + rtems_cache_invalidate_multiple_data_lines( buf, size ); } #define BCM2835_MBOX_VAL_LENGTH_MASK( _val_len ) \ -- 1.9.1 ___ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel
[PATCH 5/6] arm/raspberrypi: reorder and update MMU config table to nor force RW section later to RO.
From: Pavel Pisa Enable even the first megabyte of SDRAM to be cache-able after problems with stale cache content has been resolved by previous commit. Because major part of application usually fits to the first megabyte this speedups test dhrystone application by factor 40. --- .../arm/raspberrypi/startup/mm_config_table.c | 31 +++--- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/c/src/lib/libbsp/arm/raspberrypi/startup/mm_config_table.c b/c/src/lib/libbsp/arm/raspberrypi/startup/mm_config_table.c index 8a6d37a..50e19d8 100644 --- a/c/src/lib/libbsp/arm/raspberrypi/startup/mm_config_table.c +++ b/c/src/lib/libbsp/arm/raspberrypi/startup/mm_config_table.c @@ -23,32 +23,45 @@ #include #include +/* + * Pagetable initialization data + * + * Keep all read-only sections before read-write ones. + * This ensures that write is allowed if one page/region + * is partially filled by read-only section contentent + * and rest is used for writeable section + */ + const arm_cp15_start_section_config arm_cp15_start_mmu_config_table[] = { { .begin = (uint32_t) bsp_section_fast_text_begin, .end = (uint32_t) bsp_section_fast_text_end, .flags = ARMV7_MMU_CODE_CACHED }, { -.begin = (uint32_t) bsp_section_fast_data_begin, -.end = (uint32_t) bsp_section_fast_data_end, -.flags = ARMV7_MMU_DATA_READ_WRITE_CACHED - }, { .begin = (uint32_t) bsp_section_start_begin, .end = (uint32_t) bsp_section_start_end, .flags = ARMV7_MMU_CODE_CACHED }, { -.begin = (uint32_t) bsp_section_vector_begin, -.end = (uint32_t) bsp_section_vector_end, -.flags = ARMV7_MMU_DATA_READ_WRITE_CACHED - }, { .begin = (uint32_t) bsp_section_text_begin, .end = (uint32_t) bsp_section_text_end, -.flags = ARMV7_MMU_READ_WRITE +.flags = ARMV7_MMU_CODE_CACHED }, { .begin = (uint32_t) bsp_section_rodata_begin, .end = (uint32_t) bsp_section_rodata_end, .flags = ARMV7_MMU_DATA_READ_ONLY_CACHED }, { +.begin = (uint32_t) bsp_translation_table_base, +.end = (uint32_t) bsp_translation_table_base + 0x4000, +.flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { +.begin = (uint32_t) bsp_section_fast_data_begin, +.end = (uint32_t) bsp_section_fast_data_end, +.flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { +.begin = (uint32_t) bsp_section_vector_begin, +.end = (uint32_t) bsp_section_vector_end, +.flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { .begin = (uint32_t) bsp_section_data_begin, .end = (uint32_t) bsp_section_data_end, .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED -- 1.9.1 ___ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel
[PATCH 3/6] arm/bsps: CP15 and basic cache support entire cache clean for more architecture variants now.
From: Pavel Pisa Next cache operations should work on most of cores now rtems_cache_flush_entire_data() rtems_cache_invalidate_entire_data() rtems_cache_invalidate_entire_instruction() Instruction cache invalidate works on the first level for now only. Data cacache operations are extended to ensure flush/invalidate on all cache levels. The CP15 arm_cp15_data_cache_clean_all_levels() function extended to continue through unified levels too (ctype = 4). --- .../arm/shared/armv467ar-basic-cache/cache_.h | 22 +-- c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h | 6 ++- c/src/lib/libcpu/arm/shared/include/arm-cp15.h | 44 +- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h b/c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h index c6e1f83..2ff1ae1 100644 --- a/c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h +++ b/c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h @@ -49,11 +49,14 @@ _CPU_cache_flush_data_range( ) { _ARM_Data_synchronization_barrier(); - arm_cp15_drain_write_buffer(); arm_cache_l1_flush_data_range( d_addr, n_bytes ); + #if !defined(__ARM_ARCH_7A__) + arm_cp15_drain_write_buffer(); + #endif + _ARM_Data_synchronization_barrier(); } static inline void _CPU_cache_invalidate_1_data_line(const void *d_addr) @@ -92,6 +95,7 @@ static inline void _CPU_cache_invalidate_instruction_range( const void *i_addr, size_t n_bytes) { arm_cache_l1_invalidate_instruction_range( i_addr, n_bytes ); + _ARM_Instruction_synchronization_barrier(); } static inline void _CPU_cache_freeze_instruction(void) @@ -106,12 +110,23 @@ static inline void _CPU_cache_unfreeze_instruction(void) static inline void _CPU_cache_flush_entire_data(void) { - arm_cp15_data_cache_test_and_clean(); + _ARM_Data_synchronization_barrier(); + #if defined(__ARM_ARCH_7A__) + arm_cp15_data_cache_clean_all_levels(); + #else + arm_cp15_data_cache_clean_and_invalidate(); + arm_cp15_drain_write_buffer(); + #endif + _ARM_Data_synchronization_barrier(); } static inline void _CPU_cache_invalidate_entire_data(void) { + #if defined(__ARM_ARCH_7A__) + arm_cp15_data_cache_invalidate_all_levels(); + #else arm_cp15_data_cache_invalidate(); + #endif } static inline void _CPU_cache_enable_data(void) @@ -141,7 +156,8 @@ static inline void _CPU_cache_disable_data(void) static inline void _CPU_cache_invalidate_entire_instruction(void) { - arm_cp15_instruction_cache_invalidate(); + arm_cache_l1_invalidate_entire_instruction(); + _ARM_Instruction_synchronization_barrier(); } static inline void _CPU_cache_enable_instruction(void) diff --git a/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h b/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h index 74a65c5..9caa268 100644 --- a/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h +++ b/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h @@ -329,9 +329,13 @@ static inline void arm_cache_l1_invalidate_entire_instruction( void ) arm_cp15_instruction_cache_invalidate(); #endif /* RTEMS_SMP */ - if ( ( ctrl & ARM_CP15_CTRL_Z ) == 0 ) { + if ( ( ctrl & ARM_CP15_CTRL_Z ) != 0 ) { +#if defined(__ARM_ARCH_7A__) arm_cp15_branch_predictor_inner_shareable_invalidate_all(); +#endif +#if defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_7A__) arm_cp15_branch_predictor_invalidate_all(); +#endif } } diff --git a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h index 52cca49..a27e50d 100644 --- a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h +++ b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h @@ -1071,8 +1071,8 @@ arm_cp15_data_cache_invalidate_all_levels(void) for (level = 0; level < loc; ++level) { uint32_t ctype = arm_clidr_get_cache_type(clidr, level); -/* Check if this level has a data cache */ -if ((ctype & 0x2) != 0) { +/* Check if this level has a data cache or unified cache */ +if (((ctype & (0x6)) == 2) || (ctype == 4)) { uint32_t ccsidr; uint32_t line_power; uint32_t associativity; @@ -1134,6 +1134,46 @@ arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t set_and_way) } ARM_CP15_TEXT_SECTION static inline void +arm_cp15_data_cache_clean_all_levels(void) +{ + uint32_t clidr = arm_cp15_get_cache_level_id(); + uint32_t loc = arm_clidr_get_level_of_coherency(clidr); + uint32_t level = 0; + + for (level = 0; level < loc; ++level) { +uint32_t ctype = arm_clidr_get_cache_type(clidr, level); + +/* Check if this level has a data cache or unified cache */ +if (((ctype & (0x6)) == 2) || (ctype == 4)) { + uint32_t ccsidr; + uint32_t line_power; + uint32_t associativity; + uint32_t way; + uint32_t way_shift; + + ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1); + + line_power = arm_ccsidr_get_line_power(ccsid
[PATCH 2/6] bsps/arm: do not disable MMU during translation table management operations.
From: Pavel Pisa Disabling MMU requires complex cache flushing and invalidation operations. There is almost no way how to do that right on SMP system without stopping all other CPUs. On the other hand, there is documented sequence of operations which should be used according to ARM manual and it guarantees even distribution of maintenance operations to other cores for last generation of Cortex-A cores with multiprocessor extension. This change could require addition of appropriate entry to arm_cp15_start_mmu_config_table for some BSPs to ensure that MMU table stays accessible after MMU is enabled { .begin = (uint32_t) bsp_translation_table_base, .end = (uint32_t) bsp_translation_table_base + 0x4000, .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED } --- .../libbsp/arm/shared/arm-cp15-set-ttb-entries.c | 50 ++ c/src/lib/libcpu/arm/shared/include/arm-cp15.h | 16 +++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c b/c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c index 3d5a1e6..f650009 100644 --- a/c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c +++ b/c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c @@ -12,35 +12,69 @@ * http://www.rtems.org/license/LICENSE. */ +#include #include +/* + * Translation table modification requires to propagate + * information to memory and other cores. + * + * Algorithm follows example found in the section + * + * B3.10.1 General TLB maintenance requirements + * TLB maintenance operations and the memory order model + * + * of ARM Architecture Reference Manual + * ARMv7-A and ARMv7-R edition + * ARM DDI 0406C.b (ID072512) + */ + static uint32_t set_translation_table_entries( const void *begin, const void *end, uint32_t section_flags ) { - uint32_t cl_size = arm_cp15_get_min_cache_line_size(); uint32_t *ttb = arm_cp15_get_translation_table_base(); - uint32_t i = ARM_MMU_SECT_GET_INDEX(begin); + uint32_t istart = ARM_MMU_SECT_GET_INDEX(begin); uint32_t iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(end)); uint32_t index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U; uint32_t ctrl; uint32_t section_flags_of_first_entry; + uint32_t i; + void *first_ttb_addr; + void *last_ttb_end; - ctrl = arm_cp15_mmu_disable(cl_size); - arm_cp15_tlb_invalidate(); - section_flags_of_first_entry = ttb [i]; + ctrl = arm_cp15_get_control(); + section_flags_of_first_entry = ttb [istart]; + last_ttb_end = first_ttb_addr = ttb + istart; - while (i != iend) { + for ( i = istart; i != iend; i = (i + 1U) & index_mask ) { uint32_t addr = i << ARM_MMU_SECT_BASE_SHIFT; ttb [i] = addr | section_flags; +last_ttb_end = ttb + i + 1; + } + + if ( ctrl & (ARM_CP15_CTRL_C | ARM_CP15_CTRL_M ) ) { +rtems_cache_flush_multiple_data_lines(first_ttb_addr, +last_ttb_end - first_ttb_addr); + } + + _ARM_Data_synchronization_barrier(); -i = (i + 1U) & index_mask; + for ( i = istart; i != iend; i = (i + 1U) & index_mask ) { +void *mva = (void *) (i << ARM_MMU_SECT_BASE_SHIFT); +#if defined(__ARM_ARCH_7A__) +arm_cp15_tlb_invalidate_entry_all_asids(mva); +#else +arm_cp15_tlb_instruction_invalidate_entry(mva); +arm_cp15_tlb_data_invalidate_entry(mva); +#endif } - arm_cp15_set_control(ctrl); + _ARM_Data_synchronization_barrier(); + _ARM_Instruction_synchronization_barrier(); return section_flags_of_first_entry; } diff --git a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h index ca7a11e..52cca49 100644 --- a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h +++ b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h @@ -560,6 +560,22 @@ arm_cp15_tlb_invalidate_entry(const void *mva) } ARM_CP15_TEXT_SECTION static inline void +arm_cp15_tlb_invalidate_entry_all_asids(const void *mva) +{ + ARM_SWITCH_REGISTERS; + + mva = ARM_CP15_TLB_PREPARE_MVA(mva); + + __asm__ volatile ( +ARM_SWITCH_TO_ARM +"mcr p15, 0, %[mva], c8, c7, 3\n" +ARM_SWITCH_BACK +: ARM_SWITCH_OUTPUT +: [mva] "r" (mva) + ); +} + +ARM_CP15_TEXT_SECTION static inline void arm_cp15_tlb_instruction_invalidate(void) { ARM_SWITCH_REGISTERS; -- 1.9.1 ___ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel
Re: [PATCH 0/5] v2: Progress toward absolute time intervals
Hello Gedare, On Friday 15 of July 2016 19:22:17 Gedare Bloom wrote: > > > > cpukit/score/include/rtems/score/percpu.h > > > > typedef enum { > > /** > >* @brief Index for relative per-CPU watchdog header. > >* > >* The reference time point for this header is current ticks value > >* during insert. Time is measured in clock ticks. > >*/ > > PER_CPU_WATCHDOG_RELATIVE, > > > > /** > >* @brief Index for absolute per-CPU watchdog header. > >* > >* The reference time point for this header is the POSIX Epoch. Time > > is * measured in nanoseconds since POSIX Epoch. > >*/ > > PER_CPU_WATCHDOG_ABSOLUTE, > > > > /** > >* @brief Count of per-CPU watchdog headers. > >*/ > > PER_CPU_WATCHDOG_COUNT > > } Per_CPU_Watchdog_index; > > > > It is little complicated that each is in different time scale > > but support is there. But if I do not miss something, > > your clock_nanosleep() does not distinguish between queues. > > I think the WATCHDOG_ABSOLUTE is in ticks also, Sebastian? I have not found time to analyze code again and deeper. Sebastian clarification would help. Is one queue intended as monotonic and another one are real-time (wall clock time) which can be adjusted? > > There are four cases for clock_nanosleep() and if only > > two queues are used then they should be used next way > > > > CLOCK_REALTIME && TIMER_ABSTIME = 0 > > should use PER_CPU_WATCHDOG_RELATIVE queue > > value should be added to > > _TOD_Get_zero_based_uptime_as_timespec( ¤t_time ); > > and converted to ticks or converted the first > > and then added to _Watchdog_Ticks_since_boot added > > > > CLOCK_REALTIME && TIMER_ABSTIME = 1 > > should use PER_CPU_WATCHDOG_RELATIVE queue > > value needs to be only converted to ticks > > > > CLOCK_MONOTONIC && TIMER_ABSTIME = 0 > > should use PER_CPU_WATCHDOG_ABSOLUTE queue > > value has to be added to value retrieved by > > _TOD_Get_as_timespec( ¤t_time ); > > getnanouptime(struct timespec *tsp) > > with nanoseconds field overflow correction then converted > > somewhere to uint64_t packed timespec value by > > _Watchdog_Ticks_from_timespec > > > > CLOCK_MONOTONIC && TIMER_ABSTIME = 1 > > should use PER_CPU_WATCHDOG_ABSOLUTE queue > > value needs only to be repacked by _Watchdog_Ticks_from_timespec > > > > But I am not sure if the queues are really intended that way, > > one as monotonic and the second as realtime or if they are there > > only to spedup/eliminate complete conversion from timespec to ticks. > > > > But if there is option to set and adjust CLOCK_REALTIME there has to > > be some other/completely separated queue for monotonic time based > > operations. > > The RELATIVE queue bases the timeout from when the thread is added, > and the timeout interval only takes into consideration the ticks that > have actually elapsed since. The queues are per CPU not per single task as I read the code. So the PER_CPU_WATCHDOG_RELATIVE should be monotonic equivalent. > The ABSOLUTE queue checks the system time _Timecounter_Getnanotime() > to see if the timeout has been reached. > > Now I think I fixed my logic to use the relative queue for the > monotonic clock, so it only considers actual ticks, and the absolute > queue for the realtime clock so that if the timecounter gets adjusted > it would cause the timeout to fire. Now, I'm not quite certain if/how > the timecounter gets updated. > > > void _Watchdog_Insert( > > Watchdog_Header *header, > > Watchdog_Control *the_watchdog, > > uint64_t expire > > ) > > > > if ( expire < parent_watchdog->expire ) { > > link = _RBTree_Left_reference( parent ); > > } else { > > link = _RBTree_Right_reference( parent ); > > new_first = old_first; > > } > > Yes this could be done but I don't know how much it matters. A ticket > may be opened at least, if you feel strongly this should be considered > later. It is not critical for now. > > Generally, I am not 100% sure about mapping to actual RTEMS code > > but the concept of realtime and monotonic time is critical > > for control applications. > > Agreed. Thanks for the feedback. I had spent a lot more time on > building the score infrastructure than on thinking through the POSIX > issues here. It would be nice to have this part clean. I think that Linux clocksources and clock event devices/timers are done right way. There has been many considerations and approaches between 64-bit nanosecond scale and something which could be faster on 32-bit systems when timespec is used. I have not checked that now, but as I know implementation settled on 64-bit nanoseconds. This allows to enhance timers and system to use high resolution and tickless modes. So I would personally tend to use the same. Conversion from timespec to 64-bit ns is not horrible. Conversion back is quite expensive. It seems that Linux kernel does not found something better then r