您尚未登录。

楼主 #1 2018-08-17 17:44:41

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

2018-04-01上架版本:
核心板原理图: Lichee_nano.pdf
底板原理图:    lpi-nano-dock.pdf
网盘资料(有可能会失效): https://pan.baidu.com/s/1smzuGS9
购买地址: 9.9元起 荔枝派Nano 跨界核心板 开发板 多系统 linux


--------------------------------------------------
F1C100s资料集合:
参考链接0: 买个全志arm9 F1C100s 方案的唱戏机回来拆一拆
参考链接1: F1C100s 手册
参考链接2: 看戏机(唱戏机)F1C100原理图
参考链接3: 侨德实业有限公司VS (全志C100电脑升级)流程示意图
参考链接4: 先科唱戏机(看戏机)F1C100s方案运行XBOOT大神的XBOOT系统步骤
参考链接5: F1C100s入坑记录
参考链接6: 编译、安装Windows版本sunxi-fel步骤
参考链接7: 感谢荔枝派群主泽畔友情赠送的nano f1c100s开发板、液晶屏、电容触摸屏.












参考链接8: 荔枝派nano f1c100s开发板连接JLink调试器分享


QQ20180817174424.png

代码下载: n329xx_project_run_in_sram.7z

非常简单, 就是把协处理器的寄存器读到 R0, 没别的功能.

MDK工程,读芯片Id, 代码不到10行,没有中断向量.

: 这个代码只能在 N3290x 上面跑, 因为N3290x 的SRAM地址在 0xFF00 0000,
全志f1c100s的sram地址在 0x0 位置。





2019-04-13 更新
---------------------------------------------
支持ARM7/9旧器件的 MDK 版本:
http://www2.keil.com/mdk5/legacy/
https://armkeil.blob.core.windows.net/legacy/MDK79525.EXE
https://armkeil.blob.core.windows.net/legacy/MDK79524.EXE





离线

楼主 #2 2018-08-18 14:46:46

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180818144008.png

代码下载: f1c100s_project_run_in_sram_2.7z

不容易啊,

第一次玩汇编,

现在终于可以跑C代码了,

(中间省略1万字 ... ...)

参考自新唐 N329xx 工程.





离线

楼主 #3 2018-08-18 16:44:20

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180818164005.png

#include <stdio.h>
#include "types.h"
#include "io.h"
#include "reg-ccu.h"

typedef unsigned int u32_t; 

#define     __O     volatile     
#define     __IO    volatile 

#define CPU_PORT_BASE 0x01C20800

#define GPIOG_BASE (CPU_PORT_BASE + 0xD8)
#define GPIOG_INTERRUPT_BASE (GPIO_CPU_INTERRUPT_BASE + 0x20)

typedef struct{
   __IO u32_t CFG[4];
   __IO u32_t DAT;
   __IO u32_t DRV[2];
   __IO u32_t PUL[2];
}GPIO_Typedef;

#define GPIOG ((GPIO_Typedef *)GPIOG_BASE)



static void wait_pll_stable(u32_t base)
{
	u32_t rval = 0;
	u32_t time = 0xfff;

	do {
		rval = read32(base);
		time--;
	} while(time && !(rval & (1 << 28)));
}

static void clock_set_pll_cpu(u32_t clk)
{
	u32_t n, k, m, p;
	u32_t rval = 0;
	u32_t div = 0;

	if(clk > 720000000)
		clk = 720000000;

	if((clk % 24000000) == 0)
	{
		div = clk / 24000000;
		n = div - 1;
		k = 0;
		m = 0;
		p = 0;
	}
	else if((clk % 12000000) == 0)
	{
		m = 1;
		div = clk / 12000000;
		if((div % 3) == 0)
			k = 2;
		else if((div % 4) == 0)
			k = 3;
		else
			k = 1;
		n = (div / (k + 1)) - 1;
		p = 0;
	}
	else
	{
		div = clk / 24000000;
		n = div - 1;
		k = 0;
		m = 0;
		p = 0;
	}

	rval = read32(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL);
	rval &= ~((0x3 << 16) | (0x1f << 8) | (0x3 << 4) | (0x3 << 0));
	rval |= (1U << 31) | (p << 16) | (n << 8) | (k << 4) | m;
	write32(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL, rval);
	wait_pll_stable(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL);
}

void sys_clock_init(void)
{
	write32(F1C100S_CCU_BASE + CCU_PLL_STABLE_TIME0, 0x1ff);
	write32(F1C100S_CCU_BASE + CCU_PLL_STABLE_TIME1, 0x1ff);
	write32(F1C100S_CCU_BASE + CCU_CPU_CFG, 0x00020000);
	write32(F1C100S_CCU_BASE + CCU_AHB_APB_CFG, 0x00012110);

	clock_set_pll_cpu(408000000);
}

void sys_uart_init(void)
{
	u32_t addr;
	u32_t val;

	/* Config GPIOF4 and GPIOF2 to txd0 and rxd0 */
	addr = 0x01c208b4 + 0x00;
	val = read32(addr);
	val &= ~(0xf << ((4 & 0x7) << 2));
	val |= ((0x3 & 0x7) << ((4 & 0x7) << 2));
	write32(addr, val);

	val = read32(addr);
	val &= ~(0xf << ((2 & 0x7) << 2));
	val |= ((0x3 & 0x7) << ((2 & 0x7) << 2));
	write32(addr, val);

	/* Open the clock gate for uart0 */
	addr = 0x01c20068;
	val = read32(addr);
	val |= 1 << 20;
	write32(addr, val);

	/* Deassert uart0 reset */
	addr = 0x01c202d0;
	val = read32(addr);
	val |= 1 << 20;
	write32(addr, val);

	/* Config uart0 to 115200-8-1-0 */
	addr = 0x01c25000;
	write32(addr + 0x04, 0x0);
	write32(addr + 0x08, 0xf7);
	write32(addr + 0x10, 0x0);
	val = read32(addr + 0x0c);
	val |= (1 << 7);
	write32(addr + 0x0c, val);
	write32(addr + 0x00, 0x37 & 0xff);
	write32(addr + 0x04, (0x37 >> 8) & 0xff);
	val = read32(addr + 0x0c);
	val &= ~(1 << 7);
	write32(addr + 0x0c, val);
	val = read32(addr + 0x0c);
	val &= ~0x1f;
	val |= (0x3 << 0) | (0 << 2) | (0x0 << 3);
	write32(addr + 0x0c, val);
}

