您尚未登录。

楼主 # 2024-01-02 17:21:05

zm
会员
注册时间: 2023-09-28
已发帖子: 7
积分: 23

搞了一个T113S3裸机代码(copy xboot和awboot),遇到定时器中断一直触发不了。。。

手上有一块t113-s3 麻雀开发板,自己焊了norflash(怕nand flash出现坏块搞不定。。。),想试试能不能自己移植freertos在t113上跑,先打算实现裸机正常运行和中断正常运行。目前可以正常的打印,定时器也正常计数,就是无法触发中断,本人小白,花了一段时间,实在找不出问题,只能把源码贴出来了,希望有大佬帮忙看看。。
log:

dram start
dram init ok
welcome to T113s3
now run in security
[D] CLK: CPU PLL=PLL_CPU FREQ=1200MHz
[D] CLK: PLL_peri (2X)=1200MHz, (1X)=600MHz, (800M)=800MHz
[D] CLK: PLL_ddr=1584MHz
gic_base address is 0x3020000
gic irqs supported is 224
0)  current val = 0
1)  current val = 22779507
2)  current val = 21555507
3)  current val = 20331507
4)  current val = 19107507
5)  current val = 17883507
6)  current val = 16659507
7)  current val = 15435507
8)  current val = 14211506
9)  current val = 12987506
10)  current val = 11763507
11)  current val = 10539507
12)  current val = 9315507
13)  current val = 8091507
14)  current val = 6867506
15)  current val = 5643506
16)  current val = 4419507
17)  current val = 3195507
18)  current val = 1971507
19)  current val = 747506
20)  current val = 23523507
#include "debug.h"
#include "arch_timer/arch_timer.h"
#include "timer/timer.h"
#include "gic400/gic400.h"
#include "gic400/t113_irq.h"
#include "t113_clk/sunxi_clk.h"
#include "arm32.h"
#include "bit_ops.h"
static void timer0_irq_handler(void * data);
static void timer1_irq_handler(void * data);
int main(void)
{
    u32 cur_val = 0;
    u32 scr;
    message("welcome to T113s3\r\n");
    scr = arm32_read_scr_ns();
    if(GET_BIT(scr,0))//获取SCR.NS位,如果是0则是安全模式,如果是1则是非安全模式
    {
        message("now run in non_security\r\n");
    }
    else
    {
        message("now run in security\r\n");
    }

    sunxi_clk_dump();
    start_gic();
    register_irq(T113_IRQ_TIMER1,timer1_irq_handler,NULL,(30 << 3),3);
    start_ms_timer(TIMER1,1000);
    int i = 0;
    while(1)
    {
        cur_val = get_current_timer_value(TIMER1);
        message("%d)  current val = %d \r\n",i,cur_val);
        mdelay(50);
        i ++;
    }
    
    
}

static void timer0_irq_handler(void * data)
{
    //清中断
    clear_timern_irq(TIMER0);
    message("timer0 irq get \r\n");
}

static void timer1_irq_handler(void * data)
{
    //清中断
    clear_timern_irq(TIMER1);
    message("timer1 irq get \r\n");
}

GIC部分代码:

#include "gic400/gic400.h"
#include "gic400/t113_irq.h"
#include "io.h"
#include "smp.h"
#include "debug.h"
enum {
	DIST_CTRL 			= 0x1000,
	DIST_CTR 			= 0x1004,
	DIST_IIDR           = 0X1008,
	DIST_IGROUPRn       = 0x1080,
	DIST_ENABLE_SET 	= 0x1100,
	DIST_ENABLE_CLEAR 	= 0x1180,
	DIST_PENDING_SET 	= 0x1200,
	DIST_PENDING_CLEAR	= 0x1280,
	DIST_ACTIVE_BIT		= 0x1300,
	DIST_PRI			= 0x1400,
	DIST_TARGET			= 0x1800,
	DIST_CONFIG			= 0x1c00,
	DIST_SOFTINT		= 0x1f00,

	CPU_CTRL 			= 0x2000,
	CPU_PRIMASK 		= 0x2004,
	CPU_BINPOINT 		= 0x2008,
	CPU_INTACK 			= 0x200c,
	CPU_EOI 			= 0x2010,
	CPU_RUNNINGPRI 		= 0x2014,
	CPU_HIGHPRI 		= 0x2018,
}GIC_REG_NUM;

#define FGicPs_PRIORITY_OFFSET_CALC(InterruptID) \
	((u32)DIST_PRI + (((InterruptID)/4U) * 4U))
#define FGicPs_INT_CFG_OFFSET_CALC(InterruptID) \
	((u32)DIST_CONFIG + (((InterruptID)/16U) * 4U))

u32 read_gicd_pri(int int_id)
{
	return read32(T113_GIC_400_BASE + FGicPs_PRIORITY_OFFSET_CALC(int_id));
}

void write_gicd_pri(int int_id, u32 val)
{
	write32(T113_GIC_400_BASE + FGicPs_PRIORITY_OFFSET_CALC(int_id),val);
}

u32 read_gicd_cfg(int int_id)
{
	return read32(T113_GIC_400_BASE + FGicPs_INT_CFG_OFFSET_CALC(int_id));
}

void write_gicd_cfg(int int_id, u32 val)
{
	write32(T113_GIC_400_BASE + FGicPs_INT_CFG_OFFSET_CALC(int_id),val);
}

#if 0
static  inline uint32_t arm32_get_gic_base(void)
{
	uint32_t value;

	__asm__ __volatile__(
		"mrc p15, 4, %0, c15, c0, 0"
		: "=r" (value)
		:
		: "memory");

	return value;
}
#endif

void gic400_dist_init(void)
{
	u32_t gic_irqs;
	u32_t cpumask;

    u32_t gic_base = T113_GIC_400_BASE;
	int i;
	message("gic_base address is 0x%x \r\n",gic_base);
	write32(gic_base + DIST_CTRL, 0x0);

	/*
	 * Find out how many interrupts are supported.
	 * The GIC only supports up to 1020 interrupt sources.
	 */
	gic_irqs = read32(gic_base + DIST_CTR) & 0x1f;
	gic_irqs = (gic_irqs + 1) * 32;
	message("gic irqs supported is %d \r\n",gic_irqs);
	if(gic_irqs > 1020)
		gic_irqs = 1020;


	/*
	 * Set all global interrupts to this CPU only.
	 */
	cpumask = 1 << smp_processor_id();
	cpumask |= cpumask << 8;
	cpumask |= cpumask << 16;
	
	for(i = 32; i < gic_irqs; i += 4)
		write32(gic_base + DIST_TARGET + (i / 4 )* 4, cpumask);

	/*
	 * Set all global interrupts to be level triggered, active low.
	 */
	for(i = 32; i < gic_irqs; i += 16)
		write32(gic_base + DIST_CONFIG + (i /16) * 4 , 0);

	/*
	 * Set priority on all global interrupts.
	 */
	for(i = 32; i < gic_irqs; i += 4)
		write32(gic_base + DIST_PRI + (i / 4) * 4, 0xa0a0a0a0);

	/*
	 * Disable all interrupts, leave the SGI and PPI alone
	 * as these enables are banked registers.
	 */
	for(i = 32; i < gic_irqs; i += 32)
		write32(gic_base + DIST_ENABLE_CLEAR + (i / 32) * 4, 0xffffffff);

	//将所有中断设为group0
	for(i = 32 ; i < gic_irqs; i += 32)
		write32(gic_base + DIST_IGROUPRn + (i / 32) * 4, 0x0);


	write32(gic_base + DIST_CTRL, 0x1);
}

void gic400_cpu_init(void)
{
	int i;
    u32_t gic_base = T113_GIC_400_BASE;
	/*
	 * Deal with the banked SGI and PPI interrupts - enable all
	 * SGI interrupts, ensure all PPI interrupts are disabled.
	 */
	write32(gic_base + DIST_ENABLE_CLEAR, 0xffff0000);
	write32(gic_base + DIST_ENABLE_SET, 0x0000ffff);

	/*
	 * Set priority on SGI and PPI interrupts
	 */
	for(i = 0; i < 32; i += 4)
		write32(gic_base + DIST_PRI + ( i / 4 ) * 4, 0xa0a0a0a0);

	write32(gic_base + CPU_PRIMASK, 0xf0);
	write32(gic_base + CPU_CTRL, 0x1);
}

void irq_gic400_enable(int irq) //unmask对应中断
{
	write32(T113_GIC_400_BASE + DIST_ENABLE_SET + (irq / 32) * 4, 1 << (irq % 32));
}

void irq_gic400_disable(int irq)//mask对应中断
{
	write32(T113_GIC_400_BASE + DIST_ENABLE_CLEAR + (irq / 32) * 4, 1 << (irq % 32));
}

void irq_gic400_settype(void)
{

}

void irq_gic400_dispatch(void)//处理中断后清除中断标志
{
	int irq = read32(T113_GIC_400_BASE + CPU_INTACK) & 0x3ff;
    irq_gic400_disable(irq);

    do_handler(irq);

    write32(T113_GIC_400_BASE + CPU_EOI, irq);//清除中断
	irq_gic400_enable(irq);
}


void gic_interrupt_handle_exception(void* regs)
{
    irq_gic400_dispatch();
}


void start_gic(void)
{
    gic400_dist_init();
    gic400_cpu_init();
    
}

register_irq:

bool_t register_irq(int irq,void (*func)(void *), void * data, u8 Priority, u8 trigger)
{
    u32 val;
    u8 LocalPriority;
    if(!func)
		return FALSE;
    if(irq_hanlder_arry[irq].func != null_interrupt_function)
        return FALSE;
    irq_hanlder_arry[irq].func = func;
    irq_hanlder_arry[irq].data = data;

    // val = read_gicd_pri(irq);
    // LocalPriority = LocalPriority & (u8)(0x000000F8U);
    // val &= ~(0x000000FFU << ((irq%4U)*8U));
	// val |= (u32)LocalPriority << ((irq%4U)*8U);
    // write_gicd_pri(irq,val);

    // val = read_gicd_cfg(irq);
    // val &= ~(0x00000003U << ((irq%16U)*2U));
	// val |= (u32)trigger << ((irq%16U)*2U);

  //  write_gicd_cfg(irq,val);

    irq_gic400_enable(irq);
    arm32_interrupt_enable();
    return TRUE;
}

定时器部分

#include "timer/timer.h"

enum {
	TMR_IRQ_EN_REG 		       =0x0000	,
	TMR_IRQ_STA_REG 		   =0x0004  , 
	TMR0_CTRL_REG 	           =0x0010  ,
	TMR0_INTV_VALUE_REG 	   =0x0014  ,
	TMR0_CUR_VALUE_REG 	       =0x0018,
	TMR1_CTRL_REG              =0x0020  ,
    TMR1_INTV_VALUE_REG        =0x0024,
    TMR1_CUR_VALUE_REG         =0x0028,

}TIMER_REG_OFFSET;

#define Timer_Periodic_mode 0
#define Timer_Single_mode   1

//a &= ~(数值<<每组位数*组编号) :将连续几位清零的方法
//数值表示一组中每个bit都是1的情况下的值,比如组位数是2,则数值就是11b所代表的值,即3
//组编号是给寄存器多少个bit为1组进行分组,组号从0开始




void timern_init(int timer_id,  int timing_mode) //时钟频率为24000000/2
{
    u32 addr,val;
    if(timer_id == 0)
        addr = TIMER_BASE + TMR0_CTRL_REG;
    else
        addr = TIMER_BASE + TMR1_CTRL_REG;

    if(timing_mode == Timer_Periodic_mode)
        val = (u32)0x14;
    else
        val = (u32)0x94;

    write32(addr,val);

}

void set_timern_interval_value(int timer_id, u32 value)
{
    u32 addr,val;
    val = value;
    if(timer_id == 0)
        addr = TIMER_BASE + TMR0_INTV_VALUE_REG;
    else
        addr = TIMER_BASE + TMR1_INTV_VALUE_REG;

    write32(addr,val);//设置间隔值
}

void load_timern_interval_value(int timer_id)
{
    u32 addr,val;
    if(timer_id == 0)
        addr = TIMER_BASE + TMR0_CTRL_REG;
    else
        addr = TIMER_BASE + TMR1_CTRL_REG;
    write32(addr, read32(addr)|(1<<1)); //Set the Reload bit
    
}

void start_timer(int timer_id)
{
    u32 addr,val;
    if(timer_id == 0)
        addr = TIMER_BASE + TMR0_CTRL_REG;
    else
        addr = TIMER_BASE + TMR1_CTRL_REG;
    val	 = read32(addr);    
    val |= (0x1 << 0);
    write32(addr,val);

}

void start_ms_timer(int timer_id,u32 ms)
{
    u32 value = (24000 * ms);
    u32 addr;
    enable_timern_irq(timer_id);
    set_timern_interval_value(timer_id,value);
    timern_init(timer_id, Timer_Periodic_mode);
    load_timern_interval_value(timer_id);
    if(timer_id == 0)
        addr = TIMER_BASE + TMR0_CTRL_REG;
    else
        addr = TIMER_BASE + TMR1_CTRL_REG;
    while((read32(addr)>>1)&1);
    start_timer(timer_id);
}

void enable_timern_irq(int timer_id)
{
    u32 addr,val;
    addr = TIMER_BASE + TMR_IRQ_EN_REG;
    if(timer_id == 0)
    {
         val = read32(addr);  
         val |= (1 << 0);

    }
    else
    {
         val = read32(addr);  
         val |= (1 << 1);
    }

    write32(addr,val);

    addr = TIMER_BASE + TMR_IRQ_STA_REG;
    if(timer_id == 0)
    {
        val = read32(addr);
         
        val |= (1 << 0);
            

    }
    else
    {
        val = read32(addr); 
        
        val |= (1 << 1);
         
    }
    write32(addr,val);
}

void clear_timern_irq(int timer_id)
{
    u32 addr,val;
    addr = TIMER_BASE + TMR_IRQ_STA_REG;
    
    if(timer_id == 0)
    {
         val = read32(addr);
         if( (val & 0x01))
         {
            val |= (1 << 0);
            
         }  
            

    }
    else
    {
         val = read32(addr); 
         if((val & 0x2)) 
         {
            val |= (1 << 1);
         }
         
    }
    write32(addr,val);
}


u32 get_current_timer_value(int timer_id)
{
    u32 addr,val;
     if(timer_id == 0)
        addr = TIMER_BASE + TMR0_CUR_VALUE_REG;
    else
        addr = TIMER_BASE + TMR1_CUR_VALUE_REG;

    val = read32(addr);
    
    return val;
}

完整代码工程似乎传不上了,有兴趣的可以私聊

最近编辑记录 zm (2024-01-02 17:34:49)

离线

#1 2024-01-03 15:00:57

musich
会员
注册时间: 2018-04-17
已发帖子: 214
积分: 246

Re: 搞了一个T113S3裸机代码(copy xboot和awboot),遇到定时器中断一直触发不了。。。

瞎猜一个, 其它中断有正常的没? 或任意开一个其它中断试试. 

若能中断就是timer部分配置问题, 反之就是系统中断问题.

大概率是系统中断没弄好.

离线

#2 2024-01-09 21:59:43

eagletskt
会员
注册时间: 2020-04-13
已发帖子: 8
积分: 8

Re: 搞了一个T113S3裸机代码(copy xboot和awboot),遇到定时器中断一直触发不了。。。

我也正在T113S3上搞rtos,一堆的坑呐,想跟楼主交流

离线

楼主 #3 2024-01-10 10:45:01

zm
会员
注册时间: 2023-09-28
已发帖子: 7
积分: 23

Re: 搞了一个T113S3裸机代码(copy xboot和awboot),遇到定时器中断一直触发不了。。。

