Commit ea7d60dc authored by Andrey Filippov's avatar Andrey Filippov

implemented more debug features during boot

parent d38a7e9f
......@@ -29,8 +29,8 @@ class EzynqFeatures:
'ERR_NOT_A_FLOAT': 'Value is not a float',
'ERR_NOT_A_BOOLEAN': 'Value is not a boolean'
}
BOOLEANS=(('0','FALSE','DISABLE','DISABLED','N'),
('1','TRUE', 'ENABLE','ENABLED','Y'))
BOOLEANS=(('0','FALSE','DISABLE','DISABLED','N','OFF'),
('1','TRUE', 'ENABLE','ENABLED','Y','ON'))
# defines - a list, order determines HTML output order
# Each element has fields:
# 'NAME' - unique name to access this parameter
......@@ -146,9 +146,10 @@ class EzynqFeatures:
all_set=False
print "Configuration file is missing mandatory parameter "+self.defs[name]['CONF_NAME']+': '+self.defs[name]['DESCRIPTION']
else:
if not self.defs[name]['DEFAULT'] is None:
# use default parameter
# print 'Adding default : ',name,'=', self.defs[name]['DEFAULT']
self.pars[name]=self.defs[name]['DEFAULT']
self.pars[name]=self.defs[name]['DEFAULT']
return all_set
def get_par_names(self):
# name_offs=sorted([(name,self.registers[name]['OFFS']) for name in self.registers], key = lambda l: l[1])
......@@ -174,6 +175,16 @@ class EzynqFeatures:
except:
raise Exception (name+' not found in self.defs') # should not happen with wrong data, program bug
def get_par_value_or_none(self,name):
try:
return self.pars[name]
except:
try:
_=self.defs[name]['CONF_NAME']
except:
raise Exception (name+' not found in self.defs') # should not happen with wrong data, program bug
return
def get_par_value(self,name):
try:
return self.pars[name]
......@@ -222,6 +233,10 @@ class EzynqFeatures:
def is_specified(self,name): # directly specified
return name in self.defined
def undefine_parameter(self,name):
if name in self.pars:
self.pars[name]=None
def set_calculated_value(self,name,value,force=True):
if (not force) and (name in self.defined):
......@@ -255,11 +270,14 @@ class EzynqFeatures:
# name= self.config_names[conf_name]
feature= self.defs[name]
value= self.get_par_value(name)
if isinstance(value,int):
if (feature['TYPE']=='H'):
value=hex(value)
else:
value=str(value)
if value is None:
value='None'
else:
if isinstance(value,int):
if (feature['TYPE']=='H'):
value=hex(value)
else:
value=str(value)
try:
target_value=self.get_par_target(name)
if isinstance(target_value,int):
......
......@@ -299,6 +299,16 @@ class EzynqMIO:
('tri_enable', 1))) # ,force,warn)
return led_register_set.get_register_sets(sort_addr=True,apply_new=True)
def rbl_led_on_off(self, mio_pin, led_on, reg_sets):
# generate code to be included in RBL register setup
if led_on:
led_on=1
led_register_set= ezynq_registers.EzynqRegisters(self.MIO_PINS_DEFS,0,reg_sets)
led_register_set.set_bitfields('mio_pin_%02i'%mio_pin, ( # output 0 - LED off
('pullup', 1-led_on),
('tri_enable', 1-led_on))) # ,force,warn)
return led_register_set.get_register_sets(sort_addr=True,apply_new=True)
def parse_config_mio(self,raw_configs):
attrib_suffix='ATTRIB'
options = {}
......
......@@ -45,12 +45,12 @@ class EzynqUART:
self.channel=None
return
self.channel=max(uarts)
self.features=ezynq_feature_config.EzynqFeatures(self.UART_CFG_DEFS,self.channel) #DDR_CFG_DEFS
self.features=ezynq_feature_config.EzynqFeatures(self.UART_CFG_DEFS,self.channel)
self.features.parse_features(raw_configs)
if len(uarts)>1:
if 'DEBUG_CHANNEL' in self.features.pars:
self.channel=self.features.pars['DEBUG_CHANNEL']
self.features=ezynq_feature_config.EzynqFeatures(self.UART_CFG_DEFS,self.channel) #DDR_CFG_DEFS
self.features=ezynq_feature_config.EzynqFeatures(self.UART_CFG_DEFS,self.channel)
self.features.parse_features(raw_configs)
self.uart_register_set= ezynq_registers.EzynqRegisters(self.UART_DEFS,self.channel,[],permit_undefined_bits)
self.slcr_register_set= ezynq_registers.EzynqRegisters(self.SLCR_CLK_DEFS,0,[],permit_undefined_bits)
......@@ -98,7 +98,23 @@ class EzynqUART:
self.bdiv,self.cd,self.baud_rate=get_bdiv_cd_baud(self.baud_rate,min_bdiv)
self.features.set_calculated_value('BAUD_RATE',self.baud_rate,force=True)
# these instructions will be usen to generate C code.
# when defined here (as register writes/tests) they will appear in the overall list
# of registers (HTML file)
def set_uart_codes(self):
uart_extra_set= ezynq_registers.EzynqRegisters(self.UART_DEFS,self.channel,[])
# wait transmitter FIFO empty (use before proceeding to risky of reboot code )
uart_extra_set.wait_reg_field_values('channel_sts', # Channel status
(('tempty', 1)), True) # Transmitter FIFO empty (continuous)
uart_extra_set.flush() # to separate codes, not to combine in one write
# wait transmitter FIFO not full (OK to put more characters)
uart_extra_set.wait_reg_field_values('channel_sts', # Channel status
(('tful', 0)), True) # Transmitter FIFO full (continuous)
uart_extra_set.flush()
uart_extra_set.set_bitfields('tx_rx_fifo',( # TX/RX FIFO character data write/read
('fifo', self.cd)),True) # read/write FIFO character data
return uart_extra_set.get_register_sets(sort_addr=True,apply_new=True)
def setup_uart(self,current_reg_sets,force=False,warn=False):
......@@ -157,89 +173,3 @@ class EzynqUART:
('rxres', 0)), True, warn)
return uart_register_set.get_register_sets(sort_addr=True,apply_new=True)
#
#
# 'channel_sts': {'OFFS': 0x02c,'DFLT':0x0,'RW':'R',
# 'COMMENTS':'Channel status',
# 'FIELDS':{
# 'reserved1': {'r':(15,31),'d':0,'m':'R'},
# 'tnful': {'r':(14,14),'d':0,'m':'R', 'c':'Transmitter FIFO nearly full'},
# 'ttrig': {'r':(13,13),'d':0,'m':'R', 'c':'Transmitter FIFO level >= preset TTRIG value'},
# 'fdelt': {'r':(12,12),'d':0,'m':'R', 'c':'Receiver FIFO level >= preset FDEL value'},
# 'tactive': {'r':(11,11),'d':0,'m':'R', 'c':'Transmitter active'},
# 'ractive': {'r':(10,10),'d':0,'m':'R', 'c':'Receiver active'},
# 'reserved2': {'r':( 9, 9),'d':0,'m':'R', 'c':''},
# 'reserved3': {'r':( 8, 8),'d':0,'m':'R', 'c':''},
# 'reserved4': {'r':( 7, 7),'d':0,'m':'R', 'c':''},
# 'reserved5': {'r':( 6, 6),'d':0,'m':'R', 'c':''},
# 'reserved6': {'r':( 5, 5),'d':0,'m':'R', 'c':''},
# 'tful': {'r':( 4, 4),'d':0,'m':'R', 'c':'Transmitter FIFO full (continuous)'},
# 'tempty': {'r':( 3, 3),'d':0,'m':'R', 'c':'Transmitter FIFO empty (continuous)'},
# 'rful': {'r':( 2, 2),'d':0,'m':'R', 'c':'Receiver FIFO full (continuous)'},
# 'rempty': {'r':( 1, 1),'d':0,'m':'R', 'c':'Receiver FIFO empty (continuous)'},
# 'rtrig': {'r':( 0, 0),'d':0,'m':'R', 'c':'Receiver FIFO level >= preset RTRIG value (continuous)'}}},
# 'uart_rst_ctrl': {'OFFS': 0x228,'DFLT':0,'RW':'RW', # Never set
# 'COMMENTS':'UART software reset control for reference clock and CPU_1x (AMBA) clock domains',
# 'FIELDS':{
# 'reserved': {'r':( 4,31),'d':0, 'c':'reserved'},
# 'uart1_ref_rst': {'r':( 3, 3),'d':0, 'c':'UART 1 reference clock domain reset: 0 - normal, 1 - reset'},
# 'uart0_ref_rst': {'r':( 2, 2),'d':0, 'c':'UART 0 reference clock domain reset: 0 - normal, 1 - reset'},
# 'uart1_cpu1x_rst': {'r':( 1, 1),'d':0, 'c':'UART 1 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset'},
# 'uart0_cpu1x_rst': {'r':( 0, 0),'d':0, 'c':'UART 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset'}}},
#MIN_SAMPLES_PER_BIT
# clk_register_set.wait_reg_field_values('pll_status',tuple(bits), True, warn)
#
# if 'DDR' in self.pll_fdivs:
# clk_register_set.set_bitfields('ddr_pll_ctrl',(('pll_bypass_force', 0),
# ('pll_bypass_qual', 0)),force,warn)
# writel(0x0000000f, &slcr_base->uart_rst_ctrl); /* UART reset on */
#
# //&slcr_base->uart_rst_ctrl
# // writel(0x0000000f, &slcr_base->uart_rst_ctrl); /* UART reset on */
# /* delay ??? move reset on earlier?*/
# writel(0x00000000, &slcr_base->uart_rst_ctrl); /* UART reset off */
#
# /* uart 1 */
# writel(0x00000020, &uart1_base->mode); /* UART character frame */
# /* a. Disable the Rx path: set uart.Control_reg0 [RXEN] = 0 and [RXDIS] = 1.
# b. Disable the Txpath: set uart.Control_reg0 [TXEN] = 0 and [TXDIS] = 1. */
# writel(0x00000028, &uart1_base->control); /*a,b */
# /* c. Write the calculated CD value into the uart.Baud_rate_gen_reg0 [CD] bit field. */
# writel(12, &uart1_base->baud_rate_gen); /*c - for 25MHz and 115200 CD=12, (BDIV+1)=18 */
# /* d. Write the calculated BDIV value into the uart.Baud_rate_divider_reg0 [BDIV] bit value. */
# writel(17, &uart1_base->baud_rate_div); /*d - for 25MHz and 115200 CD=12, (BDIV+1)=18 */
# writel(0x117, &uart1_base->control); /* restart and enable ug585v1.6.1. p 555 */
# writel(0x14, &uart1_base->control); /*just a delay - 1-st character is usually lost */
# def ddr_dci_calibrate(self,current_reg_sets,force=False,warn=False):
# ddriob_register_set=self.ddriob_register_set
# ddriob_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',1),force,warn)
# ddriob_register_set.flush() # close previous register settings
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',0),force,warn)
# ddriob_register_set.flush()# close previous register settings
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', (('reset', 1),
# ('enable',1),
# ('nref_opt1',0),
# ('nref_opt2',0),
# ('nref_opt4',1),
# ('pref_opt2',0),
# ('update_control',0)),force,warn)
# # add wait for DCI calibration DONE
# ddriob_register_set.wait_reg_field_values('ddriob_dci_status',('done',1), True, warn)
#
# return ddriob_register_set.get_register_sets(True,True) # close previous register settings, return new result
......@@ -131,6 +131,12 @@ UART_DEFS={ #not all fields are defined currently
'rful': {'r':( 2, 2),'d':0,'m':'R', 'c':'Receiver FIFO full (continuous)'},
'rempty': {'r':( 1, 1),'d':0,'m':'R', 'c':'Receiver FIFO empty (continuous)'},
'rtrig': {'r':( 0, 0),'d':0,'m':'R', 'c':'Receiver FIFO level >= preset RTRIG value (continuous)'}}},
'tx_rx_fifo': {'OFFS': 0x030,'DFLT':0,'RW':'RW',
'COMMENTS':'TX/RX FIFO character data write/read',
'FIELDS':{
'reserved': {'r':( 8,31),'d':0},
'fifo': {'r':( 0, 7),'d':0, 'c':'read/write FIFO character data'}}},
'baud_rate_div': {'OFFS': 0x034,'DFLT':0xf,'RW':'RW',
'COMMENTS':'Number of bit sample periods minus 1',
......
......@@ -21,7 +21,76 @@ __version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
import os
#import ezynq_clk
import ezynq_feature_config
#Use 'TYPE':'I' for decimal output, 'H' - for hex. On input both are accepted
UBOOT_CFG_DEFS=[
{'NAME':'BOOT_DEBUG', 'CONF_NAME':'CONFIG_EZYNQ_BOOT_DEBUG','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Enable debug features during boot'},
{'NAME':'LED_DEBUG', 'CONF_NAME':'CONFIG_EZYNQ_LED_DEBUG','TYPE':'I','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'Specify MIO pin to use for debug purposed during boot process'},
{'NAME':'UART_DEBUG_USE_LED', 'CONF_NAME':'CONFIG_EZYNQ_UART_DEBUG_USE_LED','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Turn debug LED off/on while waiting for UART FIFO not full'},
{'NAME':'DUMP_SLCR_EARLY', 'CONF_NAME':'CONFIG_EZYNQ_DUMP_SLCR_EARLY','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Dump SLCR registers as soon as UART is initialized (depends on CONFIG_EZYNQ_BOOT_DEBUG)'},
{'NAME':'DUMP_DDRC_EARLY', 'CONF_NAME':'CONFIG_EZYNQ_DUMP_DDRC_EARLY','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Dump DDRC registers as soon as UART is initialized (depends on CONFIG_EZYNQ_BOOT_DEBUG)'},
{'NAME':'DUMP_SLCR_LATE', 'CONF_NAME':'CONFIG_EZYNQ_DUMP_SLCR_LATE','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Dump SLCR registers after DDR memory is initialized (depends on CONFIG_EZYNQ_BOOT_DEBUG)'},
{'NAME':'DUMP_DDRC_LATE', 'CONF_NAME':'CONFIG_EZYNQ_DUMP_DDRC_LATE','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Dump DDRC registers after DDR memory is initialized (depends on CONFIG_EZYNQ_BOOT_DEBUG)'},
{'NAME':'LED_CHECKPOINT_1', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_1', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF in RBL (just after MIO is set up)'},
{'NAME':'LED_CHECKPOINT_2', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_2', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF first after getting to user code'},
{'NAME':'LED_CHECKPOINT_3', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_3', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF first after getting to user code'},
{'NAME':'LED_CHECKPOINT_4', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_4', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF after PLL bypass is OFF'},
{'NAME':'LED_CHECKPOINT_5', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_5', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF after UART is programmed'},
{'NAME':'LED_CHECKPOINT_6', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_6', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF after DCI is calibrated'},
{'NAME':'LED_CHECKPOINT_7', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_7', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF after DDR is initialized'},
{'NAME':'LED_CHECKPOINT_8', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_8', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF before relocation to DDR (to 0x4000000+ )'},
{'NAME':'LED_CHECKPOINT_9', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_9', 'TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF after relocation to DDR (to 0x4000000+ )'},
{'NAME':'LED_CHECKPOINT_10', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_10','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF before remapping OCM0-OCM2 high'},
{'NAME':'LED_CHECKPOINT_11', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_11','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF after remapping OCM0-OCM2 high'},
{'NAME':'LED_CHECKPOINT_12', 'CONF_NAME':'CONFIG_EZYNQ_LED_CHECKPOINT_12','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':None,
'DESCRIPTION':'LED ON/OFF before leaving lowlevel_init()'},
]
#
# CONFIG_EZYNQ_BOOT_DEBUG = y # configure UARTx and send register dumps there
# CONFIG_EZYNQ_LED_DEBUG = 47 # toggle LED during boot
# CONFIG_EZYNQ_UART_DEBUG_USE_LED = y # turn on/off LED while waiting for transmit FIFO not full
#
# CONFIG_EZYNQ_DUMP_SLCR_EARLY = y # Dump SLCR registers as soon as UART is initilaized (depends on CONFIG_EZYNQ_BOOT_DEBUG)
# CONFIG_EZYNQ_DUMP_DDRC_EARLY = y # Dump DDRC registers as soon as UART is initilaized (depends on CONFIG_EZYNQ_BOOT_DEBUG)
# CONFIG_EZYNQ_DUMP_SLCR_LATE = y # Dump SLCR registers after DDR memory is initilaized (depends on CONFIG_EZYNQ_BOOT_DEBUG)
# CONFIG_EZYNQ_DUMP_DDRC_LATE = y # Dump DDRC registers after DDR memory is initilaized (depends on CONFIG_EZYNQ_BOOT_DEBUG)
#
# #Turning LED on/off at different stages of the boot process. Requires CONFIG_EZYNQ_LED_DEBUG to be set
# #If defined, each can be 0,1, ON or OFF
# CONFIG_EZYNQ_LED_CHECKPOINT_1 = ON # in RBL setup, as soon as MIO is programmed
# CONFIG_EZYNQ_LED_CHECKPOINT_2 = OFF # First after getting to user code
# CONFIG_EZYNQ_LED_CHECKPOINT_3 = OFF # After setting clock registers
# CONFIG_EZYNQ_LED_CHECKPOINT_4 = ON # After PLL bypass is OFF
# CONFIG_EZYNQ_LED_CHECKPOINT_5 = ON # After UART is programmed
# CONFIG_EZYNQ_LED_CHECKPOINT_6 = OFF # After DCI is calibrated
# CONFIG_EZYNQ_LED_CHECKPOINT_7 = ON # After DDR is initialized
# CONFIG_EZYNQ_LED_CHECKPOINT_8 = OFF # Before relocation to DDR (to 0x4000000+ )
# CONFIG_EZYNQ_LED_CHECKPOINT_9 = ON # After relocation to DDR (to 0x4000000+ )
# CONFIG_EZYNQ_LED_CHECKPOINT_10 = OFF # Before remapping OCM0-OCM2 high
# CONFIG_EZYNQ_LED_CHECKPOINT_11 = ON # After remapping OCM0-OCM2 high
# CONFIG_EZYNQ_LED_CHECKPOINT_12 = OFF # Before leaving lowlevel_init()
class EzynqUBoot:
license="""/*
* This file is automatically generated by the Free Software program using open information from the
......@@ -40,10 +109,31 @@ class EzynqUBoot:
"""
def __init__(self, verbosity):
def __init__(self, raw_configs, verbosity):
self.cfile=self.license + self.include_section
self.verbosity=verbosity
self.sections=['license','include']
self.sections=['license','include']
self.features=ezynq_feature_config.EzynqFeatures(UBOOT_CFG_DEFS)
self.features.parse_features(raw_configs)
self.features.check_missing_features()
# undefine all if debug is disabled
if not self.features.get_par_value_or_none('BOOT_DEBUG'):
for name in self.features.get_par_names():
self.features.undefine_parameter(name)
elif self.features.get_par_value_or_none('LED_DEBUG') is None:
for name in self.features.get_par_names():
if 'LED' in name:
self.features.undefine_parameter(name)
def html_list_features(self,html_file):
if not html_file:
return
html_file.write('<h2>Boot process debug features setup</h2>\n')
self.features.html_list_features(html_file)
# print self.features.get_par_names()
def get_c_file(self):
return self.cfile
def _opt_hex(self,d):
......@@ -70,14 +160,14 @@ class EzynqUBoot:
self.sections.append('slcr_lock_unlock_setup')
self.cfile+="""
/* Lock SLCR registers - may be called after everything is done. */
void lock_slcr(void) /*not to conflict with another slcr_lock() in u-boot
void lock_slcr(void)
{
"""
self._add_reg_writes(reg_sets[:1])
self.cfile+="""}
/* Unlock SLCR registers - SHOULD be called first before writing any SLCR registers. */
void unlock_slcr(void) /*not to conflict with another slcr_unlock() in u-boot
void unlock_slcr(void)
{
"""
self._add_reg_writes(reg_sets[1:])
......@@ -86,41 +176,19 @@ void unlock_slcr(void) /*not to conflict with another slcr_unlock() in u-boot
def make_led_on_off(self, reg_sets):
self.sections.append('led_on_off')
self.cfile+="""
/* Turn LED on/off for debugging of the early stages of boot process. */
void led_on_off(int on) /*not to conflict with another slcr_lock() in u-boot
/* Turn LED ON for debugging of the early stages of boot process. */
inline void debug_led_on(void)
{
"""
self._add_reg_writes([reg_sets[1]])
self.cfile+="""}
/* Turn LED OFF for debugging of the early stages of boot process. */
inline void debug_led_off(void)
{
"""
self.cfile+='\tif (on)'
self._add_reg_writes(reg_sets[1:])
self.cfile+='\telse'
self._add_reg_writes(reg_sets[:1])
self.cfile+='}\n'
#make_led_on_off
# void led_off(void){
# writel(0x00000200, &slcr_base->mio_pin[47]); /* LED off */
# }
# void led_on(void){
# writel(0x00001201, &slcr_base->mio_pin[47]); /* LED on */
# }
#
# void poll_fifo_empty(void){
# while ((readl(&uart1_base->channel_sts) & 0x8) ==0) ; /* wait transmitter buffer is empty */
# }
#
# void poll_putc(int d){
# led_off();
# while ((readl(&uart1_base->channel_sts) & 0x10) !=0) ; /* wait transmitter buffer is not full */
# led_on();
# writel(d, &uart1_base->tx_rx_fifo);
# }
# void poll_puts(char * line){
# int i=0;
# while (line[i]!=0) poll_putc(line[i++]);
# }
def registers_setup(self, reg_sets,clk,num_rbl_regs): #clk is an instance of ezynq_clk.EzynqClk
self.sections.append('registers_setup')
......@@ -145,7 +213,7 @@ inline void pll_setup(void)
self._add_reg_writes(reg_sets)
self.cfile+='}\n\n'
def uart_init (self, reg_sets,clk):
def uart_init (self, reg_sets):
self.sections.append('uart_init')
self.cfile+='''/* Initilize UART to output debug info during boot */
inline void uart_init(void)
......@@ -155,7 +223,119 @@ inline void uart_init(void)
self._add_reg_writes(reg_sets)
self.cfile+='}\n\n'
#uart_transmit (should be called after LED control is set)
def uart_transmit (self, reg_sets):
use_led=self.features.get_par_value_or_none('UART_DEBUG_USE_LED')
self.sections.append('uart_xmit')
# op, addr, data, mask, module_name, register_name, r_def=reg_sets[2]
_, addr, _, _, module_name, register_name, r_def=reg_sets[2]
try:
comments=r_def['COMMENTS']
except:
comments=''
self.cfile+='''/* Wait FIFO is empty (call before getting to risky for reboot code
to make sure all output has been actually sent */
void uart_wait_tx_fifo_empty(void)
{
'''
self._add_reg_writes([reg_sets[0]])
self.cfile+='''}
/* Wait FIFO is not full, send one character
to make sure all output has been actually sent */
void uart_putc(int c)
{
'''
if use_led:
self.cfile+='\tdebug_led_off(); /* turn LED off */\n'
self._add_reg_writes([reg_sets[1]]) # wait FIFO not full
if use_led:
self.cfile+='\tdebug_led_on(); /* turn LED on */\n'
self.cfile+='\twritel(c, 0x%08x); /* %s.%s %s */\n'%(addr,module_name,register_name,comments)
self.cfile+='''}
void uart_puts(char * line){
\tint i=0;
\twhile (line[i]!=0) uart_putc(line[i++]);
}
inline void uart_put_hex_digit(int c)
{
\tuart_putc(c+ ((c>9)? ('a'-10):'0'));
}
void uart_put_hex(int d)
{
\tint i;
\tfor (i=28;i>=0;i-=4) uart_put_hex_digit((d>>i) & 0xf);
}
void uart_dump_regs(int addr_from, int addr_to, int num_per_line )
{
\tint a;
\taddr_from &= ~3;
\tint addr_display= (num_per_line * (((addr_from>>2) & 0x3fffffff)/num_per_line))<<2;
\tfor (a=addr_display; a<=addr_to; a+=4){
\t\tint r= (((a-addr_display)>>2) & 0x3fffffff) % num_per_line;
\t\tif (r==0) {
\t\t\tuart_put_hex(a);
\t\t\tuart_putc(':');
\t\t}
\t\tuart_putc(' ');
\t\tif (a<addr_from){
\t\t\tint j;
\t\t\tfor (j=0;j<8;j++) uart_putc('-');
\t\t} else {
\t\t\tuart_put_hex(readl(a));
\t\t}
\t\tif (r==(num_per_line-1)) {
\t\t\tuart_puts("\\r\\n");
\t\t}
\t}
\tuart_puts("\\r\\n");
}
'''
def make_ddrc_register_dump(self):
self.sections.append('ddrc_dump')
self.cfile+='''/* Dump all DDR Controller registers that do not hang the system */
void dump_ddrc_regs(void)
{
\tuart_puts("DDRC registers\\r\\n");
\tuart_dump_regs(0xf8006000,0xf800607c, 16); /* access to 0xf8006080 hangs */
\tuart_puts("\\r\\n");
\tuart_dump_regs(0xf80060a0, 0xf80060b8, 16);
\tuart_puts("\\r\\n");
\tuart_dump_regs(0xf80060c4, 0xf80060fc, 16);
\tuart_puts("\\r\\n");
\tuart_dump_regs(0xf8006114, 0xf8006194, 16); /* 0xf8006198 hangs */
\tuart_puts("\\r\\n");
\tuart_dump_regs(0xf80061a4, 0xf80061e8, 16); /* 0xf80061f0 hangs */
\tuart_puts("\\r\\n");
\tuart_dump_regs(0xf8006200, 0xf8006224, 16); /* 0xf8006228 hangs */
\tuart_puts("\\r\\n");
\tuart_dump_regs(0xf8006294, 0xf80062b4, 16);
\tuart_puts("\\r\\n");
}
'''
def make_slcr_register_dump(self):
self.sections.append('slcr_dump')
self.cfile+='''/* Dump all SLCR */
void dump_slxr_regs(void)
{
\tuart_dump_regs(0xf8000000, 0xf8000b74, 16);
\tuart_puts("\\r\\n");
'''
def dci_calibration (self, reg_sets,ddr): #ddr is an instance of ezynq_ddr.EzynqDDR
if len(reg_sets)==0:
......@@ -183,57 +363,97 @@ inline void ddr_start(void)
self.sections.append('ddr_start')
def _cp_led(self,name):
led_cp=self.features.get_par_value_or_none(name)
# print name, led_cp
if not led_cp is None:
if led_cp:
self.cfile+='\tdebug_led_on(); /* Turn debug LED ON */\n'
else:
self.cfile+='\tdebug_led_off(); /* Turn debug LED OFF */\n'
def make_lowlevel_init (self):
self.cfile+='''/* Initialize clocks, DDR memory, copy OCM to DDR */
void lowlevel_init(void)
{
'''
if 'uart_init' in self.sections:
self.cfile+='''/* Initialize UART fdro debug information output */
\tuart_init();
'''
self.cfile+='''/*
Unlock SLCR
*/
/* Unlock SLCR */
\tunlock_slcr();
/*
'''
self._cp_led('LED_CHECKPOINT_2') # First after getting to user code
self.cfile+='''/*
Write PLL and clocks registers as the code is now completely loaded to the OCM and no
peripherals are needed immediately
*/
\tregister_setup();
/*
'''
self._cp_led('LED_CHECKPOINT_3') # After setting clock registers
self.cfile+='''/*
Wait PLLs locked and turn off bypass - all clocks should have specified values now
*/
\tpll_setup();
/*
'''
self._cp_led('LED_CHECKPOINT_4') # After PLL bypass is OFF
if 'uart_init' in self.sections:
self.cfile+='''/* Initialize UART for debug information output */
\tuart_init();
'''
self._cp_led('LED_CHECKPOINT_5') # After UART is programmed
if self.features.get_par_value_or_none('DUMP_SLCR_EARLY'):
self.cfile+='\tuart_puts("SLCR registers before DCI/DDR initialization\\r\\n")\n'
self.cfile+='\tdump_slcr_regs(); /*Dump all SLCR registers before DCI/DDR initialization */\n'
if self.features.get_par_value_or_none('DUMP_DDRC_EARLY'):
self.cfile+='\tuart_puts("DDRC registers before DCI/DDR initialization\\r\\n")\n'
self.cfile+='\tdump_ddrc_regs(); /*Dump all DDRC registers before DCI/DDR initialization */\n'
self.cfile+='''/*
Calibrate DDR DCI impedance and wait for completion
*/
\tdci_calibration();
/*
'''
self._cp_led('LED_CHECKPOINT_6') # After DCI is calibrated
self.cfile+='''/*
Remove soft reset from DDR controller - that starts initialization. Wait for completion
*/
\tddr_start();
/*
'''
self._cp_led('LED_CHECKPOINT_7') # After DDR is initialized
if self.features.get_par_value_or_none('DUMP_SLCR_LATE'):
self.cfile+='\tuart_puts("SLCR registers after DCI/DDR initialization\\r\\n")\n'
self.cfile+='\tdump_slcr_regs(); /*Dump all SLCR registers after DCI/DDR initialization */\n'
if self.features.get_par_value_or_none('DUMP_DDRC_LATE'):
self.cfile+='\tuart_puts("DDRC registers after DCI/DDR initialization\\r\\n")\n'
self.cfile+='\tdump_ddrc_regs(); /*Dump all DDRC registers after DCI/DDR initialization */\n'
self.cfile+='''/*
Copy 3 pages of OCM from 0x00000.0x2ffff to DDR 0x4000000.0x402ffff
*/
\tint * s= (int *) 0;
\tint * d= (int *) 0x4000000;
\twhile (s< ((int *)0x30000)) *d++=*s++;
/*
'''
# CONFIG_EZYNQ_LED_CHECKPOINT_10 = OFF # Before relocation down to address 0
# CONFIG_EZYNQ_LED_CHECKPOINT_11 = ON # After relocation down to address 0
# CONFIG_EZYNQ_LED_CHECKPOINT_12 = OFF # Before leaving lowlevel_init()
self._cp_led('LED_CHECKPOINT_8') # Before relocation to DDR (to 0x4000000+ )
self.cfile+='''/*
Now jump to the same instruction in the DDR copy of the currently executed code in OCM
Be careful not to call functions or access data stored in the 3 lower OCM pages.
writel() is OK as it is just a macro, not a function call
*/
*/
\tasm("add pc, pc, #0x4000000" );
/*
'''
self._cp_led('LED_CHECKPOINT_9') # After relocation to DDR (to 0x4000000+ )
self.cfile+='''/*
Remap DDR to zero, FILTERSTART
*/
\twritel(0, &scu_base->filter_start);
......@@ -242,13 +462,17 @@ void lowlevel_init(void)
*/
\twritel(0x757BDF0D, &devcfg_base->unlock);
\twritel(0xFFFFFFFF, &devcfg_base->rom_shadow);
/*
'''
self._cp_led('LED_CHECKPOINT_10') # Before remapping OCM0-OCM2 high
self.cfile+='''/*
Now as the code is executed outside of the OCM it is possible to remap the 3 lower
OCM pages to high memory.
OCM_CFG, Mask out the ROM, map ram into upper addresses
*/
\twritel(0x1F, &slcr_base->ocm_cfg);
/*
'''
self._cp_led('LED_CHECKPOINT_11') # After remapping OCM0-OCM2 high
self.cfile+='''/*
Copy program memory that we are currently executing to low DRAM (0x0.0x2ffff)
Not possible to call library memcpy() as it will try to access not-yet copied code
*/
......@@ -268,6 +492,9 @@ void lowlevel_init(void)
\twritel(0x0, &slcr_base->ddr_urgent_sel);
\t/* Urgent write, ports S2/S3 */
\twritel(0xC, &slcr_base->ddr_urgent);
'''
self._cp_led('LED_CHECKPOINT_12') # Before leaving lowlevel_init()
self.cfile+='''/* Lock SLCR back after everything with it is done */
\tlock_slcr();
/*
This code was called from low OCM, so return should just get back correctly
......@@ -278,7 +505,7 @@ void lowlevel_init(void)
def output_c_file(self,cname):
if not cname:
return
print 'Writing generated u-boot lowlevel() function to ',cname
print 'Writing generated u-boot lowlevel() function to ',os.path.abspath(cname)
c_out_file=open(cname,'w')
c_out_file.write(self.cfile)
c_out_file.close()
......@@ -21,6 +21,7 @@ __version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
import os
import struct
import argparse # http://docs.python.org/2/howto/argparse.html
......@@ -289,6 +290,7 @@ permit_undefined_bits=False
force=True #False
warn_notfit=True # False
regs_masked=[]
u_boot=ezynq_uboot.EzynqUBoot(raw_configs,args.verbosity)
mio_regs=ezynq_mio.EzynqMIO(args.verbosity,QUALIFIER_CHAR,[],permit_undefined_bits) # does not use regs_masked
mio_regs.process_mio(raw_configs,WARN) # does not use regs_masked
......@@ -312,32 +314,39 @@ ddr_mhz=clk.get_ddr_mhz()
if MIO_HTML:
f=open(MIO_HTML,'w')
html_file=open(MIO_HTML,'w')
print 'Generating HTML output',os.path.abspath(MIO_HTML)
else:
f=False
html_file=False
u_boot.html_list_features(html_file)
#output_slcr_lock(registers,f,False,MIO_HTML_MASK) #prohibited by RBL
mio_regs.output_mio(f,MIO_HTML_MASK)
mio_regs.output_mio(html_file,MIO_HTML_MASK)
# def process_mio(self,raw_configs,warn):
# def output_mio(self,f,MIO_HTML_MASK)
# setregs_mio(self,current_reg_sets,force=True):
clk.html_list_clocks(f)
clk.html_list_clocks(html_file)
#output_mio(registers,f,mio,MIO_HTML_MASK)
ddr.calculate_dependent_pars(ddr_mhz)
ddr.pre_validate() # before applying default values (some timings should be undefined, not defaults)
ddr.check_missing_features() #and apply default values
ddr.html_list_features(f) #verify /fix values after defaults are applied
ddr.html_list_features(html_file) #verify /fix values after defaults are applied
#clk.calculate_dependent_pars()
clk.html_list_features(f)
clk.html_list_features(html_file)
reg_sets=[]
segments=[]
reg_sets=mio_regs.setregs_mio(reg_sets,force) # reg Sets include now MIO
segments.append({'TO':len(reg_sets),'RBL':True,'NAME':'MIO','TITLE':'MIO registers configuration'})
led_debug_mio_pin= u_boot.features.get_par_value_or_none('LED_DEBUG')
if not led_debug_mio_pin is None:
led_cp_1=u_boot.features.get_par_value_or_none('LED_CHECKPOINT_1')
if not led_cp_1 is None:
reg_sets=mio_regs.rbl_led_on_off(led_debug_mio_pin, led_cp_1, reg_sets)
segments.append({'TO':len(reg_sets),'RBL':True,'NAME':'RBL_LED','TITLE':'Setting debug LED during RBL to '+('OFF','ON')[led_cp_1]})
#adding ddr registers
if raw_config_value('CONFIG_EZYNQ_SKIP_DDR', raw_configs) is None:
ddr.ddr_init_memory(reg_sets,False,False)
......@@ -353,11 +362,10 @@ segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'CLK','TITLE':'Clock regi
#print 'Debug mode: CLK/PLL configuration by u-boot'
reg_sets=clk.clocks_pll_bypass_off(reg_sets,force)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'PLL','TITLE':'Registers to switch to PLL'})
if not raw_config_value('CONFIG_EZYNQ_BOOT_DEBUG', raw_configs) is None:
if u_boot.features.get_par_value_or_none('BOOT_DEBUG'):
uart=ezynq_uart.EzynqUART()
uart.parse_parameters(raw_configs,used_mio_interfaces,False)
uart.check_missing_features()
uart_channel=uart.channel
if not uart_channel is None:
try:
......@@ -372,11 +380,15 @@ else:
uart_channel=None
if not uart_channel is None:
uart.html_list_features(f)
# Generate UART initialization, putc and wait FIFO empty code
uart.html_list_features(html_file)
reg_sets=uart.setup_uart(reg_sets,force=False,warn=False)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'UART_INIT','TITLE':'Registers to initialize UART'})
reg_sets_uart_extra=uart.set_uart_codes()
reg_sets.extend (reg_sets_uart_extra) # just to be listed, not to be loaded
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'UART_XMIT','TITLE':'UART register tests sets to output debug data'})
if raw_config_value('CONFIG_EZYNQ_SKIP_DDR', raw_configs) is None:
reg_sets=ddr.ddr_dci_calibrate(reg_sets,False,False)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DCI','TITLE':'DDR DCI Calibration'})
......@@ -389,13 +401,10 @@ reg_sets_lock_unlock=clk.generate_lock_unlock()
reg_sets.extend (reg_sets_lock_unlock) # just to be listed, not to be loaded
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'SLCR_LOCK_UNLOCK','TITLE':'SLCR lock/unlock registers - listed out of sequence'})
try:
led_mio_pin=int (raw_config_value('CONFIG_EZYNQ_LED_DEBUG', raw_configs),0)
reg_sets_led=mio_regs.generate_led_off_on(led_mio_pin)
if not led_debug_mio_pin is None:
reg_sets_led=mio_regs.generate_led_off_on(led_debug_mio_pin)
reg_sets.extend (reg_sets_led) # just to be listed, not to be loaded
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'LED','TITLE':'registers/data to turn on/off debug LED - listed out of sequence'})
except:
led_mio_pin=None
# def generate_led_off_on(self, mio_pin):
#CONFIG_EZYNQ_LED_DEBUG=47 # toggle LED during boot
#CONFIG_EZYNQ_BOOT_DEBUG
......@@ -426,27 +435,27 @@ for segment in segments:
show_comments= MIO_HTML_MASK & 0x200
filter_fields=not MIO_HTML_MASK & 0x400
all_used_fields= False
ezynq_registers.print_html_reg_header(f,
ezynq_registers.print_html_reg_header(html_file,
segment['TITLE']+" (%s)"%(('U-BOOT','RBL')[segment['RBL']]),
show_bit_fields, show_comments, filter_fields)
# print segment['TITLE']+" (%s)"%(('U-BOOT','RBL')[segment['RBL']]), start,end
ezynq_registers.print_html_registers(f,
ezynq_registers.print_html_registers(html_file,
reg_sets[:end],
start,
show_bit_fields,
show_comments,
filter_fields,
all_used_fields)
ezynq_registers.print_html_reg_footer(f)
ezynq_registers.print_html_reg_footer(html_file)
if f:
f.write('<h4>Total number of registers set up in the RBL header is <b>'+str(num_rbl_regs)+"</b> of maximal 256</h4>")
if html_file:
html_file.write('<h4>Total number of registers set up in the RBL header is <b>'+str(num_rbl_regs)+"</b> of maximal 256</h4>")
if num_rbl_regs<len(reg_sets):
f.write('<h4>Number of registers set up in u-boot is <b>'+str(len(reg_sets)-num_rbl_regs)+"</b></h4>")
html_file.write('<h4>Number of registers set up in u-boot is <b>'+str(len(reg_sets)-num_rbl_regs)+"</b></h4>")
#
if MIO_HTML:
f.close
html_file.close
#if args.verbosity >= 1:
# print registers
image =[ 0 for k in range (0x8c0/4)]
......@@ -476,9 +485,7 @@ if args.outfile:
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'UART_INIT','TITLE':'Registers to initialize UART'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DCI','TITLE':'DDR DCI Calibration'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DDR_START','TITLE':'DDR initialization start'})
u_boot=ezynq_uboot.EzynqUBoot(args.verbosity)
#CONFIG_EZYNQ_UART_DEBUG_USE_LED
if 'SLCR_LOCK_UNLOCK' in segment_dict:
u_boot.make_slcr_lock_unlock (reg_sets[segment_dict['SLCR_LOCK_UNLOCK']['FROM']:segment_dict['SLCR_LOCK_UNLOCK']['TO']])
if 'LED' in segment_dict:
......@@ -489,7 +496,12 @@ if 'CLK' in segment_dict:
if 'PLL' in segment_dict:
u_boot.pll_setup (reg_sets[segment_dict['PLL']['FROM']:segment_dict['PLL']['TO']],clk)
if 'UART_INIT' in segment_dict:
u_boot.uart_init (reg_sets[segment_dict['UART_INIT']['FROM']:segment_dict['UART_INIT']['TO']],clk)
u_boot.uart_init (reg_sets[segment_dict['UART_INIT']['FROM']:segment_dict['UART_INIT']['TO']])
if 'UART_XMIT' in segment_dict:
u_boot.uart_transmit (reg_sets[segment_dict['UART_XMIT']['FROM']:segment_dict['UART_XMIT']['TO']])
u_boot.make_ddrc_register_dump()
u_boot.make_slcr_register_dump()
#if not u_boot.features.get_par_value_or_none('BOOT_DEBUG') is None:
if 'DCI' in segment_dict:
u_boot.dci_calibration(reg_sets[segment_dict['DCI']['FROM']:segment_dict['DCI']['TO']],ddr)
......
CONFIG_EZYNQ_BOOT_DEBUG=y # configure UARTx and send register dumps there
CONFIG_EZYNQ_LED_DEBUG=47 # toggle LED during boot
CONFIG_EZYNQ_BOOT_DEBUG = y # configure UARTx and send register dumps there
CONFIG_EZYNQ_LED_DEBUG = 47 # toggle LED during boot
CONFIG_EZYNQ_UART_DEBUG_USE_LED = y # turn on/off LED while waiting for transmit FIFO not full
CONFIG_EZYNQ_DUMP_SLCR_EARLY = y # Dump SLCR registers as soon as UART is initialized (depends on CONFIG_EZYNQ_BOOT_DEBUG)
CONFIG_EZYNQ_DUMP_DDRC_EARLY = y # Dump DDRC registers as soon as UART is initialized (depends on CONFIG_EZYNQ_BOOT_DEBUG)
CONFIG_EZYNQ_DUMP_SLCR_LATE = y # Dump SLCR registers after DDR memory is initialized (depends on CONFIG_EZYNQ_BOOT_DEBUG)
CONFIG_EZYNQ_DUMP_DDRC_LATE = y # Dump DDRC registers after DDR memory is initialized (depends on CONFIG_EZYNQ_BOOT_DEBUG)
#Turning LED on/off at different stages of the boot process. Requires CONFIG_EZYNQ_LED_DEBUG to be set
#If defined, each can be 0,1, ON or OFF
CONFIG_EZYNQ_LED_CHECKPOINT_1 = ON # in RBL setup, as soon as MIO is programmed
#CONFIG_EZYNQ_LED_CHECKPOINT_2 = OFF # First after getting to user code
#CONFIG_EZYNQ_LED_CHECKPOINT_3 = ON # After setting clock registers
#CONFIG_EZYNQ_LED_CHECKPOINT_4 = OFF # After PLL bypass is OFF
#CONFIG_EZYNQ_LED_CHECKPOINT_5 = ON # After UART is programmed
CONFIG_EZYNQ_LED_CHECKPOINT_6 = OFF # After DCI is calibrated
CONFIG_EZYNQ_LED_CHECKPOINT_7 = ON # After DDR is initialized
CONFIG_EZYNQ_LED_CHECKPOINT_8 = OFF # Before relocation to DDR (to 0x4000000+ )
CONFIG_EZYNQ_LED_CHECKPOINT_9 = ON # After relocation to DDR (to 0x4000000+ )
CONFIG_EZYNQ_LED_CHECKPOINT_10 = OFF # Before remapping OCM0-OCM2 high
CONFIG_EZYNQ_LED_CHECKPOINT_11 = ON # After remapping OCM0-OCM2 high
CONFIG_EZYNQ_LED_CHECKPOINT_12 = OFF # Before leaving lowlevel_init()
CONFIG_EZYNQ_UART1_BAUD_RATE=115200
#Configuration for the microzed board
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment