搜索
bottom↓
回复: 4

请教:W25Q32JVSSIQ读写遇到问题.

[复制链接]

出0入0汤圆

发表于 2020-11-7 15:01:22 | 显示全部楼层 |阅读模式
W25Q32JVSSIQ读写遇到问题,请各位老师赐教!
在商城上买了几片W25Q32JVSSIQ,使用的时候遇到无法读写的问题,操作流程如下:
1、        读寄存器1-3;
2、        写寄存器1的WEL位,设置为允许写入;
3、        读寄存器1-3,确认WEL位为1;
4、        擦除扇区,设置读写地址为0x100000;
5、        写寄存器1的WEL位,设置为允许写入;
6、        吸入数据,地址为0x100000,写入数据为0x78;
7、        读取数据,地址为0x100000,但是读取到的数据,不是写入的数据0x78!!!
请指教,谢谢!

在写入0x06的时候,可以看到寄存器1的WEL位设置为1。

不知是否在读写之前需要对芯片的寄存器1-3进行读写设置,按照自己的理解设置了,还是无效。

主程序如下:

   //Read Reg
   ReadREG3=Read_Reg(1);
   ReadREG3=Read_Reg(2);
   ReadREG3=Read_Reg(3);
   
   //Write Enable
   W25Q32_Write_Enable();
   
   //Read Reg
   ReadREG3=Read_Reg(1);
   ReadREG3=Read_Reg(2);
   ReadREG3=Read_Reg(3);

   //WIPE Data
   Wipe_4k(0x10,0x00,0x00);

   //Write Enable
   W25Q32_Write_Enable();

   //Write data
   Write_Data(0x10,0x00,0x00,0x78);

   //Read Data
   ReadData=Read_Data(0x10,0x00,0x00);
   
   //Read Reg
   ReadREG1=Read_Reg(1);
   ReadREG2=Read_Reg(2);
   ReadREG3=Read_Reg(3);




读寄存器子程序:
uchar Read_Reg(uchar _RegIndex)
{
   uchar UCharTemp1,UCharTemp2;
   if((_RegIndex>0)&&(_RegIndex<4))
   {
      SPCR=0x51;
      PORTE&=~BIT(7);//CS Enable
      delay_clcok(10);
      if(_RegIndex==1)
      {
         UCharTemp1=0x05;
      }
      else if(_RegIndex==2)
      {
         UCharTemp1=0x35;
      }
      else if(_RegIndex==3)
      {
         UCharTemp1=0x15;
      }
      UCharTemp2=SPI_Transmit(UCharTemp1);
      SPCR=0x59;
      delay_clcok(10);   
      UCharTemp1=SPI_Transmit(0x00);
      PORTE|=BIT(7); //CS Disable
      delay_clcok(10);
      return UCharTemp1;
   }
}

判读是否忙子程序:
uchar W25Q32_Busy(void)
{
   uchar UCharTemp1,UCharTemp2;
   UCharTemp1=Read_Reg(1);
   if(UCharTemp1&01)
   {
      UCharTemp2=1;
   }
   else if(!(UCharTemp1&01))
   {
      UCharTemp2=0;
   }
   
   return UCharTemp2;
}

//25Q32允许写入子程序(写入0x06)
void W25Q32_Write_Enable(void)
{
   uchar UCharTemp1,UCharTemp2;
   
   do
   {
      UCharTemp1=W25Q32_Busy();
   }   
   while(UCharTemp1);
   
   SPCR=0x51;
   PORTE&=~BIT(7); //CS Enable
   delay_clcok(10);
      
   UCharTemp1=SPI_Transmit(0x06);
   
   delay_clcok(10);
   PORTE|=BIT(7); //CS Disable
   delay_clcok(10);
   
   do
   {
      UCharTemp1=W25Q32_Busy();
   }   
   while(UCharTemp1);
      
}

//扇区擦除子程序
void Wipe_4k(uchar _Add1,uchar _Add2,uchar _Add3)
{
   uchar UCharTemp1,UCharTemp2;
   
   do
   {
      UCharTemp1=W25Q32_Busy();
   }   
   while(UCharTemp1);
      
   SPCR=0x51;
   PORTE&=~BIT(7); //CS Enable
   delay_clcok(10);
     
   UCharTemp2=SPI_Transmit(0x20);  
   UCharTemp2=SPI_Transmit(_Add1);  
   UCharTemp2=SPI_Transmit(_Add2);
   UCharTemp2=SPI_Transmit(_Add3);

      
   delay_clcok(10);
   PORTE|=BIT(7); //CS Disable
   delay_clcok(10);
            
   do
   {
      UCharTemp1=W25Q32_Busy();
   }   
   while(UCharTemp1);
      

}

