#include "sdk_include.h"
#if SPI_USE_NUM
SPI_PARAM   ui_spi_param[SPI_USE_NUM];

SPI_PARAM *spi_get_instance(ws_dev dev)
{
	if(dev == ws_spi0) return &ui_spi_param[SPI0_IDX];

	if(dev == ws_spi1) return &ui_spi_param[SPI1_IDX];
	
	return NULL;
}

void ui_spi_init(ws_dev dev)
{
    assert_param(is_spi_dev(dev));

	SPI_PARAM * spi_param = spi_get_instance(dev);
	memset(spi_param,0,sizeof(SPI_PARAM));
	spi_param->tx_transmit_stopped = 1; 
}

void set_spi_init(ws_dev dev)
{
    SPI_PARAM * spi_param = NULL; 
    assert_param(is_spi_dev(dev));
    spi_param = spi_get_instance(dev);
	if(NULL == spi_param)
		return;
	
	spi_param->init = 1;
}

void reg_spi_rx_callback(ws_dev dev,user_spi_cfg_parameter_t *p_parameter)
{
    SPI_PARAM * spi_param = NULL; 
    spi_param = spi_get_instance(dev);
	if(spi_param){
		spi_param->spi_handler = p_parameter->spi_handler;
	}
}

void ui_spi_sendchar(ws_dev dev, uint8_t data)
{
    SPI_PARAM * spi_param = NULL; 
	spi_type_def* spix;
	
	if(dev == ws_spi0){
		spix = SPI0;
	}else if(dev == ws_spi1){
		spix = SPI1;
	}else{
		return;
	}
	
    spi_param 	= spi_get_instance(dev);
	
    while (SPI_SEND_BUF_SIZE == spi_param->Send.bytes){
		spi_param->wait ++;
		if(spi_param->wait > 1000){
			spi_param->wait = 0;
			return;
		}
	}

	if(dev == ws_spi0){
		cpu_prevent_sleep_set(SPI0_TX_ONGOING);
	}
	if(dev == ws_spi1){
		cpu_prevent_sleep_set(SPI1_TX_ONGOING);
	}

	spi_param->wait = 0;
    spi_param->Send.buf[spi_param->Send.write_index++] = data;

    if (spi_param->Send.write_index >= SPI_SEND_BUF_SIZE)
    {
        spi_param->Send.write_index = 0;
    }

    __set_faultmask(1);

	if(spi_param->Send.bytes < SPI_SEND_BUF_SIZE)
    	spi_param->Send.bytes++;
	
    if (spi_param->Send.bytes && spi_param->tx_transmit_stopped)
    {
   		dbg_putchar('O');
        spi_param->tx_transmit_stopped = 0;
		spi_it_config(spix, SPI_IT_TXE, ENABLE);
    }
	
    __set_faultmask(0);
}



uint32_t ui_get_spi_fifo_avaiable(ws_dev dev)
{    
	SPI_PARAM * spi_param = NULL; 
    spi_param 	= spi_get_instance(dev);

	return SPI_SEND_BUF_SIZE - spi_param->Send.bytes;
}

uint32_t ui_spi_recvchar(ws_dev dev, uint8_t *ch)
{
    SPI_PARAM * spi_param = NULL; 
    assert_param(is_spi_dev(dev));
    spi_param = spi_get_instance(dev);

    if (0 == spi_param->Recv.bytes)
    {
        return 0;
    }
	//此处可能有问题 while (0 == tmp_uart_param->recv.bytes);

	__set_faultmask(1);
    *ch = spi_param->Recv.buf[spi_param->Recv.read_index++];
    if (spi_param->Recv.read_index >= SPI_RECV_BUF_SIZE){
        spi_param->Recv.read_index = 0;
    }
    spi_param->Recv.bytes--;
    __set_faultmask(0);

	return 1;
}


//extern volatile char 	task_going;
void spi_dev_isr(spi_type_def * spix,SPI_PARAM * spi_param)
{
//	uint32_t val  = 0;
	uint8_t ch;
	if(spi_get_it_status(spix,SPI_IT_RXF) == SET)
	{
		dbg_putchar('R');
		ch = spi_receive_data(spix);

		spi_param->Recv.buf[spi_param->Recv.write_index]= ch;
		spi_param->Recv.write_index++;

		if(spi_param->Recv.write_index >= SPI_SEND_BUF_SIZE)
			spi_param->Recv.write_index = 0;
		
		// fifo total data
		if(spi_param->Recv.bytes < SPI_RECV_BUF_SIZE)
			spi_param->Recv.bytes++;
		else
			spi_param->Recv.read_index = spi_param->Recv.write_index;

		if(spi_param->spi_handler){
			spi_param->spi_handler(spi_param,ch);
		}
		
		spi_clear_it_pending_bit(spix, SPI_IT_RXF);
	}

	if(spi_get_it_status(spix,SPI_IT_TXE) == SET)
	{
		dbg_putchar('T');
		if(spi_param->Send.bytes)
		{
			if(SPI0 == spix){
//					dbg_printf("%x ",pUart_Param->Send.buf[pUart_Param->Send.read_index]);
			}
			spi_param->Send.bytes--;
			ch = spi_param->Send.buf[spi_param->Send.read_index++];
			if(spi_param->Send.read_index >= SPI_SEND_BUF_SIZE)
			{
				spi_param->Send.read_index = 0;
			}
			spi_send_data(spix, ch);
		}

		if (0 == spi_param->Send.bytes){
			
			dbg_putchar('S');
			
			spi_it_config(spix, SPI_IT_TXE, DISABLE);
			spi_param->tx_transmit_stopped = 1;
			
			if(spix == SPI0){
				cpu_prevent_sleep_clear(SPI0_TX_ONGOING);
			}
			if(spix == SPI1){
				cpu_prevent_sleep_clear(SPI1_TX_ONGOING);
			}
		}
		spi_clear_it_pending_bit(spix, SPI_IT_TXE);
	}
}

void set_spi_recv_busy(ws_dev dev,uint8_t busy)
{
	if(busy){
		if(dev == ws_spi0){
			cpu_prevent_sleep_set(SPI0_RX_ONGOING);
		}
		if(dev == ws_spi1){
			cpu_prevent_sleep_set(SPI1_RX_ONGOING);
		}

	}else{
		if(dev == ws_spi0){
			cpu_prevent_sleep_clear(SPI0_RX_ONGOING);
		}
		if(dev == ws_spi1){
			cpu_prevent_sleep_clear(SPI1_RX_ONGOING);
		}
	}
}

void SPI0_IRQHandler()
{
    SPI_PARAM * spi_param = spi_get_instance(ws_spi0);
	
	if(spi_param)
	{	
		dbg_block_printf("#");
		spi_dev_isr(SPI0,spi_param);
	}
	NVIC_ClearPendingIRQ(SPI0_IRQn);
}

void SPI1_IRQHandler()
{
    SPI_PARAM * spi_param = spi_get_instance(ws_spi1);
	
	if(NULL == spi_param)
	{	
		dbg_block_printf("*");
		spi_dev_isr(SPI1,spi_param);
	}
	NVIC_ClearPendingIRQ(SPI1_IRQn);
}

uint8_t ui_spi_readbuf(ws_dev  dev,uint8_t *buf,uint8_t len)
{
	uint8_t read_len = 0;
	while((read_len < len) && ui_spi_recvchar(dev,&buf[read_len])){
		read_len ++;
	}
	return read_len;
}

void ui_spi_writebuf(ws_dev dev,uint8_t * buf,uint32_t buf_len)
{
    uint32_t i = 0;
    for(i =0;i < buf_len;i++){
		ui_spi_sendchar(dev,buf[i]);
    }
}

void ui_spi_configuration(ws_dev dev,spi_init_config *pconfig,uint32_t on)
{
	spi_init_type_def 	spi_structure;
	spi_type_def *spix;
	char id = 0;
	
	typedef struct _spi_map_struct{
		gpio_remap_type cs_pin;
		gpio_remap_type clk_pin;
		gpio_remap_type miso_pin;
		gpio_remap_type mosi_pin;
	}spi_map_struct;
	

	const spi_map_struct spi_map[2]={
		{GPIO_Remap_SPI0_CSN,GPIO_Remap_SPI0_CLK,GPIO_Remap_SPI0_MISO,GPIO_Remap_SPI0_MOSI},
		{GPIO_Remap_SPI1_CSN,GPIO_Remap_SPI1_CLK,GPIO_Remap_SPI1_MISO,GPIO_Remap_SPI1_MOSI},
	};
	if(dev == ws_spi0){
		id = 0;
		spix = SPI0;
	}else if(dev == ws_spi1){
		id = 1;
		spix = SPI1;
	}else{
		return;
	}
	
    if(pconfig->cs_pin != GPIO_INVAILD){
		gpio_remap_config(pconfig->cs_pin,(on == ON)?spi_map[id].cs_pin:GPIO_Remap_GPIO);
		gpio_init(pconfig->cs_pin,(pconfig->dir == SPI_Mode_Master)?GPIO_Mode_Output:GPIO_Mode_Input);
	}
	
	if(pconfig->clk_pin != GPIO_INVAILD){
		gpio_remap_config(pconfig->clk_pin,(on == ON)?spi_map[id].clk_pin:GPIO_Remap_GPIO);
		gpio_init(pconfig->clk_pin,(on == ON)?GPIO_Mode_Output:GPIO_Mode_Input);
	}
	
	if(pconfig->miso_pin != GPIO_INVAILD){
		gpio_remap_config(pconfig->miso_pin,(on == ON)?spi_map[id].miso_pin:GPIO_Remap_GPIO);
		gpio_init(pconfig->miso_pin,GPIO_Mode_Input);
	}
	
	if(pconfig->mosi_pin != GPIO_INVAILD){
		gpio_remap_config(pconfig->mosi_pin,(on == ON)?spi_map[id].mosi_pin:GPIO_Remap_GPIO);
		gpio_init(pconfig->mosi_pin,(on == ON)?GPIO_Mode_Output:GPIO_Mode_Input);
	}

	if(on == OFF){
		return;
	}
	
	spi_structure.spi_mode 						= pconfig->mode;			//配置SPI主从模式：master
	spi_structure.spi_direction 				= pconfig->dir;				//设置SPI通信方式：全双工模式   
	spi_structure.spi_data_size 				= pconfig->data_size; 		//设置数据帧大小：8bit   
	spi_structure.spi_cpol 						= pconfig->cpol;			//设置时钟极性:空闲状态时，时钟保持低电平
	spi_structure.spi_cpha 						= pconfig->cpha;			//设置时钟相位：数据采样从第二个时钟边沿开始
	spi_structure.spi_nss 						= pconfig->nss;				//NSS信号控制选择
	spi_structure.spi_baud_rate_prescaler 		= pconfig->prescaler;		//SPI波特率分频：256 ，SPI速率=16M/256 =62.5KHz
	spi_structure.spi_rx_fifo_full_threshold 	= pconfig->rx_threshold;	//接收FIFO空中断阈值：接收FIFO中数据1个及以上触发中断
	spi_structure.spi_tx_fifo_empty_threshold 	= pconfig->tx_threshold;	//发送FIFO满中断阈值：发送FIFO中数据数量为0触发中断
	
	spi_init(spix, &spi_structure);				//SPI初始化
    spi_it_config(spix, SPI_IT_RXF, ENABLE);	//SPI接收中断使能
	spi_cmd(spix, ENABLE);						//SPI使能

}