总算搞定中断了,发现还是前面gic初始化出问题了,哎,心累  sad

dram start
dram init ok
welcome to T113s3
[D] CLK: CPU PLL=PLL_CPU FREQ=1200MHz
[D] CLK: PLL_peri (2X)=1200MHz, (1X)=600MHz, (800M)=800MHz
[D] CLK: PLL_ddr=1584MHz
now run in security
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get
sys tick handler get

下面开始移植freertos,开搞!!

离线

楼主 #5 2024-01-12 14:23:21

zm
会员
注册时间: 2023-09-28
已发帖子: 7
积分: 23

Re: 搞了一个T113S3裸机代码(copy xboot和awboot),遇到定时器中断一直触发不了。。。

freertos 初步移植成功,用的freertos版本是10.0.0,目前只验证了多任务运行,运行正常!

[I] AWBoot r51 starting...
[D] DRAM BOOT DRIVE INFO: V0.24
[D] DRAM CLK = 792 MHz
[D] DRAM Type = 3 (2:DDR2,3:DDR3)
[D] DRAMC read ODT off
[D] ZQ value = 0x12e
[D] DDR efuse: 0xa
[D] chip id efuse: 0x6000
[D] single rank and full DQ
[D] DDR efuse: 0xa
[D] chip id efuse: 0x6000
[D] rank 0 row = 13
[D] para->dram_para1 = 0x10d2
[D] rank 0 bank = 8
[D] para->dram_para1 = 0x10d2
[D] rank 0 page size = 2 KB
[D] para->dram_para1 = 0x10d2
[D] DRAM ODT value: 0x42
[D] DDR efuse: 0xa
[D] chip id efuse: 0x6000
[D] DRAM: size = 128MB
[D] DRAM: simple test OK
[D] DMA: init
[T] DMA: test 0x44000000 ====> 0x44800000, len 512KB
[T] DMA: provide channel 0
[D] DMA: test OK in 59ms
[T] SPI: parent_clk=600MHz, div=3, n=1, m=3
[T] SPI: CDR2 - n = 0
[T] SPI: clock div=0
[D] SPI: set clock asked=100MHz actual=100MHz mclk=200MHz
[T] DMA: provide channel 0
[T] SPI: tsfr mode=0 tx=1 rx=0
[T] SPI: ISR=0x1032
[T] SPI: tsfr mode=0 tx=1 rx=1
[T] SPI: ISR=0x1033
[T] SPI: tsfr mode=0 tx=1 rx=4
[T] SPI: ISR=0x1033
[I] SPI-NOR: MFR:0xEF DEV:0x4019
[T] SPI: tsfr mode=1 tx=5 rx=2097152
[T] SPI: ISR=0x1037
[I] SPI NOR: READ USER BIN TIME:89785uS
[I] ------BootLoader Jump Successed-----------
[D] welcome to T113s3
[D] CLK: CPU PLL=PLL_CPU FREQ=1200MHz
[D] CLK: PLL_peri (2X)=1200MHz, (1X)=600MHz, (800M)=800MHz
[D] CLK: PLL_ddr=1584MHz
[D] timer0 irq is enable
[D] i am task0
[D] i am task2
[D] i am task1
[D] i am task0
[D] i am task2
[D] i am task1
[D] i am task0
[D] i am task2
[D] i am task1
[D] i am task0
[D] i am task2
[D] i am task1
[D] i am task0
[D] i am task2
[D] i am task1
[D] i am task0
[D] i am task2
[D] i am task1
[D] i am task0
[D] i am task2
[D] i am task1

后续打算研究一下t113s3的在线调试,想用openocd估计又是一个大坑~

离线

#6 2024-01-26 10:22:34

tea74110
会员
注册时间: 2021-04-25
已发帖子: 8
积分: 3

Re: 搞了一个T113S3裸机代码(copy xboot和awboot),遇到定时器中断一直触发不了。。。

@zm
大佬你好,请问GIC初始化出问题了,具体是哪个问题呀。

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn