add cortex-v7a support

How To Run:
    see TencentOS-tiny\board\ALPHA_I.MX_emmc_256ddr\README.md

TODO Next:
1. VFP support
2. fault diagnosis support
3. qemu vexpress ca9 support
4. raspberry pi support
5. SMP support
This commit is contained in:
daishengdong
2020-01-19 19:06:24 +08:00
parent 08ab1d88e1
commit 3d9d6198c8
115 changed files with 98070 additions and 29 deletions

View File

@@ -0,0 +1,315 @@
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_i2c.c
作者 : 左忠凯
版本 : V1.0
描述 : IIC驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/15 左忠凯创建
***************************************************************/
#include "bsp_i2c.h"
#include "bsp_delay.h"
#include "printf.h"
/*
* @description : 初始化I2C波特率100KHZ
* @param - base : 要初始化的IIC设置
* @return : 无
*/
void i2c_init(I2C_Type *base)
{
/* 1、配置I2C */
base->I2CR &= ~(1 << 7); /* 要访问I2C的寄存器首先需要先关闭I2C */
/* 设置波特率为100K
* I2C的时钟源来源于IPG_CLK_ROOT=66Mhz
* IC2 时钟 = PERCLK_ROOT/dividison(IFDR寄存器)
* 设置寄存器IFDR,IFDR寄存器参考IMX6UL参考手册P1260页表29-3
* 根据表29-3里面的值挑选出一个还是的分频数比如本例程我们
* 设置I2C的波特率为100K 因此当分频值=66000000/100000=660.
* 在表29-3里面查找没有660这个值但是有640因此就用640,
* 即寄存器IFDR的IC位设置为0X15
*/
base->IFDR = 0X15 << 0;
/*
* 设置寄存器I2CR开启I2C
* bit[7] : 1 使能I2C,I2CR寄存器其他位其作用之前此位必须最先置1
*/
base->I2CR |= (1<<7);
}
/*
* @description : 发送重新开始信号
* @param - base : 要使用的IIC
* @param - addrss : 设备地址
* @param - direction : 方向
* @return : 0 正常 其他值 出错
*/
unsigned char i2c_master_repeated_start(I2C_Type *base, unsigned char address, enum i2c_direction direction)
{
/* I2C忙并且工作在从模式,跳出 */
if(base->I2SR & (1 << 5) && (((base->I2CR) & (1 << 5)) == 0))
return 1;
/*
* 设置寄存器I2CR
* bit[4]: 1 发送
* bit[2]: 1 产生重新开始信号
*/
base->I2CR |= (1 << 4) | (1 << 2);
/*
* 设置寄存器I2DR
* bit[7:0] : 要发送的数据,这里写入从设备地址
* 参考资料:IMX6UL参考手册P1249
*/
base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
return 0;
}
/*
* @description : 发送开始信号
* @param - base : 要使用的IIC
* @param - addrss : 设备地址
* @param - direction : 方向
* @return : 0 正常 其他值 出错
*/
unsigned char i2c_master_start(I2C_Type *base, unsigned char address, enum i2c_direction direction)
{
if(base->I2SR & (1 << 5)) /* I2C忙 */
return 1;
/*
* 设置寄存器I2CR
* bit[5]: 1 主模式
* bit[4]: 1 发送
*/
base->I2CR |= (1 << 5) | (1 << 4);
/*
* 设置寄存器I2DR
* bit[7:0] : 要发送的数据,这里写入从设备地址
* 参考资料:IMX6UL参考手册P1249
*/
base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
return 0;
}
/*
* @description : 检查并清除错误
* @param - base : 要使用的IIC
* @param - status : 状态
* @return : 状态结果
*/
unsigned char i2c_check_and_clear_error(I2C_Type *base, unsigned int status)
{
/* 检查是否发生仲裁丢失错误 */
if(status & (1<<4))
{
base->I2SR &= ~(1<<4); /* 清除仲裁丢失错误位 */
base->I2CR &= ~(1 << 7); /* 先关闭I2C */
base->I2CR |= (1 << 7); /* 重新打开I2C */
return I2C_STATUS_ARBITRATIONLOST;
}
else if(status & (1 << 0)) /* 没有接收到从机的应答信号 */
{
return I2C_STATUS_NAK; /* 返回NAK(No acknowledge) */
}
return I2C_STATUS_OK;
}
/*
* @description : 停止信号
* @param - base : 要使用的IIC
* @param : 无
* @return : 状态结果
*/
unsigned char i2c_master_stop(I2C_Type *base)
{
unsigned short timeout = 0xffff;
/*
* 清除I2CR的bit[5:3]这三位
*/
base->I2CR &= ~((1 << 5) | (1 << 4) | (1 << 3));
/* 等待忙结束 */
while((base->I2SR & (1 << 5)))
{
timeout--;
if(timeout == 0) /* 超时跳出 */
return I2C_STATUS_TIMEOUT;
}
return I2C_STATUS_OK;
}
/*
* @description : 发送数据
* @param - base : 要使用的IIC
* @param - buf : 要发送的数据
* @param - size : 要发送的数据大小
* @param - flags : 标志
* @return : 无
*/
void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size)
{
/* 等待传输完成 */
while(!(base->I2SR & (1 << 7)));
base->I2SR &= ~(1 << 1); /* 清除标志位 */
base->I2CR |= 1 << 4; /* 发送数据 */
while(size--)
{
base->I2DR = *buf++; /* 将buf中的数据写入到I2DR寄存器 */
while(!(base->I2SR & (1 << 1))); /* 等待传输完成 */
base->I2SR &= ~(1 << 1); /* 清除标志位 */
/* 检查ACK */
if(i2c_check_and_clear_error(base, base->I2SR))
break;
}
base->I2SR &= ~(1 << 1);
i2c_master_stop(base); /* 发送停止信号 */
}
/*
* @description : 读取数据
* @param - base : 要使用的IIC
* @param - buf : 读取到数据
* @param - size : 要读取的数据大小
* @return : 无
*/
void i2c_master_read(I2C_Type *base, unsigned char *buf, unsigned int size)
{
volatile uint8_t dummy = 0;
dummy++; /* 防止编译报错 */
/* 等待传输完成 */
while(!(base->I2SR & (1 << 7)));
base->I2SR &= ~(1 << 1); /* 清除中断挂起位 */
base->I2CR &= ~((1 << 4) | (1 << 3)); /* 接收数据 */
/* 如果只接收一个字节数据的话发送NACK信号 */
if(size == 1)
base->I2CR |= (1 << 3);
dummy = base->I2DR; /* 假读 */
while(size--)
{
while(!(base->I2SR & (1 << 1))); /* 等待传输完成 */
base->I2SR &= ~(1 << 1); /* 清除标志位 */
if(size == 0)
{
i2c_master_stop(base); /* 发送停止信号 */
}
if(size == 1)
{
base->I2CR |= (1 << 3);
}
*buf++ = base->I2DR;
}
}
/*
* @description : I2C数据传输包括读和写
* @param - base: 要使用的IIC
* @param - xfer: 传输结构体
* @return : 传输结果,0 成功,其他值 失败;
*/
unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer)
{
unsigned char ret = 0;
enum i2c_direction direction = xfer->direction;
base->I2SR &= ~((1 << 1) | (1 << 4)); /* 清除标志位 */
/* 等待传输完成 */
while(!((base->I2SR >> 7) & 0X1)){};
/* 如果是读的话,要先发送寄存器地址,所以要先将方向改为写 */
if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read))
{
direction = kI2C_Write;
}
ret = i2c_master_start(base, xfer->slaveAddress, direction); /* 发送开始信号 */
if(ret)
{
return ret;
}
while(!(base->I2SR & (1 << 1))){}; /* 等待传输完成 */
ret = i2c_check_and_clear_error(base, base->I2SR); /* 检查是否出现传输错误 */
if(ret)
{
i2c_master_stop(base); /* 发送出错,发送停止信号 */
return ret;
}
/* 发送寄存器地址 */
if(xfer->subaddressSize)
{
do
{
base->I2SR &= ~(1 << 1); /* 清除标志位 */
xfer->subaddressSize--; /* 地址长度减一 */
base->I2DR = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); //向I2DR寄存器写入子地址
while(!(base->I2SR & (1 << 1))); /* 等待传输完成 */
/* 检查是否有错误发生 */
ret = i2c_check_and_clear_error(base, base->I2SR);
if(ret)
{
i2c_master_stop(base); /* 发送停止信号 */
return ret;
}
} while ((xfer->subaddressSize > 0) && (ret == I2C_STATUS_OK));
if(xfer->direction == kI2C_Read) /* 读取数据 */
{
base->I2SR &= ~(1 << 1); /* 清除中断挂起位 */
i2c_master_repeated_start(base, xfer->slaveAddress, kI2C_Read); /* 发送重复开始信号和从机地址 */
while(!(base->I2SR & (1 << 1))){};/* 等待传输完成 */
/* 检查是否有错误发生 */
ret = i2c_check_and_clear_error(base, base->I2SR);
if(ret)
{
ret = I2C_STATUS_ADDRNAK;
i2c_master_stop(base); /* 发送停止信号 */
return ret;
}
}
}
/* 发送数据 */
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
{
i2c_master_write(base, xfer->data, xfer->dataSize);
}
/* 读取数据 */
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
{
i2c_master_read(base, xfer->data, xfer->dataSize);
}
return 0;
}