void user_spi_config(ws_dev dev,user_spi_cfg_parameter_t *p_parameter)
{
	SPI_PARAM * uart_parm = spi_get_instance(dev);

	uart_parm->spi_handler = p_parameter->spi_handler;
}

//=========================================================================
//****	SPI应用举例
//****
//****
//=========================================================================


void user_spi0_rcv_cbk(void *param,uint8_t ch)
{
//	dbg_printf("spi0 *0x%02X ",ch);
//	dbg_block_printf("*");
}

void user_spi1_rcv_cbk(void *param,uint8_t ch)
{
//	dbg_printf("SPI1 0x%02X ",ch);
//	dbg_block_printf("#");
}

//1.SPI slave中断测试：配合SPI_Master_TX工程测试，测试SPI slave接收数据
//2.测试方法：将master、slave的CLK、CS、MISO、MOSI管脚一一对应连接，master上

#define	SPI_TEST_SPI1				0
#define DATA_BUF_SIZE				256

#if (SPI_TEST_SPI1)
spi_type_def *spix = SPI1;
#else
spi_type_def *spix = SPI0;
#endif

uint8_t slaver_recv_buf[DATA_BUF_SIZE] = {0x00};
uint8_t slaver_send_buf[DATA_BUF_SIZE];
#define DATA_BUF_SIZE				256
uint32_t cnt = 0;

uint32_t slaver_send_buf_index = 0;
uint32_t slaver_recv_buf_index = 0;
uint8_t slaver_rx_int_flag = 0;//接收中断标志
uint8_t slaver_rx_len = 0;//接收中断标志
uint8_t slaver_rx_pos = 0;//接收中断标志
uint8_t slaver_recv_data[22] ={0x56,0x78,0x11,0x02,0x02,0x53,0x01,0x80,0x01,0x01,0x00,0x68,0x07,0x06,0x4B,0x4A,0x56,0x3C,0x45,0x53,0x12,0x34};

uint8_t slaver_tx_int_flag = 0;//接收中断标志
uint8_t slaver_tx_len = 0;//接收中断标志
uint8_t slaver_tx_pos = 0;//接收中断标志
uint8_t slaver_send_data[22] ={0x56,0x78,0x11,0x02,0x02,0x53,0x01,0x80,0x01,0x01,0x00,0x68,0x07,0x06,0x4B,0x4A,0x56,0x3C,0x45,0x53,0x12,0x34};

uint8_t master_rx_int_flag = 0;	//接收中断标志
uint8_t master_rx_len = 0;			//接收中断标志
uint8_t master_rx_pos = 0;			//接收中断标志
uint8_t master_recv_data[22] ={0x56,0x78,0x11,0x02,0x02,0x53,0x01,0x80,0x01,0x01,0x00,0x68,0x07,0x06,0x4B,0x4A,0x56,0x3C,0x45,0x53,0x12,0x34};

uint8_t master_tx_int_flag = 0;	//接收中断标志
uint8_t master_tx_len = 0;			//接收中断标志
uint8_t master_tx_pos = 0;			//接收中断标志
uint8_t master_send_data[22] ={0x12,0x34,0x11,0x02,0x02,0x53,0x01,0x80,0x01,0x01,0x00,0x68,0x07,0x06,0x4B,0x4A,0x56,0x3C,0x45,0x53,0x56,0x78};
uint8_t master_send_data2[19] ={0x80,0x68,0x53,0x01,0x80,0x01,0x01,0x00,0x68,0x00,0x00,0xA6,0x16,0x06,0x4B,0x4A,0x56,0x3C,0x45};

//====================================SPI 阻塞方式示例代码===============================
/*****************************************************************************
 函 数 名  : spi_slaver_block_read
 功能描述  : 从机阻塞读
 输入参数  : spi_type_def *spix  
 输出参数  : 无
 返 回 值  : uint8_t 
*****************************************************************************/
static uint8_t spi_slaver_block_read(spi_type_def *spix)
{
	uint16_t retry 	= 0;
	uint16_t recv 	= 0;
	while(spi_get_flag_status(spix,SPI_FLAG_RXNE) == RESET){
		retry ++;
		if(retry > 0x1ffffff)
		{
			dbg_printf("S");
			return 0;
		}
	}
	recv = spi_receive_data(spix);
	while(spi_get_flag_status(spix,SPI_FLAG_TXNF) == RESET)
	{
		retry ++;
		if(retry > 0x1ffffff)
		{
			dbg_printf("SR %02X::\n",spix->SR);
			return 0;
		}
	}

//	spi_send_data(spix, 0x00);
	return recv;
}

/*****************************************************************************
 函 数 名  : spi_slaver_block_send
 功能描述  : 从机阻塞发送
 输入参数  : spi_type_def *spix  
             uint8_t data        
 输出参数  : 无
 返 回 值  : uint8_t
*****************************************************************************/
static uint8_t spi_slaver_block_send(spi_type_def *spix,uint8_t data)
{
	uint16_t retry 	= 0;
	//uint8_t  recv 	= 0;

	while(spi_get_flag_status(spix,SPI_FLAG_RXNE) == RESET){
		retry ++;
		if(retry > 10000){
			dbg_printf("S");
			return 0;
		}
	}
	
	spi_receive_data(spix);
	retry = 0;
//	while(spi_get_flag_status(spix,SPI_FLAG_TXE) == RESET)
	while(spi_get_flag_status(spix,SPI_FLAG_TXNF) == RESET)
	{
		retry ++;
		if(retry > 10000){
			dbg_printf("SR %02X::\n",spix->SR);
			return 0;
		}
	}

	spi_send_data(spix, data);
	return 1;
}

