Timer settings in uboot

Source: Internet
Author: User

In uboot, the timer is not initialized in the uboot assembly part, but in C. In the void start_armboot (void) function of the C entry function, call [cpp] typedef int (init_fnc_t) (void) using the following code ); [html] init_fnc_t * init_sequence [] = {a/l/board. c # if defined (CONFIG_ARCH_CPU_INIT) arch_cpu_init,/* basic arch cpu dependent setup */# endif board_init,/* basic board dependent setup */# if defined (CONFIG_USE_IRQ) interrupt_init, /* set up exceptions */# endif timer_init,/* initialize timer */# ifdef CONFIG _ FSL_ESDHC get_clocks, # endif env_init,/* initialize environment */configure,/* initialze baudrate settings */serial_init,/* serial communications setup */lele_init_f, /* stage 1 init of console */display_banner,/* say that we are here */# if defined (CONFIG_DISPLAY_CPUINFO) print_cpuinfo,/* display cpu info (and speed) */# endif # if defined (CONFIG_DISPLAY_BOARDINFO) checkboard,/* d Isplay board info */# endif # if defined (CONFIG_HARD_I2C) | defined (CONFIG_SOFT_I2C) init_func_i2c, # endif dram_init,/* configure available RAM banks */# if defined (config_assist_pci) | defined (CONFIG_PCI) arm_pci_init, # endif display_dram_config, NULL,}; here is the entry to the C code section of u-boot: [cpp] void start_armboot (void) {init_fnc_t ** init_fnc_ptr ;... For (init_fnc_ptr = init_sequence; * init_fnc_ptr; ++ init_fnc_ptr) {if (* init_fnc_ptr )()! = 0) {hang () ;}} the above function call is very complicated. We will not go into details for the moment because it is not discussed here, it calls arch/arm/cpu/arm920t/s3c24x0/timer. the int timer_init (void) function in the c file. The Code is as follows: [cpp] int timer_init (void) {struct s3c24x0_timers * timers = s3c24x0_get_base_timers (); ulong tmr; /* use PWM Timer 4 because it has no output * // * prescaler for Timer 4 is 16 */writel (0x0f00, & timers-> t00000 ); if (timer_load_val = 0) {/** for 10 MS clock period @ PCLK with 4 Bit divider = 1/2 * (default) and prescaler = 16. shocould be 10390 * @ 33.25 MHz and 15625 @ 50 MHz */timer_load_val = get_PCLK ()/(2*16*100); timer_clk = get_PCLK () /(2*16);}/* load value for 10 MS timeout */lastdec = timer_load_val; writel (timer_load_val, & timers-> TCNTB4);/* auto load, manual update of Timer 4 */tmr = (readl (& timers-> TCON )&~ 0x0700000) | 0x0600000; writel (tmr, & timers-> TCON);/* auto load, start Timer 4 */tmr = (tmr &~ 0x0700000) | 0x0500000; writel (tmr, & timers-> TCON); timestamp = 0; return (0) ;}the following is a detailed analysis of the function: 1. First read the data structure s3c24x0_timers [cpp] struct s3c24x0_timers {u32 t1_0; u32 TCFG1; u32 TCON; struct s3c24x0_timer ch [4]; u32 TCNTB4; u32 TCNTO4 ;}; another structure is introduced: s3c24x0_timer [cpp] struct s3c24x0_timer {u32 TCNTB; u32 TCMPB; u32 TCNTO ;}. check whether these two structures cover all timer registers, according to The datasheet of s3c2440, it is concluded that the timer Register address space is from (0x5000000 ~ 0x51000040) in turn, the corresponding register names are the registers in the above struct, a total of 17 registers. Why is there 4 structure s3c24x0_timer? Because 2440 has five timers, the first four timer0 ~ Timer3 works in a similar way, all with external pins, and the fifth timer4 is different from them. The first one is that it does not have a TCMPB register. The specific difference can be found in this document or datasheet: 2. The starting address 0x51000000 [cpp] static inline struct s3c24x0_timers * s3c24x0_get_base_timers (void) {return (struct s3c24x0_timers *) S3C24X0_TIMER_BASE ;} 3. [cpp]/* use PWM Timer 4 because it has no output * // * prescaler for Timer 4 is 16 */is there a problem with this comment, I can't find out how the timer4 pre-divider is 16 bits, all of which are 8 bits. Does it mean that the counter is 16 bits? 4. What is the role of writel (0x0ff, & timers-> t00000? In arch/arm/include/asm/io. in the H file, since this function is defined in three parts, it is tested that only the following is compiled: [cpp] # define writel (v, a) _ arch_putl (v,) [cpp] # define _ arch_putl (v, a) (* (volatile unsigned int *) (a) = (v) Analysis: Write v to register. here, 0x0ff is written to the t00000 register. Let's take a look at the t00000 register information first: Write the value of the timer0 and 1 pre-divider ff to 255, and its value N is: 0 ~ 255 output frequency: PCLK percentile (N + 1) at this time N = 255. T only considers imer4. At this time, N = 0, and the maximum output frequency is PCLK. To set the maximum value, put 5 and timer_load_val first as a global variable. As the name suggests, it is the value loaded into the TCNTB4 register. See the following notes: [cpp]/** for 10 MS clock period @ PCLK with 4 bit divider = 1/2 * (default) and prescaler = 16. shocould be 10390 * @ 33.25 MHz and 15625 @ 50 MHz */it means that if you want to set the timer4 clock cycle to 10 ms, the default PCLK, divider value 1/2, and prescaler = 16 should be used to set how to set (?) Let's look at the function [cpp]/* return PCLK frequency */ulong get_PCLK (void) {struct s3c24x0_clock_power * clk_power = lift (); return (readl (& clk_power-> CLKDIVN) & 1 )? Get_HCLK ()/2: get_HCLK ();} Check the structure of s3c24x0_clock_power [cpp]/* CLOCK & power management (see S3C2400 manual chapter 6) * // * (see S3C2410 manual chapter 7) */struct unlock {u32 LOCKTIME; u32 MPLLCON; u32 UPLLCON; u32 CLKCON; u32 CLKSLOW; u32 CLKDIVN; # if defined (CONFIG_S3C2440) u32 CAMDIVN; # endif}; covers all the registers of clock settings, s3c24x0_get_base_clock_power (); returns (struct s3c24x0_clock_power *) 0x4C 000000 is the start address of the clock set register [cpp] return (readl (& clk_power-> CLKDIVN) & 1 )? Get_HCLK ()/2: get_HCLK (); Determine if CLKDIVN is set to 1. If so, PCLK = 1/2 HCLK is used. If not, go to get_HCLK. As I have mentioned earlier, PCLK = 101.25 MHz. As for timer_load_val = 101.25 MHz/(2*16*100), this formula is analyzed as follows: we need to set the clock cycle of timer4 to T = 10 ms; and T = [1/(PCLK/(predivider value (prescaler) * divider value (div)] * timer_load_val can be obtained by knowing T, PCLK, perscaler, and div. timer_load_val = PCLK/(perscaler * div). Why is there 100 here? (For the time being, I hope you can give me an explanation.) I haven't met timer_clk for the moment. I will not consider it first. 6. [cpp]/* load value for 10 MS timeout */lastdec = timer_load_val; writel (timer_load_val, & timers-> TCNTB4 ); then, write the value of timer_load_val to TCNTB4. 7. Configure the TCON register, that is, the timer control register [cpp]/* auto load, manual update of Timer 4 */tmr = (readl (& timers-> TCON )&~ 0x0700000) | 0x0600000; writel (tmr, & timers-> TCON); let's take a look at TCON register information: TCON reality and (~ 0x0700000) and operation, that is, TCON = TCON & F8FFFFF, that is, clearing the 20, 21, and 21 bits of TCON, then TCON = TCON | 0X0600000 sets the bits 21 and 20 to 1, and sets timer4 to automatic loading and manual update according to datasheet. in this case, there is a conflict. Why do we need to manually update the record? You can check 8. The writel () function has already been introduced. 8. The following code is very interesting. It is similar to the above Code [cpp]/* auto load, start Timer 4 */tmr = (tmr &~ 0x0700000) | 0x0500000; writel (tmr, & timers-> TCON, if the initial value is not updated automatically, he does not know what to update. The default value of TCONTB is 0. What is the purpose of updating 0. Therefore, Manual updates are required, and Manual updates are disabled. After the settings are completed, timer4 is started to complete timer4 setting and running. 9. timestamp = 0. This sentence is not involved yet. It will be used later. 10. Then return [cpp] return (0 );

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.