void sys_uart_putc(char c)
{
	u32_t addr = 0x01c25000;

	while((read32(addr + 0x7c) & (0x1 << 1)) == 0);
	write32(addr + 0x00, c);
}



int main(void)
{
	
  sys_clock_init();
  sys_uart_init();
    
  while(1)
  {
    sys_uart_putc('A');
  }
  
  u32_t cnt = 0;
  
   GPIOG->CFG[0] = (1 << 0) << 8;

  for(;;)
  {
    if(cnt==0)
      GPIOG->DAT &= ~(1U << 2);
    if(cnt==100000)
      GPIOG->DAT = 1U << 2;
    if(++cnt>200000)cnt = 0;
  }




	
	int i = 0;
	while(1)
	{
		i++;
	}
	
	return 0;
}

licheepi nano 核心板原理图: Lichee_nano.pdf

仍然是在 SRAM 里面跑,驱动串口 UART0(PF2, PF4)

源码下载: f1c100s_project_run_in_sram_3.7z

从原来的IAR项目移过来的: https://whycan.cn/t_1003.html

参考: https://github.com/xboot/xboot/tree/master/src/arch/arm32/mach-f1c100s





离线

楼主 #4 2018-08-19 16:48:21

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180819163830.png

#include <stdio.h>
#include <string.h>
#include "types.h"
#include "io.h"
#include "reg-ccu.h"

typedef unsigned int u32_t; 

#define     __O     volatile     
#define     __IO    volatile 

#define CPU_PORT_BASE 0x01C20800

#define GPIOG_BASE (CPU_PORT_BASE + 0xD8)
#define GPIOG_INTERRUPT_BASE (GPIO_CPU_INTERRUPT_BASE + 0x20)

#define vaStart(list, param) list = (char*)((s32_t)&param + sizeof(param))
#define vaArg(list, type) ((type *)(list += sizeof(type)))[-1]
	
typedef struct{
   __IO u32_t CFG[4];
   __IO u32_t DAT;
   __IO u32_t DRV[2];
   __IO u32_t PUL[2];
}GPIO_Typedef;

#define GPIOG ((GPIO_Typedef *)GPIOG_BASE)



static void wait_pll_stable(u32_t base)
{
	u32_t rval = 0;
	u32_t time = 0xfff;

	do {
		rval = read32(base);
		time--;
	} while(time && !(rval & (1 << 28)));
}

static void clock_set_pll_cpu(u32_t clk)
{
	u32_t n, k, m, p;
	u32_t rval = 0;
	u32_t div = 0;

	if(clk > 720000000)
		clk = 720000000;

	if((clk % 24000000) == 0)
	{
		div = clk / 24000000;
		n = div - 1;
		k = 0;
		m = 0;
		p = 0;
	}
	else if((clk % 12000000) == 0)
	{
		m = 1;
		div = clk / 12000000;
		if((div % 3) == 0)
			k = 2;
		else if((div % 4) == 0)
			k = 3;
		else
			k = 1;
		n = (div / (k + 1)) - 1;
		p = 0;
	}
	else
	{
		div = clk / 24000000;
		n = div - 1;
		k = 0;
		m = 0;
		p = 0;
	}

	rval = read32(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL);
	rval &= ~((0x3 << 16) | (0x1f << 8) | (0x3 << 4) | (0x3 << 0));
	rval |= (1U << 31) | (p << 16) | (n << 8) | (k << 4) | m;
	write32(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL, rval);
	wait_pll_stable(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL);
}

void sys_clock_init(void)
{
	write32(F1C100S_CCU_BASE + CCU_PLL_STABLE_TIME0, 0x1ff);
	write32(F1C100S_CCU_BASE + CCU_PLL_STABLE_TIME1, 0x1ff);
	write32(F1C100S_CCU_BASE + CCU_CPU_CFG, 0x00020000);
	write32(F1C100S_CCU_BASE + CCU_AHB_APB_CFG, 0x00012110);

	clock_set_pll_cpu(408000000);
}

void sys_uart_init(void)
{
	u32_t addr;
	u32_t val;

	/* Config GPIOF4 and GPIOF2 to txd0 and rxd0 */
	addr = 0x01c208b4 + 0x00;
	val = read32(addr);
	val &= ~(0xf << ((4 & 0x7) << 2));
	val |= ((0x3 & 0x7) << ((4 & 0x7) << 2));
	write32(addr, val);

	val = read32(addr);
	val &= ~(0xf << ((2 & 0x7) << 2));
	val |= ((0x3 & 0x7) << ((2 & 0x7) << 2));
	write32(addr, val);

	/* Open the clock gate for uart0 */
	addr = 0x01c20068;
	val = read32(addr);
	val |= 1 << 20;
	write32(addr, val);

	/* Deassert uart0 reset */
	addr = 0x01c202d0;
	val = read32(addr);
	val |= 1 << 20;
	write32(addr, val);

	/* Config uart0 to 115200-8-1-0 */
	addr = 0x01c25000;
	write32(addr + 0x04, 0x0);
	write32(addr + 0x08, 0xf7);
	write32(addr + 0x10, 0x0);
	val = read32(addr + 0x0c);
	val |= (1 << 7);
	write32(addr + 0x0c, val);
	write32(addr + 0x00, 0x37 & 0xff);
	write32(addr + 0x04, (0x37 >> 8) & 0xff);
	val = read32(addr + 0x0c);
	val &= ~(1 << 7);
	write32(addr + 0x0c, val);
	val = read32(addr + 0x0c);
	val &= ~0x1f;
	val |= (0x3 << 0) | (0 << 2) | (0x0 << 3);
	write32(addr + 0x0c, val);
}