void slaver_spi_block_awnser_data_demo(void)
{
    uint32_t i;									//cnt = 0;
    uint32_t ack_len;							//cnt = 0;
    uint32_t status= 0;							//cnt = 0;
	spi_init_type_def spi_init_structure;

	crm_cmd_periphclock(CRM_CG_CTRL_SPI0,ENABLE);
	crm_reset_periph(CRM_SOFT_RST_SPI0 );
	
	//SPI管脚映射配置
	if( spix == SPI0 )
	{
		gpio_remap_config(GPIOA_Pin0,GPIO_Remap_SPI0_CSN);
		gpio_remap_config(GPIOA_Pin1,GPIO_Remap_SPI0_CLK);
		gpio_remap_config(GPIOA_Pin2,GPIO_Remap_SPI0_MISO);
		gpio_remap_config(GPIOA_Pin3,GPIO_Remap_SPI0_MOSI);
	}
	else if( spix == SPI1 )
	{
		gpio_remap_config(GPIOA_Pin4,GPIO_Remap_SPI1_CSN);
		gpio_remap_config(GPIOA_Pin5,GPIO_Remap_SPI1_CLK);
		gpio_remap_config(GPIOA_Pin6,GPIO_Remap_SPI1_MISO);
		gpio_remap_config(GPIOA_Pin7,GPIO_Remap_SPI1_MOSI);
	}
   
	spi_init_structure.spi_mode 					= SPI_Mode_Slave;					//配置SPI主从模式：slave
	spi_init_structure.spi_direction				= SPI_Direction_2Lines_FullDuplex;	//设置SPI通信方式：全双工模式
	spi_init_structure.spi_data_size				= SPI_DataSize_8b;					//设置数据帧大小：8bit
	spi_init_structure.spi_cpol 					= SPI_CPOL_Low;						//设置时钟极性:空闲状态时，时钟保持低电平
	spi_init_structure.spi_cpha 					= SPI_CPHA_1Edge;					//设置时钟相位：数据采样从第二个时钟边沿开始
	spi_init_structure.spi_nss						= SPI_NSS_Null;						//NSS信号控制选择
	spi_init_structure.spi_baud_rate_prescaler		= SPI_BaudRatePrescaler_256;		//从机时钟不起作用，随主机  理论时钟要求 sclk < pclk/10
	spi_init_structure.spi_rx_fifo_full_threshold	= SPI_RXFIFOFullThreshold_1;		//接收FIFO空中断阈值：接收FIFO中数据1个及以上触发中断
	spi_init_structure.spi_tx_fifo_empty_threshold	= SPI_TXFIFOEmptyThreshold_0;		//发送FIFO满中断阈值：发送FIFO中数据数量为0触发中断
	
	spi_init(spix, &spi_init_structure);//SPI初始化
	spi_cmd(spix, ENABLE);//SPI使能

    for(i = 0;i < DATA_BUF_SIZE; i++)
		slaver_send_buf[i] = i % 0x100;
	
	while(1)
	{
		switch(status){
			case 0:
				if(spi_slaver_block_read(spix) == 0xAA)
				{
					status = 1;
				}
				break;
			case 1:
				ack_len = spi_slaver_block_read(spix);
				if(ack_len < 20){
					for(i=0;i<ack_len;i++){
						spi_slaver_block_send(spix,slaver_send_buf[i]);
					}
					dbg_printf("Slaver ack %d:: ",ack_len);
					for(i=0;i<ack_len;i++){
						dbg_printf("%02X ",slaver_send_buf[i]);
					}
					dbg_printf("\r\n");
				}
				status = 0;
				break;
			case 2:
				break;
		}
	}
}

//====================================SPI 阻塞方式示例代码===============================

void slaver_spi_block_protol_demo(void)
{
    uint32_t i;				//cnt = 0;
    uint32_t ack_len;		//cnt = 0;
    uint32_t status= 0;		//cnt = 0;

	spi_init_type_def spi_init_structure;

	crm_cmd_periphclock(CRM_CG_CTRL_SPI0,ENABLE);
	crm_reset_periph(CRM_SOFT_RST_SPI0 ) ;
	
	//SPI管脚映射配置
	if( spix == SPI0 )
	{
		gpio_remap_config(GPIOA_Pin0,GPIO_Remap_SPI0_CSN);
		gpio_remap_config(GPIOA_Pin1,GPIO_Remap_SPI0_CLK);
		gpio_remap_config(GPIOA_Pin2,GPIO_Remap_SPI0_MISO);
		gpio_remap_config(GPIOA_Pin3,GPIO_Remap_SPI0_MOSI);
	}
	else if( spix == SPI1 )
	{
		gpio_remap_config(GPIOA_Pin4,GPIO_Remap_SPI1_CSN);
		gpio_remap_config(GPIOA_Pin5,GPIO_Remap_SPI1_CLK);
		gpio_remap_config(GPIOA_Pin6,GPIO_Remap_SPI1_MISO);
		gpio_remap_config(GPIOA_Pin7,GPIO_Remap_SPI1_MOSI);
	}
   
	spi_init_structure.spi_mode 					= SPI_Mode_Slave;//配置SPI主从模式：slave
	spi_init_structure.spi_direction				= SPI_Direction_2Lines_FullDuplex;//设置SPI通信方式：全双工模式
	spi_init_structure.spi_data_size				= SPI_DataSize_8b;//设置数据帧大小：8bit
	spi_init_structure.spi_cpol 					= SPI_CPOL_Low;//设置时钟极性:空闲状态时，时钟保持低电平
	spi_init_structure.spi_cpha 					= SPI_CPHA_1Edge;//设置时钟相位：数据采样从第二个时钟边沿开始
	spi_init_structure.spi_nss						= SPI_NSS_Null;//NSS信号控制选择
	spi_init_structure.spi_baud_rate_prescaler		= SPI_BaudRatePrescaler_256;//从机时钟不起作用，随主机  理论时钟要求 sclk < pclk/10
	spi_init_structure.spi_rx_fifo_full_threshold	= SPI_RXFIFOFullThreshold_1;//接收FIFO空中断阈值：接收FIFO中数据1个及以上触发中断
	spi_init_structure.spi_tx_fifo_empty_threshold	= SPI_TXFIFOEmptyThreshold_0;//发送FIFO满中断阈值：发送FIFO中数据数量为0触发中断
	
	spi_init(spix, &spi_init_structure);//SPI初始化
	spi_cmd(spix, ENABLE);//SPI使能
	
	while(1)
	{
		switch(status)
		{
			case 0:
				if(spi_slaver_block_read(spix) == 0x12)
				{
					slaver_recv_data[0] = 0x12;
					status = 1;
				}
				break;
			case 1:
				if(spi_slaver_block_read(spix) == 0x34)
				{
					slaver_recv_data[1] = 0x34;
					status = 2;
				}else{
					status = 0;
				}
				break;
			case 2:
				ack_len = spi_slaver_block_read(spix);

				if(ack_len < 50)
				{
					slaver_recv_data[2] = ack_len;

					for(i=0;i<(ack_len+2);i++){
						slaver_recv_data[3 + i]=spi_slaver_block_read(spix);
					}	
				
					for(i=0;i<(ack_len+5);i++){
						spi_slaver_block_send(spix,slaver_send_data[i]);
					}	
					
					dbg_printf("Slaver recv %d:: ",(ack_len+5));
					for(i=0;i<(ack_len+5);i++){
						dbg_printf("%02X ",slaver_recv_data[i]);
					}
					dbg_printf("\r\n");

					dbg_printf("Slaver ack %d:: ",(ack_len+5));
					for(i=0;i<(ack_len+5);i++){
						dbg_printf("%02X ",slaver_send_data[i]);
					}
					dbg_printf("\r\n");
				}
				status = 0;
				break;

		}
	}
}


