页次: 1
终于把这三个函数代码分析调试并补充完整了,否则编译出错BLE发送数据包CRC不对。会被手机端APP扔掉了。
NST_BLE代码.rar
钜芯公司提供的LT8920_SDK_V1.1.zip里是有蓝牙收发的工程与APK测试工具。可惜只针对STM32F103的。而且把SPI驱动与蓝牙核心代码都打包成了LIB文件提供。无法直接移植到其它单片机平台。但是这是难不倒我强大的IDA+F5逆向工程及人工修正校对方法。经过移植后通信测试状态良好,一开心还没有来得及优化SPI驱动。直接上源码:
9G-SWM181X-rectl-20241105.rar
有3个函数反得晕晕的。感觉是某个标准的CRC校验和算法。没有时间认真核对并消化。只好直接保留源码:
原理图:
串口信息:
测试图片:
调试工具:调试Tools.rar
板子终于跑起来了。直接用开源工程。
https://whycan.com/files/members/4099/D213编译.png
https://gitee.com/artinchip/d211 厂家开源代码包
新设计的产品用了平头哥D213。放个原理图上来让人挑挑毛病。有没有支持的兄弟?D213ECV2CAN.pdf
PCB终于也排好了。上个图片。
新设计的产品用了平头哥D213。放个原理图上来让人挑挑毛病。有没有支持的兄弟?D213ECV2CAN.pdf
玩一玩几毛钱的PADAUK应广单片机跃龙PFC161。缥缈九哥借鉴网上代码测试。
包含一个1MS定时器与1个PA6输入按键反转PA4输出,以及PA5的2MS脉冲波,PA3的1秒反转信号。详细见代码:
#include "extern.h"
//================================================================================
.ramadr 0
word gw_Point;
.ramadr system
word gw_T16Cnt;
word gw_Cnt;
byte gb_Flag;
bit b_T16_1ms : gb_Flag.0 //1MS
bit b_1S_F : gb_Flag.1 //1S
byte gb_KeyDebounce;
byte gb_KeyNew;
byte gb_KeyOld;
byte gb_KeyValue;
//------------------------------------------------------------
//LED equ PA.3 // 设置PA3为LED输出
//PON equ PA.4 // 设置PA4为电源控制
//PWM equ PA.5 // 设置PA5为PWM输出
//KEY equ PA.6 // 设置PA6为按钮控制
D_KEYPORT equ 0b_0100_0000 // PA6 按键
D_KEY1 equ 0b_0100_0000 // PA6 按键
D_KeyBounce equ 30*1000/1024 // 30ms
//================================================================================
void Test_DirectScanKey(void)
{
if(b_T16_1ms)
{
b_T16_1ms = 0;
a = pa & D_KEYPORT;
a ^= D_KEYPORT;
if(gb_KeyNew == a)
{//读到值相同值,Debouce
if(--gb_KeyDebounce == 0)
{//Debounce结束
if(gb_KeyOld != gb_KeyNew)
{
gb_KeyValue = gb_KeyNew;
gb_KeyOld = gb_KeyNew;
}
}
}
else
{
gb_KeyNew = a;
gb_KeyDebounce = D_KeyBounce;
}
}
}
//================================================================================
void Test_KeyProcess(void)
{
//处理Key1
if(gb_KeyValue == D_KEY1)
{
gb_KeyValue = 0;
//pa4 电平翻转
a = pa;a ^= 0x10;pa = a;
}
}
//================================================================================
void FPPA0(void)
{
.ADJUST_IC SYSCLK=IHRC/4, IHRC=16MHz, VDD=5V;
clkmd.En_WatchDog = 1; // WatchDog Enable
// Insert Initial Code
//注:无PA.1,PA.2脚位
//未使用端口需有防漏电设置,如加内部上拉
PAPH = 0b0100_0000; //上拉控制寄存器,控制上拉高相应的引脚(1:启用,0:停用
PAPL = 0b0000_0000; //下拉控制寄存器,控制下拉高相应的引脚(1:启用,0:停用)
PAC = 0b1011_1001; //数据控制寄存器(1:输出模式,0:输入模式)
PA = 0b0000_0000; //数据寄存器
.delay 4000;
//------------------------------------------------------------
//清除RAM
gw_Point = _SYS(RAM_SIZE) - 1;
a = 0;
do
{
*gw_Point = a;
} while (--gw_Point$0);
//------------------------------------------------------------
//初始化定时器 定时1MS
gw_Point = 1024 - 1000;
stt16 gw_T16Cnt;
$ t16m SYSCLK,/4,bit10;
intrq = 0;
inten.2 = 1;
engint;
//------------------------------------------------------------
while (1)
{
// ...
if(b_1S_F)
{
b_1S_F = 0;
//PA3 反转
a = pa; a ^= 0x08;pa = a;
}
Test_DirectScanKey();
Test_KeyProcess();
.wdreset;
}
}
//================================================================================
void Interrupt (void)
{
pushaf;
if (Intrq.T16)
{ // T16 Trig
// User can add code
Intrq.T16 = 0;
//...
stt16 gw_T16Cnt;
//pa5 电平翻转
a = pa;a ^= 0x20;pa = a;
b_T16_1ms = 1;
gw_Cnt++;
if(gw_Cnt > 999)
{//1S计数
gw_Cnt = 0;
b_1S_F = 1;
}
}
popaf;
}
//缥缈九哥测试完毕!
//================================================================================
源码包:9G-LED.rar
听说STM32H7必须要用cubemx图形化HAL编程,要学一种新软件代码又不简洁,而另外一种基于MDKARM的RTM开发模式下各中依赖开发环境的源与PACK也不是很习惯,换了电脑换了开发平台可能因为丢失了头文件或者库编译不通过,或者版本不兼容痛苦。我觉得对于我这种传统STM32过来的老人习惯了直接全部工程中包含源代码比较合适。只好从代码中提取核心的API做了一个纯源码的工程包。
工程主要还是传统STM32一样,包含CMSIS头文件,启动S文件,系统初始化文件,CPU相关文件,驱动API相关的BSP包文件等。其余都是网上最新找到的库,API,初始化,头文件,其中主要还是一个个人应用入口的MAIN.C文件:
int main(void)
{
int i=0;
/* This project template calls firstly CPU_CACHE_Enable() function in order enable the CPU Cache.
These functions are provided as template implementation that User may integrate in his application.
*/
/* Configure the MPU attributes */
MPU_Config();
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* STM32H7xx HAL library initialization:
- Configure the Systick to generate an interrupt each 1 msec
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 520 MHz */
SystemClock_Config();
/* Add your application code here */
GPIO_LED_Init();
UART3_init();
printf("NUCLEO-H723ZG Build by yuanxihua@21cn.com on ("__DATE__" - "__TIME__ ")\n\r");
/* Infinite loop */
while (1)
{
GPIO_LED_Test();
printf("NUCLEO-H723ZG run %d \n\r",i++);
}
}
直接上源代码:TEV8AE_code-20220308B.rar
购买的板子是:
https://item.taobao.com/item.htm?spm=a1z09.2.0.0.70052e8d1HwnxK&id=584657396198 Sipeed lichee Nano 荔枝派 跨界开发板 多系统 Linux F1c100s (焊接的SPIFLASH是新天下的XT25F128B)
烧录方法是本论坛的:sunxi-tools-win32support_f1c100s 里面的sunxi-fel.exe
登陆方法是:USB-TTL转换线直接接到 PE1 PE0 +5V GND 脚。PC登陆用的是SecureCRT 8.5 串口终端模式115200 8N1 无流控
镜像来源于:https://www.codenong.com/cs106854611/ (别的镜像不支持这个SPIFLASH,但是测试中文件系统莫名崩溃)
文件系统来源于:
https://whycan.com/t_2689.html 和 https://whycan.com/t_2688.html
烧录方法命令是:
(注意用本坛的zadig-2.3.exe安装WCID驱动,插USB线前短路SPIFLASH的1,2脚进入USB烧录模式,用sunxi-fel.exe命令行烧录)
D:\bin\sunxi-tools-win32support_f1c100s>sunxi-fel.exe -p spiflash-write 0 u-boot-sunxi-with-spl.bin
100% [================================================] 418 kB, 89.9 kB/s
D:\bin\sunxi-tools-win32support_f1c100s>sunxi-fel.exe -p spiflash-write 0x100000 suniv-f1c100s-licheepi-nano.dtb
100% [================================================] 8 kB, 32.5 kB/s
D:\bin\sunxi-tools-win32support_f1c100s>sunxi-fel.exe -p spiflash-write 0x110000 zImage
100% [================================================] 3656 kB, 96.3 kB/s
D:\bin\sunxi-tools-win32support_f1c100s>sunxi-fel.exe -p spiflash-write 0x510000 jffs2.bin
100% [================================================] 11469 kB, 101.6 kB/s
UBOOT启动命令行与参数是:
setenv bootcmd 'sf probe 0 50000000;sf read 0x80c00000 0x100000 0x4000;sf read 0x80008000 0x110000 0x400000;bootz 0x80008000 - 0x80c00000'
setenv bbotargs 'console=ttyS0,115200 root=/dev/mtdblock3 rootfstype=jffs2 mtdparts=spi0.0:1M(uboot),64K(dtb),4M(kernel),-(rootfs)'
saveenv
run bootcmd
两个不同的文件系统登陆命令是:
其中两个文件系统 :
jffs2.bin的登陆
opendeck login: root
Password: whycan.cn
rootfs.jffs2的登陆
opendeck login: root
Password: opendeck
还是直接上代码吧:
/********************************************************************************
* @file ds18b20.c *
* @brief The Driver code for DS18B20 with SWM181CBT6 *
* @version 1.0.0 *
* @date 2018/09/19 19:26:35 *
* *
* @note *
* Copyright (C) 2000-2018 PM9GZY by yuanxihua@21cn.com. All rights reserved. *
********************************************************************************/
/* Includes --------------------------------------------------------------------*/
#include "main.h"
/*
_________________________________________________
| SWM181CBT6 DS18B20 |
| |
| DATA - PC2 <---> DQ0 |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
#define SkipROM 0xCC //跳过ROM
#define SearchROM 0xF0 //搜索ROM
#define ReadROM 0x33 //读ROM
#define MatchROM 0x55 //匹配ROM
#define AlarmROM 0xEC //告警ROM
#define StartConvert 0x44 //开始温度转换,在温度转换期间总线上输出0,转换结束后输出1
#define ReadScratchpad 0xBE //读寄存器的9个字节
#define WriteScratchpad 0x4E //写寄存器的温度告警TH和TL
#define CopyScratchpad 0x48 //将寄存器的温度告警复制到EEPROM,在复制期间总线上输出0,复制完后输出1
#define RecallEEPROM 0xB8 //将EEPROM的温度告警复制到寄存器中,复制期间输出0,复制完成后输出1
#define ReadPower 0xB4 //读电源的供电方式:0为寄生电源供电;1为外部电源供电
/* Private define ------------------------------------------------------------*/
#define PC2 PIN2
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
//void delay_us(uint32_t us)
//{
// int32_t t=SysTick->VAL-(us*CyclesPerUs);
// if(t<0){t+=SysTick->LOAD;while((SysTick->CTRL&SysTick_CTRL_COUNTFLAG_Msk)==0){;}}
// while(SysTick->VAL>t){;}
//}
//1.初始化
uint8_t DS18B20_init(uint32_t n)
{
uint32_t i=0,ret=1;
GPIO_Init(GPIOC, n, 1, 1, 0, 0); //DQ 配置为输出引脚,开启上拉,推挽输出
GPIO_SetBit(GPIOC, n); //DQ=1;
delay_us(900); //稍作延时
//开始初始化
GPIO_ClrBit(GPIOC, n); //DQ=0;
delay_us(540); //延时540us
GPIO_SetBit(GPIOC, n); //DQ=1;
GPIO_Init(GPIOC, n, 0, 1, 0, 0); //DQ 配置为输入引脚,开启上拉
delay_us(60); //稍作延时
while(GPIO_GetBit(GPIOC, n)) //等待DS18B20拉低总线
{
delay_us(1);
if(i++>240){ret=0;break;} //初始化失败
}
GPIO_Init(GPIOC, n, 1, 1, 0, 0); //DQ 配置为输出引脚,开启上拉,推挽输出
GPIO_SetBit(GPIOC, n); //DQ=1;
delay_us(480);
return ret; //初始化成功
}
//2.写字节
void write_byte(uint32_t n,uint8_t dat) //写一个字节
{
uint8_t i;
for(i=0;i<8;i++)
{
GPIO_ClrBit(GPIOC, n); //DQ=0; 总线拉低1us
delay_us(1);
if(dat&0x01){GPIO_SetBit(GPIOC, n);} //取最低位写入
else{GPIO_ClrBit(GPIOC, n);}
delay_us(60); //延时60us
GPIO_SetBit(GPIOC, n); //DQ=1; 释放总线
delay_us(1);
dat=dat>>1; //从低位开始写
}
}
//3.读字节
uint8_t read_byte(uint32_t n) //读一个字节
{
uint8_t i,dat=0;
for(i=0;i<8;i++)
{
GPIO_ClrBit(GPIOC, n); //DQ=0; 总线拉低1us
delay_us(1);
GPIO_SetBit(GPIOC, n); //DQ=1; 释放总线
GPIO_Init(GPIOC, n, 0, 1, 0, 0); //DQ 配置为输入引脚,开启上拉
delay_us(2); //延时等待数据稳定 5
dat=dat>>1; //从最低位开始读
if(GPIO_GetBit(GPIOC, n)){dat|=0x80;} //每次读一位
else{dat&=0x7f;}
delay_us(30); //等待读取数据稳定
GPIO_Init(GPIOC, n, 1, 1, 0, 0); //DQ 配置为输出引脚,开启上拉,推挽输出
GPIO_SetBit(GPIOC, n); //DQ=1; 释放总线
delay_us(1);
}
return dat;
}
//4.按位CRC运算
//Purpose: To calculate an 8-bit CRC based on a polynomial and the series
// of data bytes
//Note: Polynomial used x^8 + x^5 + x^4 + 1 = 10001100
//Inputs: A pointer to an array of the data bytes and an uint8_t saying how many
// bytes there are in the data array
//Outputs: An uint8_t which is the calculated CRC
uint8_t OneWireCRC8(uint8_t *buf, uint8_t len)
{
#define CRC8_POLYNOMIAL 0x8C
uint8_t crc=0,val=0,inb,mix;
while(len--){inb=*buf++;if(inb){val=1;}for(uint8_t i=8;i;i--){mix=(crc^inb)&0x01;crc>>=1;if(mix){crc^=CRC8_POLYNOMIAL;}inb>>=1;}}
if(!val){return 0xFF;} /* If all bytes are 0, return a different CRC so that the test will fail */
return crc;
}
//5.读温度
uint16_t read_temper(uint32_t n)
{
uint16_t temp=0xffff;uint8_t data[9],crc,ret;ret=ret;
ret=DS18B20_init(n);
write_byte(n,0xcc); //跳过ROM操作命令
write_byte(n,0x44); //发送启动温度转换命令
delay_us(2000);
ret=DS18B20_init(n);
write_byte(n,0xcc); //跳过ROM操作命令
write_byte(n,0xbe); //发送读温度寄存器命令
delay_us(2000);
for(int i=0;i<9;i++){data[i]=read_byte(n);} //read Scratchpad Memory of DS
crc=OneWireCRC8(data,8); //calculate crc
if(crc==data[8]){temp=((uint16_t)data[1]<<8)|data[0];} //compare : calculate with received
return temp; //返回温度值
}
//6.温度转换
float temper_change(uint32_t n)
{
int32_t temper;float tp;
temper=read_temper(n);
printf("temper=0x%04x\n\r",temper);
if(temper<0) //考虑负温度的情况
{
temper=temper-1;
temper=~temper;
}
tp=temper/16; //16位温度转换成10进制的温度
temper=tp*100+0.5; //留两个小数点,并四舍五入
printf("DS18B20=%3.2f\n\r",tp);
return temper;
}
//代码完毕
直接上代码:
/********************************************************************************/
/* @file adxl357.c */
/* @version V1.00 */
/* $author: yuanxihua@21cn.com */
/* $Date: 2022/01/13 02:54 $ */
/* @brief SWM181CBT6 Series ADXL357 Driver Sample Code */
/* */
/* @note */
/* Copyright (C) 2010-2022 PM9GZY Technology Corp. All rights reserved. */
/* */
/********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adxl537.h"
/*
________________________________________________
| SWM181CBT6 ADXL357 |
| |
| PA12 NSS0 ----> CS/SCL |
| PA13 MISO0 <---- MISO |
| PA14 MOSI0 ----> MOSI |
| PA15 SCLK0 ----> SCLK |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADXL357_CS_L() GPIO_ClrBit(GPIOA, PIN12)
#define ADXL357_CS_H() GPIO_SetBit(GPIOA, PIN12)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void ADXL357_Initial(void);
void ADXL357_Reset(void);
/* Private functions ---------------------------------------------------------*/
void SPI0Init(void)
{
SPI_InitStructure SPI_initStruct;
GPIO_Init(GPIOA, PIN12, 1, 0, 0, 0);ADXL357_CS_H(); //GPIOC.4 -> IOSPI.SSEL
// PORT_Init(PORTA, PIN12, PORTA_PIN12_SPI0_SSEL, 0);
PORT_Init(PORTA, PIN13, PORTA_PIN13_SPI0_MISO, 1);
PORT_Init(PORTA, PIN14, PORTA_PIN14_SPI0_MOSI, 0);
PORT_Init(PORTA, PIN15, PORTA_PIN15_SPI0_SCLK, 0);
SPI_initStruct.clkDiv = SPI_CLKDIV_4; //80NS , 12500KHZ
SPI_initStruct.FrameFormat = SPI_FORMAT_SPI;
SPI_initStruct.SampleEdge = SPI_SECOND_EDGE;
SPI_initStruct.IdleLevel = SPI_HIGH_LEVEL;
SPI_initStruct.WordSize = 8;
SPI_initStruct.Master = 1;
SPI_initStruct.RXHFullIEn = 0;
SPI_initStruct.TXEmptyIEn = 0;
SPI_initStruct.TXCompleteIEn = 0;
SPI_Init(SPI0, &SPI_initStruct);
SPI_Open(SPI0);
ADXL357_Reset();
ADXL357_Initial();
}
uint8_t ADXL357_Read(uint8_t addr,uint8_t *data,uint32_t len)
{
uint8_t cmd=(addr<<1)|0x01; // D0=R/W=1,读取模式
ADXL357_CS_L();
SPI_ReadWrite(SPI0,cmd);while(len--){*data++ =SPI_ReadWrite(SPI0,0x55)&0xff;}
ADXL357_CS_H();
}
uint8_t ADXL357_Write(uint8_t addr,uint8_t *data,uint32_t len)
{
uint8_t cmd=(addr<<1)&0xFE; // D0=R/W=0,写入模式
ADXL357_CS_L();
SPI_ReadWrite(SPI0,cmd);while(len--){SPI_ReadWrite(SPI0,*data++);}
ADXL357_CS_H();
}
uint8_t ADXL357_Read_Register(uint8_t addr){uint8_t val;ADXL357_Read(addr,&val,1);return val;}
void ADXL357_Write_Register(uint8_t addr,uint8_t data){ADXL357_Write(addr,&data,1);}
void ADXL357_Reset(void){ADXL357_Write_Register(ADXL357_Reset_REG,0x52);delay_ms(10);}
void ADXL357_Initial(void){}
float ADXL357_Read_TemperatureRead(void)
{
uint8_t tmp[2];ADXL357_Read(ADXL357_TEMP2,tmp,2);uint16_t tempH=tmp[0]&0x0F,tempL=tmp[1];
float Temperature = ((float)(tempH<<8)) + ((float)tempL);
return (25-((Temperature-1885)/9.05));
}
void ADXL357_Test(void)
{
uint8_t data[47];ADXL357_Read(ADXL357_DEVID_AD,data,sizeof(data));printf("\n\r");for(uint8_t i=0;i<sizeof(data);i++){printf("0x%02x ",data[i]);}printf("\n\r");
printf("ADXL357_DEVID_AD = 0x%02x \n\r",ADXL357_Read_Register(ADXL357_DEVID_AD));
printf("ADXL357_DEVID_MST = 0x%02x \n\r",ADXL357_Read_Register(ADXL357_DEVID_MST));
printf("ADXL357_PARTID = 0x%02x \n\r",ADXL357_Read_Register(ADXL357_PARTID));
printf("ADXL357_REVID = 0x%02x \n\r",ADXL357_Read_Register(ADXL357_REVID));
printf("ADXL357_Temperature = %f \n\r",ADXL357_Read_TemperatureRead());
}
//代码完毕
基于华芯微特SWM32SRE的IO模拟LIN总线-缥缈九哥原创
不说其它的,上源代码吧:
#include "main.h"
/******************************************************************
Lin总线帧格式:帧头+应答
帧头:同步间隔段(至少13个显性电平)+同步间隔段间隔符(至少1位隐形电平)+同步段(0x55)+字节间间隔+PID(ID+校验位)
注:PID=ID(6位)+校验(2位)
ID 取值范围为: 0x00~0x3f
ID的取值分类:
信号携带帧 : 0x00~0x3b
诊断帧(主机请求): 0x3c
诊断帧(从机应答): 0x3d
保留帧 : 0x3e,0x3f
P0 = ID0⊕ID1⊕ID2⊕ID4 异或运算
P1 = ┐(ID3⊕ID4⊕ID5⊕ID1) 异或后取非
应答:应答间隔+数据段+校验和段
注:数据段 低字节的低位先发
标准型校验和: 只校验数据段
增强型校验和: 校验数据段以及PID
诊断帧只能用标准型校验和
******************************************************************/
/******************************************************************
lin中断接收函数功能:
1、回环效果:即主机发送帧头或者主机发送帧头+应答,主机的中断服务程序都会接收数据。
可以检测出:主机串口Tx、Rx、Lin脚,三个引脚上的信号是相同的(除了电平不同)。
2、当串口检测到连续至少11位显性电平即进入中断开始接收。
3、中断服务函数接收数据时按进程推进
①接收同步段是否OK?
②接收ID校验后解析是数据执行还是反馈
若是执行: 若是反馈:
③分步接收数据 ③准备数据在帧头结束后发送数据
④匹配校验数据是否正确
⑤解析数据并执行
******************************************************************/
uint8_t TxData = 0;
volatile uint32_t TBtIdx = 0;
volatile uint32_t TxBusy = 0;
#define UART_TX_PIN PIN18
#define UART_TX_LOW() GPIO_ClrBit(GPION, UART_TX_PIN)
#define UART_TX_HIGH() GPIO_SetBit(GPION, UART_TX_PIN)
#define UART_RX_PIN PIN19
#define UART_RX_Value() GPIO_GetBit(GPION, UART_RX_PIN)
//#define UART_RX_POINT GPIOB, PIN7
#define UART_RX_POINT GPION, PIN5
uint8_t RxData = 0;
volatile uint32_t RBtIdx = 0;
volatile uint32_t RxBusy = 0;
void uart1_putchar(uint8_t ch)
{
while(TxBusy){;} //等待发送空闲
TxData = ch;TBtIdx = 0;TxBusy = 1;
TIMR_Start(TIMR1);
while(TxBusy){;} //等待发送完成
}
void TIMR1_Handler(void)
{
TIMR_INTClr(TIMR1);
if(TBtIdx == 0){UART_TX_LOW(); }else //起始位
if(TBtIdx < 9){if(TxData&0x1){UART_TX_HIGH();}else{UART_TX_LOW();} TxData>>=1;}else
if(TBtIdx == 9){UART_TX_HIGH();TIMR_Stop(TIMR1);TxBusy = 0;TBtIdx = 0;return;} //停止位
TBtIdx++;
}
void uart1_putbuf(uint8_t *buf,uint32_t len){while(len--){uart1_putchar(*buf++);}}
void uart1_puts(char *str){while(*str){uart1_putchar((int)*str++);}}
void UART1Init(void)
{
GPIO_Init(GPION, PIN19, 0, 1, 0); //GPION.19 配置为输入引脚,开启上拉
GPIO_Init(GPION, PIN18, 1, 0, 0); //GPION.18 配置为输出引脚,推挽输出
GPIO_Init(GPION, PIN17, 1, 0, 0); //GPION.17 配置为输出引脚,推挽输出
GPIO_Init(UART_RX_POINT , 1, 0, 0); //GPIOB.7 配置为输出引脚,推挽输出 用于调试接收采样点
GPIO_SetBit(GPION, PIN18);
GPIO_SetBit(GPION, PIN17);
TIMR_Init(TIMR1, TIMR_MODE_TIMER, (SystemCoreClock/LIN_BPS)*1.00, 1); //每1/LIN_BPS秒钟触发一次中断,用于发送
TIMR_Init(TIMR2, TIMR_MODE_TIMER, (SystemCoreClock/LIN_BPS)*0.99, 1); //每1/LIN_BPS秒钟触发一次中断,用于接收
}
// 主机帧头部分
// 起先是同步间隔段,因为作为主机要连续发送至少13位显性电平,这里用的是STM32自带的库函数,直接调用就行。
void Lin_SendBreak(void)
{
UART_TX_LOW(); //显性电平
DelayUs((1000000*13)/LIN_BPS); //至少13位显性电平
UART_TX_HIGH(); //隐形电平
DelayUs((1000000*1 )/LIN_BPS); //至少01位隐形电平
}
// 接着就是同步段,发送0x55
void Lin_SendSyncSegment(void){uart1_putchar(0x55);}
//然后就是发送PID(protect ID),这里的前六位为ID,后两位为校验位,函数功能为:输入ID,返回PID。
uint8_t Lin_CheckPID(uint8_t id)
{
uint8_t P0 = (((id)^(id>>1)^(id>>2)^(id>>4))&0x01)<<6 ;
uint8_t P1 = ((~((id>>1)^(id>>3)^(id>>4)^(id>>5)))&0x01)<<7 ;
return (id|P0|P1) ;
}
// 该函数体就是单片机作为主机发送的帧头,可以指定ID发送帧头,接收从机返回的数据;也可以发送帧头+数据,让从机接收。
void Lin_Hearder(uint8_t id)
{
Lin_SendBreak();
Lin_SendSyncSegment();
uart1_putchar(Lin_CheckPID(id));
}
// 此段函数功能:输入ID+数据,返回校验和段,里面有调用返回PID函数。诊断帧只能用标准校验这里还没有验证过,因为校验还没有测试。
// 是经典校验还是增强校验,另:诊断帧只能经典校验
uint8_t Lin_Checksum(uint8_t id , uint8_t data[])
{
uint8_t t ;
uint16_t sum ;
sum = data[0];
if(id == 0x3c) // 如果是诊断帧,用经典校验
{
for(t=1;t<8;t++)
{
sum += data[t];
if(sum&0xff00)
{
sum&=0x00ff;
sum+=1;
}
}
sum = ~sum;
return (uint8_t)sum ;
}
for(t=1;t<8;t++)
{
sum += data[t];
if(sum&0xff00)
{
sum&=0x00ff;
sum+=1;
}
}
sum+=Lin_CheckPID(id);
if(sum&0xff00)
{
sum&=0x00ff;
sum+=1;
}
sum = ~sum;
return (uint8_t)sum ;
}
//上面三个函数是单片机无论作为主机还是从机都需要用到的部分,所以在后面进行预编译选择的时候,放到外面。
//这里是主机的响应函数调用。
void Lin_Response(uint8_t id ,uint8_t data[])
{
uart1_putbuf(data,8);
uart1_putchar(Lin_Checksum(id,data));
}
void Lin_MainPutData(uint8_t id,uint8_t *data)
{
Lin_Hearder(id);
Lin_Response(id,data);
}
uint8_t uart1_getchar(void)
{
TIMR_Start(TIMR2);
TBtIdx = 0;RxBusy = 1;
while(RxBusy){;} //等待接收完成
return RxData;
}
void TIMR2_Handler(void)
{
TIMR_INTClr(TIMR2);
if(RBtIdx == 0){}else //起始位
if(RBtIdx < 9){RxData>>=1;GPIO_InvBit(UART_RX_POINT);if(UART_RX_Value()){RxData|=0x80;}GPIO_InvBit(UART_RX_POINT);}else
if(RBtIdx == 9){TIMR_Stop(TIMR2);RxBusy = 0;RBtIdx = 0;return;} //停止位
RBtIdx++;
}
uint8_t Lin_MainGetData(uint8_t id,uint8_t *data)
{
Lin_Hearder(id); //发送命令头
while(UART_RX_Value()){;} //等待起始位
DelayUs((1000000*0.425)/LIN_BPS); //延时半个采样点
for(int i=0;i<8;i++){data=uart1_getchar();} //接收8字节数据
uint8_t ReceiveCheckSum = uart1_getchar(); //接收校验和
uint8_t SumCheck = Lin_Checksum(id,data); //计算校验和
// printf("ReceiveCheckSum & SumCheck: 0x%02x=0x%02x ",ReceiveCheckSum,SumCheck);
if(ReceiveCheckSum == SumCheck) {return 1;} //校验正确
return 0;
}
/*
代码完毕部分内容参考了CSDN上的帖子
*/
最近测试了一个SD5128的驱动,感觉可以 利用M0516LAN的串口来实现,写了一下测试程序,请大家核对一下是否可行。谢谢大家。
附件源码如下:
#include <stdio.h>
#include "M051Series.h"
#include "Driver\DrvSYS.h"
#include "Driver\DrvUART.h"
#include "Driver\DrvGPIO.h"
//SD5128的逻辑0是25%的高75%的低,逻辑1是75%的高25%的低,那就是相当于开始25%是固定低,
//结束的25%是固定高,中间50%与逻辑相同,那么就可以简化为数据1000和1110代表逻辑0和逻辑1;
//SD5128的每个像素是3个字节的RGB数据,结束符是一位的低,25位的高,即可表示为0X7FFFFFFF
//串口UART起始位是低,结束位是高,刚好与上面的SD5128的逻辑相反,那么串口数据用6位,
//UART波形取反相后就能与SD5128的占空比符合,每个字符代表SD5128的两个BIT。编码关系如下:
// __________________________________
// |_ST_| D0 | D1 | D2 | D3 | D4 | D5 | SP |
// 00 | 0 1 1 1 0 1 1 1 | = 0x37
// 01 | 0 1 1 1 0 0 0 1 | = 0x07
// 10 | 0 0 0 1 0 1 1 1 | = 0x34
// 11 | 0 0 0 1 0 0 0 1 | = 0x04
unsigned char BIT2BYTE[4]={0x37,0x07,0x34,0x04}; //BIT2BYTE
unsigned char ENDCODE[4] ={0x7F,0xFF,0xFF,0xFF}; //ENDCODE
int SD5128_Init(void)
{
STR_UART_T sParam;
/* Set UART0 Pin */
DrvGPIO_InitFunction(E_FUNC_UART0);
/* Select UART0 Clock Source From 12Mhz*/
DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,0);
/* Select UART0 Clock Source From PLL*/
// DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,1);
/* UART0 Setting */
sParam.u32BaudRate = 800000; //1000K
sParam.u8cDataBits = DRVUART_DATABITS_6;
sParam.u8cStopBits = DRVUART_STOPBITS_1;
sParam.u8cParity = DRVUART_PARITY_NONE;
sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES;
if(DrvUART_Open(UART_PORT0,&sParam) != E_SUCCESS)
{
printf("UART0 open failed\n");
return FALSE;
}
return TRUE;
}
void SD5128_BYTE(unsigned char *buf,unsigned int length)
{
int i;
while(length--)
{
i=6;
while(i>=0)
{
while(UART0->FSR.TX_FULL == 1);
{
UART0->DATA = BIT2BYTE[(*buf>>i)&0x3];// printf(" 0x%02x",BIT2BYTE[(*buf>>i)&0x3]);
}
i=i-2;
}
buf++;
}
}
void SD5128_Test(void)
{
unsigned int i=0;
unsigned char RGBDATA[3]; //RGB
unsigned int dly;
printf("\n\r\n\r");
printf("*** 9G-M0516 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** 9G-M0516 V1.00 Rebooting ...\n\r\n\r");
SD5128_Init();
while(1)
{
if(i++ > 0xFE) i=0;
RGBDATA[0]=RGBDATA[1]=RGBDATA[2]=i; // printf("\n\ri=%02x |",i);
SD5128_BYTE(RGBDATA,3); // printf(" ||");//send rgbdata
SD5128_BYTE(ENDCODE,4); //send endcode
for(dly=0;dly<50;dly++) DrvSYS_Delay(1000); //delay 50ms
}
}
代码结束。-缥缈九哥设计
一,准备VMWARE+LINUX安装软件包
1,在http://www.ubuntu.com/getubuntu/download
下载Ubuntu 8.04 LTS 的X86的Desktop版本的ISO
http://mirror.lupaworld.com/ubuntu/releases/hardy/ubuntu-8.04.1-desktop-i386.iso
2,在http://www.3ddown.com/soft/33308.htm
下载虚拟机(VMware Workstation) v6.5.0.118166 完整注册版
VMware.Workstation.v6.5.0.118166.exe
Flashget://W0ZMQVNIR0VUXWh0dHA6Ly93d3cuM2Rkb3duLmNvbS9kb3dubG9hZC5hc3A/aWQ9MzMzMDgmZHA9MSZmaWQ9MzJbRkxBU0hHRVRd&1029&1225512051
注意:记得抄下注册码:JU04H-A8Q82-T3J18-4WF67
或者下载注册机VMware.Workstation.v6.5.0.118166-Keygen.rar
3,在http://www.tuola.net/soft/view-1441.html
下载VanDyke SecureCRT v6.0.3 build 311 破解版
http://dl.tuola.net/s/SecureCRT.v6.0.3.rar
4,在ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86/iso/
下载arm-2007-01-21.iso
ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86/iso/arm-2007-01-21.iso
5, 在http://www.crsky.com/soft/2975.html
下载Beyond_Compare_2.5.3.253_SC-special.exe
http://3.scdx1.crsky.com/200807/Beyond_Compare_2.5.3.253_SC-special.exe
二,准备ARM+LINUX开发包
1,在http://www.kernel.org/pub/linux/kernel/v2.6/
下载linux-2.6.26.tar.bz2
http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.26.tar.bz2
2,在ftp://ftp.denx.de/pub/u-boot/
下载u-boot-1.3.4.tar.bz2
ftp://ftp.denx.de/pub/u-boot/u-boot-1.3.4.tar.bz2
3,在http://busybox.net/
下载BusyBox 1.11.1. (svn, patches, how to add a patch)
http://busybox.net/downloads/busybox-1.11.1.tar.bz2
4,在http://www.arm9.net/download.asp
下载Jflash2440 ,一个Linux下Jtag烧写工具(含源代码)
http://www.arm9.com.cn/download/sbc2440v3/Jflash_linux.tgz
5,在http://blog.chinaunix.net/u/24474/showart_227846.html
下载Jflash-s3c2410_linux.tar.bz2
http://blogimg.chinaunix.net/blog/upfile/070107195410.bz2
注意:下载后把文件名改回Jflash-s3c2410_linux.tar.bz2
可参考http://blog.chinaunix.net/u/23070/showart.php?id=157735的
Jflash-s3c2410源码分析(linux).pdf
可参考http://www.datasheetcatalog.org/datasheet2/5/0wd8ohcf4gti5jzkwhd33lhka1ky.pdf
Installation Manual for S3C2440 (linux)
三,安装VMWARE+LINUX开发平台
1,在XP系统上安装VMware-workstation-6.5.0-118166.exe
A,双击VMware-workstation-6.5.0-118166.exe 启动安装,点击NEXT,选择Typical;再NEXT,安装文件夹选择
默认;再NEXT,快捷方式产生用默认;再NEXT,按install;进入安装过程,输入使用者,公司和序列号
JU04H-A8Q82-T3J18-4WF67 ,最后点击finish完成安装,重启动电脑;
B,双击桌面VMware Workstation启动虚拟机程序,选择接受版权许可后点击OK后即可进入虚拟机界面使用;
注意:XP系统需要512MB以上内存,15GB以上硬盘空间。
2,在VMware Workstation上安装ubuntu-8.04.1-desktop的X86版本
A,双击桌面VMware Workstation图标进入虚拟机,点击“New Virtual Machine”启动建立向导;选择Typical;再NEXT;
选择“Install disc image file(iso)”,点击“Browse”找到存储在硬盘上的“ubuntu-8.04.1-desktop-i386.iso”文件;
点击NEXT,在“Virtual Machine name”下面输入虚拟机文件名,在“Location”下面选择虚拟机文件夹安装位置;
点击NEXT,在“Maxinum disk size”上增加到15GB以上,下面选择“Split Virtual disk to 2GB files”;点击NEXT,显示
虚拟机配置信息,确认无误后点击“finish”即可进入安装过程;
B,进入虚拟机的操作系统安装过程中,在“ubuntu-8.04.1-desktop-i386.iso”的安装界面中按F2功能键,用上下箭头选择
“中文(简体)”再按“回车”;用上下箭头选择高亮“安装UBUNTU”时按回车;进入
ubuntu-8.04.1-desktop 的X86版本的LiveCD界面,出现一个7步的“安装”向导;
C,在安装向导上点击“前进”,地点用默认“上海”;点击“前进”,键盘布局用默认“China”;点击“前进”硬盘分区
用默认“向导”,点击“前进”,输入安装用户名和密码;点击“前进”,在“准备安装”中,点击“安装";安装完成
后,点击“现在重启”;并把虚拟机“VM”“Settings”中的“CD/DVD”改回“Use physical drive”;
注意:XP系统需在DHCP的局域网内,要独立分配IP给虚拟机;安装的用户名和密码区别于ROOT用户,每次登陆系统及修改
系统配置都要用到,需要牢记。
四,配置并更新ubuntu桌面系统
1,启动根用户和配置网络
A,进入系统后在启动菜单“应用程序”->“附件”->“终端”拉到桌面上;把启动菜单“位置”中的“计算机”也
拉到桌面上;双击桌面“终端”中打开命令行终端
B,启用root用户并修改密码
yuanxh@yuanxh-desktop:~$ sudo passwd root
C,进入root用户操作
yuanxh@yuanxh-desktop:~$ su
D,查看本机IP配置信息
root@yuanxh-desktop:/home/yuanxh# ifconfig -a
E,在启动菜单“系统”->“系统管理”->“网络”中
填入IP,子域掩码,网关,DNS等网络参数;
F,修改.bashrc启用ll la l等到命令转义
root@yuanxh-desktop:/home/yuanxh# vi /root/.bashrc
root@yuanxh-desktop:/home/yuanxh# source /root/.bashrc
2,安装虚拟驱动Vmware tools
A,进入系统后在虚拟机菜单“VM”中点击“Install Vmware tools”后桌面会弹出一个CD-ROM内容的文件夹,里面有两个
rpm和tar.gz压缩文件包;
B,双击桌面“终端”打开命令行终端,用命令模式安装虚拟驱动:
切换到root用户
yuanxh@yuanxh-desktop:~$ su
建立文件夹
root@yuanxh-desktop:/home/yuanxh# mkdir vm-tools
修改文件夹权限
root@yuanxh-desktop:/home/yuanxh# chmod 777 vm-tools/
进入文件夹
root@yuanxh-desktop:/home/yuanxh# cd vm-tools/
复制虚拟驱动软件包
root@yuanxh-desktop:/home/yuanxh/vm-tools# cp /media/cdrom0/VMwareTools-6.5.0-118166.tar.gz .
解压虚拟驱动文件包
root@yuanxh-desktop:/home/yuanxh/vm-tools# tar xzvf VMwareTools-6.5.0-118166.tar.gz
进入虚拟驱动文件夹
root@yuanxh-desktop:/home/yuanxh/vm-tools# cd vmware-tools-distrib/
运行虚拟驱动安装脚本
root@yuanxh-desktop:/home/yuanxh/vm-tools/vmware-tools-distrib# ./vmware-install.pl
C,一路按回车键,中间如果有一个编译跳不过,就输入N,再回车,直到最后能选择屏幕分辨率大小[15] 1152 X 864,
并且鼠标能自由进入虚拟机和XP之间;
D,给vmtools升级
如果VMware要更新版本的VMware Tools,先卸载旧的vmware tools
root@yuanxh-desktop:/home/yuanxh/vm-tools/vmware-tools-distrib# ./bin/vmware-uninstall-tools.pl
再重新安装新的vmware tools
root@yuanxh-desktop:/home/yuanxh/vm-tools/vmware-tools-distrib# ./vmware-install.pl
3,启用XP与虚拟机系统间的共享文件夹功能
A,在虚拟机菜单“VM”->“settings”中,切换到“options”页;选择到“Shared Folders” 设置,选择“Always enabled”;
点击“Folders”的“Add” 进入“add Shared Folder wizard”;再点击 NEXT,选择共享文件夹的“Host path”和“name”;点击“NEXT”配置好
共享文件夹属性后,点击“Finish”;退出向导,点击“OK”退出设置;
B,在设置好共享文件夹后,并且安装好虚拟驱动后启动虚拟机,便可以在虚拟机中看到共享文件夹的内容;
root@yuanxh-desktop:/home/yuanxh# ls -l /mnt/hgfs
4,为虚拟机增加并口
A,双击桌面VMware Workstation图标进入虚拟机,先不要启动虚拟系统的电源,在虚拟机菜单“VM”->“settings”中,在“Hardware”页;
点击窗口下面的“Add...” 进入“add Hardware wizard”;在Hardware Type 中选择“Parallel Port”;再点击 NEXT,在Parallel Port Type
中选择默认的“Use physicial parallel port on the host”;再点击 NEXT,在physicial parallel port 中选择“LPT1”或者用“Auto detect”,
在Device status 中选择上“Connect at power on”;最后点击“Finish”完成配置,点击“OK”退出添加硬件向导。
B,然后打开虚拟机电源,进入虚拟Linux系统,就可以使用并口了。其它串口中,USB口增加方式类似。
4,更新软件包服务器源后更新升级系统并安装SSH和ZMODEM协议
A,切换到root用户后执行以下命令更新升级系统:
网络更新系统
root@yuanxh-desktop:/home/yuanxh# apt-get update
网络升级系统
root@yuanxh-desktop:/home/yuanxh# apt-get upgrade
B,网络安装SSH客户端和服务器端
root@yuanxh-desktop:/home/yuanxh# apt-get install ssh openssh-server
只有安装了这个才能用SecureCRT远程终端SSH访问系统
C,用以下命令查找并安装ZMMODEM协议支持软件包:
查找rzsz相关软件包
root@yuanxh-desktop:~# apt-cache search rzsz
显示lrzsz软件包详细情况
root@yuanxh-desktop:~# apt-cache show lrzsz
网络安装zmodem传输协议
root@yuanxh-desktop:/home/yuanxh# apt-get install lrzsz
查看网络下载软件包存放目录
root@yuanxh-desktop:/home/yuanxh# ll /var/cache/apt/archives/
D,安装开发必需软件包
root@yuanxh-desktop:/usr/local/arm# apt-get install patch libncurses5-dev make rpm
5,安装SecureCRT远程终端SSH访问虚拟机和启用SFTP文件传输功能
A,双击SecureCRT.v6.0.3.rar里的scrt603.exe,点击“NEXT”;选择“接受协议”,再点击“NEXT”;用默认配置文件,点击“NEXT”
后选择“Complete”;点击“NEXT”后产生快捷方式用默认;点击“Install”后进行安装,点击“Finish”完成安装;
B,把SecureCRT.v6.0.3.rar里的scrt603-tbe.exe解压到安装目录并运行,点击“patch”,然后对“SecureCRT.exe”破解30天限制使用
权限;
C,利用SecureCRT的向导建立一个SSH会话到虚拟机;“下一步”后输入虚拟机IP地址和登陆用户名,建立好后双击会话SSH登陆LINUX,
在会话属性中可配置终端类型,字体,滚屏行数,字符编码,XMODEM和SFTP默认路径等;
D,建立了到LINUX的SSH会话后,在Version 6.0.3 界面的菜单“File”->“Connect SFTP Tab”可启动到相应的LINUX的SFTP连接,
在SFTP标签中输入“help”可以查看相关的SFTP命令。
五,建立FTP,NFS和交叉编译环境
1,用命令配置TFTP服务
A, 建立TFTP系统根目录并修改权限
root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir /tftpboot
root@yuanxh-desktop:/home/yuanxh/at91_works# chmod 777 /tftpboot
B,安装TFTP服务器端和客户端
root@yuanxh-desktop:/# sudo apt-get install tftp tftpd openbsd-inetd
C,修改配置文件使用TFTP根目录
root@yuanxh-desktop:/home/yuanxh/at91_works# vi /etc/inetd.conf
在/etc/inetd.conf如下行中,后面路径改成/tftpboot
tftp dgram udp wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd /tftpboot
D,启动服务
root@yuanxh-desktop:/home/yuanxh/at91_works# /etc/init.d/openbsd-inetd restart
E,测试服务
root@yuanxh-desktop:/home/yuanxh# touch /tftpboot/aaa
root@yuanxh-desktop:/home/yuanxh# vi /tftpboot/aaa
root@yuanxh-desktop:/home/yuanxh# tftp 192.168.1.100
tftp> get aaa
tftp> quit
root@yuanxh-desktop:/home/yuanxh# cat aaa
2,用命令配置NFS服务
A,安装NFS服务器端
root@yuanxh-desktop:/home/yuanxh# apt-get install nfs-kernel-server nfs-common portmap
B,配置访问目录及权限
root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir /nfsboot
root@yuanxh-desktop:/home/yuanxh/at91_works# chmod 777 /nfsboot
root@yuanxh-desktop:/home/yuanxh/at91_works# touch /nfsboot/yuanxh
root@yuanxh-desktop:/# vi /etc/exports
在/etc/exports新行中填入以下内容
/nfsboot *(rw,sync)
C,启动服务
root@yuanxh-desktop:/# exportfs -ra
root@yuanxh-desktop:/# /etc/init.d/portmap restart
root@yuanxh-desktop:/# /etc/init.d/nfs-common restart
root@yuanxh-desktop:/# /etc/init.d/nfs-kernel-server restart
D,测试服务
root@yuanxh-desktop:/# mount 192.168.1.100:/nfsboot /mnt
root@yuanxh-desktop:/home/yuanxh# ll /mnt
root@yuanxh-desktop:/home/yuanxh# rm -rf /mnt/yuanxh
root@yuanxh-desktop:/home/yuanxh# showmount
root@yuanxh-desktop:/home/yuanxh# df
root@yuanxh-desktop:/home/yuanxh# umount /mnt
root@yuanxh-desktop:/home/yuanxh# ll /nfsboot
3,安装交叉编译工具链
A,利用SecureCRT.v6.0.3登陆,传送文件到系统
root@yuanxh-desktop:/home/yuanxh# mkdir /usr/local/arm
root@yuanxh-desktop:/home/yuanxh# chmod 777 /usr/local/arm/
root@yuanxh-desktop:/home/yuanxh# cd /usr/local/arm/
root@yuanxh-desktop:/usr/local/arm# rz
在SecureCRT弹出的窗口中选择交叉编译工具安装包arm-2007-01-21.iso
B,安装ELDK交叉编译工具
root@yuanxh-desktop:/usr/local/arm# cd /usr/local/
root@yuanxh-desktop:/usr/local# mkdir eldk-4.1
root@yuanxh-desktop:/usr/local# mount –o loop –t iso9660 arm-2007-01-21.iso /mnt/cdrom
root@yuanxh-desktop:/usr/local# cp -av /mnt/cdrom/* eldk-4.1/
root@yuanxh-desktop:/usr/local# cd eldk-4.1
root@yuanxh-desktop:/usr/local/eldk-4.1# chmod 777 install
root@yuanxh-desktop:/usr/local/eldk-4.1# ./install -d /usr/local/arm/eldk-4.1
注意:eldk-4.1在ubuntu-8.04安装的rpm工具版本有问题,处理方法请查看
http://lists.denx.de/pipermail/eldk/2008-July/000280.html
在http://mirror.oss.lzu.edu.cn/software/embedded/eldk/4.2/ppc-linux-x86/distribution/RPMS/
中下载rpm-4.4.2-46.i386.rpm ,rpm-build-4.4.2-46.i386.rpm,rpm-devel-4.4.2-46.i386.rpm
在RPMS中增加rpm-4.4.2-46.i386.rpm ,rpm-build-4.4.2-46.i386.rpm,并在etc/rpm_cross.list 前两行中修改启用再安装。
D,把编译器路径添加到系统路径中
root@yuanxh-desktop:/usr/local/arm# vi /root/.bashrc
在alias l='ls -CF'后的空白处填上:
PATH=$PATH:/usr/local/arm/eldk-4.1/usr/bin:/usr/local/arm/eldk-4.1/bin
export PATH
启动新系统路径
root@yuanxh-desktop:/usr/local/arm# source /root/.bashrc
显示新系统路径
root@yuanxh-desktop:/usr/local/arm# echo $PATH
查看版本号
root@yuanxh-desktop:/usr/local/arm# arm-linux-gcc -v
六,编译U-BOOT启动代码
1,传送文件包到LINUX系统并解压
A,利用SecureCRT.v6.0.3登陆,传送文件到系统
root@yuanxh-desktop:/home/yuanxh# mkdir s3c2410
root@yuanxh-desktop:/home/yuanxh# chmod 777 s3c2410/
root@yuanxh-desktop:/home/yuanxh# cd s3c2410/
root@yuanxh-desktop:/home/yuanxh/s3c2410# rz
在SecureCRT弹出的窗口中选择u-boot-1.3.4.tar.bz2软件包
B,解压软件包
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xjvf u-boot-1.3.4.tar.bz2
2,编译生成U-BOOT启动目标码
A,进入U-BOOT源码树
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd u-boot-1.3.4
B,指定编译器
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# vi Makefile
把CROSS_COMPILE = arm-linux- 改成 CROSS_COMPILE=/usr/local/arm/eldk-4.1/usr/bin/arm-linux-
C,配置并编译
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make clean
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make mrproper
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make smdk2410_config
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# mv u-boot.bin u-boot-smdk2410.bin
D,发送目标码
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# sz u-boot-smdk2410.bin
3,编译生成Jflash工具
A,利用SecureCRT.v6.0.3登陆,传送文件到系统
root@yuanxh-desktop:/home/yuanxh/s3c2410# rz
在SecureCRT弹出的窗口中选择Jflash-s3c2410_linux.tar.bz2软件包
root@yuanxh-desktop:/home/yuanxh/s3c2410# mkdir Jflash-9gs3c2410
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd Jflash-9gs3c2410
B,解压软件包
root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# tar xvjf ../Jflash-s3c2410_linux.tar.bz2
C,在系统内指定内核头文件和体系结构头文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# cd /usr/src
root@yuanxh-desktop:/usr/src# ln -s linux-headers-2.6.24-19/ linux
root@yuanxh-desktop:/usr/src# cd linux/include
root@yuanxh-desktop:/usr/src/linux/include# ln -s asm-x86/ asm
D,在Makefile指定内核头文件和体系结构头文件路径
root@yuanxh-desktop:/usr/src/linux/include# cd /home/yuanxh/s3c2410/Jflash-9gs3c2410/
root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# vi Makefile
在 Makefile 的CFLAGS = -O2 -s -D__LINUX__ 后面添加上 -I/usr/src/linux/include/ 并保存退出
E,编译SJF生成目标码Jflash-s3c2410并执行
root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# make
root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# ./Jflash-s3c2410
F,同样的原理,用Jflash_linux.tgz,生成 Jflash-s3c2440 工具
4,用SJF工具烧启动代码到GEC2440开发板
A,按前面所说添加并口给虚拟机用,并把GEC2410_jtag V1.1 板的JP1并口与电脑并口接上,JP2的JTAG_2410口连接到GEC2440核心板
开发板的J10的脚的标准JTAG口上,并打开开发板电源;
B,在Linux上运行:
./Jflash-s3c2440 u-boot-smdk2410.bin /t=5 /d=10
如果连接上了会显示 S3C2440X(ID=0x0032409d) is detected.
C,在[K9S1208 NAND Flash JTAG Programmer]界面,K9S1208 is detected. ID=0xec76 会检测显示出来,
在Select the function to test : 后输入0 并回车,确定0:K9S1208 Program 的功能;
D,在[SMC(K9S1208V0M) NAND Flash Writing Program]界面,Available target block number: 0~4095 会显示出来,
在Input target block number: 后输入0 并回车,确定写入FLASH的首地址;
E,最后会在STATUS:后显示烧写过程Epppppppppppppppppppppppppppppppp好几行,基本是15秒种一个P,直到烧写完毕;
F,烧写完毕后显示0:K9S1208 Program 1:K9S1208 Pr BlkPage 2:Exit 时在 Select the function to test :
后输入2并回车退出烧录工具。
5,移植u-boot-1.3.4到GEC2440开发板
A,修改Makefile
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board# vi Makefile
在Makefile中的EXTRAVERSION = 后添加 -gec2440
在Makefile中的smdk2410_config后增加如下两行:
gec2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t gec2440 NULL s3c24x0
B,在/board中添加GEC2440板定义
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# cd board/
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board# cp -av smdk2410/ gec2440
修改源文件和Makefile
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board# cd gec2440/
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board/gec2440# mv smdk2410.c gec2440.c
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board/gec2440# vi Makefile
把COBJS := smdk2410.o flash.o 改成 COBJS := gec2440.o flash.o
C,在include/configs/中建立配置头文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board/gec2440# cd ../../include/configs/
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/include/configs# cp smdk2410.h gec2440.h
D,试编译GEC2440开发板的U-BOOT目标码
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/include/configs# cd ../../
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make mrproper
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make clean
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make distclean
root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make gec2440_config
E,修改压缩成u-boot-1.3.4-gev2440.tar.gz
root@yuanxh-desktop:/home/yuanxh/s3c2410# mv u-boot-1.3.4 u-boot-1.3.4-gev2440
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar czvf u-boot-1.3.4-gev2440.tar.gz u-boot-1.3.4-gev2440/
root@yuanxh-desktop:/home/yuanxh/s3c2410# sz u-boot-1.3.4-gev2440.tar.gz
6,修改u-boot-1.3.4-gev2440.tar.gz源码
A,修改include/configs/gec2440.h 文件
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd u-boot-1.3.4-gev2440/include/configs/
把
#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
修改
#define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
#define CONFIG_GEC2440 1 /* on a SAMSUNG GEC2440 Board */
(调试完毕,但笔记尚未整理完成)
七,为S3C2410编译ARM-LINUX内核
1,传送文件包到LINUX系统并解压
利用SecureCRT 登陆,传送文件到系统
root@yuanxh-desktop:/home/yuanxh# cd s3c2410/
root@yuanxh-desktop:/home/yuanxh/s3c2410# rz
在SecureCRT弹出的窗口中选择linux-2.6.26.tar.bz2包;
2,解压内核
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xjvf linux-2.6.26.tar.bz2
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd linux-2.6.26
3,为内核指定编译器
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# vi Makefile
把 EXTRAVERSION = -9gs3c2410 写上自己版本标识,指定体系结构和编译器
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/eldk-4.1/usr/bin/arm-linux-
添加可加载模块安装路径
INSTALL_MOD_PATH = $(TOPDIR)/modules-$(KERNELRELEASE)
4,编译内核及发布目标码
A,查看内核支持的开发板
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make help
B,配置为S3C2410板默认设置
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make s3c2410_defconfig
C,编译生成全部目标码
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make
D,也可分步依次生成zImage,可加载modules和安装可加载模拟到默认目录
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make zImage
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make modules
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make modules_install
E,发送内核目标码和可加载模块
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# cp arch/arm/boot/zImage .
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# mv zImage zImage-2.6.26-gec2440.bin
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# sz zImage-2.6.26-gec2440.bin
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# tar czvf modules-2.6.26-gec2440.tar.gz modules-2.6.26-gec2440/
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# sz modules-2.6.26-gec2440.tar.gz
F,个性化配置内核
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make menuconfig
.config中内核启动命令行参数CONFIG_CMDLINE改为:
mem=64M console=ttySAC0,115200 initrd=0x32000000,8388608 root=/dev/ram0 rw init=/linuxrc
G,编译生成U-BOOT可识别目标码uImage
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make uImage
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# cp arch/arm/boot/uImage .
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# mv uImage uImage-2.6.26-gec2440.bin
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# sz uImage-2.6.26-gec2440.bin
5,清除内核目标码恢复未配置状态
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make clean
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make distclean
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make mrproper
6,修改linux-2.6.26代码适合GEC2440开发板
A,修改初时钟始化
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# vi arch/arm/mach-s3c2440/mach-smdk2440.c
注释掉原来的时钟初始化函数:
// s3c24xx_init_clocks(16934400); // charge by yuanxihua@21cn.com
增加上新的时钟初始化定义:
s3c24xx_init_clocks(12000000);
B,重新编译内核
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# ./mkall
执行的脚本内容如下:
#!/bin/sh
#make by yuanxihua@21cn.com for GEC2440
#make s3c2410_defconfig
make
make uImage
cp arch/arm/boot/uImage uImage-2.6.26-9g24x0.bin
cp uImage-2.6.26-9g24x0.bin /tftpboot
make modules_install INSTALL_MOD_PATH=./modules-2.6.26-9g24x0
tar czvf modules-2.6.26-9g24x0.tar.gz ./modules-2.6.26-9g24x0
cp modules-2.6.26-9g24x0.tar.gz /tftpboot
C,修改网络CS8900问题
修改Kconfig
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# cd drivers/net/
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0/drivers/net# vi Kconfig
(调试完毕,但笔记尚未整理完成)
D,修改LCD驱动问题
C文件
/********************************************************************************/
/* @file ad7124.c */
/* @version V1.00 */
/* $author: yuanxihua@21cn.com */
/* $Date: 2019/03/04 02:54 $ */
/* @brief SWM320RBT6 Series AD7124 Driver Sample Code */
/* */
/* @note */
/* Copyright (C) 2010-2019 PM9GZY Technology Corp. All rights reserved. */
/* */
/********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "ad7124.h"
/*
_________________________________________________
| SWM320RBT6 AD7124 |
| |
| PP1 MISO1 <---- MISO |
| PP2 MOSI1 ----> MOSI |
| PP3 SCLK1 ----> SCLK |
| PP4 NSS1 ----> ANCS |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define AD7124_CS_L() GPIO_ClrBit(GPIOP, PIN4)
#define AD7124_CS_H() GPIO_SetBit(GPIOP, PIN4)
/* Private macro -------------------------------------------------------------*/
#define INVALID_VAL -1 /* Invalid argument */
#define COMM_ERR -2 /* Communication error on receive */
#define TIMEOUT -3 /* A timeout has occured */
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void AD7124_Init(void);
void AD7124_Reset(void);
/* Private functions ---------------------------------------------------------*/
void SPI1Init(void)
{
SPI_InitStructure SPI_initStruct;
PORT_Init(PORTP, PIN1, FUNMUX1_SPI1_MISO, 1);
PORT_Init(PORTP, PIN2, FUNMUX0_SPI1_MOSI, 0);
PORT_Init(PORTP, PIN3, FUNMUX1_SPI1_SCLK, 0);
GPIO_Init(GPIOP, PIN4, 1, 0, 0);AD7124_CS_H();//PORT_Init(PORTP, PIN4, FUNMUX0_SPI1_SSEL, 0);
SPI_initStruct.clkDiv = SPI_CLKDIV_64;//0.52US
SPI_initStruct.FrameFormat = SPI_FORMAT_SPI;
SPI_initStruct.SampleEdge = SPI_FIRST_EDGE;
SPI_initStruct.IdleLevel = SPI_LOW_LEVEL;
SPI_initStruct.WordSize = 8;
SPI_initStruct.Master = 1;
SPI_initStruct.RXHFullIEn = 0;
SPI_initStruct.TXEmptyIEn = 0;
SPI_initStruct.TXCompleteIEn = 0;
SPI_Init(SPI1, &SPI_initStruct);
SPI_Open(SPI1);
AD7124_Reset();
AD7124_Init();
}
void AD7124_Read_Register(ad7124_reg_t *reg)
{
uint8_t cmd=reg->addr+0x40,width=reg->size,admit=reg->rw;uint32_t val=0;
if(!(admit&AD7124_RO)){return;}
AD7124_CS_L();
SPI_ReadWrite(SPI1,cmd);while(width--){val<<=8;val|=SPI_ReadWrite(SPI1,0x55)&0xff;}reg->value=val;
AD7124_CS_H();
}
void AD7124_Write_Register(ad7124_reg_t *reg)
{
uint8_t cmd=reg->addr+0x00,width=reg->size,admit=reg->rw;uint32_t val=reg->value;
if(!(admit&AD7124_WO)){return;}
AD7124_CS_L();
SPI_ReadWrite(SPI1,cmd);while(width--){SPI_ReadWrite(SPI1,(val>>(width*8))&0xff);}
AD7124_CS_H();
}
void AD7124_Reset(void){AD7124_CS_L();for(uint8_t i=0;i<8;i++){SPI_ReadWrite(SPI1,0xFF);}AD7124_CS_H();osDelay(10);}
void AD7124_Init(void){for(uint8_t i=AD7124_Status;i<AD7124_REG_END;i++){AD7124_Write_Register(&ad7124_regs[i]);}}
uint8_t AD7124_CRC8(uint8_t *buf, uint8_t len)
{
uint8_t i,crc=0,MULA=AD7124_CRC8_POLYNOMIAL_REPRESENTATION;
while(len--){for(i=0x80;i!=0;i>>=1){if(((crc&0x80)!=0)!=((*buf&i)!=0)){crc<<=1;crc^=MULA;}else{crc<<=1;}}buf++;}
return crc;
}
void AD7124_Gain(void){}
uint8_t AD7124_Read(uint32_t *data)
{
int32_t timeout=1000000;uint8_t total=0;
uint8_t lastch=20;uint8_t nowch=20;
while(1)
{
while(--timeout)
{
/* Read the value of the Status Register */
AD7124_Read_Register(&ad7124_regs[AD7124_Status]);
/* Check the RDY bit in the Status Register */
if((ad7124_regs[AD7124_Status].value & AD7124_STATUS_REG_RDY)==0)
{nowch = AD7124_STATUS_REG_CH_ACTIVE(ad7124_regs[AD7124_Status].value);break;}
}
if(timeout<=0){printf("AD Conv Timeout!!!\n\r");return total;}
if(lastch!=nowch)
{
/* Read the value of the Data Register */
AD7124_Read_Register(&ad7124_regs[AD7124_Data]);
/* Get the read result */
data[nowch] = ad7124_regs[AD7124_Data].value; data[nowch]&=0xFFFFFF;
lastch=nowch;total++;
// printf("AD7124_Read data[%d] = 0x%08x \n\r",nowch,data[nowch]);
}
if(total>=4){break;}
}
return total;
}
void AD7124_Test(void)
{
uint32_t adc[4]={0};float val[4];
// AD7124_CS_L(); SPI_ReadWrite(SPI1,0x55);AD7124_CS_H();
// AD7124_Read_Register(&ad7124_regs[AD7124_ID]);
// printf("AD7124_ID = 0x%02x \n\r",ad7124_regs[AD7124_ID].value);
// AD7124_Read_Register(&ad7124_regs[AD7124_CHANNEL_0]);
// printf("AD7124_CHANNEL_0 = 0x%08x \n\r",ad7124_regs[AD7124_CHANNEL_0].value);
// ad7124_regs[AD7124_FILTER_0].value=0x555555;
// AD7124_Write_Register(&ad7124_regs[AD7124_FILTER_0]);
// AD7124_Read_Register(&ad7124_regs[AD7124_FILTER_0]);
// printf("AD7124_FILTER_0 = 0x%08x \n\r",ad7124_regs[AD7124_FILTER_0].value);
// for(uint8_t i=AD7124_Status;i<AD7124_REG_END;i++)
// {
// AD7124_Read_Register(&ad7124_regs[i]);
// printf("ad7124_regs[0x%02x]=0x%08x \n\r",i,ad7124_regs[i].value);
// }
AD7124_Read(adc);
// printf("ADC[0]=0x%08x,ADC[1]=0x%08x,ADC[2]=0x%08x,ADC[3]=0x%08x\n\r",adc[0],adc[1],adc[2],adc[3]);
for(uint8_t i=0;i<4;i++)
{
val[i]=adc[i];val[i]*=2.500;val[i]/=0xffffff;
}
val[0]/=128;val[1]/=16;val[2]/=4;val[3]/=1;
// printf("VAL[0]=%3.10f V\n\r",val[0]);
// printf("VAL[1]=%3.10f V\n\r",val[1]);
// printf("VAL[2]=%3.10f V\n\r",val[2]);
// printf("VAL[3]=%3.10f V\n\r",val[3]);
// val[0]*=1000;val[1]*=1000;val[2]*=1000;val[3]*=1000;
printf("%3.10f,%3.10f,%3.10f,%3.10f\n\r",val[0],val[1],val[2],val[3]);
OLED_Volute(val);
osDelay(200);
}
H文件
#ifndef __AD7124_H__
#define __AD7124_H__
#define AD7124_CRC8_POLYNOMIAL_REPRESENTATION 0x07 /* x8 + x2 + x + 1 */
#define AD7124_WO 1 /* Write */
#define AD7124_RO 2 /* Read */
#define AD7124_RW 3 /* Read and Write */
/* AD7124 Register Map */
#define AD7124_COMM_REG 0x00
#define AD7124_STATUS_REG 0x00
#define AD7124_ADC_CTRL_REG 0x01
#define AD7124_DATA_REG 0x02
#define AD7124_IO_CTRL1_REG 0x03
#define AD7124_IO_CTRL2_REG 0x04
#define AD7124_ID_REG 0x05
#define AD7124_ERR_REG 0x06
#define AD7124_ERREN_REG 0x07
#define AD7124_CH0_MAP_REG 0x09
#define AD7124_CH1_MAP_REG 0x0A
#define AD7124_CH2_MAP_REG 0x0B
#define AD7124_CH3_MAP_REG 0x0C
#define AD7124_CH4_MAP_REG 0x0D
#define AD7124_CH5_MAP_REG 0x0E
#define AD7124_CH6_MAP_REG 0x0F
#define AD7124_CH7_MAP_REG 0x10
#define AD7124_CH8_MAP_REG 0x11
#define AD7124_CH9_MAP_REG 0x12
#define AD7124_CH10_MAP_REG 0x13
#define AD7124_CH11_MAP_REG 0x14
#define AD7124_CH12_MAP_REG 0x15
#define AD7124_CH13_MAP_REG 0x16
#define AD7124_CH14_MAP_REG 0x17
#define AD7124_CH15_MAP_REG 0x18
#define AD7124_CFG0_REG 0x19
#define AD7124_CFG1_REG 0x1A
#define AD7124_CFG2_REG 0x1B
#define AD7124_CFG3_REG 0x1C
#define AD7124_CFG4_REG 0x1D
#define AD7124_CFG5_REG 0x1E
#define AD7124_CFG6_REG 0x1F
#define AD7124_CFG7_REG 0x20
#define AD7124_FILT0_REG 0x21
#define AD7124_FILT1_REG 0x22
#define AD7124_FILT2_REG 0x23
#define AD7124_FILT3_REG 0x24
#define AD7124_FILT4_REG 0x25
#define AD7124_FILT5_REG 0x26
#define AD7124_FILT6_REG 0x27
#define AD7124_FILT7_REG 0x28
#define AD7124_OFFS0_REG 0x29
#define AD7124_OFFS1_REG 0x2A
#define AD7124_OFFS2_REG 0x2B
#define AD7124_OFFS3_REG 0x2C
#define AD7124_OFFS4_REG 0x2D
#define AD7124_OFFS5_REG 0x2E
#define AD7124_OFFS6_REG 0x2F
#define AD7124_OFFS7_REG 0x30
#define AD7124_GAIN0_REG 0x31
#define AD7124_GAIN1_REG 0x32
#define AD7124_GAIN2_REG 0x33
#define AD7124_GAIN3_REG 0x34
#define AD7124_GAIN4_REG 0x35
#define AD7124_GAIN5_REG 0x36
#define AD7124_GAIN6_REG 0x37
#define AD7124_GAIN7_REG 0x38
/* Communication Register bits */
#define AD7124_COMM_REG_WEN (0 << 7)
#define AD7124_COMM_REG_WR (0 << 6)
#define AD7124_COMM_REG_RD (1 << 6)
#define AD7124_COMM_REG_RA(x) ((x) & 0x3F)
/* Status Register bits */
#define AD7124_STATUS_REG_RDY (1 << 7)
#define AD7124_STATUS_REG_ERROR_FLAG (1 << 6)
#define AD7124_STATUS_REG_POR_FLAG (1 << 4)
#define AD7124_STATUS_REG_CH_ACTIVE(x) ((x) & 0xF)
/* ADC_Control Register bits */
#define AD7124_ADC_CTRL_REG_DOUT_RDY_DEL (1 << 12)
#define AD7124_ADC_CTRL_REG_CONT_READ (1 << 11)
#define AD7124_ADC_CTRL_REG_DATA_STATUS (1 << 10)
#define AD7124_ADC_CTRL_REG_CS_EN (1 << 9)
#define AD7124_ADC_CTRL_REG_REF_EN (1 << 8)
#define AD7124_ADC_CTRL_REG_POWER_MODE(x) (((x) & 0x3) << 6)
#define AD7124_ADC_CTRL_REG_MODE(x) (((x) & 0xF) << 2)
#define AD7124_ADC_CTRL_REG_CLK_SEL(x)) (((x) & 0x3) << 0)
/* IO_Control_1 Register bits */
#define AD7124_IO_CTRL1_REG_GPIO_DAT2 (1 << 23)
#define AD7124_IO_CTRL1_REG_GPIO_DAT1 (1 << 22)
#define AD7124_IO_CTRL1_REG_GPIO_CTRL2 (1 << 19)
#define AD7124_IO_CTRL1_REG_GPIO_CTRL1 (1 << 18)
#define AD7124_IO_CTRL1_REG_PDSW (1 << 15)
#define AD7124_IO_CTRL1_REG_IOUT1(x) (((x) & 0x7) << 11)
#define AD7124_IO_CTRL1_REG_IOUT0(x) (((x) & 0x7) << 8)
#define AD7124_IO_CTRL1_REG_IOUT_CH1(x) (((x) & 0xF) << 4)
#define AD7124_IO_CTRL1_REG_IOUT_CH0(x) (((x) & 0xF) << 0)
/*IO_Control_1 AD7124-8 specific bits */
#define AD7124_8_IO_CTRL1_REG_GPIO_DAT4 (1 << 23)
#define AD7124_8_IO_CTRL1_REG_GPIO_DAT3 (1 << 22)
#define AD7124_8_IO_CTRL1_REG_GPIO_DAT2 (1 << 21)
#define AD7124_8_IO_CTRL1_REG_GPIO_DAT1 (1 << 20)
#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL4 (1 << 19)
#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL3 (1 << 18)
#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL2 (1 << 17)
#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL1 (1 << 16)
/* IO_Control_2 Register bits */
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS7 (1 << 15)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS6 (1 << 14)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS5 (1 << 11)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS4 (1 << 10)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS3 (1 << 5)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS2 (1 << 4)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS1 (1 << 1)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS0 (1 << 0)
/*IO_Control_2 AD7124-8 specific bits */
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS15 (1 << 15)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS14 (1 << 14)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS13 (1 << 13)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS12 (1 << 12)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS11 (1 << 11)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS10 (1 << 10)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS9 (1 << 9)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS8 (1 << 8)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS7 (1 << 7)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS6 (1 << 6)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS5 (1 << 5)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS4 (1 << 4)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS3 (1 << 3)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS2 (1 << 2)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS1 (1 << 1)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS0 (1 << 0)
/* ID Register bits */
#define AD7124_ID_REG_DEVICE_ID(x) (((x) & 0xF) << 4)
#define AD7124_ID_REG_SILICON_REV(x) (((x) & 0xF) << 0)
/* Error Register bits */
#define AD7124_ERR_REG_LDO_CAP_ERR (1 << 19)
#define AD7124_ERR_REG_ADC_CAL_ERR (1 << 18)
#define AD7124_ERR_REG_ADC_CONV_ERR (1 << 17)
#define AD7124_ERR_REG_ADC_SAT_ERR (1 << 16)
#define AD7124_ERR_REG_AINP_OV_ERR (1 << 15)
#define AD7124_ERR_REG_AINP_UV_ERR (1 << 14)
#define AD7124_ERR_REG_AINM_OV_ERR (1 << 13)
#define AD7124_ERR_REG_AINM_UV_ERR (1 << 12)
#define AD7124_ERR_REG_REF_DET_ERR (1 << 11)
#define AD7124_ERR_REG_DLDO_PSM_ERR (1 << 9)
#define AD7124_ERR_REG_ALDO_PSM_ERR (1 << 7)
#define AD7124_ERR_REG_SPI_IGNORE_ERR (1 << 6)
#define AD7124_ERR_REG_SPI_SLCK_CNT_ERR (1 << 5)
#define AD7124_ERR_REG_SPI_READ_ERR (1 << 4)
#define AD7124_ERR_REG_SPI_WRITE_ERR (1 << 3)
#define AD7124_ERR_REG_SPI_CRC_ERR (1 << 2)
#define AD7124_ERR_REG_MM_CRC_ERR (1 << 1)
/* Error_En Register bits */
#define AD7124_ERREN_REG_MCLK_CNT_EN (1 << 22)
#define AD7124_ERREN_REG_LDO_CAP_CHK_TEST_EN (1 << 21)
#define AD7124_ERREN_REG_LDO_CAP_CHK(x) (((x) & 0x3) << 19)
#define AD7124_ERREN_REG_ADC_CAL_ERR_EN (1 << 18)
#define AD7124_ERREN_REG_ADC_CONV_ERR_EN (1 << 17)
#define AD7124_ERREN_REG_ADC_SAT_ERR_EN (1 << 16)
#define AD7124_ERREN_REG_AINP_OV_ERR_EN (1 << 15)
#define AD7124_ERREN_REG_AINP_UV_ERR_EN (1 << 14)
#define AD7124_ERREN_REG_AINM_OV_ERR_EN (1 << 13)
#define AD7124_ERREN_REG_AINM_UV_ERR_EN (1 << 12)
#define AD7124_ERREN_REG_REF_DET_ERR_EN (1 << 11)
#define AD7124_ERREN_REG_DLDO_PSM_TRIP_TEST_EN (1 << 10)
#define AD7124_ERREN_REG_DLDO_PSM_ERR_ERR (1 << 9)
#define AD7124_ERREN_REG_ALDO_PSM_TRIP_TEST_EN (1 << 8)
#define AD7124_ERREN_REG_ALDO_PSM_ERR_EN (1 << 7)
#define AD7124_ERREN_REG_SPI_IGNORE_ERR_EN (1 << 6)
#define AD7124_ERREN_REG_SPI_SCLK_CNT_ERR_EN (1 << 5)
#define AD7124_ERREN_REG_SPI_READ_ERR_EN (1 << 4)
#define AD7124_ERREN_REG_SPI_WRITE_ERR_EN (1 << 3)
#define AD7124_ERREN_REG_SPI_CRC_ERR_EN (1 << 2)
#define AD7124_ERREN_REG_MM_CRC_ERR_EN (1 << 1)
/* Channel Registers 0-15 bits */
#define AD7124_CH_MAP_REG_CH_ENABLE (1 << 15)
#define AD7124_CH_MAP_REG_SETUP(x) (((x) & 0x7) << 12)
#define AD7124_CH_MAP_REG_AINP(x) (((x) & 0x1F) << 5)
#define AD7124_CH_MAP_REG_AINM(x) (((x) & 0x1F) << 0)
/* Configuration Registers 0-7 bits */
#define AD7124_CFG_REG_BIPOLAR (1 << 11)
#define AD7124_CFG_REG_BURNOUT(x) (((x) & 0x3) << 9)
#define AD7124_CFG_REG_REF_BUFP (1 << 8)
#define AD7124_CFG_REG_REF_BUFM (1 << 7)
#define AD7124_CFG_REG_AIN_BUFP (1 << 6)
#define AD7124_CFG_REG_AINN_BUFM (1 << 5)
#define AD7124_CFG_REG_REF_SEL(x) ((x) & 0x3) << 3
#define AD7124_CFG_REG_PGA(x) (((x) & 0x7) << 0)
/* Filter Register 0-7 bits */
#define AD7124_FILT_REG_FILTER(x) (((x) & 0x7) << 21)
#define AD7124_FILT_REG_REJ60 (1 << 20)
#define AD7124_FILT_REG_POST_FILTER(x) (((x) & 0x7) << 17)
#define AD7124_FILT_REG_SINGLE_CYCLE (1 << 16)
#define AD7124_FILT_REG_FS(x) (((x) & 0x7FF) << 0)
/*! Device register info */
typedef struct
{
uint8_t addr;
int32_t value;
uint8_t size;
uint8_t rw;
}ad7124_reg_t;
/*! Array holding the info for the ad7124 registers - address, initial value,
size and access type. */
ad7124_reg_t ad7124_regs[] =
{
{0x00, 0x00, 1, AD7124_RO}, /* AD7124_Status */
//使能DATA_STATUS、REF_EN 和 FULL POWER的连续采样模式,禁止用DOUT_RDY_DEL、CONT_READ和CS_EN,内时钟CLK无输出
{0x01, 0x0580, 2, AD7124_RW}, /* AD7124_ADC_Control */
{0x02, 0x000000, 3, AD7124_RO}, /* AD7124_Data */
//禁用IOUT0、IOUT1、不用PDSW低边桥开关
{0x03, 0x000000, 3, AD7124_RW}, /* AD7124_IOCon1 */
//禁用VBIAS0-VBIAS7
{0x04, 0x0000, 2, AD7124_RW}, /* AD7124_IOCon2 */
{0x05, 0x04, 1, AD7124_RO}, /* AD7124_ID */
{0x06, 0x000000, 3, AD7124_RO}, /* AD7124_Error */
//不用ERROR功能
{0x07, 0x000000, 3, AD7124_RW}, /* AD7124_Error_En */
{0x08, 0x00, 1, AD7124_RO}, /* AD7124_Mclk_Count */
//使能通道0、选择Setup0配置组、输入脚分配AIN0->AINP,AIN1->AINM
{0x09, 0x8001, 2, AD7124_RW}, /* AD7124_Channel_0 */
//使能通道1、选择Setup1配置组、输入脚分配AIN2->AINP,AIN3->AINM
{0x0A, 0x9043, 2, AD7124_RW}, /* AD7124_Channel_1 */
//使能通道2、选择Setup2配置组、输入脚分配AIN4->AINP,AIN5->AINM
{0x0B, 0xA085, 2, AD7124_RW}, /* AD7124_Channel_2 */
//使能通道3、选择Setup3配置组、输入脚分配AIN6->AINP,AIN7->AINM
{0x0C, 0xB0C7, 2, AD7124_RW}, /* AD7124_Channel_3 */
{0x0D, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_4 */
{0x0E, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_5 */
{0x0F, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_6 */
{0x10, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_7 */
{0x11, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_8 */
{0x12, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_9 */
{0x13, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_10 */
{0x14, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_11 */
{0x15, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_12 */
{0x16, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_13 */
{0x17, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_14 */
{0x18, 0x0000, 2, AD7124_RW}, /* AD7124_Channel_15 */
//使能单极性、REF_BUF、AIN_BUF缓冲和REF_SEL内部基准、PGA=128
{0x19, 0x01F7, 2, AD7124_RW}, /* AD7124_Config_0 */
//使能单极性、REF_BUF、AIN_BUF缓冲和REF_SEL内部基准、PGA=16
{0x1A, 0x01F4, 2, AD7124_RW}, /* AD7124_Config_1 */
//使能单极性、REF_BUF、AIN_BUF缓冲和REF_SEL内部基准、PGA=4
{0x1B, 0x01F2, 2, AD7124_RW}, /* AD7124_Config_2 */
//使能单极性、REF_BUF、AIN_BUF缓冲和REF_SEL内部基准、PGA=1
{0x1C, 0x01F0, 2, AD7124_RW}, /* AD7124_Config_3 */
{0x1D, 0x09F0, 2, AD7124_RW}, /* AD7124_Config_4 */
{0x1E, 0x09F0, 2, AD7124_RW}, /* AD7124_Config_5 */
{0x1F, 0x09F0, 2, AD7124_RW}, /* AD7124_Config_6 */
{0x20, 0x09F0, 2, AD7124_RW}, /* AD7124_Config_7 */
{0x21, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_0 */
{0x22, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_1 */
{0x23, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_2 */
{0x24, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_3 */
{0x25, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_4 */
{0x26, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_5 */
{0x27, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_6 */
{0x28, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_7 */
{0x29, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_0 */
{0x2A, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_1 */
{0x2B, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_2 */
{0x2C, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_3 */
{0x2D, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_4 */
{0x2E, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_5 */
{0x2F, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_6 */
{0x30, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_7 */
//增益寄存器
{0x31, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_0 */
//增益寄存器
{0x32, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_1 */
//增益寄存器
{0x33, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_2 */
//增益寄存器
{0x34, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_3 */
{0x35, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_4 */
{0x36, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_5 */
{0x37, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_6 */
{0x38, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_7 */
};
/*! AD7124 registers list*/
enum ad7124_registers
{
AD7124_Status = 0x00,
AD7124_ADC_CONTROL,
AD7124_Data,
AD7124_IOCONTROL_1,
AD7124_IOCONTROL_2,
AD7124_ID,
AD7124_Error,
AD7124_ERROR_EN,
AD7124_MCLK_COUNT,
AD7124_CHANNEL_0,
AD7124_CHANNEL_1,
AD7124_CHANNEL_2,
AD7124_CHANNEL_3,
AD7124_CHANNEL_4,
AD7124_CHANNEL_5,
AD7124_CHANNEL_6,
AD7124_CHANNEL_7,
AD7124_CHANNEL_8,
AD7124_CHANNEL_9,
AD7124_CHANNEL_10,
AD7124_CHANNEL_11,
AD7124_CHANNEL_12,
AD7124_CHANNEL_13,
AD7124_CHANNEL_14,
AD7124_CHANNEL_15,
AD7124_CONFIG_0,
AD7124_CONFIG_1,
AD7124_CONFIG_2,
AD7124_CONFIG_3,
AD7124_CONFIG_4,
AD7124_CONFIG_5,
AD7124_CONFIG_6,
AD7124_CONFIG_7,
AD7124_FILTER_0,
AD7124_FILTER_1,
AD7124_FILTER_2,
AD7124_FILTER_3,
AD7124_FILTER_4,
AD7124_FILTER_5,
AD7124_FILTER_6,
AD7124_FILTER_7,
AD7124_OFFSET_0,
AD7124_OFFSET_1,
AD7124_OFFSET_2,
AD7124_OFFSET_3,
AD7124_OFFSET_4,
AD7124_OFFSET_5,
AD7124_OFFSET_6,
AD7124_OFFSET_7,
AD7124_GAIN_0,
AD7124_GAIN_1,
AD7124_GAIN_2,
AD7124_GAIN_3,
AD7124_GAIN_4,
AD7124_GAIN_5,
AD7124_GAIN_6,
AD7124_GAIN_7,
AD7124_REG_END
};
#endif /* __AD7124_H__ */
/********************************************************************************/
/* @file ssd1306.c */
/* @version V1.00 */
/* $author: yuanxihua@21cn.com */
/* $Date: 2018/11/27 23:39p $ */
/* @brief SWM320RBT6 Series SSD1306 Driver Sample Code */
/* */
/* @note */
/* Copyright (C) 2010-2019 PM9GZY Technology Corp. All rights reserved. */
/* */
/********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dotcode.h"
/*
_________________________________________________
| SWM320RBT6 SSD1306 |
| |
| PB0 PDN ----> PDN |
| PP9 LRST ----> RST |
| PP8 NSS0 ----> SCS |
| PP7 MISO0 <---- SDC |
| PP6 MOSI0 ----> SDA |
| PP5 SCLK0 ----> SCK |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define SSD1306_CMD() GPIO_ClrBit(GPIOP, PIN7)
#define SSD1306_DAT() GPIO_SetBit(GPIOP, PIN7)
#define SSD1306_PON() GPIO_ClrBit(GPIOB, PIN0)
#define SSD1306_OFF() GPIO_SetBit(GPIOB, PIN0)
#define SSD1306_RST() GPIO_ClrBit(GPIOP, PIN9)
#define SSD1306_NST() GPIO_SetBit(GPIOP, PIN9)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void SPI0Init(void)
{
SPI_InitStructure SPI_initStruct;
GPIO_Init(GPIOB, PIN0, 1, 0, 0);
GPIO_Init(GPIOP, PIN9, 1, 0, 0);
PORT_Init(PORTP, PIN5 , FUNMUX1_SPI0_SCLK, 0);
PORT_Init(PORTP, PIN6 , FUNMUX0_SPI0_MOSI, 0);
GPIO_Init(GPIOP, PIN7, 1, 0, 0);//FUNMUX1_SPI0_MISO
PORT_Init(PORTP, PIN8, FUNMUX0_SPI0_SSEL, 0);
SPI_initStruct.clkDiv = SPI_CLKDIV_4;//0.04US
// SPI_initStruct.clkDiv = SPI_CLKDIV_8;//0.07US
// SPI_initStruct.clkDiv = SPI_CLKDIV_16;//0.14US
// SPI_initStruct.clkDiv = SPI_CLKDIV_32;//0.26US
// SPI_initStruct.clkDiv = SPI_CLKDIV_64;//0.53S
// SPI_initStruct.clkDiv = SPI_CLKDIV_128;//1.07US
// SPI_initStruct.clkDiv = SPI_CLKDIV_256;//2.14US
// SPI_initStruct.clkDiv = SPI_CLKDIV_512;//4.28US
SPI_initStruct.FrameFormat = SPI_FORMAT_SPI;
SPI_initStruct.SampleEdge = SPI_FIRST_EDGE;
SPI_initStruct.IdleLevel = SPI_LOW_LEVEL;
SPI_initStruct.WordSize = 8;
SPI_initStruct.Master = 1;
SPI_initStruct.RXHFullIEn = 0;
SPI_initStruct.TXEmptyIEn = 0;
SPI_initStruct.TXCompleteIEn = 0;
SPI_Init(SPI0, &SPI_initStruct);
SPI_Open(SPI0);
}
void SSD1306_WriteCMD(uint8_t cmd)
{
SSD1306_CMD();
uint8_t r=SPI_ReadWrite(SPI0,cmd);
}
void SSD1306_WriteDAT(uint8_t dat)
{
SSD1306_DAT();
uint8_t r=SPI_ReadWrite(SPI0,dat);
}
void OLED_Init(void)
{
SPI0Init();
SSD1306_OFF();
osDelay(100);
SSD1306_PON();
SSD1306_RST();
osDelay(100);
SSD1306_NST();
osDelay(200); //这里的延时很重要
SSD1306_WriteCMD(0xAE); //display off
SSD1306_WriteCMD(0x20); //Set Memory Addressing Mode
SSD1306_WriteCMD(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
SSD1306_WriteCMD(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
SSD1306_WriteCMD(0xc8); //Set COM Output Scan Direction
SSD1306_WriteCMD(0x00); //---set low column address
SSD1306_WriteCMD(0x10); //---set high column address
SSD1306_WriteCMD(0x40); //--set start line address
SSD1306_WriteCMD(0x81); //--set contrast control register
SSD1306_WriteCMD(0xff); //亮度调节 0x00~0xff
SSD1306_WriteCMD(0xa1); //--set segment re-map 0 to 127
SSD1306_WriteCMD(0xa6); //--set normal display
SSD1306_WriteCMD(0xa8); //--set multiplex ratio(1 to 64)
SSD1306_WriteCMD(0x3F); //
SSD1306_WriteCMD(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
SSD1306_WriteCMD(0xd3); //-set display offset
SSD1306_WriteCMD(0x00); //-not offset
SSD1306_WriteCMD(0xd5); //--set display clock divide ratio/oscillator frequency
SSD1306_WriteCMD(0xf0); //--set divide ratio
SSD1306_WriteCMD(0xd9); //--set pre-charge period
SSD1306_WriteCMD(0x22); //
SSD1306_WriteCMD(0xda); //--set com pins hardware configuration
SSD1306_WriteCMD(0x12);
SSD1306_WriteCMD(0xdb); //--set vcomh
SSD1306_WriteCMD(0x20); //0x20,0.77xVcc
SSD1306_WriteCMD(0x8d); //--set DC-DC enable
SSD1306_WriteCMD(0x14); //
SSD1306_WriteCMD(0xaf); //--turn on oled panel
}
void OLED_Origin(unsigned char x, unsigned char y) //设置起始点坐标
{
SSD1306_WriteCMD(0xb0+y);
SSD1306_WriteCMD(((x&0xf0)>>4)|0x10);
SSD1306_WriteCMD((x&0x0f)|0x01);
}
void OLED_Wakeup(void) //将OLED从休眠中唤醒
{
SSD1306_WriteCMD(0X8D); //设置电荷泵
SSD1306_WriteCMD(0X14); //开启电荷泵
SSD1306_WriteCMD(0XAF); //OLED唤醒
}
void OLED_Sleep(void) //让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
{
SSD1306_WriteCMD(0X8D); //设置电荷泵
SSD1306_WriteCMD(0X10); //关闭电荷泵
SSD1306_WriteCMD(0XAE); //OLED休眠
}
void OLED_Fill(uint8_t data) //全屏填充
{
unsigned char m,n;
for(m=0;m<8;m++)
{
SSD1306_WriteCMD(0xb0+m); //page0-page1
SSD1306_WriteCMD(0x00); //low column start address
SSD1306_WriteCMD(0x10); //high column start address
for(n=0;n<128;n++)
{
SSD1306_WriteDAT(data);
}
}
}
//--------------------------------------------------------------
// Prototype : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
// Calls :
// Parameters : x,y -- 起始点坐标(x:0~127, y:0~7); ch[] -- 要显示的字符串; TextSize -- 字符大小(1:6*8 ; 2:8*16)
// Description : 显示codetab.h中的ASCII字符,有6*8和8*16可选择
//--------------------------------------------------------------
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
unsigned char c = 0,i = 0,j = 0;
switch(TextSize)
{
case 1:
{
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 126)
{
x = 0;
y++;
}
OLED_Origin(x,y);
for(i=0;i<6;i++){SSD1306_WriteDAT(F6x8[c][i]);}
x += 6;
j++;
}
}break;
case 2:
{
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 120)
{
x = 0;
y++;
}
OLED_Origin(x,y);
for(i=0;i<8;i++)
SSD1306_WriteDAT(F8X16[c*16+i]);
OLED_Origin(x,y+1);
for(i=0;i<8;i++)
SSD1306_WriteDAT(F8X16[c*16+i+8]);
x += 8;
j++;
}
}break;
}
}
//--------------------------------------------------------------
// Prototype : void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
// Calls :
// Parameters : x,y -- 起始点坐标(x:0~127, y:0~7); N:汉字在codetab.h中的索引
// Description : 显示codetab.h中的汉字,16*16点阵
//--------------------------------------------------------------
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
unsigned char wm=0;
unsigned int adder=32*N;
OLED_Origin(x,y+0);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F16x16[adder++]);}
OLED_Origin(x,y+1);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F16x16[adder++]);}
}
//--------------------------------------------------------------
// Prototype : void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
// Calls :
// Parameters : x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)
// Description : 显示BMP位图
//--------------------------------------------------------------
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
unsigned int j=0;
unsigned char x,y;
if(y1%8==0){y = y1/8;}else{y = y1/8 + 1;}
for(y=y0;y<y1;y++)
{
OLED_Origin(x0,y);
for(x=x0;x<x1;x++){SSD1306_WriteDAT(BMP[j++]);}
}
}
void OLED_Welcome(void)
{
uint32_t i;
OLED_Init();
{
// OLED_Fill(0xFF);//全屏点亮
// osDelay(100);
OLED_Fill(0x00);//全屏灭
// osDelay(500);
for(i=0;i<4;i++)
{
OLED_ShowCN(32+i*16,0,i);//测试显示中文
}
// osDelay(2000);
OLED_ShowStr(40,3,"PM9GZY",2); //测试8*16字符
OLED_ShowStr(13,5,"yuanxihua@139.com",1); //测试6*8 字符
osDelay(1000);
// OLED_Fill(0);//清屏
// OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//测试BMP位图显示
// osDelay(1000);
}
}
void SSD1306_Test(void)
{
// uint32_t i;
// while(1)
// {
// SSD1306_WriteCMD(0x55);
// SSD1306_WriteDAT(0xAA);
// }
OLED_Init();
OLED_Fill(0xff);
osDelay(100);
}
void OLED_Volute(float *vol)
{
unsigned char buf[20];
OLED_Fill(0x00);//全屏灭
for(int i=0;i<4;i++){OLED_ShowCN(32+i*16,0,i);}//测试显示中文
sprintf((char *)buf,"CH1: %3.10f V",vol[0]);OLED_ShowStr(0,3,buf,1);
sprintf((char *)buf,"CH2: %3.10f V",vol[1]);OLED_ShowStr(0,4,buf,1);
sprintf((char *)buf,"CH3: %3.10f V",vol[2]);OLED_ShowStr(0,5,buf,1);
sprintf((char *)buf,"CH4: %3.10f V",vol[3]);OLED_ShowStr(0,6,buf,1);
}
void OLED_Battery(uint16_t bat)
{
uint16_t x=122-((36*bat)/100);if(x>122){x=122;}if(x<86){x=86;}
char str[10];sprintf(str,"%d%%",bat);
OLED_ShowStr(10,0,(unsigned char*)str,2); //测试8*16字符
OLED_Origin(79 ,0);for(int i=79 ;i<82 ;i++){SSD1306_WriteDAT(0xE0);}
OLED_Origin(79 ,1);for(int i=79 ;i<82 ;i++){SSD1306_WriteDAT(0x07);}
OLED_Origin(82 ,0);for(int i=82 ;i<84 ;i++){SSD1306_WriteDAT(0xff);}
OLED_Origin(82 ,1);for(int i=82 ;i<84 ;i++){SSD1306_WriteDAT(0xff);}
OLED_Origin(84 ,0);for(int i=84 ;i<86 ;i++){SSD1306_WriteDAT(0x03);}
OLED_Origin(84 ,1);for(int i=84 ;i<86 ;i++){SSD1306_WriteDAT(0xC0);}
OLED_Origin(86 ,0);for(int i=86 ;i<123;i++){SSD1306_WriteDAT((i>=x)?0xF3:0x03);}
OLED_Origin(86 ,1);for(int i=86 ;i<123;i++){SSD1306_WriteDAT((i>=x)?0xCF:0xC0);}
OLED_Origin(123,0);for(int i=123;i<125;i++){SSD1306_WriteDAT(0x03);}
OLED_Origin(123,1);for(int i=123;i<125;i++){SSD1306_WriteDAT(0xC0);}
OLED_Origin(125,0);for(int i=125;i<127;i++){SSD1306_WriteDAT(0xff);}
OLED_Origin(125,1);for(int i=125;i<127;i++){SSD1306_WriteDAT(0xff);}
}
void OLED_Digital(unsigned char x, unsigned char y, unsigned char N)
{
unsigned char wm=0;unsigned int adder=64*N;
OLED_Origin(x,y+0);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F32X32[adder++]);}
OLED_Origin(x,y+1);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F32X32[adder++]);}
OLED_Origin(x,y+2);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F32X32[adder++]);}
OLED_Origin(x,y+3);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F32X32[adder++]);}
}
void OLED_pCHz(uint16_t bat,uint32_t pchz,uint8_t PC)
{
OLED_Fill(0x00);//全屏灭
OLED_Battery(bat);
if(pchz>999){OLED_Digital(20,2, pchz/1000);pchz%=1000;
if(pchz<100){OLED_Digital(40,2, 0);}if(pchz<10){OLED_Digital(60,2, 0);}}
if(pchz>99 ){OLED_Digital(40,2, pchz/100 );pchz%=100;
if(pchz<10 ){OLED_Digital(60,2, 0);}}
if(pchz>9 ){OLED_Digital(60,2, pchz/10 );pchz%=10 ;}
OLED_Digital(80,2, pchz);
if(PC){OLED_ShowStr(108,7,"p",1);OLED_ShowStr(116,6,"C",2);}
else {OLED_ShowStr(108,6,"H",2);OLED_ShowStr(116,7,"z",1);}
}
一,准备VMWARE+LINUX安装软件包
1,在http://www.ubuntu.com/getubuntu/download
下载Ubuntu 7.10的X86桌面版本的ISO文件:
http://mirror.rootguide.org/ubuntu-releases/gutsy/ubuntu-7.10-desktop-i386.iso
1,在http://releases.ubuntu.com/releases/.pool/
下载Ubuntu 7.10的X86桌面版本的ISO文件:
ubuntu-7.10-desktop-i386.iso
2,在http://www.crsky.com/soft/8612.html
下载VMware Workstation v5.5.3 Build 34685 及 汉化补丁
VMware-workstation-5.5.3-34685.rar
VMware_Workstation_5.5.3_34685H.rar
2,在http://www.crsky.com/soft/1863.html
下载VMware Workstation v6.0.0 Build 45731 及 汉化补丁
VMwareWorkstation-v6.0.0.45731.rar
VMwareWorkstation_v60045731H.rar
3,在http://www.crsky.com/soft/6748.html上
下载SecureCRT v5.5.2
SecureCRT-v5.5.2.rar
3,在http://www.crsky.com/soft/6838.html
下载SecureCRT v5.1.2 Build 274 汉化版 by 偃月青龙
SecureCRT_5.1.2H.rar
3,在http://www.crsky.com/soft/6838.html
SecureCRT v5.1.3 Build 281 汉化版
HAP_SecureCRT_5.1.3.rar
4,在http://www.codesourcery.com/gnu_toolchains/arm/download.html
下载ARM EABI + IA32 GNU/Linux 开发工具
arm-2007q3-53-arm-none-eabi-i686-pc-linux-gnu.tar.bz2
下载ARM GNU/Linux + IA32 GNU/Linux 开发工具
arm-2007q3-51-arm-none-gnueabi-i686-pc-linux-gnu.tar.bz2
4,在ftp://ftp.denx.de/pub/eldk/4.1/
下载arm-linux-x86-uclibc
ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86-uclibc/iso/arm-2007-01-22-uclibc.iso
下载arm-linux-x86
ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86/iso/arm-2007-01-21.iso
二,准备AT91SAM9260+LINUX开发包
1,在http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933
下载AT91SAM9260-EK 全套资料
软件及硬件文档
1,在http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3883
下载AT91-ISP.exe及使用手册
Install AT91-ISP v1.10.exe
doc6224.pdf doc6272.pdf doc6132.pdf
2,在http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4093
下载AT91 Bootstrap及使用手册
AT91Bootstrap1.5.zip
doc6277.pdf
3,在http://sourceforge.net/projects/u-boot
下载Das U-Boot - Universal Bootloader
u-boot-1.1.5.tar.bz2
u-boot-1.1.6.tar.bz2
3,在ftp://ftp.denx.de/pub/u-boot/
下载U-Boot-1.1.5 released
u-boot-1.1.5.tar.bz2
4,在http://www.at91.com/ 上注册
下载u-boot-1.1.5补丁
u-boot-1.1.5_atmel_1.4.diff.bz2
5,在http://www.kernel.org/pub/linux/kernel/v2.6/
下载Linux 2.6 内核源码
linux-2.6.23.tar.bz2
6,在http://maxim.org.za/AT91RM9200/2.6/
下载Linux 2.6 Patches
2.6.23-at91.patch.gz
7,在http://www.busybox.net/
下载BusyBox 1.8.2. (svn, patches, how to add a patch)
busybox-1.8.2.tar.bz2
三,安装VMWARE+LINUX开发平台
1,在XP系统上安装VMwareWorkstation-v6.0.0.45731及汉化补丁
A,双击VMware Workstation v6.0 Build 45731 KeyGen.exe 启动破解程序,“serial”栏目中会产生一个安装
用的序列号,"Type"栏需要为“VMware Workstation ACE Edition for Windows V6";
B,双击VMware-workstation-6.0.0-45731.exe 启动安装,点击NEXT,选择Typical;再NEXT,安装文件夹选择
默认;再NEXT,快捷方式产生用默认;再NEXT,按install;输入使用者,公司和序列号,最后点击finish完成
安装,重启动电脑;
C,双击setup_tracky.exe 启动汉化,点击“下一步”,勾选“同意许可”;再“下一步”又“下一步”,安装
文件夹选择默认;再“下一步”再“下一步”,去掉第三方插件;再“下一步”后,点击“安装”;最后点击
“完成”;
注意:XP系统需要512MB以上内存,15GB以上硬盘空间。
2,在VMware Workstation上安装ubuntu-7.10-desktop的X86版本
A,双击桌面VMware Workstation图标进入虚拟机,点击“新建虚拟机”启动建立向导;点“下一步”选择“典型”;
点“下一步”选择操作系统为“linux"和版本为“Ubuntu";点“下一步”输入虚拟机名称和选择安装路径;点
“下一步”选择“使用桥接网络”;“下一步”磁盘大小填15GB以上,勾选“分割磁盘为2GB文件”;点击“完成”;
B,进入建立好的虚拟机页面,双击“CD-ROM”,“连接”选择“使用ISO镜像”; 点击“浏览”选择下载的“ubuntu-
7.10-desktop-i386.iso”文件“打开”并“确定”;点击虚拟机页面中“命令”中的“启动该虚拟机”启动安装;
C,在LINUX安装界面中按F2功能键,选择“中文(简体)”;用上下箭头选择高亮“启动或安装UBUNTU”时按回车;进入
Ubuntu-7.10-desktop的X86版本的LiveCD界面,双击“安装”进入了LiveCD安装到硬盘的过程;
D,在安装界面点击“前进”,地点用默认“上海”;点击“前进”,键盘布局用默认“美国”;点击“前进”硬盘分区
用默认“向导”,点击“前进”,输入用户名和密码;点击“前进”,在准备安装中,点击“Install";安装完成
后,点击“现在重启”并把虚拟机“设置”中的“CD-ROM”改回“使用物理驱动器”;
注意:XP系统需在DHCP的局域网内,要独立分配IP给虚拟机;安装的用户名和密码区别于ROOT用户,每次登陆系统及修改
系统配置都要用到,需要牢记。
四,配置并更新ubuntu桌面系统
1,启动根用户和配置网络
A,进入系统后在启动菜单“应用程序”->“附件”->“终端”拉到桌面上;把启动菜单“位置”中的“计算机”也
拉到桌面上;双击桌面“终端”中打开命令行终端
B,启用root用户并修改密码
yuanxh@yuanxh-desktop:~$ sudo passwd root
C,进入root用户操作
yuanxh@yuanxh-desktop:~$ su
D,查看本机IP配置信息
root@yuanxh-desktop:/home/yuanxh# ifconfig -a
E,在启动菜单“系统”->“系统管理”->“网络”中
填入IP,子域掩码,网关,DNS等网络参数;
F,修改.bashrc启用ll la等到命令转义
root@yuanxh-desktop:/home/yuanxh# vi /root/.bashrc
2,安装虚拟驱动Vmware tools
A,进入系统后在虚拟机菜单“虚拟机”中点击“安装Vmware tools”后桌面会弹出一个CD-ROM内容的文件夹,里面有两个
rpm和tar.gz压缩文件包;
B,双击桌面“终端”打开命令行终端,用命令模式安装虚拟驱动:
切换到root用户
yuanxh@yuanxh-desktop:~$ su
建立文件夹
root@yuanxh-desktop:/home/yuanxh# mkdir vm-tools
修改文件夹权限
root@yuanxh-desktop:/home/yuanxh# chmod 777 vm-tools/
进入文件夹
root@yuanxh-desktop:/home/yuanxh# cd vm-tools/
复制虚拟驱动软件包
root@yuanxh-desktop:/home/yuanxh/vm-tools# cp /media/cdrom0/VMwareTools-6.0.0-45731.tar.gz .
解压虚拟驱动文件包
root@yuanxh-desktop:/home/yuanxh/vm-tools# tar xzvf VMwareTools-6.0.0-45731.tar.gz
进入虚拟驱动文件夹
root@yuanxh-desktop:/home/yuanxh/vm-tools# cd vmware-tools-distrib/
运行虚拟驱动安装脚本
root@yuanxh-desktop:/home/yuanxh/vm-tools/vmware-tools-distrib# ./vmware-install.pl
C,一路按回车键,直到最后能选择屏幕分辨率大小,并且鼠标能自由进入虚拟机和XP之间;
3,启用XP与虚拟机系统间的共享文件夹功能
A,在虚拟机菜单“虚拟机”->“设置”中,切换到“选项”页;选择到“共享文件夹” 设置,选择“总是启用”;点击文件夹
下的添加进入“添加文件夹向导”;点击“下一步”设置文件夹“名称”和选择XP系统中的文件夹;点击“下一步”配置好
共享文件夹属性后,点击“完成”;退出向导,点击“确定”退出设置;
B,在设置好共享文件夹后,并且安装好虚拟驱动后启动虚拟机,便可以在虚拟机中看到共享文件夹的内容;
root@yuanxh-desktop:/home/yuanxh# ls -l /mnt/hgfs
4,更新软件包服务器源后更新升级系统并安装SSH和ZMODEM协议
A,在http://www.ubuntu-nl.org/source-o-matic/
自动产生source.list内容,更新到/etc/apt/sources.list 中;
B,切换到root用户后执行以下命令更新升级系统:
网络更新系统
root@yuanxh-desktop:/home/yuanxh# apt-get update
网络升级系统
root@yuanxh-desktop:/home/yuanxh# apt-get upgrade
C,网络安装系统汉字库
root@yuanxh-desktop:/home/yuanxh# apt-get install language-pack-zh language-pack-zh-base language-support-zh
在系统登陆界面的“选项”中可以选择系统默认语言;在启动菜单的“系统”->“系统管理”->“语言支持”中也可以
修改系统默认语言支持;
D,网络安装SSH客户端和服务器端
root@yuanxh-desktop:/home/yuanxh# apt-get install ssh openssh-server
只有安装了这个才能用SecureCRT远程终端SSH访问系统
E,用以下命令查找并安装ZMMODEM协议支持软件包:
查找rzsz相关软件包
root@yuanxh-desktop:~# apt-cache search rzsz
显示lrzsz软件包详细情况
root@yuanxh-desktop:~# apt-cache show lrzsz
网络安装zmodem传输协议
root@yuanxh-desktop:/home/yuanxh# apt-get install lrzsz
查看网络下载软件包存放目录
root@yuanxh-desktop:/home/yuanxh# ll /var/cache/apt/archives/
5,安装SecureCRT远程终端SSH访问虚拟机和启用SFTP文件传输功能
A,双击HAP_SecureCRT_5.1.3.exe,点击“继续”;选择“接受协议”,再点击“继续”;点击“继续”后安装路径
选择默认的;点击“继续”后选择“完整安装”;点击“继续”后产生快捷方式用默认;点击“安装”后点击“完成”;
B,双击桌面SecureCRT 5.1.3图标启动终端软件,在输入许可数据中依次输入“名字”“公司”“序列号”“许可密钥”和
“发布日期”完成注册;
C,利用向导建立一个SSH会话到虚拟机;“下一步”后输入虚拟机IP地址和登陆用户名,建立好后双击会话SSH登陆LINUX,
在会话属性中可配置终端类型,字体,滚屏行数,字符编码,XMODEM和SFTP默认路径等;
D,建立了到LINUX的SSH会话后,在SecureCRT 5.1.3界面的菜单“文件”->“连接SFTP标签”可启动到相应的LINUX的SFTP连接,
在SFTP标签中输入“help”可以查看相关的SFTP命令。
五,建立FTP,NFS和交叉编译环境
1,用命令配置TFTP服务
A, 建立TFTP系统根目录并修改权限
root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir /tftpboot
root@yuanxh-desktop:/home/yuanxh/at91_works# chmod 777 /tftpboot
B,安装TFTP服务器端和客户端
root@yuanxh-desktop:/# sudo apt-get install tftp tftpd openbsd-inetd
C,修改配置文件使用TFTP根目录
root@yuanxh-desktop:/home/yuanxh/at91_works# vi /etc/inetd.conf
在/etc/inetd.conf新行中填入以下内容
tftp dgram udp wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd /tftpboot
D,启动服务
root@yuanxh-desktop:/home/yuanxh/at91_works# /etc/init.d/openbsd-inetd restart
E,测试服务
root@yuanxh-desktop:/home/yuanxh# touch /tftpboot/aaa
root@yuanxh-desktop:/home/yuanxh# vi /tftpboot/aaa
root@yuanxh-desktop:/home/yuanxh# tftp 192.168.1.100
tftp> get aaa
tftp> quit
root@yuanxh-desktop:/home/yuanxh# cat aaa
2,用命令配置NFS服务
A,安装NFS服务器端
root@yuanxh-desktop:/home/yuanxh# apt-get install nfs-kernel-server nfs-common portmap
B,配置访问目录及权限
root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir /nfsboot
root@yuanxh-desktop:/home/yuanxh/at91_works# chmod 777 /nfsboot
root@yuanxh-desktop:/home/yuanxh/at91_works# touch /nfsboot/yuanxh
root@yuanxh-desktop:/# vi /etc/exports
在/etc/exports新行中填入以下内容
/nfsboot 192.168.1.0/24(rw,sync)
C,启动服务
root@yuanxh-desktop:/# exportfs -ra
root@yuanxh-desktop:/# /etc/init.d/portmap restart
root@yuanxh-desktop:/# /etc/init.d/nfs-common restart
root@yuanxh-desktop:/# /etc/init.d/nfs-kernel-server restart
D,测试服务
root@yuanxh-desktop:/# mount 192.168.1.100:/nfsboot /mnt
root@yuanxh-desktop:/home/yuanxh# ll /mnt
root@yuanxh-desktop:/home/yuanxh# rm -rf /mnt/yuanxh
root@yuanxh-desktop:/home/yuanxh# showmount
root@yuanxh-desktop:/home/yuanxh# df
root@yuanxh-desktop:/home/yuanxh# umount /mnt
root@yuanxh-desktop:/home/yuanxh# ll /nfsboot
3,安装交叉编译工具链
A,利用SecureCRT 5.1.3登陆,传送文件到系统
root@yuanxh-desktop:/home/yuanxh# mkdir /usr/local/arm
root@yuanxh-desktop:/home/yuanxh# chmod 777 /usr/local/arm/
root@yuanxh-desktop:/home/yuanxh# cd /usr/local/arm/
root@yuanxh-desktop:/usr/local/arm# rz
在SecureCRT弹出的窗口中选择交叉编译工具安装包
B,解压交叉编译工具包
root@yuanxh-desktop:/usr/local/arm# tar xjvf arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
root@yuanxh-desktop:/usr/local/arm# tar xjvf arm-2007q3-53-arm-none-eabi-i686-pc-linux-gnu.tar.bz2
C,安装ELDK交叉编译工具
在虚拟机窗口中右击“arm-2007-01-22-uclibc.iso”选择“解压到此处”来解压;
root@yuanxh-desktop:/usr/local/arm# cd arm-2007-01-22-uclibc/
root@yuanxh-desktop:/usr/local/arm/arm-2007-01-22-uclibc# chmod 777 install
root@yuanxh-desktop:/usr/local/arm/arm-2007-01-22-uclibc# ./install -d /usr/local/arm/eldk-uclibc-4.1
在虚拟机窗口中右击“arm-2007-01-21.iso”选择“解压到此处”来解压;
root@yuanxh-desktop:/usr/local/arm# cd arm-2007-01-21/
root@yuanxh-desktop:/usr/local/arm/arm-2007-01-21# chmod 777 install
root@yuanxh-desktop:/usr/local/arm/arm-2007-01-21# ./install -d /usr/local/arm/eldk-4.1
D,把编译器路径添加到系统路径中
root@yuanxh-desktop:/usr/local/arm# vi /root/.bashrc
在alias l='ls -CF'后的空白处填上:
PATH=$PATH:/usr/local/arm/eldk-4.1/usr/bin:/usr/local/arm/eldk-4.1/bin
export PATH
启动新系统路径
root@yuanxh-desktop:/usr/local/arm# source /root/.bashrc
显示新系统路径
root@yuanxh-desktop:/usr/local/arm# echo $PATH
查看版本号
root@yuanxh-desktop:/usr/local/arm# arm-linux-gcc -v
E,查看交叉编译工具版本信息
root@yuanxh-desktop:/usr/local/arm# ./arm-2007q3/bin/arm-none-eabi-gcc -v
root@yuanxh-desktop:/usr/local/arm# ./arm-2007q3/bin/arm-none-linux-gnueabi-gcc -v
root@yuanxh-desktop:/usr/local/arm# ./eldk-uclibc-4.1/usr/bin/arm-linux-gcc -v
六,编译Bootstrap+U-BOOT启动代码
1,传送文件包到LINUX系统并解压
A,利用SecureCRT 5.1.3登陆,传送文件到系统
root@yuanxh-desktop:/home/yuanxh# mkdir at91_works
root@yuanxh-desktop:/home/yuanxh# chmod 777 at91_works/
root@yuanxh-desktop:/home/yuanxh# cd at91_works/
root@yuanxh-desktop:/home/yuanxh/at91_works# rz
在SecureCRT弹出的窗口中选择AT91Bootstrap1.5.zip,u-boot-1.1.5.tar.bz2,u-boot-1.1.5_atmel_1.4.diff.bz2软件包
B,解压所有软件包
在虚拟机窗口中右击AT91Bootstrap1.5.zip,选择“解压到此处”来解压,同样解压u-boot-1.1.5_atmel_1.4.diff.bz2;
root@yuanxh-desktop:/home/yuanxh/at91_works# tar xjvf u-boot-1.1.5.tar.bz2
2,编译生成一级启动目标码
A,为Bootstrap-v1.5指定编译器
root@yuanxh-desktop:/home/yuanxh/at91_works# cd Bootstrap-v1.5/board/at91sam9260ek/nandflash/
root@yuanxh-desktop:/home/yuanxh/at91_works/Bootstrap-v1.5/board/at91sam9260ek/nandflash# vi Makefile
把文件中的CROSS_COMPILE=/usr/local/arm/eldk-4.1/usr/bin/arm-linux-填好,指定eldk-4.1的编译器;
B,编译生成了目标码并传送回XP
root@yuanxh-desktop:/home/yuanxh/at91_works/Bootstrap-v1.5/board/at91sam9260ek/nandflash# make
root@yuanxh-desktop:/home/yuanxh/at91_works/Bootstrap-v1.5/board/at91sam9260ek/nandflash# sz nandflash_at91sam9260ek.bin
在dataflash目录同样修改Makefile也能生成dataflash_at91sam9260ek.bin;
注意:必须保证 dataflash_at91sam9260ek.bin 和平nandflash_at91sam9260ek.bin 小于4KB;
3,编译生成二级启动目标码
A,打上补丁
root@yuanxh-desktop:/home/yuanxh/at91_works# cd u-boot-1.1.5
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# mv ../u-boot-1.1.5_atmel_1.4.diff .
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# apt-get install patch
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# patch -p1 < ./u-boot-1.1.5_atmel_1.4.diff
B,指定编译器
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# vi Makefile
把CROSS_COMPILE = arm-linux- 改成 CROSS_COMPILE=/usr/local/arm/eldk-4.1/usr/bin/arm-linux-
C,配置并编译在DATAFLASH中运行模式
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# apt-get install libncurses5-dev
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make clean
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make mrproper
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make at91sam9260ek_config
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# mv u-boot.bin u-boot-env-df.bin
注意:需要修改一下/u-boot-1.1.5/examples/Makefile的语法错误,请按/u-boot-1.1.6/examples/Makefile部分更新;
D,配置并编译在NANDFLASH中运行模式
修改配置头文件
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# vi include/configs/at91sam9260ek.h
把文件中的
#define CFG_ENV_IS_IN_DATAFLASH 1
#undef CFG_ENV_IS_IN_NAND
改成
#undef CFG_ENV_IS_IN_DATAFLASH
#define CFG_ENV_IS_IN_NAND 1
重新编译
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make clean
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make mrproper
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make at91sam9260ek_config
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# mv u-boot.bin u-boot-env-nf.bin
E,发送目标码
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# sz u-boot-env-df.bin
root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# sz u-boot-env-nf.bin
七,为SAM9260编译ARM-LINUX内核
1,传送文件包到LINUX系统并解压
利用SecureCRT 5.1.3登陆,传送文件到系统
root@yuanxh-desktop:/home/yuanxh# cd at91_works/
root@yuanxh-desktop:/home/yuanxh/at91_works# rz
在SecureCRT弹出的窗口中选择2.6.23-at91.patch.gz和linux-2.6.23.tar.bz2包;
2,解压内核及打上补丁包
root@yuanxh-desktop:/home/yuanxh/at91_works# tar xjvf linux-2.6.23.tar.bz2
root@yuanxh-desktop:/home/yuanxh/at91_works# gzip -d 2.6.23-at91.patch.gz
root@yuanxh-desktop:/home/yuanxh/at91_works# cd linux-2.6.23
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# patch -p1 < ../2.6.23-at91.patch
3,为内核指定编译器
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# vi Makefile
把 EXTRAVERSION = -9gsam9260ek 写上自己版本标识,指定体系结构和编译器
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/eldk-4.1/usr/bin/arm-linux-
添加可加载模块安装路径
INSTALL_MOD_PATH = $(TOPDIR)/modules-$(KERNELRELEASE)
4,编译内核及发布目标码
A,查看内核支持的开发板
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- help
B,配置为AT91RM9260EK板默认设置
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- at91sam9260ek_defconfig
C,编译生成全部目标码
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux-
D,也可分步依次生成zImage,可加载modules和安装可加载模拟到默认目录
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- zImage
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- modules
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- modules_install
E,发送内核目标码和可加载模块
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# cp arch/arm/boot/zImage .
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# mv zImage zImage-2.6.23-9gsam9260ek.bin
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# sz zImage-2.6.23-9gsam9260ek.bin
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# tar czvf modules-2.6.23-9gsam9260ek.tar.gz modules-2.6.23-9gsam9260ek/
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# sz modules-2.6.23-9gsam9260ek.tar.gz
F,个性化配置内核
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
.config中内核启动命令行参数CONFIG_CMDLINE改为:
mem=64M console=ttyS0,115200 initrd=0x21100000,8388608 root=/dev/ram0 rw init=/linuxrc
G,编译生成U-BOOT可识别目标码uImage
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- uImage
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# cp arch/arm/boot/uImage .
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# mv uImage uImage-2.6.23-9gsam9260ek.bin
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# sz uImage-2.6.23-9gsam9260ek.bin
5,清除内核目标码恢复未配置状态
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- clean
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- distclean
root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- mrproper
八,编译BUSYBOX建立根文件系统
1,编译BUSYBOX
A,传送文件包到LINUX系统并解压
利用SecureCRT 5.1.3登陆,传送文件到系统
root@yuanxh-desktop:~# cd /home/yuanxh/at91_works/
root@yuanxh-desktop:/home/yuanxh/at91_works# rz
在SecureCRT弹出的窗口中选择busybox-1.8.2.tar.bz2包;
B,解压及指定编译器
root@yuanxh-desktop:/home/yuanxh/at91_works# tar xjvf busybox-1.8.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/at91_works# cd busybox-1.8.2
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# vi Makefile
把 EXTRAVERSION = -9gsam9260ek 写上自己版本标识,指定体系结构和编译器
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/eldk-4.1/usr/bin/arm-linux-
C,编译生成全部目标码
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make help
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make defconfig
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make install
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# mv _install/ rootfs
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# cp -dpR examples/bootfloppy/etc rootfs/
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# tar czvf busybox-9gsam9260ek.tar.gz rootfs/
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# sz busybox-9gsam9260ek.tar.gz
D,个性化配置BUSYBOX
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make menuconfig
E,清除内核目标码恢复未配置状态
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make clean
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make distclean
root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make mrproper
2,编译RZSZ软件包
A,在http://ftp.uni-koeln.de/util/comm/
上下载rzsz-3.49.zip
B,上传到LINUX系统
root@yuanxh-desktop:/home/yuanxh/at91_works# rz
C,解压软件包
在虚拟机窗口中右击rzsz-3.49.zip,选择“解压到此处”来解压,
D,进入软件包
root@yuanxh-desktop:/home/yuanxh/at91_works# cd rzsz-3.49
E,指定编译器
root@yuanxh-desktop:/home/yuanxh/at91_works/rzsz-3.49# vi makefile
修改如下内容
CC=/usr/local/arm/eldk-4.1/usr/bin/arm-linux-gcc
F,编译生成目标码
root@yuanxh-desktop:/home/yuanxh/at91_works/rzsz-3.49# make posix
root@yuanxh-desktop:/home/yuanxh/at91_works/rzsz-3.49# tar czvf rzsz-9gsam9260ek.tar.gz rz sz
root@yuanxh-desktop:/home/yuanxh/at91_works/rzsz-3.49# sz rzsz-9gsam9260ek.tar.gz
注意:此软件有版权保护,软件中REGISTERED如果没有被宏定义,程序在使用中提示使用越权;
3,建立根文件系统
A,建立BUSYBOX基本目录
root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir rootfs-9g9sam9260ek
root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek/
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rz
传送上节编译生成的busybox-9gsam9260ek.tar.gz目标码包
B,建立树型根目录
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# tar xzvf busybox-9gsam9260ek.tar.gz
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# cd rootfs/
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# mkdir -pv app dev home mnt proc sys tmp var opt
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# install -dv -m 0750 root
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# mkdir -pv var/{lock,log,lib,run,tmp}
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# mkdir -pv usr/{lib,share}
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# chmod 1777 tmp var/tmp
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# mkdir -pv dev/pts
C,添加动态库文件
root@yuanxh-desktop:/home/yuanxh# cd /usr/local/arm/eldk-4.1/arm
root@yuanxh-desktop:/usr/local/arm/eldk-4.1/arm# tar czvf lib-eldk-4.1.tar.gz lib/
root@yuanxh-desktop:/usr/local/arm/eldk-4.1/arm# mv lib-eldk-4.1.tar.gz /home/yuanxh/at91_works/rootfs-9g9sam9260ek
root@yuanxh-desktop:/usr/local/arm/eldk-4.1/arm# cd /home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# tar xzvf ../lib-eldk-4.1.tar.gz
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# arm-linux-strip --remove-section=.note --remove-section=.comment lib/*.so
注意:可以删除部分不常用字的库以减小体积。
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/lib# rm -rf *.a *.o security gconv
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/lib# rm -rf *.7f *.79 libnss* libmudflap*
D,添加设备节点
root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek/rootfs/
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# cp -dpR /dev/* dev/
E,添加系统配置
在etc/inittab中加入以下内容
#id:3:initdefault:
#su:S016:once:/sbin/sulogin
#si::sysinit:/etc/rc.d/init.d/rc sysinit
#l0:0:wait:/etc/rc.d/init.d/rc 0
3:12345:respawn:/sbin/getty -L ttyS0 115200 vt100
// ::respawn:/sbin/getty -L ttyS1 115200 vt100
// ::respawn:/sbin/getty -L ttyS2 115200 vt100
// ::respawn:/usr/sbin/telnetd
::respawn:/usr/sbin/inetd -f
::shutdown:/bin/mount / o remount,ro
#::ctrlaltdel:/sbin/reboot
#::shutdown:/bin/umount ar
#ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
在etc/fstab中添加入以下内容
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
none /dev/pts devpts mode=0622 0 0
#devpts /dev/pts devpts gid=4,mode=620 0 0
#shm /dev/shm tmpfs defaults 0 0
在etc/profile中添加入以下内容
#set patch
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH
#alias command
alias ll='ls -l'
alias la='ls -a'
alias du='du -h'
alias df='df -h'
在/etc/init.d/rcS中添加入以下内容
/sbin/ifconfig lo 127.0.0.1
/sbin/ifconfig eth0 192.168.1.10
/bin/mount /dev/pts
dmesg > /var/log/dmesg
#hostname F /etc/hostname
hostname 9gsam9260-Linux
# mount fs
/bin/mount -o remount,rw /
# display
echo 'rootfs version 2.6.23-9gsam9260ek (yuanxihua@y21cn.com) (gcc version 4.0.0 (DENX ELDK 4.1 4.0.0))' > /dev/ttyS0
cat /root/build_time > /dev/ttyS0
/app/appinit.sh
启动/etc/init.d/rcS可执行权限
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# chmod a+x /etc/init.d/rcS
命令建立etc/passwd文件
cat > etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/sh
EOF
复制部分配置文件
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# cd rootfs/etc/
// root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/nsswitch.conf .
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/group .
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/shadow .
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/inetd.conf .
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/passwd .
修改etc/passwd,使root登陆后执行程序为bin/sh
F,添加可加载模块
root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rz
利用SecureCRT发送modules-2.6.23-9gsam9260ek.tar.gz
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# tar xzvf modules-2.6.23-9gsam9260ek.tar.gz
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rm -rf rootfs/lib/modules/*
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# mv modules-2.6.23-9gsam9260ek/lib/modules/* rootfs/lib/modules/
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rm -rf modules-2.6.23-9gsam9260ek
G,添加其它命令和应用程序
root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rz
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# cd rootfs/bin/
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/bin# tar xzvf ../../rzsz-9gsam9260ek.tar.gz
4,打包成RAMDISK根文件系统
A,进入根文件系统目录
root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek
B,然后执行如下脚本:
mkdir ramdisk
dd if=/dev/zero of=ramdisk.img bs=1k count=8192
mke2fs -F -v -m 0 -N 2000 ramdisk.img
mount -t ext2 -o loop ramdisk.img ramdisk
cp -av rootfs/* ramdisk/
umount ramdisk
gzip -9 < ramdisk.img > initrd.bin
#mv ramdisk.img initrd.bin
rm -rf ramdisk-2.6.23-9gsam9260ek.bin
mv initrd.bin ramdisk-2.6.23-9gsam9260ek.bin
cp ramdisk-2.6.23-9gsam9260ek.bin /tftpboot/
rm -rf ramdisk.img
rm -rf ramdisk
C,发送RAMDISK文件系统目标码
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# sz ramdisk-2.6.23-9gsam9260ek.bin
5,打包成JFFS2根文件系统
A,利用ELDK-4.1中的mkfs.jffs2命令打包
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# mkfs.jffs2 -d rootfs/ -o jffs2-2.6.23-9gsam9260ek.bin
B,发送目标码
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# sz jffs2-2.6.23-9gsam9260ek.bin
C,本机测试JFFS2文件系统
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rmmod mtdram
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# modprobe mtdram total_size=29568 erase_size=128
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# modprobe mtdblock
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# modprobe mtdchar
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# cat /proc/mtd
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# dd if=jffs2-2.6.23-9gsam9260ek.bin of=/dev/mtd0
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# mount -t jffs2 /dev/mtdblock0 /mnt
D,修改JFFS2文件系统内容
添加内容到/mnt,然后执行如下命令:
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# umount /mnt
root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# dd if=/dev/mtd0 of=jffs2-2.6.23-9gsam9260ek.new.bin
九,固化目标码到9GSAM9260EK中
1,安装ISP工具
双击Install AT91-ISP v1.10.exe,按NEXT;按I Agree,按NEXT,按install;
9GSAM9260EK V20 linux代码烧录过程
使用dataflash
1.J1接通2-3,J2跳开,J4,J5跳开,连上USB线,识别USB设备后,
2.启动SAM-BA v2.6,用\usb\ARM0和AT91SAM9260-EK配置,进入sam-ba,
选择DataFlash AT45DB/DCB页面,合上J5,
3.在Scripts中选择Enable Dataflash on CS1,点击旁边的Execute,
4.在Scripts中选择Erase All,点击旁边的Execute,
5.在Scripts中选择Send Boot File,在Address框中填入0x0,
点击旁边的Execute,在弹出的打开框中选择
dataflash_at91sam9260ek.bin ,
或者
9gsam9260ek-dfboot.bin ,
6.点击Send File Name框旁边的Browse,在弹出的打开框中选择
u-boot-env-df.bin,
在Internal Address框中填入 0x8000 ,
点击Send File
DATAFLASH空间不足,以下参照NAND部分7,8,9。
{
7.点击Send File Name框旁边的Browse,在弹出的打开框中选择
uImage-2.6.23-9gsam9260ek.bin,
在Internal Address框中填入 0x30000 ,
点击Send File
8.点击Send File Name框旁边的Browse,在弹出的打开框中选择
ramdisk-2.6.23-9gsam9260ek.bin,
在Internal Address框中填入 0x300000 ,
点击Send File
9.连上调试串口,复位9GSAM9260EK,看看效果。
setenv bootcmd cp.b 0xD0030000 0x21500000 0x00200000\;cp.b 0xD0300000 0x21100000 0x00400000\;bootm 0x21500000
回车,再输入
saveenv。
}
10.现在手动烧录完成,复位9GSAM9260EK,进入linux。
使用nandflash
1.J1接通2-3,J2跳开,J4,J5跳开,连上USB线,识别USB设备后,
2.启动SAM-BA v2.6,用\usb\ARM0和AT91SAM9260-EK配置,进入sam-ba,
选择NandFlash页面,合上J4,
3.在Scripts中选择NandFlash Init,点击旁边的Execute,
4.在Scripts中选择NandFlash Erase All,点击旁边的Execute,
5.在Scripts中选择NandFlash Send Boot File,在Address框中填入0x0,
点击旁边的Execute,在弹出的打开框中选择
nandflash_at91sam9260ek.bin,
6.点击Send File Name框旁边的Browse,在弹出的打开框中选择
u-boot-env-nf.bin,
在Address框中填入 0x00020000 ,
点击Send File
7.点击Send File Name框旁边的Browse,在弹出的打开框中选择
uImage-2.6.23-9gsam9260ek.bin,
在Address框中填入 0x00100000 ,
点击Send File
8.点击Send File Name框旁边的Browse,在弹出的打开框中选择
ramdisk-2.6.23-9gsam9260ek.bin,
在Address框中填入 0x00300000 ,
点击Send File
9.连上调试串口,reste 9260-ek,进入u-boot,输入
setenv bootcmd nand read 0x21500000 0x100000 0x200000\;nand read 0x21100000 0x300000 0x400000\;bootm 0x21500000
回车,再输入
saveenv
10.现在手动烧录完成,复位9GSAM9260EK,进入linux。
不用u-boot
1.J1接通2-3,J2跳开,J4,J5跳开,连上USB线,识别USB设备后,
2.启动SAM-BA v2.6,用\usb\ARM0和AT91SAM9260-EK配置,进入sam-ba,
选择NandFlash页面,合上J4,
3.在Scripts中选择NandFlash Init,点击旁边的Execute,
4.在Scripts中选择NandFlash Erase All,点击旁边的Execute,
5.在Scripts中选择NandFlash Send Boot File,在Address框中填入 0x0 ,
点击旁边的Execute,在弹出的打开框中选择
9gsam9260ek-nfboot.bin ,
6.点击Send File Name框旁边的Browse,在弹出的打开框中选择
uImage-2.6.23-9gsam9260ek.bin,
在Address框中填入 0x00100000 ,
点击Send File
7.点击Send File Name框旁边的Browse,在弹出的打开框中选择
ramdisk-2.6.23-9gsam9260ek.bin,
在Address框中填入 0x00300000 ,
点击Send File
8.现在手动烧录完成,连上DEBUG串口,复位9GSAM9260EK,进入linux。
u-boot网络启动
1.在dataflash或者nandflash里烧录上u-boot-env-df.bin或者u-boot-env-nf.bin;
2.连上DEBUG串口,复位9GSAM9260EK,进入 u-boot;
3.u-boot中配置网络环境变量
setenv serverip 192.168.102.104
setenv ipaddr 192.168.102.105
setenv ethaddr 00:11:22:33:44:55
setenv netmask 255.255.255.0
setenv hostname 9gsam9260ek
setenv gatewayip 192.168.102.254
setenv dnsip 192.168.100.254
setenv hostname 9gsam9260ek
saveenv
4.u-boot中配置启动环境变量
setenv bootfile /tftpboot/uImage-2.6.23-9gsam9260ek.bin
setenv rootpath /tftpboot/rootfs
setenv bootargs mem=64M console=ttyS0,115200 initrd=0x21100000,8388608 root=/dev/ram0 rw init=linuxrc
saveenv
5.网络下载内核和根文件系统
tftp 21500000 uImage-2.6.23-9gsam9260ek.bin
tftp 21100000 ramdisk-2.6.23-9gsam9260ek.bin
保存自动启动命令
setenv bootcmd tftp 21500000 uImage-2.6.23-9gsam9260ek.bin\;tftp 21100000 ramdisk-2.6.23-9gsam9260ek.bin\;bootm 0x21500000
saveenv
6.启动内核
bootm 0x21500000
十,9GSAM9260EK功能测试
1,USB转SD卡读卡器
A,插入SD卡读卡器到USB-HOST
B,加载到/MNT
/ # mount /dev/sda1 /mnt
C,查看
/ # ll mnt
2,SD卡座
A,补丁
http://marc.info/?l=linux-arm-kernel&m=118036170932720&w=2
3,测试USB-DEVICE
A,外接电源启动进入LINUX建立文件
/ # dd if=/dev/zero of=/tmp/usbramdisk.img bs=1k count=8192
B,执行下面命令安装驱动
/ # insmod /lib/modules/2.6.23-9gsam9260ek/kernel/drivers/usb/gadget/g_file_storage.ko file=/tmp/usbramdisk.img stall=0 removable=1
C,插上USB-DEVICE线到XP
D,在XP会出现插入U盘
E,格式化U盘全可以使用
4,测试网络
/ # ifconfig eth0 192.168.1.10
/ # ping 192.168.1.100
/ # tftp -g 192.168.1.100 -r uImage-2.6.23-9gsam9260ek.bin
5,测试远程登陆
在终端上运行查看IP
/ # ifconfig -a
然后启动telnetd服务器端
/ # /usr/sbin/telnetd
然后在SecureCRT上建立一个到开发板IP的telnet连接
测试命令
~ # echo abcd > /dev/ttyS0
在调试串口0上可以看到abcd字符
6,测试其它串口
启用串口1
/ # /sbin/getty -L ttyS1 115200 vt100
串口线接到串口1
在telnet中执行
~ # echo yuanxh > /dev/ttyS1
在调试串口1上可以看到yuanxh字符
在串口1终端上按回车,可以看到登陆信息
9gsam9260-Linux login:
输入用户名密码登陆后
执行
/sbin/getty -L ttyS2 115200 vt100
把串口线接到串口2,按回车出现同样登陆信息
输入用户名密码登陆后就可以登陆。
在网络telnet登陆中执行
~ # echo abcdyuanxh > /dev/ttyS2
在调试串口2上可以看到abcdyuanxh字符
十,9GSAM9260EK功能测试
1,USB转SD卡读卡器
A,插入SD卡读卡器到USB-HOST
B,加载到/MNT
/ # mount /dev/sda1 /mnt
C,查看
/ # ll mnt
2,SD卡座
A,补丁
http://marc.info/?l=linux-arm-kernel&m=118036170932720&w=2
3,测试USB-DEVICE
A,外接电源启动进入LINUX建立文件
/ # dd if=/dev/zero of=/tmp/usbramdisk.img bs=1k count=8192
B,执行下面命令安装驱动
/ # insmod /lib/modules/2.6.23-9gsam9260ek/kernel/drivers/usb/gadget/g_file_storage.ko file=/tmp/usbramdisk.img stall=0 removable=1
C,插上USB-DEVICE线到XP
D,在XP会出现插入U盘
E,格式化U盘全可以使用
4,测试网络
/ # ifconfig eth0 192.168.1.10
/ # ping 192.168.1.100
/ # tftp -g 192.168.1.100 -r uImage-2.6.23-9gsam9260ek.bin
5,测试远程登陆
在终端上运行查看IP
/ # ifconfig -a
然后启动telnetd服务器端
/ # /usr/sbin/telnetd
然后在SecureCRT上建立一个到开发板IP的telnet连接
测试命令
~ # echo abcd > /dev/ttyS0
在调试串口0上可以看到abcd字符
6,测试其它串口
启用串口1
/ # /sbin/getty -L ttyS1 115200 vt100
串口线接到串口1
在telnet中执行
~ # echo yuanxh > /dev/ttyS1
在调试串口1上可以看到yuanxh字符
在串口1终端上按回车,可以看到登陆信息
9gsam9260-Linux login:
输入用户名密码登陆后
执行
/sbin/getty -L ttyS2 115200 vt100
把串口线接到串口2,按回车出现同样登陆信息
输入用户名密码登陆后就可以登陆。
在网络telnet登陆中执行
~ # echo abcdyuanxh > /dev/ttyS2
在调试串口2上可以看到abcdyuanxh字符
9GSAM9260EK开发板简介
AT91SAM9260特性
带Java扩展的ARM926EJ-S内核, 2 x 8KB快速缓存, MMU内存管理单元
■ 2x4 KB SRAM, 32 KB Boot ROM
■ 180 MHz时200 MIPS
■ EBI总线可支持SDRAM, NAND Flash (带ECC)和Compact Flash CARD
■ 外设可支持DMA和FIFO,集成复位控制电路,高速中断
■ USB主控制器和USB从设备口, V2.0全速12M
■ Ethernet MAC - 10/100M
■ 图像传感器接口,10BIT接口,支持SAV和EAV
■ 一个 SSC可支持I2S和TDM
■ 两个 SPI, MCI (SD Card和MMC兼容), TWI
■ 六 USART, 支持IrDA, ISO7816 T=0/T=1, RS-485 RS-232 IRDA
■ 一个调试UART
■ 4-通道 10位ADC
■ 带实时时钟的备用电池供电的下电模式
■ 1个主时钟,1个32.768K时钟, 2 PLL和RTC
■ 3.0到3.6V IO电源,1.65到1.95V内核电源, 3.0到3.6V或1.95到3.0V 存储器电源接口
■ JTAG和边际扫描
■ PQFP-208和LFBGA217
开发板特性:
MPU
at91sam9260(PQFP-208,无铅产品)
存储器
■256MB 8位 NandFlash
■64MB 两片16位 SDRAM
■2MB DataFash
电源(Power)
■USB从设备口取电,或者5V外接
网络(Ethernet)
■一个10/100M网口,带网络变压器的RJ-45接口和板上LED指示灯
USB Host端口
■一路USB 2.0 全速12M Host端口
■支持U盘、鼠标、键盘、摄像头、打印机 等设备
USB Device 端口
■一路USB 2.0 全速12M Device端口
串口(USART)
■一个三线串口,一个五线串口,USART支持RS485和ISO7816协议
Dbgu调试口
■一个专用调试串口
实时时钟
■带后备电池的RTC
■一路CAN-Bus接口,支持CAN2.0A/B协议
■一个SD卡接口(四线方式)
■外接SPI和I2C接口
■外接简易EBI接口,可接LCD
■一路AD接口,板上可调电阻
■一路音频录放接口
■一路触摸屏接口
■四个独立GPIO口按键
■一个外置硬件看门狗和电源电压检测
■JTAG调试接口
■USB器件接口固化代码模式
■四个独立GPIO口按键
■一个外置硬件看门狗和电源电压检测
■JTAG调试接口
■USB器件接口固化代码模式
常用U-BOOT启动代码命令在GEC2440开发板上的应用
printenv
setenv serverip 192.168.1.108
setenv ipaddr 192.168.1.118
setenv ethaddr 08:08:08:08:12:27
setenv netmask 255.255.255.0
setenv gatewayip 192.168.1.1
setenv bootcmd tftp 30800000 uImage-2.6.26-9g24x0.bin;tftp 31000000 ramdisk-2.6.26-9g24x0.bin;bootm 30800000
setenv bootcmd tftp 30800000 uImage-2.6.26-9g24x0.bin;bootm 30800000
setenv bootargs noinitrd root=/dev/nfs rw nfsroot=192.168.1.108:/nfsboot/rootfs ip=192.168.1.118:192.168.1.108::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M
setenv bootargs root=/dev/ram0 rw initrd=0x31000000,0x1000000 console=ttySAC0,115200 init=/linuxrc mem=64M
(1) 查看u-boot的环境变量信息
(2) 设置TFTP服务器的IP地址
(3) 设置本机IP地址
(4) 设置本机MAC地址
(5) 设置本机子域掩码
(6) 设置网关IP地址
(7) 设置默认启动命令下载uImage内核,ramdisk根文件系统并启动uImage内核
(8) 设置默认启动命令下载uImage内核,并启动uImage内核
(9) 设置默认内核启动命令行参数,用于NFS根文件系统启动
(10) 设置默认内核启动命令行参数,用于RAMDISK根文件系统启动
nand info
nand device 0
nand bad
setenv autostart yes
nboot 3100000 0 100000
(1) 查看Nand的信息
(2) 查看Nand设备0的信息
(3) 查看Nand的块块
(4) 设置自动启动,让nboot有效调用启动参数和bootm命令
(5) nboot启动nand的 device设备0上100000的uImage,启动地址为SDRAM的3100000
tftp 32000000 uImage
nand erase 0x100000 0x200000
nand write 0x32000000 0x100000 0x200000
nand read 0x31000000 0x100000 0x200000
bootm 31000000
(1) 从网口下载uImage 到SDRAM的0x32000000处
(2) 从1M处开始擦写Nand Flash,擦写2M大小的空间
(3) 将SDRAM中的0x32000000处开始的内容uImage,烧写到Nand Flash的0x100000处开始的2M空间内,掉电能保存。
(4) 将Nand Flash的0x100000处开始的2M空间内容uImage,拷贝到SDRAM中0x31000000处开始的地方
(5) 启动uImage
fli
(1) 查看nor flash的信息
protect off all
erase 80000 1fffff
tftp 32000000 uImage
cp.b 32000000 80000 180000
cp.b 80000 31000000 180000
bootm 31000000
(1) 命令打开nor flash写保护
(2) 从80000 (前512K留给U-BOOT及参数存储空间)处开始擦写nor Flash后面全部,(擦写1M5大小的空间)
(3) 从网口下载uImage 到SDRAM的0x32000000处
(4) 将SDRAM中的0x32000000处开始的内容uImage,烧写到nor Flash的80000处开始的1M5空间内,掉电能保存。
(5) 将nor Flash的80000处开始的1M5空间内容uImage,拷贝到SDRAM中0x31000000处开始的地方
(6) 启动uImage
protect off all
erase 0 5ffff
tftp 32000000 u-boot-fs2410.bin.lcd.bf2
cp.b 32000000 0 5ffff
(1) 命令打开nor flash写保护
(2) 从0处开始擦写nor Flash 384KB 大小的空间
(3) 从网口下载u-boot-fs2410.bin.lcd.bf2 到SDRAM的0x32000000处
(4) 将SDRAM中的0x32000000处开始的内容u-boot-fs2410.bin.lcd.bf2,烧写到nor Flash的0处开始的384KB空间内,掉电能保存。
常用UBUNTU的包管理命令。
dpkg -l | less
dpkg -L abcd
dpkg -S abcdef
dpkg -i abcd.deb
apt-cache search abcd
apt-cache show abcd
apt-get install abcd
apt-get remove abcd
apt-get--purge remove abcd
apt-get source abcd
(1) 列出系统中dpkg跟踪到的所有的包
(2) 列出abcd包中包括的文件
(3) 列出abcdef命令属于的软件包
(4) 手动安装abcd.deb软件包
(5) 列出包含abcd字符内容的所有包
(6) 列出abcd包的详细信息
(7) 网络下载安装abcd软件包
(8) 卸载abcd软件包
(9) 完全卸载abcd软件包
(10)网络下载abcd软件包的源码
移植directvnc-0.7.5到GEC2440开发板
1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/s3c2410# wget http://www.adam-lilienthal.de/directvnc/directvnc-0.7.5.tar.gz
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xzvf directvnc-0.7.5.tar.gz
2,配置编译源码:
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd directvnc-0.7.5
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5# ./configure
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5# make
(编译有错,不用理会!!!只是生成个用到的config.h)
3,重建源码包目录:
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5# cd ..
root@yuanxh-desktop:/home/yuanxh/s3c2410# mkdir directvnc-0.7.5-9g24x0 directvnc-0.7.5-9g24x0/include
root@yuanxh-desktop:/home/yuanxh/s3c2410# cp directvnc-0.7.5/src/*.c directvnc-0.7.5-9g24x0/
root@yuanxh-desktop:/home/yuanxh/s3c2410# cp directvnc-0.7.5/config.h directvnc-0.7.5-9g24x0/include/
root@yuanxh-desktop:/home/yuanxh/s3c2410# cp directvnc-0.7.5/src/*.h directvnc-0.7.5-9g24x0/include/
4,添加缺少的头文件:
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd directvnc-0.7.5-9g24x0/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/X11/Xmd.h include/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/X11/keysymdef.h include/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/jpeglib.h include/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/jconfig.h include/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/jmorecfg.h include/
5,修改不对的源文件:
A,include/directvnc.h文件:
把31行: #include <X11/Xmd.h>
修改成: #include <Xmd.h> // charge by yuanxihua@21cn.com
B,include/keysym.h文件:
把69行: #include <X11/keysymdef.h>
修改成: #include <keysymdef.h> // charge by yuanxihua@21cn.com
C,dfb.c文件:
把33行: DFBCardCapabilities caps;
修改成 DFBGraphicsDeviceDescription caps; // charge by yuanxihua@21cn.com
(可能是新版本的DFB已经更新了结构体定义)
把45行: DFBCHECK(DirectFBSetOption ("quiet", ""));
修改成 //charge by yuanxihua@21cn.com DFBCHECK(DirectFBSetOption ("quiet", ""));
(可能是新版本的DFB不支持这种配置)
把70行: DFBCHECK(dfb->GetInputDevice( dfb, DIDID_MOUSE, &mouse ));
修改成 //charge by yuanxihua@21cn.com DFBCHECK(dfb->GetInputDevice( dfb, DIDID_MOUSE, &mouse ));
(因为我的系统鼠标驱动/dev/input/mouse0 [设备号13, 32]还没有实现)
6,按附录增加Makefile:
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# vi Makefile
7,编译生成目标码:
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# make
(就可以生成可执行文件directvnc)
8,添加库文件到目标板:
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cd /nfsboot/rootfs/usr/
root@yuanxh-desktop:/nfsboot/rootfs/usr# mkdir directfb
root@yuanxh-desktop:/nfsboot/rootfs/usr# cp -av /usr/directfb/* directfb/
root@yuanxh-desktop:/nfsboot/rootfs/usr# cd ../lib/
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libdirect-1.3.so.0* .
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libdirectfb-1.3.so.0* .
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libfusion-1.3.so.0* .
9,在目标板上运行:
./app/directvnc 192.168.1.2:0 -p 123456
(其中192.168.1.2是运行了VNC服务器的IP地址,:0是启动的服务端口5800后面的偏移号,-p 后是登陆密码
运行过程如果缺什么库请自行交叉编译添加到根文件系统的/lib目录,如libjpeg.so* 和 libz.so* 库)
附录:Makefile 文件:
# Makefile for directvnc-0.7.5-9g24x0, (c) 2008 yuanxihua@21cn.com
CROSS_COMPILE=arm-linux-
PKG_CONFIG =/usr/directfb/lib/pkgconfig
INCLUDE=./include
DIRECTFB=/usr/directfb
CCOPTS = -Wall -O2 -I$(INCLUDE) -I$(DIRECTFB)/include/directfb/ -L$(DIRECTFB)/lib/ \
-ldirectfb -lfusion -ldirect -lpthread -ljpeg -lm -lz
ASOPTS =
LDOPTS =
CC = $(CROSS_COMPILE)gcc
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
OBJS= args.o cursor.o d3des.o dfb.o getopt.o getopt1.o \
jpeg.o main.o rfb.o sockets.o tight.o vncauth.o
all: $(OBJS)
$(CC) $(CCOPTS) -o directvnc $(OBJS)
cp directvnc /nfsboot/rootfs/app/
.c.o:
$(CC) $(CCOPTS) -c -o $*.o $<
.S.o:
$(AS) $(ASOPTS) -o $*.o $<
clean:
rm -f core *.o *~ *.bak *.tmp
miniclean:
rm -f *.o
移植DirectFB-1.3.0到GEC2440开发板
1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/s3c2410# wget http://www.directfb.org/downloads/Core/DirectFB-1.3.0.tar.gz
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xzvf DirectFB-1.3.0.tar.gz
root@yuanxh-desktop:/home/yuanxh/s3c2410# mv DirectFB-1.3.0 DirectFB-1.3.0-9g24x0
2,建立编译脚本:
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd DirectFB-1.3.0-9g24x0
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# ./configure --help
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# vi mkall
在脚本中填入以下内容:
CC=arm-linux-gcc LD=arm-linux-ld ./configure --prefix=/usr/directfb\
--host=arm-linux --target=arm-linux\
--enable-png=no --enable-jpeg \
--enable-fbdev --enable-freetype=no --sysconfdir=/etc
make
make install
3,去掉OMAP驱动:
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# cp gfxdrivers/Makefile.in gfxdrivers/Makefile.in.org
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# cp gfxdrivers/Makefile.am gfxdrivers/Makefile.am.org
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# vi gfxdrivers/Makefile.in
把其中299行:$(OMAP_DIR) \ 删除
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# vi gfxdrivers/Makefile.am
把其中144行:$(OMAP_DIR) \ 删除
(OMAP驱动是TI的OMAP系列CPU专用的,在此应用中缺少头文件,引起编译出错)
4,配置编译安装:
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# chmod 777 mkall
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# ./mkall
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# ll /usr/
5,添加到文件系统:
root@yuanxh-desktop:/usr# cd /nfsboot/rootfs/usr/
root@yuanxh-desktop:/nfsboot/rootfs/usr# mkdir directfb
root@yuanxh-desktop:/nfsboot/rootfs/usr# cp -av /usr/directfb/* directfb/
root@yuanxh-desktop:/nfsboot/rootfs/usr# cd ../lib/
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libdirect-1.3.so.0* .
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libdirectfb-1.3.so.0* .
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libfusion-1.3.so.0* .
6,建立directfb配置脚本:
root@yuanxh-desktop:/nfsboot/rootfs/usr# cd /nfsboot/rootfs
root@yuanxh-desktop:/nfsboot/rootfs# vi etc/directfbrc
在脚本中填入以下内容:
system=fbdev
fbdev=/dev/fb0
mode=320x240
depth=16
pixelformat=RGB16
移植busybox-1.13.0到GEC2440开发板
1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/s3c2410# wget http://busybox.net/downloads/busybox-1.13.0.tar.bz2
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xjvf busybox-1.13.0.tar.bz2
root@yuanxh-desktop:/home/yuanxh/s3c2410# mv busybox-1.13.0 busybox-1.13.0-9g24x0
2,修改Makefile:
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd busybox-1.13.0-9g24x0/
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# cp Makefile Makefile.org
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# vi Makefile
把第4行: EXTRAVERSION =
修改成: EXTRAVERSION =-9g24x0
把第164行: CROSS_COMPILE ?=
修改成: CROSS_COMPILE ?=arm-linux-
3,默认配置:
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make help
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make defconfig
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make
3,修改配置:
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make menuconfig
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make install
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# tar czvf busybox-1.13.0-9g24x0-bin.tar.gz _install/
4,安装到文件系统:
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# rm -rf /nfsboot/rootfs/bin/ /nfsboot/rootfs/sbin/ /nfsboot/rootfs/usr/ /nfsboot/rootfs/linuxrc
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# mv _install/* /nfsboot/rootfs/
添加touchscreen驱动到基于linux-2.6.26的GEC2440开发板
1,修改drivers/input/touchscreen/Makefile文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/input/touchscreen/Makefile
在第24行添加:
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
2,修改drivers/input/touchscreen/Kconfig文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/input/touchscreen/Kconfig
在第188行添加:
config TOUCHSCREEN_S3C2410
tristate "Samsung S3C2410 touchscreen input driver"
depends on ARCH_SMDK2410 && INPUT && INPUT_TOUCHSCREEN
select SERIO
help
Say Y here if you have the s3c2410 touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called s3c2410_ts.
config TOUCHSCREEN_S3C2410_DEBUG
boolean "Samsung S3C2410 touchscreen debug messages"
depends on TOUCHSCREEN_S3C2410
help
Select this if you want debug messages
3,编译配置内核
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make menuconfig
进入配置菜单添加驱动到内核:
Device Drivers --->
Input device support --->
[*] Touchscreens --->
<*> Samsung S3C2410 touchscreen input driver
[*] Samsung S3C2410 touchscreen debug messages
4,修改arch/arm/mach-s3c2440/mach-smdk2440.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi arch/arm/mach-s3c2440/mach-smdk2440.c
在166行添加:
static struct s3c2410_ts_mach_info gec2440_ts_cfg __initdata = {
.delay = 10000,
.presc = 49,
.oversampling_shift = 2,
};
在static struct platform_device *smdk2440_devices[] __initdata = {结构中添加:
&s3c_device_ts,
在static void __init smdk2440_map_io(void)函数中添加:
s3c24xx_init_touchscreen(&gec2440_ts_cfg);
5,修改include/asm-arm/plat-s3c24xx/devs.h文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi include/asm-arm/plat-s3c24xx/devs.h
在第18行添加:
// add by yuanxihua@21cn.com
struct s3c2410_ts_mach_info {
int delay;
int presc;
int oversampling_shift;
};
void __init s3c24xx_init_touchscreen(struct s3c2410_ts_mach_info *hard_s3c2410_ts_info);
extern struct platform_device s3c_device_ts;
// add by yuanxihua@21cn.com
6,修改arch/arm/plat-s3c24xx/devs.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi arch/arm/plat-s3c24xx/devs.c
在第598行添加:
// add by yuanxihua@21cn.com
// Touchscreen
static struct s3c2410_ts_mach_info s3c2410_ts_info;
void __init s3c24xx_init_touchscreen(struct s3c2410_ts_mach_info *hard_s3c2410_ts_info)
{
memcpy(&s3c2410_ts_info,hard_s3c2410_ts_info,sizeof(struct s3c2410_ts_mach_info));
}
EXPORT_SYMBOL(s3c24xx_init_touchscreen);
struct platform_device s3c_device_ts = {
.name = "s3c2410-ts",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_adc_resource),
.resource = s3c_adc_resource,
.dev = {
.platform_data = &s3c2410_ts_info,
}
};
EXPORT_SYMBOL(s3c_device_ts);
// add by yuanxihua@21cn.com
7,添加drivers/input/touchscreen/s3c2410_ts.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/input/touchscreen/s3c2410_ts.c
添加的源码见附件。
8,编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make
9,在内核启动可以看到input: s3c2410 Touchscreen as /class/input/input0
注册信息为:
# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0001 Product=0002 Version=0100
N: Name="s3c2410 Touchscreen"
P: Phys=s3c2410ts/input0
S: Sysfs=/class/input/input0
U: Uniq=
H: Handlers=mouse0 event0
B: EV=b
B: KEY=400 0 0 0 0 0 0 0 0 0 0
B: ABS=1000003
设备结点为:
# ll /dev/input/
crw-rw---- 1 root root 13, 64 Dec 10 2008 event0
crw-rw---- 1 root root 13, 32 Dec 7 2008 mouse0
附件:
/* drivers/input/touchscreen/s3c2410_ts.c
*
* Touchscreen driver for GEC2440 with Samsung S3C2440A
*
* modify from corgi_ts.c
*
* Copyright (c) 2004-2005 Richard Purdie
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/plat-s3c/regs-adc.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-clock.h>
#include <asm/plat-s3c24xx/devs.h>
#include <asm/plat-s3c24xx/clock.h>
#define WAIT4INT(x) (((x)<<8) | \
S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_XY_PST(3))
#define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
#define DEBUG_LVL KERN_DEBUG
#define X_AXIS_MAX 0x3ff
#define X_AXIS_MIN 0
#define Y_AXIS_MAX 0x3ff
#define Y_AXIS_MIN 0
#define PRESSURE_MIN 0
#define PRESSURE_MAX 1
/*
* Definitions & global arrays.
*/
/*
* Per-touchscreen data.
*/
struct ts_event {
short pressure;
short xp;
short yp;
};
struct s3c2410_ts {
struct input_dev *input;
struct resource *res;
struct timer_list timer;
struct ts_event tc;
int pendown;
int count;
int shift;
struct resource *irq_gpio[2];
struct s3c2410_ts_mach_info *machinfo;
};
static void __iomem *base_addr;
static inline void s3c2410_ts_connect(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
}
static void touch_timer_fire(struct s3c2410_ts *s3c2410_ts,unsigned long data)
{
unsigned long data0;
unsigned long data1;
struct input_dev *dev = s3c2410_ts->input;
/* Disable Interrupt */
set_irq_type(s3c2410_ts->irq_gpio[0]->start, IRQT_NOEDGE);
set_irq_type(s3c2410_ts->irq_gpio[1]->start, IRQT_NOEDGE);
data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1);
s3c2410_ts->pendown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
if (s3c2410_ts->pendown) {
if (s3c2410_ts->count != 0) {
s3c2410_ts->tc.xp >>= s3c2410_ts->shift;
s3c2410_ts->tc.yp >>= s3c2410_ts->shift;
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
{
struct timeval tv;
do_gettimeofday(&tv);
printk(KERN_INFO "T: %06d, X: %03x, Y: %03x\n", (int)tv.tv_usec, s3c2410_ts->tc.xp, s3c2410_ts->tc.yp);
}
#endif
input_report_abs(dev, ABS_X, s3c2410_ts->tc.xp);
input_report_abs(dev, ABS_Y, s3c2410_ts->tc.yp);
input_report_abs(dev, ABS_PRESSURE, s3c2410_ts->tc.pressure);
input_report_key(dev, BTN_TOUCH, s3c2410_ts->pendown);
input_sync(dev);
}
s3c2410_ts->tc.xp = 0;
s3c2410_ts->tc.yp = 0;
s3c2410_ts->count = 0;
s3c2410_ts->tc.pressure = 0;
writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else {
s3c2410_ts->count = 0;
input_report_key(dev, BTN_TOUCH, 0);
input_report_abs(dev, ABS_PRESSURE, 0);
input_sync(dev);
writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
}
/* Enable Falling Edge */
set_irq_type(s3c2410_ts->irq_gpio[0]->start, IRQT_BOTHEDGE);
set_irq_type(s3c2410_ts->irq_gpio[1]->start, IRQT_BOTHEDGE);
}
static void s3c2410_ts_timer(unsigned long data)
{
struct s3c2410_ts *s3c2410ts_data = (struct s3c2410_ts *) data;
touch_timer_fire(s3c2410ts_data, 1);
}
static irqreturn_t stylus_updown(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long data0;
unsigned long data1;
struct s3c2410_ts *s3c2410_ts = dev_id;
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
printk(KERN_ERR "%s() No.%d line:\n\r",__FUNCTION__,__LINE__);
#endif
data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1);
s3c2410_ts->pendown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT1_UPDOWN));
/* TODO we should never get an interrupt with updown set while
* the timer is running, but maybe we ought to verify that the
* timer isn't running anyways. */
if (s3c2410_ts->pendown)
touch_timer_fire(s3c2410_ts, 0);
return IRQ_HANDLED;
}
static irqreturn_t stylus_action(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long data0;
unsigned long data1;
struct s3c2410_ts *s3c2410_ts = dev_id;
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
printk(KERN_ERR "%s() No.%d line:\n\r",__FUNCTION__,__LINE__);
#endif
data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1);
s3c2410_ts->tc.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
s3c2410_ts->tc.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
s3c2410_ts->count++;
s3c2410_ts->tc.pressure = 1;
if (s3c2410_ts->count < (1<<s3c2410_ts->shift)) {
writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else {
mod_timer(&s3c2410_ts->timer, jiffies + HZ / 100);
writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
}
return IRQ_HANDLED;
}
static struct clk *adc_clock;
/*
* The functions for inserting/removing us as a module.
*/
#define s3c2410ts_suspend NULL
#define s3c2410ts_resume NULL
static int __init s3c2410ts_probe(struct platform_device *pdev)
{
struct s3c2410_ts *s3c2410_ts;
struct input_dev *input_dev;
int size;
int err = -ENOMEM;
s3c2410_ts = kzalloc(sizeof(struct s3c2410_ts), GFP_KERNEL);
input_dev = input_allocate_device();
if (!s3c2410_ts || !input_dev)
goto fail1;
platform_set_drvdata(pdev, s3c2410_ts);
s3c2410_ts->machinfo = pdev->dev.platform_data;
s3c2410_ts->irq_gpio[0] = platform_get_resource(pdev, IORESOURCE_IRQ,0);
s3c2410_ts->irq_gpio[1] = platform_get_resource(pdev, IORESOURCE_IRQ,1);
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
printk(KERN_ERR "s3c2410_ts->irq_gpio[0] = %d,IRQ_TC = %d\n",s3c2410_ts->irq_gpio[0]->start,IRQ_TC);
printk(KERN_ERR "s3c2410_ts->irq_gpio[1] = %d,IRQ_ADC = %d\n",s3c2410_ts->irq_gpio[1]->start,IRQ_ADC);
#endif
if ((s3c2410_ts->irq_gpio[0]->start < 0)|(s3c2410_ts->irq_gpio[1]->start < 0)) {
err = -ENODEV;
printk(KERN_ERR "Hm... too bad : no irq for ts\n");
goto fail1;
}
if (!s3c2410_ts->machinfo)
{
printk(KERN_ERR "Hm... too bad : no platform data for ts\n");
return -EINVAL;
}
s3c2410_ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (s3c2410_ts->res == NULL) {
printk(KERN_ERR "no memory resource specified\n");
return -ENOENT;
}
adc_clock = clk_get(NULL, "adc");
if (!adc_clock) {
printk(KERN_ERR "failed to get adc clock source\n");
return -ENOENT;
}
clk_enable(adc_clock);
size = (s3c2410_ts->res->end-s3c2410_ts->res->start)+1;
base_addr=ioremap(s3c2410_ts->res->start, size);
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
printk(KERN_ERR "ioremap %08x to base_addr=%08x , size=%08x\n",s3c2410_ts->res->start,(unsigned int)base_addr,size);
#endif
if (base_addr == NULL) {
printk(KERN_ERR "Failed to remap register block\n");
return -ENOMEM;
}
/* Configure GPIOs */
s3c2410_ts_connect();
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
printk(KERN_ERR "s3c2410_ts->machinfo delay = %d,presc = %d,oversampling_shift = %d\n",
s3c2410_ts->machinfo->delay,
s3c2410_ts->machinfo->presc,
s3c2410_ts->machinfo->oversampling_shift);
#endif
if ((s3c2410_ts->machinfo->presc&0xff) > 0)
writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(s3c2410_ts->machinfo->presc&0xFF),\
base_addr+S3C2410_ADCCON);
else
writel(0,base_addr+S3C2410_ADCCON);
/* Initialise the adcdly registers */
if ((s3c2410_ts->machinfo->delay&0xffff) > 0)
writel(s3c2410_ts->machinfo->delay & 0xffff, base_addr+S3C2410_ADCDLY);
writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
__raw_writel(__raw_readl(S3C2410_GPGCON)|(0xff<<24), S3C2410_GPGCON);
s3c2410_ts->input = input_dev;
init_timer(&s3c2410_ts->timer);
s3c2410_ts->timer.data = (unsigned long) s3c2410_ts;
s3c2410_ts->timer.function = s3c2410_ts_timer;
// input_dev->private = s3c2410_ts;
input_dev->name = "s3c2410 Touchscreen";
input_dev->phys = "s3c2410ts/input0";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0002;
input_dev->id.version = 0x0100;
// input_dev->dev.parent = &pdev->dev;
s3c2410_ts->shift = s3c2410_ts->machinfo->oversampling_shift;
input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
/* Get irqs */
if (request_irq(s3c2410_ts->irq_gpio[1]->start, stylus_action, IRQF_DISABLED, pdev->name, s3c2410_ts)) {
printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");
iounmap(base_addr);
err = -EBUSY;
goto fail1;
}
if (request_irq(s3c2410_ts->irq_gpio[0]->start, stylus_updown, IRQF_DISABLED, pdev->name, s3c2410_ts)) {
printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
iounmap(base_addr);
err = -EBUSY;
goto fail1;
}
/* All went ok, so register to the input system */
err = input_register_device(s3c2410_ts->input);
if (err)
goto fail2;
/* Enable Falling Edge */
set_irq_type(s3c2410_ts->irq_gpio[0]->start, IRQT_BOTHEDGE);
set_irq_type(s3c2410_ts->irq_gpio[1]->start, IRQT_BOTHEDGE);
return 0;
fail2: free_irq(s3c2410_ts->irq_gpio, s3c2410_ts);
fail1: input_free_device(input_dev);
kfree(s3c2410_ts);
return err;
}
static int s3c2410ts_remove(struct platform_device *pdev)
{
struct s3c2410_ts *s3c2410_ts = platform_get_drvdata(pdev);
disable_irq(s3c2410_ts->irq_gpio[0]->start);
disable_irq(s3c2410_ts->irq_gpio[1]->start);
free_irq(s3c2410_ts->irq_gpio[0]->start,s3c2410_ts);
free_irq(s3c2410_ts->irq_gpio[1]->start,s3c2410_ts);
del_timer_sync(&s3c2410_ts->timer);
if (adc_clock) {
clk_disable(adc_clock);
clk_put(adc_clock);
adc_clock = NULL;
}
input_unregister_device(s3c2410_ts->input);
iounmap(base_addr);
kfree(s3c2410_ts);
return 0;
}
static struct platform_driver s3c2410ts_driver = {
.probe = s3c2410ts_probe,
.remove = s3c2410ts_remove,
.suspend = s3c2410ts_suspend,
.resume = s3c2410ts_resume,
.driver = {
.name = "s3c2410-ts",
.owner = THIS_MODULE,
},
};
static int __devinit s3c2410ts_init(void)
{
return platform_driver_register(&s3c2410ts_driver);
}
static void __exit s3c2410ts_exit(void)
{
platform_driver_unregister(&s3c2410ts_driver);
}
module_init(s3c2410ts_init);
module_exit(s3c2410ts_exit);
MODULE_AUTHOR("9g2440 <yuanxihua@21cn.com>");
MODULE_DESCRIPTION("s3c2440 TouchScreen Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:s3c2410-ts");
添加CS8900A的NET驱动到基于linux-2.6.26的GEC2440开发板
1,修改drivers/net/arm/Makefile文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/net/arm/Makefile
在第12行添加:
obj-$(CONFIG_ARM_CS8900) += cs8900.o
2,修改drivers/net/arm/Kconfig文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/net/arm/Kconfig
在第5行添加:
config ARM_CS8900
tristate "CS8900 support"
depends on NET_ETHERNET && ARM && ARCH_SMDK2410
help
support for cs8900 chipset based Ethernet cards , if you have a network card of this type.
3,编译配置内核
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make menuconfig
进入配置菜单添加驱动到内核:
Device Drivers --->
[*] Network device support --->
[*] Ethernet (10 or 100Mbit) --->
<*> CS8900 support
4,修改arch/arm/mach-s3c2440/mach-smdk2440.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi arch/arm/mach-s3c2440/mach-smdk2440.c
在static struct map_desc smdk2440_iodesc[] __initdata 最后添加:
, {
.virtual = (u32)0xE0000000,
.pfn = __phys_to_pfn(S3C2410_CS3 + (1<<24)),
.length = SZ_1M,
.type = MT_DEVICE,
}//change by yuanxihua@21cn.com
5,修改include/asm-arm/plat-s3c24xx/common-smdk.h文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi include/asm-arm/plat-s3c24xx/common-smdk.h
在14行添加:
//change by yuanxihua@21cn.com
#define pSMDK2410_ETH_IO __phys_to_pfn(0x19000000)
#define vSMDK2410_ETH_IO 0xE0000000
#define SMDK2410_ETH_IRQ IRQ_EINT9
6,添加drivers/net/arm/cs8900.h文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/net/arm/cs8900.h
添加的源码见附件。
7,添加drivers/net/arm/cs8900.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/net/arm/cs8900.c
添加的源码见附件。
8, 编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make
附件:
//drivers/net/arm/cs8900.h
#ifndef CS8900_H
#define CS8900_H
/*
* linux/drivers/net/cs8900.h
*
* Author: Abraham van der Merwe <abraham at 2d3d.co.za>
*
* A Cirrus Logic CS8900A driver for Linux
* based on the cs89x0 driver written by Russell Nelson,
* Donald Becker, and others.
*
* This source code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
/*
* Ports
*/
#define PP_Address 0x0a /* PacketPage Pointer Port (Section 4.10.10) */
#define PP_Data 0x0c /* PacketPage Data Port (Section 4.10.10) */
/*
* Registers
*/
#define PP_ProductID 0x0000 /* Section 4.3.1 Product Identification Code */
#define PP_MemBase 0x002c /* Section 4.9.2 Memory Base Address Register */
#define PP_IntNum 0x0022 /* Section 3.2.3 Interrupt Number */
#define PP_EEPROMCommand 0x0040 /* Section 4.3.11 EEPROM Command */
#define PP_EEPROMData 0x0042 /* Section 4.3.12 EEPROM Data */
#define PP_RxCFG 0x0102 /* Section 4.4.6 Receiver Configuration */
#define PP_RxCTL 0x0104 /* Section 4.4.8 Receiver Control */
#define PP_TxCFG 0x0106 /* Section 4.4.9 Transmit Configuration */
#define PP_BufCFG 0x010a /* Section 4.4.12 Buffer Configuration */
#define PP_LineCTL 0x0112 /* Section 4.4.16 Line Control */
#define PP_SelfCTL 0x0114 /* Section 4.4.18 Self Control */
#define PP_BusCTL 0x0116 /* Section 4.4.20 Bus Control */
#define PP_TestCTL 0x0118 /* Section 4.4.22 Test Control */
#define PP_ISQ 0x0120 /* Section 4.4.5 Interrupt Status Queue */
#define PP_TxEvent 0x0128 /* Section 4.4.10 Transmitter Event */
#define PP_BufEvent 0x012c /* Section 4.4.13 Buffer Event */
#define PP_RxMISS 0x0130 /* Section 4.4.14 Receiver Miss Counter */
#define PP_TxCOL 0x0132 /* Section 4.4.15 Transmit Collision Counter */
#define PP_SelfST 0x0136 /* Section 4.4.19 Self Status */
#define PP_BusST 0x0138 /* Section 4.4.21 Bus Status */
#define PP_TxCMD 0x0144 /* Section 4.4.11 Transmit Command */
#define PP_TxLength 0x0146 /* Section 4.5.2 Transmit Length */
#define PP_IA 0x0158 /* Section 4.6.2 Individual Address (IEEE Address) */
#define PP_RxStatus 0x0400 /* Section 4.7.1 Receive Status */
#define PP_RxLength 0x0402 /* Section 4.7.1 Receive Length (in bytes) */
#define PP_RxFrame 0x0404 /* Section 4.7.2 Receive Frame Location */
#define PP_TxFrame 0x0a00 /* Section 4.7.2 Transmit Frame Location */
/*
* Values
*/
/* PP_IntNum */
#define INTRQ0 0x0000
#define INTRQ1 0x0001
#define INTRQ2 0x0002
#define INTRQ3 0x0003
/* PP_ProductID */
#define EISA_REG_CODE 0x630e
#define REVISION(x) (((x) & 0x1f00) >> 8)
#define VERSION(x) ((x) & ~0x1f00)
#define CS8900A 0x0000
#define REV_B 7
#define REV_C 8
#define REV_D 9
/* PP_RxCFG */
#define Skip_1 0x0040
#define StreamE 0x0080
#define RxOKiE 0x0100
#define RxDMAonly 0x0200
#define AutoRxDMAE 0x0400
#define BufferCRC 0x0800
#define CRCerroriE 0x1000
#define RuntiE 0x2000
#define ExtradataiE 0x4000
/* PP_RxCTL */
#define IAHashA 0x0040
#define PromiscuousA 0x0080
#define RxOKA 0x0100
#define MulticastA 0x0200
#define IndividualA 0x0400
#define BroadcastA 0x0800
#define CRCerrorA 0x1000
#define RuntA 0x2000
#define ExtradataA 0x4000
/* PP_TxCFG */
#define Loss_of_CRSiE 0x0040
#define SQErroriE 0x0080
#define TxOKiE 0x0100
#define Out_of_windowiE 0x0200
#define JabberiE 0x0400
#define AnycolliE 0x0800
#define T16colliE 0x8000
/* PP_BufCFG */
#define SWint_X 0x0040
#define RxDMAiE 0x0080
#define Rdy4TxiE 0x0100
#define TxUnderruniE 0x0200
#define RxMissiE 0x0400
#define Rx128iE 0x0800
#define TxColOvfiE 0x1000
#define MissOvfloiE 0x2000
#define RxDestiE 0x8000
/* PP_LineCTL */
#define SerRxON 0x0040
#define SerTxON 0x0080
#define AUIonly 0x0100
#define AutoAUI_10BT 0x0200
#define ModBackoffE 0x0800
#define PolarityDis 0x1000
#define L2_partDefDis 0x2000
#define LoRxSquelch 0x4000
/* PP_SelfCTL */
#define RESET 0x0040
#define SWSuspend 0x0100
#define HWSleepE 0x0200
#define HWStandbyE 0x0400
#define HC0E 0x1000
#define HC1E 0x2000
#define HCB0 0x4000
#define HCB1 0x8000
/* PP_BusCTL */
#define ResetRxDMA 0x0040
#define DMAextend 0x0100
#define UseSA 0x0200
#define MemoryE 0x0400
#define DMABurst 0x0800
#define IOCHRDYE 0x1000
#define RxDMAsize 0x2000
#define EnableRQ 0x8000
/* PP_TestCTL */
#define DisableLT 0x0080
#define ENDECloop 0x0200
#define AUIloop 0x0400
#define DisableBackoff 0x0800
#define FDX 0x4000
/* PP_ISQ */
#define RegNum(x) ((x) & 0x3f)
#define RegContent(x) ((x) & ~0x3d)
#define RxEvent 0x0004
#define TxEvent 0x0008
#define BufEvent 0x000c
#define RxMISS 0x0010
#define TxCOL 0x0012
/* PP_RxStatus */
#define IAHash 0x0040
#define Dribblebits 0x0080
#define RxOK 0x0100
#define Hashed 0x0200
#define IndividualAdr 0x0400
#define Broadcast 0x0800
#define CRCerror 0x1000
#define Runt 0x2000
#define Extradata 0x4000
#define HashTableIndex(x) ((x) >> 0xa)
/* PP_TxCMD */
#define After5 0
#define After381 1
#define After1021 2
#define AfterAll 3
#define TxStart(x) ((x) << 6)
#define Force 0x0100
#define Onecoll 0x0200
#define InhibitCRC 0x1000
#define TxPadDis 0x2000
/* PP_BusST */
#define TxBidErr 0x0080
#define Rdy4TxNOW 0x0100
/* PP_TxEvent */
#define Loss_of_CRS 0x0040
#define SQEerror 0x0080
#define TxOK 0x0100
#define Out_of_window 0x0200
#define Jabber 0x0400
#define T16coll 0x8000
#define TX_collisions(x) (((x) >> 0xb) & ~0x8000)
/* PP_BufEvent */
#define SWint 0x0040
#define RxDMAFrame 0x0080
#define Rdy4Tx 0x0100
#define TxUnderrun 0x0200
#define RxMiss 0x0400
#define Rx128 0x0800
#define RxDest 0x8000
/* PP_RxMISS */
#define MissCount(x) ((x) >> 6)
/* PP_TxCOL */
#define ColCount(x) ((x) >> 6)
/* PP_SelfST */
#define T3VActive 0x0040
#define INITD 0x0080
#define SIBUSY 0x0100
#define EEPROMpresent 0x0200
#define EEPROMOK 0x0400
#define ELpresent 0x0800
#define EEsize 0x1000
/* PP_EEPROMCommand */
#define EEWriteEnable 0x00F0
#define EEWriteDisable 0x0000
#define EEWriteRegister 0x0100
#define EEReadRegister 0x0200
#define EEEraseRegister 0x0300
#define ELSEL 0x0400
#endif /* #ifndef CS8900_H */
//drivers/net/arm/cs8900.c
/*
* linux/drivers/net/cs8900.c
*
* Author: Abraham van der Merwe <abraham at 2d3d.co.za>
*
* A Cirrus Logic CS8900A driver for Linux
* based on the cs89x0 driver written by Russell Nelson,
* Donald Becker, and others.
*
* This source code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* History:
* 22-May-2002 Initial version (Abraham vd Merwe)
* 30-May-2002 Added char device support for eeprom (Frank Becker)
* 24-Jan-2004 Fixups for 2.6 (Frank Becker)
* 15-July-2004 Modified for SMDK2410 (Roc Wu pwu at jadechip.com)
*/
#define VERSION_STRING "Cirrus Logic CS8900A driver for Linux (Modified for SMDK2410)"
/*
* At the moment the driver does not support memory mode operation.
* It is trivial to implement this, but not worth the effort.
*/
/*
* TODO:
*
* 1. Sort out ethernet checksum
* 2. If !ready in send_start(), queue buffer and send it in interrupt handler
* when we receive a BufEvent with Rdy4Tx, send it again. dangerous!
* 3. how do we prevent interrupt handler destroying integrity of get_stats()?
* 4. Change reset code to check status.
* 5. Implement set_mac_address and remove fake mac address
* 7. Link status detection stuff
* 8. Write utility to write EEPROM, do self testing, etc.
* 9. Implement DMA routines (I need a board w/ DMA support for that)
* 10. Power management
* 11. Add support for multiple ethernet chips
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/pm.h>
#include <linux/irq.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/fs.h>
// Added BSt
#include <asm/mach-types.h>
#ifdef CONFIG_ARCH_SMDK2410
#include "asm/arch-s3c2410/regs-irq.h"
#include "asm/arch/regs-mem.h"
//#include "asm/arch/smdk2410.h"
#include "asm/plat-s3c24xx/common-smdk.h"
#endif
#include "cs8900.h"
//#define FULL_DUPLEX
//#define DEBUG
typedef struct {
struct net_device_stats stats;
u16 txlen;
int char_devnum;
spinlock_t lock;
} cs8900_t;
int cs8900_probe (struct net_device *dev);
static struct net_device *cs8900_dev ;
/*
* There seems to be no way to determine the exact size of the eeprom,
* so we use the largest size.
* FIXME: Verify it's safe to read/write past the end of a 64/128
* byte eeprom.
*
* Possible eeprom sizes:
* Cx46 - 64 bytes
* Cx56 - 128 bytes
* Cx66 - 256 bytes
*/
#define MAX_EEPROM_SIZE 256
/*
* I/O routines
*/
static inline u16 cs8900_read (struct net_device *dev,u16 reg)
{
outw (reg,dev->base_addr + PP_Address);
return (inw (dev->base_addr + PP_Data));
}
static inline void cs8900_write (struct net_device *dev,u16 reg,u16 value)
{
outw (reg,dev->base_addr + PP_Address);
outw (value,dev->base_addr + PP_Data);
}
static inline void cs8900_set (struct net_device *dev,u16 reg,u16 value)
{
cs8900_write (dev,reg,cs8900_read (dev,reg) | value);
}
static inline void cs8900_clear (struct net_device *dev,u16 reg,u16 value)
{
cs8900_write (dev,reg,cs8900_read (dev,reg) & ~value);
}
static inline void cs8900_frame_read (struct net_device *dev,struct sk_buff *skb,u16 length)
{
insw (dev->base_addr,skb_put (skb,length),(length + 1) / 2);
}
static inline void cs8900_frame_write (struct net_device *dev,struct sk_buff *skb)
{
outsw (dev->base_addr,skb->data,(skb->len + 1) / 2);
}
/*
* Debugging functions
*/
#ifdef DEBUG
static inline int printable (int c)
{
return ((c >= 32 && c <= 126) ||
(c >= 174 && c <= 223) ||
(c >= 242 && c <= 243) ||
(c >= 252 && c <= 253));
}
static void dump16 (struct net_device *dev,const u8 *s,size_t len)
{
int i;
char str[128];
if (!len) return;
*str = '\0';
for (i = 0; i < len; i++) {
if (i && !(i % 4)) strcat (str," ");
sprintf (str,"%s%.2x ",str,s[i]);
}
for ( ; i < 16; i++) {
if (i && !(i % 4)) strcat (str," ");
strcat (str," ");
}
strcat (str," ");
for (i = 0; i < len; i++) sprintf (str,"%s%c",str,printable (s[i]) ? s[i] : '.');
printk (KERN_DEBUG "%s: %s\n",dev->name,str);
}
static void hexdump (struct net_device *dev,const void *ptr,size_t size)
{
const u8 *s = (u8 *) ptr;
int i;
for (i = 0; i < size / 16; i++, s += 16) dump16 (dev,s,16);
dump16 (dev,s,size % 16);
}
static void dump_packet (struct net_device *dev,struct sk_buff *skb,const char *type)
{
printk (KERN_INFO "%s: %s %d byte frame %.2x:%.2x:%.2x:%.2x:%.2x:%.2x to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x type %.4x\n",
dev->name,
type,
skb->len,
skb->data[0],skb->data[1],skb->data[2],skb->data[3],skb->data[4],skb->data[5],
skb->data[6],skb->data[7],skb->data[8],skb->data[9],skb->data[10],skb->data[11],
(skb->data[12] << 8) | skb->data[13]);
if (skb->len < 0x100) hexdump (dev,skb->data,skb->len);
}
#endif /* #ifdef DEBUG */
/*
* Driver functions
*/
static void cs8900_receive (struct net_device *dev)
{
cs8900_t *priv = (cs8900_t *) dev->priv;
struct sk_buff *skb;
u16 status,length;
status = cs8900_read (dev,PP_RxStatus);
length = cs8900_read (dev,PP_RxLength);
if (!(status & RxOK)) {
priv->stats.rx_errors++;
if ((status & (Runt | Extradata))) priv->stats.rx_length_errors++;
if ((status & CRCerror)) priv->stats.rx_crc_errors++;
return;
}
if ((skb = dev_alloc_skb (length + 4)) == NULL) {
priv->stats.rx_dropped++;
return;
}
skb->dev = dev;
skb_reserve (skb,2);
cs8900_frame_read (dev,skb,length);
#ifdef FULL_DUPLEX
dump_packet (dev,skb,"recv");
#endif /* #ifdef FULL_DUPLEX */
skb->protocol = eth_type_trans (skb,dev);
netif_rx (skb);
dev->last_rx = jiffies;
priv->stats.rx_packets++;
priv->stats.rx_bytes += length;
}
static int cs8900_send_start (struct sk_buff *skb,struct net_device *dev)
{
cs8900_t *priv = (cs8900_t *) dev->priv;
u16 status;
spin_lock_irq(&priv->lock);
netif_stop_queue (dev);
cs8900_write (dev,PP_TxCMD,TxStart (After5));
cs8900_write (dev,PP_TxLength,skb->len);
status = cs8900_read (dev,PP_BusST);
if ((status & TxBidErr)) {
spin_unlock_irq(&priv->lock);
printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len);
priv->stats.tx_errors++;
priv->stats.tx_aborted_errors++;
priv->txlen = 0;
return (1);
}
if (!(status & Rdy4TxNOW)) {
spin_unlock_irq(&priv->lock);
printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name);
priv->stats.tx_errors++;
priv->txlen = 0;
/* FIXME: store skb and send it in interrupt handler */
return (1);
}
cs8900_frame_write (dev,skb);
spin_unlock_irq(&priv->lock);
#ifdef DEBUG
dump_packet (dev,skb,"send");
#endif /* #ifdef DEBUG */
dev->trans_start = jiffies;
dev_kfree_skb (skb);
priv->txlen = skb->len;
return (0);
}
static irqreturn_t cs8900_interrupt (int irq,void *id)
{
struct net_device *dev = (struct net_device *) id;
cs8900_t *priv;
volatile u16 status;
irqreturn_t handled = 0;
if (dev->priv == NULL) {
printk (KERN_WARNING "%s: irq %d for unknown device.\n",dev->name,irq);
return 0;
}
priv = (cs8900_t *) dev->priv;
while ((status = cs8900_read (dev, PP_ISQ))) {
handled = 1;
switch (RegNum (status)) {
case RxEvent:
cs8900_receive (dev);
break;
case TxEvent:
priv->stats.collisions += ColCount (cs8900_read (dev,PP_TxCOL));
if (!(RegContent (status) & TxOK)) {
priv->stats.tx_errors++;
if ((RegContent (status) & Out_of_window)) priv->stats.tx_window_errors++;
if ((RegContent (status) & Jabber)) priv->stats.tx_aborted_errors++;
break;
} else if (priv->txlen) {
priv->stats.tx_packets++;
priv->stats.tx_bytes += priv->txlen;
}
priv->txlen = 0;
netif_wake_queue (dev);
break;
case BufEvent:
if ((RegContent (status) & RxMiss)) {
u16 missed = MissCount (cs8900_read (dev,PP_RxMISS));
priv->stats.rx_errors += missed;
priv->stats.rx_missed_errors += missed;
}
if ((RegContent (status) & TxUnderrun)) {
priv->stats.tx_errors++;
priv->stats.tx_fifo_errors++;
priv->txlen = 0;
netif_wake_queue (dev);
}
/* FIXME: if Rdy4Tx, transmit last sent packet (if any) */
break;
case TxCOL:
priv->stats.collisions += ColCount (cs8900_read (dev,PP_TxCOL));
break;
case RxMISS:
status = MissCount (cs8900_read (dev,PP_RxMISS));
priv->stats.rx_errors += status;
priv->stats.rx_missed_errors += status;
break;
}
}
return IRQ_RETVAL(handled);
}
static void cs8900_transmit_timeout (struct net_device *dev)
{
cs8900_t *priv = (cs8900_t *) dev->priv;
priv->stats.tx_errors++;
priv->stats.tx_heartbeat_errors++;
priv->txlen = 0;
netif_wake_queue (dev);
}
static int cs8900_start (struct net_device *dev)
{
int result;
set_irq_type(dev->irq, IRQT_RISING);
/* enable the ethernet controller */
cs8900_set (dev,PP_RxCFG,RxOKiE | BufferCRC | CRCerroriE | RuntiE | ExtradataiE);
cs8900_set (dev,PP_RxCTL,RxOKA | IndividualA | BroadcastA);
cs8900_set (dev,PP_TxCFG,TxOKiE | Out_of_windowiE | JabberiE);
cs8900_set (dev,PP_BufCFG,Rdy4TxiE | RxMissiE | TxUnderruniE | TxColOvfiE | MissOvfloiE);
cs8900_set (dev,PP_LineCTL,SerRxON | SerTxON);
cs8900_set (dev,PP_BusCTL,EnableRQ);
#ifdef FULL_DUPLEX
cs8900_set (dev,PP_TestCTL,FDX);
#endif /* #ifdef FULL_DUPLEX */
udelay(200);
/* install interrupt handler */
if ((result = request_irq (dev->irq, &cs8900_interrupt, 0, dev->name, dev)) < 0) {
printk (KERN_ERR "%s: could not register interrupt %d\n",dev->name, dev->irq);
return (result);
}
/* start the queue */
netif_start_queue (dev);
return (0);
}
static int cs8900_stop (struct net_device *dev)
{
/* disable ethernet controller */
cs8900_write (dev,PP_BusCTL,0);
cs8900_write (dev,PP_TestCTL,0);
cs8900_write (dev,PP_SelfCTL,0);
cs8900_write (dev,PP_LineCTL,0);
cs8900_write (dev,PP_BufCFG,0);
cs8900_write (dev,PP_TxCFG,0);
cs8900_write (dev,PP_RxCTL,0);
cs8900_write (dev,PP_RxCFG,0);
/* uninstall interrupt handler */
free_irq (dev->irq,dev);
/* stop the queue */
netif_stop_queue (dev);
return (0);
}
static struct net_device_stats *cs8900_get_stats (struct net_device *dev)
{
cs8900_t *priv = (cs8900_t *) dev->priv;
return (&priv->stats);
}
static void cs8900_set_receive_mode (struct net_device *dev)
{
if ((dev->flags & IFF_PROMISC))
cs8900_set (dev,PP_RxCTL,PromiscuousA);
else
cs8900_clear (dev,PP_RxCTL,PromiscuousA);
if ((dev->flags & IFF_ALLMULTI) && dev->mc_list)
cs8900_set (dev,PP_RxCTL,MulticastA);
else
cs8900_clear (dev,PP_RxCTL,MulticastA);
}
/*
* Driver initialization routines
*/
int __init cs8900_probe (struct net_device *dev)
{
static cs8900_t priv;
int i,result;
u16 value;
printk (VERSION_STRING"\n");
memset (&priv,0,sizeof (cs8900_t));
//+kevin
// __raw_writel(0x2211d110,S3C2410_BWSCON);
// __raw_writel(0x1f7c,S3C2410_BANKCON3);
#if defined(CONFIG_ARCH_SMDK2410)
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x00;
dev->dev_addr[2] = 0x3e;
dev->dev_addr[3] = 0x26;
dev->dev_addr[4] = 0x0a;
dev->dev_addr[5] = 0x00;
#endif
dev->if_port = IF_PORT_10BASET;
dev->priv = (void *) &priv;
spin_lock_init(&priv.lock);
//hejiasheng SET_MODULE_OWNER (dev);
#if defined(CONFIG_ARCH_SMDK2410)
dev->base_addr = vSMDK2410_ETH_IO + 0x300;
dev->irq = IRQ_EINT9;
#endif /* #if defined(CONFIG_ARCH_SMDK2410) */
if ((result = check_mem_region (dev->base_addr, 16))) {
printk (KERN_ERR "%s: can't get I/O port address 0x%lx\n",dev->name,dev->base_addr);
return (result);
}
request_mem_region (dev->base_addr, 16, dev->name);
/* verify EISA registration number for Cirrus Logic */
if ((value = cs8900_read (dev,PP_ProductID)) != EISA_REG_CODE) {
printk (KERN_ERR "%s: incorrect signature 0x%.4x\n",dev->name,value);
return (-ENXIO);
}
/* verify chip version */
value = cs8900_read (dev,PP_ProductID + 2);
if (VERSION (value) != CS8900A) {
printk (KERN_ERR "%s: unknown chip version 0x%.8x\n",dev->name,VERSION (value));
return (-ENXIO);
}
/* setup interrupt number */
cs8900_write (dev,PP_IntNum,0);
printk (KERN_INFO "%s: CS8900A rev %c at %#lx irq=%d",
dev->name,'B' + REVISION (value) - REV_B, dev->base_addr, dev->irq);
for (i = 0; i < ETH_ALEN; i += 2)
cs8900_write (dev,PP_IA + i,dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8));
printk (", addr:");
for (i = 0; i < ETH_ALEN; i += 2)
{
u16 mac = cs8900_read (dev,PP_IA + i);
printk ("%c%02X:%2X", (i==0)?' ':':', mac & 0xff, (mac >> 8));
}
printk ("\n");
return (0);
}
static int __init cs8900_init (void)
{
struct net_device *ndev;
ndev = alloc_etherdev(sizeof (cs8900_t));
if (!ndev) {
printk("%s: could not allocate device.\n", "cs8900");
return -ENOMEM;
}
cs8900_dev = ndev;
cs8900_dev->init = cs8900_probe;
ether_setup (ndev);
ndev->open = cs8900_start;
ndev->stop = cs8900_stop;
ndev->hard_start_xmit = cs8900_send_start;
ndev->get_stats = cs8900_get_stats;
ndev->set_multicast_list = cs8900_set_receive_mode;
ndev->tx_timeout = cs8900_transmit_timeout;
ndev->watchdog_timeo = HZ;
return (register_netdev (cs8900_dev));
}
static void __exit cs8900_cleanup (void)
{
cs8900_t *priv = (cs8900_t *) cs8900_dev->priv;
if( priv->char_devnum)
{
unregister_chrdev(priv->char_devnum,"cs8900_eeprom");
}
release_mem_region (cs8900_dev->base_addr,16);
unregister_netdev (cs8900_dev);
}
MODULE_AUTHOR ("Abraham van der Merwe <abraham at 2d3d.co.za>");
MODULE_DESCRIPTION (VERSION_STRING);
MODULE_LICENSE ("GPL");
module_init (cs8900_init);
module_exit (cs8900_cleanup);
添加LTV350QV的FB驱动到基于linux-2.6.26的GEC2440开发板
1,编译配置内核
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make menuconfig
进入配置菜单添加驱动到内核:
Device Drivers --->
Graphics support --->
<*> Support for frame buffer devices --->
<*> S3C2410 LCD framebuffer support
2,修改arch/arm/mach-s3c2440/mach-smdk2440.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi arch/arm/mach-s3c2440/mach-smdk2440.c
把static struct s3c2410fb_display smdk2440_lcd_cfg __initdata 修改成:
// change by yuanxihua@21cn.com
static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {
.lcdcon5 = S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVCLK |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
// S3C2410_LCDCON5_INVVD |
// S3C2410_LCDCON5_INVVDEN |
// S3C2410_LCDCON5_PWREN |
// S3C2410_LCDCON5_BSWP |
S3C2410_LCDCON5_HWSWP,
.type = S3C2410_LCDCON1_TFT,
.width = 320,
.height = 240,
.pixclock = 270000, /* HCLK 60 MHz, divisor 10 */
.xres = 320,
.yres = 240,
.bpp = 16,
.left_margin = 21,
.right_margin = 14,
.hsync_len = 19,
.upper_margin = 6,
.lower_margin = 5,
.vsync_len = 4,
};
把static struct s3c2410fb_mach_info smdk2440_fb_info __initdata修改成:
// change by yuanxihua@21cn.com
static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {
.displays = &smdk2440_lcd_cfg,
.num_displays = 1,
.default_display = 0,
#if 1
/* currently setup by downloader */
.gpccon = 0xaa9556a9,
.gpccon_mask = 0xffffffff,
.gpcup = 0xffffffff,
.gpcup_mask = 0xffffffff,
.gpdcon = 0xaaaaaaaa,
.gpdcon_mask = 0xffffffff,
.gpdup = 0xffffffff,
.gpdup_mask = 0xffffffff,
#endif
.lpcsel = 0,
};
把s3c24xx_init_clocks(16934400);修改成:
// s3c24xx_init_clocks(16934400); // change by yuanxihua@21cn.com
s3c24xx_init_clocks(12000000);
3,修改include/asm-arm/arch-s3c2410/regs-lcd.h文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi include/asm-arm/arch-s3c2410/regs-lcd.h
把#define S3C2410_LCDCON1_MMODE (1<<7)修改成:
//#define S3C2410_LCDCON1_MMODE (1<<7)
#define S3C2410_LCDCON1_MMODE (0<<7) // change by yuanxihua@21cn.com
4,修改drivers/video/s3c2410fb.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/video/s3c2410fb.c
在第51行的/* useful functions */后添加:
/************************************************/
//LTV350QV_FOE_V0.0
#define LTV350QV_FOE 0x1d //device ID
typedef struct _LTV350qv_spi_data_{
unsigned char Device_ID; //ID of the device
unsigned int Index; //index of register
unsigned long Structure; //structure to be writed
}LTV350QV_SPI_Data;
//micro for LTV350QV_FOE
#define CS_H __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<< 8), S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_CS)
#define CS_L __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<< 8), S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_CS)
#define SCLK_H __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<< 9), S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_SCL)
#define SCLK_L __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<< 9), S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_SCL)
#define SDI_H __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<<10), S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_SDI)
#define SDI_L __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<<10), S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_SDI)
#define RST_H __raw_writel(__raw_readl(S3C2410_GPDDAT) |(1<< 0), S3C2410_GPDDAT)//MAKE_HIGH(LTV350QV_RST)
#define RST_L __raw_writel(__raw_readl(S3C2410_GPDDAT)&~(1<< 0), S3C2410_GPDDAT)//MAKE_LOW(LTV350QV_RST)
//***************************************************************
//**********these functions for SUMSUN LTV350QV TFT LCD****************
//***************************************************************
static void LTV350QV_Short_Delay(u_char time)
{
ndelay(150);
}
/*
static void LTV350QV_Rst(void)
{
RST_L;
mdelay(1);
RST_H;
mdelay(1);
}
*/
static void LTV350QV_Register_Write(LTV350QV_SPI_Data regdata)
{
u_char i,temp1;
u_int temp2;
u_long temp3;
unsigned long flags;
//write index
temp1=regdata.Device_ID<<2 | 0<<1 | 0<<0; //register index
temp2=regdata.Index;
temp3=(temp1<<24) | (temp2<<8);
local_irq_save(flags);
CS_L;
LTV350QV_Short_Delay(1);
for(i=0;i<24;i++)
{
SCLK_L;
if(temp3 & (1<<(31-i)) ) //if is H
SDI_H;
else
SDI_L;
LTV350QV_Short_Delay(1); //setup time
SCLK_H;
LTV350QV_Short_Delay(1); //hold time
}
CS_H;
LTV350QV_Short_Delay(5);
//write instruction
temp1=regdata.Device_ID<<2 | 1<<1 | 0<<0; //instruction
temp2=regdata.Structure;
temp3=(temp1<<24) | (temp2<<8);
CS_L;
LTV350QV_Short_Delay(1);
for(i=0;i<24;i++)
{
SCLK_L;
if(temp3 & (1<<(31-i)) ) //if is H
SDI_H;
else
SDI_L;
LTV350QV_Short_Delay(1);
SCLK_H;
LTV350QV_Short_Delay(1);
}
CS_H;
local_irq_restore(flags);
}
/****************************************
* *
****************************************/
static void LTV350QV_Write(u_int index, u_int regdata)
{
LTV350QV_SPI_Data WriteData;
WriteData.Device_ID = LTV350QV_FOE;
WriteData.Index = index;
WriteData.Structure = regdata;
LTV350QV_Register_Write(WriteData);
}
/****************************************
* *power ON sequence
****************************************/
static void LTV350QV_Power_ON(void)
{
LTV350QV_Write( 9, 0x0000);
mdelay(150);
LTV350QV_Write( 9, 0x4000);
LTV350QV_Write(10, 0x2000);
LTV350QV_Write( 9, 0x4055);
mdelay(550);
LTV350QV_Write( 1, 0x409d);
LTV350QV_Write( 2, 0x0204);
LTV350QV_Write( 3, 0x0100);
LTV350QV_Write( 4, 0x3000);
LTV350QV_Write( 5, 0x4003);
LTV350QV_Write( 6, 0x000a);
LTV350QV_Write( 7, 0x0021);
LTV350QV_Write( 8, 0x0c00);
LTV350QV_Write(10, 0x0103);
LTV350QV_Write(11, 0x0301);
LTV350QV_Write(12, 0x1f0f);
LTV350QV_Write(13, 0x1f0f);
LTV350QV_Write(14, 0x0707);
LTV350QV_Write(15, 0x0307);
LTV350QV_Write(16, 0x0707);
LTV350QV_Write(17, 0x0000);
LTV350QV_Write(18, 0x0004);
LTV350QV_Write(19, 0x0000);
mdelay(200);
LTV350QV_Write( 9, 0x4a55);
LTV350QV_Write( 5, 0x5003);
}
/**********************************
* *power OFF sequence
**********************************/
/*static void LTV350QV_Powen_OFF(void)
{
LTV350QV_Write( 9, 0x4055);// GON -> 0, POC -> 0
LTV350QV_Write( 5, 0x4003);// DSC -> 0
LTV350QV_Write(10, 0x0000);// VCOMG -> 0
mdelay(20);
LTV350QV_Write( 9, 0x4000);// AP[2:0] -> 000
}*/
static void s3c2440fb_init_ltv350qv(void)
{
__raw_writel(0xaa9556a9, S3C2410_GPCCON); //Initialize VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
//LCDVF[0],[1],[2]---output;VD[0],[1],[2]----output.
__raw_writel(0xffffffff, S3C2410_GPCUP); // Disable Pull-up register
LTV350QV_Power_ON() ; //init LCD model
__raw_writel(0xaaaaaaaa, S3C2410_GPDCON);
__raw_writel(0xffffffff, S3C2410_GPDUP);
// __raw_writel(3, S3C2410_LCDINTMSK); // MASK LCD Sub Interrupt
// __raw_writel(0, S3C2410_TPAL); // Disable Temp Palette
// __raw_writel(0, S3C2410_LPCSEL); // Disable LPC3600
}
在static int s3c2410fb_init_registers(struct fb_info *info)的 return 0;前添加:
s3c2440fb_init_ltv350qv();
5, 编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make
添加XMODEM下载协议到基于u-boot-1.3.4的9G9260开发板
1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/sam9260# wget ftp://ftp.denx.de/pub/u-boot/u-boot-1.3.4.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# wget ftp://www.linux4sam.org/pub/uboot/u-boot-1.3.4-exp/u-boot-1.3.4-exp.diff
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xjvf u-boot-1.3.4.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# mv u-boot-1.3.4 u-boot-1.3.4-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# mv u-boot-1.3.4-exp.diff u-boot-1.3.4-9g9260/
2,打补丁:
root@yuanxh-desktop:/home/yuanxh/sam9260# cd u-boot-1.3.4-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# patch -p1 < ./u-boot-1.3.4-exp.diff
3,默认配置:
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_dataflash_cs0_config
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_dataflash_cs1_config
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_nandflash_config
(选择对应的一项,区分NANDFLASH和DATAFLASH的CS0,CS1)
4,添加XMODEM下载协议
在\common\Makefile的147行添加 COBJS-y += cmd_xmodem.o xmodem.o
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# vi common/Makefile
在\common\中增加源文件 xmodem.c cmd_xmodem.c
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# rz
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# mv xmodem.c cmd_xmodem.c common/
5,编译发布:
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# mv u-boot.bin u-boot-1.3.4-9g9260.bin
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# sz u-boot-1.3.4-9g9260.bin
6, 清除配置
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make distclean
附件:xmodem.c文件
/*******************************************************************************
*
* Filename: xmodem.c
*
* change from KB9202 , yuanxihua@21cn.com
******************************************************************************/
#include <common.h>
extern int xmodem_rx(char *dest);
/* Line control codes */
#define SOH 0x01 /* start of header for Xmodem protocol */
#define STX 0x02 /* start of header for 1K xmodem protocol*/
#define ACK 0x06 /* Acknowledge */
#define NAK 0x15 /* Negative acknowledge */
#define CAN 0x18 /* Cancel */
#define EOT 0x04 /* end of text */
#define TIMEOUT 2
#define TIMEOUT_LONG 10
#define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */
#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */
enum {
INVALID_STATE = 0,
WAITING_START,
WAIT_HEAD,
RX_PACKET,
RX_EOT,
SEND_NAK
};
static char packetNumber;
static int PACKET_SIZE;
static char HEAD;
#define TransitionState(x, y) (x = y)
void DebugPutc(char cValue)
{
putc (cValue & 0x1FF);
}
int WaitForChar(char *cPtr, int seconds)
{
unsigned long counter = 0;
seconds = seconds * 1000 ; /* delay 1000 * 50 * 20us */
while (!tstc () && (counter < seconds * 50 ))
{
udelay (20);
counter++;
}
if (tstc ())
{
*cPtr = getc ();
return 1;
}
return 0;
}
static int GetRecord(char blocknum, char *dest) {
int size;
char nextChar;
unsigned chk, j;
chk = 0;
if (!WaitForChar(&nextChar, TIMEOUT)) {
return (0);
}
if ((char)nextChar != (char)~blocknum) {
return (0);
}
for (size = 0; size < PACKET_SIZE; ++size) {
if (!WaitForChar(&nextChar, TIMEOUT)) {
return (0);
}
chk = chk ^(int)nextChar << 8;
for (j = 0; j < 8; ++j) {
if (chk & 0x8000)
chk = chk << 1 ^ 0x1021;
else
chk = chk << 1;
}
*dest++ = nextChar;
}
chk &= 0xFFFF;
if ((!WaitForChar(&nextChar, TIMEOUT)) || (nextChar != ((chk >> 8) & 0xFF))) {
return (0);
}
if ((!WaitForChar(&nextChar, TIMEOUT)) || (nextChar != (chk & 0xFF))) {
return (0);
}
DebugPutc(ACK);
return (1);
}
int xmodem_rx(char *dest) {
int state;
char nextChar, *startAddress = dest;
packetNumber = 1;
state = WAITING_START;
PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
HEAD = SOH;
while (1) {
if (state == WAITING_START) {
DebugPutc('C');
if (WaitForChar(&nextChar, TIMEOUT)) {
if (nextChar == SOH)
{
PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
HEAD = SOH;
TransitionState(state, RX_PACKET);
}
else
if (nextChar == STX)
{
PACKET_SIZE = XMODEM_DATA_SIZE_STX;
HEAD = STX;
TransitionState(state, RX_PACKET);
}
}
}
if (state == WAIT_HEAD) {
if (!WaitForChar(&nextChar, TIMEOUT_LONG)) {
return (-1);
}
/* if (nextChar == HEAD) {
TransitionState(state, RX_PACKET);
}
*/
if (nextChar == SOH)
{
PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
HEAD = SOH;
TransitionState(state, RX_PACKET);
}
else
if (nextChar == STX)
{
PACKET_SIZE = XMODEM_DATA_SIZE_STX;
HEAD = STX;
TransitionState(state, RX_PACKET);
}
if (nextChar == EOT) {
// TransitionState(state, RX_EOT);
DebugPutc(ACK);
return (dest - startAddress);
}
}
if (state == RX_PACKET) {
if (!WaitForChar(&nextChar, TIMEOUT)) {
return (-1);
}
if (nextChar != packetNumber) {
// TransitionState(state, SEND_NAK);
DebugPutc(NAK);
return (-1);
}
if (GetRecord(packetNumber, dest)) {
dest += PACKET_SIZE;
++packetNumber;
TransitionState(state, WAIT_HEAD);
} else {
return (-1);
}
}
}
// the loop above should return in all cases
return (-1);
}
附件:cmd_xmodem.c文件
#include <common.h>
#include <command.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
static ulong load_xmodem_bin(ulong *);
static char *bin_start_address;
int do_xmodem(cmd_tbl_t *cmdtp,int flag,int argc, char *argv[])
{
DECLARE_GLOBAL_DATA_PTR;
ulong offset = 0;
ulong addr;
int load_baudrate, current_baudrate;
int rcode = 0;
char *s;
/* pre-set offset from CFG_LOAD_ADDR */
offset = CFG_LOAD_ADDR;
/* pre-set offset from $loadaddr */
if ((s = getenv("loadaddr")) != NULL) {
offset = simple_strtoul(s, NULL, 16);
}
load_baudrate = current_baudrate = gd->baudrate;
if (argc >= 2) {
offset = simple_strtoul(argv[1], NULL, 16);
}
if (argc == 3) {
load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
/* default to current baudrate */
if (load_baudrate == 0)
load_baudrate = current_baudrate;
}
if (load_baudrate != current_baudrate) {
printf ("## Switch baudrate to %d bps and press ENTER ...\n",
load_baudrate);
udelay(50000);
gd->baudrate = load_baudrate;
serial_setbrg ();
udelay(50000);
for (;;) {
if (getc() == '\r')
break;
}
}
printf ("## Ready for binary (xmodem) download "
"to 0x%08lX at %d bps...\n",
offset,
load_baudrate);
addr = load_xmodem_bin((ulong *) offset);
if (addr == ~0) {
load_addr = 0;
printf ("## Binary (xmodem) download aborted\n");
rcode = 1;
} else {
printf ("## Start Addr = 0x%08lX\n", addr);
load_addr = addr;
}
if (load_baudrate != current_baudrate) {
printf ("## Switch baudrate to %d bps and press ESC ...\n",
current_baudrate);
udelay (50000);
gd->baudrate = current_baudrate;
serial_setbrg ();
udelay (50000);
for (;;) {
if (getc() == 0x1B) /* ESC */
break;
}
}
#ifdef CONFIG_AUTOSCRIPT
if (load_addr) {
char *s;
if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
rcode = autoscript (load_addr);
}
}
#endif
return rcode;
}
static ulong load_xmodem_bin(unsigned long *addr)
{
int size, i;
char buf[32];
ulong offset;
// set_kerm_bin_mode ((ulong *) offset);
// size = k_recv ();
offset = addr;
bin_start_address = (char *) addr;
size = xmodem_rx(bin_start_address);
/*
* Gather any trailing characters (for instance, the ^D which
* is sent by 'cu' after sending a file), and give the
* box some time (100 * 1 ms)
*/
for (i=0; i<100; ++i) {
if (tstc()) {
(void) getc();
}
udelay(1000);
}
flush_cache (offset, size);
printf("## Total Size = 0x%08x = %d Bytes\n", size, size);
sprintf(buf, "%X", size);
setenv("filesize", buf);
return offset;
}
U_BOOT_CMD(
rx, 3, 0, do_xmodem,
"rx - load binary file over serial line (xmodem)\n",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'\n"
);
移植linux-2.6.27到9G9260开发板
1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://maxim.org.za/AT91RM9200/2.6/2.6.27-at91.patch.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# wget ftp://www.linux4sam.org/pub/linux/2.6.27-at91/2.6.27-at91-exp.patch.gz
2,打补丁:
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xjvf linux-2.6.27.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# gzip -d 2.6.27-at91.patch.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# gzip -d 2.6.27-at91-exp.patch.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# mv linux-2.6.27 linux-2.6.27-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# mv 2.6.27-at91.patch 2.6.27-at91-exp.patch linux-2.6.27-9g9260/
root@yuanxh-desktop:/home/yuanxh/sam9260# cd linux-2.6.27-9g9260/
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# patch -p1 < ./2.6.27-at91.patch
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# patch -p1 < ./2.6.27-at91-exp.patch
3,修改Makefile
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi Makefile
把第4行的EXTRAVERSION = 修改为 EXTRAVERSION =-9g9260
把193行的ARCH ?= $(SUBARCH) 修改为 ARCH ?= arm
把194行的CROSS_COMPILE ?= 修改为 CROSS_COMPILE ?= arm-linux-
4,修改Kconfig
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi arch/arm/mach-at91/Kconfig
在第189行添加上:
config MACH_9G9260EK
bool "9G9260-EK Evaluation Kit"
depends on MACH_AT91SAM9260EK
help
Select this if you are using yuanxihua's 9G9260EK Evaluation Kit
<http://blog.163.com/yuan_xihua/>
5,默认配置:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make help
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make at91sam9260ek_defconfig
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make menuconfig
关闭掉这个选项
Kernel Features --->
[*] Use the ARM EABI to compile the kernel
修改启动命令行参数
Boot options --->
(mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw)
修改为:
noinitrd root=/dev/nfs rw nfsroot=192.168.1.108:/nfsboot/rootfs ip=192.168.1.118:192.168.1.108::255.255.255.0 console=ttyS0,115200 init=/linuxrc mem=64M
选择如下配置:
System Type --->
Atmel AT91 System-on-Chip --->
[*] 9G9260-EK Evaluation Kit
保存配置:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# cp .config 9g9260ek_defconfig
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# mv 9g9260ek_defconfig arch/arm/configs/
6,编译发布:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make 9g9260ek_defconfig
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make uImage
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# cp arch/arm/boot/uImage uImage-2.6.27-9g9260.bin
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# sz uImage-2.6.27-9g9260.bin
7,清除配置
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make distclean
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make mrproper
测试基于linux-2.6.27的9G9260开发板I2C驱动
1,找到drivers/i2c/busses/i2c-at91.c文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi drivers/i2c/busses/Makefile
在第28行看到:
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
2, 找到drivers/i2c/busses/Kconfig文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi drivers/i2c/busses/Kconfig
在第259行看到:
config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
help
This supports the use of the I2C interface on Atmel AT91
processors.
This driver is BROKEN because the controller which it uses
will easily trigger RX overrun and TX underrun errors. Using
low I2C clock rates may partially work around those issues
on some systems. Another serious problem is that there is no
documented way to issue repeated START conditions, as needed
to support combined I2C messages. Use the i2c-gpio driver
unless your system can cope with those limitations.
说明AT91 I2C标准驱动不稳定,需要用GPIO模拟!!!
3,编译配置内核
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make menuconfig
进入配置菜单添加驱动到内核:
Device Drivers --->
<*> I2C support --->
<*> I2C device interface
I2C Hardware Bus support --->
<*> GPIO-based bitbanging I2C
4, 编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make
5, 查看内核启动信息
i2c /dev entries driver
i2c-gpio i2c-gpio: using pins 55 (SDA) and 56 (SCL)
6,查看内核系统信息
# cat /proc/devices
会看到
Character devices:
...
89 i2c
...
# cat /sys/devices/platform/i2c-gpio/i2c-adapter\:i2c-0/name
i2c-gpio-1
7,建立设备结点
mknod /dev/i2c-0 c 89 0
8,编译测试代码
root@yuanxh-desktop:/home/yuanxh/sam9260/i2ctest-1.0-9g9260# arm-linux-gcc -o i2ctest i2ctest.c
root@yuanxh-desktop:/home/yuanxh/sam9260/i2ctest-1.0-9g9260# cp i2ctest /nfsboot/rootfs/app
9,运行测试代码
# /app/i2ctest
I2C Test version 1.0-9g9260 (yuanxihua@21cn.com) Buile on Jan 5 2009 00:54:45
buf[0x00] = 0x46
...
附件:
//i2ctest.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define CHIP_ADDR 0x50 //24C64
#define PAGE_SIZE 32
#define I2C_DEV "/dev/i2c-0"
static int read_eeprom(int fd,char buff[],int addr,int count)
{
int res;
if (write(fd,&addr,1)!=1)
{
printf("Can't write %s's addr %d\n",I2C_DEV,addr);
return -1;
}
res = read(fd,buff,count);
printf("read %d bytes at 0x%02x\n\r",res,addr);
return res;
}
static int write_eeprom(int fd,char buff[],int addr,int count)
{
int res;
int i;
static char sendbuffer[PAGE_SIZE+1];
memcpy(sendbuffer+1,buff,count);
sendbuffer[0]=addr;
res = write(fd,&addr,count+1);
printf("write %d bytes at 0x%02x\n\r",res,addr);
return res;
}
int main(void)
{
int fd,i,res;
unsigned char buf[PAGE_SIZE];
printf("I2C Test version 1.0-9g9260 (yuanxihua@21cn.com) Buile on %s %s\n\r",__DATE__,__TIME__);
fd=open(I2C_DEV,O_RDWR);
if(fd<0)
{
printf("Can't Open %s !!!\n\r",I2C_DEV);
return -1;
}
res = ioctl(fd,I2C_TENBIT,0);
res = ioctl(fd,I2C_SLAVE,CHIP_ADDR);
for(i=0;i<sizeof(buf);i++)
{
// write_eeprom(fd,buf,i,1);
}
for(i=0;i<sizeof(buf);i++)
{
read_eeprom (fd,buf+i,i,1);
printf("buf[0x%02x] = 0x%02x\n\r",i,buf[i]);
}
close(fd);
return 0;
}
移植mtd-utils-20080508到9G9260开发板
1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://debian.mirror.inra.fr/debian/pool/main/m/mtd-utils/mtd-utils_20080508.orig.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://www.zlib.net/zlib-1.2.3.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.03.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xzvf zlib-1.2.3.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# mv zlib-1.2.3 zlib-1.2.3-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xzvf lzo-2.03.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# mv lzo-2.03 lzo-2.03-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xzvf mtd-utils_20080508.orig.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# mv mtd-utils-20080508 mtd-utils-20080508-9g9260
2,编译安装zlib:
root@yuanxh-desktop:/home/yuanxh/sam9260# cd zlib-1.2.3-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260/zlib-1.2.3-9g9260# CC=arm-linux-gcc ./configure --shared --prefix=/usr/zlib-1.2.3
root@yuanxh-desktop:/home/yuanxh/sam9260/zlib-1.2.3-9g9260# make
root@yuanxh-desktop:/home/yuanxh/sam9260/zlib-1.2.3-9g9260# make install
root@yuanxh-desktop:/home/yuanxh/sam9260/zlib-1.2.3-9g9260# cd ..
3,编译安装lzo:
root@yuanxh-desktop:/home/yuanxh/sam9260# cd lzo-2.03-9g9260/
root@yuanxh-desktop:/home/yuanxh/sam9260/lzo-2.03-9g9260# CC=arm-linux-gcc ./configure --host=arm-linux --prefix=/usr/lzo-2.03
root@yuanxh-desktop:/home/yuanxh/sam9260/lzo-2.03-9g9260# make
root@yuanxh-desktop:/home/yuanxh/sam9260/lzo-2.03-9g9260# make install
root@yuanxh-desktop:/home/yuanxh/sam9260/lzo-2.03-9g9260# cd ..
4,修改mtd-utils的Makefile文件
root@yuanxh-desktop:/home/yuanxh/sam9260# cd mtd-utils-20080508-9g9260/
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# cp Makefile Makefile.arm
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# cp Makefile Makefile.x86
修改Makefile.arm文件
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# vi Makefile.arm
把第8行的 #CROSS=arm-linux-
修改为 CROSS=arm-linux-
把第10行的 CFLAGS := -I./include $(OPTFLAGS)
修改为
CFLAGS := -I./include $(OPTFLAGS) -I/usr/zlib-1.2.3/include -I/usr/lzo-2.03/include
LDFLAGS := -L/usr/zlib-1.2.3/lib -L/usr/lzo-2.03/lib
把第46行的 make -C $(BUILDDIR)/ubi-utils
修改为 make -C ubi-utils
把第46行的 make -C $(BUILDDIR)/ubi-utils clean
修改为 make -C ubi-utils clean
5,增加mtd-utils的编译脚本
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# vi mkall
在 mkall中写入:
make -f Makefile.$1 clean
make -f Makefile.$1 WITHOUT_XATTR=1
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# vi mkclean
在 mkall中写入:
make -f Makefile.$1 clean
保存后修改可执行权限
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# chmod 777 mkall
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# chmod 777 mkclean
6,编译mtd-utils
ARM版本
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# ./mkall arm
可以得到flash_eraseall等工具命令
X86版本
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# ./mkall x86
可以得到mkfs.jffs2等工具命令
7,清除mtd-utils目标码
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# ./mkclean arm
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# ./mkclean x86
测试基于linux-2.6.27的9G9260开发板MTD驱动
1,修改内核源码:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi arch/arm/mach-at91/board-sam9260ek.c
在第174行修改成如下:
/*
* NAND flash
*/
static struct mtd_partition __initdata ek_nand_partition[] = {
{
.name = "Bootstrap",
.offset = 0,
.size = 0x20000,
},
{
.name = "U-boot",
.offset = 0x20000,
.size = 0xe0000,
},
{
.name = "uImage",
.offset = 0x100000,
.size = 0x200000,
},
{
.name = "ramdisk",
.offset = 0x300000,
.size = 0x400000,
},
{
.name = "rootfs",
.offset = 0x700000,
.size = 0x900000,
},
{
.name = "data",
.offset = 16 * 1024 * 1024,
.size = MTDPART_SIZ_FULL,
},
};
2,修改内核配置:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make menuconfig
Boot options --->
(mem=64M console=ttyS0,115200 root=/dev/mtdblock4 rootfstype=jffs2 init=/linuxrc)
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
<*> MTD concatenating support
[*] MTD partitioning support
[*] Command line partition table parsing
<*> Direct char device access to MTD devices
-*- Common interface to block layer for MTD 'translation layers'
<*> Caching block device access to MTD devices
<*> NAND Device Support --->
<*> Support for NAND Flash / SmartMedia on AT91 and AVR32
ECC management for NAND Flash / SmartMedia on AT91 / AVR32 (Software ECC) --->
File systems --->
<*> Second extended fs support
Miscellaneous filesystems --->
<*> Journalling Flash File System v2 (JFFS2) support
(0) JFFS2 debugging verbosity (0 = quiet, 2 = noisy)
[*] JFFS2 write-buffering support
[*] JFFS2 summary support (EXPERIMENTAL)
默认就是如此,不作修改。
3,编译内核:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make uImage
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# cp arch/arm/boot/uImage uImage-2.6.27-9g9260.bin
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# sz uImage-2.6.27-9g9260.bin
4,生成JFFS2文件系统:
root@yuanxh-desktop:/nfsboot# ./mkfs.jffs2 -d rootfs -o jffs2-2.6.27-9g9260.bin -n --pagesize=0x800 --eraseblock=0x20000 --pad=0x900000
root@yuanxh-desktop:/nfsboot# sz jffs2-2.6.27-9g9260.bin
5,测试MTD驱动
# cat /proc/mtd
# flash_eraseall /dev/mtd5
# mount -t jffs2 /dev/mtdblock5 /mnt
# cd /app
# touch yuanxihua
# vi yuanxhua
掉电后重新启动,看到文件及内容还存在。
添加AL9V576的CHAR驱动到基于linux-2.6.27的9G9260开发板
1,修改drivers/char/Makefile文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi drivers/char/Makefile
在第102行添加:
obj-$(CONFIG_FY_AL9V576) += al9v576.o
2, 修改drivers/char/Kconfig文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi drivers/char/Kconfig
在第1123行添加:
config FY_AL9V576
tristate "AverLogic AL9V576 MPEG-4/2/1 A/V Encoder"
depends on MACH_9G9260EK
help
If you say yes here you get support for the
AverLogic AL9V576 MPEG-4/2/1 A/V Encoder.
This driver can also be built as a module. If so, the module
will be called al9v576.
config FY_AL9V576_DEBUG
boolean "AL9V576 Encoder debug messages"
depends on MACH_9G9260EK && FY_AL9V576
help
Select this if you want AL9V576 debug messages
3,编译配置内核
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make menuconfig
进入配置菜单添加驱动到内核:
System Type --->
Atmel AT91 System-on-Chip --->
[*] Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit
[*] 9G9260-EK Evaluation Kit
Device Drivers --->
Character devices --->
<M> AverLogic AL9V576 MPEG-4/2/1 A/V Encoder
[*] AL9V576 Encoder debug messages
4,修改arch/arm/mach-at91/board-sam9260ek.c文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi arch/arm/mach-at91/board-sam9260ek.c
在头文件列表后添加:
#include <mach/at91sam9260.h>
#include <mach/at91sam9260_matrix.h>
#include <mach/at91sam9_smc.h>
在static void __init ek_board_init(void)内部添加:
#if defined(CONFIG_MACH_9G9260EK)
/* al9v576 */
at91_add_device_al9v576();
#endif
在static void __init ek_board_init(void)前面添加:
#if defined(CONFIG_MACH_9G9260EK)
#define AL9V576_BASE AT91_CHIPSELECT_0
#define AL9V576_SIZE SZ_1K
static struct resource al9v576_resources[] =
{
{
.start = AL9V576_BASE,
.end = AL9V576_BASE + AL9V576_SIZE - 1,
.flags = IORESOURCE_MEM,
}
};
static struct platform_device al9v576_driver =
{
.name = "al9v576",
.id = 0,
.dev =
{
.platform_data = NULL,
},
.resource = al9v576_resources,
.num_resources = ARRAY_SIZE(al9v576_resources),
};
static struct sam9_smc_config __initdata al9v576_smc_config =
{
.ncs_read_setup = 0x01,
.nrd_setup = 0x02,
.ncs_write_setup = 0x01,
.nwe_setup = 0x02,
.ncs_read_pulse = 0x08,
.nrd_pulse = 0x06,
.ncs_write_pulse = 0x08,
.nwe_pulse = 0x06,
.read_cycle = 0x12,
.write_cycle = 0x12,
.mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
.tdf_cycles = 0x08,
};
static __init void at91_add_device_al9v576(void)
{
unsigned long csa;
csa = at91_sys_read(AT91_MATRIX_EBICSA);
at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_VDDIOMSEL_3_3V);
/* setup bus-width (8 or 16) */
#if defined(CONFIG_AL9V576_BUSWIDTH_16)
al9v576_smc_config.mode |= AT91_SMC_DBW_16;
#else
al9v576_smc_config.mode |= AT91_SMC_DBW_8;
#endif
/* configure chip-select 0 (AL9V576) */
sam9_smc_configure(0, &al9v576_smc_config);
platform_device_register(&al9v576_driver);
}
#endif
5,添加drivers/char/al9v576.h文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi drivers/char/al9v576.h
添加的源码见附件。
6,添加drivers/char/al9v576.c文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi drivers/char/al9v576.c
添加的源码见附件。
7, 编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make
附件:
(保密)
9G-STM32 EWARM开发过程简介
一,准备EWARM+JLINK+STM32软件包
1,在http://www.mcu123.com/down/view.asp?id=83
下载IAR Embedded Workbench for ARM v5.20版本
EWARM-EV-WEB-520.rar
http://esoft.mcu123.com/MCU123_temp_0080309@/arm/EWARM-EV-WEB-520.rar
(注册机自行查找,安装过程略)
2,在http://www.segger.com/download_jlink.html
下载Software and documentation pack V4.04a软件
Setup_JLinkARM_V404a.zip
http://www.segger.com/pub/jlink/Setup_JLinkARM_V404a.zip
(JLINK自行购买,安装过程略)
3,在http://www.st.com/mcu/devicedocs-STM32F103T8-110.html
下载ARM-based 32-bit MCU STM32F10xxx standard peripheral library
stm32f10x_stdperiph_lib_v3.0.0.zip
http://www.st.com/stonline/products/support/micro/files/stm32f10x_stdperiph_lib_v3.0.0.zip
二,建立STM32 LCCD工程
1,解压stm32f10x_stdperiph_lib_v3.0.0.zip软件包,把其中的“Libraries”和“Project”文件夹复制到“D:\works\lccd-1.0.0\”,
在“D:\works\lccd-1.0.0\”下建立“Drivers”、“Linker”、“Include”和“Source”空文件夹,在“D:\works\lccd-1.0.0\Project”
下建立“Stm32f103”空文件夹,把“Project\Template”下的C文件复制到“Source”和H文件复制到“Include”,把“Project\Template\
EWARMv5”下的所有ICF文件复制到“Linker”;
2,在EWARM菜单中“Project”->“Create New Project”打开“Create New Project”窗口,点击“OK”打开“另存为”窗口,
选择项目工程存储路径“D:\works\lccd-1.0.0\Project\Stm32f103\”填写项目文件名“lccd.ewp",在菜单中“File”->“Save All”
打开“Save Workspace As”窗口,填写工作环境文件名“lccd.eww”;
3,在EWARM的左面“Workspace”窗口下面的“Files”空白部分右击鼠标,选择“Add”->“Add Group”出现““Add Group - lccd”窗口,
在“Group name”中填上“CMSIS”,同样方法建立“USER”“BOOT”“DRV”“INC”“LIB”等文件组后点击“Save All”快捷键;
4,在EWARM的左面“Workspace”窗口下面的“CMSIS”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - CMSIS”窗口,选择
打开“D:\works\lccd-1.0.0\Libraries\CMSIS\Core\CM3”文件夹下的“core_cm3.c”和“system_stm32f10x.c”文件;
5,在EWARM的左面“Workspace”窗口下面的“BOOT”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - BOOT”窗口,选择
打开“D:\works\lccd-1.0.0\Libraries\CMSIS\Core\CM3\startup\iar”文件夹下的“startup_stm32f10x_md.s”文件;
6,在EWARM的左面“Workspace”窗口下面的“LIB”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - LIB”窗口,选择
打开“D:\works\lccd-1.0.0\Libraries\STM32F10x_StdPeriph_Driver\src”文件夹下的“stm32f10x_gpio.c”等所有C文件;
7,在EWARM的左面“Workspace”窗口下面的“INC”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - INC”窗口,选择
打开“D:\works\lccd-1.0.0\Include”文件夹下的所有H文件;
8,在EWARM的左面“Workspace”窗口下面的“USER”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - USER ”窗口,选择
打开“D:\works\lccd-1.0.0\Source”文件夹下的所有C文件,点击“Save All”快捷键;
三,配置STM32 LCCD工程
在EWARM的左面“Workspace”窗口下面的“Files”的“lccd - Debug”左击鼠标,选择“Project”->“Options”出现“Options for node "lccd"”窗口;
1,在左面“Category:”中选择上“General Options”,在“Target”->“Processor Variant”->“Device”中选择“ST STM32F10xx8”,
在“Library Configuration”->“Library”中选择“FULL”;
2,在左面“Category:”中选择上“C/C++ Complier”,在“Preprocessor”->“Additional include directories:”中填上下面几行:
$PROJ_DIR$\..\..\Include
$PROJ_DIR$\..\..\Libraries\CMSIS\Core\CM3
$PROJ_DIR$\..\..\Libraries\STM32F10x_StdPeriph_Driver\inc
在“Preprocessor”->“Define symbols:”中填上下面几行:
USE_STDPERIPH_DRIVER
STM32F10X_MD
USE_STM3210B_EVAL(我暂时不用)
3,在左面“Category:”中选择上“Output Converter”,在“Output”中勾选“Generate addition output”并在“Output format:”中选择“binary”,
在“Output”->“Output file”中勾选“override default”并填写上目标码文件名:lccd-debug-1.0.0.bin;
4,在左面“Category:”中选择上“Linker”,在“Config”->“Linker configuration file”中勾选“override default”,在下面填上:
“$PROJ_DIR$\..\..\Linker\stm32f10x_flash.icf”,在“List”中勾选“Generate linker map file”;
5,在左面“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“J-link/J-trace”,在“Download”勾选择“Use flash loader”;
6,在左面“Category:”中选择上“J-link/J-trace”,在“Setup”->“JTAG/SWD speed”中选择“Fixed”并填上“4000”,在“Connection”->“Interface”
中选择“SWD”,点击“Save All”快捷键;
7,在EWARM的左面“Workspace”窗口下选择“Release”,然后可以对“lccd - Release”左击鼠标,选择“Project”->“Options”出现“Options for
node "lccd"”窗口,做类似上面“lccd - Debug”的配置,注意不选择调试信息及目标友文件名为lccd-release-1.0.0.bin;
四,调试STM32 LCCD工程
1,在EWARM菜单中“Project”->“Make”打开编译工程命令;
2,在EWARM菜单中“Project”->“Download and Debug”打开下载调试命令;
3,在EWARM菜单中“Debug”->“Go”打开全速运行命令;
4,其它调试命令请自行尝试;
五,修改STM32 LCCD工程
1,移植USART的PRINTF应用
A,把D:\works\lccd-1.0.0\Include\stm32f10x_conf.h的第46行的注释打开;
B,把D:\works\lccd-1.0.0\Project\Examples\USART\Printf\platform_config.h 复制到D:\works\lccd-1.0.0\Include\目录;
C,把D:\works\lccd-1.0.0\Project\Examples\USART\Printf\main.c 复制到D:\works\lccd-1.0.0\Source;
D,编译调试即可以在 RT1看到115200 8N1的字符“USART Printf Example: retarget the C library printf function to the USART”
2,整理USART的PRINTF应用
A,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\ rt.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\ rt.c的源码如下:
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stdio.h"
#include "platform_config.h"
/** @addtogroup StdPeriph_Examples
* @{
*/
/** @addtogroup USART_Printf
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void RT_Configuration(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Configures the different GPIO ports.
* @param None
* @retval : None
*/
void RT_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
#if defined USE_USART2 && defined USE_STM3210B_EVAL
/* Enable AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* Enable the USART2 Pins Software Remapping */
GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
#endif
/* Configure USARTx_Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_TxPin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOx, &GPIO_InitStructure);
/* Configure USARTx_Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_RxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOx, &GPIO_InitStructure);
/* USARTx configuration ------------------------------------------------------*/
/* USARTx configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure the USARTx */
USART_Init(USARTx, &USART_InitStructure);
/* Enable the USARTx */
USART_Cmd(USARTx, ENABLE);
}
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval : None
*/
int fputc(int ch, FILE *f)
{
/* Write a character to the USART */
USART_SendData(USARTx, (uint8_t) ch);
/* Loop until the end of transmission */
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET)
{
}
return ch;
}
/*******************************************************************************
* Function Name : fgetc
* Description : Get a key from the HyperTerminal
* Input : None
* Output : None
* Return : The Key Pressed
*******************************************************************************/
int fgetc(FILE *f)
{
/* Waiting for user input */
while ( USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET);
return (uint8_t)USARTx->DR;
}
B,修改D:\works\lccd-1.0.0\Source\main.c的int main(void)如下:
int main(void)
{
/* System Clocks Configuration */
RCC_Configuration();
/* Configure the GPIO ports */
RT_Configuration();
/* Output a message on Hyperterminal using printf function */
printf("\n\r\n\r\n\r\n\r");
printf("*** LCCD V1.0 Build by y nxih @21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** LCCD V1.0 Rebooting ...\n\r");
while (1)
{
}
}
并在文件前添加:
extern void RT_Configuration(void);
9G-STM32 EWARM开发过程简介之二
六,移植STM32 LCCD工程
1,移植GPIO的IOToggle应用
A,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\gpio.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\gpio.c的源码如下:
(参考GPIO/IOToggle/main.c)
B,修改D:\works\lccd-1.0.0\Source\main.c的int main(void) 的while (1)前加上:
/* Configure the GPIO ports */
GPIO_Configuration();
while (1)里面加上:
{
printf("*** LCCD V1.0 running %d \n\r",i++);
GPIO_Test();
}
并在文件前添加:
extern void GPIO_Configuration(void);
extern void GPIO_Test(void);
2,移植SYSTICK的应用
A,在D:\works\lccd-1.0.0\Source\main.c的int main(void)添加:
/* Setup SysTick Timer for 1 msec interrupts */
if (SysTick_Config(SystemFrequency / 1000))
{
/* Capture error */
while (1);
}
B,在D:\works\lccd-1.0.0\Source\stm32f10x_it.c 的 void SysTick_Handler(void) 加上:
TimingDelay_Decrement(); 文件前加上:
extern void TimingDelay_Decrement(void);
C,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\time.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\time.c的源码如下:
(参考SysTick/main.c)
3,移植DMA的ADC1的应用
A,修改D:\works\lccd-1.0.0\Source\main.c的int main(void) 的while (1)前加上:
/* ADC1 Configuration */
ADC_Configuration();
while (1)里面加上:
printf("*** LCCD V1.0 running %d adc =%d mv \n\r",i++,(unsigned int)ADC_read());
并在文件前添加:
extern void ADC_Configuration(void);
extern unsigned int ADC_read(void);
B,在D:\works\lccd-1.0.0\Source\stm32f10x_it.c 的 void SysTick_Handler(void) 加上:
ADC_filter();
文件前加上:
extern unsigned int ADC_filter(void);
C,在D:\works\lccd-1.0.0\Include\stm32f10x_conf.h 中,打开注释:
#include "stm32f10x_adc.h"
#include "stm32f10x_dma.h"
D,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\adc.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\adc.c的源码如下:
(参考ADC/ADC1_DMA/main.c)
4,移植TIM的PWM应用
A,修改D:\works\lccd-1.0.0\Source\main.c的int main(void) 的while (1)前加上:
/* TIM1 Configuration */
TIM2_Configuration();
/* TIM1 Configuration */
TIM2_Configuration();
并在文件前添加:
extern void TIM1_Configuration(void);
extern void TIM2_Configuration(void);
B,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\tim.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\tim.c的源码如下:
(参考TIM/PWM_Output/main.c)
5,移植EXTI的外部中断应用
A,修改D:\works\lccd-1.0.0\Source\main.c的int main(void) 的while (1)前加上:
/* EXTI Configuration */
EXTI_Configuration();
并在文件前添加:
extern void EXTI_Configuration(void);
B,在D:\works\lccd-1.0.0\Source\stm32f10x_it.c 的 void SysTick_Handler(void) 后面加上:
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
EXTI_PA0_IRQHandler();
/* Clear the EXTI_Line9 pending bit */
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
在文件前加上:
extern void EXTI_PA0_IRQHandler(void);
C, 在D:\works\lccd-1.0.0\Include\stm32f10x_it.h 的 void SysTick_Handler(void) 后面加上
void EXTI0_IRQHandler(void);
D,在D:\works\lccd-1.0.0\Include\stm32f10x_conf.h 中,打开注释:
#include "stm32f10x_exti.h"
#include "misc.h"
E,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\exti.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\exti.c的源码如下:
(NVIC/Priority/main.c)
9G-AVR EWAVR开发过程简介
一,准备EWARM+AVR STUDIO+PROTEUS+UIP软件包
1,在http://www.mcu123.com/news/Soft/embsof/avr/200902/491.html
下载IAR Embedded Workbench for AVR 5.20 FULL版本
CD-EWAVR-520-2.zip
http://esoft.mcu123.com/MCU123_temp_0080309@/avr/CD-EWAVR-520-2.zip
(注册机自行查找,安装过程略)
2,在http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725
下载AVR Studio 4.16 (build 628)软件
AvrStudio416Setup.exe
http://www.atmel.com/dyn/resources/prod_documents/AvrStudio416Setup.exe
(AVRISP自行购买,安装过程略)
3, 在http://bbs.cechina.cn/ShowTopic.aspx?id=78131上下载
Proteus Pro 7[1].4 sp3.part01.rar 到 Proteus Pro 7[1].4 sp3.part15.rar
其中Proteus Pro 7[1].4 sp3.part08.rar下载不了,请到
在http://bbs.eeworld.com.cn/viewthread.php?tid=71645上注册下载
下载Proteus Pro 7.4 sp3.part08.rar (3.91 MB) 软件
Proteus_Pro_7.4_sp3.part08.rar
按次序改名成Proteus_Pro_7.4_sp3.part01.rar至Proteus_Pro_7.4_sp3.part15.rar后
解压即得到Proteus Pro 7.4 sp3软件及基注册号和破解补丁;
(汉化文件自己找)
4,在http://www.sics.se/~adam/uip/index.php/Download
下载uip-1.0.tar.gz软件
uip-1.0.tar.gz
http://www.sics.se/~adam/download/?f=uip-1.0.tar.gz
5,在http://www.tuxgraphics.org/common/src2/article09051/上下载
eth_tcp_client_server-3.3.tar.gz
http://www.tuxgraphics.org/common/src2/article09051/eth_tcp_client_server-3.3.tar.gz
二,建立AVR NET工程
1,在IAR EW IDE菜单中“Project”->“Create New Project”打开“Create New Project”窗口,点击“OK”打开“另存为”窗口,
选择项目工程存储路径“D:\works\avrnet-1.0.0\Project\”填写项目文件名“avrnet.ewp",在菜单中“File”->“Save All”
打开“Save Workspace As”窗口,填写工作环境文件名“avrnet.eww”;
2,在“D:\works\avrnet-1.0.0\”下建立“driver”、“atmega32”“include”和“source”空文件夹;
3,在D:\works\avrnet-1.0.0\driver\下建立uart.c如下:
#include "config.h"
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = (1<<URSEL) | 0x06;
UBRRL = 0x33; //set baud rate lo
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x18;
}
int putchar(int c)
{
while(!(UCSRA&(1<<UDRE)));
UDR=(char)c;
return 0;
}
int getchar(void)
{
while(!(UCSRA&(1<<RXC)));
return (int)UDR;
}
4,在D:\works\avrnet-1.0.0\atmega32\下建立main.c如下:
#include "config.h"
extern void uart0_init(void);
void init_devices(void)
{
_CLI(); //disable all interrupts
MCUCR = 0x00;
MCUCSR = 0x80;//禁止JTAG
GICR = 0x00;
uart0_init();
_SEI(); //re-enable interrupts
}
int main(void)
{
unsigned int i=0;
init_devices();
printf("\n\r\n\r\n\rAVRnet Version 1.0-ATmega32A (yuanxihuah@21cn.com) Build on %s %s\n\r\n\r",__DATE__,__TIME__);
while(1)
{
__delay_cycles(16*1000);
printf("\n\rAVRnet-1.0.0 run time = %d ...",i++);
}
}
5,在D:\works\avrnet-1.0.0\include\下建立config.h如下:
#include <stdio.h>
#ifndef ENABLE_BIT_DEFINITIONS
#define ENABLE_BIT_DEFINITIONS
// Enable the bit definitions in the iom128.h file
#endif
#include <avr_macros.h>
#include <ina90.h>
#include <intrinsics.h>
#include <iomacro.h>
#include <iom32a.h>
三,配置AVR NET工程
1, 在IAR EW IDE的左面“Workspace”窗口下面的“Files”空白部分右击鼠标,选择“Add”->“Add Group”出现““Add Group - avrnet”窗口,
在“Group name”中填上“DRV”,同样方法建立“SRC”“INC”“LIB”等文件组后点击“Save All”快捷键;
2, 在IAR EW IDE的左面“Workspace”窗口下面的“SRC”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - SRC”窗口,选择
打开“D:\works\avrnet-1.0.0\atmega32”文件夹下的main.c文件;
3, 在IAR EW IDE的左面“Workspace”窗口下面的“SRC”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - SRC”窗口,选择
打开“D:\works\avrnet-1.0.0\driver”文件夹下的uart.c文件;
在IAR EW IDE的左面“Workspace”窗口下面的“Files”的“avrnet - Release”左击鼠标,选择“Project”->“Options”出现“Options for node "avrnet"”窗口;
4,在左面“Category:”中选择上“General Options”,在“Target”->“Processor configuration”中选择“--cpu=m32a, Atmega32A”,
“Memory model”中选择“Small”;
5,在左面“Category:”中选择上“C/C++ Complier”,在“Preprocessor”->“Additional include directories:”中填上下面几行:
$PROJ_DIR$\..\include
$PROJ_DIR$\..\library\uip-1.0\uip
6,在左面“Category:”中选择上“Linker”,在“Output”中勾选“override default”,在下面填上:avrnet-1.0.0.hex
在“Format”中勾选“Other”并在“Output”后面选择上“intel-standard”;
四,调试AVR NET工程
1,在IAR EW IDE菜单中“Project”->“Make”打开编译工程命令生成目标码:
D:\works\avrnet-1.0.0\project\Release\Exe\avrnet-1.0.0.hex
2,利用Proteus仿真程序(自行实现)。
五,移植AVR NET工程
1,解压uip-1.0.tar.gz软件包,把全部代码的“uip-1.0”文件夹复制到“D:\works\avrnet-1.0.0\library”,修改D:\works\avrnet-1.0.0\library\uip-1.0\unix\main.c
为uip_main.c并与其它C文件一起复制到D:\works\avrnet-1.0.0\atmega32,H文件复制到D:\works\avrnet-1.0.0\include下面;
2,在IAR EW IDE的左面“Workspace”窗口下面的“Files”空白部分右击鼠标,选择“Add”->“Add Group”出现“Add Group - avrnet”窗口,
在“Group name”中填上“UIP”后点击“Save All”快捷键;
3,在IAR EW IDE的左面“Workspace”窗口下面的“UIP”上右击鼠标,选择“Add”->“Add Group”出现““Add Group - UIP”窗口,
在“Group name”中填上“UIP”,同样方法建立“APPS”“LIB”“UNIX”等文件组后点击“Save All”快捷键;
4,在IAR EW IDE的左面“Workspace”窗口“UIP”下面的“UIP”上右击鼠标,选择“Add”->“Add Files”出现“Add Files - UIP”窗口,选择
打开“D:\works\avrnet-1.0.0\library\uip-1.0\uip” 文件夹下的8个C文件;
5,在IAR EW IDE的左面“Workspace”窗口“UIP”下面的“LIB”上右击鼠标,选择“Add”->“Add Files”出现“Add Files - LIB”窗口,选择
打开“D:\works\avrnet-1.0.0\library\uip-1.0\lib” 文件夹下的1个C文件;
6,在D:\works\avrnet-1.0.0\include建立inttypes.h文件:
#ifndef __INTTYPES_H_
#define __INTTYPES_H_
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed int int16_t;
typedef unsigned int uint16_t;
typedef signed long int int32_t;
typedef unsigned long int uint32_t;
typedef signed long long int int64_t;
typedef unsigned long long int uint64_t;
#endif /* __INTTYPES_H_ */
7,添加ENC28J60驱动
解压eth_tcp_client_server-3.3.tar.gz文件包,把其中的enc28j60.c和enc28j60.h复制到D:\works\avrnet-1.0.0\driver目录;
用上面类似的方式添加到工程目录“DRV”中;
把enc28j60.c的第15行的#include <avr/io.h>修改为:#include "config.h"
把enc28j60.c的第20行的#include <util/delay.h>修改为:#include "delay.h" //#include <util/delay.h>
在D:\works\avrnet-1.0.0\include建立delay.h文件,实现以下延时接口;
void _delay_loop_1(uint8_t __count){}
void _delay_loop_2(uint16_t __count){}
void _delay_ms(double __ms){}
void _delay_us(double __us){}
修改D:\works\avrnet-1.0.0\atmega32\tapdev.c文件的驱动接口函数:
#include "config.h"
#include "uip.h"
#include "clock-arch.h"
extern void enc28j60Init(uint8_t* macaddr);
extern uint16_t enc28j60PacketReceive(uint16_t maxlen, uint8_t* packet);
extern void enc28j60PacketSend(uint16_t len, uint8_t* packet);
volatile unsigned int Packet_length;
/*---------------------------------------------------------------------------*/
void tapdev_init(void)
{
#if UIP_FIXEDETHADDR == 0
extern unsigned char avr_mac[];
#else
unsigned char avr_mac[] = {UIP_ETHADDR0,UIP_ETHADDR1,UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5};
#endif
enc28j60Init(avr_mac);
Packet_length = 0;
GICR |= 0x01 << 6;
}
/*---------------------------------------------------------------------------*/
unsigned int tapdev_read(void)
{
unsigned int temp;
extern volatile clock_time_t sys_ticks;
temp = sys_ticks;
while (Packet_length == 0 && temp == sys_ticks) {;}
temp = Packet_length;
Packet_length = 0;
return temp;
}
/*---------------------------------------------------------------------------*/
#pragma vector=INT0_vect
__interrupt void enc28j60_int(void)
{
Packet_length = enc28j60PacketReceive(UIP_BUFSIZE,uip_buf);
}
void tapdev_send(void)
{
enc28j60PacketSend(uip_len ,uip_buf);
}
8,增加系统定时器
把D:\works\avrnet-1.0.0\atmega32的第42行修改为:#include "config.h"//#include <sys/time.h>
在clock_time_t clock_time(void) {}前面增加:volatile clock_time_t sys_ticks;
并且把clock_time_t clock_time(void) {}函数体其它内容注释掉,改为:return sys_ticks;
在D:\works\avrnet-1.0.0\driver建立clock.c文件:
#include "clock-arch.h"
#include "config.h"//#include <sys/time.h>
extern volatile clock_time_t sys_ticks;
void sys_clock_init(void)
{
TCCR0 = 0;
TCCR0 |= (1 << CS02);
TIMSK |= (1 << TOIE0);
TCNT0 = 0x06;
sys_ticks = 0;
}
#pragma vector=TIMER0_OVF_vect //定时器0溢出中断入口地址
__interrupt void time0(void)
{
TCNT0 = 0x06;
sys_ticks++;
}
六,测试TELNET协议
1, 在IAR EW IDE的左面“Workspace”窗口“UIP”下面的“APPS”上右击鼠标,选择“Add”->“Add Files”出现“Add Files - APPS”窗口,选择
D:\works\avrnet-1.0.0\library\uip-1.0\apps下面的“TELNETD”文件夹的C文件加入到项目后,点击“Save All”快捷键;
2,在左面“Category:”中选择上“C/C++ Complier”,在“Preprocessor”->“Additional include directories:”中填上下面几行:
$PROJ_DIR$\..\library\uip-1.0\apps\telnetd
$PROJ_DIR$\..\library\uip-1.0\lib
3,打开D:\works\avrnet-1.0.0\include\uip-conf.h 把第148行的#include "telnetd.h"注释打开;
4,打开D:\works\avrnet-1.0.0\atmega32\uip_main.c文件,加入#include "config.h" 包含,修改main(void)为uip_main(void),并在其中打开
telnetd_init();注释掉 /* httpd_init(); */,完成;
5,在D:\works\avrnet-1.0.0\atmega32\main.c文件前加入extern int uip_main(void);并在while(1) 前加入调用uip_main();主程序,完成。
6,在D:\works\avrnet-1.0.0\include\uip-conf.h中,修改#define UIP_CONF_MAX_CONNECTIONS 6 //40 减少连接数,修改
#define UIP_CONF_MAX_LISTENPORTS 1 //40,修改#define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN //LITTLE_ENDIAN,
并且添加以下代码:
#define TELNETD_CONF_NUMLINES 1
#define TELNETD_CONF_LINELEN 40
#define notdef 0
#define UIP_CONF_IPV6 0
#define UIP_ARCH_ADD32 0
#define UIP_ARCH_CHKSUM 0
#define UIP_NEIGHBOR_CONF_ADDRTYPE 0
#define UIP_IPADDR0 192
#define UIP_IPADDR1 168
#define UIP_IPADDR2 1
#define UIP_IPADDR3 80
#define UIP_NETMASK0 255
#define UIP_NETMASK1 255
#define UIP_NETMASK2 255
#define UIP_NETMASK3 0
#define UIP_DRIPADDR0 192
#define UIP_DRIPADDR1 168
#define UIP_DRIPADDR2 1
#define UIP_DRIPADDR3 1
#define UIP_ETHADDR0 'A'
#define UIP_ETHADDR1 'V'
#define UIP_ETHADDR2 'R'
#define UIP_ETHADDR3 'N'
#define UIP_ETHADDR4 'E'
#define UIP_ETHADDR5 'T'
7,编译通过。(参考了网络上的一些例子,只记得有一个是风城少主的。请多包涵。)
9G-S08 CWS08开发过程简介
一,9G-S08 CWS08开发过程简介
一,准备CWS08+LICEMSE+OSBDM 软件包
1,在http://www.myhcs08.com/upload/soft/CW_MCU_V6_2_SE.rar
下载CodeWarrior for HCS08 V6.2软件
CW_MCU_V6_2_SE.rar
http://www.myhcs08.com/upload/soft/CW_MCU_V6_2_SE.rar
(自行安装到默认C盘)
2,在http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=1709998&bbs_page_no=1&bbs_id=2070
点击此处下载 ourdev_479901.zip(文件大小:3K) (原文件名:licenseForCW62.zip)
解压后得到文件license.dat
http://www.ouravr.com/bbs/bbs_upload387291/files_11/ourdev_479901.zip
(把license.dat文件解压放在C:\Program Files\Freescale\CodeWarrior for Microcontrollers V6.2目录)
3,在http://shop36265907.taobao.com/
或者http://longqiu.21ic.org 上联系购买
BDM XS128 USBDM V1.3 8/16/32位 通用下载器及驱动程序
如需要自己制作请查看:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1312798&bbs_page_no=1&bbs_id=2070
网址。
二,建立工程
1,在XP开始菜单“所有程序->Freescale CodeWarrior->CW for Microcontrollers V6.2”中打开CodeWarrior IDE,
在Startup向导框中选择“Create New Project”向导,点开“HCS08”下面的“HCS08Q Family”选择“MC9S08QD4”按“下一步”;
2,默认选择C语言开发,项目名称用“qd4_ook.mcp”,项目路径用“D:\works\qd4_ook-1.0”点“下一步”,不用添加源码,再点击“下一步”,
快速开发意见选择“None”点击“下一步”,启动代码,内存模式,浮点模式用默认,再点“下一步”,PC-LINT版本管理用“No”,点击“完成”;
3,点开项目工程的“Files”中的“Sources”中的“main.c”,在main.c中的void main(void) { 前添加以下代码:
void delay_ms(int nms)
{
int i,j;
for(i=0;i<nms;i++)
{ for(j=0;j<300;j++){__RESET_WATCHDOG();}} //
}
在 for(;;) { 前添加:
PTADD = 0xFF;
PTAD= 0x00;
在 for(;;) { 里添加:
delay_ms(500);
PTAD=~PTAD;
三,编译工程
1,在IDE左面工程框中选择“HCS08 Open Source BDM”,执行菜单“Project->Make”,编译代码。
四,调试工程
1,插上USB接口的BDM工具及MC9S08QD4的小开发板,(板子由BDM提供5V,GND,RST和BKGD信号,PTA0上上拉一个LED到5V);
2,执行菜单“Project->Debug”,确认弹出两个对话框,就把目标码下载到CPU,并弹出“True-Time Simulator & Real-Time Debugger”工具;
3,在Debugger窗口菜单中执行“Run->Start/Continue”全速运行代码,就能在MC9S08QD4的LED上看到闪烁;
4,其它的高级单步,跳过,跳出,汇编单步,暂停,复位等自行尝试。
9G-S12 CWS12开发过程简介
一,准备CWS12+LICENSE+OSBDM 软件包
1,在http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=CW-HCS12X&fpsp=1&tab=Design_Tools_Tab
上注册下载Eval tion: CodeWarrior Development Studio for Freescale HCS12(X) Microcontrollers V5.0 软件
CW_S12_v5.0_Eval.exe
(自行安装到默认C盘)
2,在www.mcu123.net/bbs/ 上下载uFztvdTV.rar 文件包
解压后得到文件license.dat
(把license.dat文件解压放在C:\Program Files\Freescale\CodeWarrior for S12(X) V5.0目录)
3,在http://shop36265907.taobao.com/上联系购买
BDM XS128 USBDM V1.3 8/16/32位 通用下载器及驱动程序
如需要自己制作请查看:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1312798&bbs_page_no=1&bbs_id=2070
网址。
二,建立9S12_ook工程
1,在启动菜单中打开CodeWarrior IDE,在Startup向导框中选择“Create New Project”向导,点开“HCS12X”下面的“HCS12XS Family”
下面的“MC9S12XS128”器件,点击“下一步”;
2,选择开发语言“C”,项目名称用“ook.mcp”项目路径用“D:\works\9S12_ook-1.0\ook”,再占点击“下一步”;添加源码,再点击“下一步”
初始化代码产生意见用“None”,点击“下一步”;启动代码,内存模式,浮点格式,都用默认,再点击“下一步”;
3,FLASH,RAM的页面影射用默认,点击“下一步”,PC-LINT代码管理意见用“None”,点击“完成”建立项目工程。
三,修改9S12_ook工程
1,打开IDE左面“Files”中“Sources”中的“main.c”文件,把该文件修改如下:
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include <stdio.h>
extern void SCI_Init(void);
void PLL_init(void)
{
CLKSEL=0X00; // disengage PLL to system
PLLCTL_PLLON=1; // turn on PLL
SYNR=0x00 | 0x01; // VCOFRQ[7:6];SYNDIV[5:0]
REFDV=0x80 | 0x01; // REFFRQ[7:6];REFDIV[5:0]
POSTDIV=0x00; // 4:0, fPLL= fVCO/(2xPOSTDIV)
_asm(nop); // BUS CLOCK=16M
_asm(nop);
while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;
CLKSEL_PLLSEL =1; //engage PLL to system;
}
void delay_ms(int nms)
{
int i,j;
for(i=0;i<nms;i++)
{ for(j=0;j<2770;j++){;}} //32MHz--1ms
}
void main(void) {
int i=0;
/* put your own code here */
PLL_init();
SCI_Init();
EnableInterrupts;
printf("\n\r\n\r\n\r9S12ook Version 1.0-xs128 (y nxih h@21cn.com) Build on %s %s\n\r\n\r",__DATE__,__TIME__);
for(;;)
{
printf("\n\r9S12ook-1.0 run times = %d ...",i++);
delay_ms(1000);
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
2,在D:\works\9S12_ook-1.0\ook中建立“Drivers”文件夹,及“ rt.c”文件:
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include <stdio.h>
void SCI_Init(void)
{
SCI0CR2=0x2c; //enable Receive Full Interrupt,RX enable,Tx enable
SCI0BDH=0x00; //SCI0BDL=busclk/(16*SCI0BDL)
SCI0BDL=0x68; //busclk 8MHz, 9600bps,SCI0BDL=0x68
}
void TERMIO_PutChar(unsigned char ch)
{
while(!(SCI0SR1&0x80)) ; //keep waiting when not empty
SCI0DRL=ch;
}
unsigned char TERMIO_GetChar(void)
{
while(!(SCI0SR1&0x80)) ; //keep waiting when not empty
return SCI0DRL;
}
3,在IDE左面“Files”点击右键,选择“Create Group”在向导中填入“Drivers”,点击“OK”,
在IDE左面“Files”下面的“Drivers”上右击选择“Add Files”,打开“D:\works\9S12_ook-1.0\ook\Drivers\ rt.c”;
四,调试9S12_ook工程
1,在菜单中选择“Project”->“Make”编译工程生成目标码;
2,把USBDM 下载器连接上开发板及USB接口,安装下载器自带的TBDML驱动;
3,在IDE工程左面的仿真类型中选择用“TBDML”然后在菜单中选择“Project”->“Debug”调试工程;
4,跳出几个框都确认后就能把目标码下载到CPU中,然后可以在实时仿真界面做单步,全速等操作。
9G-STM32 EWARM开发过程简介之三--移植 OS-II 2.86 操作系统
一,准备 OSII+JLINK+STM32开发板
1,在http://www.mcu123.com/上联系购买支持SWD的JLINK
JLINK ARM仿真器全功能版
http://www.mcu123.com/www/prodshow.asp?ProdId=NO060
一定要购买全功能支持SWD调试的版本。
2,在http://www.manley.com.cn/web/prod t_1.asp?lei_big=仿真学习套件&lei_small=STM3210系列&lan=4上联系购买
EK-STM3210E系列仿真学习套件
http://www.manley.com.cn/web/prod t_neirong_01.asp?pro=280
把开发板上的左下角的CN8旁边的R37,R38焊掉,去掉板上ST-LINK对外加JLINK的SWD接口的干扰。
3,在http://www.micrium.com/st/STM32.html上注册下载 OSII
OSII-ST-STM32F103ZE-SK.exe
http://www.micrium.com/secure/ OSII-ST-STM32F103ZE-SK.exe
解压后得到“Software”文件包
二,建立EK-STM3210E- OSII工程
1,依照以下网页在D:\works\EK-STM3210E- OSII\建立EWARM的开发工程
EK-STM3210E- OSII及项目名称stm32_ os
http://blog.163.com/yuan_xihua/blog/static/30740544200932931856676/
2,在D:\works\EK-STM3210E- OSII\ software\下建立以下文件夹目录
“ OS-II\Ports”“ OS-II\Source”“ -CPU”“ -LIB”“ -BSP”
3,在IDE工程中建立“ SW”文件组,并在此文件夹中再建立
“ OS-II->Ports”“ OS-II->Source”“ OS-CPU”“ OS-LIB”“ OS-BSp”
4,在左面“Category:”中选择上“C/C++ Complier”,在“Preprocessor”->“Additional include directories:”中添加以下预处理头文件路径
$PROJ_DIR$\..\..\ software\ OS-II\Ports
$PROJ_DIR$\..\..\ software\ OS-II\Source
$PROJ_DIR$\..\..\ software\ -CPU
$PROJ_DIR$\..\..\ software\ -LIB
$PROJ_DIR$\..\..\ software\ -BSP
5,复制源文件
A,复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD\app.c到
D:\works\EK-STM3210E- OSII\Source\app.c
把主函数改为:int os_main (void)
在文件前添加:
#include "stm32f10x.h"
#include "stdio.h"
#include "platform_config.h"
在D:\works\EK-STM3210E- OSII\Source\main.c中有while(1)前加上:
/* System Clocks Configuration */
RCC_Configuration();
/* Configure the GPIO ports */
GPIO_Configuration();
/* Configure the UART ports */
UART_Configuration();
/* Setup SysTick Timer for 1 msec interrupts */
if (SysTick_Config(SystemFrequency / 1000))
{
/* Capture error */
while (1);
}
/* ADC1 Configuration */
ADC_Configuration();
/* Output a message on Hyperterminal using printf function */
printf("\n\r\n\r\n\r\n\r");
printf("*** STM32_ OS2 V2.86 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** STM32_ OS2 V2.86 Rebooting ...\n\r");
os_main();
并在文件头前加上:
extern int os_main (void);
B,复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\BSP下的源文件到
D:\works\EK-STM3210E- OSII\ software\ -BSP
复制Software\ -CPU\ARM-Cortex-M3\IAR 下的源文件到
D:\works\EK-STM3210E- OSII\ software\ -CPU
复制\Software\ -LIB\文件夹到
D:\works\EK-STM3210E- OSII\ software\ -LIB\
复制Software\ OS-II\Ports\arm-cortex-m3\Generic\IAR\下的源文件到
D:\works\EK-STM3210E- OSII\ software\ OS-II\Ports
复制Software\ OS-II\Source\下的源文件到
D:\works\EK-STM3210E- OSII\ software\ OS-II\Source\
6,复制头文件
A,复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD\app_cfg.h到
D:\works\EK-STM3210E- OSII\Include\app_cfg.h
去掉文件中下面几行:
//#define APP_CFG_PROBE_OS_PLUGIN_EN DEF_ENABLED /* DEF_ENABLED = Present, DEF_DISABLED = Not Present */
//#define APP_CFG_PROBE_COM_EN DEF_ENABLED
//#define APP_CFG_LCD_EN DEF_ENABLED
//#define APP_CFG_KSD_EN DEF_ENABLED
B,复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD\os_cfg.h 到
D:\works\EK-STM3210E- OSII\Include\os_cfg.h
复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD\includes.h到
D:\works\EK-STM3210E- OSII\Include\includes.h
复制Software\ -CPU\cpu_def.h到
D:\works\EK-STM3210E- OSII\Include\cpu_def.h
7,去掉编译中出现的找不到stm32f10x_lib.h头文件错误
注释掉所有引用到stm32f10x_lib.h的源文件的这行://#include <stm32f10x_lib.h>
在D:\works\EK-STM3210E- OSII\ software\ -BSP\bsp.c中注释掉:
// FLASH_SetLatency(FLASH_Latency_2);
// FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
和
// FLASH_SetLatency(FLASH_Latency_2); /* Embedded Flash Configuration */
// FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_Disable);
// FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
8,修改中断向量
把D:\works\EK-STM3210E- OSII\Libraries\CMSIS\Core\CM3\startup\iar\startup_stm32f10x_md.s
中的:
PendSV_Handler 改为:OS_CPU_PendSVHandler
SysTick_Handler 改为:OS_CPU_SysTickHandler
并在文件前添加:
EXTERN OS_CPU_PendSVHandler
EXTERN OS_CPU_SysTickHandler
三,移植修改EK-STM3210E- OSII工程
1,在D:\works\EK-STM3210E- OSII\ software\ -BSP\bsp.c中
修改键盘宏定义,键盘初始化及键盘状态读取,使之与EK-STM3210E板硬件相一致;
2,在D:\works\EK-STM3210E- OSII\Source\app.c中
修改接收到按键信息做相应的处理;
四,编译调试EK-STM3210E- OSII工程
按常规编译下载调试即可。
移植QtEmbedded-4.5.2到mini2440开发板
1,下载解压源码:
root@yuanxh-desktop:/# wget http://www.arm123.com.cn/linux/arm-linux-gcc-4.3.2.tgz
root@yuanxh-desktop:/# tar xzvf arm-linux-gcc-4.3.2.tgz
root@yuanxh-desktop:/# mkdir /home/yuanxh/mini2440/
root@yuanxh-desktop:/# cd /home/yuanxh/mini2440/
root@yuanxh-desktop:/home/yuanxh/mini2440# wget ftp://ftp.qtsoftware.com/qt/source/qt-x11-opensource-src-4.5.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/mini2440# wget ftp://ftp.qtsoftware.com/qt/source/qt-embedded-linux-opensource-src-4.5.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/mini2440# tar xjvf qt-x11-opensource-src-4.5.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/mini2440# tar xjvf qt-embedded-linux-opensource-src-4.5.2.tar.bz2
2,配置编译Qt源码:
root@yuanxh-desktop:/home/yuanxh/mini2440# cd qt-x11-opensource-src-4.5.2
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2# ./configure
选择o确定开源版本,选择yes接受版权;
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2# make install
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2# cd ..
root@yuanxh-desktop:/home/yuanxh/mini2440# cd qt-x11-opensource-src-4.5.2/tools/qvfb
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2/tools/qvfb# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2/tools/qvfb# make install
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2/tools/qvfb# cd ../../../
root@yuanxh-desktop:/home/yuanxh/mini2440# file qt-x11-opensource-src-4.5.2/bin/qvfb
3,配置编译QtE源码X86版本:
root@yuanxh-desktop:/home/yuanxh/mini2440# mv qt-embedded-linux-opensource-src-4.5.2 qt-embedded-linux-opensource-src-4.5.2-x86
root@yuanxh-desktop:/home/yuanxh/mini2440# cd qt-embedded-linux-opensource-src-4.5.2-x86
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-x86# ./configure -prefix /usr/local/Trolltech/QtEmbedded-4.5.2-x86 -embedded x86 -qvfb
选择o确定开源版本,选择yes接受版权;
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-x86# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-x86# make install
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-x86# cd ..
root@yuanxh-desktop:/home/yuanxh/mini2440# file /usr/local/Trolltech/QtEmbedded-4.5.2-x86/examples/widgets/analogclock/analogclock
root@yuanxh-desktop:/home/yuanxh/mini2440# cp qt-x11-opensource-src-4.5.2/bin/qvfb /usr/local/Trolltech/QtEmbedded-4.5.2-x86/bin
4,在QVFB上运行DEMO代码
建立配置脚本
root@yuanxh-desktop:/home/yuanxh/mini2440# cd /usr/local/Trolltech/QtEmbedded-4.5.2-x86
root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86# vi setenv-x86.sh
添加如下内容:
QTEDIR=/usr/local/Trolltech/QtEmbedded-4.5.2-x86
PATH=/usr/local/Trolltech/QtEmbedded-4.5.2-x86/bin:$PATH
LD_LIBRARY_PATH=/usr/local/Trolltech/QtEmbedded-4.5.2-x86/lib:$LD_LIBRARY_PATH
保存退出.
root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86# source setenv-x86.sh
root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86# cd /examples/widgets/analogclock
root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86/examples/widgets/analogclock# qvfb -width 640 -height 480 &
root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86/examples/widgets/analogclock# ./analogclock -qws
5,配置编译QtE源码ARM版本:
root@yuanxh-desktop:/home/yuanxh/mini2440# tar xvjf qt-embedded-linux-opensource-src-4.5.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/mini2440# mv qt-embedded-linux-opensource-src-4.5.2 qt-embedded-linux-opensource-src-4.5.2-arm
root@yuanxh-desktop:/home/yuanxh/mini2440# cd qt-embedded-linux-opensource-src-4.5.2-arm/
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# cd mkspecs/qws/linux-arm-g++/
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm/mkspecs/qws/linux-arm-g++# cp qmake.conf qmake.conf.org
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm/mkspecs/qws/linux-arm-g++# vi qmake.conf
把所有的 arm-linux- 修改为:/usr/local/arm/4.3.2/bin/arm-linux- 后保存
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm/mkspecs/qws/linux-arm-g++# cd ../../../
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# ./configure -prefix /usr/local/QtEmbedded-4.5.2 -embedded arm -no-webkit
选择o确定开源版本,选择yes接受版权;
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# make install
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# cd ..
root@yuanxh-desktop:/home/yuanxh/mini2440# file /usr/local/QtEmbedded-4.5.2/examples/widgets/analogclock/analogclock
root@yuanxh-desktop:/home/yuanxh/mini2440# cd /usr/local/
root@yuanxh-desktop:/usr/local# tar czvf QtEmbedded-4.5.2.tgz QtEmbedded-4.5.2
root@yuanxh-desktop:/usr/local# sz QtEmbedded-4.5.2.tgz
6,在ARM板上运行DEMO
建立配置脚本
[root@FriendlyARM /]# mkdir /usr/local/QtEmbedded-4.5.2/
[root@FriendlyARM /]# cd /usr/local/QtEmbedded-4.5.2/
[root@FriendlyARM QtEmbedded-4.5.2]# vi setenv-arm.sh
添加如下内容:
export QTDIR=/usr/local/QtEmbedded-4.5.2
export QPEDIR=/usr/local/QtEmbedded-4.5.2
export LD_LIBRARY_PATH=$QTDIR/lib:/usr/local/lib:$LD_LIBRARY_PATH
/usr/local/QtEmbedded-4.5.2/analogclock -qws &
保存退出,并执行。
[root@FriendlyARM QtEmbedded-4.5.2]# mkdir lib/
[root@FriendlyARM QtEmbedded-4.5.2]# mkdir lib/fonts/
把以下的库文件从编译生成的QtEmbedded-4.5.2.tgz文件包的/lib复制到目标板的/usr/local/QtEmbedded-4.5.2/lib
libQtCore.so.4
libQtGui.so.4
libQtNetwork.so.4
libQtSql.so.4
把例子程序analogclock从编译生成的QtEmbedded-4.5.2.tgz文件包的/examples/widgets/analogclock复制到目标板的/usr/local/QtEmbedded-4.5.2/
常用字库文件从从编译生成的QtEmbedded-4.5.2.tgz文件包的lib/fonts/复制到目标板的/usr/local/QtEmbedded-4.5.2/lib/fonts/
......
运行例子
[root@FriendlyARM QtEmbedded-4.5.2]# ./analogclock -qws
[root@FriendlyARM /]# vi /etc/init.d/rcS
在文件中加入:
/usr/local/QtEmbedded-4.5.2/setenv-arm.sh
#/bin/qtopia &
添加自动启动。
7,裁剪编译QtE源码ARM版本:
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# ./configure -prefix /usr/local/QtEmbedded-4.5.2 -embedded arm \
-release -shared -fast -no-largefile -qt-sql-sqlite -no-qt3support -no-xmlpatterns -no-mmx -no-3dnow -no-sse -no-sse2 -no-svg -no-webkit -qt-zlib -qt-gif \
-qt-libtiff -qt-libpng -qt-libmng -qt-libjpeg -make libs -nomake tools -nomake examples -nomake docs -nomake demo -no-nis -no-cups -no-iconv -no-dbus \
-no-openssl -xplatform qws/linux-arm-g++ -little-endian -qt-freetype -depths 16,18 -qt-gfx-linuxfb -no-gfx-transformed -no-gfx-multiscreen \
-no-gfx-vnc -no-gfx-qvfb -qt-kbd-usb -no-glib -qt-mouse-tslib
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# make install
// 9G-STM32 EWARM开发过程简介之四--移植FSMC的T6963C驱动
/*
一,把VDT6与T6963C连接
NOE -> /RD ;
NWE -> /WR ;
NE1 -> /CE ;
A16 -> C/D ; A16 最近,接线最方便。
PC4 -> /RST ;
D8 -> DB0 ; D8-D15 最近, 接线最方便。
...
D15 -> DB7 ;
二,把IO配置成FSMC模式
*/
void LCD_CtrlLinesConfig(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable FSMC, GPIOC, GPIOD, GPIOE clocks */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* Set PC.04(LCDRST) as alternate
function push pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
/* Set PD.04(NOE), PD.05(NWE), PD.07(NE1), PD.08(D13), PD.09(D14), PD.10(D15), PD.11(A16) as alternate
function push pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 ;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Set PE.11(D8), PE.12(D9), PE.13(D10), PE.14(D11), PE.15(D12) as alternate function push pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOE, &GPIO_InitStructure);
}
/*
三,配置FSMC工作模式
*/
void LCD_FSMCConfig(void)
{
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef p;
/*-- FSMC Configuration ------------------------------------------------------*/
/*----------------------- SRAM Bank 1 ----------------------------------------*/
/* FSMC_Bank1_NORSRAM1 configuration */
p.FSMC_AddressSetupTime = 1;
p.FSMC_AddressHoldTime = 1;
p.FSMC_DataSetupTime = 6;
p.FSMC_BusTurnAroundDuration = 1;
p.FSMC_CLKDivision = 1;
p.FSMC_DataLatency = 2;
p.FSMC_AccessMode = FSMC_AccessMode_A;
/* Color LCD configuration ------------------------------------
LCD configured as follow:
- Data/Address MUX = Disable
- Memory Type = SRAM
- Data Width = 16bit
- Write Operation = Enable
- Extended Mode = Enable
- Asynchronous Wait = Disable */
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
/* Enable FSMC_Bank1_NORSRAM1 */
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
}
/*
四,定义物理访问地址
*/ //TXEC 240128BDLNW-EY
// T6963C
/*A16=0 -- dat*/
#define LCD_DAT_ADDR (*((volatile unsigned char *) 0x60000001))
/*A16=1 -- cmd*/
#define LCD_CMD_ADDR (*((volatile unsigned char *) 0x60020001))
#define IMAGE 1
#define TEXT 0
#define VISION_PIXEL_LENGTH 240
#define VISION_PIXEL_WIDTH 128
#define FRAME_BUFFER_LENGTH 256
#define FRAME_BUFFER_WIDTH 128
/*
五,定义指令访问接口
*/
//指令&数据读写状态
static void RWCheck(void)
{
while((LCD_CMD_ADDR & 0x03) != 0x03); //低电平忙
}
//数据自动写状态
void CheckAutoWrite(void)
{
while((LCD_CMD_ADDR & 0x08) != 0x08); //低电平忙
}
//屏读/屏考贝出错状态
void CheckScreen(void)
{
while(LCD_CMD_ADDR & 0x40); //1出错,0正确
}
static void WriteDATA(unsigned char Data)
{
RWCheck();
LCD_DAT_ADDR = Data;
}
static unsigned char ReadDATA(void)
{
RWCheck();
return LCD_DAT_ADDR;
}
static void WriteCMD0(unsigned char Comd)
{
RWCheck();
LCD_CMD_ADDR = Comd;
}
static void WriteCMD1(unsigned char Para,unsigned char Comd)
{
WriteDATA(Para);
WriteCMD0(Comd);
}
static void WriteCMD2(unsigned char Par1,unsigned char Par2,unsigned char Comd)
{
WriteDATA(Par1);
WriteDATA(Par2);
WriteCMD0(Comd);
}
/*
六,定义API访问接口
*/
void LCD_Reset(void)
{
GPIO_SetBits(GPIOC, GPIO_Pin_4); //置1 LCDRST = 1;
OSTimeDlyHMSM(0, 0, 0, 10);
GPIO_ResetBits(GPIOC, GPIO_Pin_4); //清0 LCDRST = 0;
OSTimeDlyHMSM(0, 0, 0, 50);
GPIO_SetBits(GPIOC, GPIO_Pin_4); //置1 LCDRST = 1;
OSTimeDlyHMSM(0, 0, 0, 50);
}
void STM32_T6963C_Init(void)
{
unsigned int i;
/* Configure the LCD Control pins --------------------------------------------*/
LCD_CtrlLinesConfig();
/* Configure the FSMC Parallel interface -------------------------------------*/
LCD_FSMCConfig();
/* initialize sequence -------------------------------*/
LCD_Reset();
WriteCMD2(0x00,0x08,0x42); //设置显示图形首地址
WriteCMD2((FRAME_BUFFER_LENGTH/8),0x00,0x43); //设置图形显示区域宽度
WriteCMD0(0x98); //图形显示开
WriteCMD0(0x88); //设定显示方式,图形/文本或的方式
}
void STM32_T6963C_Clear(void)
{
unsigned int i;
WriteCMD2(0x00,0x00,0x24);
WriteCMD0(0xb0);
for(i=0;i<0x2000;i++)
{
WriteCMD1(0x00,0xc0);
}
WriteCMD0(0xb2);
}
//设定显示地址函数
static void LCD_Set_x_y(unsigned char x,unsigned char y,unsigned char mode)
{
unsigned int temp;
temp=(FRAME_BUFFER_LENGTH/8)*y + x/8;
if(mode==IMAGE)
{ //如果图形模式要加上图形区首地址0x0800
temp+=0x0800;
}
WriteCMD2(temp&0xff,temp/256,0x24);
}
void LCD_Paint_dot(unsigned char x,unsigned char y)
{
LCD_Set_x_y(x,y,IMAGE);
WriteCMD0(0xf8|(0x07&(~(x%8))));
}
void LCD_Clear_dot(unsigned char x,unsigned char y)
{
LCD_Set_x_y(x,y,IMAGE);
WriteCMD0(0xf0|(0x07&(~(x%8))));
}
void LCD_Paint_line_x(unsigned char y) //图形方式画一条线
{
unsigned char i;
LCD_Set_x_y(0,y,IMAGE);
for(i=0;i<(VISION_PIXEL_LENGTH/8);i++)
{
WriteCMD1(0xFF, 0xc0); //数据写地址不变
}
}
void LCD_Paint_line_y(unsigned char x)
{
unsigned char i;
for(i=0;i<VISION_PIXEL_WIDTH;i++)
{
LCD_Paint_dot(x,i);
}
}
/*
七,其它接口自行处理
*/
9G-STM32 EWARM开发过程简介之五--移植FATFS的NANDFLASH驱动
一,建立工程FATFS源码
1,在http://elm-chan.org/fsw/ff/00index_e.html上下载ff007c.zip,并把ff007c.zip里面的
src文件夹复制到D:\works\EK-STM3210E-UCOSII下,并改名为Fatfs;
2,在IDE工程中右击选择“Add Group”建立“FATFS”文件组,并在“FATFS”上右击选择“Add Files”添加
D:\works\EK-STM3210E-UCOSII\Fatfs下的C文件;
3,把D:\works\EK-STM3210E-UCOSII\Fatfs文件夹目录添加到项目头文件搜索路径中,如:
$PROJ_DIR$\..\..\Fatfs
二,移植NANDFLASH驱动接口
1,把stm32f10x_stdperiph_lib_v3.0.0\Project\Examples\FSMC\NAND下的fsmc_nand.c复制到
D:\works\EK-STM3210E-UCOSII\Drivers下,并加入到工程的DRV文件组;
2,把stm32f10x_stdperiph_lib_v3.0.0\Project\Examples\FSMC\NAND下的fsmc_nand.h复制到
D:\works\EK-STM3210E-UCOSII\Include下;
3,在fsmc_nand.c前添加上#include "stm32f10x_conf.h",并把系统中的 "stm32f10x_conf.h"
文件的/* #include "stm32f10x_fsmc.h" */注释打开;
三,修改FATFS的配置文件
1,把D:\works\EK-STM3210E-UCOSII\Fatfs下的ff.h中的宏定义:
#define _USE_MKFS 0
#define _CODE_PAGE 932
#define _FS_RPATH 0
#define _MAX_SS 512
修改为:
#define _USE_MKFS 1
#define _CODE_PAGE 936
#define _MAX_SS 2048
#define _FS_RPATH 1
2,把D:\works\EK-STM3210E-UCOSII\Fatfs下的integer.h的宏定义:
typedef enum { FALSE = 0, TRUE } BOOL;
修改为:
typedef bool BOOL;//typedef enum { FALSE = 0, TRUE } BOOL;
四,修改FATFS的DISK/IO接口
1,把diskio.c复制后改名为nandio.c替换掉工程中的diskio.c,并添加到EWARM的工程中的
“FATFS”文件组;
2,媒介初始化直接返回正常的0:
DSTATUS disk_initialize (BYTE drv)
{ return 0;}
3,媒介状态查询直接返回正常的0:
DSTATUS disk_status (BYTE drv)
{ return 0;}
4,取系统系统直接返回0(自己可以按格式修改为真实时间):
DWORD get_fattime (void)
{ return 0;}
5,媒介控制接口:
DRESULT disk_ioctl (BYTE drv,BYTE ctrl, void *buff)
{
DRESULT res = RES_OK;
uint32_t result;
if (drv){ return RES_PARERR;}
switch(ctrl)
{
case CTRL_SYNC:
break;
case GET_BLOCK_SIZE:
*(DWORD*)buff = NAND_BLOCK_SIZE;
break;
case GET_SECTOR_COUNT:
*(DWORD*)buff = (((NAND_MAX_ZONE/2) * NAND_ZONE_SIZE) * NAND_BLOCK_SIZE);
break;
case GET_SECTOR_SIZE:
*(WORD*)buff = NAND_PAGE_SIZE;
break;
default:
res = RES_PARERR;
break;
}
return res;
}
6,媒介多扇区读接口:
DRESULT disk_read (BYTE drv,BYTE *buff,DWORD sector,BYTE count)
{
uint32_t result;
if (drv || !count){ return RES_PARERR;}
result = FSMC_NAND_ReadSmallPage(buff, sector, count);
if(result & NAND_READY){ return RES_OK; }
else { return RES_ERROR; }
}
7,媒介多扇区写接口:
#if _READONLY == 0
DRESULT disk_write (BYTE drv,const BYTE *buff,DWORD sector,BYTE count)
{
uint32_t result;
uint32_t BackupBlockAddr;
uint32_t WriteBlockAddr;
uint16_t IndexTmp = 0;
uint16_t OffsetPage;
/* NAND memory write page at block address*/
WriteBlockAddr = (sector/NAND_BLOCK_SIZE);
/* NAND memory backup block address*/
BackupBlockAddr = (WriteBlockAddr + (NAND_MAX_ZONE/2)*NAND_ZONE_SIZE);
OffsetPage = sector%NAND_BLOCK_SIZE;
if (drv || !count){ return RES_PARERR;}
/* Erase the NAND backup Block */
result = FSMC_NAND_EraseBlock(BackupBlockAddr*NAND_BLOCK_SIZE);
/* Backup the NAND Write Block to High zone*/
for (IndexTmp = 0; IndexTmp < NAND_BLOCK_SIZE; IndexTmp++ )
{
FSMC_NAND_MoveSmallPage (WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp,BackupBlockAddr*NAND_BLOCK_SIZE+IndexTmp);
}
/* Erase the NAND Write Block */
result = FSMC_NAND_EraseBlock(WriteBlockAddr*NAND_BLOCK_SIZE);
/*return write the block with modify*/
for (IndexTmp = 0; IndexTmp < NAND_BLOCK_SIZE; IndexTmp++ )
{
if((IndexTmp>=OffsetPage)&&(IndexTmp < (OffsetPage+count)))
{
FSMC_NAND_WriteSmallPage((uint8_t *)buff, WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp, 1);
buff = (uint8_t *)buff + NAND_PAGE_SIZE;
}
else
{
FSMC_NAND_MoveSmallPage (BackupBlockAddr*NAND_BLOCK_SIZE+IndexTmp,WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp);
}
}
if(result == NAND_READY){ return RES_OK;}
else { return RES_ERROR;}
}
#endif /* _READONLY */
五,调用接口及测试代码
1,调用接口,先初始化FSMC和NANDFLASH:
//NANDFLASH HY27UF081G2A-TPCB
#define NAND_HY_MakerID 0xAD
#define NAND_HY_DeviceID 0xF1
/* Configure the NAND FLASH */
void NAND_Configuration(void)
{
NAND_IDTypeDef NAND_ID;
/* Enable the FSMC Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
/* FSMC Initialization */
FSMC_NAND_Init();
/* NAND read ID command */
FSMC_NAND_ReadID(&NAND_ID);
/* Verify the NAND ID */
if((NAND_ID.Maker_ID == NAND_ST_MakerID) && (NAND_ID.Device_ID == NAND_ST_DeviceID))
{
printf("ST NANDFLASH");
}
else
if((NAND_ID.Maker_ID == NAND_HY_MakerID) && (NAND_ID.Device_ID == NAND_HY_DeviceID))
{
printf("HY27UF081G2A-TPCB");
}
printf(" ID = 0x%x%x%x%x \n\r",NAND_ID.Maker_ID,NAND_ID.Device_ID,NAND_ID.Third_ID,NAND_ID.Fourth_ID);
}
2,然后对媒介格式化,创建读写文件:
void test_fatfs(void)
{
FATFS fs;
FIL fl;
FATFS *pfs;
DWORD clust;
unsigned int r,w,i;
FRESULT res;
// NF_CHKDSK(0,1024);
display_page(0,0);
// for mount
res=f_mount(0,&fs);
printf("f_mount=%x \n\r",res);
// for format
//res=f_mkfs(0,1,2048); //MUST Format for New NANDFLASH !!!
//printf("f_mkfs=%x \n\r",res);
// for
pfs=&fs;
res = f_getfree("/", &clust, &pfs);
printf("f_getfree=%x \n\r",res);
printf("\n\r%lu MB total drive space."
"\n\r%lu MB available.\n\r",
(DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,
clust * pfs->csize /2/1024);
// for read
res=f_open(&fl,"/test2.dat",FA_OPEN_EXISTING | FA_READ);
printf("f_open=%x \n\r",res);
for(i=0;i<2;i++)
{
for(r = 0; r < NAND_PAGE_SIZE; r++)
{
RxBuffer[r]= 0xff;
}
res=f_read(&fl,RxBuffer,NAND_PAGE_SIZE,&r);
printf("f_read=%x \n\r",res);
if(res || r == 0)break;
for(r = 0; r < NAND_PAGE_SIZE; r++)
{
printf("D[%08x]=%02x ",(i*NAND_PAGE_SIZE+r),RxBuffer[r]);
if((r%8)==7)
{printf("\n\r");}
}
}
f_close(&fl);
// for write
res=f_open(&fl,"/test2.dat",FA_CREATE_ALWAYS | FA_WRITE);
printf("f_open=%x \n\r",res);
for(i=0;i<2;i++)
{
for(w = 0; w < NAND_PAGE_SIZE; w++)
{
TxBuffer[w]=((w<<0)&0xff);
}
res=f_write(&fl,TxBuffer,NAND_PAGE_SIZE,&w);
printf("f_write=%x \n\r",res);
if(res || w<NAND_PAGE_SIZE)break;
}
f_close(&fl);
// for umount
f_mount(0,NULL);
}
六,编写NANDFLASH接口
1,fsmc_nand.c文件:
/* Includes ------------------------------------------------------------------*/
#include "fsmc_nand.h"
#include "stm32f10x_conf.h"
/** @addtogroup StdPeriph_Examples
* @{
*/
/** @addtogroup FSMC_NAND
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define FSMC_Bank_NAND FSMC_Bank2_NAND
#define Bank_NAND_ADDR Bank2_NAND_ADDR
#define Bank2_NAND_ADDR ((uint32_t)0x70000000)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Configures the FSMC and GPIOs to interface with the NAND memory.
* This function must be called before any write/read operation
* on the NAND.
* @param None
* @retval : None
*/
void FSMC_NAND_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NANDInitTypeDef FSMC_NANDInitStructure;
FSMC_NAND_PCCARDTimingInitTypeDef p;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE);
/*-- GPIO Configuration ------------------------------------------------------*/
/* CLE, ALE, D0->D3, NOE, NWE and NCE2 NAND pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15 |
GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* D4->D7 NAND pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* NWAIT NAND pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* INT2 NAND pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/*-- FSMC Configuration ------------------------------------------------------*/
p.FSMC_SetupTime = 0x1;
p.FSMC_WaitSetupTime = 0x3;
p.FSMC_HoldSetupTime = 0x2;
p.FSMC_HiZSetupTime = 0x1;
FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND;
FSMC_NANDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Enable;
FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable;
FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;
FSMC_NANDInitStructure.FSMC_TCLRSetupTime = 0x00;
FSMC_NANDInitStructure.FSMC_TARSetupTime = 0x00;
FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;
FSMC_NANDInit(&FSMC_NANDInitStructure);
/* FSMC NAND Bank Cmd Test */
FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);
}
/**
* @brief Reads NAND memory's ID.
* @param NAND_ID: pointer to a NAND_IDTypeDef structure which will hold
* the Manufacturer and Device ID.
* @retval : None
*/
void FSMC_NAND_ReadID(NAND_IDTypeDef* NAND_ID)
{
uint32_t data = 0;
/* Send Command to the command area */
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READID;
/* Send Address to the address area */
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = NAND_CMD_IDADDR;
/* Sequence to read ID from NAND flash */
data = *(__IO uint32_t *)(Bank_NAND_ADDR | DATA_AREA);
NAND_ID->Maker_ID = DATA_1st_CYCLE (data);
NAND_ID->Device_ID = DATA_2nd_CYCLE (data);
NAND_ID->Third_ID = DATA_3rd_CYCLE (data);
NAND_ID->Fourth_ID = DATA_4th_CYCLE (data);
}
/**
* @brief This routine is for move one 2048 Bytes Page size to an other 2048 Bytes Page.
* the copy-back program is permitted just between odd address pages or even address pages.
* @param SourcePageAddress: Source page address
* @param TargetPageAddress: Target page address
* @retval : New status of the NAND operation. This parameter can be:
* - NAND_TIMEOUT_ERROR: when the previous operation generate
* a Timeout error
* - NAND_READY: when memory is ready for the next operation
* And the new status of the increment address operation. It can be:
* - NAND_VALID_ADDRESS: When the new address is valid address
* - NAND_INVALID_ADDRESS: When the new address is invalid address
*/
uint32_t FSMC_NAND_MoveSmallPage(uint32_t SourcePageAddress, uint32_t TargetPageAddress)
{
uint32_t status = NAND_READY ;
uint32_t data = 0xff;
/* Page write command and address */
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE0;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(SourcePageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(SourcePageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(SourcePageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(SourcePageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE1;
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE2;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(TargetPageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(TargetPageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(TargetPageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(TargetPageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE3;
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
/* Check status for successful operation */
status = FSMC_NAND_GetStatus();
data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
if(!(data&0x1)) status = NAND_READY;
return (status);
}
/**
* @brief This routine is for writing one or several 2048 Bytes Page size.
* @param pBuffer: pointer on the Buffer containing data to be written
* @param PageAddress: First page address
* @param NumPageToWrite: Number of page to write
* @retval : New status of the NAND operation. This parameter can be:
* - NAND_TIMEOUT_ERROR: when the previous operation generate
* a Timeout error
* - NAND_READY: when memory is ready for the next operation
* And the new status of the increment address operation. It can be:
* - NAND_VALID_ADDRESS: When the new address is valid address
* - NAND_INVALID_ADDRESS: When the new address is invalid address
*/
uint32_t FSMC_NAND_WriteSmallPage(uint8_t *pBuffer, uint32_t PageAddress, uint32_t NumPageToWrite)
{
uint32_t index = 0x00, numpagewritten = 0x00,addressstatus = NAND_VALID_ADDRESS;
uint32_t status = NAND_READY, size = 0x00;
uint32_t data = 0xff;
while((NumPageToWrite != 0x00) && (addressstatus == NAND_VALID_ADDRESS) && (status == NAND_READY))
{
/* Page write command and address */
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE0;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
/* Calculate the size */
size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpagewritten);
/* Write data */
for(; index < size; index++)
{
*(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA) = pBuffer[index];
}
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE1;
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
/* Check status for successful operation */
status = FSMC_NAND_GetStatus();
data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
if(!(data&0x1)) status = NAND_READY;
if(status == NAND_READY)
{
numpagewritten++; NumPageToWrite--;
/* Calculate Next small page Address */
if(PageAddress++ > (NAND_MAX_ZONE*NAND_ZONE_SIZE*NAND_BLOCK_SIZE))
{ addressstatus = NAND_INVALID_ADDRESS;}
}
}
return (status | addressstatus);
}
/**
* @brief This routine is for sequential read from one or several
* 2048 Bytes Page size.
* @param pBuffer: pointer on the Buffer to fill
* @param PageAddress: First page address
* @param NumPageToRead: Number of page to read
* @retval : New status of the NAND operation. This parameter can be:
* - NAND_TIMEOUT_ERROR: when the previous operation generate
* a Timeout error
* - NAND_READY: when memory is ready for the next operation
* And the new status of the increment address operation. It can be:
* - NAND_VALID_ADDRESS: When the new address is valid address
* - NAND_INVALID_ADDRESS: When the new address is invalid address
*/
uint32_t FSMC_NAND_ReadSmallPage(uint8_t *pBuffer, uint32_t PageAddress, uint32_t NumPageToRead)
{
uint32_t index = 0x00, numpageread = 0x00, addressstatus = NAND_VALID_ADDRESS;
uint32_t status = NAND_READY, size = 0x00;
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READ1;
while((NumPageToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS))
{
/* Page Read command and page address */
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READ2;
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
/* Calculate the size */
size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpageread);
/* Get Data into Buffer */
for(; index < size; index++)
{
pBuffer[index]= *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
}
numpageread++; NumPageToRead--;
/* Calculate page address */
if(PageAddress++ > (NAND_MAX_ZONE*NAND_ZONE_SIZE*NAND_BLOCK_SIZE))
{ addressstatus = NAND_INVALID_ADDRESS;}
}
status = FSMC_NAND_GetStatus();
return (status | addressstatus);
}
/**
* @brief This routine erase complete block from NAND FLASH
* @param PageAddress: Any address into block to be erased
* @retval :New status of the NAND operation. This parameter can be:
* - NAND_TIMEOUT_ERROR: when the previous operation generate
* a Timeout error
* - NAND_READY: when memory is ready for the next operation
*/
uint32_t FSMC_NAND_EraseBlock(uint32_t PageAddress)
{
uint32_t data = 0xff, status = NAND_ERROR;
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE0;
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE1;
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
/* Read status operation ------------------------------------ */
FSMC_NAND_GetStatus();
data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
if(!(data&0x1)) status = NAND_READY;
return (status);
}
/**
* @brief This routine reset the NAND FLASH
* @param None
* @retval :NAND_READY
*/
uint32_t FSMC_NAND_Reset(void)
{
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_RESET;
return (NAND_READY);
}
/**
* @brief Get the NAND operation status
* @param None
* @retval :New status of the NAND operation. This parameter can be:
* - NAND_TIMEOUT_ERROR: when the previous operation generate
* a Timeout error
* - NAND_READY: when memory is ready for the next operation
*/
uint32_t FSMC_NAND_GetStatus(void)
{
uint32_t timeout = 0x1000000, status = NAND_READY;
status = FSMC_NAND_ReadStatus();
/* Wait for a NAND operation to complete or a TIMEOUT to occur */
while ((status != NAND_READY) &&( timeout != 0x00))
{
status = FSMC_NAND_ReadStatus();
timeout --;
}
if(timeout == 0x00)
{
status = NAND_TIMEOUT_ERROR;
}
/* Return the operation status */
return (status);
}
/**
* @brief Reads the NAND memory status using the Read status command
* @param None
* @retval :The status of the NAND memory. This parameter can be:
* - NAND_BUSY: when memory is busy
* - NAND_READY: when memory is ready for the next operation
* - NAND_ERROR: when the previous operation gererates error
*/
uint32_t FSMC_NAND_ReadStatus(void)
{
uint32_t data = 0x00, status = NAND_BUSY;
/* Read status operation ------------------------------------ */
*(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_STATUS;
data = *(__IO uint8_t *)(Bank_NAND_ADDR);
if((data & NAND_ERROR) == NAND_ERROR)
{
status = NAND_ERROR;
}
else if((data & NAND_READY) == NAND_READY)
{
status = NAND_READY;
}
else
{
status = NAND_BUSY;
}
return (status);
}
2,fsmc_nand.h文件:
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FSMC_NAND_H
#define __FSMC_NAND_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/* Exported types ------------------------------------------------------------*/
typedef struct
{
uint8_t Maker_ID;
uint8_t Device_ID;
uint8_t Third_ID;
uint8_t Fourth_ID;
}NAND_IDTypeDef;
typedef struct
{
uint16_t Zone;
uint16_t Block;
uint16_t Page;
} NAND_ADDRESS;
/* Exported constants --------------------------------------------------------*/
/* NAND Area definition for STM3210E-EVAL Board RevD */
#define CMD_AREA (uint32_t)(1<<16) /* A16 = CLE high */
#define ADDR_AREA (uint32_t)(1<<17) /* A17 = ALE high */
#define DATA_AREA ((uint32_t)0x00000000)
/* FSMC NAND memory command */
#define NAND_CMD_READ1 ((uint8_t)0x00)
#define NAND_CMD_READ2 ((uint8_t)0x30)
#define NAND_CMD_WRITE0 ((uint8_t)0x80)
#define NAND_CMD_WRITE1 ((uint8_t)0x10)
#define NAND_CMD_MOVE0 ((uint8_t)0x00)
#define NAND_CMD_MOVE1 ((uint8_t)0x35)
#define NAND_CMD_MOVE2 ((uint8_t)0x85)
#define NAND_CMD_MOVE3 ((uint8_t)0x10)
#define NAND_CMD_ERASE0 ((uint8_t)0x60)
#define NAND_CMD_ERASE1 ((uint8_t)0xD0)
#define NAND_CMD_READID ((uint8_t)0x90)
#define NAND_CMD_IDADDR ((uint8_t)0x00)
#define NAND_CMD_STATUS ((uint8_t)0x70)
#define NAND_CMD_RESET ((uint8_t)0xFF)
/* NAND memory status */
#define NAND_VALID_ADDRESS ((uint32_t)0x00000100)
#define NAND_INVALID_ADDRESS ((uint32_t)0x00000200)
#define NAND_TIMEOUT_ERROR ((uint32_t)0x00000400)
#define NAND_BUSY ((uint32_t)0x00000000)
#define NAND_ERROR ((uint32_t)0x00000001)
#define NAND_READY ((uint32_t)0x00000040)
/* FSMC NAND memory parameters */
//#define NAND_PAGE_SIZE ((uint16_t)0x0200) /* 512 bytes per page w/o Spare Area */
//#define NAND_BLOCK_SIZE ((uint16_t)0x0020) /* 32x512 bytes pages per block */
//#define NAND_ZONE_SIZE ((uint16_t)0x0400) /* 1024 Block per zone */
//#define NAND_SPARE_AREA_SIZE ((uint16_t)0x0010) /* last 16 bytes as spare area */
//#define NAND_MAX_ZONE ((uint16_t)0x0004) /* 4 zones of 1024 block */
/* FSMC NAND memory HY27UF081G2A-TPCB parameters */
#define NAND_PAGE_SIZE ((uint16_t)0x0800) /* 2048 bytes per page w/o Spare Area */
#define NAND_BLOCK_SIZE ((uint16_t)0x0040) /* 64x2048 bytes pages per block */
#define NAND_ZONE_SIZE ((uint16_t)0x0200) /* 512 Block per zone */
#define NAND_SPARE_AREA_SIZE ((uint16_t)0x0040) /* last 64 bytes as spare area */
#define NAND_MAX_ZONE ((uint16_t)0x0002) /* 2 zones of 1024 block */
/* FSMC NAND memory data computation */
#define DATA_1st_CYCLE(DATA) (uint8_t)((DATA)& 0xFF) /* 1st data cycle */
#define DATA_2nd_CYCLE(DATA) (uint8_t)(((DATA)& 0xFF00) >> 8) /* 2nd data cycle */
#define DATA_3rd_CYCLE(DATA) (uint8_t)(((DATA)& 0xFF0000) >> 16) /* 3rd data cycle */
#define DATA_4th_CYCLE(DATA) (uint8_t)(((DATA)& 0xFF000000) >> 24) /* 4th data cycle */
/* FSMC NAND memory HY27UF081G2A-TPCB address computation */
#define ADDR_1st_CYCLE(PADDR) (uint8_t)(0x0) /* 1st addressing cycle */
#define ADDR_2nd_CYCLE(PADDR) (uint8_t)(0x0) /* 2nd addressing cycle */
#define ADDR_3rd_CYCLE(PADDR) (uint8_t)(PADDR & 0xFF) /* 3rd addressing cycle */
#define ADDR_4th_CYCLE(PADDR) (uint8_t)((PADDR>>8) & 0xFF) /* 4th addressing cycle */
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void FSMC_NAND_Init(void);
void FSMC_NAND_ReadID(NAND_IDTypeDef* NAND_ID);
uint32_t FSMC_NAND_WriteSmallPage(uint8_t *pBuffer, uint32_t Address, uint32_t NumPageToWrite);
uint32_t FSMC_NAND_ReadSmallPage (uint8_t *pBuffer, uint32_t Address, uint32_t NumPageToRead);
uint32_t FSMC_NAND_MoveSmallPage (uint32_t SourcePageAddress, uint32_t TargetPageAddress);
//uint32_t FSMC_NAND_WriteSpareArea(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumSpareAreaTowrite);
//uint32_t FSMC_NAND_ReadSpareArea(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumSpareAreaToRead);
uint32_t FSMC_NAND_EraseBlock(uint32_t Address);
uint32_t FSMC_NAND_Reset(void);
uint32_t FSMC_NAND_GetStatus(void);
uint32_t FSMC_NAND_ReadStatus(void);
//uint32_t FSMC_NAND_AddressIncrement(NAND_ADDRESS* Address);
#endif /* __FSMC_NAND_H */
七,NFTL代码层
有关NFTL代码,自行处理。
9G-STM32 MDK-ARM开发过程简介
一,准备MDK-ARM+JLINK+STM32软件包
1,在http://www.mcu123.com/news/Soft/embsof/arm/200908/505.html
下载RealView MDK-ARM 3.80a(MDK-ARM V3.80a,MDK3.80a)版本
mdk380a_mcu123.rar
http://esoft.mcu123.com/MCU123_temp_0080309@/arm/mdk380a_mcu123.rar
(注册机自行查找,安装过程略)
2,在http://www.segger.com/cms/jlink-software.html
下载Software and documentation pack V4.08l软件
Setup_JLinkARM_V408l.zip
http://www.segger.com/cms/admin/uploads/userfiles/file/J-Link/Setup_JLinkARM_V408l.zip
(JLINK自行购买,安装过程略)
3,在http://www.st.com/mcu/familiesdocs-110.html
下载ARM-based 32-bit MCU STM32F10xxx standard peripheral library
stm32f10x_stdperiph_lib.zip
http://www.st.com/stonline/products/support/micro/files/stm32f10x_stdperiph_lib.zip
二,建立STM32工程
1,解压stm32f10x_stdperiph_lib.zip软件包,把其中的“Libraries”和“Project”文件夹复制到“D:\works\EK-STM3210E-MDK\”,
在“D:\works\EK-STM3210E-MDK\”下建立“Drivers”、“Include”和“Source”空文件夹,在“D:\works\lccd-1.0.0\Project”
下建立“Stm32f103”空文件夹,把“Project\Template”下的C文件复制到“Source”和H文件复制到“Include”;
2,在Keil uVision3菜单中“Project”->“New uVision Project”打开“Create New Project”窗口,选择项目工程存储路径
“D:\works\EK-STM3210E-MDK\Project\Stm32f103”填写项目文件名“stm32.uv2",选择“保存”后自动打开“Select Device for
Target "Target 1"”窗口,在左面“CPU”页面下的“Data base”点开“STMicroelectronics”前面的“+”选择上“STM32F103ZD”
点击“OK”再确定“是”;
3,在Keil uVision3菜单中“Project”->“New Project Workspace”打开“Create New Multi Project Workspace”窗口,选择项目
工作区存储路径“D:\works\EK-STM3210E-MDK\Project\Stm32f103”填写工作区文件名“stm32.mpw",点击“保存”打开
“Create New Multi-Project Workspace”窗口,点击插入项目,然后选择到刚才建立的“stm32.uv2"再点“OK”“确定”
即可建立一个新的 Workspace;
4,在Keil uVision3菜单中“Project”->“Manage”选择“Project "stm32" Components”打开“Components Environment and Books”窗口,
把“Target 1”改为“EK-STM3210E”把“Source Group 1”以为“BOOT”点击“OK”;并在“Groups”下建立“SRC”,“DRV”,“SRC”,
“INC”,“SDRV”等 目录;
5,在Keil uVision3的左面“Workspace”窗口下面的“BOOT”上右击鼠标,选择“Add Files to Group "BOOT"”选择上文件
“D:\works\EK-STM3210E-MDK\Libraries\CMSIS\Core\CM3”文件夹下的“core_cm3.c”和“system_stm32f10x.c”文件,和
D:\works\EK-STM3210E-MDK\Libraries\CMSIS\Core\CM3\startup\arm文件夹下的“startup_stm32f10x_hd.s”后点击“CLOSE”退出;
6,在Keil uVision3的左面“Workspace”窗口下面的“SDRV”上右击鼠标,选择“Add Files to Group "SDRV"”选择上文件
“D:\works\EK-STM3210E-MDK\Libraries\STM32F10x_StdPeriph_Driver\src”文件夹下的所有C文件后点击“CLOSE”退出;
7,在Keil uVision3的左面“Workspace”窗口下面的“SRC”上右击鼠标,选择“Add Files to Group "SRC"”选择上文件
“D:\works\EK-STM3210E-MDK\Source”文件夹下的“main.c”和“stm32f10x_it.c”文件后点击“CLOSE”退出;
8,在Keil uVision3的左面“Workspace”窗口下面的“DRV”上右击鼠标,选择“Add Files to Group "DRV"”选择上文件
“D:\works\EK-STM3210E-MDK\Source”文件夹下的“serial.c”文件后点击“CLOSE”退出;
三,配置STM32工程
在Keil uVision3的左面“Workspace”窗口下面的“EK-STM3210E”右击鼠标,选择“Options for Target "EK-STM3210E"”窗口;
1,在页面“Device”中选择上“STMicroelectronics”下面的STM32F103ZD”,
在页面“TarGet”中选择上“USE microLIB”;
2,在页面“Output”中选择上“Select Folder for Objects...”,在文件夹选择框中指定到路径:
D:\works\EK-STM3210E-MDK\Project\Stm32f103\obj 后点击“OK”;并勾选上Create HEX File,
产生“Debug information”浏览“Browse information”;
3,在页面“Listing”中选择上“Select Folder for Listing...”,在文件夹选择框中指定到路径:
D:\works\EK-STM3210E-MDK\Project\Stm32f103\lst 后点击“OK”;并勾选上C Compiler Listing
和 C Preprocessor Listing (看看自己是否需要);
4,在页面“C/C++”中的“Include Paths ”,中添加:
..\..\Libraries\STM32F10x_StdPeriph_Driver\inc
..\..\Libraries\CMSIS\Core\CM3
..\..\Include
在页面“C/C++”中的“Preprocessor Symbols”,中添加:
USE_STDPERIPH_DRIVER, USE_FULL_ASSERT, STM32F10X_HD,USE_STM3210C_EVAL
5,在页面“ASM”中的“Include Paths ”,中添加:
..\..\Libraries\STM32F10x_StdPeriph_Driver\inc
..\..\Libraries\CMSIS\Core\CM3
..\..\Include
在页面“ASM”中的“Preprocessor Symbols”,中添加:
USE_STDPERIPH_DRIVER, USE_FULL_ASSERT, STM32F10X_HD,USE_STM3210C_EVAL
6,在页面“Debug”中选择右边的硬件仿真功能的“Cortex-M3 J-LINK”,并点开右面的“Settings”配置页面,选择SW接口并把速度改成2M;
在“Flash Download”的编程算法选择上“STM32F10x High-density Flash”;
7,在页面“Utlites”中硬件FLASH编程工具“Cortex-M3 J-LINK”,并点开右面的“Settings”配置页面,选择SW接口并把速度改成2M;
在“Flash Download”的编程算法选择上“STM32F10x High-density Flash”;
四,修改STM32工程
(待续)
附件:
1,serial.c 文件
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include <stdio.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void UART_Configuration(void)
{
/* Enable USART1 clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
/* Configure USART1_Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART1_Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USARTx configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// STM_EVAL_COMInit(COM1, &USART_InitStructure);
/* Configure the USARTx */
USART_Init(USART1, &USART_InitStructure);
/* Enable the USARTx */
USART_Cmd(USART1, ENABLE);
}
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
int fputc(int ch, FILE *f)
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
USART_SendData(USART1, (uint8_t) ch);
/* Loop until the end of transmission */
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
{}
return ch;
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
printf("Wrong parameters value: file %s on line %d\r\n", file, line);
/* Infinite loop */
while (1)
{
}
}
#endif
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
2,main.c文件
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include <stdio.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
extern void UART_Configuration(void);
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
/* Setup STM32 system (clock, PLL and Flash configuration) */
SystemInit();
UART_Configuration();
/* Output a message on Hyperterminal using printf function */
printf("\n\r\n\r\n\r\n\r");
printf("*** STM32-MDK V1.0 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** STM32-MDK V1.0 Rebooting ...\n\r");
/* Add your application code here
*/
/* Infinite loop */
while (1)
{
}
}
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
9G-STM8 CXSTM8使用过程简介
一,准备STVD+CXSTM8+STM8软件包
1,在http://www.st.com/mcu/familiesdocs-120.html
下载ST Visual Develop (STVD) 4.1.3 and ST Visual Programmer (STVP) 3.1.3 版本
sttoolset.exe
http://www.st.com/stonline/products/support/micro/files/sttoolset.exe
2,在http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3229327&bbs_page_no=1&bbs_id=3020
下载CXSTM8 4.2.8 无需License,去除16K限制软件
CXSTM8.rar
http://cache.ourdev.cn/bbs_upload247021/files_12/ourdev_423629.rar
还有补丁
Cosmic.rar
http://cache.ourdev.cn/bbs_upload247021/files_13/ourdev_424179.rar
(试用限制版本http://www.cosmicsoftware.com/cxstm8_16k.exe)
3,在http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3600882&bbs_page_no=7&bbs_id=3020
下载STM8S105S4-PKT演示代码.zip
ourdev_484758.zip
http://cache.ourdev.cn/bbs_upload247021/files_19/ourdev_484758.zip
STM8S105S4-PKT演示代码使用说明.pdf
ourdev_484759.pdf
http://cache.ourdev.cn/bbs_upload247021/files_19/ourdev_484759.pdf
其它相关资源:
如何开始STM8S系列单片机的开发
http://images.stmicroelectronics.com.cn/stonline/mcu/images/STM8S_development.pdf
STM8S体验系统板STM8S105S4-PKT用户手册
http://download.ourdev.cn/bbs_upload247021/files_22/ourdev_506732.pdf
开发板套件见连接:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3723427&bbs_page_no=1&bbs_id=3020
4,其它文档的下载地址如下:
http://www.st.com/mcu/familiesdocs-120.html
http://www.st.com/mcu/modules.php?name=mcu&file=familiesdocs&FAM=113
http://www.stmicroelectronics.com.cn/mcu/inchtml-pages-stm8l.html
http://www.stmicroelectronics.com.cn/mcu/inchtml-pages-stm8s.html
二,建立STVD+CXSTM8开发环境
1,双击sttoolset.exe,默认安装STVD和STVP到C盘的C:\Program Files\STMicroelectronics\st_toolset
将会在桌面产生ST Visual Develop和ST Visual Programmer的快捷方式;
2,解压COSMIC.rar到C盘的C:\Program Files\STMicroelectronics;
3,双击桌面的ST Visual Develop,打开STVD工具,在Tools->Options下的Toolset页面的Toolset中选择
STM8 cosmic,在Root path中选择C:\Program Files\STMicroelectronics\CXSTM8,然后应用,确定;
三,连接开发工具
1,把ST-LINK的SWIM电缆连接在ST-LINK和STM8S105S4-PKT开发板之间,共有4个信号:TVCC,SWIM,GND,RESET;
2,对STM8S105S4-PKT开发板加上9V的直流电源,把ST-LINK用USB线连接到PC的USB口上;
四,测试STM8S105S4-PKT演示工程
1,解压STM8S105S4-PKT演示代码.zip到PC上会得到一个Demo的目录;
2,用STVD工具的File->Open Workspace打开Demo\Touch Sensing\STM8S_EXAMPLE_FW\Project\STVD\Cosmic\example.stw;
3,用STVD工具的Debug instrument->Target Settings中的Debug Instrument Selection中选择Swim ST-LINK,应用,确定;
4,用STVD工具的Build->Rebuild All全部重新编译代码;
5,用STVD工具的Debug->Start Debugging下载代码到目标板上去;
6,然后可以使用单步执行,全速执行等命令,然后每按一次K3,K2,K1,相应的LD2,LD3,LD4就会相应的改变亮灭状态一次;
7,同样可以编译Demo\LED\Demo.stw和Demo\Music\Demo.stw等工程,查看LED流水灯和播放音乐。
五,用STVP+ST-LINK读写STM8
1,同样用ST-LINK的SWIM接口连接开发板和PC机,然后上电;
2,双击ST Visual Programmer打开STVP;
3,在STVP的Project->new 中建立一个新工程STM8S105S4-PKT.stp;
4,然后选择Hardware的ST-LINK,和Device的STM8S105x6确定;
5,用File->Open打开一个十六进制的HEX文件,然后用Program->All Tabs烧录进STM8去;
6,同样也可以用Read->All Tabs,来读出STM8中所有的目标码。
9G-STM32 LwIP测试过程简介
一,准备STM32 LwIP软件包
1,在http://www.st.com/mcu/devicedocs-STM32F107RC-110.html
下载lwIP TCP/IP stack demonstration for STM32F107xx connectivity line microcontrollers软件包
an3102.zip
http://www.st.com/stonline/products/support/micro/files/an3102.zip
2,在http://www.st.com/mcu/devicedocs-STM32F107RC-110.html
下载lwIP TCP/IP stack demonstration for STM32F107xx connectivity line microcontrollers文档
16620.pdf
http://www.st.com/stonline/products/literature/an/16620.pdf
3,有关STM32F107VC-PKT的PCB和SCH和测试代码见下面连接:
http://www.freescaleic.org/yuanxihua/blog/10-01/183297_155bc.html
二,建立STM32 LwIP开发工程
1,把an3102.zip解压到D:\works形成工程文件夹:D:\works\STM32F107_ETH_LwIP_V1.0.0 ;
2,进入到目录D:\works\STM32F107_ETH_LwIP_V1.0.0\Project\EWARMv5,双击Project.eww打开工程;
3,在EWARM中的Project->make 编译通过整个项目。
三,修改STM32 LwIP开发工程
1,打开Project->Options ,在Category中选择Debugger的setup驱动用J-Link/J-Trace,在J-Link/J-Trace
中选择connection的SWD接口;
2,对STM32F107VC-PKT开发板加上5V的直流电源,把J-LINK用USB线连接到PC的USB口上,执行Project->Download and Debug
下载代码到板子后,执行Debug->Go 。
四,修改STM32 LwIP开发源码
1,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Project\src\main.c 的53行后添加如下代码:
/* Output a message on Hyperterminal using printf function */
printf("\n\r\n\r\n\r\n\r");
printf("*** STM32F107VC-PKT V1.0 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** STM32F107VC-PKT V1.0 Rebooting ...\n\r");
2,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Project\src\stm32f107.c 的包含头文件中添加:
#include "stdio.h"
在第30行选择用MII模式:
#define MII_MODE /* MII mode for STM3210C-EVAL Board (MB784) (check jumpers setting) */
//#define RMII_MODE /* RMII mode for STM3210C-EVAL Board (MB784) (check jumpers setting) */
在54行后添加:
USART_InitTypeDef USART_InitStructure;
在125行后添加:
/* Configure the com port */
/* USARTx configuration ------------------------------------------------------*/
/* USARTx configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
STM_EVAL_COMInit(COM1, &USART_InitStructure);
}
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval : None
*/
int fputc(int ch, FILE *f)
{
/* Write a character to the USART */
USART_SendData(USART2, (uint8_t) ch);
/* Loop until the end of transmission */
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
{
}
return ch;
}
/**
* @brief Get a key from the HyperTerminal
* @param None
* @retval : The Key Pressed
*/
int fgetc(FILE *f)
{
/* Waiting for user input */
while ( USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET);
return (uint8_t)USART2->DR;
在341-344行修改为:
/* ADC Channel10 config --------------------------------------------------------*/
/* Relative to STM32F107VC-PKT Board */
/* Configure PC.00 (ADC Channel10) as analog input -------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
在375-376行修改为:
/* ADC1 regular channel10 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);
3,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Project\src\netconf.c 中的119-121行和316-318行把
IP地址都修改如下:
IP4_ADDR(&ipaddr, 192, 168, 1, 8);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 192, 168, 1, 1);
4,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Utilities\lwip-1.3.1\port\lwipopts.h中把
#define LWIP_DHCP 1
修改成:
#define LWIP_DHCP 0
5,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Utilities\STM32_EVAL\STM3210C_EVAL\stm3210c_eval.h中把
#define LED1_GPIO_PIN GPIO_Pin_7
修改成:
#define LED1_GPIO_PIN GPIO_Pin_13
把
#define LED2_GPIO_PIN GPIO_Pin_13
修改成:
#define LED2_GPIO_PIN GPIO_Pin_14
把
#define LED3_GPIO_PIN GPIO_Pin_3
修改成:
#define LED3_GPIO_PIN GPIO_Pin_15
把
#define COMn 1
修改成
#define COMn 2
6,同样执行Project->Download and Debug 下载代码到板子后,执行Debug->Go 可以全速仿真运行。
五,演示STM32 LwIP开发工程
1,用交叉网线连接STM32F107VC-PKT到PC的网口,用交叉串口线连接RS232到PC的串口中,再对板子用5V上电
复位启动工作;
2,可以在串口终端上用115200 8N1的格式看到:
*** STM32F107VC-PKT V1.0 Build by yuanxihua@21cn.com on (Jan 12 2010 - 12:43:08)
*** STM32F107VC-PKT V1.0 Rebooting ...
3,在PC的IE浏览器中输入:http://192.168.1.8/ 回车刷新可以访问到板子,看到Home page主页:
STM32F107 Webserver Demo
Based on the lwIP TCP/IP stack
4,点击Led control从Home page切换LED控制,任意勾上或者去掉LED1-3,再按SEND,可以看到板子的LED相应的
被控制亮或者灭;
5,点击ADC status bar从Led control页面切换到ADC采集,旋转板子上的RV1,可以看到STM32F107 ADC status bar
上绿色的滚动条被ADC的输入电压控制增减;
6,在SecureCRT 5.1终端中可以以telnet协议访问192.168.1.8,端口就是23,连接上了会显示:
Hello. What is your name? ,输入字符串YUANXIHUA,马上会回复Hello YUANXIHUA
9G-LM3S8 MDK-ARM使用过程简介
一,准备MDK-ARM+LM3S8软件包
1,在http://www.mcu123.com/news/Soft/embsof/arm/201001/516.html
下载RealView MDK-ARM 4.03a(MDK-ARM V4.03a,MDK4.03a)
mdk403a_mcu123.rar
ftp://www.mcu123.com/%D2%D1%D5%FB%C0%ED%C4%BF%C2%BC/%BF%AA%B7%A2%B9%A4%BE%DF%C8%ED%BC%FE/ARM/mdk403a_mcu123.rar
(自己查找破解文件)
2,在http://www.luminarymicro.com/products/ekk-lm3s8962_can_ethernet_evaluation_kit.html 上
在Manuals and Schematics中的Quickstart Keil Tools-1.8 (Evaluation Kit Quickstart Keil Tools)
点击download注册下载Quickstart-Eval-Kit-Keil.pdf
在Manuals and Schematics中的EK-LM3S8962-08 (Stellaris LM3S8962 Evaluation Board User's Manual)
点击download注册下载8962_EvalBoard.pdf
在Manuals and Schematics中的RMF-EK-LM3S8962-1.4 (LM3S8962 Evaluation Kit Readme First)
点击download注册下载READMEFirst-LM3S8962-Eval-Kit.pdf
在Software Updates中的EKK-LM3S8962-CD-534 (LM3S8962 Evaluation Kit for Keil CD)
点击download注册下载EKK-LM3S8962-CD-534.zip
在Software Updates中的SW-EK-LM3S8962-5570 (EK-LM3S8962 Firmware Development Package)
点击download注册下载SW-EK-LM3S8962-5570.exe
3,在http://www.luminarymicro.com/products/software_updates.html 上
选择StellarisWare中的SW-EK-LM3S8962-5570 (EK-LM3S8962 Firmware Development Package)
点击download注册下载SW-EK-LM3S8962-5570.exe
选择Utilities中的LMFlashProgrammer-923 (GUI and command line flash programmere)
点击download注册下载LMFlashProgrammer_923.zip
选择Utilities中的Serial Flash Loader-00 (Serial Flash Loader)
点击download下载Serial Flash Loader.zip
选择Utilities中的LMIDK-AGDI-33 (Keil debug interface DLL for Stellaris ICDI)
点击download注册下载lmidk-agdi-b33.zip
选择Misc中的Stellaris FTDI Driver-2.06.00 (Stellaris FTDI driver)
点击download下载Stellaris_FTDI-2_06_00.zip
4,其它软件文档的下载地址如下:
http://www.luminarymicro.com/products/software_updates.html
二,建立MDK+LM3S8开发环境
1,双击MDK403a.exe自行安装MDK-ARM 4.03a,
将会在桌面产生Keil uVision4的快捷方式;
2,双击SW-EK-LM3S8962-5570.exe将软件安装到C盘的c:\StellarisWare;
3,双击LMFlashProgrammer_923.zip,运行里面的LMFlashProgrammer.msi安装FlashProgrammer到默认C盘,
将会在电脑桌面生成LM Flash Programmer的快捷方式;
三,连接开发工具
1,把EK-LM3S8962开发板用USB电缆连接到电脑上,将会发现找到新硬件Stellaris Development Board;
2,手动安装驱动程序时指向Stellaris_FTDI-2_06_00.zip的解压后的文件夹,安装Stellaris Development Board驱动;
3,再次出现新硬件Stellaris Virtual COM Port时,再指向刚才的目录即可安装相关驱动。
四,测试SW-EK-LM3S8962-5570.exe演示工程
1,用MDK打开C:\StellarisWare\boards\ek-lm3s8962\ek-lm3s8962.mpw工程;
2,在MDK的Project工程窗口的graphics上右击Set as Active Project;
3,在MDK工程窗口菜单中选择Flash->Download命令编译下载目标码;
4,复位LM3S8962的开发板,也可以编译下载后用Debug->Start命令启动调试后全速运行;
5,便可在LM3S8962的开发板的OLED上看到luminarymicro的LOGO;
6,也可以选择激活Project工程窗口其它它工程来运行;
7,如qs_ek-lm3s8962就是显示了TI和KEIL的LOGO后一个小迷宫游戏。
五,用LM Flash Programmer读写LM3S8962
1,同样用USB电缆连接开发板和PC机;
2,双击桌面LM Flash Programmer打开Programmer;
3,在Configureation的Quick Set中选择LM3S8962...;
4,然后在Flash Utilities的Upload...中指定一个BIN文件;
5,选择整块FLASH然后Upload便可以读出LM3S8962中的目标码;
6,同样也可以把目标码写入LM3S8962。
9G-LM3S8 EWARM使用过程简介
一,准备EWARM+LM3S8软件包
1,在http://www.mcu123.com/news/Soft/embsof/arm/201001/514.html
下载IAR Embedded Workbench for ARM version 5.41 (2010.1.5更新)
CD-EWARM-5411-1760_mcu123.zip
http://esoft.mcu123.com/MCU123_temp_20100103@/ARM/CD-EWARM-5411-1760_mcu123.zip
(自己查找破解文件)
2,在http://www.luminarymicro.com/products/eki-lm3s8962_can_ethernet_evaluation_kit.html
在Manuals and Schematics中的Quickstart IAR Tools-1.7 (Evaluation Kit Quickstart IAR Tools)
点击download注册下载Quickstart-Eval-Kit-IAR.pdf
在Manuals and Schematics中的EK-LM3S8962-08 (Stellaris LM3S8962 Evaluation Board User's Manual)
点击download注册下载8962_EvalBoard.pdf
在Manuals and Schematics中的RMF-EK-LM3S8962-1.4 (LM3S8962 Evaluation Kit Readme First)
点击download注册下载READMEFirst-LM3S8962-Eval-Kit.pdf
在Software Updates中的EKI-LM3S8962-CD-534 (LM3S8962 Evaluation Kit for IAR CD)
点击download注册下载EKI-LM3S8962-CD-534.zip
在Software Updates中的SW-EK-LM3S8962-5570 (EK-LM3S8962 Firmware Development Package)
点击download注册下载SW-EK-LM3S8962-5570.exe
3,在http://www.luminarymicro.com/products/software_updates.html 上
选择StellarisWare中的SW-EK-LM3S8962-5570 (EK-LM3S8962 Firmware Development Package)
点击download注册下载SW-EK-LM3S8962-5570.exe
选择Utilities中的LMFlashProgrammer-923 (GUI and command line flash programmere)
点击download注册下载LMFlashProgrammer_923.zip
选择Utilities中的Serial Flash Loader-00 (Serial Flash Loader)
点击download下载Serial Flash Loader.zip
选择Utilities中的LMIDK-AGDI-33 (Keil debug interface DLL for Stellaris ICDI)
点击download注册下载lmidk-agdi-b33.zip
选择Misc中的Stellaris FTDI Driver-2.06.00 (Stellaris FTDI driver)
点击download下载Stellaris_FTDI-2_06_00.zip
4,其它文档的下载地址如下:
http://www.luminarymicro.com/products/software_updates.html
二,建立EWARM+LM3S8开发环境
1,双击CD-EWARM-5411-1760.zip,运行里面的autorun.exe默认安装IAR EWARM到C盘,
将会在电脑启动菜单中产生IAR Embedded Workbench的快捷方式;
2,双击SW-EK-LM3S8962-5570.exe将软件安装到C盘的c:\StellarisWare;
3,双击LMFlashProgrammer_923.zip,运行里面的LMFlashProgrammer.msi安装FlashProgrammer到默认C盘,
将会在电脑桌面生成LM Flash Programmer的快捷方式;
三,连接开发工具
1,把EK-LM3S8962开发板用USB电缆连接到电脑上,将会发现找到新硬件Stellaris Development Board;
2,手动安装驱动程序时指向Stellaris_FTDI-2_06_00.zip的解压后的文件夹,安装Stellaris Development Board驱动;
3,再次出现新硬件Stellaris Virtual COM Port时,再指向刚才的目录即可安装相关驱动。
四,测试SW-EK-LM3S8962-5570.exe演示工程
1,双击C:\StellarisWare\boards\ek-lm3s8962\ek-lm3s8962.eww用EWARM打开工程;
2,在EWARM工程窗口的Workspace中选择graphics-Debug;
3,在EWARM工程窗口菜单中选择Project->Download and Debug命令;
4,在EWARM的高度窗口中选择Debug->Go全速运行;
5,便可在LM3S8962的开发板的OLED上看到luminarymicro的LOGO;
6,也可以选择Workspace中选择其它工程来运行;
7,如qs_ek-lm3s8962-Debug就是显示了TI和IAR的LOGO后一个小迷宫游戏。
五,用LM Flash Programmer读写LM3S8962
1,同样用USB电缆连接开发板和PC机;
2,双击桌面LM Flash Programmer打开Programmer;
3,在Configureation的Quick Set中选择LM3S8962...;
4,然后在Flash Utilities的Upload...中指定一个BIN文件;
5,选择整块FLASH然后Upload便可以读出LM3S8962中的目标码;
6,同样也可以把目标码写入LM3S8962。
U-BOOT移植过程流水账
1,修改MAKEFILE
增加开发板编译定义
at91sam9260ek_config : unconfig
@./mkconfig $(@:_config=) arm arm926ejs at91sam9260ek NULL at91sam926x
指定编译器
ifeq ($(ARCH),arm)
CROSS_COMPILE = /usr/local/arm/eldk-4.1/usr/bin/arm-linux-
2,修改MAKEALL
增加ARM9开发板支持列表
LIST_ARM9=" \
at91rm9200dk cmc_pu2 \
at91sam9260ek at91sam9261ek at91sam9263ek \
3,\include\asm-arm\mach-types.h的修改
增加CPU型号定义
#define MACH_TYPE_AT91SAM9261EK 848
#define MACH_TYPE_PDNB3 1002
#define MACH_TYPE_AT91SAM9260EK 1099
#define MACH_TYPE_AT91SAM9263EK 1202
4,include\configs\at91sam9260ek.h
增加开发板定义头文件
at91sam9260ek.h
5,include\asm-arm\arch-at91sam926x\at91sam9260.h
增加CPU的寄存器定义头文件
at91sam9260.h
6,examples\Makefile
修改如此类
ELF = hello_world
编译错误
7,board\at91sam9260ek\
增加开发板定义文件夹
at91sam9260ek.c config.mk dm9161a.c Makefile nand.c u-boot.lds
8,cpu\arm926ejs\at91sam926x\
增加CPU核的支持文件夹
config.mk ether.c interrupts.c lcd.c lcd_lut.h Makefile serial.c spi.c usb_ohci.c usb_ohci.h
启动过程
1,\cpu\arm926ejs\start.S
A,在\board\at91sam9260ek\u-boot.lds 中定义程序入口标志为 ENTRY(_start) TEXT段首文件: cpu/arm926ejs/start.o (.text)
B,在\board\at91sam9260ek\config.mk 中定义程度执行地址为 TEXT_BASE = 0x23f00000
C, _start -> cpu_init_crit -> relocate -> stack_setup -> clear_bss -> start_armboot 先初始化系统,然后进入主循环
D,中断处理
2,\lib_arm\board.c
start_armboot() 先初始化系统,然后进入主循环
A, *init_sequence[] 初始化列表
cpu_init 在 \cpu\arm926ejs\cpu.c
board_init 在 \board\at91sam9260ek\at91sam9260ek.c
interrupt_init 在\cpu\arm926ejs\at91sam926x\interrupts.c
env_init 在\common\env_dataflash.c 或者 \common\env_nand.c
(include\configs\at91sam9260ek.h 中CFG_ENV_IS_IN_DATAFLASH CFG_ENV_IS_IN_NAND 决定)
init_baudrate 在\lib_arm\board.c
serial_init 在\cpu\arm926ejs\at91sam926x\serial.c
console_init_f 在\common\console.c
display_banner 在\lib_arm\board.c
print_cpuinfo 在\cpu\arm926ejs\cpuinfo.c
checkboard 不启用
dram_init 在 \board\at91sam9260ek\at91sam9260ek.c
display_dram_config 在\lib_arm\board.c
B,外设初始化配置
flash_init NORFLASH初始化
display_flash_config NORFLASH信息显示
(include\configs\at91sam9260ek.h 中CFG_NO_FLASH 决定不用)
LCD VFD都不用 include\configs\at91sam9260ek.h 中CONFIG_VFD CONFIG_LCD 定义不用
mem_malloc_init 初始化malloc空间 在\lib_arm\board.c
nand_init 在\drivers\nand\nand.c
AT91F_DataflashInit 在\drivers\dataflash.c
dataflash_print_info 在\drivers\dataflash.c
env_relocate 在\common\env_common.c
getenv_IPaddr 在\net\net.c
getenv 在\common\cmd_nvedit.c
devices_init 在\common\devices.c
jumptable_init 在\common\exports.c
console_init_r 在\common\console.c
enable_interrupts 在\cpu\arm926ejs\interrupts.c
board_late_init 在\board\at91sam9260ek\at91sam9260ek.c
eth_initialize 在\net\eth.c
C,进入主循环
main_loop 在\common\main.c
3,\common\main.c
A,启动禁用 CONFIG_BOOTCOUNT_LIMIT,CONFIG_MODEM_SUPPORT,VFD_TEST_LOGO,CONFIG_VERSION_VARIABLE,CFG_HUSH_PARSER,
CONFIG_PREBOOT,CONFIG_AUTOBOOT_KEYED,CONFIG_BOOT_RETRY_TIME,CONFIG_MENUKEY,CONFIG_AMIGAONEG3SE,CONFIG_AMIGAONEG3SE
include\configs\at91sam9260ek.h 中没有定义
B,判断自启动延时
abortboot 在\common\main.c
parse_string_outer 在\common\hush.c
C,命令终端for (;;)
禁用 CONFIG_RESET_TO_RETRY CONFIG_AUTO_COMPLETE
在include\configs\at91sam9260ek.h 中没有定义
readline 在\common\main.c
run_command 在\common\main.c
添加过程
1,修改MAKEFILE
在\common\Makefile的 COBJS =
后面目标码协列表中添加新的目标码 cmd_xmodem.o xmodem.o
2,增加源文件
在\common\中增加源文件
xmodem.c cmd_xmodem.c
3,增加头文件
在\include\中增加头文件
xmodem.h
4,添加命令过程
A,核心处理函数
int do_xmodem(cmd_tbl_t *cmdtp,int flag,int argc, char *argv[])
B,命令定义模板
U_BOOT_CMD(
rx, 3, 0, do_xmodem,
"rx - load binary file over serial line (xmodem)\n",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'\n"
);
C,命令模板定义
命令结构体
typedef struct cmd_tbl_s cmd_tbl_t
命令模板宏
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
在 \include\command.h
D,XMODEM协议核心
int xmodem_rx(char *dest)
9G-CM0 新唐CM0+MDK-ARM入门开发过程简介
一,准备MDK-ARM + 新唐CM0软件包
1,在http://www.mcu123.com/news/Soft/embsof/arm/201006/529.html
下载RealView MDK-ARM 4.12 (MDK-ARM V4.12,MDK4.12)
mdk412_mcu123.rar
在http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=3&SoftID=529上
右击“下载地址:”后的“下载”选择“目标另存为”下载文件到本地硬盘。
(自己查找破解文件“keygen.exe”)
http://esoft.mcu123.com/MCU123_temp_20100103@/arm/mdk412_mcu123.rar
2,在http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=403a9c50-52c2-4463-9057-2595190602c5 上
上下载 “NUC1xx Keil ICE driver (Build 3814) V1.01.zip”
NUC1xxKeilICEdriverBuild3814V101.zip
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxKeilICEdriverBuild3814V101.zip
下载“NUC1xx Nu-Tiny-EVB and Nu-Link-Me Board user manual EN v1.0.pdf”文档
NUC1xxNuTinyEVBandNuLinkMeBoardusermanualENv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuTinyEVBandNuLinkMeBoardusermanualENv10.pdf
下载“NUC1xx Nu-Link-Me_001 Board Schematic v1.0.pdf”文档
NUC1xxNuLinkMe_001BoardSchematicv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuLinkMe_001BoardSchematicv10.pdf
下载“NUC1xx Nu-Tiny-EVB_001 Board Schemetic v1.0.pdf”文档
NUC1xxNuTinyEVB_001BoardSchemeticv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuTinyEVB_001BoardSchemeticv10.pdf
3,在http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=7052964b-b71b-46b7-91b2-221afeddd575上
上下载 “NUC1xxBSP_v1.1.1.zip”
NUC1xxBSP_v111.zip
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=38a57efd-e9f8-4809-a585-21e62f8b6041
4,新唐官方资料网址
新唐CM0官方资料主页
http://www.nuvoton.com/hq/chs/Pages/default.aspx
新唐CM0主页资料入口
ARM单片机 -> ARM Cortex?-M0 单片机 NuMicro? 家族
新唐CM0主页资料网址
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=30cfcae5-0f93-414d-a8df-b3bac8b932a2
新唐CM0在线选型工具
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Pages/SelectGuide.aspx
新唐CM0在线培训教程
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Pages/OnLineTraining.aspx
二,建立CM0的MDK-ARM+Nu-LINK开发环境
1,双击“mdk412_mcu123.rar”运行里面的“MDK412.exe”,一路的“NEXT”再“NEXT”,最后就会安装MDK-ARM 4.12到电脑上,将会在桌面产生Keil uVision4的快捷方式;
2,双击“keygen.exe”,把“uVision4”的“File->License Management”菜单里面的“CID”复制到keygen里面的CID框中,选择“TARGET”为“ARM”后点击“Generate”,把
产生的序列号复制到前面“uVision4”的窗口中的“LIC”框中,点击“ADD LIC”便会解除编译限制;
3,双击“NUC1xxKeilICEdriverBuild3814V101.zip ”运行里面的“Nu-Link_Driver.EXE”,便会在KEIL目录中安装上相关的“Nu-LINK”的驱动。
三,建立CM0的MDK-ARM基本工程
1,在电脑开始菜单中打开“Keil uVision4”,在“uVision4”的IDE菜单中选择“Project”->“New uVision Project”创建一个新工程,在“Create New Project”选择存储目录
到D:\works\9G-CM0\nuc140\project下面,工程名叫“nuc140.uvproj”;
2,接着在“select a CPU Data Base File”菜单中选择“NUVOTON NUC1XX Devices”点击“OK”,选择“Nuvoton”公司下面的“NUC140VE3AN”点击“OK”后确认复制启动代码“startup_NUC1xx.s”和
加入到工程项目中,即可产生一个空工程,再点击全部保存项目,会D:\works\9G-CM0\nuc140\project目录中发现“nuc140.uvproj”和“nuc140.uvopt”,“startup_NUC1xx.s”等文件;
3,在“D:\works\9G-CM0\nuc140”下建立文件夹“include”,“driver”,“library”,“source”,等子目录,解压“NUC1xxBSP_v111.zip”,把里面的目录“NUC1xxBSP”解压到“library”里面,在D:\works\9G-CM0\nuc140\project
下建立子目录“obj”和“lst”;
4,在“uVision4”的IDE菜单中选择“Project”->“Manage”->“Components,Environment,Books”打开“Components,Environment,Books”页面里的“Project Components”,
双击“Target1”改名为“NUC140”,双击“Source Group 1”改名为“boot”再添加“lib”“drv”“src”“inc”等目录后确定。
5,在“uVision4”的IDE菜单中选择“File”->“New”后选择“File”->“Save”把新建立的文件保存到D:\works\9G-CM0\nuc140\source,文件名为“main.c”,右击项目窗口中的“src”选择“Add Files
to Group 'src'”并在“main.c”中填入下面内容:
#include <NUC1xx.H> /* NUC1xx definitions */
void SystemInit(void){}
void GPIO_Init(void){ NUC_GPIOC->PMD = 0x00005555;} /* LEDs on PORT C defined as Output */
int main(void)
{
int i;
GPIO_Init();
while(1)
{
for(i=0;i<1000000;i++); NUC_GPIOC->DOUT &= 0xFFFFFF00; /* switch on LEDs */
for(i=0;i<1000000;i++); NUC_GPIOC->DOUT |= 0x000000FF; /* switch off LEDs */
}
}
三,配置CM0的MDK-ARM基本工程
1,在“uVision4”的IDE菜单中选择“Project”->“Opitions for Target ‘NUC140’”,在“Output”页面勾选“Create HEX File”,并在“Select Folder Objects”指定目录到“D:\works\9G-CM0\nuc140\project\obj”,
后点击“OK”,同样在“Listing”中在“Select Folder Listings”指定目录到“D:\works\9G-CM0\nuc140\project\lst”;
2,在“Opitions for Target ‘NUC140’”的“Debug”页面选择用硬件仿真器“Nu-Link Debugger”勾选“Run to main{}”,在“Utilities”页面选择“Use Target Driver for Flash Programming”用
“Nu-Link Debugger”勾选上“Update Target before Debugging”后在“Setting”里面的“Configure”,确保用内置22M晶体,和从“APROM”启动及低压检测电压值等配置选项后点击“OK”再“OK”退出;
3,在“Opitions for Target ‘NUC140’”的“C/C++”页面的“Include Paths”中填入“C:\Keil\ARM\INC\Nuvoton\NUC1xx”
四,调试CM0的MDK-ARM基本工程
1,点击在“uVision4”的IDE菜单中选择“Flash”->“Download”便会自己编译代码生成HEX文件并下载到目标板子中;
2,点击在“uVision4”的IDE菜单中选择“Debug”->“Start/Stop Debug session”进入调试状态,然后选择“Debug”->“Run”,全速运行,可以看到IO口上的LED在闪烁。
四,建立CM0的MDK-ARM高级工程
(待续)
9G-CM0 新唐CM0+EWARM入门开发过程简介
一,准备EWARM + 新唐CM0软件包
1,在http://www.mcu123.net/bbs/viewthread.php?tid=16064&highlight=CD-EWARM-5501-1908 上
下载 IAR Embedded Workbench for ARM version 5.50 软件
CD-EWARM-5501-1908_mcu123.zip
ftp://mcu123:mcu123@mcu123.com/已整理目录/开发工具软件/ARM/CD-EWARM-5501-1908_mcu123.zip
相关文件“IAR_EWARM5.4和谐文件.rar ”可以在GOOGLE上搜索到
http://bbs.mcu123.net/bbs/thread-15164-1-1.html
并下载:
IAR_EWARM5[1].4和谐文件.rar
2,在http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=403a9c50-52c2-4463-9057-2595190602c5 上
下载 “NuMicro IAR Embedded Workbench? driver (Build 4033) V1.02.zip”
NuMicro IAR Embedded Workbench driver (Build 4033) V1.02.zip
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NuMicro%20IAR%20Embedded%20Workbench%20driver%20%20(Build%204033)%20V1.02.zip
下载“NUC1xx Nu-Tiny-EVB_001 Board Schemetic v1.0.pdf”文档
NUC1xxNuTinyEVB_001BoardSchemeticv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuTinyEVB_001BoardSchemeticv10.pdf
下载“NUC1xx Nu-Tiny-EVB and Nu-Link-Me Board user manual EN v1.0.pdf”文档
NUC1xxNuTinyEVBandNuLinkMeBoardusermanualENv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuTinyEVBandNuLinkMeBoardusermanualENv10.pdf
下载“NUC1xx Nu-Link-Me_001 Board Schematic v1.0.pdf”文档
NUC1xxNuLinkMe_001BoardSchematicv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuLinkMe_001BoardSchematicv10.pdf
3,在http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=7052964b-b71b-46b7-91b2-221afeddd575上
上下载 “NUC1xxBSP_v1.1.2.zip”
NUC1xxBSP_v1.1.2.zip
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxBSP_v1.1.2.zip
4,新唐官方资料网址
新唐CM0官方资料主页
http://www.nuvoton.com/hq/chs/Pages/default.aspx
新唐CM0主页资料入口
ARM单片机 -> ARM Cortex?-M0 单片机 NuMicro? 家族
新唐CM0主页资料网址
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=5cc43799-121d-42c9-9ac0-3b4a6cbdb7c3
新唐CM0在线选型工具
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Pages/SelectGuide.aspx
新唐CM0在线培训教程
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Pages/onlineEtraining.aspx
5,在http://www.segger.com/cms/jlink-software.html 上
下载Software and documentation pack V4.14g软件
Setup_JLinkARM_V414g.zip
http://www.segger.com/cms/admin/uploads/userfiles/file/J-Link/Setup_JLinkARM_V414g.zip
二,建立CM0的EWARM+Nu-LINK开发环境
1,双击“IAR_EWARM5[1].4和谐文件.rar”,运行里面的“EWARM_FULL_ARM540.exe”,选择“Product”中的“Embedded Workbench For ARM v5.40”,然后点击“Generate”
把产生的“License key”“License number”密码和序列号记录下来;
2,双击“CD-EWARM-5501-1908_mcu123.zip”运行里面的“autorun.exe”,在“Welcome to IAR Systems”中选择“Install IAR Embedded Workbench”,按常规的软件安装方式
把“IAR Embedded Workbench For ARM”安装到电脑上;
3,双击“NuMicro IAR Embedded Workbench driver (Build 4033) V1.02.zip”运行里面的“Nu-Link_IAR_Driver 1.02.exe”,便会在“C:\Program Files\Nuvoton Tools\Nu-Link_IAR”
目录中安装上相关的“Nu-LINK”的驱动。
4,双击“Setup_JLinkARM_V414g.zip”运行里面的“Setup_JLinkARM_V414g.exe”,便会在“C:\Program Files\SEGGER\JLinkARM_V414g”
目录中安装上相关的“J-LINK”的驱动。
三,建立CM0的EWARM基本工程
1,在电脑开始菜单中打开“IAR Embedded Workbench IDE”,在“EWARM”的IDE菜单中选择“Project”->“Create New Project”创建一个新工程,在“Create New Project”选择“OK”存储目录
到D:\works\9G-CM0\nuc140\project\iar下面,工程名叫“nuc140.ewp”,点击“OK”完成,点击“File”下的“Save Workspace”保存工作空间到目录中的“nuc140.eww”;
2,在“D:\works\9G-CM0\nuc140”下建立文件夹“include”,“driver”,“library”,“source”,等子目录,在“D:\works\9G-CM0\nuc140\project\iar下建立子目录“config”,并把
“NUC1xxBSP_v1.1.2.zip”解压到“D:\works\9G-CM0\nuc140\library”目录;
3,在“EWARM”的IDE菜单中选择“Project”->“Options”中的“General Options”的“Target”中的“Device”中选择“Nuvoton NUC140xE”,在“Linker”菜单中选择“Linker configuration file”里选择
“override default”并填上“$PROJ_DIR$\config\NUC140_Flash.icf”;
4,在“Options for node 'nuc140'”的“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“Third-Party Driver”,然后在“Third-Party Driver”选择驱动到
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll”;
5,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\FlashNUC1xxxE.board”,把
“D:\works\9G-CM0\nuc140\library\NUC1xxBSP\NuvotonPlatform_IAR\Sample\Driver\Smpl_DrvGPIO”下的“Smpl_DrvGPIO.icf”复制到“D:\works\9G-CM0\nuc140\project\iar\config”
并改名为“NUC140_Flash.icf”;
6,在“IAR Embedded Workbench IDE”的“Workspace”下的“Files”中右击选择“Add”->“Add Group”并填入“BOOT”,另外同样建立“DRV”,“SRC”,“INC”“LIB”等目录,然后在“BOOT”上右击
选择“Add”->“Add Files” 然后选择“D:\works\9G-CM0\nuc140\library\NUC1xxBSP\CMSIS\CM0\startup\iar”下的“ startup_NUCxxx_iar.s”;
7,在“D:\works\9G-CM0\nuc140\source”中建立“main.c”,然后添加到工程的“SRC”中,并在“main.c”中填入下面内容:
#include <Nuvoton\ionuc140.h>
void SystemInit(void){}
void GPIO_Init(void){ GPIOC_PMD = 0x55555555;GPIOA_PMD = 0x55555555;} /* LEDs on PORT C defined as Output */
int main(void)
{
int i;
GPIO_Init();
while(1)
{
for(i=0;i<3000000;i++);
GPIOC_DOUT &= 0x00000000; /* switch on LEDs */
GPIOA_DOUT &= 0x00000000;
for(i=0;i<3000000;i++);
GPIOC_DOUT |= 0xFFFFFFFF; /* switch off LEDs */
GPIOA_DOUT |= 0xFFFFFFFF;
}
}
8,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\LDROMNUC1xx.board”,可以把
相应的程序烧进LDROM区;
9,在“EWARM”的IDE菜单中选择“Nu-Link”->“ICP Programming Tool”中,可以不擦除整片FLASH改变配置位从APPROM区切换到LDROM区,
FLASH的1能修改成0;
四,调试CM0的EWARM基本工程
1,在“EWARM”的IDE菜单中选择“Project”->“Options”中“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“J-Link/J-Trace”;
2,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\LDROMNUC1xx.board”,可以把
相应的程序烧进LDROM区;
(待续)
基于IAR EWARM开发新唐M0的CONFIG修改及NU-LINK驱动
1,把下面的内容保存成文件“nuc1xx_APROM.board”:
<?xml version="1.0" encoding="iso-8859-1"?>
<flash_board>
<pass>
<loader>$TOOLKIT_DIR$\config\flashloader\Nuvoton\FlashNUC1xxxE.flash</loader>
<args>--config</args>
</pass>
</flash_board>
2,把下面的内容保存成文件“nuc1xx_LDROM.board”:
<?xml version="1.0" encoding="iso-8859-1"?>
<flash_board>
<pass>
<loader>$TOOLKIT_DIR$\config\flashloader\Nuvoton\LDROMNUC1xx.flash</loader>
<abs_offset>0x100000</abs_offset>
<args>--config
0xFFFFFF7F
0x0001F800</args>
</pass>
</flash_board>
注:其中参数: <args>--config
0xFFFFFF7F
0x0001F800</args>
就是新唐M0的配置区的CONFIG0,1 的值,严格根据你的需要的配置去修改。
3,然后在IAR EWARM的项目工程的Options->Debugger->Dwnload里勾选上Use flash loader及Override default .boadr file。
然后下面填上路径:
$PROJ_DIR$\nuc1xx_LDROM.board
或者
$PROJ_DIR$\nuc1xx_APROM.board
4,双击NuMicro IAR Embedded Workbench driver (Build 4228) V1.03.ZIP把
NU-LINK的驱动默认安装到电脑上,然后IAR EWARM的项目工程的Options->Debugger的驱动
驱动用Third-Party Driver的,再指定到NU-LINK的DLL路径:
C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll
5,新唐M0的ISP的要点:
1,CPU的LDROM中要烧有ISP_LD_NUC100series.bin(针对NUC1XX)或者ISP_LD_M051series.bin(针对M05X);
2,CPU的CONFIG0要配置从LDROM启动,甚至要配置外部12M晶体(用USB下载做ISP);
3,CPU的UART0或者USB(NUC120,140)上要有线正确连接到PC上;
4,CPU的上电复位时,NUC1XX是INT1(PB15)或者M05X是INT0(P3.2)要接地,否则跳进APROM;
5,CPU进入了ISP后再用NuMicro ISP Writer V1.10.exe去连接CPU(选择对的COM口或者USB口)
6,CPU的ISP连接后不能操作LDROM,但可以在重新复位前多次操作APROM和CONFIG和DATAFLASH;
7,CPU的ISP软件PC端NuMicro ISP Writer V1.10.exe的同一目录要有config.ini文件。
启动新唐M0的semihost半主机调试:
利用NUC100SERIESBSP_CMSIS_V1.03.002建立的工程。
1,针对startup_NUC1xx.s文件的修改
A,第010行改为:SEMIHOSTED SETL {TRUE} ;SEMIHOSTED SETL {FALSE}
B,第256行改为:;yuanxihua@21cn.com ENTRY
2,针对 retarget.c文件的修改
A,第021行改为:#define DEBUG_ENABLE_SEMIHOST /* To enable semihosted. !!!The SEMIHOSTED of startup_NUC1xx.s must be {TRUE} */
3,在MDK的NU-LINK的Debug模式中,打开View->Serial Windows-> UART #1即可利用如下调试信息:
printf("*** 9G-NUC122 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** 9G-NUC122 V1.00 Rebooting ...\n\r\n\r");
打印到上面的虚拟串口。
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0203ic/Bgbjjgij.html
8.1.1. 什么是半主机?
半主机是用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。 例如,使用此机制可以启用 C 库中的函数,如
printf()
和
scanf()
,来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。
这种机制很有用,因为开发时使用的硬件通常没有最终系统的所有输入和输出设备。 半主机可让主机来提供这些设备。
半主机是通过一组定义好的软件指令(如 SVC)来实现的,这些指令通过程序控制生成异常。 应用程序调用相应的半主机调用,然后调试代理处理该异常。 调试代理提供与主机之间的必需通信。
半主机接口对 ARM 公司提供的所有调试代理都是通用的。 在无需移植的情况下使用 RealView ARMulator? ISS、指令集系统模型 (ISSM)、实时系统模型 (RTSM)、RealView ICE 或 RealMonitor 时,会执行半主机操作,请参阅Figure 8.1。
在很多情况下,半主机由库函数内的代码调用。 应用程序还可以直接调用半主机操作。 有关 ARM C 库中的半主机支持的详细信息,请参阅《库和浮点支持指南》中的第 2 章 C 和 C++ 库。
9G-NUC140 新唐CM0+EWARM入门开发过程简介
一,准备EWARM + 新唐CM0软件包
1,在http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=1&SoftID=535 上
下载 IAR Embedded Workbench for ARM v6.20 FULL CD-EWARM-6201-2590 软件
CD-EWARM-6201-2590_mcu123.zip
ftp://mcu123:mcu123@mcu123.com/已整理目录/开发工具软件/ARM/CD-EWARM-6201-2590_mcu123.zip
相关文件“IAR_EWARM5.4和谐文件.rar ”可以在GOOGLE上搜索到
http://bbs.mcu123.net/bbs/thread-15164-1-1.html
并下载:
IAR_EWARM5[1].4和谐文件.rar
2,在http://www.nuvoton-m0.com/forum.php?mod=viewthread&tid=1&extra=page%3D1上
下载Nu-Link驱动“公测版驱动下载 v1.17.5218,支持最新的IAR 6.21”
Nu-Link_IAR_Driver 1.17.5218.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=MTg3fDI4NGFkNTk1fDEzMTUyOTkyOTF8MA%3D%3D
下载ICP编程工具“NuMicro ICP Programming Tool 1.17.5218”
NuMicro ICP Programming Tool 1.17.5218.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=MTg2fDI3YTFmZmJlfDEzMTUyOTkyOTF8MA%3D%3D
下载ISP编程工具“NuMicro ISP Programming Tool v1.41”
NuMicro ISP Programming Tool V1.41.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NDh8OTBkZjBjYTJ8MTMxNTI5OTI5MXww
下载NUC100系列基础程序库“NUC100Series BSP_CMSIS V1.05.001.7z”
NUC100SeriesBSP_v1.05.001.7z
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NTR8YWY2YWI1Njd8MTMxNTMwMDA0OHww
3,在“http://dzstic.com/down.asp”上下载“NuTiny-SDK-NUC140.rar”文档
NuTiny-SDK-NUC140.rar
http://dzstic.com/upload/20110906/20110906162939454.rar
4,新唐官方资料网址
新唐CM0官方资料主页
http://www.nuvoton.com/hq/chs/Pages/default.aspx
二,建立CM0的EWARM+Nu-LINK开发环境
1,双击“IAR_EWARM5[1].4和谐文件.rar”,运行里面的“EWARM_FULL_ARM540.exe”,选择“Product”中的“Embedded Workbench For ARM v5.40”,然后点击“Generate”
把产生的“License key”“License number”密码和序列号记录下来;
2,双击“CD-EWARM-6201-2590_mcu123.zip”运行里面的“autorun.exe”,在“IAR Embedded Workbench For ARM”中选择“Install IAR Embedded Workbench”,按常规的软件安装方式
把“IAR Embedded Workbench For ARM”安装到电脑上;
3,双击“Nu-Link_IAR_Driver 1.17.5218.zip”运行里面的“Nu-Link_IAR_Driver 1.17.5218.exe”,便会在“C:\Program Files\Nuvoton Tools\Nu-Link_IAR”和“C:\Program Files
\IAR Systems\Embedded Workbench 6.0” 目录中安装上相关的“Nu-LINK”的驱动。
4,双击“NuMicro ICP Programming Tool 1.17.5218.zip”运行里面的“NuMicro ICP Programming Tool 1.17.5218.exe”,便会在“C:\Program Files\Nuvoton Tools\ICPTool”
目录中安装上相关的“ ICP Programming Tool”的工具。
三,建立CM0的EWARM基本工程
1,在电脑开始菜单中打开“IAR Embedded Workbench IDE”,在“EWARM”的IDE菜单中选择“Project”->“Create New Project”创建一个新工程,在“Create New Project”选择“OK”存储目录
到“D:\works\9G-CM0\9G-NUC140\prj”下面,工程名叫“nuc140.ewp”,点击“OK”完成,点击“File”下的“Save Workspace”保存工作空间到目录中的“nuc140.eww”;
2,在“D:\works\9G-CM0\nuc140”下建立文件夹“bsp”“drv”“inc”“src”,等子目录,在“D:\works\9G-CM0\9G-NUC140\prj”下建立子目录“config”,并把 “NUC100SeriesBSP_v1.05.001.7z”
的“NUC100SeriesBSP\NuvotonPlatform_IAR\Src\Driver”和“NUC100SeriesBSP\NuvotonPlatform_IAR\Include\Driver”解压到“D:\works\9G-CM0\9G-NUC140\bsp\Driver”目录,把“NUC100SeriesBSP\
NuvotonPlatform_IAR\Include\System”解压到“D:\works\9G-CM0\9G-NUC140\bsp\System”目录,把“NUC100SeriesBSP\CMSIS\CM0\DeviceSupport\Nuvoton\NUC1xx\startup\iar\startup_NUC1xx.s”解压到
“D:\works\9G-CM0\9G-NUC140\bsp\Boot”,把“NUC100SeriesBSP\CMSIS\CM0\DeviceSupport\Nuvoton\NUC1xx”下的H和C文件及“NUC100SeriesBSP\CMSIS\CM0\CoreSupport”下的H和C文件解压到
“D:\works\9G-CM0\9G-NUC140\bsp\Cmsis”;
3,在“EWARM”的IDE菜单中选择“Project”->“Options”中的“General Options”的“Target”中的“Device”中选择“Nuvoton NUC140xE”,在“Linker”菜单中选择“Linker configuration file”里选择
“override default”并填上“$PROJ_DIR$\config\NUC140_Flash.icf,在“Library Configuration”下的库选项用“FULL”在“Library Opitions”下的“printf”和“scanf”格式也用“FULL”;
4,在“Options for node 'nuc140'”的“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“Third-Party Driver”,然后在“Third-Party Driver”选择驱动到
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll”,在“C/C++ Compiler”下的“Preprocessor”下面的方框内填上:
$PROJ_DIR$\..\inc\
$PROJ_DIR$\..\bsp\
$PROJ_DIR$\..\bsp\Cmsis\
$PROJ_DIR$\..\bsp\Driver\
5,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\NUC100_APROM.board”,把
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Samples\NUC140_PWM\config”下的“NUC140_Flash.icf”和“NUC140_Ram.icf”复制到“D:\works\9G-CM0\9G-NUC140\prj\config”,
把“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Samples\NUC140_PWM”下的“SH_retarget.c”和“SH_startup_NUCxxx_iar.s”复制到“D:\works\9G-CM0\9G-NUC140\bsp\Boot”;
6,在“IAR Embedded Workbench IDE”的“Workspace”下的“Files”中右击选择“Add”->“Add Group”并填入“sys”,另外同样建立“bsp”,“drv”,“src”等目录,然后在“sys”上右击
选择“Add”->“Add Files” 然后选择“D:\works\9G-CM0\9G-NUC140\bsp\Boot”下的“SH_retarget.c”,“SH_startup_NUCxxx_iar.s”和“D:\works\9G-CM0\9G-NUC140\bsp\Cmsis”下的
“core_cm0.c”和“system_NUC1xx.c”;同样用“Add”->“Add Files”把“D:\works\9G-CM0\9G-NUC140\bsp\Driver”的文件添加到“bsp”目录;(retarget.c和DrvUSB.c除外)
7,在“D:\works\9G-CM0\9G-NUC140\src”中建立“main.c”,然后添加到工程的“src”中,并在“main.c”中填入下面内容:
#include <stdio.h>
#include <stdint.h>
#include <Nuvoton\ionuc1xx.h>
int main(void)
{
uint32_t i=0;
/* Output a message on Hyperterminal using printf function */
printf("\n\r\n\r\n\r\n\r");
printf("*** 9G-NUC120 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** 9G-NUC120 V1.00 Rebooting ...\n\r\n\r");
while(1)
{
GPA_DOUT =0xffff;
for(uint32_t j = 0; j <1000000; j++);
GPA_DOUT =0x0000;
for(uint32_t j = 0; j <1000000; j++);
printf("*** 9G-NUC140 V1.00 Running %d Times...\n\r",i++);
}
}
(编译时会有与core_cm0.h与“C:\Program Files\IAR Systems\Embedded Workbench 6.0\arm\inc\c\intrinsics.h”相冲突时,
把有问题的uint32_t改回相应的 unsigned long即可;)
8,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\NUC100_LDROM.board”,可以把
相应的程序烧进LDROM区;
9,在“EWARM”的IDE菜单中选择“Nu-Link”->“ICP Programming Tool”中,可以不擦除整片FLASH直接改变配置位从APPROM区切换到LDROM区启动,FLASH的1能修改成0;
9G-MINI51 新唐CM0+EWARM入门开发过程简介
一,准备EWARM + 新唐CM0软件包
1,在http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=1&SoftID=535 上
下载 IAR Embedded Workbench for ARM v6.20 FULL CD-EWARM-6201-2590 软件
CD-EWARM-6201-2590_mcu123.zip
ftp://mcu123:mcu123@mcu123.com/已整理目录/开发工具软件/ARM/CD-EWARM-6201-2590_mcu123.zip
相关文件“IAR_EWARM5.4和谐文件.rar ”可以在GOOGLE上搜索到
http://bbs.mcu123.net/bbs/thread-15164-1-1.html
并下载:
IAR_EWARM5[1].4和谐文件.rar
2,在http://www.nuvoton-m0.com/forum.php?mod=viewthread&tid=2&extra=page%3D1上
下载Nu-Link驱动“公测版驱动下载 v1.17.5218,支持最新的IAR 6.21”
Nu-Link_IAR_Driver 1.17.5218.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=MTg3fDI4NGFkNTk1fDEzMTUyOTkyOTF8MA%3D%3D
下载ICP编程工具“NuMicro ICP Programming Tool 1.17.5218”
NuMicro ICP Programming Tool 1.17.5218.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=MTg2fDI3YTFmZmJlfDEzMTUyOTkyOTF8MA%3D%3D
下载ISP编程工具“NuMicro ISP Programming Tool v1.41”
NuMicro ISP Programming Tool V1.41.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NDh8OTBkZjBjYTJ8MTMxNTI5OTI5MXww
下载?M051软件库资源“M051SeriesBSP_CMSIS V1.02.001”和“M051SeriesBSP_RegCtrlPrg V1.00.002”
M051SeriesBSP_v1.02.001.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NDV8ZTc3MTg5M2V8MTMxNTM3NjExOHww
M051SeriesBSP_RegCtrlPrg.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NDZ8OTVlMjM1OGN8MTMxNTM3NjExOHww
3,在“http://dzstic.com/down.asp”上下载“NuTiny-EVB-Mini51_V002”文档
NuTiny-EVB-Mini51_V002.rar
http://dzstic.com/upload/20110907/20110907141832652.rar
4,新唐官方资料网址
新唐CM0官方资料主页
http://www.nuvoton.com/hq/chs/Pages/default.aspx
二,建立CM0的EWARM+Nu-LINK开发环境
1,双击“IAR_EWARM5[1].4和谐文件.rar”,运行里面的“EWARM_FULL_ARM540.exe”,选择“Product”中的“Embedded Workbench For ARM v5.40”,然后点击“Generate”
把产生的“License key”“License number”密码和序列号记录下来;
2,双击“CD-EWARM-6201-2590_mcu123.zip”运行里面的“autorun.exe”,在“IAR Embedded Workbench For ARM”中选择“Install IAR Embedded Workbench”,按常规的软件安装方式
把“IAR Embedded Workbench For ARM”安装到电脑上;
3,双击“Nu-Link_IAR_Driver 1.17.5218.zip”运行里面的“Nu-Link_IAR_Driver 1.17.5218.exe”,便会在“C:\Program Files\Nuvoton Tools\Nu-Link_IAR”和“C:\Program Files
\IAR Systems\Embedded Workbench 6.0” 目录中安装上相关的“Nu-LINK”的驱动。
4,双击“NuMicro ICP Programming Tool 1.17.5218.zip”运行里面的“NuMicro ICP Programming Tool 1.17.5218.exe”,便会在“C:\Program Files\Nuvoton Tools\ICPTool”
目录中安装上相关的“ ICP Programming Tool”的工具。
三,建立CM0的EWARM基本工程
1,在电脑开始菜单中打开“IAR Embedded Workbench IDE”,在“EWARM”的IDE菜单中选择“Project”->“Create New Project”创建一个新工程,在“Create New Project”选择“OK”存储目录
到“D:\works\9G-CM0\9G-MINI51\prj”下面,工程名叫“MINI51.ewp,点击“OK”完成,点击“File”下的“Save Workspace”保存工作空间到目录中的“MINI51.eww”;
2,在“D:\works\9G-CM0\9G-MINI51”下建立文件夹“bsp”“drv”“inc”“src”,等子目录,在“D:\works\9G-CM0\9G-MINI51\prj”下建立子目录“config”,并把 “M051SeriesBSP_v1.02.001.zip”
的“M051SeriesBSP\NuvotonPlatform_IAR\Src\Driver”和“M051SeriesBSP\NuvotonPlatform_IAR\Include\Driver”解压到“D:\works\9G-CM0\9G-MINI51\bsp\Driver”目录,把“M051SeriesBSP\
NuvotonPlatform_IAR\Include\System”解压到“D:\works\9G-CM0\9G-MINI51\bsp\System”目录,把“M051SeriesBSP\CMSIS\CM0\DeviceSupport\Nuvoton\M051Series\startup\iar\startup_M051Series.s”解压到
“D:\works\9G-CM0\9G-MINI51\bsp\Boot”,把“M051SeriesBSP\CMSIS\CM0\DeviceSupport\Nuvoton\M051Series”下的H和C文件及“M051SeriesBSP\CMSIS\CM0\CoreSupport”下的H和C文件解压到
“D:\works\9G-CM0\9G-MINI51\bsp\Cmsis”;
3,在“EWARM”的IDE菜单中选择“Project”->“Options”中的“General Options”的“Target”中的“Device”中选择“Nuvoton Mini51 series (Mini51,Mini52,Mini54)”,在“Linker”菜单中选择“Linker configuration file”里选择
“override default”并填上“$PROJ_DIR$\config\M052_Flash.icf”,在“Library Configuration”下的库选项用“FULL”在“Library Opitions”下的“printf”和“scanf”格式也用“FULL”;
4,在“Options for node 'MINI51'”的“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“Third-Party Driver”,然后在“Third-Party Driver”选择驱动到
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll”,在“C/C++ Compiler”下的“Preprocessor”下面的方框内填上:
$PROJ_DIR$\..\inc\
$PROJ_DIR$\..\bsp\
$PROJ_DIR$\..\bsp\Cmsis\
$PROJ_DIR$\..\bsp\Driver\
5,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\Mini51_APROM.board”,把
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Samples\M052\config”下的“M052_Flash.icf”复制到“D:\works\9G-CM0\9G-MINI51\prj\config”,
把“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Samples\M052”下的“SH_retarget.c”和“SH_startup_M05x_iar.s”复制到“D:\works\9G-CM0\9G-MINI51\bsp\Boot”;
6,在“IAR Embedded Workbench IDE”的“Workspace”下的“Files”中右击选择“Add”->“Add Group”并填入“sys”,另外同样建立“bsp”,“drv”,“src”等目录,然后在“sys”上右击
选择“Add”->“Add Files” 然后选择“D:\works\9G-CM0\9G-MINI51\bsp\Boot”下的“SH_retarget.c”,“SH_startup_NUCxxx_iar.s”和“D:\works\9G-CM0\9G-MINI51\bsp\Cmsis”下的
“core_cm0.c”和“system_M051Series.c”;同样用“Add”->“Add Files”把“D:\works\9G-CM0\9G-MINI51\bsp\Driver”的文件添加到“bsp”目录;(retarget.c除外)
7,在“D:\works\9G-CM0\9G-MINI51\src”中建立“main.c”,然后添加到工程的“src”中,并在“main.c”中填入下面内容:
#include <stdio.h>
#include <stdint.h>
#include <Nuvoton\iomini51.h>
int main(void)
{
uint32_t i=0;
/* Output a message on Hyperterminal using printf function */
printf("\n\r\n\r");
printf("*** 9G-MINI51 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** 9G-MINI51 V1.00 Rebooting ...\n\r\n\r");
GPIO_P0_PMD = 0X5555;
GPIO_P1_PMD = 0X5555;
GPIO_P2_PMD = 0X5555;
GPIO_P3_PMD = 0X5555;
GPIO_P4_PMD = 0X5555;
GPIO_P5_PMD = 0X5555;
while(1)
{
for(uint32_t j = 0; j <800000; j++);
GPIO_P0_DOUT = 0x5E; /* switch on LEDs */
GPIO_P1_DOUT = 0xCA;
GPIO_P2_DOUT = 0xAB;
GPIO_P3_DOUT = 0x9A;
GPIO_P4_DOUT = 0x55;//NO USE
GPIO_P5_DOUT = 0XE2;
for(uint32_t j = 0; j <800000; j++);
GPIO_P0_DOUT = 0xAD; /* switch off LEDs */
GPIO_P1_DOUT = 0xF7;
GPIO_P2_DOUT = 0xD7;
GPIO_P3_DOUT = 0xED;
GPIO_P4_DOUT = 0xAA;//NO USE
GPIO_P5_DOUT = 0XDD;
printf("*** 9G-MINI51 V1.00 Running %d Times...\n\r",i++);
}
}
(编译时会有与core_cm0.h与“C:\Program Files\IAR Systems\Embedded Workbench 6.0\arm\inc\c\intrinsics.h”相冲突时,把有问题的uint32_t改回相应的 unsigned long即可。)
本程序采用了新唐NUC120RD2BN带了EBI总线的CPU,因为ILI9327只有一个地址线RS,也就是命令,数据寄存器地址,而且又支持16位总线,所以把此地址线接到多余的ALE上,把ALE配置成GPIO模式,把ALE地址锁存的时序忽略掉,直接用EBI总线驱动ILI9327的数据总线。
其余不多说,请查看源码文件:ili9327.c
文件内容如下:
* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <NUC1xx.H>
#include "Driver\DrvSYS.h"
#include "Driver\DrvGPIO.h"
#include "Driver\DrvEBI.h"
#define TFT_BL E_GPA, 15 /* PA.15 = TFT_BL */
#define TFT_RST E_GPA, 9 /* PA.9 = TFT_RST */
#define TFT_DC E_GPB, 6 /* PB.6 = TFT_DC */
#define ILI9327_READ() (*(__IO uint16_t *)(0x60000000))
#define ILI9327_DAT(DAT) *(__IO uint16_t *)(0x60000000) = DAT
#define ILI9327_CMD(CMD) {GPIOB->DOUT &= 0xffbf;*(__IO uint16_t *)(0x60000000) = CMD;GPIOB->DOUT |= 0x0040;}
/*
//make by yuanxihua@21cn.com
//BYD LCM
//BM240400-8790FTGB
//262K TFT 240RGB×400dots
//
//ILI9327 is a 262,144-color single-chip SoC driver for a-TFT liquid crystal display
//with resolution of 240RGBx432 dots, comprising a 720-channel source driver, a 432-channel
//gate driver, 233,280 bytes GRAM for graphic data of 240RGBx432 dots, and power supply circuit.
_________________________________________________
| NUC120RD2BN ILI9327B |
| |
| PA9 TFT_RST ----> RESET |
| PA15 TFT_BL ----> BACKLIGHT |
| PB6 TFT_DC ----> RS |
| NCS TFT_CS ----> CS |
| NWR TFT_WR ----> WR |
| NRD TFT_RD ----> RD |
| AD0 TFT_D0 <---> DB0 |
| ... ... <---> ... |
| AD15 TFT_D15 <---> DB15 |
|_______________________________________________|
*/
uint16_t color_table[16]={0x0000,0xf800,0x07e0,0x001f,0xf81f,0xffe0,0x07ff,0xffff,};
void EBI_Init(void)
{
DRVEBI_CONFIG_T sEBIConfig;
DRVEBI_TIMING_T sEBITiming;
// Open EBI function
sEBIConfig.eDataWidth = E_DRVEBI_DATA_16BIT;
sEBIConfig.eAddrWidth = E_DRVEBI_ADDR_16BIT;
sEBIConfig.u32BaseAddress = DRVEBI_BASE_ADDR;
sEBIConfig.u32Size = DRVEBI_MAX_SIZE;
DrvEBI_Open(sEBIConfig);
// Disable nWRH & nWRL for EBI support
outpw(&SYS->GPBMFP, inpw(&SYS->GPBMFP) & ~(0x3<<2));
outpw(&SYS->ALTMFP, inpw(&SYS->ALTMFP) & ~(0x3<<13));
// Configure EBI timing
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_1; // 1656.0 KHZ //Display And Read ID ERROR!!!
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_2; // 1147.0 KHZ //Display OK, But Read ID ERROR!!!
sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_4; // 666.7 KHZ //Display OK, And Read ID OK!!!
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_8; // 400.0 KHZ
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_16; // 211.9 KHZ
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_32; // 106.4 KHZ
sEBITiming.u8ExttALE = 0;
sEBITiming.u8ExtIR2R = 0;
sEBITiming.u8ExtIW2X = 0;
sEBITiming.u8ExttAHD = 0;
sEBITiming.u8ExttACC = 0;
DrvEBI_SetBusTiming(sEBITiming);
}
void ILI9327_READ_ID(void)
{
uint16_t i;
ILI9327_CMD(0xEF); //Device Code Read
printf("ILI9327 ID DATA: ");
for(i=1;i<=6;i++){printf("%04x ",(uint16_t)ILI9327_READ());}
printf("\n\r\n\r");
}
void ILI9327_RESET(void)
{
//PA9 PA15 PB6 is defined as GPIO;
outpw(&SYS->GPAMFP, inpw(&SYS->GPAMFP) & ~(0x1<< 9));
outpw(&SYS->GPAMFP, inpw(&SYS->GPAMFP) & ~(0x1<<15));
outpw(&SYS->GPBMFP, inpw(&SYS->GPBMFP) & ~(0x1<< 6));
//TFT_RST TFT_DC TFT_BL is defined as Output;
DrvGPIO_Open(TFT_RST, E_IO_OUTPUT);
DrvGPIO_Open(TFT_DC , E_IO_OUTPUT);
DrvGPIO_Open(TFT_BL , E_IO_OUTPUT);
DrvGPIO_SetBit(TFT_DC );
DrvGPIO_ClrBit(TFT_BL );
DrvGPIO_SetBit(TFT_RST);
DrvSYS_Delay(1000);
DrvGPIO_ClrBit(TFT_RST); // RESET LOW >= 1 ms
DrvSYS_Delay(2000);
DrvGPIO_SetBit(TFT_RST); // RESET HIGH >= 120 ms
DrvSYS_Delay(200000);
}
void ILI9327_CLEAR(uint16_t color)
{
uint16_t i,j;
for(i=0;i<240;i++)
{
for (j=0;j<400;j++) {ILI9327_DAT(color);}
}
}
void Delay_1ms(int delay)
{
uint32_t i;
for(i=0;i<delay;i++)DrvSYS_Delay(1000);
}
void ILI9327_TEST(void)
{
uint16_t i,color;
printf("%s(%d): Running: %s()\n\r",__FILE__,__LINE__,__FUNCTION__);
while(1)
{
color = color_table[(i++)%8];
printf("COLOR = 0x%04x \n\r",color);
ILI9327_CLEAR(color);
Delay_1ms(2000); // 2s
}
}
void ILI9327_Init(void)
{
printf("*** ILI9327 Driver V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r\n\r");
EBI_Init();
ILI9327_RESET();
ILI9327_READ_ID();
ILI9327_CMD(0xE9); //
ILI9327_DAT(0x20);
ILI9327_CMD(0x11); //exit_sleep_mode
DrvSYS_Delay(100000); //100 ms
ILI9327_CMD(0xD1); //VCOM Control
ILI9327_DAT(0x00);
ILI9327_DAT(0x6b);
ILI9327_DAT(0x18);
ILI9327_CMD(0xD0); //Power_Setting
ILI9327_DAT(0x07);
ILI9327_DAT(0x04);
ILI9327_DAT(0x88);
ILI9327_CMD(0x36); //set_address_mode
ILI9327_DAT(0x88);
ILI9327_CMD(0xC1); //Display_Timing_Setting for Normal/Partial Mode
ILI9327_DAT(0x10);
ILI9327_DAT(0x10);
ILI9327_DAT(0x02);
ILI9327_DAT(0x02);
ILI9327_CMD(0xC0); //Panel Driving Setting
ILI9327_DAT(0x00);
ILI9327_DAT(0x35);
ILI9327_DAT(0x00);
ILI9327_DAT(0x00);
ILI9327_DAT(0x01);
ILI9327_DAT(0x02);
ILI9327_CMD(0xC5); //Frame Rate Control
ILI9327_DAT(0x02);
ILI9327_CMD(0xD2); //Power_Setting for Normal Mode
ILI9327_DAT(0x01);
ILI9327_DAT(0x44);
ILI9327_CMD(0xC8); //Gamma Setting
ILI9327_DAT(0x00);
ILI9327_DAT(0x56);
ILI9327_DAT(0x45);
ILI9327_DAT(0x04);
ILI9327_DAT(0x03);
ILI9327_DAT(0x01);
ILI9327_DAT(0x23);
ILI9327_DAT(0x12);
ILI9327_DAT(0x77);
ILI9327_DAT(0x40);
ILI9327_DAT(0x09);
ILI9327_DAT(0x06);
ILI9327_DAT(0x88);
ILI9327_DAT(0x88);
ILI9327_DAT(0x88);
ILI9327_CMD(0x3A); //set_pixel_format
ILI9327_DAT(0x55);
ILI9327_CMD(0x2A); //set_column_address
ILI9327_DAT(0x00);
ILI9327_DAT(0x00);
ILI9327_DAT(0x00);
ILI9327_DAT(0xEF);
ILI9327_CMD(0x2B); //set_page_address
ILI9327_DAT(0x00);
ILI9327_DAT(0x20);
ILI9327_DAT(0x01);
ILI9327_DAT(0xAF);
ILI9327_CMD(0x29); //set_display_on
ILI9327_CMD(0x2C); //write_memory_start
DrvGPIO_SetBit(TFT_BL );
ILI9327_TEST();
}
void ILI9327_SLEEP(void)
{
ILI9327_CMD(0x10); //enter_sleep_mode
}
void ILI9327_WAKEUP(void)
{
ILI9327_CMD(0x11); //exit_sleep_mode
}
void EBI_test(void)
{
uint32_t i,j=0;
uint32_t data;
printf("%s(%d): Running: %s()\n\r",__FILE__,__LINE__,__FUNCTION__);
EBI_Init();
printf("MCLK of EBI colck is %d KHz.\n\r", (DrvSYS_GetHCLKFreq()/4)/1000);
//PA9 PB6 is defined as GPIO;
outpw(&SYS->GPAMFP, inpw(&SYS->GPAMFP) & ~(0x1<<9));
outpw(&SYS->GPBMFP, inpw(&SYS->GPBMFP) & ~(0x1<<6));
//TFT_RST TFT_DC TFT_BLis defined as Output;
DrvGPIO_Open(TFT_RST, E_IO_OUTPUT);
DrvGPIO_Open(TFT_DC , E_IO_OUTPUT);
DrvGPIO_Open(TFT_BL , E_IO_OUTPUT);
DrvGPIO_Open(E_GPB, 1 , E_IO_OUTPUT); //LED test...
DrvGPIO_SetBit(TFT_DC );
DrvGPIO_SetBit(TFT_RST);
DrvGPIO_ClrBit(TFT_BL );
while(0)
{
//test for write
*(__IO uint16_t *)((uint32_t)0x60000000) = 0xffff;
*(__IO uint16_t *)((uint32_t)0x60000000) = 0x0000;
}
while(0)
{
//test for read
data = *(__IO uint16_t *)((uint32_t)0x60000000);
printf("Running %d Times : D15-D0:%1d%1d%1d%1d%1d%1d%1d%1d_%1d%1d%1d%1d%1d%1d%1d%1dB\n\r",j++,
(data>>15)&0x1,(data>>14)&0x1,(data>>13)&0x1,(data>>12)&0x1,
(data>>11)&0x1,(data>>10)&0x1,(data>> 9)&0x1,(data>> 8)&0x1,
(data>> 7)&0x1,(data>> 6)&0x1,(data>> 5)&0x1,(data>> 4)&0x1,
(data>> 3)&0x1,(data>> 2)&0x1,(data>> 1)&0x1,(data>> 0)&0x1);
for(i=0;i<0x200000;i++); //delay about 1 second
}
while(1)
{
printf("Running %d Times...\n\r",j++);
//test for IO
DrvGPIO_SetBit(TFT_RST);
DrvGPIO_SetBit(TFT_DC );
DrvGPIO_SetBit(TFT_BL );
GPIOB->DOUT |= (1 << 1);
for(i=0;i<0x200000;i++);
DrvGPIO_ClrBit(TFT_RST);
DrvGPIO_ClrBit(TFT_DC );
DrvGPIO_ClrBit(TFT_BL );
GPIOB->DOUT &= ~(1 << 1);
for(i=0;i<0x200000;i++);
}
}
文件结束。
元旦放假,急于赶一个小项目,做了一个M0516LAN驱动SIM900A的测试。第一次用SIM900A,其中遇到几个小问题,调了好久,也问过群里用过SIM900A的几位朋友才调通,在此感谢。最弱智的问题是我把NRESET接到了PWM3上,然后又启动了PWM3,虽然后面把P43置成IO输出却不成功,然后大半晚上就那么悲剧掉了。新唐的库是置成了复用功能再想置回IO,需要先DrvGPIO_InitFunction(E_FUNC_GPIO);才能配置IO功能的。我后来还是不启动PWM就通过了开机过程。只要SIM900A开机了,NETLIGHT的LED就会闪烁,不管有没有SIM卡。另外,所有SIM900A的AT命令都是以“\r”结束的。
“sim900a.c ”文件源码如下:
#include <stdio.h>
#include <M051Series.h>
#include "Driver\DrvUART.h"
#include "Driver\DrvGPIO.h"
#include "Driver\DrvSYS.h"
#define PWRKEY E_PORT2, E_PIN1
#define NRESET E_PORT4, E_PIN3
#define STATUS E_PORT2, E_PIN3
#define RI E_PORT3, E_PIN2
#define CTS E_PORT0, E_PIN0
/*
_________________________________________________
| M0516LAN SIM900A |
| |
| P21 PWRKEY ----> PWRKEY |
| P43 NRESET ----> NRESET |
| P23 STATUS <---- STATUS |
| P32 RI <---- RI |
| P00 CTS1 <---- CTS |
| P13 TXD1 ----> RXD |
| P12 RXD1 <---- TXD |
|_______________________________________________|
*/
int UART1_init(void)
{
STR_UART_T sParam;
/* Set UART1 Pin */
DrvGPIO_InitFunction(E_FUNC_UART1);
// outpw(&SYS->P1_MFP, (inpw(&SYS->P1_MFP) | (0x3<<10)) & ~(0x3<<2));
// outpw(&SYS->P0_MFP, (inpw(&SYS->P0_MFP) | (0x3<<8)) & ~(0x3<<0));
/* Select UART1 Clock Source From 12Mhz*/
DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,0);
/* UART1 Setting */
sParam.u32BaudRate = 9600;
sParam.u8cDataBits = DRVUART_DATABITS_8;
sParam.u8cStopBits = DRVUART_STOPBITS_1;
sParam.u8cParity = DRVUART_PARITY_NONE;
sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES;
if(DrvUART_Open(UART_PORT1,&sParam) != E_SUCCESS)
{
printf("UART1 open failed\n");
return FALSE;
}
/* Enable Interrupt and install the call back function */
// DrvUART_EnableInt(UART_PORT1, (DRVUART_RLSINT | DRVUART_RDAINT),UART1_INT_HANDLE);
/* Disable Interrupt */
// DrvUART_DisableInt(UART_PORT1,DRVUART_RLSINT | DRVUART_THREINT | DRVUART_RDAINT);
return TRUE;
}
int SIM900A_Open(void)
{
int dly;
DrvGPIO_ClrBit(PWRKEY);
for(dly=0;dly<2000;dly++) DrvSYS_Delay(1000); //delay 1S
DrvGPIO_SetBit(PWRKEY);
for(dly=0;dly<3000;dly++) DrvSYS_Delay(1000); //delay 3S
if(DrvGPIO_GetBit(STATUS))
{
printf("SIM900A Open Success!!!\n\r");
return 1;
}
else
{
printf("SIM900A Open Failure!!!\n\r");
return 0;
}
}
int SIM900A_Close(void)
{
int dly;
DrvGPIO_ClrBit(PWRKEY);
for(dly=0;dly<6000;dly++) DrvSYS_Delay(1000); //delay 1S-5S
DrvGPIO_SetBit(PWRKEY);
for(dly=0;dly<4000;dly++) DrvSYS_Delay(1000); //delay 2S
if(DrvGPIO_GetBit(STATUS))
{
printf("SIM900A Close Failure!!!\n\r");
return 1;
}
else
{
printf("SIM900A Close Success!!!\n\r");
return 0;
}
}
int SIM900A_Reset(void)
{
int dly;
DrvGPIO_ClrBit(NRESET);
DrvSYS_Delay(100); //delay 20uS-50uS
DrvGPIO_SetBit(NRESET);
for(dly=0;dly<2000;dly++) DrvSYS_Delay(1000); //delay 2S
if(DrvGPIO_GetBit(STATUS)==1)
return 1;
else
return 0;
}
int SIM900A_init(void)
{
int ret =0;
DrvGPIO_Open(STATUS, E_IO_INPUT);
DrvGPIO_Open(RI, E_IO_INPUT);
DrvGPIO_Open(CTS, E_IO_INPUT);
DrvGPIO_Open(PWRKEY, E_IO_OUTPUT);
DrvGPIO_Open(NRESET, E_IO_OUTPUT);
DrvGPIO_SetBit(PWRKEY);
DrvGPIO_SetBit(NRESET);
ret = SIM900A_Open();
UART1_init();
return ret;
}
int SIM900A_gets(char *buf)
{
int ret=0;
int dly=3000000; // delay 3S
while(dly-->1)
{
if(UART1->FSR.RX_EMPTY == 0 )
{
*buf++ =UART1->DATA;//printf("%c",*(buf-1));
ret++;dly=10000; //delay 10ms
}
DrvSYS_Delay(1); //delay 1us
}
return ret;
}
void SIM900A_puts(const char *buf)
{
while(*buf)
{
while(UART1->FSR.TX_FULL == 1);
UART1->DATA =(*buf++)&0xff;//printf("%c",*(buf-1));
}
}
// AT+CPOWD=1 //Power down
// AT+CFUN=x //Power Saving
// AT+CBC //monitor the supply voltage
// AT+IPR=x //fixed baud rate ,“RDY” is received
// AT+CSCLK=1 //enable the SLEEP mode
// AT+CMIC //adjust the input gain level of microphone
// AT+SIDET //set the side-tone level
// AT+CLVL //adjust the output gain level
// AT+CADC //read the voltage value on ADC
void SIM900A_test(void)
{
char buffer[128];
printf("\n\r\n\r");
printf("*** 9G-M0516 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** 9G-M0516 V1.00 Rebooting ...\n\r\n\r");
SIM900A_init();
printf("SIM900A_test Send AT COMMAND @ 9600 bps !!!\n\r");
// SIM900A_puts("ATI\r");
SIM900A_puts("AT+GMM\r");
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
}
//源码完毕。--缥缈九哥调试通过。
半主机的调试信息如下:
*** 9G-M0516 V1.00 Build by yuanxihua@21cn.com on (Jan 3 2012 - 13:16:32)
*** 9G-M0516 V1.00 Rebooting ...
SIM900A Open Success!!!
SIM900A_test Send AT COMMAND @ 9600 bps !!!
AT+GMM
SIMCOM_SIM900A
OK
--缥缈九哥验证
读SIM卡电话本。
SIM900A_puts("AT+CPBS=\"SM\"\r");
读第一条电话本记录
//get SIM no.1 phoneid
SIM900A_puts("AT+CPBR=1,1\r");
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
for(i=0;i<11;i++)
{
//AT+CPBR=1,1
//+CPBR: 1,"13925101136",129,"yuanxihua"
// printf("\n\r%c",buffer[24+i]);
callphoneid[i]= buffer[24+i];
}
//
发中文短信。
SIM900A_puts("AT+CMGF=1\r"); //TEXT Mode
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
SIM900A_puts("AT+CSCS=\"UCS2\"\r"); //for CHINESE
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
//不用配置短信服务中心号码
/*
SIM900A_puts("AT+CSCA=\"002B0038003600310033003800300030003200300030003500300030\",145\r"); //+8613800200500 短信中心号码
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
*/
SIM900A_puts("AT+CSMP=17,167,0,25\r");
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
// SIM900A_puts("AT+CMGS=\"00310033003900320035003100300031003100330036\"\r"); //13925101136 被叫号码,不固定,从SIM卡读。
SIM900A_puts("AT+CMGS=\"");
for(i=0;i<11;i++)
{
SIM900A_puts("003");
SIM900A_putchar(callphoneid[i]);
}
SIM900A_puts("\"\r");
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
SIM900A_puts("4F60597D ");
//你好 短信内容,UNICODE格式;
SIM900A_putchar(26); //<Ctrl+Z>
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0);
{printf("\n\r%s\n\r",buffer);}
打电话
printf("SIM900A Phone a call by AT-commond @ 9600 bps !!!\n\r");
// Call a phone
SIM900A_puts("ATD");
for(i=0;i<11;i++)
{
SIM900A_putchar(callphoneid[i]);
}
SIM900A_puts(";\r");
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
发英文短信
printf("SIM900A Send a English SMS by AT-commond @ 9600 bps !!!\n\r");
//init SIM900A for SMS
SIM900A_puts("AT+CMGF=1\r"); //TEXT Mode
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
SIM900A_puts("AT+CSCS=\"GSM\"\r");
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
//prepore config SIM900A for sendding a SMS
SIM900A_puts("AT+CMGS=\"+86");
for(i=0;i<11;i++)
{
SIM900A_putchar(callphoneid[i]);
}
SIM900A_puts("\"\r");
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
//send a SMS to SIM900A
SIM900A_puts("This a report from yuanxihua@21cn.com!!!\x1a");// \x1a = <Ctrl+Z>
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
一,准备Keil C51 + 新唐N79E8X软件包
1,在http://www.mcu123.com/news/Soft/embsof/uc/201109/539.html
上点击“::下载地址:: ”下的“FTP下载地址1 ”,在弹出的网页上
http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=1&SoftID=539
上再右击“下载地址:”后的“下载”选择“目标另存为”下载文件到本地硬盘。
下载keil c51v9.05 KEIL V9 C51V905
文件名是:c51v905_mcu123.rar
ftp://mcu123.com/%D2%D1%D5%FB%C0%ED%C4%BF%C2%BC/%BF%AA%B7%A2%B9%A4%BE%DF%C8%ED%BC%FE/51/c51v905_mcu123.rar
(自己查找破解文件“keygen.exe”)
2,在http://www.nuvoton.com 上点开“8051 Microcontroller”下的“80C51 LPC Microcontroller”来打开网页
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=6913c5ee-ddaa-464c-a71b-e7e57f056436
把“N79/W79 LPC Series - Industrial Temperature Grade ”下面的数据手册全部下载下来;
然后点击“Development Resources”子栏目中的“Development Tool”出现
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=670aaf31-5d5c-45d3-8a9e-040e148d55cf
然后右击“Nuvoton 8051 Keil uVision Driver v1.02.zip”选择“目标另存为”下载文件到本地硬盘,
Nuvoton_8051_Keil_uVision_Driver_v1.02.zip
同样右击另存下载“Nuvoton ISP-ICP Programmer v6.00.zip”到本地硬盘;
Nuvoton+ISP-ICP+Programmer+v6.00.zip
退回上个网页
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=6913c5ee-ddaa-464c-a71b-e7e57f056436
并点击“Development Resources”子栏目中的“Demo Code”出现
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=515275c4-f6ae-4915-89ce-366fd8097efc
把“Demo Code”下面的所有例子代码包全部下载下来。
二,建立Keil C51+N79E8X开发环境
1,双击“c51v905_mcu123.rar”运行里面的“c51v905.exe”,一路的“NEXT”再“NEXT”,最后就会安装“PK51 Prof. Developrs Kit”到电脑上,
将会在桌面产生“Keil uVision4”的快捷方式;
2,双击和谐软件“keygen.exe”,把“uVision4”的“File->License Management”菜单里面的“CID”复制到keygen里面的CID框中,选择“TARGET”
为“C51”后点击“Generate”,把产生的序列号复制到前面“uVision4”的窗口中的“LIC”框中,点击“ADD LIC”便会解除编译限制;
3,双击“Nuvoton_8051_Keil_uVision_Driver_v1.02.zip”运行里面的“Nuvoton_8051_Keil_uVision_Driver_v1.02.EXE”,便会在KEIL目录中安装上
相关的“Nu-LINK ICE Bridge”的驱动。
三,建立Keil C51+N79E8X基本工程
1,在电脑开始菜单中打开“Keil uVision4”,在“uVision4”的IDE菜单中选择“Project”->“New uVision Project”创建一个新工程,在“Create New Project”选择存储目录
到“D:\works\9G-CM0\9G-N79E8X\prj”下面,工程名叫“9g-n79e8x.uvproj”;
2,接着在“select a CPU Data Base File”菜单中选择“Generic CPU Base”点击“OK”,选择“Nuvoton”公司下面的“N79E855”点击“OK”后确认复制启动代码“STARTUP.A51”和
加入到工程项目中,即可产生一个空工程,再点击全部保存项目,会在“D:\works\9G-CM0\9G-N79E8X\prj”目录中发现“9g-n79e8x.uvopt”和“9g-n79e8x.uvproj”,“STARTUP.A51”等文件;
3,在“D:\works\9G-CM0\9G-N79E8X”下建立“drv”,“inc”,“lst”,“obj”,“src”等子目录,
4,在“uVision4”的IDE菜单中选择“Project”->“Manage”->“Components,Environment,Books”打开“Components,Environment,Books”页面里的“Project Components”,
双击“Target1”改名为“N79E8X”,双击“Source Group 1”改名为“boot”再添加“lib”“drv”“src”“inc”等目录后点击“OK”。
5,在“uVision4”的IDE菜单中选择“File”->“New”后选择“File”->“Save”把新建立的文件保存到“D:\works\9G-CM0\9G-N79E8X\src”,文件名为“main.c”,右击项目窗口中的“src”选择“Add Files
to Group 'src'”并在“main.c”中填入下面内容:
#include <stdio.h>
#include "N79E855A.h"
void delay_ms(unsigned ms)
{
unsigned int i,j;
for(i=0;i<ms;i++){for(j=0;j<300;j++);}
}
void main(void)
{
while(1)
{
P0=P1=P2=P3=0x00;
delay_ms(500);
P0=P1=P2=P3=0xFF;
delay_ms(500);
}
}
三,配置Keil C51+N79E8X基本工程
1,在“uVision4”的IDE菜单中选择“Project”->“Opitions for Target ‘N79E8X’”,在“Output”页面勾选“Create HEX File”,并在“Select Folder Objects”指定
目录到“D:\works\9G-CM0\9G-N79E8X\obj”,后点击“OK”,同样在“Listing”中在“Select Folder Listings”指定目录到“D:\works\9G-CM0\9G-N79E8X\lst”;
2,在“Opitions for Target ‘N79E8X’”的“Debug”页面选择用硬件仿真器“NUVOTON_8051_KEIL_Driver”或者“Nuvoton Nu-Link 8051 Debugger”勾选“Run to main{}”,
点击后面的“Setting”里面选择上“AP”,“2.7V”,“CHBDA=0xff”,“CBORST”,“XTAL1”,“CKF”和“22MHZ”后点击“Write Config”,页面的“Driver DLL:”
中填上“S8051.DLL”。
3,在“Opitions for Target ‘N79E8X’”的“Utilities”页面选择“Use Target Driver for Flash Programming”用 “NUVOTON_8051_KEIL_Driver”
或者“Nuvoton Nu-Link 8051 Debugger”勾选上“Update Target before Debugging”后在“Setting”里面的“Configure”,勾选择全部4个选项后点击“OK”再“OK”退出;
3,在“Opitions for Target ‘N79E8X’”的“C/C++”页面的“Include Paths”中填入“..\inc”。
四,调试CM0的MDK-ARM基本工程
1,点击在“uVision4”的IDE菜单中选择“Flash”->“Download”便会自己编译代码生成HEX文件并下载到目标板子中(N79E85J Tiny Board V002的板子要通过USB线接到电脑USB上);;
2,点击在“uVision4”的IDE菜单中选择“Debug”->“Start/Stop Debug session”进入调试状态,然后选择“Debug”->“Run”,全速运行,可以看到IO口上的LED在秒闪烁。
(全文完,缥缈九哥测试于2012-01-18在广州)
应朋友要求,设计了一个游戏机的功夫宝宝的控制台板子,用一个SH88F516驱动两片TM1640的芯片,数码管用LN5461AS,驱动代码如下:
#include "SH88F516.h"
#include <stdio.h> /* prototype declarations for I/O functions */
#define U2DIN P1_5
#define U2SCLK P1_6
#define U1DIN P3_7
#define U1SCLK P3_6
#define TM1640_DELAY 1
//0 1 2 3 4 5 6 7 8 9 A B C D E F
const unsigned char code TM1640_CODE[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7F, 0x39, 0x3F, 0x79, 0x71};
const unsigned char code TM1640_CODEA[16] _at_ 0xe000;
void tm1640_display(unsigned char *led_data);
void tm1640_delay(unsigned int delay)
{
unsigned int i;
for(i=0;i<delay;i++);
}
void tm1640_start(void)
{
U1DIN = U2DIN = 1;
U1SCLK = U2SCLK = 1; tm1640_delay(TM1640_DELAY);
U1DIN = U2DIN = 0; tm1640_delay(TM1640_DELAY);
U1SCLK = U2SCLK = 0; tm1640_delay(TM1640_DELAY);
}
void tm1640_end(void)
{
U1SCLK = U2SCLK = 0;
U1DIN = U2DIN = 0; tm1640_delay(TM1640_DELAY);
U1SCLK = U2SCLK = 1; tm1640_delay(TM1640_DELAY);
U1DIN = U2DIN = 1; tm1640_delay(TM1640_DELAY);
}
void tm1640_byte(unsigned char data1,unsigned char data2)
{
unsigned int i;
for(i=0;i<8;i++)
{
data1 = data1 >>1; U1DIN =CY;
data2 = data2 >>1;
U2DIN =CY; tm1640_delay(TM1640_DELAY);
U1SCLK = U2SCLK = 1; tm1640_delay(TM1640_DELAY);
U1SCLK = U2SCLK = 0; tm1640_delay(TM1640_DELAY);
}
}
void tm1640_display(unsigned char *led_data)
{
unsigned int i;
P1M0 &= ~(1<<6 ); P1M1 |= 1<<6; //
P1M0 &= ~(1<<5 ); P1M1 |= 1<<5; //
P3M0 &= ~(1<<6 ); P3M1 |= 1<<6; //
P3M0 &= ~(1<<7 ); P3M1 |= 1<<7; //
tm1640_end();
tm1640_start();
tm1640_byte(0x40,0x40); // command1
tm1640_end();
tm1640_start();
tm1640_byte(0xc0,0xc0); // command2
for(i=0;i<16;i++)
{
tm1640_byte(TM1640_CODE[led_data[i]],TM1640_CODE[led_data[16+i]]);
}
tm1640_end();
tm1640_start();
tm1640_byte(0x8b,0x8b); // command3
tm1640_end();
}
有一STM32项目需要用到DES算法,从网上找了很多资料什么的,看的似是而非的,只好找以前一个ASCOM的基于8位机,16位机的IC卡电话机的DES源码移植过来使用,测试通过后公布,方便大家借鉴使用。
//以下是des.c文件全部:
//密钥: B4 31 5B 86 9D 7D FA A2
//数据: 1F AD 61 A5 F7 19 77 14
//DES加密结果:4C 78 E9 1A F2 DA 9C D3
const uint8_t initial_tr[64] =
{
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7,
56, 48, 40, 32, 24, 16, 8, 0,
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6
};
const uint8_t final_tr[64] =
{
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25,
32, 0, 40, 8, 48, 16, 56, 24
};
const uint8_t swap[64] =
{
33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64,
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32
};
const uint8_t key_tr1[56] =
{
56, 48, 40, 32, 24, 16, 8,
0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26,
18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14,
6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28,
20, 12, 4, 27, 19, 11, 3
};
const uint8_t key_tr2[64] =
{
0, 0, 13, 4, 16, 10, 23, 0,
0, 0, 2, 9, 27, 14, 5, 20,
0, 0, 22, 7, 18, 11, 3, 25,
0, 0, 15, 1, 6, 26, 19, 12,
0, 0, 40, 54, 51, 30, 36, 46,
0, 0, 29, 47, 39, 50, 44, 32,
0, 0, 43, 52, 48, 38, 55, 33,
0, 0, 45, 31, 41, 49, 35, 28
};
const uint8_t etr[64] =
{
0, 0, 31, 4, 0, 1, 2, 3,
0, 0, 3, 8, 4, 5, 6, 7,
0, 0, 7, 12, 8, 9, 10, 11,
0, 0, 11, 16, 12, 13, 14, 15,
0, 0, 15, 20, 16, 17, 18, 19,
0, 0, 19, 24, 20, 21, 22, 23,
0, 0, 23, 28, 24, 25, 26, 27,
0, 0, 27, 0, 28, 29, 30, 31
};
const uint8_t ptr[32] =
{
31, 14, 39, 44, 60, 23, 55, 36,
4, 30, 46, 53, 12, 37, 62, 21,
5, 15, 47, 29, 63, 54, 6, 20,
38, 28, 61, 13, 45, 22, 7, 52
};
const uint8_t s[8][64] =
{
{
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
},
{
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
},
{
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
},
{
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
},
{
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
},
{
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
},
{
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
},
{
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}
};
const uint8_t rots[16] =
{
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
const uint8_t bit_msk[8] =
{
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
};
uint8_t DES_Encrypt_key[8];
uint8_t DES_Decrypt_key[8];
uint8_t sub_keys[16][8]; //sub_keys[16][8]
uint8_t main_key[8];
void des(uint8_t*, uint8_t*, uint8_t, uint8_t*);
void FLASH_Read_KEYS(uint8_t key_index);
static void transpose (uint8_t*, uint8_t*, const uint8_t*, uint8_t);
static void rotate_l (uint8_t*);
static void compute_subkeys (uint8_t*);
static void f (uint8_t*, uint8_t*, uint8_t*);
/************************************************************************/
/* */
/* Module title: des */
/* Module type: des mainrutine */
/* */
/* Author: YXH */
/* Date: 2012-07-13 */
/* */
/* Last changed by: YXH */
/* Date: 2012-07-13 */
/* */
/* Functional Description: Encipher and decipher 64 bits string */
/* according to a 64 bits key string */
/* The string format is shown below */
/* */
/* input parameter 1: pointer to 64 bits input string */
/* 2: pointer to 64 bits key string */
/* 3: boolean if false indicating enciphering */
/* if true dechiphering */
/* 4: pointer to a 64 bits output string */
/************************************************************************/
/* */
/* msb lsb */
/* bit bit */
/* +-- -- -- -- -- -- -- --+ */
/* addr !1st 8th! */
/* +-- -- -- -- -- -- -- --+ */
/* addr+1 !9th 16th! */
/* +-- -- -- -- -- -- -- --+ */
/* : : */
/* : : */
/* +-- -- -- -- -- -- -- --+ */
/* addr+7 !57th 64th! */
/* +-- -- -- -- -- -- -- --+ */
/* */
/************************************************************************/
void des(uint8_t *plain_strng, uint8_t *key, uint8_t d, uint8_t *ciph_strng)
{
uint8_t a_str[8], b_str[8], x_str[8];
uint8_t i, j, *pkey, temp;
for (i = 0; i < 8 ; ++i)
{
if (key[i] != main_key[i])
{
compute_subkeys(key);
i = 7;
}
}
transpose(plain_strng, a_str, initial_tr, 64);
for (i=1; i < 17; ++i)
{
for (j=0; j < 8; ++j){b_str[j] = a_str[j];}
if (!d) /*enchipher*/
pkey = &sub_keys[i-1][0];
else /*dechipher*/
pkey = &sub_keys[16-i][0];
for (j=0; j < 4; ++j){a_str[j] = b_str[j+4];}
f(pkey, a_str, x_str);
for (j=0; j < 4; ++j) {a_str[j+4] = b_str[j] ^ x_str[j];}
}
temp = a_str[0]; a_str[0] = a_str[4]; a_str[4] = temp;
temp = a_str[1]; a_str[1] = a_str[5]; a_str[5] = temp;
temp = a_str[2]; a_str[2] = a_str[6]; a_str[6] = temp;
temp = a_str[3]; a_str[3] = a_str[7]; a_str[7] = temp;
transpose(a_str, ciph_strng, final_tr, 64);
}
/************************************************************************/
/* */
/* Module title: transpose */
/* Module type: des subrutine */
/* */
/* Author: YXH */
/* Date: 2012-07-13 */
/* */
/* Last changed by: YXH */
/* Date: 2012-07-13 */
/* */
/* Functional Description: Permute n bits in a string, according */
/* to a table describing the new order. */
/* 0 < n <= 64 */
/* */
/* input parameter 1: pointer to first byte in input string */
/* 2: pointer to first byte in output string */
/* 3: pointer to table describing new order */
/* 4: number of bits to be permuted */
/************************************************************************/
void transpose(uint8_t *idata, uint8_t *odata, const uint8_t *tbl, uint8_t n)
{
const uint8_t *tab_adr;
int i, bi_idx;
tab_adr = &bit_msk[0];
i = 0;
do
{odata[i++] = 0;}
while (i < 8);
i = 0;
do
{
bi_idx = *tbl++;
if (idata[bi_idx>>3] & tab_adr[bi_idx & 7])
{
odata[i>>3] |= tab_adr[i & 7];
}
}
while (++i < n);
}
/************************************************************************/
/* */
/* Module title: rotate_l */
/* Module type: des subrutine */
/* */
/* Author: YXH */
/* Date: 2012-07-13 */
/* */
/* Last changed by: YXH */
/* Date: 2012-07-13 */
/* */
/* Functional Description: rotate 2 concatenated strings of 28 */
/* bits one position to the left. */
/* */
/* input parameter 1: pointer to first byte in key string */
/* */
/************************************************************************/
void rotate_l(uint8_t *key)
{
uint8_t str_x[8];
uint8_t i;
for (i=0; i < 8; ++i) str_x[i] = key[i];
for (i=0; i < 7; ++i)
{
key[i] = (key[i] << 1);
if ((i < 6) && ((str_x[i+1] & 128) == 128))
key[i] |= 1;
}
if (str_x[0] & 0x80 )
key[3] |= 0x10;
else
key[3] &= ~0x10;
if (str_x[3] & 0x08 )
key[6] |= 0x01;
else
key[6] &= ~0x01;
}
/************************************************************************/
/* */
/* Module title: compute_subkeys */
/* Module type: des subrutine */
/* */
/* Author: YXH */
/* Date: 2012-07-13 */
/* */
/* Last changed by: YXH */
/* Date: 2012-07-13 */
/* */
/* Functional Description: Computes the 16 sub keys for use in the */
/* DES algorithm */
/* */
/* input parameter 1: pointer to first byte in key string */
/* output : fills the array sub_keys[16][8] with */
/* sub keys and stores the input key in */
/* main_key[8] */
/************************************************************************/
void compute_subkeys(uint8_t *key)
{
uint8_t i, j, ikey[8], okey[8];
for (i=0; i < 8; ++i)
{
main_key[i] = key[i];
}
transpose(key, ikey, key_tr1, 56);
for (i=0; i < 16; ++i)
{
for (j=0; j < rots[i]; ++j) {rotate_l(ikey);}
transpose(ikey, okey, key_tr2, 64);
for (j=0; j < 8; ++j)
{ sub_keys[i][j] = okey[j];}
}
}
/************************************************************************/
/* */
/* Module title: f */
/* Module type: des subrutine */
/* */
/* Author: YXH */
/* Date: 2012-07-13 */
/* */
/* Last changed by: YXH */
/* Date: 2012-07-13 */
/* */
/* Functional Description: The chipher function */
/* */
/* input parameter 1: pointer to first byte in key string */
/* 2: pointer to a 32 bit input string */
/* 3: pointer to a 32 bit output string */
/************************************************************************/
void f(uint8_t *skey, uint8_t *a_str, uint8_t *x_str)
{
uint8_t e_str[8], y_str[8], z_str[8];
uint8_t k;
transpose(a_str, e_str, etr, 64);
for (k=0; k < 8; ++k)
{
y_str[k] = (e_str[k] ^ skey[k]) & 63;
z_str[k] = s[k] [y_str[k]];
}
transpose(z_str, x_str, ptr, 32);
}
//源码完毕
产品用到铁电存储,要用到5V环境,我还是选择用了FM25640C了。下面是基于新唐NUC123SeriesBSP_CMSIS_V1.01.002的测试代码,希望能抛砖引玉。谢谢。
/**************************************************************************//**
* @file fm25640c.c
* @version V1.00
* $author: yuanxihua@21cn.com
* $Date: 2013/01/03 11:33a $
* @brief NUC123 Series FM25640C Driver Sample Code
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "NUC123Series.h"
/*
_________________________________________________
| NUC123SD4AN0 FM25640C |
| |
| PC8 SS10 ----> CS |
| PC9 SPICLK1 ----> SCK |
| PC10 MISO10 <---- SO |
| PC11 MOSI10 ----> SI |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//#define FM25640C_CS PC8
#define FM25640C_SIZE 8*1024
//FM25640C命令
#define FM25640C_WREN 0x06
#define FM25640C_WRDI 0x04
#define FM25640C_RDSR 0x05ff
#define FM25640C_WRSR 0x0100
#define FM25640C_READ 0x030000FF
#define FM25640C_WRITE 0x02000000
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void FM25640C_Init(void);
void FM25640C_Write_Byte(uint32_t addr,uint8_t wrdata);
void FM25640C_Write_Status_Register(uint8_t wrdata);
uint8_t FM25640C_Read_Byte(uint32_t addr);
uint8_t FM25640C_Read_Status_Register(void);
void SPI1_Send_Data(uint32_t wrdata,uint8_t bits);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
void FM25640C_Test(void)
{
uint32_t i;
/* Configure the FM25640C */
FM25640C_Init();
while(0)
{
// SPI1_Send_Data(0x55, 8);
// SPI_SET_SS0(SPI1); SPI1_Send_Data(0x55, 8);SPI_CLR_SS0(SPI1); //写0x55测试SPI接口
// FM25640C_Write_Byte(0xCC, 0x55);
// FM25640C_Read_Byte (0xCC);
// FM25640C_Read_Status_Register();
}
FM25640C_Write_Status_Register(0x00);
printf("FM25640C_Read_Status_Register() = 0x%02x \n\r",FM25640C_Read_Status_Register());
FM25640C_Write_Byte(0xAA, 0x55);
FM25640C_Write_Byte(0x55, 0xAA);
printf("FM25640C_Read_Byte(0xAA) = 0x%02x \n\r",FM25640C_Read_Byte(0xAA));
printf("FM25640C_Read_Byte(0x55) = 0x%02x \n\r",FM25640C_Read_Byte(0x55));
while(1)
{
for(i=0;i<FM25640C_SIZE;i++)
{FM25640C_Write_Byte(i, i&0xff);}
SYS_SysTickDelay(300000);
for(i=0;i<FM25640C_SIZE;i++)
{
//for display
if((i%16)== 0){printf("\n\r%08xh:",i);}
printf(" %02x",FM25640C_Read_Byte(i));
if((i%16)==15){printf(" ;");}
//display end
}
SYS_SysTickDelay(300000);
}
}
// SPI1_Send_Data(FM25640C_WREN,8);
// SPI1_Send_Data(FM25640C_WRDI,8);
uint8_t FM25640C_Read_Byte(uint32_t addr)
{
uint32_t rddata,tmpdata=FM25640C_READ;
tmpdata |= (addr << 8);
SPI1_Send_Data(tmpdata,32);
rddata = SPI_GET_RX0_DATA(SPI1);
return (uint8_t)rddata;
}
void FM25640C_Write_Byte(uint32_t addr, uint8_t wrdata)
{
uint32_t tmpdata=FM25640C_WRITE;
SPI1_Send_Data(FM25640C_WREN,8); //中:使能写操作//Write Enable
tmpdata |= (addr << 8) + wrdata;
SPI1_Send_Data(tmpdata,32);
}
uint8_t FM25640C_Read_Status_Register(void)
{
uint32_t rddata;
SPI1_Send_Data(FM25640C_RDSR,16);
rddata = SPI_GET_RX0_DATA(SPI1);
return (uint8_t)rddata;
}
void FM25640C_Write_Status_Register(uint8_t wrdata)
{
uint16_t dat=FM25640C_WRSR | wrdata;
SPI1_Send_Data(FM25640C_WREN,8); //中:使能写操作//Write Enable
SPI1_Send_Data(dat,16);
}
void SPI1_Send_Data(uint32_t wrdata, uint8_t bits)
{
SPI1->CNTRL = (SPI1->CNTRL&0xFFFFFF07) | ((bits&0x1f) <<3);
SPI_WRITE_TX0(SPI1, wrdata); //中:待发数据//en:data waiting for sending
SPI_SET_GO(SPI1); //中:启动发送//en: Start Transfer
while(SPI_IS_BUSY(SPI1) !=0); //中:等待发送结束//en:waiting for sending finished
}
void SPI1_Init(void)
{
/* Enable IP clock */
SET_SPI1_CLKSRC(CLK_SPI1_HCLK); //En:Select SPI1 clock source
GPIO_SPI1(); //中:配置PC8~11为SPI功能//Set PC11~PC8 as SPI1 pin. PC8=SPISS10,PC9=SPICLK1,PC10=MISO10,PC11=MOSI10
DrvSPI_Init(SPI1, SPI_MASTER, SPI_TYPE0, 32);
SPI_SET_DIVIDER(SPI1, 1); //中:设置SPI的分频值//en:Set divider of SPI_CLK SPIclk = Pclk/((DIVIDER+1)*2)
SPI_SET_MSB_FIRST(SPI1); //En:MSB first
SPI_SET_SS(SPI1, SPI_SS_LOW_TRIGGER, SPI_AUTO_SS);//中:自动片选选择//en:Slave Select auto
SPI_SET_SS0(SPI1); //中:置片选有效//En:active SS1
}
void FM25640C_Init(void)
{
SPI1_Init();
}
//程序完毕。
某个朋友的项目,用到TM1668做LED显示和键盘驱动,我给他写了一个例子,现在公开给大家参考,希望有用。
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <MINI51.H>
#include "Driver\DrvSYS.h"
#include "Driver\DrvSPI.h"
#include "Driver\DrvGPIO.h"
/*
//make by yuanxihua@21cn.com
____________________________________________
| MINI51LAN TM1668 |
| |
| P04 SS ----> LSTB |
| P05 MOSI ----> LDIO |
| P06 MISO ----> LDIO |
| P07 SCLK <---> LCLK |
|___________________________________________|
*/
#define TM1668_STB E_GPC, 7 /* PC.7 */
#define TM1668_CLK E_GPC, 6 /* PC.6 */
#define TM1668_DIO E_GPA, 13 /* PA.13 */
#define DISP_DELAY 2
//0 1 2 3 4 5 6 7 8 9 A B C D E F
const unsigned char TM1668_CODE[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7F, 0x39, 0x3F, 0x79, 0x71};
const unsigned short TM1668_LINE[10]={0x200,0x300,0x380,0x3C0,0x3E0,0x3F0,0x3F8,0x3FC,0x3FE,0x3FF};
void TM1668_init(void);
void TM1668_Write_ADDR_INC(uint8_t *WrData);
void TM1668_Write_Byte(uint8_t WrData);
void TM1668_Read_KEY(uint8_t *RdData);
void TM1668_Test(void)
{
unsigned char wrbuff[14];
unsigned char rdbuff[5];
unsigned char key[7];
unsigned char led[7];
TM1668_init();
while(1)
{
// TM1668_Write_Byte(0x55);
TM1668_Read_KEY(rdbuff);
key[1] = (rdbuff[0]&0x01)?1:0;
key[2] = (rdbuff[0]&0x08)?1:0;
key[3] = (rdbuff[1]&0x01)?1:0;
key[4] = (rdbuff[1]&0x08)?1:0;
key[5] = (rdbuff[0]&0x02)?1:0;
key[6] = (rdbuff[0]&0x10)?1:0;
led[1] = key[1]?1:0;
led[2] = key[2]?1:0;
led[3] = key[3]?1:0;
led[4] = key[4]?1:0;
led[5] = key[5]?1:0;
led[6] = key[6]?1:0;
wrbuff[0] = (led[6]<<5)|(led[5]<<4)|(led[4]<<3)|(led[3]<<2)|(led[2]<<1)|(led[1]<<0);
printf("*** 9G-MINI51 V1.00 %02x...\n\r",wrbuff[0]);
TM1668_Write_ADDR_INC(wrbuff);
}
}
void TM1668_init(void)
{
/* 设置SPI I/O */
DrvGPIO_InitFunction(FUNC_SPI);
/* 设置SPI为主模式, 32-bit 传输 */
DrvSPI_Open(eDRVSPI_MASTER, eDRVSPI_TYPE1, 32);
/* 配置传输时的比特优先次序为LSB优先 */
DrvSPI_SetEndian(eDRVSPI_LSB_FIRST);
/* 关闭自动片选功能 */
DrvSPI_DisableAutoSS();
/* 设置片选信号启动电平为片选信号低电平或者下降沿启动 */
DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_ACTIVE_LOW_FALLING);
/* 设置SPI时钟速度为 12MHz */
DrvSPI_SetClockFreq(12000000, 0);
}
void TM1668_Write_Byte(uint8_t WrData)
{
uint32_t SPI_Data = WrData;
/* 设置SPI长度为8个位元 */
DrvSPI_SetBitLength(8);
/* 片选脚设为启动状态 */
DrvSPI_SetSS();
/* 传送WrData */
SPI_Data = 0x03;//Command1: 显示模式设置命令
DrvSPI_SingleWrite(&SPI_Data);
/* 等待传送退出 */
while (DrvSPI_IsBusy());
/* 片选脚设为非启动状态 */
DrvSPI_ClrSS();
}
void TM1668_Write_ADDR_INC(uint8_t *WrData)
{
uint32_t i,SPI_Data;
/* 设置SPI长度为8个位元 */
DrvSPI_SetBitLength(8);
/* 片选脚设为启动状态 */
DrvSPI_SetSS();
/* 传送WrData */
SPI_Data = 0x03;//Command1: 显示模式设置命令
DrvSPI_SingleWrite(&SPI_Data);
/* 等待传送退出 */
while (DrvSPI_IsBusy());
/* 片选脚设为非启动状态 */
DrvSPI_ClrSS();
/* 片选脚设为启动状态 */
DrvSPI_SetSS();
/* 传送WrData */
SPI_Data = 0x40;//Command2: 数据读写设置命令
DrvSPI_SingleWrite(&SPI_Data);
/* 等待传送退出 */
while (DrvSPI_IsBusy());
/* 片选脚设为非启动状态 */
DrvSPI_ClrSS();
/* 片选脚设为启动状态 */
DrvSPI_SetSS();
/* 传送WrData */
SPI_Data = 0xC0;//Command3: 显示地址设置命令
DrvSPI_SingleWrite(&SPI_Data);
/* 等待传送退出 */
while (DrvSPI_IsBusy());
for(i=0;i<14;i++)//Data1~n: 显示数据,以Command3指定的地址为起始地址(最多14 bytes)
{
/* 传送WrData */
SPI_Data = WrData;
DrvSPI_SingleWrite(&SPI_Data);
/* 等待传送退出 */
while (DrvSPI_IsBusy());
}
/* 片选脚设为启动状态 */
DrvSPI_SetSS();
/* 传送WrData */
SPI_Data = 0x88;//Command4: 显示控制命令
DrvSPI_SingleWrite(&SPI_Data);
/* 等待传送退出 */
while (DrvSPI_IsBusy());
/* 片选脚设为非启动状态 */
DrvSPI_ClrSS();
}
void TM1668_Read_KEY(uint8_t *RdData)
{
uint32_t i,SPI_Data;
/* 设置SPI长度为8个位元 */
DrvSPI_SetBitLength(8);
/* 片选脚设为启动状态 */
DrvSPI_SetSS();
/* 传送WrData */
SPI_Data = 0x42;//Command4: 显示控制命令
DrvSPI_SingleWrite(&SPI_Data);
/* 等待传送退出 */
while (DrvSPI_IsBusy());
for (i = 0; i < 5; i++)
{
/* 读取资料 */
SPI_Data = 0xffffffff;
DrvSPI_SingleWrite(&SPI_Data);
/* 等待传送退出 */
while (DrvSPI_IsBusy());
/* 从Rx寄存器内读取资料 */
DrvSPI_DumpRxRegister(&SPI_Data, 1);
RdData = (uint8_t) SPI_Data;
}
/* 片选脚设为非启动状态 */
DrvSPI_ClrSS();
}
--代码完毕。
基于新唐M0的XXTEA加密解密算法源码
/*---------------------------------------------------------------------------------------------------------
在数据的加解密领域,算法分为对称密钥与非对称密钥两种。对称密钥与非对称密钥由于各自的特点,所应用的领域是不尽相
同的。对称密钥加密算法由于其速度快,一般用于整体数据的加密,而非对称密钥加密算法的安全性能佳,在数字签名领域得到广
泛的应用。
TEA算法是由剑桥大学计算机实验室的David Wheeler和Roger Needham于1994年发明,TEA是Tiny Encryption Algorithm的缩写,
以加密解密速度快,实现简单著称。TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,
推荐的迭代轮数是64轮,最少32轮。为解决TEA算法密钥表攻击的问题,TEA算法先后经历了几次改进,从XTEA到BLOCK TEA,直至
最新的XXTEA。XTEA也称做TEAN,它使用与TEA相同的简单运算,但四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。
Block TEA算法可以对32位的任意整数倍长度的变量块进行加解密的操作,该算法将XTEA轮循函数依次应用于块中的每个字,并且
将它附加于被应用字的邻字。XXTEA使用跟Block TEA相似的结构,但在处理块中每个字时利用了相邻字,且用拥有两个输入量的
MX函数代替了XTEA轮循函数。本文所描述的安全机制采用的加密算法就是TEA算法中安全性能最佳的改进版本-XXTEA算法。
XXTEA算法的结构非常简单,只需要执行加法、异或和寄存的硬件即可,且软件实现的代码非常短小,具有可移植性,非常适合
嵌入式系统应用。由于XXTEA算法的以上优点,可以很好地应用于嵌入式RFID系统当中。
---------------------------------------------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#define MX (z>>5^y<<2) + (y>>3^z<<4)^(sum^y) + (k[p&3^e]^z)
//注意:delta的取值是随机的,但是为了避免不良的取值,采取的是
//黄金分割数(根号5-2)/2与2的32次方的乘积。为0x9e3779b9。
//在解密中,sum=delta×round,如:delta×32=13C6EF3720
//v表示为运算的长整型数据的首地址
//k为长整型的密钥的首地址
//n表示以32bit为基本单位的要运算的组元个数,正表示加密,负表示解密
long xxtea(long* v, long n, long* k);
long xxtea(long* v, long n, long* k)
{
unsigned long z=v[n-1], y=v[0], sum=0, e, DELTA=0x9e3779b9;
long p, q;
if(n > 1)
{/* 加密过程 */
q = 6 + 52/n;
while(q-- > 0)
{
sum += DELTA; e = (sum >> 2) & 3;
for (p=0; p<n-1; p++) y = v[p+1], z = v[p] += MX;
y = v[0]; z = v[n-1] += MX;
}
return 0;
}
else
if(n < -1)
{/* 解密过程 */
n = -n; q = 6 + 52/n; sum = q*DELTA;
while(sum != 0)
{
e = (sum >> 2) & 3;
for (p=n-1; p>0; p--) z = v[p-1], y = v[p] -= MX;
z = v[n-1]; y = v[0] -= MX; sum -= DELTA;
}
return 0;
}
return 1;
}
void xxtea_test(void)
{
unsigned long buff[4];
unsigned long test[4]={0x11223344,0x55667788,0x99AABBCC,0xDDEEFF00};
unsigned long keys[4]={0x12345678,0x9ABCDEF0,0x12345678,0x9ABCDEF0};
while(1)
{
printf("\n\rxxtea test: \n\r");
memcpy(buff,test,16); printf("0x%08x,0x%08x,0x%08x,0x%08x\n\r",buff[0],buff[1],buff[2],buff[3]);
xxtea( buff, 4,keys); printf("0x%08x,0x%08x,0x%08x,0x%08x\n\r",buff[0],buff[1],buff[2],buff[3]);
xxtea( buff,-4,keys); printf("0x%08x,0x%08x,0x%08x,0x%08x\n\r",buff[0],buff[1],buff[2],buff[3]);
while(1);
}
}
//--缥缈九哥收集整理
一,下载安装测试arm-none-eabi-gcc编译工具链
1,查看arm-none-eabi-gcc编译工具版本
打开网页:https://sourcery.mentor.com/GNUT ... db0be6eb3fb4a618248
有关详细的工具手册。
2,下载arm-none-eabi-gcc编译工具链
打开网页:https://sourcery.mentor.com/GNUToolchain/release2322
下载文件:arm-2012.09-63-arm-none-eabi-i686-mingw32.tar.bz2
详细连接:https://sourcery.mentor.com/GNUT ... 686-mingw32.tar.bz2
3,安装arm-none-eabi-gcc编译工具链
把arm-2012.09-63-arm-none-eabi-i686-mingw32.tar.bz2解压到目录:C:\Sourcery\
或者下载:arm-2012.09-63-arm-none-eabi.exe并且安装(详细连接:https://sourcery.mentor.com/GNUT ... 3-arm-none-eabi.exe)
4,配置系统环境变量
右击“我的电脑”->“属性”->“高级”->“环境变量”->“系统变量”选择“Path”后点击“编辑”出现“编辑系统变量”
后在“变量值”后增加“;C:\Sourcery\arm-2012.09\bin;C:\Sourcery\arm-2012.09\arm-none-eabi\bin”后连续按三次“确定”。
4,测试arm-none-eabi-gcc编译工具链
在开始菜单中打开“运行”,执行cmd.exe,然后在里面执行命令:arm-none-eabi-gcc -v
然后查看版本是不是:gcc version 4.7.2 (Sourcery CodeBench Lite 2012.09-63)
二,建立MDK环境
1,在“D:\works\9G-CM0\HID\prj”下新建MDK空工程“hid.uvproj”,并且在“prj”下建立“obj”和“lst”文件夹,
在“D:\works\9G-CM0\HID”下建立“inc”和“src”目录;
2,点开“project->manage”下的“Components,Environment and Books”,中间的一页“Folders/Extensions”,
勾选“Use GCC”,并且“GNU-Tool-Prefix”用“arm-none-eabi-”,“GNU-Tool folder”用“C:\Sourcery\arm-2012.09”
3,配置工程“Options”,obj文件放到“prj\obj”,lst文件放到“prj\lst”,在“User”的编译结束
后执行“arm-none-eabi-size !L.elf”来生成的ELF目标码的大小提示;
4,在“CC”页面勾选“Compile Thumb Code”,“Optimiation”用“Level 2 (speed)”,“Warning”用“Level 1”,
在“Misc Controls”用“-pipe -ffunction-sections -fdata-sections -fshort-wchar -gstrict-dwarf -finline-limit=100000000”
5,在“Linker”页面的选择不用系统库及启动文件,连接脚本用“.\nuc122_usb.ld”,“Misc Control” 用:
“-Wl,--relax -Wl,--gc-sections -Wl,-z -Wl,max-page-size=0”
6,然后在工程树中的“Target1”下面创建文件组“Configuration”“C++ Source”“C Source”和“Document”
右击“C++ Source”修改它的“Options”->“CC”的“Include Paths”用“..\inc”,而“Misc Controls”为:
“-std=c++11 -fno-rtti -fno-exceptions -Wno-pmf-conversions”
7,需要下载整个工程源码的可以与我联系。
三,测试HID通信
1,打开“Bus Hound 6.01”软件,选择“Devices”页面,勾选上“Auto select hot plugged devices”,然后把HID工程编译下载到目标板
NUC123-TINY后运行,听到电脑“冬叮”一声,会自动选择上要监测的“(37)USB人体学输入设备”和“(38)HID-compliant device”;
2,把“(38)HID-compliant device”前的勾去掉,双击“(37)USB人体学输入设备”出现命令发送窗口,选择到“USB”页,点选端点中的
“interput Out”,“data length”填写“64”,再在下面的“Hex Bytes”中填入64个字节的“55”;
3,在“Bus Hound 6.01”的“Capture”页面的右下角点击上“Run”,再到刚才的“USB”命令页面上面的“Run”按钮,就可以把64个
BYTE的0x55发送给HID从设备;
4,在“Bus Hound 6.01”的“Capture”页面的数据窗口,你就能看到USB发送了64个0x55并且接收到64个0xaa。测试正确。完毕。
--感谢lee老师(j.y.lee@yeah.net)的指导及帮助
代码可以到这个地址下载:http://bbs.21ic.com/icview-413678-1-1.html
利用OllyDbg和Enigma Virtual Box对WINDOWS下的MinGW4.9.1的Qt-5.4.0程序打包方法
1,下载 odbg201.zip
打开网页:http://www.ollydbg.de/version2.html
下载文件:odbg201.zip
详细连接:http://www.ollydbg.de/odbg201.zip
2,下载 Enigma Virtual Box
打开网页:http://enigmaprotector.com/en/downloads.html
下载文件:enigmavb.exe
详细连接:http://enigmaprotector.com/assets/files/enigmavb.exe
安装目录:C:\Program Files (x86)\Enigma Virtual Box
3,查看程序依赖库
在Qt Creator (Community)中用Realse打开项目setram.exe执行
打开 odbg201.zip里的ollydbg.exe软件后,用File->Attach菜单 然后选择到程序setram.exe
执行 View->Executable Modules菜单,找到下列动态链接库:
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\icudt53.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\icuin53.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\icuuc53.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\libgcc_s_dw2-1.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\libstdc++-6.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\libwinpthread-1.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\Qt5Core.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\Qt5Gui.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\Qt5Widgets.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\plugins\platforms\qwindows.dll
C:\Qt\Qt5.4.0\5.4\mingw491_32\plugins\platforms\qminimal.dll
4,打包程序
打开软件Enigma Virtual Box。新建工程并找到要打包的exe路径及要打包生成的exe的路径
在下面文件列表中增加上面的每个DLL文件
icudt53.dll,icuin53.dll,icuuc53.dll
libgcc_s_dw2-1.dll,libstdc++-6.dll,libwinpthread-1.dll
Qt5Core.dll ,Qt5Gui.dll,Qt5Widgets.dll
及文件夹下的platforms\qwindows.dll和platforms\qminimal.dll文件
然后在右下角“文件选项”中选择上“压缩文件”,
最后执行“执行封包”并运行即可退出大功告成。
基于QT 5.8.0 for Android 的 Windows 10 开发环境搭建
一、下载软件
1.jdk: jdk-8u121-windows-i586.exe
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-windows-i586.exe
2.sdk: android-studio-bundle-145.3537739-windows.exe
https://developer.android.com/studio/index.html
https://dl.google.com/dl/android/studio/install/2.2.3.0/android-studio-bundle-145.3537739-windows.exe
3.qte: qt-opensource-windows-x86-android-5.8.0-rc_699.exe
http://download.qt.io/development_releases/qt/5.8/5.8.0-rc/
http://download.qt.io/development_releases/qt/5.8/5.8.0-rc/qt-opensource-windows-x86-android-5.8.0-rc_699.exe
4.ndk: android-ndk-r13b-windows-x86.zip
https://developer.android.com/ndk/downloads/index.html
https://dl.google.com/android/repository/android-ndk-r13b-windows-x86.zip
5.ant: apache-ant-1.10.0-bin.zip
http://ant.apache.org/bindownload.cgi
http://mirror.bit.edu.cn/apache//ant/binaries/apache-ant-1.10.0-bin.zip
二、安装软件
1,把 jdk-8u121-windows-i586.exe 安装到 C:\Program Files (x86)\Java\jdk1.8.0_121\ 和 C:\Program Files (x86)\Java\jre1.8.0_121 下面;
2,把 android-studio-bundle-145.3537739-windows.exe 安装到 C:\Program Files\Android\Android Studio 和 C:\Users\yuanxihua\AppData\Local\Android\sdk 下面;
3,把 qt-opensource-windows-x86-android-5.8.0-rc_699 的全部组件安装到 C:\Qt\Qt5.8.0 下面;
4,把 android-ndk-r13b-windows-x86.zip 解压到 C:\Qt\android-ndk-r13b 下面;
5,把 apache-ant-1.10.0-bin.zip 解压到 C:\Qt\apache-ant-1.10.0 下面;
三、开发项目
1,配置环境
打开 C:\Qt\Qt5.8.0\Tools\QtCreator\bin 下面的 qtcreator.exe,在 “工具”->“选项”->“设备”里面选择“andorid”的配置填入上面的软件
JDK、SDK、NDK、ANT的路径:C:\Program Files (x86)\Java\jdk1.8.0_121 和 C:\Users\yuanxihua\AppData\Local\Android\sdk1 和 C:\Qt\android-ndk-r13b
及 C:\Qt\apache-ant-1.10.0\bin\ant.bat
2,建立工程
A,打开 qtcreator.exe,在“文件”->“新建文件或项目”选择“所有模板”->Application->Qt Widgets Application
然后点击“Choose…”,选择项目路径“D:\works\TEST\qttest”和项目名称“test”,勾选“Android for armeabi-v7a(GCC 4.9 ,Qt 5.8.0)”
和“Desktop Qt 5.8.0 MinGW 32bit”两个模板;
B,一路直接按下去就建立好测试项目,选择项目里面的“Android for armeabi-v7a(GCC 4.9 ,Qt 5.8.0)”下的构建,然在“构建”菜单下选择
“选择重新构建项目‘TEST’”进行编译,就会在
“D:\works\TEST\qttest\build-test-Android_for_armeabi_v7a_GCC_4_9_Qt_5_8_0-Release\android-build\bin”下生成“QtApp-debug.apk”
和“QtApp-debug-unaligned.apk”文件;
C,把生成的APK文件通过数据线下载到安卓手机就能安装测试使用。
基于ARM-MDK+JLINK开发环境的新唐N32905的裸奔调试模板-缥缈九哥移植整理
N32905是一个主频高达240MHZ(@2.0V)的ARM926EJ-S核CPU,它内置MJPEG编解码器(VGA 30FPS),CMOS接口(3M),
16Mbitx16 DDR(-20°C~85°C)内存,支持USB2.0 HS从接口,USB1.1 FS主设备口,32通道声音处理单元SPU,
10位麦克风放大ADC, 16位立体声耳机DAC,和TV输出编码器,内置支持FlashLite(FL3.1.7)的2D BitBLT加速器。
支持D1 (720x480)的TV视频输出,支持XVGA(1,024x768)的TFT LCD屏。14X14X1.4MM大小和0.4MM 脚距的S2LQFP-128
小MCP封装。
它的极高集成度使之仅仅外置一个简单的SPI的FLASH及相关的电源和时钟就可以独立形成最小系统。它可以仅用
双面板设计来降低整机成本及生产工艺难度。它可以用于多媒体处理电子书,学习机,玩具,人机界面,广告指示牌,
WIFI透传模块,IP摄像头,人机界面,二维码识别及机器视觉的应用。
一,N32905的物理寻址空间:
IBR: 0xFFFF_0000 - 0xFFFF_FFFF
保留: 0xFF00_2000 - 0xFFFE_FFFF
SRAM: 0xFF00_0000 - 0xFF00_1FFF
保留: 0xC000_0000 - 0xFEFF_FFFF
APB: 0xB800_0000 - 0xBFFF_FFFF
AHB: 0xB000_0000 - 0xB7FF_FFFF
SSDRAM: 0x8000_0000 - 0xAFFF_FFFF (SDRAM的影射空间)
保留: 0x4000_0000 - 0x7FFF_FFFF
SDRAM: 0x0000_0000 - 0x3FFF_FFFF
二,N32905的内置IBR启动配置:
ND1-0: IBR Boot Mode: 10=Recover; 11=Normal;
ND3-2: Boot crystal : 10=12MHz; 11=27MHz;
others 保留。
三,N32905的内置IBR引导顺序:
1,正常Normal模式串口信息:
Init RTC....OK
DDR size: 32MB
SD Port0 Booting Fail - No/Bad Card Insert
NAND Booting (2K-page 4 Address Cycle) Fail - Not for Booting
SPI Booting Fail - No Check ID
SD Port1 Booting Fail - No/Bad Card Insert
USB Booting
2,修复Recover模式串口信息:
Init RTC....OK
DDR size: 32MB
USB Booting
四,N32905的NANDFLASH配置:
LVDATA[6]: 0=EF((Error Free) NAND; 1=Raw NAND;
LVDATA[5:4]: 0=2K,1=4K,2=8K page size; 3=Ignore NAND;
ND7: 0=4 address cycle; 1=5 address cycle;
ND6: 保留。
ND5-4: 0=SDRAM; 1=mDDR; 2=DDR2; 3=DDR;
五,N32905的物理器件ID:
CHIPID: 0xFA_5C30 ,位于0xB0000000地址
六,9GLoader的简单程序模板
本程序的串口驱动及头文件移植自新唐的ADS环境的裸奔Non-OS代码包的Loader\NandLoader例子。在建立项目时选择AT91SAM9260及它的启动代码,然后去掉9260的CPU的硬件初始化部分,在MDK的工程配置的执行地址是:0x8000,连接脚本SCT文件用MDK默认产生的,详细可以查看源码包。它能通过JLINK直接下载到CPU里调试,主要是依靠初始化脚本:9G-N32905\cfg\SDRAM.ini进行SDRAM,PLL的初始化及下载AXF文件到SDRAM的8000的执行地址里进行调试。
附件代码: http://bbs.21ic.com/forum.php?mod=attachment&aid=MTczNTE2fGZjMTJhNWU3fDE0NjA5NTEyNDJ8NTA1NzExfDU0MjkyOA%3D%3D
( 注:AXF文件是与ELF相兼容的一种调试文件格式,最前面的0-0X33是文件头;接着后面0x34开始就是BIN内容;
再后面是调试信息)
//SDRAM.ini
/******************************************************************************/
/* Dbg_RAM.ini: Initialization Script for Debugging in SDRAM */
/******************************************************************************/
/* This file is part of the uVision/ARM development tools. */
/* Copyright (c) 2011 Keil Software. All rights reserved. */
/* This software may only be used under the terms of a valid, current, */
/* end user licence from KEIL for a compatible version of KEIL software */
/* development tools. Nothing else gives you the right to use this software. */
/******************************************************************************/
DEFINE INT Entry;
DEFINE LONG GCR_BA;
DEFINE LONG CLK_BA;
DEFINE LONG SDIC_BA;
DEFINE LONG GP_BA;
Entry = 0x00008000;
GCR_BA = 0xB0000000;
CLK_BA = 0xB0000200;
SDIC_BA = 0xB0003000;
GP_BA = 0xB8001000;
FUNC void Clock_Setup (void)
{
}
FUNC void SDRAM_Setup(void)
{
_WDWORD(0xb0003000, 0x00130456); // SDOPM Init DDR
_WDWORD(0xb0003030, 0x00001010); // DQSODS
_WDWORD(0xb0003010, 0x00000005); // SDSIZE0
_WDWORD(0xb0003004, 0x00000021); // SDCMD
_WDWORD(0xb0003004, 0x00000023); // SDCMD
_WDWORD(0xb0003004, 0x00000027); // SDCMD
_WDWORD(0xb000301C, 0x00001002); // SDEMR
_WDWORD(0xb0003018, 0x00000122); // SDMR
_WDWORD(0xb0003004, 0x00000027); // SDCMD
_WDWORD(0xb0003004, 0x0000002B); // SDCMD
_WDWORD(0xb0003004, 0x0000002B); // SDCMD
_WDWORD(0xb0003018, 0x00000022); // SDMR
_WDWORD(0xb0003004, 0x00000020); // SDCMD
_WDWORD(0xb0003034, 0x00AAAA00); // CKDQSDS
_WDWORD(0xb0003008, 0x0000805A); // SDREF
_WDWORD(0xb00000A0, 0x00000000); // MISCPCR
_WDWORD(0xb0000224, 0x0000447E); // UPLLCON PLL=192MHz
_WDWORD(0xb000020C, 0x00000018); // CLKDIV0 Divider
_WDWORD(0xb000021C, 0x00000000); // CLKDIV4
_WDWORD(0xb0003028, 0x094E7549); // SDTIME Sdram Timing
_sleep_(10);
_WDWORD(0xb8001010, 0x00000008); // GPIOB_OMD PB3=OUTPUT
_WDWORD(0xb8001018, 0x00000008); // GPIOB_DOUT PB3=HIGH
_sleep_(10);
}
FUNC void Remap (void)
{
}
FUNC void Download (void)
{
exec("load %L incremental");
}
FUNC void PC_Setup (void)
{
PC = Entry;
}
FUNC void GoMain (void)
{
exec("g,main");
}
//Clock_Setup();
SDRAM_Setup();
//Remap();
Download();
PC_Setup();
GoMain();
//main.c文件
#include <stdio.h>
#include "wblib.h"
#define DebugCom 0x100
void Delay(UINT32 k)
{
volatile int j=k*36000;
while(j--);
}
void InitDebugCom(void)
{
WB_UART_T *uart;
//Nornal Speed UART
outp32(REG_GPAFUN, inp32(REG_GPAFUN) | (MF_GPA11 | MF_GPA10));
outp32(REG_APBCLK, inp32(REG_APBCLK) | UART1_CKE);
uart->uiFreq = (((inp32(REG_CHIPCFG)&0xC)==0x8)?12000:27000)*1000; /*Use external clock*/
uart->uiBaudrate = 115200;
uart->uiDataBits = WB_DATA_BITS_8;
uart->uiStopBits = WB_STOP_BITS_1;
uart->uiParity = WB_PARITY_NONE;
uart->uiRxTriggerLevel = LEVEL_1_BYTE;
/* Reset the TX/RX FIFOs */
outpw(REG_UART_FCR+DebugCom, 0x07);
/* Setup baud rate */
outpw(REG_UART_BAUD+DebugCom, ((0x30<<24)|((uart->uiFreq / uart->uiBaudrate)-2)));
/* Set the modem control register. Set DTR, RTS to output to LOW,
and set INT output pin to normal operating mode */
//outpb(UART_MCR, (WB_DTR_Low | WB_RTS_Low | WB_MODEM_En));
/* Setup parity, data bits, and stop bits */
outpw(REG_UART_LCR+DebugCom,(uart->uiParity | uart->uiDataBits | uart->uiStopBits));
/* Timeout if more than ??? bits xfer time */
outpw(REG_UART_TOR+DebugCom, 0x80+0x20);
/* Setup Fifo trigger level and enable FIFO */
outpw(REG_UART_FCR+DebugCom, uart->uiRxTriggerLevel|0x01);
}
int fputc(int ch, FILE *f)
{
/* Wait until the transmitter buffer is empty */
while (!(inpw(REG_UART_FSR+DebugCom)&0x400000));
/* Transmit the character */
outpb(REG_UART_THR+DebugCom, ch);
return ch;
}
int fgetc(FILE *f)
{
while((inpw(REG_UART_ISR+DebugCom)&0x01)==0);
return(inpb(REG_UART_RBR+DebugCom));
}
int main(void)
{
int i=0;
InitDebugCom();
printf("\n\r\n\r");
printf("*** 9G-N32905 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** 9G-N32905 V1.00 Running ...\n\r\n\r");
outp32(REG_GPIOC_OMD,0x0000FFFF);
outp32(REG_GPIOE_OMD,0x0000FFFF);
while(1)
{
printf("run times %d\n\r",i++);
outp32(REG_GPIOC_DOUT,0x0000FFFF);
outp32(REG_GPIOE_DOUT,0x0000FFFF);
Delay(500);
outp32(REG_GPIOC_DOUT,0x00000000);
outp32(REG_GPIOE_DOUT,0x00000000);
Delay(500);
}
}
基于新唐M0516的MDK+GCC的编译环境建立与LOOK应用开发
一,下载安装MDK+GCC编译环境
1,从KEIL主页上下载MDK471A的:http://www.keil.com/fid/edz9p7w1 ... es/eval/mdk471a.exe
并且默认安装到C盘的:C:\Keil,自行和谐处理。
2,从https://sourcery.mentor.com/GNUToolchain/release2449上面下载Sourcery CodeBench Lite Edition for ARM EABI
https://sourcery.mentor.com/GNUT ... 3-arm-none-eabi.exe
并且默认安装到C:\Program Files\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI
修改XP下的系统环境变量最前添加:C:\Program Files\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI\bin;
3,在新唐主页上下载安装NU-LINK驱动和ICP软件,并安装到C:\Keil里面。
4,在新唐主页上下载数据手册,BSP包文件。
二,建立“Keil uVision4”工程项目
1,在“D:\works\9G-CM0\”下建立“9G-LOOK”目录,再在“9G-LOOK”目录下建立“look”“src”“inc”“prj”目录;
在“prj”下再建立“debug\obj”“debug\lst”“release\obj”“release\lst”目录;
2,打开桌面的“Keil uVision4”,点开“project”->“New uVision project”选择路径到“D:\works\9G-CM0\9G-LOOK\prj”
建立“9g-look”工程;
3,在接着的“select a CPU Data Base File”上选择“NuMicro Cortex M0 Database”数据库;在里面的“Nuvoton”下拉中选择
器件中选择“M0516LBN”后点击OK并选择“否”禁止拷贝启动代码文件;
4,在“Keil uVision4”窗口的左面的“project”窗口里的“Target 1”改成成“debug”,下面的“Source Group 1”改名成“look”;
并且在“project”窗口里的“debug”上右击“Add Group”建立一个空文件夹,并改名成“src”;
5,点击“Keil uVision4”窗口菜单的“Targets Options”,打开项目配置窗口的“Output”,点开“Select Folder for Objects...”
选择到“D:\works\9G-CM0\9G-LOOK\prj\debug\obj\”并勾选上“Create HEX File”;
6, 打开项目配置窗口的“Listing”,点开“Select Folder for Listing...”选择到“D:\works\9G-CM0\9G-LOOK\prj\debug\lst\”;并且
把下面的所有选项全部勾上;
7,在项目配置窗口的“User”窗口的编译成功能运行的命令第一行,第二行勾选并分别填入命令:
“arm-none-eabi-objcopy.exe -O binary -j .text .\debug\obj\!L.elf .\debug\obj\!L.bin”
“arm-none-eabi-size.exe !L.elf”
8,在项目配置窗口“CC”窗口,填上宏定义define:“SEMIHOSTING”,包含路径“..\src;..\inc;..\look\include”
去掉“enable APCS...”和 “Support Calls Between ....”选择项并勾选上“Compile Thumb code”和真入编译器编译控制参数
“-pipe -ffunction-sections -fdata-sections -gstrict-dwarf -finline-limit=100000000”
9,在项目配置窗口的“Linker”窗口里,勾选择上不用标准启动文件和库文件,填入连接脚本:“.\m051.ld”,LOOK的路径
“..\look\lib” 和连接控制参数“-Wl,--relax -Wl,--gc-sections -Wl,-z -Wl,max-page-size=0”
10,在项目配置窗口的“Debug”和“Utilities”窗口里都选择上仿真下载器“Nuvoton Nu-Link Debugger”并勾选择上“Run to main{}”
和“Update Target Before Debugging”。
11,在“project”->“Manage”->“Compoments...”的“Folders..”里面选择GCC做编译器前缀是“arm-none-eabi-”
编译器的路径为:“C:\Program Files\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI\”
12,在“project”->“Manage”->“Compoments...”的“Project...”里面增加一个“release”版本的工程,在这个工程“Targets Options”的
“Output”和“Listing”指定目录到“release\obj”“release\lst”目录;“CC”里的宏定义“SEMIHOSTING”去掉;
13,右击在“Keil uVision4”窗口的左面的“project”下的“src”文件夹,选择“options”里的“CC”添加上编译选项
“-std=c++11 -fno-rtti -fno-exceptions -Wno-pmf-conversions”
三,组织“Keil uVision4”工程项目
1,把“j.y.lee@yeah.net”老师的“look”里的“include”“lib”“look-rm.chm”全部复制到“D:\works\9G-CM0\9G-LOOK\look” 目录;
把“.\m051.ld”复制到“D:\works\9G-CM0\9G-LOOK\prj”下,把“numicro”放到“INC”目录;
2,把“idle.cpp”“idle.h”“init.cpp”“scheduler.cpp”“systick.cpp”“vector.cpp”“semi.cpp”“semi.h”全部复制到
“D:\works\9G-CM0\9G-LOOK\src”目录;
3,把文件“look.h”和“m0516lan.h”放到目录“D:\works\9G-CM0\9G-LOOK\inc”中,并且把上面的CPP文件添加到工程“Project”
下面的“Debug”下的“src”中,把“look.h”“attribute.h”“sfr”“m0516lan.h”放到“D:\works\9G-CM0\9G-LOOK\inc”中。
4,把“redapricot”和“utils”文件夹及“sfr”文件复制到“D:\works\9G-CM0\9G-LOOK\inc”中;在D:\works\9G-CM0\9G-LOOK\src
建立“led.h”和“led.cpp”文件,编写LED闪烁代码并添加到项目工程的src中。
四,编译及运行工程项目
1,按“F7”进去项目工程的编译,“CTRL+F5”进行DEBUG下载;“F5”全速运行项目即可看到LED在秒闪烁。
2,项目工程源码程序,请到下面网址上下载:http://bbs.21ic.com/icview-554086-1-1.html
/******************************************************************************
* @file ir.c
* @brief The Driver code for VS1838A with MINI54FDE
* @version 1.0.0
* @date 22, August, 2014
*
* @note
* Copyright (C) 2000-2014 PM9GZY by yuanxihua@21cn.com. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "Mini51Series.h"
/*
红外线编码是数据传输和家用电器遥控常用的一种通讯方法,
其实质是一种脉宽调制的串行通讯。
家电遥控中常用的红外线编码电路有μPD6121G型HT622型和7461型等。
μPD6121G遥控器的红外遥控系统的编码格式
二进制“0”由0.56ms的间隔加0.565ms的脉冲表示;
二进制“1”由0.56ms的间隔加1.685ms的脉冲表示。
每次发送的32位二进制码可分成两部分,其中
前16位是遥控器辨识码,主要用于区别不同遥控器,
后16位是操作码。这两个部分的后8位都是前8位的反码,用作数据校验。
每帧数据以9ms的间隔加4.5ms的脉冲作为数据头header信号。
当键盘按下长达108ms时,发射端开始发送连续信号,与单次发送一样,
只是数据头header信号是由9ms的间隔加2.5ms的脉冲组成的。
*/
/*
_________________________________________________
| MINI54FDE LED |
| |
| P25 <--- VS1838A |
| P24 ---> RED-LED |
|_______________________________________________|
*/
#pragma anon_unions
#define TIME_INTERRUPT_PERIOD_US 128 //定时中断时间,用于计算下降沿到下降沿之间时间,也就是一个脉冲+间隙的时间
#define TIME_INFRARED_HEAD_US 13500 //数据头的时间:TH=9+4.5=13.5ms
#define TIME_INFRARED_REPEAT_US 11500 //当键盘按下长达108ms时,发送连续信号的数据头的时间:TH=9+2.5=11.5ms
#define TIME_INFRARED_ZERO_US 1125 //数据“0”的时间:T0=0.565+0.56=1.125ms
#define TIME_INFRARED_ONE_US 2245 //数据“1”的时间:T1=1.685+0.56=2.245ms
typedef enum {IDLE=1,HEAD,DATA} irstatus_t;
typedef union {uint32_t data;struct {uint8_t data0;uint8_t data1;uint16_t address;};}irdata_t;
irdata_t ir;
uint32_t irticks=0,ircount=0,ledcount=0;
irstatus_t irwork=IDLE;
uint8_t disp_flag=0;
// The Timer1 default IRQ, declared in startup_Mini51.s.
void TMR1_IRQHandler(void)
{
irticks++;ledcount++;
TIMER_ClearIntFlag(TIMER1);
}
// The Port2/Port3/Port4 default IRQ, declared in startup_Mini51.s.
void GPIO234_IRQHandler(void)
{
uint8_t irdata;
if (P2->ISRC & BIT5)
{ /* To check if P2.5 interrupt occurred */
switch(irwork)
{
case IDLE: irwork=HEAD;
break;
case HEAD: irwork=(irticks>((TIME_INFRARED_HEAD_US+TIME_INFRARED_REPEAT_US)/2)/TIME_INTERRUPT_PERIOD_US)?DATA:IDLE;
ir.data=0;ircount=0;
break;
case DATA: irdata=(irticks>((TIME_INFRARED_ZERO_US+TIME_INFRARED_ONE_US )/2)/TIME_INTERRUPT_PERIOD_US)?1:0;
ir.data<<=1;ir.data|=irdata;ircount++;
if(ircount>=32){irwork=IDLE;disp_flag=1;}
break;
}
irticks=0; P2->ISRC = BIT5;
}else
{ /* Un-expected interrupt. Just clear all PORT2, PORT3 and PORT4 interrupts */
P2->ISRC = P2->ISRC; P3->ISRC = P3->ISRC; P4->ISRC = P4->ISRC;
printf("Un-expected interrupts. \n\r");
}
}
void IR_test(void)
{
/*Configure P24 for LED control */
GPIO_SetMode(P2, BIT4, GPIO_PMD_OUTPUT);
/* Configure P2.5 as Quasi-bidirection mode and enable interrupt by falling edge trigger */
GPIO_SetMode(P2, BIT5, GPIO_PMD_QUASI);
GPIO_EnableInt(P2, 5, GPIO_INT_FALLING);
NVIC_EnableIRQ(GPIO234_IRQn);
// Enable IP clock
CLK_EnableModuleClock(TMR1_MODULE);
// Select Timer 1 clock source from internal 22.1184MHz RC clock.
CLK_SetModuleClock(TMR1_MODULE,CLK_CLKSEL1_TMR1_S_IRC22M,1);
// configure timer to operate in specified mode.
TIMER_Open(TIMER1, TIMER_PERIODIC_MODE, 7812); //7.8125K = 0.128MS = 128US
// start Timer counting
TIMER_Start(TIMER1);
// enable the Timer time-out interrupt function.
TIMER_EnableInt(TIMER1);
// Enable timer interrupt
NVIC_EnableIRQ(TMR1_IRQn);
while(1)
{
if(disp_flag)
{
printf("ir.data=0x%x, ADDR=%04x DATA1=%02x /DATA1=%02x DATA0=%02x \n\r",
ir.data,ir.address,ir.data1,0xff-ir.data1,ir.data0);
if((0xff-ir.data0)==ir.data1){P24^=1;}
disp_flag=0;
}
}
}
//SPI的时钟定为2.5MHZ,也就是400NS,一个数据位用3位SPI波形来表示;
//那么就把一个数据字节扩展成了24位的SPI波形字长;
//把逻辑0转化成二进制100就是0x04,就是高400nS,低800nS;
//把逻辑1转化成二进制110就是0x06,就是高800nS,低400nS;
//这样就能用SPI的MOSI发数据来驱动TM1812的DIN。
源码:
/*---------------------------------------------------------------------------------------------------------*/
/* @file tm1812.c */
/* @version V1.00 */
/* $Date: 15/07/01 11:44a $ */
/* @brief M051 Series UART for M35 GPRS Sample Code */
/* Copyright(c) PM9GZY Technology Corp. yuanxihua@21cn.com. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
#include "main.h"
/* M0516LBN MOSI --> TM1812 DIN */
/*
逻辑0 高电平时间 350-450ns 低电平时间 800-900ns
逻辑1 高电平时间 700-999ns 低电平时间 250-550ns
位逻辑 低电平时间 8-24us
逻辑0 高400NS 低800NS
逻辑1 高800NS 低400NS
复位 低2000NS
*/
/* Function prototype declaration */
void SPI0_Init(void);
void spi0_write(uint32_t word)
{
// while(SPI_GET_TX_FIFO_FULL_FLAG(SPI0));
/* Write to TX register */
SPI_WRITE_TX0(SPI0, word);
/* Trigger SPI data transfer */
SPI_TRIGGER(SPI0);
/* Check SPI0 busy status */
while(SPI_IS_BUSY(SPI0));
/* Read received data */
// tmp = SPI_READ_RX0(SPI0);tmp=tmp;
}
//SPI的时钟定为2.5MHZ,也就是400NS,一个数据位用3位SPI波形来表示;
//那么就把一个数据字节扩展成了24位的SPI波形字长;
//把逻辑0转化成二进制100就是0x04,就是高400nS,低800nS;
//把逻辑1转化成二进制110就是0x06,就是高800nS,低400nS;
//这样就能用SPI的MOSI发数据来驱动TM1812的DIN。
void tm1812_write_byte(uint8_t byte)
{
uint32_t tmp,data=0;
for(uint8_t i=0;i<8;i++){tmp=(byte&1)?0x06:0x04;data|=tmp<<(i*3);byte>>=1;}
spi0_write(data);
}
void tm1812_display_lamp(color_t *led)
{
for(uint8_t i=0;i<24;i++)
{
tm1812_write_byte(led.red);
tm1812_write_byte(led.green);
tm1812_write_byte(led.blue);
}
CLK_SysTickDelay(24); //更新显示,复位时间24uS
}
void tm1812_display_all(color_t *color)
{
color_t led[24];for(uint8_t i=0;i<24;i++){led=*color;}
tm1812_display_lamp((color_t*)led);
}
void tm1812_display_off(void){uint32_t color =0;tm1812_display_all((color_t *)&color);}
void tm1812_display_key(uint8_t key_value,color_t *color)
{
color_t led[24];memset((void *)&led[0],0,sizeof(led));
led[0]=*color;for(uint8_t i=0;i<key_value;i++){led[8+i]=*color;}
tm1812_display_lamp((color_t*)led);
}
void spi0_test(void)
{
uint32_t i;
for(i=0;i<254;i++){uint32_t color=i<<16;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
while(i--) {uint32_t color=i<<16;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
for(i=0;i<254;i++){uint32_t color=i<< 8;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
while(i--) {uint32_t color=i<< 8;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
for(i=0;i<254;i++){uint32_t color=i<< 0;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
while(i--) {uint32_t color=i<< 0;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
tm1812_display_off();CLK_SysTickDelayMs(200);
}
void SPI0_Init(void)
{
/* Select HCLK as the clock source of SPI0 */
CLK_SetModuleClock(SPI0_MODULE, CLK_CLKSEL1_SPI0_S_HCLK, MODULE_NoMsk);
/* Enable SPI0 peripheral clock */
CLK_EnableModuleClock(SPI0_MODULE);
/* Setup SPI0 multi-function pins */
/* Set P1 multi-function pins for SPI0 */
SYS->P1_MFP = (SYS->P1_MFP & (~(SYS_MFP_P14_Msk | SYS_MFP_P15_Msk | SYS_MFP_P16_Msk | SYS_MFP_P17_Msk)))
| (/*SYS_MFP_P14_SPISS0 |*/ SYS_MFP_P15_MOSI_0 /*| SYS_MFP_P16_MISO_0 | SYS_MFP_P17_SPICLK0*/);
/* Set P1。3 pins for GPIO */
SYS->P1_MFP = (SYS->P1_MFP & (~(SYS_MFP_P13_Msk))) | (SYS_MFP_P13_TXD1);
/* Configure P1.3 as Input mode */
GPIO_SetMode(P1, BIT3, GPIO_PMD_INPUT);
/*---------------------------------------------------------------------------------------------------------*/
/* Init SPI */
/*---------------------------------------------------------------------------------------------------------*/
/* Configure as a master, clock idle low, 24-bit transaction, drive output on falling clock edge and latch input on rising edge. */
/* Set IP clock divider. SPI clock rate = 2.5MHz */
SPI_Open(SPI0, SPI_MASTER, SPI_MODE_0, 24, 2500000);
/* Enable the automatic hardware slave select function. Select the SS pin and configure as low-active. */
SPI_EnableAutoSS(SPI0, SPI_SS, SPI_SS_ACTIVE_LOW);
}
//完毕
最近做个项目,用到ARMJISHU公司的神舟III号4.3寸液晶屏,用NANO120KE3BN驱动起来了。CPU的PLL是96M,主频超到了48M。特地发出来抛砖引玉。
源码:
/******************************************************************************
* @file ssd1963.c
* @brief The Driver code for 480*272 16 Color LCD with NANO120KE3BN
* @version 1.0.0
* @date 05, December, 2013
*
* @note
* Copyright (C) 2000-2013 PM9GZY by yuanxihua@21cn.com. All rights reserved.
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "nano1xx.h"
#include "nano1xx_gpio.h"
#include "nano1xx_ebi.h"
#include "stdlib.h"
#include "core_cmInstr.h"
#include "rfid.h"
/*
_________________________________________________
| NANO120KE3BN SSD1963 |
| |
| EBIAD0- EBIAD15 <---> DB0-DB15 |
| EBIWR PA10 ----> WR# |
| EBIRD PA11 ----> RD# |
| EBICS PB7 ----> CS# |
| PB6 EBIALE ----> D/C# |
| PA8 EBIPA8 ----> RESET# |
| PA9 EBIPA9 ----> LEDA |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define LCD_LEDA GPIOA, 9 /* PA9=High,BackLight ON; Low,BackLight OFF */
#define LCD_RESET GPIOA, 8 /* PA8=Low,LCD Reset;PA8=High,LCD Working */
#define LCD_DCMD GPIOB, 6 /* PB6=High,DATA mode; PB6=Low,COMMAND mode */
#define LCD_RESET_DELAY 100 /* LCD_RESET=Low,LCD_RESET_DELAY>=100us */
#define BLACK 0x0000 /* 黑色: 0 , 0 , 0 */
#define NAVY 0x000F /* 深蓝色: 0 , 0 , 128 */
#define DGREEN 0x03E0 /* 深绿色: 0 , 128, 0 */
#define DCYAN 0x03EF /* 深青色: 0 , 128, 128 */
#define MAROON 0x7800 /* 深红色: 128, 0 , 0 */
#define PURPLE 0x780F /* 紫色: 128, 0 , 128 */
#define OLIVE 0x7BE0 /* 橄榄绿: 128, 128, 0 */
#define LGRAY 0xC618 /* 灰白色: 192, 192, 192 */
#define DGRAY 0x7BEF /* 深灰色: 128, 128, 128 */
#define BLUE 0x001F /* 蓝色: 0 , 0 , 255 */
#define GREEN 0x07E0 /* 绿色: 0 , 255, 0 */
#define CYAN 0x07FF /* 青色: 0 , 255, 255 */
#define RED 0xF800 /* 红色: 255, 0 , 0 */
#define MAGENTA 0xF81F /* 品红: 255, 0 , 255 */
#define YELLOW 0xFFE0 /* 黄色: 255, 255, 0 */
#define WHITE 0xFFFF /* 白色: 255, 255, 255 */
#define SSD1963_HDP 0xDF01 /* HDP=479=0x01DF */
#define SSD1963_HT 0x1302 /* HT =531=0x0213 */
#define SSD1963_HPS 0x2B00 /* HPS=43 =0x002B */
#define SSD1963_LPS 0x0800 /* LPS=8 =0x0008 */
#define SSD1963_HPW 10 /* HPW=10 =0x0A */
#define SSD1963_VDP 0x0F01 /* VDP=271=0x010F */
#define SSD1963_VT 0x2001 /* VT =288=0x0120 */
#define SSD1963_VPS 0x0C00 /* VPS=12 =0x000C */
#define SSD1963_FPS 0x0100 /* FPS=1 =0x0001 */
#define SSD1963_VPW 10 /* VPW=10 =0x0A */
/* Private macro -------------------------------------------------------------*/
/* Command Hex Code Description */
#define SSD1963_nop 0x00 /* No operation */
#define SSD1963_soft_reset 0x01 /* Software Reset */
#define SSD1963_get_power_mode 0x0A /* Get the current power mode */
#define SSD1963_get_address_mode 0x0B /* Get the frame buffer to the display panel read order */
#define SSD1963_Reserved0c 0x0C /* Reserved */
#define SSD1963_get_display_mode 0x0D /* The SSD1963 returns the Display Image Mode. */
#define SSD1963_get_tear_effect_status 0x0E /* Get the Tear Effect status */
#define SSD1963_Reserved0f 0x0F /* Reserved */
#define SSD1963_enter_sleep_mode 0x10 /* Turn off the panel. This command will pull low the GPIO0. If GPIO0 is configured as normal GPIO or LCD miscellaneous signal with command set_gpio_conf, this command will be ignored. */
#define SSD1963_exit_sleep_mode 0x11 /* Turn on the panel. This command will pull high the GPIO0. If GPIO0 is configured as normal GPIO or LCD miscellaneous signal with command set_gpio_conf, this command will be ignored. */
#define SSD1963_enter_partial_mode 0x12 /* Part of the display area is used for image display. */
#define SSD1963_enter_normal_mode 0x13 /* The whole display area is used for image display. */
#define SSD1963_exit_invert_mode 0x20 /* Displayed image colors are not inverted. */
#define SSD1963_enter_invert_mode 0x21 /* Displayed image colors are inverted. */
#define SSD1963_set_gamma_curve 0x26 /* Selects the gamma curve used by the display panel. */
#define SSD1963_set_display_off 0x28 /* Blanks the display panel */
#define SSD1963_set_display_on 0x29 /* Show the image on the display panel */
#define SSD1963_set_column_address 0x2A /* Set the column address */
#define SSD1963_set_page_address 0x2B /* Set the page address */
#define SSD1963_write_memory_start 0x2C /* Transfer image information from the host processor interface to the SSD1963 starting at the location provided by set_column_address and set_page_address */
#define SSD1963_read_memory_start 0x2E /* Transfer image data from the SSD1963 to the host processor interface starting at the location provided by set_column_address and set_page_address */
#define SSD1963_set_partial_area 0x30 /* Defines the partial display area on the display panel */
#define SSD1963_set_scroll_area 0x33 /* Defines the vertical scrolling and fixed area on display area */
#define SSD1963_set_tear_off 0x34 /* Synchronization information is not sent from the SSD1963 to the host processor */
#define SSD1963_set_tear_on 0x35 /* Synchronization information is sent from the SSD1963 to the host processor at the start of VFP */
#define SSD1963_set_address_mode 0x36 /* Set the read order from frame buffer to the display panel */
#define SSD1963_set_scroll_start 0x37 /* Defines the vertical scrolling starting point */
#define SSD1963_exit_idle_mode 0x38 /* Full color depth is used for the display panel */
#define SSD1963_enter_idle_mode 0x39 /* Reduce color depth is used on the display panel. */
#define SSD1963_Reserved3a 0x3A /* Reserved */
#define SSD1963_write_memory_continue 0x3C /* Transfer image information from the host processor interface to the SSD1963 from the last written location */
#define SSD1963_read_memory_continue 0x3E /* Read image data from the SSD1963 continuing after the last read_memory_continue or read_memory_start */
#define SSD1963_set_tear_scanline 0x44 /* Synchronization information is sent from the SSD1963 to the host processor when the display panel refresh reaches the provided scanline */
#define SSD1963_get_scanline 0x45 /* Get the current scan line */
#define SSD1963_read_ddb 0xA1 /* Read the DDB from the provided location */
#define SSD1963_Reserveda8 0xA8 /* Reserved */
#define SSD1963_set_lcd_mode 0xB0 /* Set the LCD panel mode and resolution */
#define SSD1963_get_lcd_mode 0xB1 /* Get the current LCD panel mode, pad strength and resolution */
#define SSD1963_set_hori_period 0xB4 /* Set front porch */
#define SSD1963_get_hori_period 0xB5 /* Get current front porch settings */
#define SSD1963_set_vert_period 0xB6 /* Set the vertical blanking interval between last scan line and next LFRAME pulse */
#define SSD1963_get_vert_period 0xB7 /* Set the vertical blanking interval between last scan line and next LFRAME pulse */
#define SSD1963_set_gpio_conf 0xB8 /* Set the GPIO configuration. If the GPIO is not used for LCD, set the direction. Otherwise, they are toggled with LCD signals. */
#define SSD1963_get_gpio_conf 0xB9 /* Get the current GPIO configuration */
#define SSD1963_set_gpio_value 0xBA /* Set GPIO value for GPIO configured as output */
#define SSD1963_get_gpio_status 0xBB /* Read current GPIO status. If the individual GPIO was configured as input, the value is the status of the corresponding pin. Otherwise, it is the programmed value. */
#define SSD1963_set_post_proc 0xBC /* Set the image post processor */
#define SSD1963_get_post_proc 0xBD /* Set the image post processor */
#define SSD1963_set_pwm_conf 0xBE /* Set the image post processor */
#define SSD1963_get_pwm_conf 0xBF /* Set the image post processor */
#define SSD1963_set_lcd_gen0 0xC0 /* Set the rise, fall, period and toggling properties of LCD signal generator 0 */
#define SSD1963_get_lcd_gen0 0xC1 /* Get the current settings of LCD signal generator 0 */
#define SSD1963_set_lcd_gen1 0xC2 /* Set the rise, fall, period and toggling properties of LCD signal generator 1 */
#define SSD1963_get_lcd_gen1 0xC3 /* Get the current settings of LCD signal generator 1 */
#define SSD1963_set_lcd_gen2 0xC4 /* Set the rise, fall, period and toggling properties of LCD signal generator 2 */
#define SSD1963_get_lcd_gen2 0xC5 /* Get the current settings of LCD signal generator 2 */
#define SSD1963_set_lcd_gen3 0xC6 /* Set the rise, fall, period and toggling properties of LCD signal generator 3 */
#define SSD1963_get_lcd_gen3 0xC7 /* Get the current settings of LCD signal generator 3 */
#define SSD1963_set_gpio0_rop 0xC8 /* Set the GPIO0 with respect to the LCD signal generators using ROP operation. No effect if the GPIO0 is configured as general GPIO. */
#define SSD1963_get_gpio0_rop 0xC9 /* Get the GPIO0 properties with respect to the LCD signal generators. */
#define SSD1963_set_gpio1_rop 0xCA /* Set the GPIO1 with respect to the LCD signal generators using ROP operation. No effect if the GPIO1 is configured as general GPIO. */
#define SSD1963_get_gpio1_rop 0xCB /* Get the GPIO1 properties with respect to the LCD signal generators. */
#define SSD1963_set_gpio2_rop 0xCC /* Set the GPIO2 with respect to the LCD signal generators using ROP operation. No effect if the GPIO2 is configured as general GPIO. */
#define SSD1963_get_gpio2_rop 0xCD /* Get the GPIO2 properties with respect to the LCD signal generators. */
#define SSD1963_set_gpio3_rop 0xCE /* Set the GPIO3 with respect to the LCD signal generators using ROP operation. No effect if the GPIO3 is configured as general GPIO. */
#define SSD1963_get_gpio3_rop 0xCF /* Get the GPIO3 properties with respect to the LCD signal generators. */
#define SSD1963_set_dbc_conf 0xD0 /* Set the dynamic back light configuration 0xD1 get_dbc_conf Get the current dynamic back light configuration */
#define SSD1963_set_dbc_th 0xD4 /* Set the threshold for each level of power saving */
#define SSD1963_get_dbc_th 0xD5 /* Get the threshold for each level of power saving */
#define SSD1963_set_pll 0xE0 /* Start the PLL. Before the start, the system was operated with the crystal oscillator or clock input */
#define SSD1963_set_pll_mn 0xE2 /* Set the PLL */
#define SSD1963_get_pll_mn 0xE3 /* Get the PLL settings */
#define SSD1963_get_pll_status 0xE4 /* Get the current PLL status */
#define SSD1963_set_deep_sleep 0xE5 /* Set deep sleep mode */
#define SSD1963_set_lshift_freq 0xE6 /* Set the LSHIFT (pixel clock) frequency */
#define SSD1963_get_lshift_freq 0xE7 /* Get current LSHIFT (pixel clock) frequency setting */
#define SSD1963_Reservede8 0xE8 /* Reserved */
#define SSD1963_Reservede9 0xE9 /* Reserved */
#define SSD1963_set_pixel_data_interface 0xF0 /* Set the pixel data format of the parallel host processor interface */
#define SSD1963_get_pixel_data_interface 0xF1 /* Get the current pixel data format settings */
#define SSD1963_Reservedff 0xFF /* Reserved */
/* Private variables ---------------------------------------------------------*/
void SSD1963_Fill(uint16_t color);
extern void SYS_Delay(uint32_t us);
void Delay_ms(uint32_t ms)
{
for(uint32_t i=0;i<ms;i++){SYS_Delay(1000);}
}
// Enable EBI function with 16-bit data width
void NANOEBI_Init(void)
{
EBI_TIMING_T sEBITiming;
UNLOCKREG();
/* Enable EBI clock */
CLK->AHBCLK |= CLK_AHBCLK_EBI_EN;
/* EBI function enable */
EBI->EBICON |= EBI_EBICON_ExtEN;
EBI->EBICON |= EBI_EBICON_ExtBW16;
// Enable EBIAD15-0, GPIOPA9-8
GCR->PA_L_MFP = (GCR->PA_L_MFP & 0x0000000f) | 0x22222220; //PA7_MFP-PA1_MFP = EBI AD[6]-EBI AD[12]
GCR->PA_H_MFP = (GCR->PA_H_MFP & 0xf0000000) | 0x02222200; //PA14_MFP-PA12_MFP = EBI AD[15]-EBI AD[13] PA11_MFP-PA10_MFP = EBIWR-EBIRD PA9_MFP-PA8_MFP = PA9-PA8
GCR->PB_L_MFP = (GCR->PB_L_MFP & 0x00ffffff) | 0x20000000; //PB7_MFP-PB6_MFP = EBICS-PB6
GCR->PB_H_MFP = (GCR->PB_H_MFP & 0xff00ffff) | 0x00220000; //PB13_MFP-PB12_MFP = EBI AD[1]-EBI AD[0]
GCR->PC_L_MFP = (GCR->PC_L_MFP & 0x00ffffff) | 0x22000000; //PC15_MFP-PC14_MFP = EBI AD[3]-EBI AD[2]
GCR->PC_H_MFP = (GCR->PC_H_MFP & 0x00ffffff) | 0x22000000; //PC7_MFP-PC6_MFP = EBI AD[5]-EBI AD[4]
sEBITiming.eMCLKDIV = E_EBI_MCLKDIV_1; //OK!!! 480NS 2.083MHZ
sEBITiming.u8ExttALE=sEBITiming.u8ExtIR2R=sEBITiming.u8ExtIR2W = 0;
sEBITiming.u8ExtIW2X=sEBITiming.u8ExttAHD=sEBITiming.u8ExttACC = 0;
EBI_SetBusTiming(sEBITiming);
*(volatile uint16_t*)EBI_BASE_ADDR=0xFFFF; //Set D0-D15 to HIGH
GPIO_Open(GPIOA, GPIO_PMD_PMD8_OUTPUT, GPIO_PMD_PMD8_MASK);
GPIO_Open(GPIOA, GPIO_PMD_PMD9_OUTPUT, GPIO_PMD_PMD9_MASK);
GPIO_Open(GPIOB, GPIO_PMD_PMD6_OUTPUT, GPIO_PMD_PMD6_MASK);
GPIO_SetBit(LCD_LEDA); //PA9=High,BackLight ON; Low,BackLight OFF
GPIO_SetBit(LCD_DCMD); //PB6=High,DATA mode; PB6=Low,COMMAND mode
GPIO_SetBit(LCD_RESET); //PA8=Low,LCD Reset;PA8=High,LCD Working
SYS_Delay(LCD_RESET_DELAY);
GPIO_ClrBit(LCD_RESET);
SYS_Delay(LCD_RESET_DELAY);
GPIO_SetBit(LCD_RESET);
// LOCKREG();
}
static void EBI_test(void) {while(1) {*(volatile uint16_t*)EBI_BASE_ADDR=0x5555;*(volatile uint16_t*)EBI_BASE_ADDR=0xAAAA;}}
static __INLINE void SSD1963_WrPAR(uint8_t *data, uint8_t len){while(len--){EBI_WRITE_DATA16(0, *data++);}}
static __INLINE void SSD1963_WrCMD(uint8_t cmd, uint8_t *data, uint8_t len){GPIO_ClrBit(LCD_DCMD);EBI_WRITE_DATA16(0, cmd);GPIO_SetBit(LCD_DCMD);SSD1963_WrPAR(data, len);}
static __INLINE void SSD1963_WrRAM(uint16_t *data, uint32_t len){while(len--){EBI_WRITE_DATA16(0, *data++);}}
void SSD1963_Init(void)
{
uint32_t Parameter;
Parameter=0x04021d; //PLL multiplier, set PLL clock to 120M N=0x36 for 6.5M, 0x23 for 10M crystal
SSD1963_WrCMD(SSD1963_set_pll_mn,(uint8_t*)&Parameter, 3);
Parameter=0x01; //Enable PLL
SSD1963_WrCMD(SSD1963_set_pll,(uint8_t*)&Parameter, 1);
Delay_ms(1);
Parameter=0x03; //Use PLL output as system clock
SSD1963_WrCMD(SSD1963_set_pll,(uint8_t*)&Parameter, 1);
Delay_ms(5);
SSD1963_WrCMD(SSD1963_soft_reset,(uint8_t*)&Parameter, 0); //software reset
Delay_ms(5);
Parameter=0x16D900; //PLL setting for PCLK, depends on resolution
SSD1963_WrCMD(SSD1963_set_lshift_freq,(uint8_t*)&Parameter, 3);
Parameter=0x0020; //LCD SPECIFICATION
SSD1963_WrCMD(SSD1963_set_lcd_mode,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_HDP; //Set HDP
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=SSD1963_VDP; //Set VDP
SSD1963_WrPAR((uint8_t*)&Parameter, 3);
Parameter=SSD1963_HT; //Set HT HSYNC
SSD1963_WrCMD(SSD1963_set_hori_period,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_HPS; //Set HPS
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=SSD1963_HPW; //Set HPW
SSD1963_WrPAR((uint8_t*)&Parameter, 1);
Parameter=SSD1963_LPS; //Set LPS
SSD1963_WrPAR((uint8_t*)&Parameter, 3);
Parameter=SSD1963_VT; //Set VT VSYNC
SSD1963_WrCMD(SSD1963_set_vert_period,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_VPS; //Set VPS
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=SSD1963_VPW; //Set VPW
SSD1963_WrPAR((uint8_t*)&Parameter, 1);
Parameter=SSD1963_FPS; //Set FPS
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=0x05; //0x000F; //GPIO[3:0] out 1
SSD1963_WrCMD(SSD1963_set_gpio_value,(uint8_t*)&Parameter, 1);
Parameter=0x0107; //GPIO0 normal GPIO3=input, GPIO[2:0]=output
SSD1963_WrCMD(SSD1963_set_gpio_conf,(uint8_t*)&Parameter, 2);
Parameter=0x00; //rotation
SSD1963_WrCMD(SSD1963_set_address_mode,(uint8_t*)&Parameter, 1);
Delay_ms(50);
Parameter=0x8006; //set PWM for B/L
SSD1963_WrCMD(SSD1963_set_pwm_conf,(uint8_t*)&Parameter, 2);
Parameter=0x0000f001;
SSD1963_WrPAR((uint8_t*)&Parameter, 4);
Parameter=0x0d; //设置动态背光控制配置
SSD1963_WrCMD(SSD1963_set_dbc_conf,(uint8_t*)&Parameter, 1);
Parameter=0x03; //03:16-bit (565 format)
SSD1963_WrCMD(SSD1963_set_pixel_data_interface,(uint8_t*)&Parameter, 1);
// SSD1963_WrCMD(SSD1963_enter_invert_mode,(uint8_t*)&Parameter, 0); //进入图形颜色翻转模式
// Parameter=0x01808080; //处理机允许 饱和度值 亮度 对比度
// SSD1963_WrCMD(SSD1963_set_post_proc,(uint8_t*)&Parameter, 4);
SSD1963_Fill(BLACK);
SSD1963_WrCMD(SSD1963_set_display_on,(uint8_t*)&Parameter, 0); //display on
Delay_ms(5);
}
void SSD1963_Fill(uint16_t color)
{
uint32_t Parameter;
Parameter=0;
SSD1963_WrCMD(SSD1963_set_column_address,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_HDP;
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=0;
SSD1963_WrCMD(SSD1963_set_page_address,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_VDP;
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
SSD1963_WrCMD(SSD1963_write_memory_start,(uint8_t*)&Parameter, 0);
for(uint32_t i=0;i<130560;i++){SSD1963_WrRAM(&color, 1);}
}
void LCD_test(void)
{
uint16_t i=0,color[]={BLACK, NAVY, DGREEN, DCYAN, MAROON, PURPLE, OLIVE, LGRAY, DGRAY, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE};
while(1)
{
if(i++>(sizeof(color)/sizeof(color[0])))i=0;
SSD1963_Fill(color);Delay_ms(5000);
}
}
void LCD_Configuration(void)
{
NANOEBI_Init();
SSD1963_Init();
printf("REVSH(0x1234)=0x%04x\n\r",__REVSH(0x1234));
LCD_test();
EBI_test();
}
//代码完毕
--缥缈九哥测试
测试了一个用M0516的SPI驱动TM1668驱动的10个7段数码管驱动,需要做行列段的转换驱动表,请同行们指正。
源码:
/******************************************************************************
* @file tM1668.c
* @brief The Driver code for 10 7-Segment-Digital LED
* @version 1.0.0
* @date 06, december 2013
*
* @note
* Copyright (C) 2000-2013 PM9GZY by yuanxihua@21cn.com. All rights reserved.
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "M051Series.h"
#include "rfid.h"
/*
//make by yuanxihua@21cn.com
____________________________________________
| M0517LBN TM1668 |
| |
| P14 SPISS0 ----> STB |
| P15 MOSI0 ----> DIO |
| P16 MISO0 <---- DIO |
| P17 SCLK0 ----> CLK |
|___________________________________________|
*/
//const unsigned char TM1668_7X8_CODE[]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7F, 0x39, 0x3F, 0x79, 0x71};/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
const unsigned short int TM1668_10X7_CODE[]={0xffed,0x2f9f,0x2ffb,0x7b6d,0xfd45,0xff71,0xcf7c};
void SPI0_Init(void);
void SPI0_Write_Byte(uint8_t data);
void TM1668_Init(void){SPI0_Init();}
void TM1668_Read_Key(uint8_t *key);
void TM1668_Write_ADDR_INC(uint8_t *data);
void TM1668_DISPLAY(uint8_t *led);
void TM1668_Number(uint32_t data1,uint32_t data2);
void SPI0_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Set P1.4, P1.5, P1.6, P1.7 for SPI0 */
SYS->P1_MFP = SYS_MFP_P14_SPISS0 | SYS_MFP_P15_MOSI_0 | SYS_MFP_P16_MISO_0 | SYS_MFP_P17_SPICLK0;
/* Configure SPI0 as a master, clock idle high, rising clock edge Tx, rising edge Rx and 8-bit LSB transaction */
SPI0->CNTRL = SPI_CNTRL_MASTER_MODE | SPI_CNTRL_CLK_IDLE_HIGH | SPI_CNTRL_TX_RISING |
SPI_CNTRL_RX_RISING | SPI_CNTRL_LSB_FIRST | SPI_CNTRL_TX_BIT_LEN(8);
/* SPI_SSR setting to force SPI master SS signal to high by software */
SPI0->SSR = SPI_SSR_SW_SS_PIN_HIGH;
/* Disable the automatic slave select function of the user-specified SPI port */
_SPI_DISABLE_HW_AUTO_SLAVE_SELECT(SPI0);
/* Set IP clock divider. SPI clock rate = HCLK / ((1+1)*2) = 12MHz */
SPI0->DIVIDER = (SPI0->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | SPI_DIVIDER_DIV(1);
/* Clear Tx register of SPI1 to avoid send non-zero data to Master. Just for safe. */
_SPI_WRITE_TX_BUFFER0(SPI1, 0);
/* Lock protected registers */
SYS_LockReg();
}
void SPI0_Write_Byte(uint8_t data)
{
//片选脚设为低电平状态
SPI0->SSR = SPI_SSR_SW_SS_PIN_LOW;
//发送数据
_SPI_WRITE_TX_BUFFER0(SPI0, data);_SPI_SET_GO(SPI0);
//等待发送数据完毕
while(_SPI_GET_BUSY_STATUS(SPI0)){;}
//片选脚设为高电平状态
SPI0->SSR = SPI_SSR_SW_SS_PIN_HIGH;
}
void TM1668_Read_Key(uint8_t *key)
{
//片选脚设为低电平状态
SPI0->SSR = SPI_SSR_SW_SS_PIN_LOW;
//Command1: 数据读写设置命令
//发送数据
_SPI_WRITE_TX_BUFFER0(SPI0, 0x42);_SPI_SET_GO(SPI0); //读键扫数据
//等待发送数据完毕
while(_SPI_GET_BUSY_STATUS(SPI0)){;}
//配置MOSI为高阻输入的AIN口
SYS->P1_MFP = SYS_MFP_P15_AIN5;
for(uint8_t i=0;i<5;i++)
{
SYS->P1_MFP = SYS_MFP_P15_MOSI_0;
//发送数据
_SPI_WRITE_TX_BUFFER0(SPI0, 0xff);_SPI_SET_GO(SPI0);
//等待发送数据完毕
while(_SPI_GET_BUSY_STATUS(SPI0)){;}
//读取数据
key=_SPI_GET_RX0_DATA(SPI0);
}
//配置P15为MOSI口
SYS->P1_MFP = SYS_MFP_P15_MOSI_0;
//片选脚设为高电平状态
SPI0->SSR = SPI_SSR_SW_SS_PIN_HIGH;
}
void TM1668_Write_ADDR_INC(uint8_t *data)
{
//Command1: 显示模式设置命令
SPI0_Write_Byte(0x03);//显示模式:7位10段
//Command2: 数据读写设置命令
SPI0_Write_Byte(0x40);//写数据到显示寄存器
//片选脚设为低电平状态
SPI0->SSR = SPI_SSR_SW_SS_PIN_LOW;
//Command3: 显示地址设置命令
_SPI_WRITE_TX_BUFFER0(SPI0, 0xC0);_SPI_SET_GO(SPI0);//显示地址=0X00
//等待传送退出
while(_SPI_GET_BUSY_STATUS(SPI0)){;}
for(uint32_t i=0;i<14;i++)//Data1~n: 显示数据,以Command3指定的地址为起始地址(最多14 bytes)
{
//发送数据
_SPI_WRITE_TX_BUFFER0(SPI0, data);_SPI_SET_GO(SPI0);
//等待发送数据完毕
while(_SPI_GET_BUSY_STATUS(SPI0)){;}
}
//片选脚设为高电平状态
SPI0->SSR = SPI_SSR_SW_SS_PIN_HIGH;
//Command4: 显示控制命令
SPI0_Write_Byte(0x88);//显示开,亮度脉冲宽度为1/16:0x88,设置脉冲宽度为14/16:0x8F
}
void TM1668_DISPLAY(uint8_t *led)
{
uint16_t TM1668[7],*code=(uint16_t*)TM1668_10X7_CODE;
memset(TM1668,0,sizeof(TM1668));
// for(uint8_t i=0;i<10;i++){DBG_PRINTF("led[%d]=%d\n\r",i,led);}
for(uint8_t i=0;i<10;i++){for(uint8_t j=0;j<7;j++){TM1668[j]|=((led>0xf)?0:(code[j]>>led)&1)<<i;}}
TM1668_Write_ADDR_INC((uint8_t *)(&TM1668[0]));
}
void TM1668_Number(uint32_t data1,uint32_t data2)
{
uint8_t led[10],*p=&led[3],*q=&led[9];
if((data1>9999)||(data2>999999)) return;
memset(led,' ',sizeof(led));led[3]=led[9]=0;
for(uint32_t i=data1;i!=0;i/=10){*p--=i%10;}
for(uint32_t i=data2;i!=0;i/=10){*q--=i%10;}
// for(uint8_t i=0;i<10;i++){DBG_PRINTF("led[%d]=%d\n\r",i,led);}
TM1668_DISPLAY(led);
}
void TM1668_Test(void)
{
uint8_t i=0;
TM1668_Init();
/* while(1)
{
//SPI0_Write_Byte(0x55);
if(++i>9)i=0;
uint32_t data0=i*10+i,data1=data0*100+data0,data2=data1*100+data0;
DBG_PRINTF("*** 9G-M0517LBN V1.00 %04d %06d...\n\r",data1,data2);
TM1668_Number(data1,data2);
for(uint16_t i=0;i<500;i++){SYS_SysTickDelay(1000);}
}
*/
i=i;
uint32_t j=0,k=0;
while(1)
{
//SPI0_Write_Byte(0x55);
if(j++>9999){j=0;} if(k++>999999)k=0;
DBG_PRINTF("*** 9G-M0517LBN V1.00 %04d %06d...\n\r",j,k);
TM1668_Number(j,k);
// for(uint16_t i=0;i<100;i++){SYS_SysTickDelay(1000);}
}
}
//缥缈九哥测试通过
基于新唐NUC123的3.0的BSP包的PCF8563驱动程序
源码如下:
/******************************************************************************
* @file pcf8563.c
* @brief The Driver code for PCF8563 with NUC123ZD4AN0
* @version 1.0.0
* @date 22, June, 2018
*
* @note
* Copyright (C) 2000-2016 PM9GZY by yuanxihua@21cn.com. All rights reserved.
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/*
_________________________________________________
| NUC123ZD4AN0 PCF8563 |
| |
| SDA1 - PA10 <---> SDA |
| SCL1 - PA11 ---> SCL |
| INT0 - PB14 <--- INT |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {START=0,STOP,ACK,NAK}i2c_status_t;
typedef struct
{
uint8_t CTL_status[2];
uint8_t VL_second;
uint8_t TM_minute;
uint8_t TM_hour;
uint8_t TM_day;
uint8_t TM_weekday;
uint8_t CTY_month;
uint8_t TM_year;
uint8_t AL_minute;
uint8_t AL_hour;
uint8_t AL_day;
uint8_t AL_weekday;
uint8_t CTL_clkout;
uint8_t CTL_timer;
uint8_t TM_timer;
}pcf8563_t;
//#define pbcd_to_byte(x) (((((x)>>4)&0x0f)*10)+((x)&0x0f))
//#define byte_to_pbcd(x) (((((x)/10)&0x0f)<<4)+(((x)%10)&0x0f))
/* Private define ------------------------------------------------------------*/
#define PCF8563_SLAVEADDR 0xA2 /* Clock i2c slave address */
#define PCF8563_CLK_HZ 100000 /* Clock i2c speed */
#define PCF8563_I2C_WAIT_US 100000 /* Clock wait time */
/* Private macro -------------------------------------------------------------*/
void PCF8563_Get_Time(struct tm *Time);
void PCF8563_Set_Time(struct tm Time);
/* Private variables ---------------------------------------------------------*/
uint8_t pbcd_to_byte(uint8_t pbcd)
{
uint8_t msb,lsb;
msb = (pbcd >> 4);
lsb = pbcd & 0xf;
if((msb>9)||(lsb>9)){return(99);}
else{return((10*msb)+lsb);}
}
uint8_t byte_to_pbcd(uint8_t bin)
{
if(bin>=99){return(0x99);}/* overflow? */
else{return(((bin/10)<<4)|(bin%10));}
}
static void CLK_SysTickDelayMs(uint32_t ms)
{
for(uint32_t i=0;i<ms;i++){CLK_SysTickDelay(1000);}
}
void I2C1_Configuration(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Set GPA multi-function pins for I2C1 SDA and SCL */
SYS->GPA_MFP &= ~(SYS_GPA_MFP_PA10_Msk | SYS_GPA_MFP_PA11_Msk);
SYS->GPA_MFP |= (SYS_GPA_MFP_PA10_I2C1_SDA | SYS_GPA_MFP_PA11_I2C1_SCL);
SYS->ALT_MFP &= ~(SYS_ALT_MFP_PA10_Msk | SYS_ALT_MFP_PA11_Msk);
SYS->ALT_MFP |= (SYS_ALT_MFP_PA10_I2C1_SDA | SYS_ALT_MFP_PA11_I2C1_SCL);
/* Enable I2C1 module clock */
CLK_EnableModuleClock(I2C1_MODULE);
/* reset I2C1 modules */
SYS_ResetModule(I2C1_RST);
/* Get I2C1 clock */
// DBG_PRINTF("I2C1 clock %d Hz\n", I2C_GetClockFreq(I2C1));
/* Lock protected registers */
SYS_LockReg();
}
static void I2C_SEND_STATUS(I2C_T *i2c,i2c_status_t status)
{
uint32_t i=PCF8563_I2C_WAIT_US;
if(status==START){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_STA_SI); }else //set start
if(status==STOP ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_STO_SI); }else //set stop
if(status==ACK ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA); }else //set ack
if(status==NAK ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI); }else{;} //set nack
while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
// DBG_PRINTF("I2C_SS STATUS=0x%02x\n\r",I2C_GET_STATUS(i2c));
}
static void I2C_SEND_DATA(I2C_T *i2c,uint8_t data,i2c_status_t ack)
{
uint32_t i=PCF8563_I2C_WAIT_US;
I2C_SET_DATA(i2c, data);
if(ack==ACK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA); }else //ACK
if(ack==NAK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI); }else{;} //NACK
while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
// DBG_PRINTF("I2C_SD=0x%02x STATUS=0x%02x\n\r",data,I2C_GET_STATUS(i2c));
}
static uint8_t I2C_READ_DATA(I2C_T *i2c,i2c_status_t ack)
{
uint32_t i=PCF8563_I2C_WAIT_US;
while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
uint8_t data=I2C_GET_DATA(i2c);
if(ack==ACK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA); }else //ACK
if(ack==NAK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI); }else{;} //NACK
// DBG_PRINTF("I2C_RD STATUS=0x%02x\n\r",I2C_GET_STATUS(i2c));
return data;
}
void PCF8563_Get_Time(struct tm *Time)
{
uint8_t buf[16],i;
I2C1_Configuration();
//i2c bus open
I2C_Open(I2C1, PCF8563_CLK_HZ);
//send i2c start
I2C_SEND_STATUS(I2C1,START);
//send slave address & writer command
I2C_SEND_DATA(I2C1,0xa2,ACK);
//send register address
I2C_SEND_DATA(I2C1,0x00,ACK);
//send i2c start
I2C_SEND_STATUS(I2C1,START);
//send slave address & read command
I2C_SEND_DATA(I2C1,0xa3,ACK);
uint8_t tmp=I2C_READ_DATA(I2C1,ACK);
for(i=0;i<15;i++)
{
//receive data with ack
buf[i]= I2C_READ_DATA(I2C1,ACK);
CLK_SysTickDelay(100);
}
//receive data with nak
buf[i]= I2C_READ_DATA(I2C1,NAK);
//send i2c stop
I2C_SEND_STATUS(I2C1,STOP);
CLK_SysTickDelay(100);
I2C_Close(I2C1);
// DBG_PRINTF("\n\rGETBUF:");for(i=0;i<16;i++){printf("%02x ",buf[i]);}
// memset(Time,0,sizeof(struct tm));
Time->tm_sec = pbcd_to_byte(buf[2]&0x7f);
Time->tm_min = pbcd_to_byte(buf[3]&0x7f);
Time->tm_hour = pbcd_to_byte(buf[4]&0x3f);
Time->tm_mday = pbcd_to_byte(buf[5]&0x3f);
Time->tm_mon = pbcd_to_byte(buf[7]&0x1f)-1;
Time->tm_year = pbcd_to_byte(buf[8])+100;
}
void PCF8563_Set_Time(struct tm Time)
{
uint8_t buf[16],i;
buf[0]=0;
buf[1]=0;
buf[2]=byte_to_pbcd(Time.tm_sec);
buf[3]=byte_to_pbcd(Time.tm_min);
buf[4]=byte_to_pbcd(Time.tm_hour);
buf[5]=byte_to_pbcd(Time.tm_mday);
buf[7]=byte_to_pbcd(Time.tm_mon)+1;
buf[8]=byte_to_pbcd(Time.tm_year%100);
// DBG_PRINTF("\n\rSETBUF:");for(i=0;i<16;i++){printf("%02x ",buf[i]);}
I2C1_Configuration();
//i2c bus open
I2C_Open(I2C1, PCF8563_CLK_HZ);
//send i2c start
I2C_SEND_STATUS(I2C1,START);
//send slave address & writer command
I2C_SEND_DATA(I2C1,0xa2,ACK);
//send register address
I2C_SEND_DATA(I2C1,0x00,ACK);
for(i=0;i<15;i++)
{
//send data with ack
I2C_SEND_DATA(I2C1,buf[i],ACK);
CLK_SysTickDelay(100);
}
//send data with nak
I2C_SEND_DATA(I2C1,buf[i],NAK);
//send i2c stop
I2C_SEND_STATUS(I2C1,STOP);
CLK_SysTickDelay(100);
I2C_Close(I2C1);
}
uint8_t PCF8563_Chk_Time(struct tm *t)
{
uint32_t year=t->tm_year, month=t->tm_mon, day=t->tm_mday; //防止修改指针
uint32_t hour=t->tm_hour, minute=t->tm_min, second=t->tm_sec; //防止修改指针
if((year<2010)||(year>2030)){return 0;}
if((month<1)||(month>12)){return 0;}
if((day<1)||(day>31)){return 0;}
if((month==4||month==6||month==9||month==11)&&(day>30)){return 0;}
if(month==2){if(year%4){if(day>28){return 0;}}else{if(day>29){return 0;}}}
if((hour>23)||(minute>59)||(second>60)){return 0;}
return 1;
}
void PCF8563_test(void)
{
__align(4) struct tm Time;
#if 0
const char Month[12][4]= {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};char sMonth[4]= {0};
const char *DataStr = __DATE__; //Aug 20 2016
const char *TimeStr = __TIME__; //20:12:38
sscanf(DataStr, "%s %d %d", sMonth, &Time.tm_mday, &Time.tm_year);
sscanf(TimeStr, "%d:%d:%d", &Time.tm_hour, &Time.tm_min, &Time.tm_sec);
for(int i=0;i<12;i++){if(strncmp(sMonth, Month[i],3)==0){Time.tm_mon=i;break;}}
Time.tm_year -= 1900; /* years since 1900 */
// Time.tm_mon = 8-1; /* months since January, 0 to 11 */
// Time.tm_mday = 20; /* day of the month, 1 to 31 */
// Time.tm_hour = 18; /* hours since midnight, 0 to 23 */
// Time.tm_min = 43; /* minutes after the hour, 0 to 59 */
Time.tm_sec +=10; /* seconds after the minute, 0 to 60
(0 - 60 allows for the occasional leap second) */
PCF8563_Set_Time(Time);
while(1)
#endif
{
PCF8563_Get_Time(&Time);
time_t t=mktime(&Time); // printf("t=%d %s",t, ctime(&t));
printf("%s", asctime(&Time));
char str[80]; strftime(str,100,"GET Time:%F %H:%M:%S\n\r",&Time); printf("%s", str);
CLK_SysTickDelayMs(1000);
struct tm a;
a.tm_year = 100; /* years since 1900 */
a.tm_mon = 0; /* months since January, 0 to 11 */
a.tm_mday = 1; /* day of the month, 1 to 31 */
a.tm_hour = 0; /* hours since midnight, 0 to 23 */
a.tm_min = 0; /* minutes after the hour, 0 to 59 */
a.tm_sec = 0; /* seconds after the minute, 0 to 60 */
time_t p=mktime(&a);
printf("p=0x%08x = %d , %s",p,p,ctime(&p));
//p=0x386d4380 = 946684800 , Sat Jan 1 00:00:00 2000
t=0x1F4DC49F+p;//1986-08-23 14:11:43
printf("t=0x%08x = %d , %s",t,t,ctime(&t));
//t=1471875103 Mon Aug 22 14:11:43 2016
}
}
//代码完毕。
基于新唐NUC123的3.0的BSP包的FM25CL64BG驱动开发
源码如下:
/**************************************************************************//**
* @file fm25640c.c
* @version V3.00
* $Revision: 5 $
* $Date: 16/08/04 11:18a $
* @brief Demonstrate how to perform timer counting in periodic mode.
* @note
* Copyright (C) 2014~2016 PM9GZY Technology Corp. yuanxihua@21cn.com All rights reserved.
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "NUC123.h"
/*
_________________________________________________
| NUC123ZD4AN0 FM25CL64BG |
| |
| PC8 SS10 ----> CS |
| PC9 SPICLK1 ----> SCK |
| PC10 MISO10 <---- SO |
| PC11 MOSI10 ----> SI |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//#define FM25CL64BG_CS PC8
#define FM25CL64BG_SIZE 8*1024
//FM25CL64BG命令
#define FM25CL64BG_WREN 0x06
#define FM25CL64BG_WRDI 0x04
#define FM25CL64BG_RDSR 0x05ff
#define FM25CL64BG_WRSR 0x0100
#define FM25CL64BG_READ 0x030000FF
#define FM25CL64BG_WRITE 0x02000000
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void FM25CL64BG_Init(void);
void FM25CL64BG_Read (uint32_t addr, uint8_t *buf, uint32_t len);
void FM25CL64BG_Write(uint32_t addr, uint8_t *buf, uint32_t len);
void FM25CL64BG_Write_Byte(uint32_t addr,uint8_t wrdata);
void FM25CL64BG_Write_Status_Register(uint8_t wrdata);
uint8_t FM25CL64BG_Read_Byte(uint32_t addr);
uint8_t FM25CL64BG_Read_Status_Register(void);
void SPI1_Send_Data(uint32_t wrdata,uint8_t bits);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
void FM25CL64BG_Test(void)
{
uint32_t i;
/* Configure the FM25CL64BG */
FM25CL64BG_Init();
while(0)
{
// SPI1_Send_Data(0x55, 8);
// SPI_SET_SS0(SPI1); SPI1_Send_Data(0x55, 8);SPI_CLR_SS0(SPI1); //写0x55测试SPI接口
// FM25CL64BG_Write_Byte(0xCC, 0x55);
// FM25CL64BG_Read_Byte (0xCC);
// FM25CL64BG_Read_Status_Register();
}
FM25CL64BG_Write_Status_Register(0x00);
printf("FM25CL64BG_Read_Status_Register() = 0x%02x \n\r",FM25CL64BG_Read_Status_Register());
FM25CL64BG_Write_Byte(0xAA, 0x55);
FM25CL64BG_Write_Byte(0x55, 0xAA);
printf("FM25CL64BG_Read_Byte(0xAA) = 0x%02x \n\r",FM25CL64BG_Read_Byte(0xAA));
printf("FM25CL64BG_Read_Byte(0x55) = 0x%02x \n\r",FM25CL64BG_Read_Byte(0x55));
while(1)
{
for(i=0;i<FM25CL64BG_SIZE;i++)
{FM25CL64BG_Write_Byte(i, i&0xff);}
CLK_SysTickDelay(300000);
for(i=0;i<FM25CL64BG_SIZE;i++)
{
//for display
if((i%16)== 0){printf("\n\r%08xh:",i);}
printf(" %02x",FM25CL64BG_Read_Byte(i));
if((i%16)==15){printf(" ;");}
//display end
}
CLK_SysTickDelay(300000);
}
}
// SPI1_Send_Data(FM25640C_WREN,8);
// SPI1_Send_Data(FM25640C_WRDI,8);
void FM25CL64BG_Read(uint32_t addr, uint8_t *buf, uint32_t len)
{
uint32_t i;
for(i=0;i<len;i++)
{buf[i] = FM25CL64BG_Read_Byte(addr+i);}
}
void FM25CL64BG_Write(uint32_t addr, uint8_t *buf, uint32_t len)
{
uint32_t i;
for(i=0;i<len;i++)
{FM25CL64BG_Write_Byte(addr+i,buf[i]);}
}
uint8_t FM25CL64BG_Read_Byte(uint32_t addr)
{
uint32_t rddata,tmpdata=FM25CL64BG_READ;
tmpdata |= (addr << 8);
SPI1_Send_Data(tmpdata,32);
rddata = SPI_READ_RX0(SPI1);
return (uint8_t)rddata;
}
void FM25CL64BG_Write_Byte(uint32_t addr, uint8_t wrdata)
{
uint32_t tmpdata=FM25CL64BG_WRITE;
SPI1_Send_Data(FM25CL64BG_WREN,8); //中:使能写操作//Write Enable
tmpdata |= (addr << 8) + wrdata;
SPI1_Send_Data(tmpdata,32);
}
uint8_t FM25CL64BG_Read_Status_Register(void)
{
uint32_t rddata;
SPI1_Send_Data(FM25CL64BG_RDSR,16);
rddata = SPI_READ_RX0(SPI1);
return (uint8_t)rddata;
}
void FM25CL64BG_Write_Status_Register(uint8_t wrdata)
{
uint16_t dat=FM25CL64BG_WRSR | wrdata;
SPI1_Send_Data(FM25CL64BG_WREN,8); //中:使能写操作//Write Enable
SPI1_Send_Data(dat,16);
}
void SPI1_Send_Data(uint32_t wrdata, uint8_t bits)
{
SPI1->CNTRL = (SPI1->CNTRL&0xFFFFFF07) | ((bits&0x1f) << SPI_CNTRL_TX_BIT_LEN_Pos);
/* Write to TX register */
SPI_WRITE_TX0(SPI1, wrdata);
/* Trigger SPI1 data transfer */
SPI_TRIGGER(SPI1);
/* Check SPI1 busy status */
while(SPI_IS_BUSY(SPI1));
}
void SPI1_Init(void)
{
/* Select HCLK as the clock source of SPI1 */
CLK_SetModuleClock(SPI1_MODULE, CLK_CLKSEL1_SPI1_S_HCLK, MODULE_NoMsk);
/* Enable SPI1 peripheral clock */
CLK_EnableModuleClock(SPI1_MODULE);
/* Setup SPI1 multi-function pins */
SYS->GPC_MFP &= ~(SYS_GPC_MFP_PC8_Msk | SYS_GPC_MFP_PC9_Msk | SYS_GPC_MFP_PC10_Msk | SYS_GPC_MFP_PC11_Msk);
SYS->GPC_MFP |= SYS_GPC_MFP_PC8_SPI1_SS0 | SYS_GPC_MFP_PC9_SPI1_CLK | SYS_GPC_MFP_PC10_SPI1_MISO0 | SYS_GPC_MFP_PC11_SPI1_MOSI0;
SYS->ALT_MFP1 &= ~(SYS_ALT_MFP1_PC8_Msk | SYS_ALT_MFP1_PC9_Msk | SYS_ALT_MFP1_PC10_Msk | SYS_ALT_MFP1_PC11_Msk);
SYS->ALT_MFP1 |= SYS_ALT_MFP1_PC8_SPI1_SS0 | SYS_ALT_MFP1_PC9_SPI1_CLK | SYS_ALT_MFP1_PC10_SPI1_MISO0 | SYS_ALT_MFP1_PC11_SPI1_MOSI0;
/*---------------------------------------------------------------------------------------------------------*/
/* Init SPI */
/*---------------------------------------------------------------------------------------------------------*/
/* Configure as a master, clock idle low, 32-bit transaction, drive output on falling clock edge and latch input on rising edge. */
/* Set IP clock divider. SPI clock rate = 36MHz */
SPI_Open(SPI1, SPI_MASTER, SPI_MODE_0, 32, 36000000);
/* Enable the automatic hardware slave select function. Select the SS pin and configure as low-active. */
SPI_EnableAutoSS(SPI1, SPI_SS0, SPI_SS_ACTIVE_LOW);
}
void FM25CL64BG_Init(void)
{
SPI1_Init();
}
//源码完毕
某年写个番禺龙美游戏机IO板用到了STM32F103VBT6及TM1629.写下了一个驱动程序。希望能帮助到有需要的朋友。不多说了,代码如下:
/* Includes ------------------------------------------------------------------*/
#ifdef GAME
#include "stm32f10x.h"
#include "stdio.h"
/** @addtogroup STM32F10x_StdPeriph_Examples
* @{
*/
/** @addtogroup GPIO_JTAG_Remap
* @{
*/
/*
_________________________________________________
| STM32F103 TM1629 |
| |
| PC0-3 CSA-CSD ----> STB |
| PE14 MISO <---- MISO |
| PC6 SCLK ----> SCLK |
| PC7 MOSI ----> MOSI |
| PC4 KEYLED ----> KEYLED |
| PC5 CPULED ----> CPULED |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//TM1629片选 //STB
#define TM1629_STB GPIOC /* PC0-PC3 */
#define TM1629_CSA GPIOC, GPIO_Pin_0
#define TM1629_CSB GPIOC, GPIO_Pin_1
#define TM1629_CSC GPIOC, GPIO_Pin_2
#define TM1629_CSD GPIOC, GPIO_Pin_3
//TM1629信号脚
#define TM1629_SCLK GPIOC, GPIO_Pin_6 /*PC6 SCLK*/
#define TM1629_MOSI GPIOC, GPIO_Pin_7 /*PC7 DIN*/
#define TM1629_MISO GPIOE, GPIO_Pin_14 /*PE14 DOUT*/
//键盘指示灯使能
#define KEY_LAMP_EN GPIOC, GPIO_Pin_4 /*PC4 RESVIN*/
#define CPU_LAMP_EN GPIOC, GPIO_Pin_5 /*PC5 LAMP*/
//TM1629命令
#define TM1629_ADDR_INC 0x40
#define TM1629_ADDR_FIXED 0x44
#define TM1629_ADDR_BASE 0xc0
#define TM1629_DISP_OFF 0x80
#define TM1629_DISP_MINON 0x88
#define TM1629_DISP_MAXON 0x8f
#define TM1629_DISP_ONX 7
#define TM1629_DISP_ON (0x88+TM1629_DISP_ONX)
#define TM1629_KEY_READ 0x42
//TM1629延时
#define TM1629_DELAY 2 /* 640ns */
//TM1629应用
#define TM1629_LED_DARK 0x00
#define TM1629_LED_BRIGHT 0x7F
#define TM1629_LED_BRIGHT_DOT 0xFF
#define TM1629_CS_MASK 0xFFF0
#ifdef PART5
#define TM1629_CS_NONE 7
#else
#define TM1629_CS_NONE 0
#endif
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
const unsigned char TM1629_CODE[16]=
/*0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xb 0xC 0xd 0xE 0xF*/
{0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7C, 0x39, 0x5E, 0x79, 0x71};
const unsigned char TM1629_CODE_LED[16]=
/*0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF*/
{0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF, 0xF7, 0XFF, 0xB9, 0xBF, 0xF9, 0xF1};
const unsigned char TM1629_SEGMENT[8]=
/* a b c d e f g h*/
{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
/* Private function prototypes -----------------------------------------------*/
void TM1629_Test(void);
void TM1629_Configuration(void);
void TM1629_Write_Byte(uint8_t wrdata);
void TM1629_Write_CMD(uint8_t chip,uint8_t wrdata);
void TM1629_Write_CMD2(uint8_t chip,uint8_t wrdata);
uint8_t TM1629_Read_Byte(void);
uint32_t TM1629_Read_Keys(unsigned char chip);
void TM1629_Activation(uint8_t chip);
void TM1629_Write_Chip(uint8_t chip,uint8_t *led_data);
void TM1629_Write_Led(uint8_t chip,uint8_t led_index,uint8_t led_data);
void TM1629_Write_Leds(uint8_t chip,uint8_t index,uint32_t *data,uint8_t length);
void TM1629_Write_Digital(uint8_t chip,uint8_t led_index,uint8_t led_data);
void TM1629_Write_3Digital(uint8_t chip,uint8_t led_index,uint32_t led_data);
void TM1629_Write_Digitals(uint8_t chip,uint8_t led_index,uint32_t led_data,uint8_t digit_limit);
void TM1629_Write_Segment(uint8_t chip,uint8_t led_index,uint8_t led_data);
extern void SEND_RS485_STRING(char *s);
extern void Delay(__IO uint32_t nTime);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
void TM1629_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
uint32_t i,j;
/* Enable GPIOC, GPIOE and AFIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE);
/* Enable GPIOC PC0-PC7 output */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBits(KEY_LAMP_EN);
GPIO_ResetBits(CPU_LAMP_EN);
TM1629_Activation(TM1629_CS_NONE);
/* Enable GPIOE PE14 input */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 ;
GPIO_Init(GPIOE, &GPIO_InitStructure);
//全部熄灭
for(i=1;i<=8;i++)
{for(j=0;j<16;j++){TM1629_Write_Led(i,j,TM1629_LED_DARK);}}
GPIO_ResetBits(KEY_LAMP_EN);
}
void TM1629_Write_Byte(uint8_t wrdata)
{
uint8_t i; uint32_t j;
for(i=0;i<8;i++)
{
GPIO_ResetBits(TM1629_SCLK); //拉低时钟
if(wrdata&0x01) //最低位判断
{GPIO_SetBits(TM1629_MOSI); } //最低位为1,则写1到DIN口
else
{GPIO_ResetBits(TM1629_MOSI);} //最低位为0,则写0到DIN口
for(j=0;j<TM1629_DELAY;j++){;} //delay
GPIO_SetBits(TM1629_SCLK); //拉高时钟
for(j=0;j<TM1629_DELAY;j++){;} //delay
wrdata>>=1; //数据移到下一位
}
}
uint8_t TM1629_Read_Byte(void)
{
uint8_t i,rddata=0x0; uint32_t j;
for(i=0;i<8;i++)
{
GPIO_ResetBits(TM1629_SCLK); //拉低时钟
for(j=0;j<TM1629_DELAY;j++){;} //delay
GPIO_SetBits(TM1629_SCLK); //拉高时钟
rddata>>=1; //数据移到下一位
//DOUT为1,最高位付值为1
if(GPIO_ReadInputDataBit(TM1629_MISO)) //最高位判断
{rddata|=0x80;}
//DOUT为0,最高位付值为0
for(j=0;j<TM1629_DELAY;j++){;} //delay
}
return rddata;
}
void TM1629_Activation(uint8_t chip)
{
uint16_t temp = (GPIO_ReadOutputData(TM1629_STB)&TM1629_CS_MASK)+chip;
GPIO_Write(TM1629_STB, temp);
}
void TM1629_Write_CMD(uint8_t chip,uint8_t wrdata)
{ uint32_t j;
TM1629_Activation(TM1629_CS_NONE);
for(j=0;j<TM1629_DELAY;j++){;}//delay
TM1629_Activation(chip);
TM1629_Write_Byte(wrdata);
}
void TM1629_Write_CMD2(uint8_t chip,uint8_t wrdata)
{
TM1629_Write_CMD(chip,wrdata);
TM1629_Activation(TM1629_CS_NONE);
}
void TM1629_Write_Led(uint8_t chip,uint8_t led_index,uint8_t led_data)
{
TM1629_Write_CMD(chip,TM1629_ADDR_FIXED);
TM1629_Write_CMD(chip,TM1629_ADDR_BASE+led_index);
TM1629_Write_Byte(led_data);
TM1629_Write_CMD2(chip,TM1629_DISP_ON);
}
void TM1629_Write_Digital(uint8_t chip,uint8_t led_index,uint8_t led_data)
{TM1629_Write_Led(chip,led_index,TM1629_CODE[led_data]);}
void TM1629_Write_Segment(uint8_t chip,uint8_t led_index,uint8_t led_data)
{TM1629_Write_Led(chip,led_index,TM1629_SEGMENT[led_data]);}
void TM1629_Write_Leds(uint8_t chip,uint8_t index,uint32_t *data,uint8_t length)
{
uint8_t i;
TM1629_Write_CMD(chip,TM1629_ADDR_INC);
TM1629_Write_CMD(chip,TM1629_ADDR_BASE+index);
for(i=0;i<length;i++){TM1629_Write_Byte(data[i]);}
TM1629_Write_CMD2(chip,TM1629_DISP_ON);
}
void TM1629_Write_3Digital(uint8_t chip,uint8_t led_index,uint32_t led_data)
{
TM1629_Write_CMD(chip,TM1629_ADDR_INC);
TM1629_Write_CMD(chip,TM1629_ADDR_BASE+led_index);
TM1629_Write_Byte(TM1629_CODE[(led_data% 10)/ 1]);
TM1629_Write_Byte(TM1629_LED_DARK);
if(led_data>99)TM1629_Write_Byte(TM1629_CODE[(led_data% 1000)/ 100]);
else TM1629_Write_Byte(TM1629_LED_DARK);
if(led_data> 9)TM1629_Write_Byte(TM1629_CODE[(led_data% 100)/ 10]);
else TM1629_Write_Byte(TM1629_LED_DARK);
TM1629_Write_CMD2(chip,TM1629_DISP_ON);
}
void TM1629_Write_Digitals(uint8_t chip,uint8_t led_index,uint32_t led_data,uint8_t digit_limit)
{
uint8_t i,data[16];
data[0]=TM1629_CODE[0];
for(i=1;i<digit_limit;i++){data[i]=0x0;}
for(i=0;(led_data>0)&&(i<digit_limit);led_data/=10)
{data[i++]=TM1629_CODE[led_data%10];}
TM1629_Write_CMD(chip,TM1629_ADDR_INC);
TM1629_Write_CMD(chip,TM1629_ADDR_BASE+led_index);
for(i=0;i<digit_limit;i++)
{TM1629_Write_Byte(data[i]);}
TM1629_Write_CMD2(chip,TM1629_DISP_ON);
}
void TM1629_Write_Chip(uint8_t chip,uint8_t *led_data)
{
uint8_t i;
TM1629_Write_CMD(chip,TM1629_ADDR_INC);
TM1629_Write_CMD(chip,TM1629_ADDR_BASE);
for(i=0;i<16;i++){TM1629_Write_Byte(led_data[i]);}
TM1629_Write_CMD2(chip,TM1629_DISP_ON);
}
uint32_t TM1629_Read_Keys(uint8_t chip)
{
uint32_t i,j;
union {__IO uint32_t u32data;__IO uint8_t u8data[4];} data;
TM1629_Write_CMD(chip,TM1629_KEY_READ);
for(j=0;j<TM1629_DELAY;j++){;}//delay
for(i=0;i<4;i++){data.u8data[i]=TM1629_Read_Byte(); }
TM1629_Activation(TM1629_CS_NONE);
return data.u32data;
}
void TM1629_Clear_All(void)
{
uint8_t i,data[16];
for(i=0;i<16;i++){data[i]=0;}
TM1629_Configuration();
for(i=1;i<=9;i++)
{TM1629_Write_Chip(i,data);}
}
#endif
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
代码完毕。
基于MDK-ARM的华芯微特SWM180+RTOS的JLINK开发环境建立
一,下载软件
1,mdk:MDK-523.EXE
http://www.keil.com/fid/j34rw9wlgtwj1w3qhmw11ww3fwxbkks16d2wd1/files/eval/mdk523.exe
2,pack:Synwit.SWM32_DFP.1.0.0.pack
通过代理商或者“yuanxihua@21cn.com”获取此Pack文件。
二,安装软件
1,右击 MDK-523.EXE 用管理员权限安装到 C:\Keil ;
2,安装 Synwit.SWM32_DFP.1.0.0.pack 到 C:\Keil\ARM\PACK\Synwit\SWM32_DFP\1.1.0 ;
3,打开MDK-ARM的IDE界面,在菜单的 “project”->“Manage”->“Pack Installer”下刷新在线安装 ARM下的所有PACK包 ;
4,在MDK-ARM的IDE界面,在菜单的 “File”->“License Management”里安装上RL-ARM和 MAK-ARM Plus 的版权。
三,建立工程
1,右击桌面“Keil uVision5” 打开MDK-ARM界面,在菜单的 “project”->“New uVision Project ...”下建立项目“9g-swm180”到:
“D:\works\9G-CM0\9G-SWM180X”目录下面;
2,在弹出的“Select Device for Target ‘Target1’”选择里选择 “Synwit” 下的“SWM1800 Series”下的“SWM180xB”器件后点击“OK”
现成项目器件的选择;
3,在弹出的“Manage Run-Time Environment”里选择“CMSIS”下的“CORE”和“RTOS(API)”下的“Keil RTX”,以及“Device”下的
“Startup”及“Driver”下面的所有外设驱动,然后点击“OK”完成项目的建立;
3,在“D:\works\9G-CM0\9G-SWM180X”下建立“source”文件夹,并在MDK-ARM界面左侧“Project”下的“Target 1”下面的“Source Group1”
修改成“source”文件夹;
4,在MDK-ARM界面“File”->“New...”建立一个空文件后保存到“D:\works\9G-CM0\9G-SWM180X\source”并命名为“main.c”,并且加入到项目的
左侧的“source”文件夹中;
5,修改“main.c”文件内容如下:
#include "SWM1800.h"
int main(void)
{
SystemInit();
GPIO_Init(GPIOA, PIN8 , 1, 0, 0, 0);//GPIOA.8 配置为输出引脚,推挽输出
while(1){GPIO_InvBit(GPIOA, PIN8);for(int i=0; i<1000000; i++) {;}}
}
四,配置工程
1,打开MDK-ARM的界面,在菜单的 “Project”->“Options for Target1 ...”下“Target”里选择上“Use MicroLIB”,在“Output”里选择上“Create HEX File”,
在“Debug”里选择上“J-LINK/J-TRACE Cortex”,并在后面的“Setting”弹出的“Target device settings”里选择上“Cortex-M0”,后点击“OK”,
退回的“Debug”里面“Port:”下选择端口“SW”,看到能识别IDCODE后点击 “确定”再“OK”完成项目设置;
五,执行工程
1,利用JLINK的SWD口连接目标板到电脑的USB口,在MDK-ARM的界面菜单的 “Debug”->“Start/Stop Session”进行编译下载代码,然后按F5全速
运行程序。完成实现入门点灯全过程!
六,应用RTX
1,在“main.c”文件前部分加上头文件“#include "cmsis_os.h"”,定义两个进程号 “osThreadId idLED, idCOM;”声明两个进程“void TaskLED(void const *arg);”和“
void TaskCOM(void const *arg);”定义两个进程“osThreadDef(TaskLED, osPriorityNormal, 1, 0);”和“osThreadDef(TaskCOM, osPriorityNormal, 1, 0);”
2,在“main()”函数中加入RTOS初始化“ osKernelInitialize();”以及创建进程“idLED = osThreadCreate(osThread(TaskLED), NULL);”和“idLED = osThreadCreate(osThread(TaskCOM), NULL);”
并启动RTOS“osKernelStart();”;
3,添加两个进程实体后“main.c”如下:
#include "SWM1800.h"
#include "cmsis_os.h"
osThreadId idLED, idCOM;
void TaskLED(void const *arg);
void TaskCOM(void const *arg);
osThreadDef(TaskLED, osPriorityNormal, 1, 0);
osThreadDef(TaskCOM, osPriorityNormal, 1, 0);
void SerialInit(void);
int main(void)
{
SystemInit();
osKernelInitialize();
idLED = osThreadCreate(osThread(TaskLED), NULL);
idLED = osThreadCreate(osThread(TaskCOM), NULL);
osKernelStart();
}
void TaskLED(void const *arg)
{
GPIO_Init(GPIOA, PIN8, 1, 0, 0, 0); //GPIOA.8配置为输出引脚,推挽输出
GPIO_Init(GPIOA, PIN9, 1, 0, 0, 0); //GPIOA.9配置为输出引脚,推挽输出
GPIO_ClrBit(GPIOA, PIN8);GPIO_SetBit(GPIOA, PIN9);
while(1)
{
GPIO_InvBit(GPIOA, PIN8);GPIO_InvBit(GPIOA, PIN9);
osDelay(500);
}
}
void TaskCOM(void const *arg)
{
SerialInit();
while(1)
{
printf("Hi, World!\r\n");
osDelay(500);
}
}
void SerialInit(void)
{
UART_InitStructure UART_initStruct;
PORT_Init(PORTA, PIN0, FUNMUX_UART0_RXD, 1); //GPIOA.0配置为UART0输入引脚
PORT_Init(PORTA, PIN1, FUNMUX_UART0_TXD, 0); //GPIOA.1配置为UART0输出引脚
UART_initStruct.Baudrate = 57600;
UART_initStruct.RXThresholdIEn = 0;
UART_initStruct.TXThresholdIEn = 0;
UART_initStruct.TimeoutIEn = 0;
UART_Init(UART0, &UART_initStruct);
UART_Open(UART0);
}
int fputc(int ch, FILE *f)
{
UART_WriteByte(UART0, ch);
while(UART_IsTXBusy(UART0));
return ch;
}
4,在MDK-ARM的界面菜单的 “Debug”->“Start/Stop Session”进行编译下载代码,然后按F5全速
运行程序。
不多说请看注释及源码,有用到或转发的请记住这是缥缈九哥(yuanxihua@21cn.com)原创:
/*******************************************************************************************
WS2812S的标准时序如下:
TH+TL=1.25us±150ns, RES>50us
T0H=0.25us±150ns = 0.10us - 0.40us
T1H=1.00us±150ns = 0.85us - 1.15us
T0L=1.00us±150ns = 0.85us - 1.15us
T1L=0.25us±150ns = 0.10us - 0.40us
占空比取1:3,Bit = 0.290us - 0.350us , T=1.160us - 1.40us
用UART的TXD驱动WS2812,采用3M即0.333US的波特率。
那么起始位+D0D1D2位组合成0111做为WS2812的0码,D3D4D5D6位0001做为WS2812的1码;
或者起始位+D0D1D2位组合成0001做为WS2812的1码,D3D4D5D6位0111做为WS2812的0码;
而且剩下的D7+结束位+2位字间空隙组合成固定的1111为新的空闲位。
那么只要外置74HC04做反相功能,即可符合标准的WS2812的接收的时序要求。
即是T0H=0.333US,T0L=0.999US,T1H=0.999US,T1L=0.333US;
即是TH+TL=1.332us 小于周期1.4US,而且 IDLE=1.332uS 小于RES的50us时间,以上状态会保持下去。
结论:用连续12个字节的UART信号即可传送一个WS2812显示像素24位数据。
*********************************************************************************************/
#include "SWM1800.h"
#include "cmsis_os.h"
#include "string.h"
#include <stdlib.h>
typedef __packed struct
{
uint8_t blue;
uint8_t green;
uint8_t red;
uint8_t white;
}pixel_t;
void UART1Init(void)
{
UART_InitStructure UART_initStruct;
PORT_Init(PORTA, PIN0, FUNMUX_UART1_RXD, 1); //GPIOA.0配置为UART1输入引脚
PORT_Init(PORTA, PIN1, FUNMUX_UART1_TXD, 0); //GPIOA.1配置为UART1输出引脚
UART_initStruct.Baudrate = 3000000; //=clk/16/x BIT = 0.333us
UART_initStruct.TXThreshold = 0; //取值0--7
UART_initStruct.TXThresholdIEn = 0; //当TX FIFO中数据个数 <= TXThreshold时触发中断
UART_initStruct.RXThreshold = 7; //取值0--7
UART_initStruct.RXThresholdIEn = 1; //当RX FIFO中数据个数 >= RXThreshold时触发中断
UART_initStruct.TimeoutTime = 20; //超时时长 = TimeoutTime/(Baudrate/10) 秒
UART_initStruct.TimeoutIEn = 1; //超时中断,超过 TimeoutTime/(Baudrate/10) 秒没有在RX线上接收到数据时触发中断
UART_Init(UART1, &UART_initStruct);
UART_Open(UART1);
}
void Uart1Write(char data)
{
UART_WriteByte(UART1, data);
while(UART_IsTXBusy(UART1));
}
#if 0
void Uart1Test(void)
{
UART1Init();
while(1){Uart1Write(0x55);}
}
void Ws2812Reset(void)
{
GPIO_Init(GPIOA, PIN1, 1, 0, 0, 0); //GPIOA.1配置为输出引脚,推挽输出
GPIO_SetBit(GPIOA, PIN1);
osDelay(1);//延时60us以上
PORT_Init(PORTA, PIN1, FUNMUX_UART1_TXD, 0); //GPIOA.1配置为UART1输出引脚
}
#endif
void Ws2812WriteByte(uint8_t byte)
{
for(uint8_t i=0;i<4;i++)
{
uint8_t data=((byte&0x80)?0x04:0x07)|((byte&0x40)?0x40:0x70)|0x80; // D0-D2:D3-D6:D7
Uart1Write(data);
byte<<=2;
}
}
void Ws2812Pixel(pixel_t *pixel,uint32_t length)
{
osDelay(1);//延时1ms以复位
__disable_irq();
for(uint32_t i=0;i<length;i++)
{
Ws2812WriteByte(pixel[i].green); //绿色
Ws2812WriteByte(pixel[i].red); //红色
Ws2812WriteByte(pixel[i].blue); //蓝色
}
__enable_irq();
}
void Ws2812Test(void)
{
uint32_t i=0,j,color[8],len=8,dly=4;
UART1Init();
while(1)
{
while(i++<255){for(j=0;j<8;j++){color[j]=i<<16;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i--> 1){for(j=0;j<8;j++){color[j]=i<<16;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i++<255){for(j=0;j<8;j++){color[j]=i<< 8;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i--> 1){for(j=0;j<8;j++){color[j]=i<< 8;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i++<255){for(j=0;j<8;j++){color[j]=i<< 0;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i--> 1){for(j=0;j<8;j++){color[j]=i<< 0;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
}
}
全文完毕。
不废话,上代码:
/********************************************************************************
* @file htu20d.c *
* @brief The Driver code for HTU21D with SWM181CBT6 *
* @version 1.0.0 *
* @date 2018/08/23 01:35:35 *
* *
* @note *
* Copyright (C) 2000-2018 PM9GZY by yuanxihua@21cn.com. All rights reserved. *
********************************************************************************/
/* Includes --------------------------------------------------------------------*/
#include "wall.h"
/*
_________________________________________________
| SWM181CBT6 HTU20D |
| |
| SDA - PD3 <---> SDA |
| SCL - PD2 ---> SCL |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {START=0x01,STOP=0x02,WRD=0x04,RDA=0x08,ACK=0x10,NAK=0x20}i2c_status_t;
typedef enum {TEMP=0xF3,HUMID=0xF5,TEMPHOLD=0xE3,HUMIDHOLD=0xE5,WRUSER=0xE6,RDUSER=0xE7,RESET=0xFE}i2c_cmd_t;
/* Private define ------------------------------------------------------------*/
#define HTU20D_I2C_CLK_HZ 100000 /* Clock i2c speed 100KHz */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
void I2C0Init(void)
{
I2C_InitStructure I2C_initStruct;
PORT_Init(PORTD, PIN2, FUNMUX_I2C0_SCL, 1); //GPIOD.2配置为I2C0 SCL引脚
PORT_Init(PORTD, PIN3, FUNMUX_I2C0_SDA, 1); //GPIOD.3配置为I2C0 SDA引脚
PORTD->OPEND |= (1 << PIN2)|(1 << PIN3); //开漏
PORTD->PULLU |= (1 << PIN2)|(1 << PIN3); //上拉
I2C_initStruct.Master = 1;
I2C_initStruct.Addr7b = 1;
I2C_initStruct.MstClk = HTU20D_I2C_CLK_HZ;
I2C_initStruct.MstIEn = 0;
I2C_Init(I2C0, &I2C_initStruct);
I2C_Open(I2C0);
//After power up, the device needs at most 15ms while SCK is high
osDelay(20);
}
void I2C_SEND_STATUS(I2C_TypeDef *i2c,i2c_status_t status)
{
uint8_t cmd=0;
if(status & START){cmd |= (1 << I2C_MSTCMD_STA_Pos);} //set start
if(status & STOP ){cmd |= (1 << I2C_MSTCMD_STO_Pos);} //set stop
if(status & WRD ){cmd |= (1 << I2C_MSTCMD_WR_Pos );} //set write
if(status & RDA ){cmd |= (1 << I2C_MSTCMD_RD_Pos );} //set read
if(status & ACK ){cmd &= ~(0 << I2C_MSTCMD_ACK_Pos);} //set ack
if(status & NAK ){cmd |= (1 << I2C_MSTCMD_ACK_Pos);} //set nack
i2c->MSTCMD=cmd;while(i2c->MSTCMD & I2C_MSTCMD_TIP_Msk){;} //等待发送完成
}
uint8_t I2C_SEND_DATA(I2C_TypeDef *i2c,uint8_t data,i2c_status_t status)
{
i2c->MSTDAT=data;
I2C_SEND_STATUS(i2c,status);
return (i2c->MSTCMD & I2C_MSTCMD_RXACK_Msk)?NAK:ACK;
}
uint8_t I2C_READ_DATA(I2C_TypeDef *i2c,i2c_status_t status)
{
I2C_SEND_STATUS(i2c,status);
return i2c->MSTDAT;
}
void HTU20D_Soft_Reset(void)
{
uint8_t ack;ack=ack;
//send i2c start + address + write
ack=I2C_SEND_DATA(I2C0,0x80,START|WRD);
//send Soft Reset Command
ack=I2C_SEND_DATA(I2C0,RESET,WRD|STOP);//0xFE
//The soft reset takes less than 15ms.
osDelay(20);
}
uint8_t HTU20D_Read_User_Register(void)
{
uint8_t ack;ack=ack;
//send i2c start + address + write
ack=I2C_SEND_DATA(I2C0,0x80,START|WRD);
//send Read Register Command
ack=I2C_SEND_DATA(I2C0,RDUSER,WRD);//0xE7
//send i2c start + address + read
ack=I2C_SEND_DATA(I2C0,0x81,START|WRD);
//read Register content
uint8_t data=I2C_READ_DATA(I2C0,RDA|NAK|STOP);
//wait i2c delay
osDelay(20);
return data;
}
void HTU20D_Write_User_Register(uint8_t data)
{
uint8_t ack;ack=ack;
//send i2c start + address + write
ack=I2C_SEND_DATA(I2C0,0x80,START|WRD);
//send Write Register Command
ack=I2C_SEND_DATA(I2C0,WRUSER,WRD);//0xE6
//send Register Content to be written
ack=I2C_SEND_DATA(I2C0,data,WRD|STOP);
//wait i2c delay
osDelay(20);
}
uint16_t HTU20D_Read_Temperature_Humidity(i2c_cmd_t cmd)
{
uint8_t ack;ack=ack;
//send i2c start + address + write
ack=I2C_SEND_DATA(I2C0,0x80,START|WRD);
//send Read Register Command
ack=I2C_SEND_DATA(I2C0,cmd,WRD);
//continue measuring
while(I2C_SEND_DATA(I2C0,0x81,START|WRD)==NAK){;}
//read Register content MSB
uint16_t data =I2C_READ_DATA(I2C0,RDA|ACK);
//read Register content LSB
data=(data<<8)+I2C_READ_DATA(I2C0,RDA|ACK);
//read Checksum
uint16_t cks = I2C_READ_DATA(I2C0,RDA|NAK|STOP);
//wait i2c delay
osDelay(20);
return data;
}
void HTU20D_Read(float *Temperature, float *Humidity)
{
float temp;
temp=HTU20D_Read_Temperature_Humidity(TEMP )&0xfffc;
// printf("HTU20D_Read Temperature=0x%x\n\r",(int)temp);
*Temperature=((temp*175.72)/65536)-46.85;
temp=HTU20D_Read_Temperature_Humidity(HUMID)&0xfffc;
// printf("HTU20D_Read Humidity =0x%x\n\r",(int)temp);
*Humidity=((temp*125)/65536)-6;
}
void HTU20D_test(void)
{
float Humidity,Temperature;
HTU20D_Soft_Reset();
HTU20D_Write_User_Register(0x00);
printf("HTU20D User_Registe=0x%02x\n\r",HTU20D_Read_User_Register());
HTU20D_Read(&Temperature,&Humidity);
printf("HTU20D Trigger No Hold T=%f 摄氏度 H=%f %%RH\n\r",Temperature,Humidity);
}
//代码完毕
页次: 1