void sys_uart_putc(char c)
{
	u32_t addr = 0x01c25000;

	while((read32(addr + 0x7c) & (0x1 << 1)) == 0);
	write32(addr + 0x00, c);
}


void sysPutString(char *string)
{
	while (*string != '\0')
	{
		sys_uart_putc(*string);
		string++;
	}
}

void sysPutStringReverse(char *s, u32_t index)
{
	while ((index--) > 0)
	sys_uart_putc(s[index]);
}

static void sysPutRepChar(char c, u32_t count)
{
	while (count--)
	sys_uart_putc(c);
}

static void sysPutNumber(s32_t value, s32_t radix, s32_t width, s8_t fill)
{
	s8_t    buffer[40];
	s32_t     bi = 0;
	u32_t  uvalue;
	u16_t  digit;
	u16_t  left = 0;
	u16_t  negative = 0;

	if (fill == 0)
	    	fill = ' ';

	if (width < 0)
	{
		width = -width;
		left = 0;
	}

	if (width < 0 || width > 80)
	    	width = 0;

	if (radix < 0)
	{
		radix = -radix;
		if (value < 0)
		{
			negative = 0;
			value = -value;
	    	}
	}

	uvalue = value;

	do
	{
		if (radix != 16)
		{
			digit = uvalue % radix;
			uvalue = uvalue / radix;
		}
		else
		{
			digit = uvalue & 0xf;
			uvalue = uvalue >> 4;
		}
		buffer[bi] = digit + ((digit <= 9) ? '0' : ('A' - 10));
		bi++;

		if (uvalue != 0)
		{
			if ((radix == 10)
			    && ((bi == 3) || (bi == 7) || (bi == 11) | (bi == 15)))
			{
				buffer[bi++] = ',';
			}
		}
	}
	while (uvalue != 0);

	if (negative)
	{
		buffer[bi] = '-';
		bi += 1;
	}

	if (width <= bi)
		sysPutStringReverse(buffer, bi);
	else
	{
		width -= bi;
		if (!left)
			sysPutRepChar(fill, width);
		sysPutStringReverse(buffer, bi);
		if (left)
		    	sysPutRepChar(fill, width);
	}
}

static u8_t *FormatItem(u8_t *f, s32_t a)
{
	u8_t   c;
	s32_t    fieldwidth = 0;
	s32_t    leftjust = 0;
	s32_t    radix = 0;
	u8_t   fill = ' ';

	if (*f == '0')
		fill = '0';

	while ((c = *f++) != 0)
	{
		if (c >= '0' && c <= '9')
		{
			fieldwidth = (fieldwidth * 10) + (c - '0');
		}
		else
			switch (c)
			{
				case '\000':
					return (--f);
				case '%':
				    	sys_uart_putc('%');
				    	return (f);
				case '-':
				    	leftjust = 1;
				    	break;
				case 'c':
				{
				        if (leftjust)
				        	sys_uart_putc(a & 0x7f);

				        if (fieldwidth > 0)
				            	sysPutRepChar(fill, fieldwidth - 1);

				        if (!leftjust)
				            	sys_uart_putc(a & 0x7f);
				        return (f);
				}
				case 's':
				{
				        if (leftjust)
				        	sysPutString((char*)a);

				        if (fieldwidth > strlen((s8_t*)a))
				            	sysPutRepChar(fill, fieldwidth - strlen((s8_t*)a));

				        if (!leftjust)
				           	sysPutString((s8_t*)a);
				        return (f);
				}
				case 'd':
				case 'i':
				   	 radix = -10;
				break;
				case 'u':
				    	radix = 10;
				break;
				case 'x':
				    	radix = 16;
				break;
				case 'X':
				    	radix = 16;
				break;
				case 'o':
				    	radix = 8;
				break;
				default:
				    	radix = 3;
				break;      /* unknown switch! */
			}
		if (radix)
		    break;
	}

	if (leftjust)
	    	fieldwidth = -fieldwidth;

	sysPutNumber(a, radix, fieldwidth, fill);

	return (f);
}


void sysprintf(s8_t* pcStr,...)
{
	u8_t  *argP;
    
	vaStart(argP, pcStr);       /* point at the end of the format string */
	while (*pcStr)
	{                       /* this works because args are all ints */
	    	if (*pcStr == '%')
	        	pcStr = FormatItem(pcStr + 1, vaArg(argP, u32_t));
	    	else
	        	sys_uart_putc(*pcStr++);
	}
}

int main(void)
{
	
  sys_clock_init();
  sys_uart_init();
    
  while(1)
  {
		sysprintf("hello %s: %d 0x%x \n", "world", 10, 20);
    //sys_uart_putc('A');
  }
  
  u32_t cnt = 0;
  
   GPIOG->CFG[0] = (1 << 0) << 8;

  for(;;)
  {
    if(cnt==0)
      GPIOG->DAT &= ~(1U << 2);
    if(cnt==100000)
      GPIOG->DAT = 1U << 2;
    if(++cnt>200000)cnt = 0;
  }




	
	int i = 0;
	while(1)
	{
		i++;
	}
	
	return 0;
}