uint8_t spi_master_block_read_write(spi_type_def *spix,uint8_t data)
{
	uint16_t retry 	= 0;
	retry = 0;
	while(spi_get_flag_status(spix,SPI_FLAG_TXE) == RESET){
		retry ++;
		if(retry > 10000)
		{
			dbg_printf("M");
			return 0;
		}
	}
	spi_send_data(spix, data);
	retry = 0;
	while(spi_get_flag_status(spix,SPI_FLAG_RXNE) == RESET){
		retry ++;
		if(retry > 10000)
		{
			dbg_printf("m");
			return 0;
		}
	}
	return spi_receive_data(spix);
}

void master_spi_block_read_data_demo(void)
{
    uint32_t i;				//cnt = 0;

	uint8_t  send_char = 0xAA;
	
	crm_cmd_periphclock(CRM_CG_CTRL_SPI0,ENABLE);
	crm_reset_periph(CRM_SOFT_RST_SPI0 ) ;

	spi_init_type_def spi_init_structure;
	//SPI管脚映射配置
	if( spix == SPI0 )
	{
		gpio_remap_config(GPIOA_Pin0,GPIO_Remap_SPI0_CSN);
		gpio_remap_config(GPIOA_Pin1,GPIO_Remap_SPI0_CLK);
		gpio_remap_config(GPIOA_Pin2,GPIO_Remap_SPI0_MISO);	//测试直连 MISO MOSI会自动区分
		gpio_remap_config(GPIOA_Pin3,GPIO_Remap_SPI0_MOSI);	//直连
	}
	else if( spix == SPI1 )
	{
		gpio_remap_config(GPIOA_Pin4,GPIO_Remap_SPI1_CSN);
		gpio_remap_config(GPIOA_Pin5,GPIO_Remap_SPI1_CLK);
		gpio_remap_config(GPIOA_Pin6,GPIO_Remap_SPI1_MISO);
		gpio_remap_config(GPIOA_Pin7,GPIO_Remap_SPI1_MOSI);
	}	 
	
	spi_init_structure.spi_mode 					= SPI_Mode_Master;//配置SPI主从模式：master
	spi_init_structure.spi_direction				= SPI_Direction_2Lines_FullDuplex;//设置SPI通信方式：全双工模式   
	spi_init_structure.spi_data_size				= SPI_DataSize_8b; //设置数据帧大小：8bit	
	spi_init_structure.spi_cpol 					= SPI_CPOL_Low;//设置时钟极性:空闲状态时，时钟保持低电平
	spi_init_structure.spi_cpha 					= SPI_CPHA_1Edge;//设置时钟相位：数据采样从第二个时钟边沿开始
	spi_init_structure.spi_nss						= SPI_NSS_0;//NSS信号控制选择
	spi_init_structure.spi_baud_rate_prescaler		= SPI_BaudRatePrescaler_256;//SPI波特率分频：256 ，SPI速率=16M/256 =62.5KHz
	spi_init_structure.spi_rx_fifo_full_threshold	= SPI_RXFIFOFullThreshold_1;//接收FIFO空中断阈值：接收FIFO中数据1个及以上触发中断
	spi_init_structure.spi_tx_fifo_empty_threshold	= SPI_TXFIFOEmptyThreshold_0;//发送FIFO满中断阈值：发送FIFO中数据数量为0触发中断
	
	spi_init(spix, &spi_init_structure);				//SPI初始化
	spi_cmd(spix, ENABLE);//SPI使能

	spi_init(spix, &spi_init_structure);//SPI初始化
	spi_cmd(spix, ENABLE);//SPI使能

	while(1)
	{
		spi_master_block_read_write(spix, send_char);	//发送数据头
		spi_master_block_read_write(spix, 19);			//发送读取长度
		spi_master_block_read_write(spix, 0xFF);		//读取空字节
		
		for(i = 0 ; i < 50000 ; i++);
		
		for(i=0;i<19;i++){
			master_recv_data[i] = spi_master_block_read_write(spix, 0xFF);
		}
		
		dbg_printf("\r\n Master Read ::");
		for(i=0;i<19;i++){
			dbg_printf("%02X ",master_recv_data[i]);
		}
		dbg_printf("\r\n");
		for(i = 0 ; i < 0x1ffffff ; i++);
	}
}


