OpenEtherCATsociety / SOES

Simple Open Source EtherCAT Slave
Other
559 stars 244 forks source link

linux spi read write error #181

Open 996-PYG opened 2 months ago

996-PYG commented 2 months ago

Hello everyone, I encountered some difficulties while testing SOES. I faced some troubles when using Linux for SPI communication. Since I'm not familiar with the provided driver in the source code, I modified the esc_hw.c file as an alternative. Unfortunately, the program did not run correctly. The return value of ioctl(fd, SPI_IOC_MESSAGE(1), &tr) is -1. However, the SPI communication test code I wrote myself runs correctly, which makes me feel very confused. The code below works well and prints 00 00 00 21 43 56 87 21 43 56 87 21 43 56 87 21 43 56 87 21 43 56 87 21 43

static const char *device = "/dev/spidev0.0";
static uint32_t mode = 0; /* CPOL=0,CPHA=0。 */
static uint8_t bits = 8; /* 8bits,MSB first。*/
static uint16_t delay = 0;
static uint32_t speed = 3*1000*1000;
static int g_SPI_Fd = 0;
int SPI_Open(void)
{
    int fd;
    int ret = 0;
    if (g_SPI_Fd != 0) /*  */
        return 0xF1;

    fd = open(device, O_RDWR);
    if (fd < 0)printf("can't open device\n");
    // else
    //     pr_debug("SPI - Open Succeed. Start Init SPI...\n");

    g_SPI_Fd = fd;
    /*
     * spi mode
     */

    ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
    if (ret == -1)printf("can't set spi mode\n");
    // mode |= SPI_CS_HIGH;
    ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
    if (ret == -1)printf("can't get spi mode\n");

    /*
     * bits per word
     */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)printf("can't set bits per word\n");

    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1)printf("can't get bits per word\n");

    /*
     * max speed hz
     */
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)printf("can't set max speed hz");

    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    if (ret == -1)printf("can't get max speed hz");

    return fd;
}

int SPI_Transfer(const uint8_t *TxBuf, uint8_t *RxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;

    struct spi_ioc_transfer tr ={
    .tx_buf = (unsigned long) TxBuf,
    .rx_buf = (unsigned long) RxBuf,
    .len =len,
    .delay_usecs = delay,
    };

    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
        printf("can't send spi message\n");
    return ret;
}

int main()
{
    int fd = SPI_Open();
    unsigned char rxbuf[256] = {0};
    while(1){
    usleep(1000);
    unsigned char txbuf[256] = {0x03,0x00,0x64,0,0,0,0,0};
    SPI_Transfer(txbuf,rxbuf,25);
    for(int i=0;i<25;i++){
        printf("%02X ",*(rxbuf+i));
    }
    printf("\n");
    }
    close(fd);
    return 0;
}

However, in SOES, it doesn't work:

void ESC_init (const esc_cfg_t * config)
{
   uint32_t value;
   // const char * spi_name = (char *)config->user_arg;
   lan9252 = SPI_Open ();
   // printf("9252: %d\n",lan9252);
   /* Reset the ecat core here due to evb-lan9252-digio not having any GPIO
    * for that purpose.
    */
   #ifdef debug
   {
      unsigned char rxbuf[256] = {0};
      while(1){
      usleep(1000);
         unsigned char txbuf[256] = {0x03,0x00,0x64,0,0,0,0,0};
      SPI_Transfer(txbuf,rxbuf,25);
      for(int i=0;i<25;i++){
         printf("%02X ",*(rxbuf+i));
      }
      printf("\n");
      }
      value = lan9252_read_32(0x64);
      printf("0x64: %08X\n", value);
   }
   #endif
   lan9252_write_32(ESC_RESET_CTRL_REG,ESC_RESET_CTRL_RST);
   do
   {
      value = lan9252_read_32(ESC_CSR_CMD_REG);
   } while(value & ESC_RESET_CTRL_RST);
}
nakarlsson commented 2 months ago

I guess it is HW related, the LAN9252 would not return -1. Any errno or anything that might give more info.

Also, make sure SPI is correct setup. Mode, speed and chip select.