实现了格式化输出的demo:
f1c100s_project_run_in_sram_4.7z





离线

楼主 #5 2018-08-20 11:58:01

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180820115543.png

  sys_clock_init();
  sys_uart_init();
	
	write32(TMR0_INTV_VALUE_REG, 0x2EE0);   //Set interval value 
	
	write32(TMR0_CTRL_REG, 0x14);   //Select Single mode,24MHz clock source,2 pre-scale 
	
	write32(TMR0_CTRL_REG, read32(TMR0_CTRL_REG)|(1<<1)); //Set Reload bit 

	while((read32(TMR0_CTRL_REG)>>1)&1);  //Waiting Reload bit turns to 0 
	
	write32(TMR0_CTRL_REG, read32(TMR0_CTRL_REG)|(1<<0));  //Enable Timer0 
	
  while(1)
  {
		//sysprintf("hello %s: %d 0x%x \n", "world", 10, 20);
    //sys_uart_putc('A');
		u32_t a = read32(TMR0_CUR_VALUE_REG);
		sysprintf("%d\n", a);
  }
  

实现timer0 定时器累加简单demo: f1c100s_project_run_in_sram_5.7z





离线

楼主 #6 2018-08-20 16:54:43

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180820164457.png

__irq void sysIrqHandler()
{
	static int i = 0;
	i++;
}

#define INTC_EN_REG0			(0x01C20400 + 0x20)
#define INTC_MASK_REG0		(0x01C20400 + 0x30)

int main(void)
{
	//void* _mOldIrqVect = *(void volatile *)0x38;
	*(void* volatile *)0x38 = (void* volatile)sysIrqHandler;
	
  sys_clock_init();
  sys_uart_init();
	
	write32(TMR_IRQ_EN_REG, 1);
	
	write32(INTC_EN_REG0, (read32(INTC_EN_REG0)) | 1 << 13);
	
	write32(TMR_IRQ_EN_REG, (read32(TMR_IRQ_EN_REG)) | 1 << 13);
	
	write32(TMR0_INTV_VALUE_REG, 0x2EE0);   //Set interval value 
	
	write32(TMR0_CTRL_REG, 0x10);   //Select Single mode,24MHz clock source,2 pre-scale 
	
	write32(TMR0_CTRL_REG, read32(TMR0_CTRL_REG)|(1<<1)); //Set Reload bit 

	while((read32(TMR0_CTRL_REG)>>1)&1);  //Waiting Reload bit turns to 0 
	
	write32(TMR0_CTRL_REG, read32(TMR0_CTRL_REG)|(1<<0));  //Enable Timer0 
	
	
	u32_t temp;	
	__asm
	{
		 MRS    temp, CPSR
		 AND    temp, temp, 0x7F
		 MSR    CPSR_c, temp
	}
			
	u32_t old = 0;	
  while(1)
  {
		//sysprintf("hello %s: %d 0x%x \n", "world", 10, 20);
    //sys_uart_putc('A');
		volatile u32_t a = read32(TMR0_CUR_VALUE_REG);
		if(old == a)
		{			
		}
		else
		{
			old = a;
			if(a % 256 == 0)
			{
				sysprintf("%d\n", a);
			}
		}
  }
  
  u32_t cnt = 0;
  
   GPIOG->CFG[0] = (1 << 0) << 8;

  for(;;)
  {
    if(cnt==0)
      GPIOG->DAT &= ~(1U << 2);
    if(cnt==100000)
      GPIOG->DAT = 1U << 2;
    if(++cnt>200000)cnt = 0;
  }




	
	int i = 0;
	while(1)
	{
		i++;
	}
	
	return 0;
}

实现了定时器中断的简单demo: f1c100s_project_run_in_sram_6.7z

仍然感谢新唐提供的裸奔程序。





离线

楼主 #8 2018-08-21 16:50:14

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180821164721.png

__asm __irq void sysSwiHandler()
{
	STMFD r13!,{r0 - r5,r14}   //Push r0 - r5 and LR保存寄存器

	MOV R0, #0xAA;
	MOV R1, #0xBB;
	MOV R2, #0xCC;
	MOV R3, #0xDD;		

	LDR R4, [LR, #-4] 
	BIC R4, R4, #0xFF000000 //将SWI指令高8位清除掉,只保留低24位立即数,取得SWI指令编码


	LDMFD r13!,{r0 - r5,r14}   //Pop r0 - r5 and LR恢复寄存器

	MOV PC, LR		
}

int main(void)
{
	
	*(void* volatile *)0x28 = (void* volatile)sysSwiHandler;
}	

实现一个简单的swi中断处理,并取出用户自定义中断号到R4寄存器: f1c100s_project_run_in_sram_7.7z





离线

楼主 #9 2018-08-22 14:03:43

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

#define TMR_IRQ_EN_REG 			(0x01C20C00 + 0x00)
#define TMR_IRQ_STA_REG 		(0x01C20C00 + 0x04)
#define TMR0_CTRL_REG 			(0x01C20C00 + 0x10)
#define TMR0_INTV_VALUE_REG	(0x01C20C00 + 0x14)
#define TMR0_CUR_VALUE_REG	(0x01C20C00 + 0x18)


#define INTC_PEND_REG0		(0x01C20400 + 0x10)
#define INTC_PEND_REG1		(0x01C20400 + 0x14)
#define INTC_EN_REG0			(0x01C20400 + 0x20)
#define INTC_EN_REG1			(0x01C20400 + 0x24)
#define INTC_MASK_REG0		(0x01C20400 + 0x30)
#define INTC_MASK_REG1		(0x01C20400 + 0x34)
#define INTC_RESP_REG0 		(0x01C20400 + 0x40)
#define INTC_RESP_REG1 		(0x01C20400 + 0x44)
#define INTC_FF_REG0			(0x01C20400 + 0x50)
#define INTC_FF_REG1			(0x01C20400 + 0x54)
#define INTC_PRIO_REG0 		(0x01C20400 + 0x60)
#define INTC_PRIO_REG1 		(0x01C20400 + 0x60)


static volatile int test_count = 0;
__irq void sysIrqHandler()
{	
	test_count++;
	
	write32(TMR_IRQ_STA_REG, (1)); //清除TIMER0中断标识
}


int main(void)
{
	*(void* volatile *)0x38 = (void* volatile)sysIrqHandler;//设置IRQ中断处理程序
			
	sys_clock_init();
	sys_uart_init();
	
	
	write32(TMR_IRQ_EN_REG, 1);
	
	write32(INTC_EN_REG0, (read32(INTC_EN_REG0)) | 1 << 13);
	
	write32(TMR_IRQ_EN_REG, (read32(TMR_IRQ_EN_REG)) | 1 << 13);
	
	write32(TMR0_INTV_VALUE_REG, 0x2EE0);   //Set interval value 
	
	write32(TMR0_CTRL_REG, 0x10);   //此行注释有误,具体看手册 Select Single mode,24MHz clock source,2 pre-scale 
	
	write32(TMR0_CTRL_REG, read32(TMR0_CTRL_REG)|(1<<1)); //Set Reload bit 

	while((read32(TMR0_CTRL_REG)>>1)&1);  //Waiting Reload bit turns to 0 
#if 1
	write32(TMR0_CTRL_REG, read32(TMR0_CTRL_REG)|(1<<0));  //Enable Timer0 
	
	//开启中断使能
	u32_t temp;	
	__asm
	{
		 MRS    temp, CPSR
		 AND    temp, temp, 0x7F
		 MSR    CPSR_c, temp
	}
#endif
				
		
	u32_t old = 0;	
	while(1)
	{
		if(old == test_count)
		{			
		}
		else
		{
			old = test_count;
			if(test_count % 256 == 0)
			{
				sysprintf("%d\n", test_count);
			}
		}
	}
}

QQ20180822140802.png

QQ20180822140525.png

跳出七七四十九道坑写的TIMER0 中断处理程序:

f1c100s_project_run_in_sram_8.7z





离线

楼主 #11 2018-08-22 17:20:32

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

Jin劲 说:

半小时内搞定上传.
copy from xboot





离线

楼主 #12 2018-08-22 18:22:52

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180822182058.png

//xarray数组定义到ddr
unsigned char xarray[128] __attribute__((at(0x80000000)));

extern void sys_dram_init(void);
int main(void)
{
	sys_dram_init();
	memset(xarray, 0xAA, sizeof(xarray));
	xarray[1] = xarray[0] + 1;
	xarray[2] = xarray[1] + 2;
}

代码参考: https://github.com/xboot/xboot/blob/master/src/arch/arm32/mach-f1c100s/sys-dram.c

/*
 * sys-dram.c
 *
 * Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
 * Official site: http://xboot.org
 * Mobile phone: +86-18665388956
 * QQ: 8192542
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <xboot.h>
#include <f1c100s/reg-ccu.h>
#include <f1c100s/reg-dram.h>

#define PLL_DDR_CLK			(156000000)
#define SDR_T_CAS			(0x2)
#define SDR_T_RAS			(0x8)
#define SDR_T_RCD			(0x3)
#define SDR_T_RP			(0x3)
#define SDR_T_WR			(0x3)
#define SDR_T_RFC			(0xd)
#define SDR_T_XSR			(0xf9)
#define SDR_T_RC			(0xb)
#define SDR_T_INIT			(0x8)
#define SDR_T_INIT_REF		(0x7)
#define SDR_T_WTR			(0x2)
#define SDR_T_RRD			(0x2)
#define SDR_T_XP			(0x0)

enum dram_type_t
{
	DRAM_TYPE_SDR	= 0,
	DRAM_TYPE_DDR	= 1,
	DRAM_TYPE_MDDR	= 2,
};

struct dram_para_t
{
	u32_t base;				/* dram base address */
	u32_t size;				/* dram size (unit: MByte) */
	u32_t clk;				/* dram work clock (unit: MHz) */
	u32_t access_mode;		/* 0: interleave mode 1: sequence mode */
	u32_t cs_num;			/* dram chip count  1: one chip  2: two chip */
	u32_t ddr8_remap;		/* for 8bits data width DDR 0: normal  1: 8bits */
	enum dram_type_t sdr_ddr;
	u32_t bwidth;			/* dram bus width */
	u32_t col_width;		/* column address width */
	u32_t row_width;		/* row address width */
	u32_t bank_size;		/* dram bank count */
	u32_t cas;				/* dram cas */
};

static inline void sdelay(int loops)
{
	__asm__ __volatile__ ("1:\n" "subs %0, %1, #1\n"
		"bne 1b":"=r" (loops):"0"(loops));
}

static void dram_delay(int ms)
{
	sdelay(ms * 2 * 1000);
}

static int dram_initial(void)
{
	unsigned int time = 0xffffff;

	write32(F1C100S_DRAM_BASE + DRAM_SCTLR, read32(F1C100S_DRAM_BASE + DRAM_SCTLR) | 0x1);
	while((read32(F1C100S_DRAM_BASE + DRAM_SCTLR) & 0x1) && time--)
	{
		if(time == 0)
			return 0;
	}
	return 1;
}

static int dram_delay_scan(void)
{
	unsigned int time = 0xffffff;

	write32(F1C100S_DRAM_BASE + DRAM_DDLYR, read32(F1C100S_DRAM_BASE + DRAM_DDLYR) | 0x1);
	while((read32(F1C100S_DRAM_BASE + DRAM_DDLYR) & 0x1) && time--)
	{
		if(time == 0)
			return 0;
	}
	return 1;
}