void master_spi_block_protol_demo(void)
{
    uint32_t i;				//cnt = 0;
//    uint32_t ack_len;		//cnt = 0;
//    uint32_t status= 0;		//cnt = 0;
//	uint8_t  send_char = 0xAA;

	spi_init_type_def spi_init_structure;	

	crm_cmd_periphclock(CRM_CG_CTRL_SPI0,ENABLE);
	crm_reset_periph(CRM_SOFT_RST_SPI0 ) ;
	
	//SPI管脚映射配置
	if( spix == SPI0 )
	{
		gpio_remap_config(GPIOA_Pin0,GPIO_Remap_SPI0_CSN);
		gpio_remap_config(GPIOA_Pin1,GPIO_Remap_SPI0_CLK);
		gpio_remap_config(GPIOA_Pin2,GPIO_Remap_SPI0_MISO);	//测试直连 MISO MOSI会自动区分
		gpio_remap_config(GPIOA_Pin3,GPIO_Remap_SPI0_MOSI);	//直连
	}
	else if( spix == SPI1 )
	{
		gpio_remap_config(GPIOA_Pin4,GPIO_Remap_SPI1_CSN);
		gpio_remap_config(GPIOA_Pin5,GPIO_Remap_SPI1_CLK);
		gpio_remap_config(GPIOA_Pin6,GPIO_Remap_SPI1_MISO);
		gpio_remap_config(GPIOA_Pin7,GPIO_Remap_SPI1_MOSI);
	}	 
	
	spi_init_structure.spi_mode 					= SPI_Mode_Master;//配置SPI主从模式：master
	spi_init_structure.spi_direction				= SPI_Direction_2Lines_FullDuplex;//设置SPI通信方式：全双工模式   
	spi_init_structure.spi_data_size				= SPI_DataSize_8b; //设置数据帧大小：8bit	
	spi_init_structure.spi_cpol 					= SPI_CPOL_Low;//设置时钟极性:空闲状态时，时钟保持低电平
	spi_init_structure.spi_cpha 					= SPI_CPHA_1Edge;//设置时钟相位：数据采样从第二个时钟边沿开始
	spi_init_structure.spi_nss						= SPI_NSS_0;//NSS信号控制选择
	spi_init_structure.spi_baud_rate_prescaler		= 48;//SPI波特率分频：256 ，SPI速率=16M/256 =62.5KHz
	spi_init_structure.spi_rx_fifo_full_threshold	= SPI_RXFIFOFullThreshold_1;//接收FIFO空中断阈值：接收FIFO中数据1个及以上触发中断
	spi_init_structure.spi_tx_fifo_empty_threshold	= SPI_TXFIFOEmptyThreshold_0;//发送FIFO满中断阈值：发送FIFO中数据数量为0触发中断
	
	spi_init(spix, &spi_init_structure);				//SPI初始化
	spi_cmd(spix, ENABLE);//SPI使能

		
	while(1)
	{
		for(i=0;i<13;i++){
			spi_master_block_read_write(spix, master_send_data2[i]);
		}
		for(i=0;i<500000;i++);
		
		for(i=0;i<17;i++){
			master_recv_data[i] = spi_master_block_read_write(spix, 0x7F);
		}
		
		dbg_printf("\r\n Master Block Read ::");
		for(i=0;i<17;i++){
			dbg_printf("%02X ",master_recv_data[i]);
		}
		dbg_printf("\r\n");
		for(i = 0 ; i < 0x1ffffff ; i++);
	}
}


//
void slaver_spi_irq_protol_handler(spi_type_def* spix)
{
	uint8_t ch;
	uint8_t i;
	if(spi_get_it_status(spix,SPI_IT_RXF) == SET)
	{
		ch = spi_receive_data(spix);
		if(master_rx_int_flag == 0){
			master_rx_len = 0;
			master_rx_pos = 0;
			if(ch == 0x12){
				master_rx_int_flag 		= 1;
				master_recv_data[master_rx_pos]	= ch;
				master_rx_pos 				++;
//				ser_put_char('1');
			}
		}else if(master_rx_int_flag == 1){
			master_rx_len = 0;
			if(ch == 0x34){
				master_rx_int_flag 		= 2;
				master_recv_data[master_rx_pos]	= ch;
				master_rx_pos 				++;
//				ser_put_char('2');
			}
		}else if(master_rx_int_flag == 2){
			if(ch < 40){
				master_rx_len 				= ch;
				master_rx_int_flag 		= 3;
				master_recv_data[master_rx_pos]	= ch;
				master_rx_pos ++;
//				ser_put_char('3');
//				dbg_printf("rx len %d rx pos %d\n",rx_len,rx_pos);
			}else{
				master_rx_int_flag = 0;
			}

		}else if(master_rx_int_flag == 3){
			master_recv_data[master_rx_pos]		=	ch;
			master_rx_pos					++;
			if(master_rx_pos >= (master_rx_len+5)){

				if((master_recv_data[master_rx_len + 3] == 0x56) && (master_recv_data[master_rx_len + 4] == 0x78)){
					master_rx_int_flag 	= 4;
					master_tx_len 			= master_rx_len+5;
					master_tx_pos 			= 0;
					
//					dbg_printf("Slaver recv %d:: ",(rx_len+5));
//					for(i=0;i<(rx_len+5);i++){
//						dbg_printf("%02X ",recv_data[i]);
//					}
//					dbg_printf("\r\n");
				}else{
					dbg_printf("Slaver Check %d:: ",(master_rx_len+5));
					for(i=0;i<(master_rx_len+5);i++){
						dbg_printf("%02X ",master_recv_data[i]);
					}
					master_rx_int_flag = 5;
				}
			}
		}
	}
	spi_clear_it_pending_bit(spix, SPI_IT_RXF);
	if((spi_get_it_status(spix,SPI_IT_TXE) == SET) && (master_rx_int_flag == 4)){
		if(master_tx_pos < master_tx_len){
			spi_send_data(spix, master_send_data[master_tx_pos]);
			master_tx_pos ++;
			if(master_tx_pos == master_tx_len){
				dbg_printf("Slaver ack %d:: ",(master_tx_len));
				for(i=0;i<(master_tx_len);i++){
					dbg_printf("%02X ",master_send_data[i]);
				}
				master_rx_int_flag = 0;
				dbg_printf("\r\n");
			}
		}
	}		
	spi_clear_it_pending_bit(spix, SPI_IT_TXE);
//	spi_clear_it_pending_bit(spix, SPI_IT_TXO);
}

