617 lines
16 KiB
C
617 lines
16 KiB
C
|
#include "asm/iic_hw.h"
|
|||
|
#include "system/generic/gpio.h"
|
|||
|
#include "system/generic/log.h"
|
|||
|
#include "asm/clock.h"
|
|||
|
#include "asm/cpu.h"
|
|||
|
|
|||
|
/*
|
|||
|
[[ 注意!!! ]]
|
|||
|
* 适用于带cfg_done的硬件IIC,另一种硬件IIC另作说明
|
|||
|
* 硬件IIC的START / ACK(NACK)必须在发送或接收字节cfg_done前设置,且不能
|
|||
|
接cfg_done单独发送;而STOP则应在发送或接收字节cfg_done后设置,必须接
|
|||
|
cfg_done单独发送
|
|||
|
*/
|
|||
|
|
|||
|
/* const struct hw_iic_config hw_iic_cfg_test[] = { */
|
|||
|
/* //iic0 data */
|
|||
|
/* { */
|
|||
|
/* // SCL SDA */
|
|||
|
/* .port = {IO_PORTA_06, IO_PORTA_07}, */
|
|||
|
/* .baudrate = 100000, //IIC通讯波特率 */
|
|||
|
/* .hdrive = 0, //是否打开IO口强驱 */
|
|||
|
/* .io_filter = 1, //是否打开滤波器(去纹波) */
|
|||
|
/* .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 */
|
|||
|
/* .role = IIC_MASTER, */
|
|||
|
/* }, */
|
|||
|
/* }; */
|
|||
|
|
|||
|
static JL_IIC_TypeDef *const iic_regs[IIC_HW_NUM] = {
|
|||
|
JL_IIC,
|
|||
|
};
|
|||
|
|
|||
|
#define iic_get_id(iic) (iic)
|
|||
|
|
|||
|
#define iic_info_port(iic, x) (hw_iic_cfg[iic_get_id(iic)].port[x])
|
|||
|
#define iic_info_baud(iic) (hw_iic_cfg[iic_get_id(iic)].baudrate)
|
|||
|
#define iic_info_hdrive(iic) (hw_iic_cfg[iic_get_id(iic)].hdrive)
|
|||
|
#define iic_info_io_filt(iic) (hw_iic_cfg[iic_get_id(iic)].io_filter)
|
|||
|
#define iic_info_io_pu(iic) (hw_iic_cfg[iic_get_id(iic)].io_pu)
|
|||
|
#define iic_info_role(iic) (hw_iic_cfg[iic_get_id(iic)].role)
|
|||
|
|
|||
|
static inline u32 iic_get_scl(hw_iic_dev iic)
|
|||
|
{
|
|||
|
u8 port = iic_info_port(iic, 0);
|
|||
|
return port;
|
|||
|
}
|
|||
|
|
|||
|
static inline u32 iic_get_sda(hw_iic_dev iic)
|
|||
|
{
|
|||
|
u8 port = iic_info_port(iic, 1);
|
|||
|
return port;
|
|||
|
}
|
|||
|
|
|||
|
static int iic_port_init(hw_iic_dev iic)
|
|||
|
{
|
|||
|
u32 reg;
|
|||
|
int ret = 0;
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
u32 scl, sda;
|
|||
|
scl = iic_get_scl(iic);
|
|||
|
sda = iic_get_sda(iic);
|
|||
|
if (id == 0) {
|
|||
|
gpio_set_fun_output_port(scl, FO_IIC_SCL, 1, 1);
|
|||
|
gpio_set_fun_output_port(sda, FO_IIC_SDA, 1, 1);
|
|||
|
gpio_set_fun_input_port(scl, PFI_IIC_SCL);
|
|||
|
gpio_set_fun_input_port(sda, PFI_IIC_SDA);
|
|||
|
if (scl >= IO_PORT_DP || sda >= IO_PORT_DP) {
|
|||
|
usb_iomode(1);
|
|||
|
}
|
|||
|
if (iic_info_hdrive(iic)) {
|
|||
|
gpio_set_hd(scl, 1);
|
|||
|
gpio_set_hd(sda, 1);
|
|||
|
} else {
|
|||
|
gpio_set_hd(scl, 0);
|
|||
|
gpio_set_hd(sda, 0);
|
|||
|
}
|
|||
|
if (iic_info_io_pu(iic)) {
|
|||
|
gpio_set_pull_up(scl, 1);
|
|||
|
gpio_set_pull_down(scl, 0);
|
|||
|
gpio_set_pull_up(sda, 1);
|
|||
|
gpio_set_pull_down(sda, 0);
|
|||
|
} else {
|
|||
|
gpio_set_pull_up(scl, 0);
|
|||
|
gpio_set_pull_down(scl, 0);
|
|||
|
gpio_set_pull_up(sda, 0);
|
|||
|
gpio_set_pull_down(sda, 0);
|
|||
|
}
|
|||
|
} else {
|
|||
|
ret = -EINVAL;
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
int hw_iic_set_baud(hw_iic_dev iic, u32 baud)
|
|||
|
{
|
|||
|
//f_iic = f_sys / (IIC_BAUD * 2)
|
|||
|
//=> IIC_BAUD = f_sys / (2 * f_iic)
|
|||
|
u32 sysclk;
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
|
|||
|
sysclk = clk_get("lsb");
|
|||
|
/* printf("lsb clk:%d",sysclk); */
|
|||
|
if (sysclk < 2 * baud) {
|
|||
|
return -EINVAL;
|
|||
|
}
|
|||
|
iic_baud_reg(iic_regs[id]) = sysclk / (2 * baud);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
static void hw_iic_set_die(hw_iic_dev iic, u8 en)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
u32 scl, sda;
|
|||
|
scl = iic_get_scl(iic);
|
|||
|
sda = iic_get_sda(iic);
|
|||
|
if (id == 0) {
|
|||
|
gpio_set_die(scl, en);
|
|||
|
gpio_set_die(sda, en);
|
|||
|
} else {
|
|||
|
//undefined
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void hw_iic_suspend(hw_iic_dev iic)
|
|||
|
{
|
|||
|
hw_iic_set_die(iic, 0);
|
|||
|
}
|
|||
|
|
|||
|
void hw_iic_resume(hw_iic_dev iic)
|
|||
|
{
|
|||
|
hw_iic_set_die(iic, 1);
|
|||
|
}
|
|||
|
|
|||
|
int hw_iic_init(hw_iic_dev iic)
|
|||
|
{
|
|||
|
int ret;
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
|
|||
|
if ((ret = iic_port_init(iic))) {
|
|||
|
printf("invalid hardware iic port\n");
|
|||
|
return ret;
|
|||
|
}
|
|||
|
hw_iic_set_die(iic, 1);
|
|||
|
if (iic_info_role(iic) == IIC_MASTER) {
|
|||
|
iic_host_mode(iic_regs[id]);
|
|||
|
if ((ret = hw_iic_set_baud(iic, iic_info_baud(iic)))) {
|
|||
|
printf("iic baudrate is invalid\n");
|
|||
|
return ret ;
|
|||
|
}
|
|||
|
} else {
|
|||
|
iic_slave_mode(iic_regs[id]);
|
|||
|
iic_slave_scl_pull_down_enble(iic_regs[id]); //在收到/在发送数据时把SCL拉低
|
|||
|
iic_dir_in(iic_regs[id]);
|
|||
|
}
|
|||
|
if (iic_info_io_filt(iic)) {
|
|||
|
iic_isel_filter(iic_regs[id]);
|
|||
|
} else {
|
|||
|
iic_isel_direct(iic_regs[id]);
|
|||
|
}
|
|||
|
|
|||
|
iic_auto_ack(iic_regs[id]);
|
|||
|
iic_int_disable(iic_regs[id]);
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
iic_enable(iic_regs[id]);
|
|||
|
/* iic_disable(iic_regs[id]); */
|
|||
|
#if 0
|
|||
|
printf("info->scl = %d\n", iic_get_scl(iic));
|
|||
|
printf("info->sda = %d\n", iic_get_sda(iic));
|
|||
|
printf("info->baudrate = %d\n", iic_info_baud(iic));
|
|||
|
printf("info->hdrive = %d\n", iic_info_hdrive(iic));
|
|||
|
printf("info->io_filter = %d\n", iic_info_io_filt(iic));
|
|||
|
printf("info->io_pu = %d\n", iic_info_io_pu(iic));
|
|||
|
printf("info->role = %d\n", iic_info_role(iic));
|
|||
|
printf("IIC_CON0 0x%04x\n", iic_regs[id]->CON0);
|
|||
|
printf("IIC_CON1 0x%04x\n", iic_regs[id]->CON1);
|
|||
|
printf("IIC_BAUD 0x%02x\n", iic_regs[id]->BAUD);
|
|||
|
//printf("IIC_BUF %02x\n", iic_regs[id]->BUF);
|
|||
|
printf("IOMC1 0x%08x\n", JL_IOMAP->CON1);
|
|||
|
#endif
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
void hw_iic_uninit(hw_iic_dev iic)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
u32 scl, sda;
|
|||
|
|
|||
|
scl = iic_get_scl(iic);
|
|||
|
sda = iic_get_sda(iic);
|
|||
|
hw_iic_set_die(iic, 0);
|
|||
|
if (id == 0) {
|
|||
|
gpio_set_hd(scl, 0);
|
|||
|
gpio_set_hd(sda, 0);
|
|||
|
gpio_set_pull_up(scl, 0);
|
|||
|
gpio_set_pull_up(sda, 0);
|
|||
|
if (scl >= IO_PORT_DP || sda >= IO_PORT_DP) {
|
|||
|
usb_iomode(0);
|
|||
|
}
|
|||
|
}
|
|||
|
iic_disable(iic_regs[id]);
|
|||
|
}
|
|||
|
|
|||
|
static u8 start_signal = 0;
|
|||
|
static u8 end_signal = 0;
|
|||
|
void hw_iic_start(hw_iic_dev iic)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
/* iic_enable(iic_regs[id]); */
|
|||
|
start_signal |= BIT(7);
|
|||
|
start_signal++;
|
|||
|
if ((start_signal & 0x7f) == 2) {
|
|||
|
start_signal &= ~BIT(7);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void hw_iic_stop(hw_iic_dev iic)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
/* iic_disable(iic_regs[id]); */
|
|||
|
iic_host_send_stop(iic_regs[id]); //stop singal
|
|||
|
start_signal = 0;
|
|||
|
while (!iic_host_is_stop_pending(iic_regs[id]));
|
|||
|
}
|
|||
|
|
|||
|
u8 hw_iic_tx_byte(hw_iic_dev iic, u8 byte)
|
|||
|
{
|
|||
|
u8 ack = 0;
|
|||
|
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
|
|||
|
iic_dir_out(iic_regs[id]);
|
|||
|
|
|||
|
if ((start_signal & 0x7f) >= 2) { //连续两次起始信号则进入发送地址并接收模式
|
|||
|
iic_dir_in(iic_regs[id]);
|
|||
|
iic_host_receive_continue_byte(iic_regs[id]);
|
|||
|
iic_restart(iic_regs[id]);
|
|||
|
/* printf("rst/\n"); */
|
|||
|
}
|
|||
|
|
|||
|
iic_buf_reg(iic_regs[id]) = byte;
|
|||
|
|
|||
|
if (start_signal & BIT(7)) {
|
|||
|
iic_kick_start(iic_regs[id]); //kick start
|
|||
|
start_signal &= ~BIT(7);
|
|||
|
/* printf("st/\n"); */
|
|||
|
}
|
|||
|
|
|||
|
while (!iic_is_pnding(iic_regs[id]));
|
|||
|
|
|||
|
if (!iic_host_send_is_ack(iic_regs[id])) {
|
|||
|
ack = 1;
|
|||
|
}
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
|
|||
|
|
|||
|
return ack;
|
|||
|
}
|
|||
|
|
|||
|
u8 hw_iic_rx_byte(hw_iic_dev iic, u8 ack)
|
|||
|
{
|
|||
|
u8 data = 0;
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
iic_dir_in(iic_regs[id]);
|
|||
|
|
|||
|
iic_host_receive_continue_byte(iic_regs[id]);
|
|||
|
|
|||
|
iic_host_read_kick_start(iic_regs[id]);
|
|||
|
|
|||
|
if (ack) {
|
|||
|
} else {
|
|||
|
iic_host_nack_auto_stop(iic_regs[id]); //硬件检测到nack(这个nack是我们硬件发出的), 自动长生stop信号
|
|||
|
iic_host_receive_continue_byte_stop(iic_regs[id]); //最后1byte, 完成后自动nack;
|
|||
|
}
|
|||
|
while (!iic_is_pnding(iic_regs[id]));
|
|||
|
data = iic_buf_reg(iic_regs[id]);
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
|
|||
|
return data;
|
|||
|
}
|
|||
|
|
|||
|
int hw_iic_write_buf(hw_iic_dev iic, const void *buf, int len)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
int i = 0;
|
|||
|
|
|||
|
if (!buf || !len) {
|
|||
|
return -1;
|
|||
|
}
|
|||
|
iic_dir_out(iic_regs[id]);
|
|||
|
|
|||
|
for (i = 0; i < len; i++) {
|
|||
|
iic_buf_reg(iic_regs[id]) = ((u8 *)buf)[i];
|
|||
|
/* if (i == 0) { */
|
|||
|
/* iic_kick_start(iic_regs[id]); //kick start */
|
|||
|
/* } */
|
|||
|
while (!iic_is_pnding(iic_regs[id]));
|
|||
|
|
|||
|
if (iic_host_send_is_ack(iic_regs[id])) {
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
break;
|
|||
|
}
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
return i;
|
|||
|
}
|
|||
|
|
|||
|
int hw_iic_read_buf(hw_iic_dev iic, void *buf, int len)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
int i;
|
|||
|
if (!buf || !len) {
|
|||
|
return -1;
|
|||
|
}
|
|||
|
iic_dir_in(iic_regs[id]);
|
|||
|
iic_host_receive_continue_byte(iic_regs[id]);
|
|||
|
|
|||
|
for (i = 0; i < len; i++) {
|
|||
|
iic_host_read_kick_start(iic_regs[id]);
|
|||
|
if (i == len - 1) {
|
|||
|
iic_host_nack_auto_stop(iic_regs[id]); //硬件检测到nack(这个nack是我们硬件发出的), 自动长生stop信号
|
|||
|
iic_host_receive_continue_byte_stop(iic_regs[id]); //最后1byte, 完成后自动nack;
|
|||
|
}
|
|||
|
while (!iic_is_pnding(iic_regs[id]));
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
|
|||
|
((u8 *)buf)[i] = iic_buf_reg(iic_regs[id]);
|
|||
|
}
|
|||
|
return len;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*================================= IIC slave mode ============================*/
|
|||
|
//测试:需两个,一个下载host_test程序,一个下载slave_test程序.宏:IIC_SLAVE_BYTE_MODE_EN控制从机接收方式
|
|||
|
static int cur_iic = 0;
|
|||
|
#define IIC_SLAVE_BYTE_MODE_EN 1 //1:iic slave byte rx ; 0:iic slave dma rx
|
|||
|
#define IIC_SLAVE_wADDR 0xB0
|
|||
|
#define IIC_SLAVE_rADDR 0xB1
|
|||
|
|
|||
|
enum {
|
|||
|
IIC_STATE_START = 0,
|
|||
|
IIC_STATE_RECEIVE,
|
|||
|
IIC_STATE_SEND,
|
|||
|
};
|
|||
|
#define RX_LEN 80
|
|||
|
u8 rx_data[RX_LEN];
|
|||
|
|
|||
|
___interrupt
|
|||
|
static void hw_iic_slave_irq(void)
|
|||
|
{
|
|||
|
#if IIC_SLAVE_BYTE_MODE_EN //byte mode test
|
|||
|
static u8 iic_slave_state = IIC_STATE_START;
|
|||
|
static u8 receive_cnt = 0;
|
|||
|
/*========= 1.从机单byte 发送和接收 ============*/
|
|||
|
u8 id = iic_get_id(cur_iic);
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
if (iic_slave_state == IIC_STATE_START) {
|
|||
|
if (iic_slave_is_required_send(iic_regs[id])) {
|
|||
|
iic_dir_out(iic_regs[id]);
|
|||
|
iic_slave_state = IIC_STATE_SEND;
|
|||
|
/* printf("Send"); */
|
|||
|
goto _slave_isr_send;
|
|||
|
} else {
|
|||
|
iic_dir_in(iic_regs[id]);
|
|||
|
iic_slave_state = IIC_STATE_RECEIVE;
|
|||
|
/* printf("Receive"); */
|
|||
|
receive_cnt = 0;
|
|||
|
goto _slave_isr_end;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*========= 1-1.从机单byte 接收 ============*/
|
|||
|
#define REV_CNT RX_LEN
|
|||
|
if (iic_slave_state == IIC_STATE_RECEIVE) {
|
|||
|
rx_data[receive_cnt++] = iic_buf_reg(iic_regs[id]);
|
|||
|
/* HOW To Know END (stop singal)*/
|
|||
|
if (receive_cnt < REV_CNT - 1) {
|
|||
|
} else if (receive_cnt < REV_CNT) {
|
|||
|
iic_force_nack(iic_regs[id]); //从机收到最后1byte,会nack
|
|||
|
/* printf("nack\n"); */
|
|||
|
} else {
|
|||
|
iic_auto_ack(iic_regs[id]);
|
|||
|
iic_slave_state = IIC_STATE_START;
|
|||
|
put_buf(rx_data, receive_cnt); //接受完成
|
|||
|
}
|
|||
|
}
|
|||
|
/*========= 1-2.从机单byte 发送 ============*/
|
|||
|
_slave_isr_send:
|
|||
|
if (iic_slave_state == IIC_STATE_SEND) {
|
|||
|
static u8 send_byte = 0x0;
|
|||
|
if (iic_slave_send_is_end(iic_regs[id])) { //主机回了nack
|
|||
|
iic_slave_state = IIC_STATE_START;
|
|||
|
send_byte = 0;
|
|||
|
printf("host nack\n");
|
|||
|
} else {
|
|||
|
/* printf(" slave send: 0x%x", send_byte); */
|
|||
|
iic_buf_reg(iic_regs[id]) = send_byte++;
|
|||
|
}
|
|||
|
}
|
|||
|
#else //DMA mode test
|
|||
|
/*========= 3.从机dma 接收 ============*/
|
|||
|
/*========= pending条件 addr + dma buf full ============*/
|
|||
|
u8 id = iic_get_id(cur_iic);
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
if (iic_slave_dma_is_enable(iic_regs[id])) {
|
|||
|
u32 buf_len = iic_slave_dma_get_buf_len(iic_regs[id]);
|
|||
|
/* iic_slave_dma_disable(iic_regs[id]); */
|
|||
|
iic_force_nack(iic_regs[id]);
|
|||
|
iic_auto_ack(iic_regs[id]);
|
|||
|
printf("dma end. rx len:%d\n", buf_len);
|
|||
|
put_buf((u8 *)iic_slave_dma_buf(iic_regs[id]), buf_len);
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
_slave_isr_end:
|
|||
|
/*iic_pnding_clr(iic_regs[id]);*/
|
|||
|
iic_slave_scl_pull_down_release(iic_regs[id]);
|
|||
|
}
|
|||
|
|
|||
|
void hw_iic_set_slave_addr(hw_iic_dev iic, u8 slave_addr)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
iic_baud_reg(iic_regs[id]) = slave_addr;
|
|||
|
}
|
|||
|
|
|||
|
int hw_iic_slave_init(hw_iic_dev iic, u8 dma_en, u32 *buf, u32 buf_len)
|
|||
|
{
|
|||
|
int ret;
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
hw_iic_init(iic);//结构体成员: role=IIC_SLAVE
|
|||
|
|
|||
|
iic_disable(iic_regs[id]);
|
|||
|
//设置从机地址
|
|||
|
hw_iic_set_slave_addr(iic, IIC_SLAVE_wADDR); //从机地址
|
|||
|
iic_dir_in(iic_regs[id]);
|
|||
|
//从机dma
|
|||
|
if (dma_en) {
|
|||
|
if (buf) {
|
|||
|
/*iic_slave_dma_big_endian(iic_regs[id]);*/
|
|||
|
iic_slave_dma_little_endian(iic_regs[id]);
|
|||
|
iic_slave_dma_buf(iic_regs[id]) = (u32)buf;
|
|||
|
if (((u32)buf % 4) != 0) {
|
|||
|
printf("dma buf not align 4");
|
|||
|
}
|
|||
|
iic_slave_dma_buf_depth(iic_regs[id]) = buf_len ;//单位: 32bit
|
|||
|
iic_slave_dma_enable(iic_regs[id]);
|
|||
|
} else {
|
|||
|
printf("IIC SLAVE DMA BUF NULL");
|
|||
|
}
|
|||
|
} else {
|
|||
|
iic_slave_dma_disable(iic_regs[id]);
|
|||
|
}
|
|||
|
//中断
|
|||
|
request_irq(IRQ_IIC_IDX, 1, hw_iic_slave_irq, 0);
|
|||
|
iic_int_enable(iic_regs[id]); //中断使能
|
|||
|
|
|||
|
cur_iic = iic;
|
|||
|
|
|||
|
iic_enable(iic_regs[id]);
|
|||
|
iic_kick_start(iic_regs[id]);
|
|||
|
#if 0
|
|||
|
printf("info->scl = %d\n", iic_get_scl(iic));
|
|||
|
printf("info->sda = %d\n", iic_get_sda(iic));
|
|||
|
printf("info->baudrate = %d\n", iic_info_baud(iic));
|
|||
|
printf("info->hdrive = %d\n", iic_info_hdrive(iic));
|
|||
|
printf("info->io_filter = %d\n", iic_info_io_filt(iic));
|
|||
|
printf("info->io_pu = %d\n", iic_info_io_pu(iic));
|
|||
|
printf("IIC_CON0 0x%04x\n", iic_regs[id]->CON0);
|
|||
|
printf("IIC_BAUD 0x%02x\n", iic_regs[id]->BAUD);
|
|||
|
#endif
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*================iic slave int test================*/
|
|||
|
static u32 dma_buf[20] __attribute__((aligned(4)));
|
|||
|
int hw_iic_slave_test(void)
|
|||
|
{
|
|||
|
int tmp = 0;
|
|||
|
//结构体成员: role=IIC_SLAVE
|
|||
|
#if IIC_SLAVE_BYTE_MODE_EN //byte mode test
|
|||
|
hw_iic_slave_init(0, 0, NULL, 0);
|
|||
|
printf("\niic slave byte test:\t");
|
|||
|
#else //dma mode test
|
|||
|
hw_iic_slave_init(0, 1, dma_buf, sizeof(dma_buf) / 4);
|
|||
|
printf("\niic slave dma test:\t");
|
|||
|
#endif
|
|||
|
__asm__ volatile("%0 =icfg" : "=r"(tmp)); //读
|
|||
|
printf("%s icfg = 0x%x\n", __func__, tmp);
|
|||
|
#if 0
|
|||
|
u32 con2 = 0;
|
|||
|
u32 *addr = NULL;
|
|||
|
addr = (u8 *)iic_slave_dma_buf(iic_regs[0]);
|
|||
|
con2 = iic_slave_dma_buf_depth(iic_regs[0]);
|
|||
|
while (1) {
|
|||
|
if (con2 != iic_slave_dma_buf_depth(iic_regs[0])) {
|
|||
|
asm("trigger");
|
|||
|
con2 = iic_slave_dma_buf_depth(iic_regs[0]);
|
|||
|
printf("dma con2: 0x%x, data = 0x%x @ 0x%x", con2, *(addr + (con2 >> 16)), addr + (con2 >> 16));
|
|||
|
}
|
|||
|
delay(1000);
|
|||
|
};
|
|||
|
#endif
|
|||
|
|
|||
|
delay(10000);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*================iic host int test================*/
|
|||
|
volatile u8 flag = 0;
|
|||
|
___interrupt
|
|||
|
static void hw_iic_host_irq(void)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(0);
|
|||
|
/* printf("%s", __func__); */
|
|||
|
iic_pnding_clr(iic_regs[id]);
|
|||
|
iic_host_send_stop(iic_regs[id]); //stop singal
|
|||
|
while (!iic_host_is_stop_pending(iic_regs[id]));
|
|||
|
flag = 0 ;
|
|||
|
}
|
|||
|
|
|||
|
static void hw_iic_host_int_test(void)
|
|||
|
{
|
|||
|
u8 id = iic_get_id(0);
|
|||
|
iic_disable(iic_regs[id]);
|
|||
|
request_irq(IRQ_IIC_IDX, 1, hw_iic_host_irq, 0);
|
|||
|
iic_int_enable(iic_regs[id]);
|
|||
|
|
|||
|
iic_enable(iic_regs[id]);
|
|||
|
|
|||
|
iic_dir_out(iic_regs[id]);
|
|||
|
printf("%s in\n", __func__);
|
|||
|
for (int i = 0; i < 50; i++) {
|
|||
|
flag = 1;
|
|||
|
iic_buf_reg(iic_regs[id]) = IIC_SLAVE_wADDR;
|
|||
|
iic_kick_start(iic_regs[id]); //kick start
|
|||
|
printf("%s run\n", __func__);
|
|||
|
while (flag);
|
|||
|
}
|
|||
|
printf("%s out\n", __func__);
|
|||
|
while (1);
|
|||
|
}
|
|||
|
|
|||
|
/*================iic host test================*/
|
|||
|
static void hw_iic_host_test_process(hw_iic_dev iic)//与从机接收对应
|
|||
|
{
|
|||
|
const u8 test_len = RX_LEN;
|
|||
|
u8 retry = 50;
|
|||
|
u8 id = iic_get_id(iic);
|
|||
|
u8 ack = 0;
|
|||
|
int i;
|
|||
|
//主发
|
|||
|
__retry_tx:
|
|||
|
hw_iic_start(iic);
|
|||
|
ack = hw_iic_tx_byte(iic, IIC_SLAVE_wADDR);
|
|||
|
if (!ack && retry--) {
|
|||
|
hw_iic_stop(iic);
|
|||
|
delay(3000);
|
|||
|
goto __retry_tx;
|
|||
|
}
|
|||
|
u8 data = 'A';
|
|||
|
for (i = 0; i < test_len - 1; i++) {
|
|||
|
hw_iic_tx_byte(iic, data++);
|
|||
|
}
|
|||
|
ack = hw_iic_tx_byte(iic, data);
|
|||
|
hw_iic_stop(iic);
|
|||
|
delay(8000000);
|
|||
|
//主收
|
|||
|
__retry_rx:
|
|||
|
hw_iic_start(iic);
|
|||
|
ack = hw_iic_tx_byte(iic, IIC_SLAVE_rADDR);
|
|||
|
if (!ack && retry--) {
|
|||
|
hw_iic_stop(iic);
|
|||
|
delay(3000);
|
|||
|
goto __retry_rx;
|
|||
|
}
|
|||
|
u8 rx_data[50];
|
|||
|
for (i = 0; i < test_len - 1; i++) {
|
|||
|
rx_data[i] = hw_iic_rx_byte(iic, 1);
|
|||
|
}
|
|||
|
rx_data[i] = hw_iic_rx_byte(iic, 0);
|
|||
|
hw_iic_stop(iic);
|
|||
|
put_buf(rx_data, test_len);
|
|||
|
}
|
|||
|
|
|||
|
int hw_iic_host_test(void)
|
|||
|
{
|
|||
|
printf("%s\n", __func__);
|
|||
|
hw_iic_init(0);//结构体成员: role=IIC_MASTER
|
|||
|
/* hw_iic_host_int_test(); */
|
|||
|
hw_iic_host_test_process(0);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void iic_disable_for_ota()
|
|||
|
{
|
|||
|
JL_IIC->CON0 = 0;
|
|||
|
}
|
|||
|
|
|||
|
|