View File

@@ -0,0 +1,61 @@
#ifndef _BSP_I2C_H
#define _BSP_I2C_H
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_i2c.c
作者 : 左忠凯
版本 : V1.0
描述 : IIC驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/1/15 左忠凯创建
***************************************************************/
#include "bsp.h"
/* 相关宏定义 */
#define I2C_STATUS_OK (0)
#define I2C_STATUS_BUSY (1)
#define I2C_STATUS_IDLE (2)
#define I2C_STATUS_NAK (3)
#define I2C_STATUS_ARBITRATIONLOST (4)
#define I2C_STATUS_TIMEOUT (5)
#define I2C_STATUS_ADDRNAK (6)
/*
* I2C方向枚举类型
*/
enum i2c_direction
{
kI2C_Write = 0x0, /* 主机向从机写数据 */
kI2C_Read = 0x1, /* 主机从从机读数据 */
} ;
/*
* 主机传输结构体
*/
struct i2c_transfer
{
unsigned char slaveAddress; /* 7位从机地址 */
enum i2c_direction direction; /* 传输方向 */
unsigned int subaddress; /* 寄存器地址 */
unsigned char subaddressSize; /* 寄存器地址长度 */
unsigned char *volatile data; /* 数据缓冲区 */
volatile unsigned int dataSize; /* 数据缓冲区长度 */
};
/*
*函数声明
*/
void i2c_init(I2C_Type *base);
unsigned char i2c_master_start(I2C_Type *base, unsigned char address, enum i2c_direction direction);
unsigned char i2c_master_repeated_start(I2C_Type *base, unsigned char address, enum i2c_direction direction);
unsigned char i2c_check_and_clear_error(I2C_Type *base, unsigned int status);
unsigned char i2c_master_stop(I2C_Type *base);
void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size);
void i2c_master_read(I2C_Type *base, unsigned char *buf, unsigned int size);
unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer);
#endif