void slaver_spi_irq_protol_demo(void)
{
//    uint32_t i;				//cnt = 0;
//    uint32_t ack_len;		//cnt = 0;
//    uint32_t status= 0;		//cnt = 0;
	spi_init_type_def spi_init_structure;
	nvic_init_type_def nvic_init_structure;
	
	crm_cmd_periphclock(CRM_CG_CTRL_SPI0,ENABLE);
	crm_reset_periph(CRM_SOFT_RST_SPI0 ) ;
	
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_3);
	nvic_init_structure.nvic_irq_channel = SPI0_IRQn;
	nvic_init_structure.nvic_irq_channel_preemption_priority = 0;
	nvic_init_structure.nvic_irq_channel_subpriority = 0;
	nvic_init_structure.nvic_irq_channel_cmd = ENABLE;
	nvic_init(&nvic_init_structure);

	//SPI管脚映射配置
	if( spix == SPI0 )
	{
		gpio_remap_config(GPIOA_Pin0,GPIO_Remap_SPI0_CSN);
		gpio_remap_config(GPIOA_Pin1,GPIO_Remap_SPI0_CLK);
		gpio_remap_config(GPIOA_Pin2,GPIO_Remap_SPI0_MISO);
		gpio_remap_config(GPIOA_Pin3,GPIO_Remap_SPI0_MOSI);
	}
	else if( spix == SPI1 )
	{
		gpio_remap_config(GPIOA_Pin4,GPIO_Remap_SPI1_CSN);
		gpio_remap_config(GPIOA_Pin5,GPIO_Remap_SPI1_CLK);
		gpio_remap_config(GPIOA_Pin6,GPIO_Remap_SPI1_MISO);
		gpio_remap_config(GPIOA_Pin7,GPIO_Remap_SPI1_MOSI);
	}

	spi_init_structure.spi_mode 					= SPI_Mode_Slave;//配置SPI主从模式：slave
	spi_init_structure.spi_direction				= SPI_Direction_2Lines_FullDuplex;//设置SPI通信方式：全双工模式
	spi_init_structure.spi_data_size				= SPI_DataSize_8b;//设置数据帧大小：8bit
	spi_init_structure.spi_cpol 					= SPI_CPOL_Low;//设置时钟极性:空闲状态时，时钟保持低电平
	spi_init_structure.spi_cpha 					= SPI_CPHA_1Edge;//设置时钟相位：数据采样从第二个时钟边沿开始
	spi_init_structure.spi_nss						= SPI_NSS_Null;//NSS信号控制选择
	spi_init_structure.spi_baud_rate_prescaler		= SPI_BaudRatePrescaler_256;//从机时钟不起作用，随主机  理论时钟要求 sclk < pclk/10
	spi_init_structure.spi_rx_fifo_full_threshold	= SPI_RXFIFOFullThreshold_1;//接收FIFO空中断阈值：接收FIFO中数据1个及以上触发中断
	spi_init_structure.spi_tx_fifo_empty_threshold	= SPI_TXFIFOEmptyThreshold_0;//发送FIFO满中断阈值：发送FIFO中数据数量为0触发中断
	
	spi_init(spix, &spi_init_structure);						//SPI初始化
	spi_it_config(spix, SPI_IT_RXF | SPI_IT_TXE, ENABLE);
	spi_cmd(spix, ENABLE);										//SPI使能
	
	while(1)
	{
		
	}
}