static void dram_set_autofresh_cycle(u32_t clk)
{
	u32_t val = 0;
	u32_t row = 0;
	u32_t temp = 0;

	row = read32(F1C100S_DRAM_BASE + DRAM_SCONR);
	row &= 0x1e0;
	row >>= 0x5;

	if(row == 0xc)
	{
		if(clk >= 1000000)
		{
			temp = clk + (clk >> 3) + (clk >> 4) + (clk >> 5);
			while(temp >= (10000000 >> 6))
			{
				temp -= (10000000 >> 6);
				val++;
			}
		}
		else
		{
			val = (clk * 499) >> 6;
		}
	}
	else if(row == 0xb)
	{
		if(clk >= 1000000)
		{
			temp = clk + (clk >> 3) + (clk >> 4) + (clk >> 5);
			while(temp >= (10000000 >> 7))
			{
				temp -= (10000000 >> 7);
				val++;
			}
		}
		else
		{
			val = (clk * 499) >> 5;
		}
	}
	write32(F1C100S_DRAM_BASE + DRAM_SREFR, val);
}

static int dram_para_setup(struct dram_para_t * para)
{
	u32_t val = 0;

    val = (para->ddr8_remap) |
    	(0x1 << 1) |
		((para->bank_size >> 2) << 3) |
		((para->cs_num >> 1) << 4) |
		((para->row_width - 1) << 5) |
		((para->col_width - 1) << 9) |
		((para->sdr_ddr ? (para->bwidth >> 4) : (para->bwidth >> 5)) << 13) |
		(para->access_mode << 15) |
		(para->sdr_ddr << 16);

	write32(F1C100S_DRAM_BASE + DRAM_SCONR, val);
	write32(F1C100S_DRAM_BASE + DRAM_SCTLR, read32(F1C100S_DRAM_BASE + DRAM_SCTLR) | (0x1 << 19));
	return dram_initial();
}

static u32_t dram_check_delay(u32_t bwidth)
{
	u32_t dsize;
	u32_t i,j;
	u32_t num = 0;
	u32_t dflag = 0;

	dsize = ((bwidth == 16) ? 4 : 2);
	for(i = 0; i < dsize; i++)
	{
		if(i == 0)
			dflag = read32(F1C100S_DRAM_BASE + DRAM_DRPTR0);
		else if(i == 1)
			dflag = read32(F1C100S_DRAM_BASE + DRAM_DRPTR1);
		else if(i == 2)
			dflag = read32(F1C100S_DRAM_BASE + DRAM_DRPTR2);
		else if(i == 3)
			dflag = read32(F1C100S_DRAM_BASE + DRAM_DRPTR3);

		for(j = 0; j < 32; j++)
		{
			if(dflag & 0x1)
				num++;
			dflag >>= 1;
		}
	}
	return num;
}

static int sdr_readpipe_scan(void)
{
	u32_t k = 0;

	for(k = 0; k < 32; k++)
	{
		write32(0x80000000 + 4 * k, k);
	}
	for(k = 0; k < 32; k++)
	{
		if(read32(0x80000000 + 4 * k) != k)
			return 0;
	}
	return 1;
}

static u32_t sdr_readpipe_select(void)
{
	u32_t value = 0;
	u32_t i = 0;
	for(i = 0; i < 8; i++)
	{
		write32(F1C100S_DRAM_BASE + DRAM_SCTLR, (read32(F1C100S_DRAM_BASE + DRAM_SCTLR) & (~(0x7 << 6))) | (i << 6));
		if(sdr_readpipe_scan())
		{
			value = i;
			return value;
		}
	}
	return value;
}

static u32_t dram_check_type(struct dram_para_t * para)
{
	u32_t val = 0;
	u32_t times = 0;
	u32_t i;

	for(i = 0; i < 8; i++)
	{
		val = read32(F1C100S_DRAM_BASE + DRAM_SCTLR);
		val &= ~(0x7 << 6);
		val |= (i << 6);
		write32(F1C100S_DRAM_BASE + DRAM_SCTLR, val);

		dram_delay_scan();
		if(read32(F1C100S_DRAM_BASE + DRAM_DDLYR) & 0x30)
			times++;
	}

	if(times == 8)
	{
		para->sdr_ddr = DRAM_TYPE_SDR;
		return 0;
	}
	else
	{
		para->sdr_ddr = DRAM_TYPE_DDR;
		return 1;
	}
}

static u32_t dram_scan_readpipe(struct dram_para_t * para)
{
	u32_t i, rp_best = 0, rp_val = 0;
	u32_t val = 0;
	u32_t readpipe[8];

	if(para->sdr_ddr == DRAM_TYPE_DDR)
	{
		for(i = 0; i < 8; i++)
		{
			val = read32(F1C100S_DRAM_BASE + DRAM_SCTLR);
			val &= ~(0x7 << 6);
			val |= (i << 6);
			write32(F1C100S_DRAM_BASE + DRAM_SCTLR, val);
			dram_delay_scan();
			readpipe[i] = 0;
			if((((read32(F1C100S_DRAM_BASE + DRAM_DDLYR) >> 4) & 0x3) == 0x0) &&
				(((read32(F1C100S_DRAM_BASE + DRAM_DDLYR) >> 4) & 0x1) == 0x0))
			{
				readpipe[i] = dram_check_delay(para->bwidth);
			}
			if(rp_val < readpipe[i])
			{
				rp_val = readpipe[i];
				rp_best = i;
			}
		}
		val = read32(F1C100S_DRAM_BASE + DRAM_SCTLR);
		val &= ~(0x7 << 6);
		val |= (rp_best << 6);
		write32(F1C100S_DRAM_BASE + DRAM_SCTLR, val);
		dram_delay_scan();
	}
	else
	{
		val = read32(F1C100S_DRAM_BASE + DRAM_SCONR);
		val &= (~(0x1 << 16));
		val &= (~(0x3 << 13));
		write32(F1C100S_DRAM_BASE + DRAM_SCONR, val);
		rp_best = sdr_readpipe_select();
		val = read32(F1C100S_DRAM_BASE + DRAM_SCTLR);
		val &= ~(0x7 << 6);
		val |= (rp_best << 6);
		write32(F1C100S_DRAM_BASE + DRAM_SCTLR, val);
	}
	return 0;
}

