# # Copyright (C) 2015 Xilinx, Inc. # # This file is part of the FreeRTOS port. # # FreeRTOS 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 >>!AND MODIFIED BY!<< the FreeRTOS exception. # # NOTE: The modification to the GPL is included to allow you to distribute a # combined work that includes FreeRTOS without being obliged to provide the # source code for proprietary components outside of the FreeRTOS kernel. # # FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. Full license text is available on the following # link: http://www.freertos.org/a00114.html # # standalone bsp version. set this to the latest "ACTIVE" version. set standalone_version standalone_v5_3 proc FreeRTOS_drc {os_handle} { global env set sw_proc_handle [hsi::get_sw_processor] set hw_proc_handle [hsi::get_cells [common::get_property HW_INSTANCE $sw_proc_handle] ] set proctype [common::get_property IPNAME $hw_proc_handle] if { $proctype == "microblaze" } { mb_drc_checks } } proc generate {os_handle} { variable standalone_version set have_tick_timer 0 set sw_proc_handle [hsi::get_sw_processor] set hw_proc_handle [hsi::get_cells [common::get_property HW_INSTANCE $sw_proc_handle] ] set proctype [common::get_property IP_NAME $hw_proc_handle] set need_config_file "false" set enable_sw_profile [common::get_property CONFIG.enable_sw_intrusive_profiling $os_handle] # proctype should be "microblaze", ps7_cortexa9, psu_cortexr5 or psu_cortexa53 set commonsrcdir "../${standalone_version}/src/common" set mbsrcdir "../${standalone_version}/src/microblaze" set armr5srcdir "../${standalone_version}/src/cortexr5" set armr5gccdir "../${standalone_version}/src/cortexr5/gcc" set arma53srcdir "../${standalone_version}/src/cortexa53" set arma5364srcdir "../${standalone_version}/src/cortexa53/64bit" set arma5332srcdir "../${standalone_version}/src/cortexa53/32bit" set arma5364gccdir "../${standalone_version}/src/cortexa53/64bit/gcc" set arma5332gccdir "../${standalone_version}/src/cortexa53/32bit/gcc" set includedir "../${standalone_version}/src/cortexa53/includes_ps" set arma9srcdir "../${standalone_version}/src/cortexa9" set arma9gccdir "../${standalone_version}/src/cortexa9/gcc" set arma9armccdir "../${standalone_version}/src/cortexa9/armcc" set arma9iarccdir "../${standalone_version}/src/cortexa9/iarcc" foreach entry [glob -nocomplain [file join $commonsrcdir *]] { file copy -force $entry [file join ".." "${standalone_version}" "src"] } switch $proctype { "psu_cortexr5" { puts "In start copy psu_cortexr5" file copy -force "./src/Makefile_psu_cortexr5" "./src/Makefile" file copy -force "./src/Makefile" "./src/Makefile_dep" foreach entry [glob -nocomplain [file join $armr5srcdir *]] { file copy -force $entry [file join ".." "${standalone_version}" "src"] } foreach entry [glob -nocomplain [file join $armr5gccdir *]] { file copy -force $entry [file join ".." "${standalone_version}" "src"] } file copy -force $includedir "../${standalone_version}/src/" file delete -force "../${standalone_version}/src/gcc" file delete -force "../${standalone_version}/src/profile" if { $enable_sw_profile == "true" } { error "ERROR: Profiling is not supported for R5" } set need_config_file "true" set file_handle [::hsi::utils::open_include_file "xparameters.h"] puts $file_handle "#include \"xparameters_ps.h\"" puts $file_handle "" close $file_handle } "psu_cortexa53" { set procdrv [hsi::get_sw_processor] set compiler [get_property CONFIG.compiler $procdrv] if {[string compare -nocase $compiler "arm-none-eabi-gcc"] == 0} { error "ERROR: FreeRTOS is not supported for 32bit A53" } puts "In start copy psu_cortexa53" file copy -force "./src/Makefile_psu_cortexa53" "./src/Makefile" file copy -force "./src/Makefile" "./src/Makefile_dep" foreach entry [glob -nocomplain [file join $arma5364srcdir *]] { file copy -force $entry [file join ".." "${standalone_version}" "src"] } foreach entry [glob -nocomplain [file join $arma5364gccdir *]] { file copy -force $entry [file join ".." "${standalone_version}" "src"] } file copy -force $includedir "../${standalone_version}/src/" file delete -force "../${standalone_version}/src/gcc" file delete -force "../${standalone_version}/src/profile" if { $enable_sw_profile == "true" } { error "ERROR: Profiling is not supported for A53" } set need_config_file "true" set file_handle [::hsi::utils::open_include_file "xparameters.h"] puts $file_handle "#include \"xparameters_ps.h\"" puts $file_handle "" close $file_handle } "ps7_cortexa9" { puts "In start copy ps7_cortexa9" file copy -force "./src/Makefile_ps7_cortexa9" "./src/Makefile" file copy -force "./src/Makefile" "./src/Makefile_dep" foreach entry [glob -nocomplain [file join $arma9srcdir *]] { file copy -force $entry [file join ".." "${standalone_version}" "src"] } foreach entry [glob -nocomplain [file join $arma9gccdir *]] { file copy -force $entry [file join ".." "${standalone_version}" "src"] } file delete -force "../${standalone_version}/src/gcc" file delete -force "../${standalone_version}/src/iccarm" file delete -force "../${standalone_version}/src/armcc" set need_config_file "true" set file_handle [::hsi::utils::open_include_file "xparameters.h"] puts $file_handle "#include \"xparameters_ps.h\"" puts $file_handle "" close $file_handle } "microblaze" { puts "In start copy microblaze" file copy -force "./src/Makefile_microblaze" "./src/Makefile" file copy -force "./src/Makefile" "./src/Makefile_dep" foreach entry [glob -nocomplain [file join $mbsrcdir *]] { if { [string first "microblaze_interrupt_handler" $entry] == -1 } { ;# Do not copy over the Standalone BSP exception handler file copy -force $entry [file join ".." "${standalone_version}" "src"] } } set need_config_file "true" } "default" { puts "processor type $proctype not supported\n" } } # Write the Config.make file set makeconfig [open "../${standalone_version}/src/config.make" w] file rename -force -- "../${standalone_version}/src/Makefile" "../${standalone_version}/src/Makefile_depends" if { $proctype == "psu_cortexr5" || $proctype == "ps7_cortexa9" || $proctype == "microblaze" || $proctype == "psu_cortexa53" } { puts $makeconfig "LIBSOURCES = *.c *.S" puts $makeconfig "LIBS = standalone_libs" } close $makeconfig # Remove arm directory... file delete -force $armr5srcdir file delete -force $arma9srcdir file delete -force $arma5364srcdir file delete -force $mbsrcdir # Copy core kernel files to the main src directory file copy -force [file join src Source tasks.c] ./src file copy -force [file join src Source queue.c] ./src file copy -force [file join src Source list.c] ./src file copy -force [file join src Source timers.c] ./src file copy -force [file join src Source event_groups.c] ./src file copy -force [file join src Source portable MemMang heap_4.c] ./src if { $proctype == "psu_cortexr5" } { file copy -force [file join src Source portable GCC ARM_CR5 port.c] ./src file copy -force [file join src Source portable GCC ARM_CR5 portASM.S] ./src file copy -force [file join src Source portable GCC ARM_CR5 port_asm_vectors.S] ./src file copy -force [file join src Source portable GCC ARM_CR5 portmacro.h] ./src file copy -force [file join src Source portable GCC ARM_CR5 portZynqUltrascale.c] ./src } if { $proctype == "psu_cortexa53" } { file copy -force [file join src Source portable GCC ARM_CA53 port.c] ./src file copy -force [file join src Source portable GCC ARM_CA53 portASM.S] ./src file copy -force [file join src Source portable GCC ARM_CA53 port_asm_vectors.S] ./src file copy -force [file join src Source portable GCC ARM_CA53 portmacro.h] ./src file copy -force [file join src Source portable GCC ARM_CA53 portZynqUltrascale.c] ./src } if { $proctype == "ps7_cortexa9" } { file copy -force [file join src Source portable GCC ARM_CA9 port.c] ./src file copy -force [file join src Source portable GCC ARM_CA9 portASM.S] ./src file copy -force [file join src Source portable GCC ARM_CA9 port_asm_vectors.S] ./src file copy -force [file join src Source portable GCC ARM_CA9 portmacro.h] ./src file copy -force [file join src Source portable GCC ARM_CA9 portZynq7000.c] ./src } if { $proctype == "microblaze" } { file copy -force [file join src Source portable GCC MicroBlazeV8 port.c] ./src file copy -force [file join src Source portable GCC MicroBlazeV8 port_exceptions.c] ./src file copy -force [file join src Source portable GCC MicroBlazeV8 portasm.S] ./src file copy -force [file join src Source portable GCC MicroBlazeV8 portmacro.h] ./src file copy -force [file join src Source portable GCC MicroBlazeV8 portmicroblaze.c] ./src # Create config file for microblaze interrupt handling if {[string compare -nocase $need_config_file "true"] == 0} { xhandle_mb_interrupts } # Create config files for Microblaze exception handling if { [mb_has_exceptions $hw_proc_handle] } { xcreate_mb_exc_config_file } # Create bspconfig file set bspcfg_fn [file join ".." "${standalone_version}" "src" "bspconfig.h"] file delete $bspcfg_fn set bspcfg_fh [open $bspcfg_fn w] xprint_generated_header $bspcfg_fh "Configurations for Standalone BSP" if { [mb_has_pvr $hw_proc_handle] } { set pvr [get_property CONFIG.C_PVR $hw_proc_handle] switch $pvr { "0" { puts $bspcfg_fh "#define MICROBLAZE_PVR_NONE" } "1" { puts $bspcfg_fh "#define MICROBLAZE_PVR_BASIC" } "2" { puts $bspcfg_fh "#define MICROBLAZE_PVR_FULL" } "default" { puts $bspcfg_fh "#define MICROBLAZE_PVR_NONE" } } } close $bspcfg_fh } set headers [glob -join ./src/Source/include *.\[h\]] foreach header $headers { file copy -force $header src } file delete -force [file join src Source] # Remove microblaze, cortexa9 and common directories... file delete -force $mbsrcdir file delete -force $commonsrcdir file delete -force $armr5srcdir file delete -force $armr5gccdir file delete -force $arma53srcdir file delete -force $arma9srcdir file delete -force $arma9gccdir file delete -force $arma9armccdir file delete -force $arma9iarccdir # Handle stdin and stdout ::hsi::utils::handle_stdin $os_handle ::hsi::utils::handle_stdout $os_handle file copy -force "./src/outbyte.c" "../${standalone_version}/src/" file copy -force "./src/inbyte.c" "../${standalone_version}/src/" set file_handle [::hsi::utils::open_include_file "xparameters.h"] puts $file_handle "\n/******************************************************************/\n" close $file_handle ############################################################################ ## Add constants common to all architectures to the configuration file. ############################################################################ set config_file [xopen_new_include_file "./src/FreeRTOSConfig.h" "FreeRTOS Configuration parameters"] puts $config_file "\#include \"xparameters.h\" \n" set val [common::get_property CONFIG.use_preemption $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_PREEMPTION" "0" } else { xput_define $config_file "configUSE_PREEMPTION" "1" } set val [common::get_property CONFIG.use_mutexes $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_MUTEXES" "0" } else { xput_define $config_file "configUSE_MUTEXES" "1" } set val [common::get_property CONFIG.use_recursive_mutexes $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_RECURSIVE_MUTEXES" "0" } else { xput_define $config_file "configUSE_RECURSIVE_MUTEXES" "1" } set val [common::get_property CONFIG.use_counting_semaphores $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_COUNTING_SEMAPHORES" "0" } else { xput_define $config_file "configUSE_COUNTING_SEMAPHORES" "1" } set val [common::get_property CONFIG.use_timers $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_TIMERS" "0" } else { xput_define $config_file "configUSE_TIMERS" "1" } set val [common::get_property CONFIG.use_idle_hook $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_IDLE_HOOK" "0" } else { xput_define $config_file "configUSE_IDLE_HOOK" "1" } set val [common::get_property CONFIG.use_tick_hook $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_TICK_HOOK" "0" } else { xput_define $config_file "configUSE_TICK_HOOK" "1" } set val [common::get_property CONFIG.use_malloc_failed_hook $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_MALLOC_FAILED_HOOK" "0" } else { xput_define $config_file "configUSE_MALLOC_FAILED_HOOK" "1" } set val [common::get_property CONFIG.use_trace_facility $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_TRACE_FACILITY" "0" } else { xput_define $config_file "configUSE_TRACE_FACILITY" "1" } xput_define $config_file "configUSE_16_BIT_TICKS" "0" xput_define $config_file "configUSE_APPLICATION_TASK_TAG" "0" xput_define $config_file "configUSE_CO_ROUTINES" "0" set tick_rate [common::get_property CONFIG.tick_rate $os_handle] xput_define $config_file "configTICK_RATE_HZ" "($tick_rate)" set max_priorities [common::get_property CONFIG.max_priorities $os_handle] xput_define $config_file "configMAX_PRIORITIES" "($max_priorities)" xput_define $config_file "configMAX_CO_ROUTINE_PRIORITIES" "2" set min_stack [common::get_property CONFIG.minimal_stack_size $os_handle] set min_stack [expr [expr $min_stack + 3] & 0xFFFFFFFC] xput_define $config_file "configMINIMAL_STACK_SIZE" "( ( unsigned short ) $min_stack)" set total_heap_size [common::get_property CONFIG.total_heap_size $os_handle] xput_define $config_file "configTOTAL_HEAP_SIZE" "( ( size_t ) ( $total_heap_size ) )" set max_task_name_len [common::get_property CONFIG.max_task_name_len $os_handle] xput_define $config_file "configMAX_TASK_NAME_LEN" $max_task_name_len set val [common::get_property CONFIG.idle_yield $os_handle] if {$val == "false"} { xput_define $config_file "configIDLE_SHOULD_YIELD" "0" } else { xput_define $config_file "configIDLE_SHOULD_YIELD" "1" } set val [common::get_property CONFIG.timer_task_priority $os_handle] if {$val == "false"} { xput_define $config_file "configTIMER_TASK_PRIORITY" "0" } else { xput_define $config_file "configTIMER_TASK_PRIORITY" $val } set val [common::get_property CONFIG.timer_command_queue_length $os_handle] if {$val == "false"} { xput_define $config_file "configTIMER_QUEUE_LENGTH" "0" } else { xput_define $config_file "configTIMER_QUEUE_LENGTH" "10" } set val [common::get_property CONFIG.timer_task_stack_depth $os_handle] if {$val == "false"} { xput_define $config_file "configTIMER_TASK_STACK_DEPTH" "0" } else { xput_define $config_file "configTIMER_TASK_STACK_DEPTH" "($val * 2)" } set val [get_property CONFIG.use_freertos_asserts $os_handle] if {$val == "true"} { puts $config_file "#define configASSERT( x ) if( ( x ) == 0 ) vApplicationAssert( __FILE__, __LINE__ )\n" } set val [common::get_property CONFIG.use_queue_sets $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_QUEUE_SETS" "0" } else { xput_define $config_file "configUSE_QUEUE_SETS" "1" } set val [common::get_property CONFIG.check_for_stack_overflow $os_handle] if {$val == "false"} { xput_define $config_file "configCHECK_FOR_STACK_OVERFLOW" "0" } else { if { $val > 2 } { error "ERROR: check_for_stack_overflow must be between 0 and 2" } else { xput_define $config_file "configCHECK_FOR_STACK_OVERFLOW" $val } } set val [common::get_property CONFIG.queue_registry_size $os_handle] if {$val == "false"} { xput_define $config_file "configQUEUE_REGISTRY_SIZE" "0" } else { xput_define $config_file "configQUEUE_REGISTRY_SIZE" $val } set val [common::get_property CONFIG.use_stats_formatting_functions $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_STATS_FORMATTING_FUNCTIONS" "0" } else { xput_define $config_file "configUSE_STATS_FORMATTING_FUNCTIONS" "1" } set val [common::get_property CONFIG.num_thread_local_storage_pointers $os_handle] if {$val == "false"} { xput_define $config_file "configNUM_THREAD_LOCAL_STORAGE_POINTERS" "0" } else { xput_define $config_file "configNUM_THREAD_LOCAL_STORAGE_POINTERS" $val } puts $config_file "#define configUSE_TICKLESS_IDLE 0" puts $config_file "#define configTASK_RETURN_ADDRESS NULL" puts $config_file "#define INCLUDE_vTaskPrioritySet 1" puts $config_file "#define INCLUDE_uxTaskPriorityGet 1" puts $config_file "#define INCLUDE_vTaskDelete 1" puts $config_file "#define INCLUDE_vTaskCleanUpResources 1" puts $config_file "#define INCLUDE_vTaskSuspend 1" puts $config_file "#define INCLUDE_vTaskDelayUntil 1" puts $config_file "#define INCLUDE_vTaskDelay 1" puts $config_file "#define INCLUDE_eTaskGetState 1" puts $config_file "#define INCLUDE_xTimerPendFunctionCall 1" puts $config_file "#define INCLUDE_pcTaskGetTaskName 1" ############################################################################ ## Add constants specific to the psu_cortexr5 ############################################################################ if { $proctype == "psu_cortexr5" } { set val [common::get_property CONFIG.PSU_TTC0_Select $os_handle] if {$val == "true"} { set have_tick_timer 1 set val1 [common::get_property CONFIG.PSU_TTC0_Select_Cntr $os_handle] if {$val1 == "0"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_0_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_0_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_0_INTR" } else { if {$val1 == "1"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_1_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_1_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_1_INTR" } else { if {$val1 == "2"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_2_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_2_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_2_INTR" } else { error "ERROR: invalid timer selected" "mdt_error" } } } } set val [common::get_property CONFIG.PSU_TTC1_Select $os_handle] if {$val == "true"} { if {$have_tick_timer == 1} { error "ERROR: Cannot select multiple timers for tick generation " "mdt_error" } else { set have_tick_timer 1 set val1 [common::get_property CONFIG.PSU_TTC1_Select_Cntr $os_handle] if {$val1 == "0"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_3_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_3_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_3_INTR" } else { if {$val1 == "1"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_4_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_4_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_4_INTR" } else { if {$val1 == "2"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_5_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_5_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_5_INTR" } else { error "ERROR: invalid timer selected " "mdt_error" } } } } } set val [common::get_property CONFIG.PSU_TTC2_Select $os_handle] if {$val == "true"} { if {$have_tick_timer == 1} { error "ERROR: Cannot select multiple timers for tick generation " "mdt_error" } else { set have_tick_timer 1 set val1 [common::get_property CONFIG.PSU_TTC2_Select_Cntr $os_handle] if {$val1 == "0"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_6_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_6_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_6_INTR" } else { if {$val1 == "1"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_7_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_7_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_7_INTR" } else { if {$val1 == "2"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_8_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_8_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_8_INTR" } else { error "ERROR: invalid timer selected " "mdt_error" } } } } } set val [common::get_property CONFIG.PSU_TTC3_Select $os_handle] if {$val == "true"} { if {$have_tick_timer == 1} { error "ERROR: Cannot select multiple timers for tick generation " "mdt_error" } else { set have_tick_timer 1 set val1 [common::get_property CONFIG.PSU_TTC3_Select_Cntr $os_handle] if {$val1 == "0"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_9_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_9_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_9_INTR" } else { if {$val1 == "1"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_10_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_10_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_10_INTR" } else { if {$val1 == "2"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_11_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_11_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_11_INTR" } else { error "ERROR: invalid timer selected " "mdt_error" } } } } } if {$have_tick_timer == 0} { error "ERROR: No tick timer selected " "mdt_error" } xput_define $config_file "configUNIQUE_INTERRUPT_PRIORITIES" "32" xput_define $config_file "configINTERRUPT_CONTROLLER_DEVICE_ID" "XPAR_SCUGIC_SINGLE_DEVICE_ID" xput_define $config_file "configINTERRUPT_CONTROLLER_BASE_ADDRESS" "XPAR_SCUGIC_0_DIST_BASEADDR" xput_define $config_file "configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET" "0x1000" # Function prototypes cannot be in the common code as some compilers or # ports require pre-processor guards to ensure they are not visible from # assembly files. puts $config_file "void vApplicationAssert( const char *pcFile, uint32_t ulLine );" puts $config_file "void FreeRTOS_SetupTickInterrupt( void );" puts $config_file "#define configSETUP_TICK_INTERRUPT() FreeRTOS_SetupTickInterrupt()\n" puts $config_file "void FreeRTOS_ClearTickInterrupt( void );" puts $config_file "#define configCLEAR_TICK_INTERRUPT() FreeRTOS_ClearTickInterrupt()\n" puts $config_file "#define configGENERATE_RUN_TIME_STATS 0\n" puts $config_file "#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()\n" puts $config_file "#define portGET_RUN_TIME_COUNTER_VALUE()\n" puts $config_file "#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096\n" puts $config_file "#define recmuCONTROLLING_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )\n" set max_api_call_interrupt_priority [common::get_property CONFIG.max_api_call_interrupt_priority $os_handle] xput_define $config_file "configMAX_API_CALL_INTERRUPT_PRIORITY" "($max_api_call_interrupt_priority)" set val [common::get_property CONFIG.use_port_optimized_task_selection $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_PORT_OPTIMISED_TASK_SELECTION" "0" } else { xput_define $config_file "configUSE_PORT_OPTIMISED_TASK_SELECTION" "1" } } # end of if $proctype == "psu_cortexr5" ############################################################################ ## Add constants specific to the psu_cortexa53 ############################################################################ if { $proctype == "psu_cortexa53" } { set val [common::get_property CONFIG.PSU_TTC0_Select $os_handle] if {$val == "true"} { set have_tick_timer 1 set val1 [common::get_property CONFIG.PSU_TTC0_Select_Cntr $os_handle] if {$val1 == "0"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_0_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_0_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_0_INTR" } else { if {$val1 == "1"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_1_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_1_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_1_INTR" } else { if {$val1 == "2"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_2_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_2_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_2_INTR" } else { error "ERROR: invalid timer selected" "mdt_error" } } } } set val [common::get_property CONFIG.PSU_TTC1_Select $os_handle] if {$val == "true"} { if {$have_tick_timer == 1} { error "ERROR: Cannot select multiple timers for tick generation " "mdt_error" } else { set have_tick_timer 1 set val1 [common::get_property CONFIG.PSU_TTC1_Select_Cntr $os_handle] if {$val1 == "0"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_3_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_3_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_3_INTR" } else { if {$val1 == "1"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_4_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_4_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_4_INTR" } else { if {$val1 == "2"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_5_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_5_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_5_INTR" } else { error "ERROR: invalid timer selected " "mdt_error" } } } } } set val [common::get_property CONFIG.PSU_TTC2_Select $os_handle] if {$val == "true"} { if {$have_tick_timer == 1} { error "ERROR: Cannot select multiple timers for tick generation " "mdt_error" } else { set have_tick_timer 1 set val1 [common::get_property CONFIG.PSU_TTC2_Select_Cntr $os_handle] if {$val1 == "0"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_6_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_6_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_6_INTR" } else { if {$val1 == "1"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_7_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_7_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_7_INTR" } else { if {$val1 == "2"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_8_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_8_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_8_INTR" } else { error "ERROR: invalid timer selected " "mdt_error" } } } } } set val [common::get_property CONFIG.PSU_TTC3_Select $os_handle] if {$val == "true"} { if {$have_tick_timer == 1} { error "ERROR: Cannot select multiple timers for tick generation " "mdt_error" } else { set have_tick_timer 1 set val1 [common::get_property CONFIG.PSU_TTC3_Select_Cntr $os_handle] if {$val1 == "0"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_9_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_9_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_9_INTR" } else { if {$val1 == "1"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_10_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_10_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_10_INTR" } else { if {$val1 == "2"} { xput_define $config_file "configTIMER_ID" "XPAR_XTTCPS_11_DEVICE_ID" xput_define $config_file "configTIMER_BASEADDR" "XPAR_XTTCPS_11_BASEADDR" xput_define $config_file "configTIMER_INTERRUPT_ID" "XPAR_XTTCPS_11_INTR" } else { error "ERROR: invalid timer selected " "mdt_error" } } } } } if {$have_tick_timer == 0} { error "ERROR: No tick timer selected " "mdt_error" } xput_define $config_file "configUNIQUE_INTERRUPT_PRIORITIES" "32" xput_define $config_file "configINTERRUPT_CONTROLLER_DEVICE_ID" "XPAR_SCUGIC_SINGLE_DEVICE_ID" xput_define $config_file "configINTERRUPT_CONTROLLER_BASE_ADDRESS" "XPAR_SCUGIC_0_DIST_BASEADDR" xput_define $config_file "configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET" "0x10000" # Function prototypes cannot be in the common code as some compilers or # ports require pre-processor guards to ensure they are not visible from # assembly files. puts $config_file "void vApplicationAssert( const char *pcFile, uint32_t ulLine );" puts $config_file "void FreeRTOS_SetupTickInterrupt( void );" puts $config_file "#define configSETUP_TICK_INTERRUPT() FreeRTOS_SetupTickInterrupt()\n" puts $config_file "void FreeRTOS_ClearTickInterrupt( void );" puts $config_file "#define configCLEAR_TICK_INTERRUPT() FreeRTOS_ClearTickInterrupt()\n" puts $config_file "#define configGENERATE_RUN_TIME_STATS 0\n" puts $config_file "#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()\n" puts $config_file "#define portGET_RUN_TIME_COUNTER_VALUE()\n" puts $config_file "#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096\n" puts $config_file "#define recmuCONTROLLING_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )\n" puts $config_file "#define fabs( x ) __builtin_fabs( x )\n" set max_api_call_interrupt_priority [common::get_property CONFIG.max_api_call_interrupt_priority $os_handle] xput_define $config_file "configMAX_API_CALL_INTERRUPT_PRIORITY" "($max_api_call_interrupt_priority)" set val [common::get_property CONFIG.use_port_optimized_task_selection $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_PORT_OPTIMISED_TASK_SELECTION" "0" } else { xput_define $config_file "configUSE_PORT_OPTIMISED_TASK_SELECTION" "1" } } # end of if $proctype == "psu_cortexa53" ############################################################################ ## Add constants specific to the ps7_cortexa9 ############################################################################ if { $proctype == "ps7_cortexa9" } { set max_api_call_interrupt_priority [common::get_property CONFIG.max_api_call_interrupt_priority $os_handle] xput_define $config_file "configMAX_API_CALL_INTERRUPT_PRIORITY" "($max_api_call_interrupt_priority)" set val [common::get_property CONFIG.use_port_optimized_task_selection $os_handle] if {$val == "false"} { xput_define $config_file "configUSE_PORT_OPTIMISED_TASK_SELECTION" "0" } else { xput_define $config_file "configUSE_PORT_OPTIMISED_TASK_SELECTION" "1" } puts $config_file "#define configINTERRUPT_CONTROLLER_BASE_ADDRESS ( XPAR_PS7_SCUGIC_0_DIST_BASEADDR )" puts $config_file "#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ( -0xf00 )" puts $config_file "#define configUNIQUE_INTERRUPT_PRIORITIES 32" # Function prototypes cannot be in the common code as some compilers or # ports require pre-processor guards to ensure they are not visible from # assembly files. puts $config_file "void vApplicationAssert( const char *pcFile, uint32_t ulLine );" puts $config_file "void FreeRTOS_SetupTickInterrupt( void );" puts $config_file "#define configSETUP_TICK_INTERRUPT() FreeRTOS_SetupTickInterrupt()\n" puts $config_file "void FreeRTOS_ClearTickInterrupt( void );" puts $config_file "#define configCLEAR_TICK_INTERRUPT() FreeRTOS_ClearTickInterrupt()\n" } # end of if $proctype == "ps7_cortexa9" ############################################################################ ## Add constants specific to the microblaze ############################################################################ if { $proctype == "microblaze" } { # Interrupt controller setting assumes only one is in use. puts $config_file "#define configINTERRUPT_CONTROLLER_TO_USE XPAR_INTC_SINGLE_DEVICE_ID" puts $config_file "#define configINSTALL_EXCEPTION_HANDLERS 1" # Avoid non #define statements getting included in assembly files. puts $config_file "#ifndef __ASSEMBLER__" puts $config_file "void vApplicationAssert( const char *pcFile, uint32_t ulLine );" puts $config_file "#endif" } # end of if $proctype == "microblaze" # complete the header protectors puts $config_file "\#endif" close $config_file } proc xopen_new_include_file { filename description } { set inc_file [open $filename w] xprint_generated_header $inc_file $description set newfname [string map {. _} [lindex [split $filename {\/}] end]] puts $inc_file "\#ifndef _[string toupper $newfname]" puts $inc_file "\#define _[string toupper $newfname]\n\n" return $inc_file } proc xput_define { config_file parameter param_value } { puts $config_file "#define $parameter $param_value\n" } proc xhandle_mb_interrupts {} { set default_interrupt_handler "XNullHandler" set default_arg "XNULL" set source_interrupt_handler $default_interrupt_handler set source_handler_arg $default_arg # Handle the interrupt pin set sw_proc_handle [get_sw_processor] set periph [get_cells $sw_proc_handle] set source_ports [xget_interrupt_sources $periph] if {[llength $source_ports] > 1} { error "Too many interrupting ports on the MicroBlaze. Should only find 1" "" "error" return } if {[llength $source_ports] == 1} { set source_port [lindex $source_ports 0] if {[llength $source_port] != 0} { set source_port_name [get_property NAME $source_port] set source_periph [get_cells -of_objects $source_port] set source_name [get_property NAME $source_periph] set source_driver [get_drivers $source_name] if {[string compare -nocase $source_driver ""] != 0} { set int_array [get_arrays -of_objects $source_driver] if {[llength $int_array] != 0} { set size [get_property PROPERTY.size $int_array] for {set i 0 } { $i < $size } { incr $i } { set int_port [lindex [get_property PARAM.int_port $int_array] $i] if {[llength $int_port] != 0} { if {[string compare -nocase $int_port $source_port_name] == 0 } { set source_interrupt_handler [lindex [get_property PARAM.int_handler $int_array] $i ] set source_handler_arg [lindex [get_property PARAM.int_handler_arg $int_array] $i ] if {[string compare -nocase $source_handler_arg DEVICE_ID] == 0 } { set source_handler_arg [xget_name $source_periph "DEVICE_ID"] } else { if {[llength $source_periph] == 0} { set source_handler_arg $default_arg } else { set source_handler_arg [xget_name $source_periph "C_BASEADDR"] } } break } } } } } } } # Generate microblaze_interrupts_g.c file... xcreate_mb_intr_config_file $source_interrupt_handler $source_handler_arg } proc xcreate_mb_intr_config_file {handler arg} { set mb_table "MB_InterruptVectorTable" variable standalone_version set filename [file join ".." "${standalone_version}" "src" "microblaze_interrupts_g.c"] file delete $filename set config_file [open $filename w] xprint_generated_header $config_file "Interrupt Handler Table for MicroBlaze Processor" puts $config_file "#include \"microblaze_interrupts_i.h\"" puts $config_file "#include \"xparameters.h\"" puts $config_file "\n" puts $config_file [format "extern void %s (void *);" $handler] puts $config_file "\n/*" puts $config_file "* The interrupt handler table for microblaze processor" puts $config_file "*/\n" puts $config_file [format "%sEntry %s\[\] =" $mb_table $mb_table] puts $config_file "\{" puts -nonewline $config_file [format "\{\t%s" $handler] puts -nonewline $config_file [format ",\n\t(void*) %s\}" $arg] puts -nonewline $config_file "\n\};" puts $config_file "\n" close $config_file } # -------------------------------------- # Return true if this MB has # exception handling support # -------------------------------------- proc mb_has_exceptions { hw_proc_handle } { # Check if the following parameters exist on this MicroBlaze's MPD set ee [get_property CONFIG.C_UNALIGNED_EXCEPTIONS $hw_proc_handle] if { $ee != "" } { return true } set ee [get_property CONFIG.C_ILL_OPCODE_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [get_property CONFIG.C_IOPB_BUS_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [get_property CONFIG.C_DOPB_BUS_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [get_property CONFIG.C_DIV_BY_ZERO_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [get_property CONFIG.C_DIV_ZERO_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [get_property CONFIG.C_FPU_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [get_property CONFIG.C_USE_MMU $hw_proc_handle] if { $ee != "" } { return true } return false } # ------------------------------------------- # Tcl procedure xcreate_mb_exc_config file # ------------------------------------------- proc xcreate_mb_exc_config_file { } { set hfilename [file join "src" "microblaze_exceptions_g.h"] file delete $hfilename set hconfig_file [open $hfilename w] xprint_generated_header $hconfig_file "Exception Handling Header for MicroBlaze Processor" puts $hconfig_file "\n" set sw_proc_handle [get_sw_processor] set hw_proc_handle [get_cells [get_property HW_INSTANCE $sw_proc_handle] ] set proctype [get_property IP_NAME $hw_proc_handle] set procver [get_ip_version $hw_proc_handle] if { ![mb_has_exceptions $hw_proc_handle]} { ;# NO exceptions are enabled close $hconfig_file ;# Do not generate any info in either the header or the C file return } puts $hconfig_file "\#define MICROBLAZE_EXCEPTIONS_ENABLED 1" if { [mb_can_handle_exceptions_in_delay_slots $procver] } { puts $hconfig_file "#define MICROBLAZE_CAN_HANDLE_EXCEPTIONS_IN_DELAY_SLOTS" } close $hconfig_file } # -------------------------------------- # Return true if MB ver 'procver' has # support for handling exceptions in # delay slots # -------------------------------------- proc mb_can_handle_exceptions_in_delay_slots { procver } { if { [string compare -nocase $procver "5.00.a"] >= 0 } { return true } else { return false } } # -------------------------------------- # Return true if this MB has PVR support # -------------------------------------- proc mb_has_pvr { hw_proc_handle } { # Check if the following parameters exist on this MicroBlaze's MPD set pvr [get_property CONFIG.C_PVR $hw_proc_handle] if { $pvr != "" } { return true } return false } # -------------------------------------- # Microblaze config checks # -------------------------------------- proc mb_drc_checks { } { set compiler [common::get_property CONFIG.compiler $sw_proc_handle] # check for valid compiler if { [string first "mb-gcc" $compiler] == 0 && [string first "mb-g++" $compiler] == 0} { error "Wrong compiler requested. FreeRTOS can be compiled only with the GNU compiler for MicroBlaze." "" "mdt_error" } # check for valid stdio parameters set stdin [common::get_property CONFIG.stdin $os_handle] set stdout [common::get_property CONFIG.stdout $os_handle] if { $stdin == "none" || $stdout == "none" } { error "The STDIN/STDOUT parameters are not set. FreeRTOS requires stdin/stdout to be set." "" "mdt_error" } # check if the design has a intc set intr_port [hsi::get_pins -of_objects $hw_proc_handle Interrupt] set intr_flag 1 if { [llength $intr_port] == 0 } { set intr_flag 0 } else { set intr_net [hsi::get_nets -of_objects $intr_port] if { [llength $intr_port] == 0 } { set intr_flag 0 } } if {$intr_flag == 0 } { error "CPU has no connection to Interrupt controller." "" "mdt_error" } # support only AXI/PLB set bus_name "" set interconnect [common::get_property CONFIG.C_INTERCONNECT $hw_proc_handle] puts [format "hw_proc_handle is %s" $hw_proc_handle] if { $interconnect == 2 } { set intf_pin [hsi::get_intf_pins -of_objects $hw_proc_handle "M_AXI_DP"] if { [llength $intf_pin] } { set bus_name [hsi::get_intf_nets -of_objects $intf_pin] } } else { error "FreeRTOS supports Microblaze with only a AXI interconnect" "" "mdt_error" } if { [llength $bus_name] == 0 } { error "Microblaze M_AXI_DP is not connected to slave peripherals" } # obtain handles to all the peripherals in the design set slave_ifs [hsi::get_intf_pins -of_objects $bus_name -filter "TYPE==SLAVE"] puts [format "slave_ifs %s bus_name %s" $slave_ifs $bus_name] set timer_count 0 set timer_has_intr 0 # check for a valid timer foreach if $slave_ifs { set ip_handle [hsi::get_cells -of_objects $if] if {$ip_handle != $hw_proc_handle} { set type [common::get_property IP_NAME $ip_handle] if { $type == "axi_timer" } { incr timer_count # check if the timer interrupts are enabled set intr_port [hsi::get_pins -of_objects $ip_handle interrupt] if { [llength $intr_port] != 0 } { set intr_net [hsi::get_nets -of_objects $intr_port] if { [llength $intr_net] != 0 } { set timer_has_intr 1 } } } } } if { $timer_count == 0 } { error "FreeRTOS for Microblaze requires an axi_timer or xps_timer. The HW platform doesn't have a valid timer." "" "mdt_error" } if { $timer_has_intr == 0 } { error "FreeRTOS for Microblaze requires interrupts enabled for a timer." "" "mdt_error" } set systmr_interval_ms [common::get_property CONFIG.systmr_interval $os_handle] if { $systmr_interval_ms <= 0 } { error "Invalid value for parameter systmr_interval specified. Please specify a positive value." "" "mdt_error" } }