void master_spi_irq_protol_handler(spi_type_def* spix)
{
	uint8_t ch;
	uint8_t i;
	if(spi_get_it_status(spix,SPI_IT_TXE) == SET)
	{
		if(master_tx_pos < master_tx_len){
			spi_send_data(spix, master_send_data[master_tx_pos]);
			master_tx_pos ++;
			master_rx_int_flag = 0xFF;							//发送数据
		}else{
			spi_send_data(spix, 0xFF);					
			if(master_rx_int_flag == 0xFF){
				master_rx_int_flag = 0x00;						//读取数据
			}
		}
		spi_clear_it_pending_bit(spix, SPI_IT_TXE);
		if(master_rx_int_flag == 4)								// 接收完成
		{
			spi_it_config(spix, SPI_IT_RXF | SPI_IT_TXE, DISABLE);
		}
	}

	if(spi_get_it_status(spix,SPI_IT_RXF) == SET)
	{
		ch = spi_receive_data(spix);
		if(master_rx_int_flag == 0){
			master_rx_len = 0;
			master_rx_pos = 0;
			if(ch == 0x56)
			{
				master_rx_int_flag 		= 1;
				master_recv_data[master_rx_pos]	=ch;
				master_rx_pos 				++;
			}
		}else if(master_rx_int_flag == 1){
			master_rx_len = 0;
			if(ch == 0x78){
				master_rx_int_flag 		= 2;
				master_recv_data[master_rx_pos]	= ch;
				master_rx_pos 				++;
			}
		}else if(master_rx_int_flag == 2){
			if(ch < 40){
				master_rx_len 				= ch;
				master_rx_int_flag 		= 3;
				master_recv_data[master_rx_pos]	=ch;
				master_rx_pos 				++;
			}else{
				master_rx_int_flag = 0;
			}
		}else if(master_rx_int_flag == 3){
			master_recv_data[master_rx_pos]=ch;
			master_rx_pos++;
			if(master_rx_pos >= master_rx_len+5){
				if((master_recv_data[master_rx_pos+3] == 0x12) && (master_recv_data[master_rx_pos+4] == 0x34)){
					master_rx_int_flag 	= 4;
					dbg_printf("Master Read %d:: ",(master_rx_len+5));
					for(i=0;i<(master_rx_len+5);i++){
						dbg_printf("%02X ",master_recv_data[i]);
					}
					dbg_printf("\r\n");
				}else{
					dbg_printf("Master Check %d:: ",(master_rx_len+5));
					for(i=0;i<(master_rx_len+5);i++){
						dbg_printf("%02X ",master_recv_data[i]);
					}
					master_rx_int_flag = 5;
				}
			}
		}
		spi_clear_it_pending_bit(spix, SPI_IT_RXF);
	}
}

void master_spi_irq_protol_demo(void)
{
    uint32_t i;						//cnt = 0;
//    uint32_t ack_len;				//cnt = 0;
//    uint32_t status= 0;				//cnt = 0;
//	uint8_t  send_char = 0xAA;

	spi_init_type_def spi_init_structure;	
	nvic_init_type_def nvic_init_structure;
	
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_3);
	nvic_init_structure.nvic_irq_channel = SPI0_IRQn;
	nvic_init_structure.nvic_irq_channel_preemption_priority = 0;
	nvic_init_structure.nvic_irq_channel_subpriority = 0;
	nvic_init_structure.nvic_irq_channel_cmd = ENABLE;
	nvic_init(&nvic_init_structure);
	//SPI管脚映射配置
	if( spix == SPI0 )
	{
		gpio_remap_config(GPIOA_Pin0,GPIO_Remap_SPI0_CSN);
		gpio_remap_config(GPIOA_Pin1,GPIO_Remap_SPI0_CLK);
		gpio_remap_config(GPIOA_Pin2,GPIO_Remap_SPI0_MISO);	//测试直连 MISO MOSI会自动区分
		gpio_remap_config(GPIOA_Pin3,GPIO_Remap_SPI0_MOSI);	//直连
	}
	else if( spix == SPI1 )
	{
		gpio_remap_config(GPIOA_Pin4,GPIO_Remap_SPI1_CSN);
		gpio_remap_config(GPIOA_Pin5,GPIO_Remap_SPI1_CLK);
		gpio_remap_config(GPIOA_Pin6,GPIO_Remap_SPI1_MISO);
		gpio_remap_config(GPIOA_Pin7,GPIO_Remap_SPI1_MOSI);
	}	 
	 
	spi_init_structure.spi_mode 					= SPI_Mode_Master;//配置SPI主从模式：master
	spi_init_structure.spi_direction				= SPI_Direction_2Lines_FullDuplex;//设置SPI通信方式：全双工模式   
	spi_init_structure.spi_data_size				= SPI_DataSize_8b; //设置数据帧大小：8bit	
	spi_init_structure.spi_cpol 					= SPI_CPOL_Low;//设置时钟极性:空闲状态时，时钟保持低电平
	spi_init_structure.spi_cpha 					= SPI_CPHA_1Edge;//设置时钟相位：数据采样从第二个时钟边沿开始
	spi_init_structure.spi_nss						= SPI_NSS_0;//NSS信号控制选择
//	spi_init_structure.spi_baud_rate_prescaler		= SPI_BaudRatePrescaler_256;//SPI波特率分频：256 ，SPI速率=16M/256 =62.5KHz
	spi_init_structure.spi_baud_rate_prescaler		= 24;//SPI波特率分频：256 ，SPI速率=16M/256 =62.5KHz
	spi_init_structure.spi_rx_fifo_full_threshold	= SPI_RXFIFOFullThreshold_1;//接收FIFO空中断阈值：接收FIFO中数据1个及以上触发中断
	spi_init_structure.spi_tx_fifo_empty_threshold	= SPI_TXFIFOEmptyThreshold_0;//发送FIFO满中断阈值：发送FIFO中数据数量为0触发中断
	
	spi_init(spix, &spi_init_structure);//SPI初始化
	spi_it_config(spix, SPI_IT_RXF | SPI_IT_TXE, DISABLE);
	spi_cmd(spix, ENABLE);//SPI使能

	while(1)
	{
		master_tx_pos = 0;
		master_tx_len = 22;
		spi_it_config(spix, SPI_IT_RXF | SPI_IT_TXE, ENABLE);
		
		for(i = 0 ; i < 0x1ffffff ; i++);	
		
	}
}

void SLAVER_SPI0_IRQHandler(void)
{
	slaver_spi_irq_protol_handler(SPI0);
	NVIC_ClearPendingIRQ(SPI0_IRQn);
}

void MASTER_SPI0_IRQHandler(void)
{
	master_spi_irq_protol_handler(SPI0);
	NVIC_ClearPendingIRQ(SPI0_IRQn);
}

#endif