static u32_t dram_get_dram_size(struct dram_para_t * para)
{
	u32_t colflag = 10, rowflag = 13;
	u32_t i = 0;
	u32_t val1 = 0;
	u32_t count = 0;
	u32_t addr1, addr2;

	para->col_width = colflag;
	para->row_width = rowflag;
	dram_para_setup(para);
	dram_scan_readpipe(para);
	for(i = 0; i < 32; i++)
	{
		*((u32_t *)(0x80000200 + i)) = 0x11111111;
		*((u32_t *)(0x80000600 + i)) = 0x22222222;
	}
	for(i = 0; i < 32; i++)
	{
		val1 = *((u32_t *)(0x80000200 + i));
		if(val1 == 0x22222222)
			count++;
	}
	if(count == 32)
	{
		colflag = 9;
	}
	else
	{
		colflag = 10;
	}
	count = 0;
	para->col_width = colflag;
	para->row_width = rowflag;
	dram_para_setup(para);
	if(colflag == 10)
	{
		addr1 = 0x80400000;
		addr2 = 0x80c00000;
	}
	else
	{
		addr1 = 0x80200000;
		addr2 = 0x80600000;
	}
	for(i = 0; i < 32; i++)
	{
		*((u32_t *)(addr1 + i)) = 0x33333333;
		*((u32_t *)(addr2 + i)) = 0x44444444;
	}
	for(i = 0; i < 32; i++)
	{
		val1 = *((u32_t *)(addr1 + i));
		if(val1 == 0x44444444)
		{
			count++;
		}
	}
	if(count == 32)
	{
		rowflag = 12;
	}
	else
	{
		rowflag = 13;
	}
	para->col_width = colflag;
	para->row_width = rowflag;
	if(para->row_width != 13)
	{
		para->size = 16;
	}
	else if(para->col_width == 10)
	{
		para->size = 64;
	}
	else
	{
		para->size = 32;
	}
	dram_set_autofresh_cycle(para->clk);
	para->access_mode = 0;
	dram_para_setup(para);

	return 0;
}

static int dram_init(struct dram_para_t * para)
{
	u32_t val = 0;
	u32_t i;

	write32(0x01c20800 + 0x24, read32(0x01c20800 + 0x24) | (0x7 << 12));
	dram_delay(5);
	if(((para->cas) >> 3) & 0x1)
	{
		write32(0x01c20800 + 0x2c4, read32(0x01c20800 + 0x2c4) | (0x1 << 23) | (0x20 << 17));
	}
	if((para->clk >= 144) && (para->clk <= 180))
	{
		write32(0x01c20800 + 0x2c0, 0xaaa);
	}
	if(para->clk >= 180)
	{
		write32(0x01c20800 + 0x2c0, 0xfff);
	}
	if((para->clk) <= 96)
	{
		val = (0x1 << 0) | (0x0 << 4) | (((para->clk * 2) / 12 - 1) << 8) | (0x1u << 31);
	}
	else
	{
		val = (0x0 << 0) | (0x0 << 4) | (((para->clk * 2) / 24 - 1) << 8) | (0x1u << 31);
	}

	if(para->cas & (0x1 << 4))
	{
		write32(F1C100S_CCU_BASE + CCU_PLL_DDR0_PAT, 0xd1303333);
	}
	else if(para->cas & (0x1 << 5))
	{
		write32(F1C100S_CCU_BASE + CCU_PLL_DDR0_PAT, 0xcce06666);
	}
	else if(para->cas & (0x1 << 6))
	{
		write32(F1C100S_CCU_BASE + CCU_PLL_DDR0_PAT, 0xc8909999);
	}
	else if(para->cas & (0x1 << 7))
	{
		write32(F1C100S_CCU_BASE + CCU_PLL_DDR0_PAT, 0xc440cccc);
	}
	if(para->cas & (0xf << 4))
	{
		val |= 0x1 << 24;
	}
	write32(F1C100S_CCU_BASE + CCU_PLL_DDR_CTRL, val);
	write32(F1C100S_CCU_BASE + CCU_PLL_DDR_CTRL, read32(F1C100S_CCU_BASE + CCU_PLL_DDR_CTRL) | (0x1 << 20));
	while((read32(F1C100S_CCU_BASE + CCU_PLL_DDR_CTRL) & (1 << 28)) == 0);
	dram_delay(5);
	write32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0, read32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0) | (0x1 << 14));
	write32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0, read32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0) & ~(0x1 << 14));
	for(i = 0; i < 10; i++)
		continue;
	write32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0, read32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0) | (0x1 << 14));

	val = read32(0x01c20800 + 0x2c4);
	(para->sdr_ddr == DRAM_TYPE_DDR) ? (val |= (0x1 << 16)) : (val &= ~(0x1 << 16));
	write32(0x01c20800 + 0x2c4, val);

	val = (SDR_T_CAS << 0) | (SDR_T_RAS << 3) | (SDR_T_RCD << 7) | (SDR_T_RP << 10) | (SDR_T_WR << 13) | (SDR_T_RFC << 15) | (SDR_T_XSR << 19) | (SDR_T_RC << 28);
	write32(F1C100S_DRAM_BASE + DRAM_STMG0R, val);
	val = (SDR_T_INIT << 0) | (SDR_T_INIT_REF << 16) | (SDR_T_WTR << 20) | (SDR_T_RRD << 22) | (SDR_T_XP << 25);
	write32(F1C100S_DRAM_BASE + DRAM_STMG1R, val);
	dram_para_setup(para);
	dram_check_type(para);

	val = read32(0x01c20800 + 0x2c4);
	(para->sdr_ddr == DRAM_TYPE_DDR) ? (val |= (0x1 << 16)) : (val &= ~(0x1 << 16));
	write32(0x01c20800 + 0x2c4, val);

	dram_set_autofresh_cycle(para->clk);
	dram_scan_readpipe(para);
	dram_get_dram_size(para);

	for(i = 0; i < 128; i++)
	{
		*((volatile u32_t *)(para->base + 4 * i)) = para->base + 4 * i;
	}

	for(i = 0; i < 128; i++)
	{
		if(*((volatile u32_t *)(para->base + 4 * i)) != (para->base + 4 * i))
			return 0;
	}
	return 1;
}

void sys_dram_init(void)
{
	struct dram_para_t para;
	u32_t * dsz = (void *)0x0000005c;

	para.base = 0x80000000;
	para.size = 32;
	para.clk = PLL_DDR_CLK / 1000000;
	para.access_mode = 1;
	para.cs_num = 1;
	para.ddr8_remap = 0;
	para.sdr_ddr = DRAM_TYPE_DDR;
	para.bwidth = 16;
	para.col_width = 10;
	para.row_width = 13;
	para.bank_size = 4;
	para.cas = 0x3;

	if((dsz[0] >> 24) == 'X')
		return;
	if(dram_init(&para))
		dsz[0] = (((u32_t)'X') << 24) | (para.size << 0);
}

f1c100s 初始化ddr 代码工程:f1c100s_project_run_in_sram_9.7z





离线

楼主 #13 2018-08-23 09:28:47

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

上面的视频演示 timer0 控制寄存器 TMR0_CTRL_REG 设置为单次触发,
中断程序只进入一次.

TMR0_MODE.
Timer 0 mode.

0: Continuous mode. When interval value reached, the timer will not disable
automatically.

1: Single mode. When interval value reached, the timer will disable
automatically.





离线

楼主 #14 2018-08-23 17:52:17

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180823174724.png





离线

楼主 #15 2018-08-28 18:24:46

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180828182543.png

先烧录这个ddr初始化文件到spi flash: f1c100s_ddr_init.bin
修改自: https://whycan.cn/t_1457.html

源码下载: f1c100s_project_run_in_sram_10.7z





离线

楼主 #16 2018-08-28 19:22:25

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

@达克罗德  大神方便帮我看下楼上的MDK工程吗,
调用ddr初始化代码lcd就显示不正常了,
只有把你的工程编译烧到spi flash,
让他初始化ddr,
才能正常LCD显示。





离线

楼主 #19 2018-08-29 08:13:48

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

我这个工程和 xboot 的初始化代码不一样,
还有这个代码直接通过 MDK 的调试按钮,下载到 SRAM 里面调试.

1.  如果 main 函数这样 (清除了flash):

int main(void)
{
    sys_clock_init(); 
    sys_dram_init();
    //....
}

sys_dram_init() 每次都可以初始化通过,
但是 sys_dram_init() 执行过后把 SRAM 的很多处数据都改了,
也没有跟踪到到底哪行代码作怪,
因为数据被改,这样就出现了非法指令,进入了错误中断.


2. 代码改成这样(清除了flash):

int main(void)
{
#if 1
    arm32_interrupt_disable();
    arm32_mmu_disable();
    arm32_icache_disable();
    arm32_dcache_disable();
#endif
    sys_clock_init(); 
    sys_dram_init();
    //....

情况和1 一模一样.

3. 如果第一次用1的方法代码初始化DDR, 程序飞了,停止调试。屏蔽DDR初始化那一行代码

//sys_dram_init();

程序可以正常运行了,循环写帧缓冲区也没有问题, 但是屏幕只显示淡蓝色, 一直都是淡蓝色.
实际上中断程序,看颜色变量是正常的红绿蓝颜色.
QQ20180829085709.jpg

4. 如果按上面方法, 把xboot 的 bin 烧录到 flash(只有ddr 初始化,然后进入死循环), 然后再用MDK SRAM调试,

int main(void)
{
    sys_clock_init(); 
    //sys_dram_init();
    //....
}

代码中不再有 DDR 初始化相关部分, 那么运行正常, 可以蓝绿红切换屏幕.





离线

楼主 #21 2018-08-29 09:02:50

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

QQ20180829090033.png

0x5C只是一个 Abort_Handler 地址而已, 估计是借几个位用于标识是否初始化过DDR.
SRAM那个问题确实有点神奇, 不知道是不是MDK JLink调试工具引起的。





离线

楼主 #26 2019-04-13 14:08:04

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

有朋友反应MDK没有 ARM9 器件可以选择, 解决方案如下:




2019-04-13 更新
---------------------------------------------
支持ARM7/9旧器件的 MDK 版本:
http://www2.keil.com/mdk5/legacy/
https://armkeil.blob.core.windows.net/legacy/MDK79525.EXE
https://armkeil.blob.core.windows.net/legacy/MDK79524.EXE





离线

楼主 #32 2019-08-15 17:31:53

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,245
积分: 9197

Re: step by step 全志 f1c100s MDK 裸奔各种外设(参考N3290x)

就是基于新唐的Demo工程修改的。





离线

页脚

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

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