482 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			482 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /****************************************************************************
 | |||
|  | 
 | |||
|  | Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. | |||
|  | 
 | |||
|  | This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT | |||
|  | be copied by any method or incorporated into another program without | |||
|  | the express written consent of Aerospace C.Power. This Information or any portion | |||
|  | thereof remains the property of Aerospace C.Power. The Information contained herein | |||
|  | is believed to be accurate and Aerospace C.Power assumes no responsibility or | |||
|  | liability for its use in any way and conveys no license or title under | |||
|  | any patent or copyright and makes no representation or warranty that this | |||
|  | Information is free from patent or copyright infringement. | |||
|  | 
 | |||
|  | ****************************************************************************/ | |||
|  | #include "iot_bitops.h"
 | |||
|  | #include "os_lock.h"
 | |||
|  | #include "iot_config.h"
 | |||
|  | #include "dtest_printf.h"
 | |||
|  | #include "cpu.h"
 | |||
|  | #include "ahb.h"
 | |||
|  | #include "iot_gptmr_api.h"
 | |||
|  | #include "iot_spinlock.h"
 | |||
|  | #include "gp_timer.h"
 | |||
|  | #if HW_PLATFORM > HW_PLATFORM_SIMU
 | |||
|  | #include "dbg_io.h"
 | |||
|  | #endif
 | |||
|  | #include "iot_io.h"
 | |||
|  | #include "gpio_hw.h"
 | |||
|  | #include "hw_reg_api.h"
 | |||
|  | #include "iot_gpio.h"
 | |||
|  | #include "gtmr_reg.h"
 | |||
|  | 
 | |||
|  | uint32_t gp_timer_reg_read(uint32_t reg); | |||
|  | void gp_timer_reg_write(uint32_t reg, uint32_t data); | |||
|  | 
 | |||
|  | #define GPTMR_TEST_SPINLOCK     5
 | |||
|  | 
 | |||
|  | uint32_t g_tmr_count = 0; | |||
|  | 
 | |||
|  | extern void _core_start(void); | |||
|  | uint32_t gp_timer_get_current_val(uint8_t); | |||
|  | 
 | |||
|  | uint8_t gptmr_isr(iot_addrword_t data) | |||
|  | { | |||
|  |     g_tmr_count++; | |||
|  | 
 | |||
|  |     return 0; | |||
|  | } | |||
|  | 
 | |||
|  | void gptmr_core2_loop(void) | |||
|  | { | |||
|  |     uint32_t cur_cpu = cpu_get_mhartid(), next_cnt = 0, loop, spinlock = GPTMR_TEST_SPINLOCK; | |||
|  | 
 | |||
|  |     iot_spinlock_lock(spinlock, cur_cpu); | |||
|  |     dprintf("CPU %d : Start!!!\n", cur_cpu); | |||
|  |     iot_spinlock_unlock(spinlock, cur_cpu); | |||
|  | 
 | |||
|  |     iot_gp_timer_set(0, 0xFFFFFFFF, 1); | |||
|  | 
 | |||
|  |     iot_gp_timer_start(0); | |||
|  | 
 | |||
|  |     for(;;) { | |||
|  |         if (next_cnt < gp_timer_get_current_val(0)) { | |||
|  |             iot_spinlock_lock(spinlock, cur_cpu); | |||
|  |             dprintf("I'm CPU %d : tmr 0 count %d\n", cur_cpu, next_cnt); | |||
|  |             iot_spinlock_unlock(spinlock, cur_cpu); | |||
|  |             next_cnt += 2000000; | |||
|  |         } | |||
|  | 
 | |||
|  |         loop = 0; | |||
|  | 
 | |||
|  |         while(loop++ < 100000) __asm volatile ("nop\n"); | |||
|  |     } | |||
|  | } | |||
|  | 
 | |||
|  | #define COUNTER_TIMER_ID    0
 | |||
