MTK SPI驅動開發
阿新 • • 發佈:2018-11-02
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模組自己控制,此程式碼僅供各位參考,多多指教。