#include "driver.h" #include #include #include #include "com_gpio.h" #include "hal_interface_api.h" #include "linux/fcntl.h" #include "time.h" #include #define DEV_NAME "/dev/spi" /* bus: 1,2,3,4,5,6 */ int stm32_spi_master_write(uint8_t spi, uint8_t *pBuf, uint32_t size) { int fd; int ret; uint8_t dev_name[10] = {0}; spi_arg_t spi_arg; // GPIO_TypeDef *NSS_PORT = NULL; // uint16_t NSS_PIN = 0; switch(spi) { case 1: break; case 2: // NSS_PORT = GPIOI; // NSS_PIN = GPIO_PIN_0; break; case 3: break; case 4: break; case 5: // NSS_PORT = GPIOF; // NSS_PIN = GPIO_PIN_6; break; case 6: break; default: printf("Invalid bus number %d\n", spi); return -1; } sprintf(dev_name, "%s%d", DEV_NAME, spi); fd = open(dev_name, O_RDWR); if(fd == -1) { printf("Open %s failed!\n", dev_name); } // //NSS low // stm32_gpio_write(GPIOF, GPIO_PIN_6, GPIO_PIN_RESET); // usleep(1000); spi_arg.Size = size; memcpy(spi_arg.buf, pBuf, size); ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); if(ret == -1) { printf("Write spi failed!\n"); } // //NSS high // stm32_gpio_write(GPIOF, GPIO_PIN_6, GPIO_PIN_SET); close(fd); return 0; } int stm32_spi_master_read(uint8_t spi, uint8_t *pBuf, uint32_t size) { int fd; int ret; uint8_t dev_name[10] = {0}; spi_arg_t spi_arg; // GPIO_TypeDef *NSS_PORT = NULL; // uint16_t NSS_PIN = 0; switch(spi) { case 1: break; case 2: // NSS_PORT = GPIOI; // NSS_PIN = GPIO_PIN_0; break; case 3: break; case 4: break; case 5: // NSS_PORT = GPIOF; // NSS_PIN = GPIO_PIN_6; break; case 6: break; default: printf("Invalid bus number %d\n", spi); return -1; } sprintf(dev_name, "%s%d", DEV_NAME, spi); fd = open(dev_name, O_RDWR); if(fd == -1) { printf("Open %s failed!\n", DEV_NAME); } spi_arg.Size = size; ret = ioctl(fd, SPI_MASTER_RECEIVE, &spi_arg); if(ret == -1) { printf("Read spi failed!\n"); } memcpy(pBuf, spi_arg.buf, size); close(fd); return 0; } int stm32_spi_master_write_read(uint8_t spi, uint8_t *txBuf, uint32_t txSize, uint8_t *rxBuf, uint32_t rxSize) { int fd; int ret; uint8_t dev_name[10] = {0}; spi_arg_t spi_arg; // GPIO_TypeDef *NSS_PORT = NULL; // uint16_t NSS_PIN = 0; switch(spi) { case 1: break; case 2: // NSS_PORT = GPIOI; // NSS_PIN = GPIO_PIN_0; break; case 3: break; case 4: break; case 5: // NSS_PORT = GPIOF; // NSS_PIN = GPIO_PIN_6; break; case 6: break; default: printf("Invalid bus number %d\n", spi); return -1; } sprintf(dev_name, "%s%d", DEV_NAME, spi); fd = open(dev_name, O_RDWR); if(fd == -1) { printf("Open %s failed!\n", DEV_NAME); } //Tx if(txSize > 0) { spi_arg.Size = txSize; memcpy(spi_arg.buf, txBuf, txSize); ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); if(ret == -1) { printf("Read spi failed!\n"); } } //Rx if(rxSize > 0) { spi_arg.Size = rxSize; memset(spi_arg.buf, 0, rxSize); ret = ioctl(fd, SPI_MASTER_RECEIVE, &spi_arg); if(ret == -1) { printf("Read spi failed!\n"); } memcpy(rxBuf, spi_arg.buf, rxSize); } close(fd); return 0; } /* timeout: ms */ static int sf_wait_spi_ready(int fd, uint32_t timeout) { spi_arg_t spi_arg; int ret = 0; uint32_t timeCnt = 0; spi_arg.Size = 1; spi_arg.buf[0] = 0x05; ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); if(ret == -1) { printf("SPI Read status1 failed!\n"); return -1; } timeCnt = 0; do{ timeCnt++; spi_arg.Size = 1; ret = ioctl(fd, SPI_MASTER_RECEIVE, &spi_arg); if(ret == -1) { printf("SPI Read status1 failed!\n"); } if(spi_arg.buf[0]&0x01) usleep(10); else break; }while(timeCnt < timeout*100); //NSS high //stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); } /* flash: fw flash, spi5 cmd: erase 4 KB */ int sf_sector_erase(uint8_t spi, uint32_t offset) { int fd; int ret; uint8_t dev_name[10] = {0}; spi_arg_t spi_arg; uint32_t erase_addr = 0; uint8_t status1_reg; uint32_t timeout = 0; GPIO_TypeDef *NSS_PORT = NULL; uint16_t NSS_PIN = 0; //erase_addr is the start address of one sector. erase_addr = (offset/4096)*4096; switch(spi) { case 1: break; case 2: NSS_PORT = GPIOI; NSS_PIN = GPIO_PIN_0; break; case 3: break; case 4: break; case 5: NSS_PORT = GPIOF; NSS_PIN = GPIO_PIN_6; break; case 6: break; default: printf("Invalid bus number %d\n", spi); return -1; } sprintf(dev_name, "%s%d", DEV_NAME, spi); fd = open(dev_name, O_RDWR); if(fd == -1) { printf("Open %s failed!\n", dev_name); } //Write Enable spi_arg.Size = 1; spi_arg.buf[0] = 0x06; stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high if(ret == -1) { printf("SPI Write Enable failed!\n"); return -1; } //Sector Erase spi_arg.Size = 4; spi_arg.buf[0] = 0x20; spi_arg.buf[1] = (erase_addr>>16)&0xff; spi_arg.buf[2] = (erase_addr>>8)&0xff; spi_arg.buf[3] = erase_addr&0xff; stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high if(ret == -1) { printf("SPI sector erase failed!\n"); return -1; } usleep(30000); //30ms stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low sf_wait_spi_ready(fd, 400); //400ms stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high close(fd); return 0; } int sf_get_id(uint8_t spi, uint8_t *id) { int fd; spi_arg_t args; uint8_t dev_name[10] = {0}; int i; GPIO_TypeDef *NSS_PORT = NULL; uint16_t NSS_PIN = 0; switch(spi) { case 1: break; case 2: NSS_PORT = GPIOI; NSS_PIN = GPIO_PIN_0; break; case 3: break; case 4: break; case 5: NSS_PORT = GPIOF; NSS_PIN = GPIO_PIN_6; break; case 6: break; default: printf("Invalid bus number %d\n", spi); return -1; } sprintf(dev_name, "%s%d", DEV_NAME, spi); fd = open(dev_name, O_RDWR); if(fd < 0) printf("open failed\n"); memset(args.buf, 0, 100); args.buf[0] = 0x9f; args.Size = 1; stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ioctl(fd, SPI_MASTER_TRANSFER, &args); args.Size = 3; ioctl(fd, SPI_MASTER_RECEIVE, &args); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high memcpy(id, args.buf, args.Size); //printf("get id: %#x %#x %#x\n", id[0], id[1], id[2]); close(fd); } /* spi: 1,2,3,4,5,6 PageSize = 256 bytes. Address must be the start of one page. */ int sf_write(uint8_t spi, uint32_t offset, uint8_t *buf, uint32_t size) { int fd; int ret; spi_arg_t spi_arg; uint8_t dev_name[10] = {0}; uint8_t status1_reg; uint32_t timeout = 0; uint32_t remain = 0, writeLen = 0; uint32_t writeAddr = 0; GPIO_TypeDef *NSS_PORT = NULL; uint16_t NSS_PIN = 0; //erase_addr is the start address of one sector. if(offset&0xff) { printf("The Address %#x is not a pages start!\n", offset); return -1; } switch(spi) { case 1: break; case 2: NSS_PORT = GPIOI; NSS_PIN = GPIO_PIN_0; break; case 3: break; case 4: break; case 5: NSS_PORT = GPIOF; NSS_PIN = GPIO_PIN_6; break; case 6: break; default: printf("Invalid bus number %d\n", spi); return -1; } sprintf(dev_name, "%s%d", DEV_NAME, spi); fd = open(dev_name, O_RDWR); if(fd == -1) { printf("Open %s failed!\n", dev_name); } //usleep(1000); remain = size; writeLen = 0; writeAddr = offset; while(remain > 256) { //Write Enable spi_arg.Size = 1; spi_arg.buf[0] = 0x06; stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high if(ret == -1) { printf("SPI Write Enable failed!\n"); return -1; } //Page Write spi_arg.Size = 260; spi_arg.buf[0] = 0x02; //page write spi_arg.buf[1] = (writeAddr>>16)&0xff; spi_arg.buf[2] = (writeAddr>>8)&0xff; spi_arg.buf[3] = writeAddr&0xff; memcpy(&spi_arg.buf[4], &buf[writeLen], 256); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high if(ret == -1) { printf("SPI Read status1 failed!\n"); return -1; } //wait page write finish usleep(700); //700us stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low if(0 != sf_wait_spi_ready(fd, 3)) //3ms printf("Warnning page write timeout!\n"); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high remain -= 256; writeLen += 256; writeAddr += 256; } if(remain > 0) { //Write Enable spi_arg.Size = 1; spi_arg.buf[0] = 0x06; stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high if(ret == -1) { printf("SPI Write Enable failed!\n"); return -1; } //page write spi_arg.Size = remain + 4; spi_arg.buf[0] = 0x02; //page write spi_arg.buf[1] = (writeAddr>>16)&0xff; spi_arg.buf[2] = (writeAddr>>8)&0xff; spi_arg.buf[3] = writeAddr&0xff; memcpy(&spi_arg.buf[4], &buf[writeLen], remain); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high if(ret == -1) { printf("SPI Read status1 failed!\n"); return -1; } //wait page write finish usleep(700); //700us stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low if(0 != sf_wait_spi_ready(fd, 3)) //3ms printf("Warnning page write timeout!\n"); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high writeLen += remain; writeAddr += remain; remain -= remain; } close(fd); return 0; } /* spi: 1,2,3,4,5 PageSize = 256 bytes. Address must be the start of one page. */ int sf_read(uint8_t spi, uint32_t offset, uint8_t *buf, uint32_t size) { int fd; int ret; spi_arg_t spi_arg; uint8_t dev_name[10] = {0}; uint8_t status1_reg; uint32_t timeout = 0; uint32_t remain = 0, readLen = 0; uint32_t readAddr; GPIO_TypeDef *NSS_PORT = NULL; uint16_t NSS_PIN = 0; //erase_addr is the start address of one sector. if(offset&0xff) { printf("The Address %#x is not a pages start!\n", offset); return -1; } switch(spi) { case 1: break; case 2: NSS_PORT = GPIOI; NSS_PIN = GPIO_PIN_0; break; case 3: break; case 4: break; case 5: NSS_PORT = GPIOF; NSS_PIN = GPIO_PIN_6; break; case 6: break; default: printf("Invalid bus number %d\n", spi); return -1; } sprintf(dev_name, "%s%d", DEV_NAME, spi); fd = open(dev_name, O_RDWR); if(fd == -1) { printf("Open %s failed!\n", dev_name); } remain = size; readLen = 0; readAddr = offset; while(remain > 256) { spi_arg.Size = 5; spi_arg.buf[0] = 0x0B; //fast read spi_arg.buf[1] = (readAddr>>16)&0xff; spi_arg.buf[2] = (readAddr>>8)&0xff; spi_arg.buf[3] = readAddr&0xff; spi_arg.buf[4] = 0; //dummy stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); if(ret == -1) { printf("SPI Fast Read command failed!\n"); return -1; } spi_arg.Size = 256; ret = ioctl(fd, SPI_MASTER_RECEIVE, &spi_arg); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high if(ret == -1) { printf("SPI fast Read failed!\n"); return -1; } memcpy(&buf[readLen], spi_arg.buf, 256); remain -= 256; readLen += 256; readAddr += 256; } if(remain > 0) { spi_arg.Size = 5; spi_arg.buf[0] = 0x0B; //fast read spi_arg.buf[1] = (readAddr>>16)&0xff; spi_arg.buf[2] = (readAddr>>8)&0xff; spi_arg.buf[3] = readAddr&0xff; spi_arg.buf[4] = 0; //dummy stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_RESET); //NSS low ret = ioctl(fd, SPI_MASTER_TRANSFER, &spi_arg); if(ret == -1) { printf("SPI Fast Read command failed!\n"); return -1; } spi_arg.Size = remain; ret = ioctl(fd, SPI_MASTER_RECEIVE, &spi_arg); stm32_gpio_write(NSS_PORT, NSS_PIN, GPIO_PIN_SET); //NSS high if(ret == -1) { printf("SPI fast Read failed!\n"); return -1; } memcpy(&buf[readLen], spi_arg.buf, remain); readLen += remain; readAddr += remain; remain -= remain; } close(fd); return 0; }