|  | void gptmr_div_freq_test() | |||
|  | { | |||
|  |     uint32_t tmp; | |||
|  |     uint32_t timer0_val, timer1_val, timer2_val; | |||
|  |     dcase_start("gp_timer div freq test\n"); | |||
|  |     /* 时钟1M,分频系数1 */ | |||
|  |     tmp = gp_timer_reg_read(CFG_GTMR0_CTRL_CFG_ADDR); | |||
|  |     REG_FIELD_SET(TMR0_TICK_SEL, tmp, 1); //1m tick sel
 | |||
|  |     gp_timer_reg_write(CFG_GTMR0_CTRL_CFG_ADDR, tmp); | |||
|  |     /* 分频 1 */ | |||
|  |     gp_timer_reg_write(CFG_GTMR0_DIV_ADDR, 1); | |||
|  |     gp_timer_set(0, 1000000, 0); | |||
|  | 
 | |||
|  |     /* 时钟25M,分频系数1 */ | |||
|  |     tmp = gp_timer_reg_read(CFG_GTMR1_CTRL_CFG_ADDR); | |||
|  |     REG_FIELD_SET(TMR0_TICK_SEL, tmp, 0); //25m tick sel
 | |||
|  |     gp_timer_reg_write(CFG_GTMR1_CTRL_CFG_ADDR, tmp); | |||
|  |     /* 分频 1 */ | |||
|  |     gp_timer_reg_write(CFG_GTMR1_DIV_ADDR, 1); | |||
|  |     gp_timer_set(1, 100000000, 0); | |||
|  | 
 | |||
|  |     /* 时钟25M,分频系数5 */ | |||
|  |     tmp = gp_timer_reg_read(CFG_GTMR2_CTRL_CFG_ADDR); | |||
|  |     REG_FIELD_SET(TMR0_TICK_SEL, tmp, 0); //25m tick sel
 | |||
|  |     gp_timer_reg_write(CFG_GTMR2_CTRL_CFG_ADDR, tmp); | |||
|  |     /* 分频 5 */ | |||
|  |     gp_timer_reg_write(CFG_GTMR2_DIV_ADDR, 5); | |||
|  |     gp_timer_set(2, 100000000, 0); | |||
|  |     /* 启动 */ | |||
|  |     gp_timer_start(0); | |||
|  |     gp_timer_start(1); | |||
|  |     gp_timer_start(2); | |||
|  | 
 | |||
|  |     while(!(gp_timer_get_int_status(0) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_stop(0); | |||
|  |     gp_timer_stop(1); | |||
|  |     gp_timer_stop(2); | |||
|  |     /* timer0_val 1000000 */ | |||
|  |     timer0_val = gp_timer_get_current_val(0); | |||
|  |     /* timer1_val 25000000 左右 */ | |||
|  |     timer1_val = gp_timer_get_current_val(1); | |||
|  |     /* timer2_val 5000000 左右 */ | |||
|  |     timer2_val = gp_timer_get_current_val(2); | |||
|  |     dprintf("timer0 val:%u timer1 val:%u timer2 val:%u\n", | |||
|  |         timer0_val, timer1_val, timer2_val); | |||
|  |     gp_timer_clear_int_status(0); | |||
|  | 
 | |||
|  |     /* 时钟切回1m */ | |||
|  |     tmp = gp_timer_reg_read(CFG_GTMR1_CTRL_CFG_ADDR); | |||
|  |     REG_FIELD_SET(TMR0_TICK_SEL, tmp, 1); //1m tick sel
 | |||
|  |     gp_timer_reg_write(CFG_GTMR1_CTRL_CFG_ADDR, tmp); | |||
|  |     tmp = gp_timer_reg_read(CFG_GTMR2_CTRL_CFG_ADDR); | |||
|  |     REG_FIELD_SET(TMR0_TICK_SEL, tmp, 1); //1m tick sel
 | |||
|  |     gp_timer_reg_write(CFG_GTMR2_CTRL_CFG_ADDR, tmp); | |||
|  | } | |||
|  | 
 | |||
|  | void gptmr_repeat_test() | |||
|  | { | |||
|  |     uint32_t repeat_cnt = 0; | |||
|  |     dcase_start("gp_timer repeat test\n"); | |||
|  | 
 | |||
|  |     gp_timer_init(); | |||
|  |     gp_timer_set(0, 1000000, 1); | |||
|  |     gp_timer_set(1, 5000000, 0); | |||
|  |     gp_timer_start(0); | |||
|  |     gp_timer_start(1); | |||
|  |     while(repeat_cnt < 3) { | |||
|  |         if (gp_timer_get_int_status(0) & TMR0_INT_RAW_MASK) { | |||
|  |             gp_timer_clear_int_status(0); | |||
|  |             repeat_cnt++; | |||
|  |         } | |||
|  | 
 | |||
|  |         if (gp_timer_get_int_status(1) & TMR1_INT_RAW_MASK) { | |||
|  |             gp_timer_clear_int_status(1); | |||
|  |             break; | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     if (repeat_cnt != 3) { | |||
|  |         dcase_failed(); | |||
|  |     } else { | |||
|  |         dcase_success(); | |||
|  |     } | |||
|  |     gp_timer_stop(0); | |||
|  | } | |||
|  | 
 | |||
|  | void gptmr_start_pause_stop_test() | |||
|  | { | |||
|  |     /* 使用timer0作为计时,timer1用作测试    */ | |||
|  |     uint32_t timer1_val1, timer1_val2, tmp; | |||
|  | 
 | |||
|  |     dcase_start("gp_timer start pause stop test\n"); | |||
|  |     gp_timer_init(); | |||
|  |     /* 启动timer1 100s */ | |||
|  |     gp_timer_set(1, 100000000, 1); | |||
|  |     gp_timer_start(1); | |||
|  | 
 | |||
|  |     /* 获取当前timer1的计数值 */ | |||
|  |     timer1_val1 = gp_timer_get_current_val(1); | |||
|  |     dprintf("start timer1 start: val:%u\n", timer1_val1); | |||
|  |     /* 计时1s钟 */ | |||
|  |     gp_timer_set(COUNTER_TIMER_ID, 1000000, 1); | |||
|  |     gp_timer_start(COUNTER_TIMER_ID); | |||
|  |     while(!(gp_timer_get_int_status(COUNTER_TIMER_ID) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_clear_int_status(COUNTER_TIMER_ID); | |||
|  |     timer1_val2 = gp_timer_get_current_val(1); | |||
|  |     dprintf("start timer1 end: val:%u\n", timer1_val2); | |||
|  |     /* 数值没有变,则timer没有启动 */ | |||
|  |     if (timer1_val1 == timer1_val2) { | |||
|  |         dcase_failed(); | |||
|  |         return; | |||
|  |     } | |||
|  |     /* 停止timer1 */ | |||
|  |     gp_timer_stop(1); | |||
|  |     /* 获取当前timer1的计数值 */ | |||
|  |     timer1_val1 = gp_timer_get_current_val(1); | |||
|  |     dprintf("stop timer1 start: val:%u\n", timer1_val1); | |||
|  |     /* 计时1s */ | |||
|  |     while(!(gp_timer_get_int_status(COUNTER_TIMER_ID) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_clear_int_status(COUNTER_TIMER_ID); | |||
|  |     timer1_val2 = gp_timer_get_current_val(1); | |||
|  |     dprintf("stop timer1 end: val:%u\n", timer1_val2); | |||
|  |     /* 数值变化了,则timer没有停止 */ | |||
|  |     if (timer1_val1 != timer1_val2) { | |||
|  |         dcase_failed(); | |||
|  |         return; | |||
|  |     } | |||
|  | 
 | |||
|  |     /* 启动timer1 */ | |||
|  |     gp_timer_set(1, 100000000, 1); | |||
|  |     gp_timer_start(1); | |||
|  |     /* 获取当前timer1的计数值 */ | |||
|  |     timer1_val1 = gp_timer_get_current_val(1); | |||
|  |     dprintf("pause timer1 val:%u\n", timer1_val1); | |||
|  |     /* 计时1s钟 */ | |||
|  |     while(!(gp_timer_get_int_status(COUNTER_TIMER_ID) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_clear_int_status(COUNTER_TIMER_ID); | |||
|  |     timer1_val2 = gp_timer_get_current_val(1); | |||
|  |     dprintf("pause timer1 start: val:%u\n", timer1_val2); | |||
|  |     /* 数值没有变,则timer没有启动 */ | |||
|  |     if (timer1_val1 == timer1_val2) { | |||
|  |         dcase_failed(); | |||
|  |         return; | |||
|  |     } | |||
|  |     /* 暂停timer1 */ | |||
|  |     tmp = gp_timer_reg_read(CFG_GTMR1_CTRL_CFG_ADDR); | |||
|  |     REG_FIELD_SET(TMR1_PAUSE_CFG, tmp, 1); | |||
|  |     gp_timer_reg_write(CFG_GTMR1_CTRL_CFG_ADDR, tmp); | |||
|  |     /* 获取当前timer1的计数值 */ | |||
|  |     timer1_val1 = gp_timer_get_current_val(1); | |||
|  |     dprintf("pause timer1 val:%u\n", timer1_val1); | |||
|  |     /* 计时1s */ | |||
|  |     while(!(gp_timer_get_int_status(COUNTER_TIMER_ID) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_clear_int_status(COUNTER_TIMER_ID); | |||
|  |     timer1_val2 = gp_timer_get_current_val(1); | |||
|  |     dprintf("pause timer1 end: val:%u\n", timer1_val2); | |||
|  | 
 | |||
|  |     /* 数值变化了,则timer没有暂停 */ | |||
|  |     if (timer1_val1 != timer1_val2) { | |||
|  |         dcase_failed(); | |||
|  |         return; | |||
|  |     } | |||
|  |     /* 取消暂停 */ | |||
|  |     tmp = gp_timer_reg_read(CFG_GTMR1_CTRL_CFG_ADDR); | |||
|  |     REG_FIELD_SET(TMR1_PAUSE_CFG, tmp, 0); | |||
|  |     gp_timer_reg_write(CFG_GTMR1_CTRL_CFG_ADDR, tmp); | |||
|  | 
 | |||
|  |     gp_timer_stop(COUNTER_TIMER_ID); | |||
|  |     gp_timer_stop(1); | |||
|  |     dcase_success(); | |||
|  | } | |||
|  | 
 | |||
|  | void gptmr_interrupt_test() | |||
|  | { | |||
|  |     uint32_t cur_cpu = cpu_get_mhartid(); | |||
|  |     uint32_t timer_id1, timer_id2; | |||
|  |     dcase_start("gp_timer interrupt test\n"); | |||
|  |     iot_gp_timer_init(); | |||
|  | 
 | |||
|  |     timer_id1 = iot_gp_timer_create(cur_cpu, NULL, gptmr_isr, 0); | |||
|  |     iot_gp_timer_set(timer_id1, 1000000, 0); | |||
|  |     iot_gp_timer_start(timer_id1); | |||
|  | 
 | |||
|  |     timer_id2 = iot_gp_timer_create(cur_cpu, NULL, gptmr_isr, 0); | |||
|  |     iot_gp_timer_set(timer_id2, 2000000, 0); | |||
|  |     iot_gp_timer_start(timer_id2); | |||
|  | 
 | |||
|  |     while(gp_timer_get_current_val(timer_id2) < 1500000) { | |||
|  |         if (g_tmr_count > 0) { | |||
|  |             dcase_success(); | |||
|  |             iot_gp_timer_stop(timer_id1); | |||
|  |             iot_gp_timer_stop(timer_id2); | |||
|  |             return; | |||
|  |         } | |||
|  |     } | |||
|  |     dcase_failed(); | |||
|  | } | |||
|  | 
 | |||
|  | void gptmr_precision_test() | |||
|  | { | |||
|  |     uint32_t cpu_cycle1, cpu_cycle2; | |||
|  |     dcase_start("gp_timer precision test\n"); | |||
|  |     /* 计时1s钟 */ | |||
|  |     gp_timer_set(COUNTER_TIMER_ID, 1000000, 0); | |||
|  |     gp_timer_start(COUNTER_TIMER_ID); | |||
|  |     cpu_cycle1 = cpu_get_mcycle(); | |||
|  |     while(!(gp_timer_get_int_status(COUNTER_TIMER_ID) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_clear_int_status(COUNTER_TIMER_ID); | |||
|  |     cpu_cycle2 = cpu_get_mcycle(); | |||
|  |     dprintf("gp_timer delta: 1000000 cpu_cycle delta:%u\n", | |||
|  |         cpu_cycle2 - cpu_cycle1); | |||
|  | } | |||
|  | 
 | |||
|  | void gptmr_gpio_latch_test() | |||
|  | { | |||
|  | #define TEST_TIMER_ID 3
 | |||
|  | #define INPUT_GPIO 28
 | |||
|  | 
 | |||
|  |     uint32_t value1, value2; | |||
|  |     dcase_start("gp_timer gpio_latch test\n"); | |||
|  |     /* 开始计时 */ | |||
|  |     gp_timer_set(TEST_TIMER_ID, 0xffffffff, 0); | |||
|  |     gp_timer_set_gpio_latch(TEST_TIMER_ID, INPUT_GPIO); | |||
|  |     gp_timer_start(TEST_TIMER_ID); | |||
|  |     hw_gpio_api_table.gpio_init(); | |||
|  |     hw_gpio_api_table.set_gpio_mode(INPUT_GPIO, GPIO_OUTPUT); | |||
|  |     /* 输入管脚拉低,开始计数 */ | |||
|  |     hw_gpio_api_table.set_value(INPUT_GPIO, 0); | |||
|  | 
 | |||
|  |     gp_timer_set(COUNTER_TIMER_ID, 1000000, 0); | |||
|  |     gp_timer_start(COUNTER_TIMER_ID); | |||
|  |     while(!(gp_timer_get_int_status(COUNTER_TIMER_ID) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_clear_int_status(COUNTER_TIMER_ID); | |||
|  |     /* 输入管脚拉高,停止计数 */ | |||
|  |     hw_gpio_api_table.set_value(INPUT_GPIO, 1); | |||
|  |     value1 = gp_timer_get_current_val(TEST_TIMER_ID); | |||
|  |     dprintf("gp_timer value1: %d\n", value1); | |||
|  |     gp_timer_set(COUNTER_TIMER_ID, 1000000, 0); | |||
|  |     gp_timer_start(COUNTER_TIMER_ID); | |||
|  |     while(!(gp_timer_get_int_status(COUNTER_TIMER_ID) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_clear_int_status(COUNTER_TIMER_ID); | |||
|  |     value2 = gp_timer_get_current_val(TEST_TIMER_ID); | |||
|  |     dprintf("gp_timer value2:%u\n", value2); | |||
|  | 
 | |||
|  |     gp_timer_stop(COUNTER_TIMER_ID); | |||
|  |     gp_timer_stop(TEST_TIMER_ID); | |||
|  | 
 | |||
|  |     if (value1 == value2) { | |||
|  |         dcase_success(); | |||
|  |     } else { | |||
|  |         dcase_failed(); | |||
|  |     } | |||
|  | #undef TEST_TIMER_ID
 | |||
|  | #undef INPUT_GPIO
 | |||
|  | } | |||
|  | void gp_timer_reg_write(uint32_t reg, uint32_t data); | |||
|  | uint32_t gp_timer_reg_read(uint32_t reg); | |||
|  | 
 | |||
|  | void gptmr_64bit_timer(void) | |||
|  | { | |||
|  | #define DELAY_TIMER_ID  2
 | |||
|  | #define TIMER_64BIT_ID0 0
 | |||
|  | #define TIMER_64BIT_ID1 1
 | |||
|  |     uint32_t tmp; | |||
|  |     dcase_start("gp_timer 64bit timer test\n"); | |||
|  |     gp_timer_reg_write(CFG_TMR64_SEL_ADDR, 0x1); | |||
|  |     /* timer 0 low 32bit timer 1 high 32bit */ | |||
|  |     gp_timer_set(TIMER_64BIT_ID0, 1098, 0); | |||
|  |     gp_timer_set(TIMER_64BIT_ID1, 1, 0); | |||
|  |     /* 切换时钟为25m */ | |||
|  |     tmp = gp_timer_reg_read(CFG_GTMR0_CTRL_CFG_ADDR); | |||
|  |     REG_FIELD_SET(TMR0_TICK_SEL, tmp, 0); //25m tick sel
 | |||
|  |     gp_timer_reg_write(CFG_GTMR0_CTRL_CFG_ADDR, tmp); | |||
|  |     gp_timer_start(TIMER_64BIT_ID0); | |||
|  |     /* 打印间隔 1s */ | |||
|  |     gp_timer_set(DELAY_TIMER_ID, 1000000, 1); | |||
|  |     gp_timer_start(DELAY_TIMER_ID); | |||
|  |     while(1) { | |||
|  |         while(!(gp_timer_get_int_status(DELAY_TIMER_ID) & TMR2_INT_RAW_MASK)); | |||
|  |         gp_timer_clear_int_status(DELAY_TIMER_ID); | |||
|  |         dprintf("64bit timer value high: [%u] low:[%u]\n", | |||
|  |         gp_timer_get_current_val(TIMER_64BIT_ID1), gp_timer_get_current_val(TIMER_64BIT_ID0)); | |||
|  |         if (gp_timer_get_int_status(TIMER_64BIT_ID0) & TMR0_INT_STS_MASK) { | |||
|  |             dprintf("64bit timer interrupt status OK\n"); | |||
|  |             dcase_success(); | |||
|  |             gp_timer_clear_int_status(TIMER_64BIT_ID0); | |||
|  |             break; | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     gp_timer_stop(DELAY_TIMER_ID); | |||
|  |     /* 切换为32bit timer */ | |||
|  |     gp_timer_reg_write(CFG_TMR64_SEL_ADDR, 0x0); | |||
|  | } | |||
|  | 
 | |||
|  | void gptmr_core0_loop(void) | |||
|  | { | |||
|  |     uint32_t cur_cpu = cpu_get_mhartid(), next_cnt = 0, loop, spinlock = GPTMR_TEST_SPINLOCK; | |||
|  | 
 | |||
|  |     iot_spinlock_lock(spinlock, cur_cpu); | |||
|  |     dprintf("CPU %d : Start!!!\n", cur_cpu); | |||
|  |     iot_spinlock_unlock(spinlock, cur_cpu); | |||
|  |     dstart(); | |||
|  |     dversion(); | |||
|  |     gp_timer_init(); | |||
|  |     gptmr_div_freq_test(); | |||
|  |     gptmr_repeat_test(); | |||
|  |     gptmr_start_pause_stop_test(); | |||
|  |     gptmr_precision_test(); | |||
|  |     gptmr_gpio_latch_test(); | |||
|  |     gptmr_64bit_timer(); | |||
|  |     gptmr_interrupt_test(); | |||
|  |     dend(); | |||
|  |     iot_gp_timer_set(0, 0xFFFFFFFF, 1); | |||
|  | 
 | |||
|  |     iot_gp_timer_start(0); | |||
|  | 
 | |||
|  |     for(;;) { | |||
|  | 
 | |||
|  |         if (next_cnt < gp_timer_get_current_val(0)) { | |||
|  |             iot_spinlock_lock(spinlock, cur_cpu); | |||
|  |             dprintf("I'm CPU %d : tmr 0 count %d\n", cur_cpu, next_cnt); | |||
|  |             iot_spinlock_unlock(spinlock, cur_cpu); | |||
|  |             next_cnt += 1100000; | |||
|  |         } | |||
|  | 
 | |||
|  |         loop = 0; | |||
|  | 
 | |||
|  |         while(loop++ < 100000) __asm volatile ("nop\n"); | |||
|  |     } | |||
|  | } | |||
|  | 
 | |||
|  | void gptmr_core1_loop() | |||
|  | { | |||
|  |     uint32_t cur_cpu = cpu_get_mhartid(), id, loop, last_cnt = 0, spinlock = GPTMR_TEST_SPINLOCK; | |||
|  | 
 | |||
|  |     iot_gp_timer_init(); | |||
|  | 
 | |||
|  |     id = iot_gp_timer_create(cur_cpu, NULL, gptmr_isr, 0); | |||
|  | 
 | |||
|  |     iot_gp_timer_set(id, 1000000, 1); | |||
|  | 
 | |||
|  |     iot_gp_timer_start(id); | |||
|  | 
 | |||
|  |     iot_spinlock_lock(spinlock, cur_cpu); | |||
|  |     dprintf("Test tmr%d @ cpu%d\n", id, cur_cpu); | |||
|  |     iot_spinlock_unlock(spinlock, cur_cpu); | |||
|  | 
 | |||
|  |     for(;;) { | |||
|  | 
 | |||
|  |         if (last_cnt != g_tmr_count) { | |||
|  | 
 | |||
|  |             iot_spinlock_lock(spinlock, cur_cpu); | |||
|  |             dprintf("I'm CPU %d : tmr %d interrupts %d times.\n", cur_cpu, id, g_tmr_count); | |||
|  |             iot_spinlock_unlock(spinlock, cur_cpu); | |||
|  | 
 | |||
|  |             last_cnt = g_tmr_count; | |||
|  |         } | |||
|  | 
 | |||
|  |         loop = 0; | |||
|  | 
 | |||
|  |         while(loop++ < 100000) __asm volatile ("nop\n"); | |||
|  |     } | |||
|  | 
 | |||
|  |     return; | |||
|  | } | |||
|  | 
 | |||
|  | #include "clk.h"
 | |||
|  | int main(void) | |||
|  | { | |||
|  |     gp_timer_set(COUNTER_TIMER_ID, 1000000, 0); | |||
|  |     gp_timer_start(COUNTER_TIMER_ID); | |||
|  |     while(!(gp_timer_get_int_status(COUNTER_TIMER_ID) & TMR0_INT_RAW_MASK)); | |||
|  |     gp_timer_clear_int_status(COUNTER_TIMER_ID); | |||
|  | 
 | |||
|  |     uint32_t cur_cpu = cpu_get_mhartid(); | |||
|  | 
 | |||
|  |     if(cur_cpu == 0) { | |||
|  |         clk_system_clock_tree_config(CLK_FRQ_GP_IDX_FAST); | |||
|  |         dbg_uart_init(); | |||
|  | 
 | |||
|  | //        ahb_core2_set_start((uint32_t)_core_start);
 | |||
|  | //
 | |||
|  | //        ahb_core2_enable();
 | |||
|  | //
 | |||
|  | //        ahb_core2_reset();
 | |||
|  | 
 | |||
|  |         gptmr_core0_loop(); | |||
|  | 
 | |||
|  |     } else if (cur_cpu == 2) { | |||
|  | 
 | |||
|  |         ahb_core1_set_start((uint32_t)_core_start); | |||
|  | 
 | |||
|  |         ahb_core1_enable(); | |||
|  | 
 | |||
|  |         ahb_core1_reset(); | |||
|  | 
 | |||
|  |         gptmr_core2_loop(); | |||
|  |     } else { | |||
|  |         gptmr_core1_loop(); | |||
|  |     } | |||
|  | 
 | |||
|  | 
 | |||
|  |     return 0; | |||
|  | } |