//写入数据子程序
void Write_Data(uchar _Add1,uchar _Add2,uchar _Add3,uchar _Data)
{
   uchar UCharTemp1,UCharTemp2;
   
   do
   {
      UCharTemp1=W25Q32_Busy();
   }   
   while(UCharTemp1);
      
   SPCR=0x51;
   PORTE&=~BIT(7); //CS Enable
   delay_clcok(10);
     
   UCharTemp2=SPI_Transmit(0x02);  
   UCharTemp2=SPI_Transmit(_Add1);  
   UCharTemp2=SPI_Transmit(_Add2);
   UCharTemp2=SPI_Transmit(_Add3);
   UCharTemp2=SPI_Transmit(_Data);
      
   delay_clcok(10);
   PORTE|=BIT(7); //CS Disable
   delay_clcok(10);
            
   do
   {
      UCharTemp1=W25Q32_Busy();
   }   
   while(UCharTemp1);
}

//读取数据子程序
uchar Read_Data(uchar _Add1,uchar _Add2,uchar _Add3)
{
   uchar UCharTemp1,UCharTemp2;
   
   do
   {
      UCharTemp1=W25Q32_Busy();
   }   
   while(UCharTemp1);
      
   SPCR=0x51;
   PORTE&=~BIT(7); //CS Enable
   delay_clcok(10);
   
   UCharTemp2=SPI_Transmit(0x03);   
   UCharTemp2=SPI_Transmit(_Add1);  
   UCharTemp2=SPI_Transmit(_Add2);
   UCharTemp2=SPI_Transmit(_Add3);
   SPCR=0x59;
   delay_clcok(10);   
   UCharTemp2=SPI_Transmit(0x00);
      
   delay_clcok(10);
   PORTE|=BIT(7); //CS Disable
   delay_clcok(10);
            
   do
   {
      UCharTemp1=W25Q32_Busy();
   }   
   while(UCharTemp1);
      
   return(UCharTemp2);
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入442汤圆

发表于 2020-11-7 17:19:59 来自手机 | 显示全部楼层
wp和hold接对了吗?新片子可能没有解锁,先把status reg写0再试试。

出25入84汤圆

发表于 2020-11-7 17:29:49 | 显示全部楼层
本帖最后由 chun2495 于 2020-11-7 17:31 编辑

给楼主上传个自己写的模拟io的程序,linux的。原理是一样。
  1. /*
  2. * 说明:w25q驱动程序,在android上运行。
  3. * 日期:2020.04.07
  4. * 作者:chun307
  5. */

  6. #include <linux/kernel.h>
  7. #include <linux/module.h>
  8. #include <linux/i2c.h>
  9. #include <linux/input.h>
  10. #include <linux/delay.h>
  11. #include <linux/slab.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/irq.h>
  14. #include <linux/gpio.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/miscdevice.h>
  17. #include <asm/uaccess.h>

  18. #define DEVICE_NAME        "epcs_ctl"
  19. #define DRIVER_NAME        "epcs_ctl"

  20. #define SPI_CS                IMX_GPIO_NR(2, 28)//MX6Q_PAD_EIM_EB0__GPIO_2_28
  21. #define SPI_CLK                IMX_GPIO_NR(2, 29)//MX6Q_PAD_EIM_EB1__GPIO_2_29
  22. #define SPI_TXD                IMX_GPIO_NR(3, 26)//MX6Q_PAD_EIM_D26__GPIO_3_26
  23. #define SPI_RXD                IMX_GPIO_NR(3, 27)//MX6Q_PAD_EIM_D27__GPIO_3_27


  24. static int epcss_out[] = {
  25.         SPI_CS,
  26.         SPI_CLK,
  27.         SPI_TXD,
  28. };

  29. static int epcss_in[] = {
  30.         SPI_RXD,
  31. };

  32. #define GPIO_NUM_OUT        ARRAY_SIZE(epcss_out)
  33. #define GPIO_NUM_IN         ARRAY_SIZE(epcss_in)


  34. #define GPIO_HIGH                  1
  35. #define GPIO_LOW                   0
  36. #define CS_OUT()         gpio_direction_output(SPI_CS, 1)
  37. #define CS_HIGH()        gpio_set_value(SPI_CS, GPIO_HIGH)
  38. #define CS_LOW()         gpio_set_value(SPI_CS, GPIO_LOW)
  39. #define CLK_OUT()        gpio_direction_output(SPI_CLK, 1)
  40. #define CLK_HIGH()       gpio_set_value(SPI_CLK, GPIO_HIGH)
  41. #define CLK_LOW()        gpio_set_value(SPI_CLK, GPIO_LOW)
  42. #define TXD_OUT()        gpio_direction_output(SPI_TXD, 1)
  43. #define TXD_HIGH()       gpio_set_value(SPI_TXD, GPIO_HIGH)
  44. #define TXD_LOW()        gpio_set_value(SPI_TXD, GPIO_LOW)
  45. #define RXD_IN()                 gpio_direction_input(SPI_RXD)
  46. #define RXD_GET()                   gpio_get_value(SPI_RXD)

  47. //页大小和页数目
  48. #define EPCS_Page_Size                 256
  49. #define EPCS_Page_Max                 8192
  50. //功能寄存器地址
  51. #define WRITE_ENABLE                 0X06
  52. #define WRITE_DISABLE                 0X04
  53. #define READ_ID                         0X9F
  54. #define READ_STAUS_REG                 0X05
  55. #define WRITE_STAUS_REG         0X01
  56. #define READ_DATA                         0X03
  57. #define FAST_READ_DATA                 0X0B
  58. #define PAGE_PROGRAM                 0X02
  59. #define SECTOR_ERASE                 0XD8
  60. #define BULK_ERASE                         0XC7
  61. #define DEEP_POWER_DOWN         0XB9
  62. #define WAKE_UP                         0XAB


  63. unsigned char SPI_Flash_Read()
  64. {
  65.         unsigned char i = 0;
  66.         unsigned char temp = 0;        //read data

  67.         for (i = 0; i < 8; i++){        // 8 bits Data
  68.                 CLK_LOW();
  69. //                udelay(1);
  70.                 CLK_HIGH();
  71.                 temp <<= 1;
  72.                 temp |= RXD_GET();
  73. //                udelay(1);
  74.         }
  75.         return temp;
  76. }

  77. void SPI_Flash_Write(unsigned char data)
  78. {
  79.         unsigned char i;

  80.         for (i = 0; i < 8; i++){
  81.                 CLK_LOW();
  82. //                udelay(1);
  83.                 if (data & 0x80){
  84.                         TXD_HIGH();
  85.                 } else{
  86.                         TXD_LOW();
  87.                 }
  88.                 CLK_HIGH();
  89. //                udelay(1);
  90.                 data <<= 1;
  91.         }
  92. }

  93. void EPCS_Write_Enable(void)
  94. {
  95.         CS_LOW();
  96.         SPI_Flash_Write(WRITE_ENABLE);
  97.         CS_HIGH();
  98. }

  99. void EPCS_Write_Disable(void)
  100. {
  101.         CS_LOW();
  102.         SPI_Flash_Write(WRITE_DISABLE);
  103.         CS_HIGH();
  104. }

  105. unsigned int EPCS_Read_Id()
  106. {
  107.         unsigned char i;
  108.         unsigned char id[3];
  109.        
  110.         CS_LOW();
  111.         SPI_Flash_Write(READ_ID);
  112.         for(i = 0; i < 3; i++){
  113.                 id[i] = SPI_Flash_Read();
  114.         }
  115.         CS_HIGH();
  116. //        printk("ID: 0X%X 0X%X 0X%X\n", id[0], id[1], id[2]);
  117.         return (unsigned int)((id[0]<<16) | (id[1]<< 8) | id[2]);
  118. }

  119. unsigned char EPCS_Read_Status_Reg(void)
  120. {
  121.         unsigned char sta;
  122.        
  123.         CS_LOW();
  124.         SPI_Flash_Write(READ_STAUS_REG);
  125.         sta= SPI_Flash_Read();
  126.         CS_HIGH();
  127.         return sta;
  128. }

  129. void EPCS_Write_Status_Reg(unsigned char reg)
  130. {
  131.         CS_LOW();
  132.         SPI_Flash_Write(WRITE_STAUS_REG);       
  133.         SPI_Flash_Write(reg);
  134.         CS_HIGH();
  135. }

  136. void EPCS_Sector_Erase(unsigned int addr)
  137. {
  138.         addr *= 65536; //扇区*页(64K)
  139.         EPCS_Write_Enable();
  140.        
  141.         CS_LOW();
  142.         SPI_Flash_Write(SECTOR_ERASE);       
  143.         SPI_Flash_Write((addr>>16) & 0xff);
  144.         SPI_Flash_Write((addr>>8) & 0xff);
  145.         SPI_Flash_Write(addr & 0xff);
  146.         CS_HIGH();
  147.        
  148.         while(EPCS_Read_Status_Reg()&0x01);
  149. }

  150. void EPCS_Bulk_Erase(void)
  151. {
  152.         EPCS_Write_Enable();
  153.        
  154.         CS_LOW();
  155.         SPI_Flash_Write(BULK_ERASE);
  156.         CS_HIGH();
  157.        
  158.         while(EPCS_Read_Status_Reg()&0x01);
  159. }

  160. void EPCS_Deep_Power_Down(void)
  161. {
  162.         CS_LOW();
  163.         SPI_Flash_Write(DEEP_POWER_DOWN);
  164.         CS_HIGH();
  165. }

  166. unsigned char EPCS_Wake_Up(void)
  167. {
  168.         unsigned char res;
  169.        
  170.         CS_LOW();
  171.         SPI_Flash_Write(WAKE_UP);
  172.         SPI_Flash_Write(0);
  173.         SPI_Flash_Write(0);
  174.         SPI_Flash_Write(0);
  175.         res = SPI_Flash_Read();
  176.         CS_HIGH();
  177.         return res;
  178. }

  179. //读数据,自动翻页,addr为字节地址
  180. void EPCS_Read_Data(unsigned int addr, unsigned int len, unsigned char *buf)
  181. {
  182.         unsigned int i;
  183.        
  184.         CS_LOW();
  185.         SPI_Flash_Write(READ_DATA);       
  186.         SPI_Flash_Write((addr>>16) & 0xff);//扇区:16个
  187.         SPI_Flash_Write((addr>>8) & 0xff); //页:256页
  188.         SPI_Flash_Write(addr & 0xff);//页内地址:256字节
  189.         for(i = 0; i < len; i++){
  190.           buf[i] = SPI_Flash_Read();
  191.         }
  192.         CS_HIGH();
  193. }

  194. //快速读数据
  195. void EPCS_Fast_Read_Data(unsigned int addr, unsigned int len, unsigned char *buf)
  196. {
  197.         unsigned int i;

  198.         CS_LOW();
  199.         SPI_Flash_Write(FAST_READ_DATA);       
  200.         SPI_Flash_Write((addr>>16) & 0xff);
  201.         SPI_Flash_Write((addr>>8) & 0xff);
  202.         SPI_Flash_Write(addr & 0xff);
  203.         SPI_Flash_Write(0);
  204.         for(i = 0; i < len; i++){
  205.                 buf[i] = SPI_Flash_Read();
  206.         }
  207.         CS_HIGH();
  208. }

  209. //页编程函数,页编程前一定要进行区擦除!
  210. void EPCS_Page_Program(unsigned int addr, unsigned short len, unsigned char *buf)
  211. {
  212.         unsigned int i;
  213.        
  214.         EPCS_Write_Enable();
  215.        
  216.         CS_LOW();
  217.         SPI_Flash_Write(PAGE_PROGRAM);
  218.         SPI_Flash_Write((addr>>16) & 0xff);
  219.         SPI_Flash_Write((addr>>8) & 0xff);
  220.         SPI_Flash_Write(addr & 0xff);
  221.         for(i = 0; i < len; i++)
  222.                 SPI_Flash_Write(buf[i]);
  223.         CS_HIGH();
  224.        
  225.         while(EPCS_Read_Status_Reg()&0x01);
  226. }

  227. /*****************************************************************************
  228. *函数名称:void M25PXX_Write_NoCheck(unsigned char* pBuffer,unsigned int WriteAddr,u16 NumByteToWrite)
  229. *功    能:无检验写SPI FLASH,具有自动换页功能
  230. *说    明:必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
  231. *输入参数:pBuffer:数据存储区,WriteAddr:开始写入的地址(24bit),
  232.          NumByteToWrite:要写入的字节数(最大65535)
  233. *输出参数:无
  234. ******************************************************************************/
  235. void EPCS_Write_NoCheck(unsigned char * pBuffer, unsigned int WriteAddr, unsigned int NumByteToWrite)
  236. {
  237.         unsigned int pageremain;
  238.        
  239.         pageremain = 256 - WriteAddr%256; //单页剩余的字节数
  240.         if(NumByteToWrite <= pageremain) pageremain = NumByteToWrite;//不大于256个字节
  241.         while(1){
  242.                 EPCS_Page_Program(WriteAddr, pageremain, pBuffer);//写页
  243.                 if(NumByteToWrite == pageremain) break;//写入结束了
  244.                  else{ //NumByteToWrite>pageremain
  245.                         pBuffer += pageremain;
  246.                         WriteAddr += pageremain;
  247.                         NumByteToWrite -= pageremain;                           //减去已经写入了的字节数
  248.                         if(NumByteToWrite > 256) pageremain = 256; //一次可以写入256个字节
  249.                         else pageremain = NumByteToWrite;                      //不够256个字节了
  250.                 }
  251.         }
  252. }

  253. static int okmx6q_epcs_open(struct inode *inode, struct file *file) {
  254.         return 0;
  255. }

  256. static int okmx6q_epcs_close(struct inode *inode, struct file *file) {
  257.         return 0;
  258. }

  259. //count(最大65535)
  260. static ssize_t okmx6q_epcs_read(struct file *filp, char __user *buf, size_t count, loff_t *ofs)
  261. {
  262.         printk("EPCS read count is %d, ofs is %d\n", count, *ofs);
  263.        
  264.         unsigned int i;
  265.         unsigned int addr = *ofs;
  266.         unsigned int len = count;

  267.         CS_LOW();
  268.         SPI_Flash_Write(READ_DATA);
  269.         SPI_Flash_Write((addr>>16) & 0xff);
  270.         SPI_Flash_Write((addr>>8) & 0xff);
  271.         SPI_Flash_Write(addr & 0xff);
  272.        
  273.         for(i = 0; i < len; i++){
  274.                 buf[i] = SPI_Flash_Read();
  275.         }
  276.         CS_HIGH();
  277.        
  278.         printk("EPCS read done!\n");
  279.         return 0;
  280. }

  281. /*****************************************************************************
  282. *函数名称:void M25PXX_Write(unsigned char* pBuffer,unsigned int WriteAddr,u16 NumByteToWrite)
  283. *功    能:写SPI FLASH,在指定地址开始写入指定长度的数据
  284. *说    明:该函数带擦除操作!
  285. *输入参数:pBuffer:数据存储区,WriteAddr:开始写入的地址(24bit),               
  286.          NumByteToWrite:要写入的字节数(最大65535)
  287. *输出参数:无
  288. ******************************************************************************/       
  289. unsigned char EPCS_BUFFER[65536];
  290. static ssize_t okmx6q_epcs_write(struct file *filp, const char __user *pBuffer, size_t NumByteToWrite, loff_t *ofs)
  291. {
  292.        
  293.         unsigned int WriteAddr = *ofs;
  294.         unsigned int secpos;
  295.         unsigned int secoff;
  296.         unsigned int secremain;
  297.         unsigned int i;
  298.         unsigned char *EPCS_BUF;
  299.        
  300.         printk("EPCS Write Len : %d, Addr : %d\n", NumByteToWrite, WriteAddr);
  301.        
  302.            EPCS_BUF = EPCS_BUFFER;                        //得到数值缓存区
  303.         secpos = WriteAddr/65536;                //扇区地址
  304.         secoff = WriteAddr%65536;                //在扇区内的偏移
  305.         secremain = 65536 - secoff;                //扇区剩余空间大小
  306.         if(NumByteToWrite <= secremain) secremain = NumByteToWrite;//不大于64K个字节
  307.         while(1){
  308.                 printk("read start...\n");
  309.                 EPCS_Read_Data(secpos*65536, 65536, EPCS_BUF);//读出整个扇区的内容
  310.                 for(i = 0; i < secremain; i++){//校验数据
  311.                         if(EPCS_BUF[secoff + i] != 0XFF) break;//需要擦除
  312.                 }
  313.                 printk("write start...\n");
  314.                 if(i < secremain){//需要擦除
  315.                         EPCS_Sector_Erase(secpos);//擦除这个扇区
  316.                         for(i = 0; i < secremain; i++){//复制
  317.                                 EPCS_BUF[i + secoff] = pBuffer[i];
  318.                         }
  319.                         EPCS_Write_NoCheck(EPCS_BUF, secpos*65536, 65536);//写入整个扇区
  320.                 }else EPCS_Write_NoCheck(pBuffer, WriteAddr, secremain);//写已经擦除了的,直接写入扇区剩余区间.
  321.                 if(NumByteToWrite == secremain) break;//写入结束了
  322.                 else{//写入未结束
  323.                         secpos++;                                //扇区地址增1
  324.                         secoff = 0;                         //偏移位置为0
  325.                            pBuffer += secremain;   //指针偏移
  326.                         WriteAddr += secremain; //写地址偏移
  327.                            NumByteToWrite -= secremain;                                        //字节数递减
  328.                         if(NumByteToWrite > 65536) secremain = 65536;        //下一个扇区还是写不完
  329.                         else secremain = NumByteToWrite;                                //下一个扇区可以写完了
  330.                 }
  331.                 printk("EPCS write done!\n");
  332.         }
  333.         return 0;
  334. }

  335. /* static ssize_t okmx6q_epcs_write(struct file *filp, const char __user *pBuffer, size_t NumByteToWrite, loff_t *ofs)
  336. {
  337.         unsigned int i;
  338.         unsigned int addr = *ofs;
  339.         unsigned int len = NumByteToWrite;
  340.        
  341.         printk("EPCS Write Len : %d, Addr : %d\n", len, addr);
  342.        
  343.         EPCS_Sector_Erase(addr/65536);//擦除这个扇区
  344.        
  345.         EPCS_Write_Enable();
  346.        
  347.         CS_LOW();
  348.         SPI_Flash_Write(PAGE_PROGRAM);
  349.         SPI_Flash_Write((addr>>16) & 0xff);
  350.         SPI_Flash_Write((addr>>8) & 0xff);
  351.         SPI_Flash_Write(addr & 0xff);
  352.         for(i = 0; i < len; i++){
  353.                 SPI_Flash_Write(pBuffer[i]);
  354.         }
  355.         CS_HIGH();
  356.        
  357.         while(EPCS_Read_Status_Reg()&0x01);
  358.        
  359.         printk("EPCS write done!\n");
  360.         return 0;
  361. } */

  362. /* static ssize_t okmx6q_epcs_write(struct file *filp, const char __user *pBuffer, size_t NumByteToWrite, loff_t *ofs)
  363. {
  364.         unsigned int i;
  365.         unsigned int addr = *ofs;
  366.         unsigned int len = NumByteToWrite;
  367.        
  368.         printk("EPCS Write Len : %d, Addr : %d\n", len, addr);
  369.        
  370.         EPCS_Sector_Erase(addr/65536);//擦除这个扇区
  371.        
  372.         EPCS_Write_NoCheck(pBuffer, addr, len);
  373.        
  374.         printk("EPCS write done!\n");
  375.         return 0;
  376. } */

  377. static long okmx6q_epcs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  378. {
  379.         unsigned int ret = 0;
  380.        
  381.         printk("cmd is %d, arg is %d\n", cmd, arg);
  382.        
  383.         switch(cmd) {
  384.                 case 0:        ret = EPCS_Read_Id();
  385.                         break;
  386.                 default:
  387.                         printk("error\n");
  388.                         return -EINVAL;
  389.         }
  390.         return ((long)ret);
  391. }

  392. static struct file_operations okmx6q_epcs_ops = {
  393.         .owner                        = THIS_MODULE,
  394.         .open                        = okmx6q_epcs_open,
  395.         .release                = okmx6q_epcs_close,
  396.         .read                        = okmx6q_epcs_read,
  397.         .write              = okmx6q_epcs_write,
  398.         .unlocked_ioctl        = okmx6q_epcs_ioctl,
  399. };

  400. static struct miscdevice okmx6q_misc_dev = {
  401.         .minor = MISC_DYNAMIC_MINOR,
  402.         .name = DEVICE_NAME,
  403.         .fops = &okmx6q_epcs_ops,
  404. };

  405. static int okmx6q_epcs_probe(struct platform_device *pdev)
  406. {
  407.         int ret;
  408.        
  409.         //SPI_CS
  410.         ret = gpio_request(SPI_CS, DEVICE_NAME);
  411.         if (ret) {
  412.                 printk("request SPI_CS failed, ret= %d\n", ret);
  413.                 return ret;
  414.         }
  415.         else{
  416.                 gpio_direction_output(SPI_CS, 1);
  417.                 gpio_set_value(SPI_CS, 1);
  418.         }
  419.        
  420.         //SPI_CLK
  421.         ret = gpio_request(SPI_CLK, DEVICE_NAME);
  422.         if (ret) {
  423.                 printk("request SPI_CLK failed, ret= %d\n", ret);
  424.                 return ret;
  425.         }
  426.         else{
  427.                 gpio_direction_output(SPI_CLK, 1);
  428.                 gpio_set_value(SPI_CLK, 1);
  429.         }
  430.        
  431.         //SPI_TXD
  432.         ret = gpio_request(SPI_TXD, DEVICE_NAME);
  433.         if (ret) {
  434.                 printk("request SPI_TXD failed, ret= %d\n", ret);
  435.                 return ret;
  436.         }
  437.         else{
  438.                 gpio_direction_output(SPI_TXD, 1);
  439.                 gpio_set_value(SPI_TXD, 1);
  440.         }
  441.        
  442.         //SPI_RXD
  443.         ret = gpio_request(SPI_RXD, DEVICE_NAME);
  444.         if (ret) {
  445.                 printk("request SPI_RXD failed, ret= %d\n", ret);
  446.                 return ret;
  447.         }
  448.         else{
  449.                 gpio_direction_input(SPI_RXD);
  450.         }
  451.        
  452.         ret = misc_register(&okmx6q_misc_dev);
  453.         printk(DEVICE_NAME "\tinitialized\n");
  454.         return 0;
  455. }

  456. static int okmx6q_epcs_remove (struct platform_device *pdev)
  457. {
  458.         int i;
  459.        
  460.         for(i = 0; i < GPIO_NUM_OUT; i++){
  461.                 gpio_free(epcss_out[i]);
  462.         }
  463.         for(i = 0; i < GPIO_NUM_IN; i++){
  464.                 gpio_free(epcss_in[i]);
  465.         }
  466.         misc_deregister(&okmx6q_misc_dev);

  467.         return 0;
  468. }

  469. static int okmx6q_epcs_suspend (struct platform_device *pdev, pm_message_t state)
  470. {
  471.         printk("epcs suspend!\n");
  472.         return 0;
  473. }

  474. static int okmx6q_epcs_resume (struct platform_device *pdev)
  475. {
  476.         printk("epcs resume!\n");
  477.         return 0;
  478. }

  479. static struct platform_driver okmx6q_epcs_driver = {
  480.         .probe = okmx6q_epcs_probe,
  481.         .remove = okmx6q_epcs_remove,
  482.         .suspend = okmx6q_epcs_suspend,
  483.         .resume = okmx6q_epcs_resume,
  484.         .driver = {
  485.                 .name = DRIVER_NAME,
  486.                 .owner = THIS_MODULE,
  487.         },
  488. };

  489. static int __init okmx6q_epcs_dev_init(void) {
  490.         return platform_driver_register(&okmx6q_epcs_driver);
  491. }

  492. static void __exit okmx6q_epcs_dev_exit(void) {
  493.         platform_driver_unregister(&okmx6q_epcs_driver);
  494. }

  495. module_init(okmx6q_epcs_dev_init);
  496. module_exit(okmx6q_epcs_dev_exit);

  497. MODULE_LICENSE("GPL");
  498. MODULE_AUTHOR("chun307");
  499. MODULE_DESCRIPTION("OKMX6Q EPCS Driver");
复制代码

出0入0汤圆

 楼主| 发表于 2020-11-7 18:11:07 | 显示全部楼层
chun2495 发表于 2020-11-7 17:29
给楼主上传个自己写的模拟io的程序,linux的。原理是一样。

收到,谢谢。我先研究下,搞不出来还要向你请教。

出0入0汤圆

 楼主| 发表于 2020-11-7 18:14:11 | 显示全部楼层
wye11083 发表于 2020-11-7 17:19
wp和hold接对了吗?新片子可能没有解锁,先把status reg写0再试试。

WP通过一个10k接的VCC,HOLD脚悬空的。这样有问题不?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-16 22:31

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表