MTK SPI驱动开发

MTK SPI驱动开发

1.由于SPI驱动 MTK封装的比较好,所以比较好处理。

唯一需要注意的是spi使用的全局Buffer必须要放在内存地址为“NONCACHEDZI”的区域

直接上代码管脚配置此处不再赘述
/*****************************************************************
    
    简单封装的 SPI 驱动代码
    Author     
    Date       20180915
    
    *****************************************************************/
    //外部GPIO函数声明:
    //初始化GPIO方向
    extern void GPIO_InitIO(char direction, kal_uint16 port);
    //读指定GPIO口的管脚值
    extern char GPIO_ReadIO(kal_uint16 port);
    //输出指定电平到GPIO
    extern void GPIO_WriteIO(char data, kal_uint16 port);
    //设置GPIO的模式。GPIO模式为模式0.
    extern void GPIO_ModeSetup(kal_uint16 port, kal_uint16 conf_dada);
    //设置GPIO的上/下拉使能
    extern void GPIO_PullenSetup(kal_uint16 port, kal_bool enable);
    //设置GPIO端口为上拉还是下拉
    extern void GPIO_PullSelSetup(kal_uint16 port, kal_bool pull_up);
    
    void spi_delayms(unsigned int ms)
    {
      unsigned int x , y;
      for(x = ms; x > 0; x--)           /*  通过一定周期循环进行延时*/
        for(y = 3000 ; y > 0 ; y--);
    }
    
    #define SPI_GROUP0_CS_PIN	(18|0x80)
    #define SPI_GROUP1_CS_PIN	(14|0x80)
    
    
    #define SPI_CS_CPIO_INIT	GPIO_ModeSetup(SPI_GROUP0_CS_PIN, 0);\
    							GPIO_ModeSetup(SPI_GROUP1_CS_PIN, 0);\
    							GPIO_PullenSetup(SPI_GROUP0_CS_PIN, 0);\
    							GPIO_PullenSetup(SPI_GROUP1_CS_PIN, 0);\
    							GPIO_PullSelSetup(SPI_GROUP0_CS_PIN, 0);\
    							GPIO_PullSelSetup(SPI_GROUP1_CS_PIN, 0);\
    							GPIO_InitIO(1, SPI_GROUP0_CS_PIN);\
    							GPIO_InitIO(1, SPI_GROUP1_CS_PIN);\
    							GPIO_WriteIO(1, SPI_GROUP0_CS_PIN);\
    							GPIO_WriteIO(1, SPI_GROUP1_CS_PIN);
    
    #define SPI_CS_PIN_SET(group)	if(0 == group)\
                                        GPIO_WriteIO(1,	SPI_GROUP0_CS_PIN);\
    								else\
    									GPIO_WriteIO(1,	SPI_GROUP1_CS_PIN);
    
    #define SPI_CS_PIN_CLR(group)	if(0 == group)\
    									GPIO_WriteIO(0,	SPI_GROUP0_CS_PIN);\
    								else\
    								    GPIO_WriteIO(0,	SPI_GROUP1_CS_PIN);
    
    
    //spi driver使用的buffer必须定义为non cachedrw	大小暂时为10k
    #define SPI_WRITE_BUFF_MAXSIZE (1024*5)
    #define SPI_READ_BUFF_MAXSIZE  (1024*5)
    
    //放在段空间为  NONCACHEDRW  的位置 
    #pragma arm section rwdata = "NONCACHEDRW", zidata = "NONCACHEDZI"
    __align(4) kal_uint8 g_spi_write_buffer[SPI_WRITE_BUFF_MAXSIZE] = {0};
    __align(4) kal_uint8 g_spi_read_buffer[SPI_READ_BUFF_MAXSIZE] = {0};
    #pragma arm section rwdata, zidata
    
    //目前设计只支持5组SPI调用
    #define SPI_AVAIABLE_PORT	0
    #define MAX_SPI_GROUP 		5
    
    typedef enum
    {
    	SPI_IS_CLOSED,
    	SPI_IS_OPEN,	
    	SPI_MAX_STATUS,
    }SPI_ISOPEN;
    
    typedef struct
    {
    	SPI_ISOPEN 			spi_isopen_status;
    	SPI_CONFIG_PARAM_T	spi_config_param;
    }SPI_DESCRIPTION;
    
    static SPI_HANDLE		 g_spi_handle;
    static SPI_DESCRIPTION  g_spi_description[MAX_SPI_GROUP]= {0};
    
    //用于预防SPI操作过程中被打断的互斥变量
    static kal_mutexid  g_spi_mutexid = 0;
    
    //开放我们可用的SPI只有PORT 0:
    SPI_RESULT m_spi_configure(SPI_HANDLE handle, SPI_CONFIG_PARAM_T* pConfigParam)
    { 
    	return spi_configure(handle,pConfigParam);
    }
    
    SPI_RESULT m_spi_write(kal_uint32 group, void* pBuffer, kal_uint32 length, kal_uint32 count, SPI_CALLBACK fCB)
    {
    	SPI_RESULT	spi_status;
    	//如果此接口未打开,则返回ERROR
    	if(SPI_IS_OPEN != g_spi_description[group].spi_isopen_status)	
    	{
    		return SPI_RESULT_ERROR;
    	}
    	//SPI 端口未打开
    	if(0 == g_spi_handle)
    	{
    		return SPI_RESULT_ERROR;
    	}
    
    	//spi_status = m_spi_configure(g_spi_handle,&g_spi_description[group].spi_config_param);
    
    	if(SPI_RESULT_OK != spi_status)
    	{
    		//return spi_status;
    	}
    
        kal_take_mutex(g_spi_mutexid);
    	
    	if(0 == group)	SPI_CS_PIN_CLR(group);
    	memcpy(g_spi_write_buffer,(kal_uint8*)pBuffer,length);
    	spi_status = spi_write(g_spi_handle,g_spi_write_buffer,length,count,fCB);
    	if(0 == group)	SPI_CS_PIN_SET(group);
        
    	kal_give_mutex(g_spi_mutexid);
    
    	return spi_status;
    }
    
    SPI_RESULT m_spi_read(kal_uint32 group,void* pBuffer, kal_uint32 length, kal_uint32 count, SPI_CALLBACK fCB)
    {	
    	SPI_RESULT spi_status;
    
    	//如果此接口未打开,则返回ERROR
    	if(SPI_IS_OPEN != g_spi_description[group].spi_isopen_status)	
    	{
    		return SPI_RESULT_ERROR;
    	}
    	//SPI 端口未打开
    	if(0 == g_spi_handle)
    	{
    		return SPI_RESULT_ERROR;
    	}
    
    	//spi_status = m_spi_configure(g_spi_handle,&g_spi_description[group].spi_config_param);
    
    	if(SPI_RESULT_OK != spi_status)
    	{
    		//return spi_status;
    	}	
    
        kal_take_mutex(g_spi_mutexid);
    	
    	if(0 == group)	SPI_CS_PIN_CLR(group);
    	spi_status =  spi_read(g_spi_handle,g_spi_read_buffer,length,count,fCB);
    	if(0 == group)	SPI_CS_PIN_SET(group);
    	
    	if(SPI_RESULT_OK == spi_status)
    	{
    		memcpy((kal_uint8*)pBuffer,g_spi_read_buffer,length);  
            kal_give_mutex(g_spi_mutexid);	
    		return spi_status;	
    	}
    	
        kal_give_mutex(g_spi_mutexid);
    	return spi_status;
    
    }
    
    SPI_RESULT m_spi_readwrite(kal_uint32 group, void* pOutBuffer, void* pInBuffer, kal_uint32 length, kal_uint32 count, SPI_CALLBACK fCB)
    {
    	SPI_RESULT spi_status;
    
    	//如果此接口未打开,则返回ERROR
    	if(SPI_IS_OPEN != g_spi_description[group].spi_isopen_status)	
    	{
    		return SPI_RESULT_ERROR;
    	}
    	//SPI 端口未打开
    	if(0 == g_spi_handle)
    	{
    		return SPI_RESULT_ERROR;
    	}
    
    	spi_status = m_spi_configure(g_spi_handle,&g_spi_description[group].spi_config_param);
    
    	if(SPI_RESULT_OK != spi_status)
    	{
    		return spi_status;
    	}	
    	
    	memcpy(g_spi_write_buffer,(kal_uint8*)pInBuffer,length);
    	spi_status = spi_readwrite(g_spi_handle,g_spi_read_buffer,g_spi_write_buffer,length,count,fCB);
    	if(SPI_RESULT_OK == spi_status)
    	{
    		memcpy((kal_uint8*)pOutBuffer,g_spi_read_buffer,length);
    		dbg_print("end to readwrite data to spi buffer\n");
    		return spi_status;
    	}	
    
    	return spi_status;
    }
    
    SPI_RESULT m_spi_power_ctrl(kal_bool bPowerOn)
    {
    	return spi_power_ctrl(g_spi_handle,bPowerOn);
    }
    
    //所有的SPIGROUP都是关闭状态,才会调用SPI关闭函数,否则只是置SPI的开关状态为关闭并返回OK
    SPI_RESULT m_spi_close(kal_uint32 group)
    {
    	SPI_RESULT spi_status;
    	kal_uint8 i = 0;
    	g_spi_description[group].spi_isopen_status = SPI_IS_CLOSED;
    
    	for(i = 0 ;i<MAX_SPI_GROUP;i++)
    	{
    		if(SPI_IS_CLOSED != g_spi_description[i].spi_isopen_status)
    		{
    			return SPI_RESULT_OK;
    		}
    	}
    
    	spi_status = spi_close(g_spi_handle);
    	g_spi_handle = 0;
    	return spi_status;
    }
    
    SPI_RESULT m_spi_open(kal_uint32 group, SPI_CONFIG_PARAM_T* pConfigParam)
    {
    	//暂不清楚是否需要关闭在开启,先执行关闭
    	SPI_RESULT spi_status = SPI_RESULT_OK;
    
    	if(0 == g_spi_mutexid)  g_spi_mutexid = kal_create_mutex("SPIMUTEX");
        
    	if(0 == g_spi_handle)
    	{
    		SPI_CS_CPIO_INIT;
    		//SPI_CS_PIN_CLR(0);
    		//SPI_CS_PIN_CLR(1);
    		g_spi_handle = spi_open(SPI_AVAIABLE_PORT);
    		spi_status = m_spi_configure(g_spi_handle,pConfigParam);
    	}
    	
    	if(SPI_RESULT_OK == spi_status)
    	{
    		dbg_print("init spi ok  g_spi_handle = %x \n",g_spi_handle);
    		g_spi_description[group].spi_isopen_status = SPI_IS_OPEN;
    		g_spi_description[group].spi_config_param.cs_setup_time = pConfigParam->cs_setup_time;
    		g_spi_description[group].spi_config_param.cs_hold_time = pConfigParam->cs_hold_time;
    		g_spi_description[group].spi_config_param.cs_idle_time = pConfigParam->cs_idle_time;
    		g_spi_description[group].spi_config_param.clk_low_time = pConfigParam->clk_low_time;
    		g_spi_description[group].spi_config_param.clk_high_time = pConfigParam->clk_high_time;
    		g_spi_description[group].spi_config_param.tx_msbf = pConfigParam->tx_msbf;
    		g_spi_description[group].spi_config_param.rx_msbf = pConfigParam->rx_msbf;
    		g_spi_description[group].spi_config_param.tx_endian = pConfigParam->tx_endian;
    		g_spi_description[group].spi_config_param.rx_endian = pConfigParam->rx_endian;
    		g_spi_description[group].spi_config_param.clk_polarity = pConfigParam->clk_polarity;
    		g_spi_description[group].spi_config_param.clk_fmt = pConfigParam->clk_fmt;
    	}
    	else
    	{
    		g_spi_description[group].spi_isopen_status = SPI_IS_CLOSED;
    	}
    
    	return spi_status;
    }
 由于笔者的硬件系统CS1挂载的是FLASH来使用文件系统,所以CS1的的片选由Flash模块自己控制,此代码仅供各位参考,多多指教。

猜你喜欢

转载自blog.csdn.net/LuoLuoSheShuiShe/article/details/83582339
MTK
今日推荐