diff --git a/Makefile b/Makefile index 28bcd6b..ff0facc 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ all: nrfprog CFLAGS=-ggdb -Wall +DEBUG := $(if $(DEBUG),-DDEBUG_PRINT) nrfprog: nrfprog.c bp.h nrf24le1.h - gcc ${CFLAGS} -o nrfprog nrfprog.c + gcc ${CFLAGS} -o nrfprog nrfprog.c $(DEBUG) clean: rm -f nrfprog diff --git a/README b/README deleted file mode 100644 index 2312891..0000000 --- a/README +++ /dev/null @@ -1,9 +0,0 @@ -This is a simple programmer for the nRF24LE1 using the Bus Pirate as the SPI -device. - -Type "make" to build the source. - -Running the program directly (./nrfprog) will dump the InfoPage. Put this some -where safe, as this contains information unique to your nRF24LE1. Running the -program, but passing a .hex file as a parameter will make the programmer write -the .hex file to the device. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e411a85 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# BusPirate NRF24LE1/NRF24LU1+ programmer +This is a simple programmer for the nRF24LE1 (or nRF24LU1p) using the Bus Pirate as the SPI +device. + +## building +``` +make clean +make +``` + +### debugging +for debug build, use: +``` +make clean +DEBUG=1 make +``` + +## usage +`nrfprog BUSPIRATE_PORT [filename]` + +Running the program directly (./nrfprog) will dump the InfoPage. Put this some +where safe, as this contains information unique to your nRF24LE1. Running the +program, but passing a existing .hex file as a parameter will make the programmer write +the .hex file to the device. If you pass in filename of non-existing file, nrfprog will attempt to read from chip into the file. + +## hardware + +| bus pirate | nrf 24 pin | nrf 32 pin | nrf 48 pin | +|--------------|------------|------------|------------| +| GND (brown) | GND | GND | GND | +| 3V3 (red) | PROG | PROG | PROG | +| AUX (blue) | RESET | RESET | RESET | +| CS (white) | P0.5 | P1.1 | P2.0 | +| MISO (black) | P0.4 | P1.0 | P1.6 | +| MOSI (grey) | P0.3 | P0.7 | P1.5 | +| CLK (purple) | P0.2 | P0.5 | P1.2 | + +## references + * bus pirate binary modes: http://dangerousprototypes.com/docs/SPI_%28binary%29 + * nrf24le1 datasheet: https://www.nordicsemi.com/kor/nordic/content_download/2443/29442/file/nRF24LE1_Product_Specification_rev1_6.pdf + diff --git a/bp.h b/bp.h index a0518d7..e2ae701 100644 --- a/bp.h +++ b/bp.h @@ -35,6 +35,7 @@ #define BP_SPI_CFG_CKE 0x02 #define BP_SPI_CFG_SMP 0x01 #define BP_SPI_WR_RD 0x04 + #define BP_SPI_WR_RD_NO_CS 0x05 #define BP_I2C 0x02 #define BP_UART 0x03 diff --git a/nrf24le1.h b/nrf24le1.h index d1edef1..cb124e8 100644 --- a/nrf24le1.h +++ b/nrf24le1.h @@ -2,9 +2,9 @@ #define __NRF24LE1_H_ -#define NRF24_BLOCK_SZ (512) -#define NRF24_FLASH_SZ (32*NRF24_BLOCK_SZ) -#define NRF24_INFO_SZ (256) +#define NRF24_PAGE_SZ (512) +#define NRF24_FLASH_SZ (32*NRF24_PAGE_SZ) +#define NRF24_INFO_SZ (512) #define NRF24_SPI_WRSR (0x01) #define NRF24_SPI_PROGRAM (0x02) diff --git a/nrfprog.c b/nrfprog.c index b5eaee2..c3e1a83 100644 --- a/nrfprog.c +++ b/nrfprog.c @@ -26,7 +26,9 @@ int ser_open(char *port) { TRACE_MSG; // Open the port - fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY); + //fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY); + fd = open(port, O_RDWR | O_NOCTTY); + if(fd == -1) { printf("Could not open the serial port: %s\n", port); exit(-1); @@ -56,6 +58,8 @@ int ser_open(char *port) { cfg.c_oflag &= ~OPOST; // Disable Software Flow Control cfg.c_iflag &= ~(IXON | IXOFF | IXANY); + //cfg.c_cc[VMIN] = 1; // read blocking + //cfg.c_cc[VTIME] = 1; // timeout // Send the config to the port tcsetattr(fd, TCSANOW, &cfg); return fd; @@ -72,12 +76,18 @@ void ser_write(int fd, uint8_t *stream, uint16_t sz) { int ret, ct; uint8_t c; TRACE_MSG; - + //tcdrain(fd); // Write out one byte at a time +#ifdef DEBUG_PRINT + printf("ser_write: "); +#endif for(ct=0; ct 25) { + if(err_ct > 20) { printf("Unable to read!\n"); break; } } #ifdef DEBUG_PRINT - printf("0x%02X ", buf[pos]); + printf("%02X ", buf[pos]); + if (pos % 16 == 15) { + printf("\n"); + } #endif } #ifdef DEBUG_PRINT @@ -392,19 +427,16 @@ void spi_wait(int fd, uint8_t *cmd, uint16_t len, char *resp_exp, uint16_t resp uint8_t bytes[3]; char *buf; TRACE_MSG; - buf = (char *)malloc(resp_len * sizeof(char)); for(ct = 0; ct < 25; ct++) { // Initiate the WR_RD operation ser_cmd(fd, BP_SPI_WR_RD); - // Send the read/write length and command bytes write_bytes = len; read_bytes = resp_len; s2b(write_bytes, bytes); ser_write(fd, (uint8_t *) bytes, 2); s2b(read_bytes, bytes); ser_write(fd, (uint8_t *) bytes, 2); - // Send the command ser_write(fd, cmd, len); @@ -415,7 +447,7 @@ void spi_wait(int fd, uint8_t *cmd, uint16_t len, char *resp_exp, uint16_t resp for(rd_ct=0; rd_ct < resp_len; rd_ct++) { err_ct = 0; while(read(fd, &(buf[rd_ct]), 1) != 1) { - usleep(1000); + usleep(400); err_ct++; if(err_ct > 25) { printf("Unable to read!\n"); @@ -438,7 +470,6 @@ void spi_write(int fd, uint8_t *buf, uint16_t len, int start_addr, char *err) { uint16_t write_bytes, read_bytes; uint8_t bytes[3]; TRACE_MSG; - // Set WREN to enable writing bytes[0] = NRF24_SPI_WREN; spi_cmd(fd, bytes, 1, "Enable Writing"); @@ -459,7 +490,8 @@ void spi_write(int fd, uint8_t *buf, uint16_t len, int start_addr, char *err) { s2b(start_addr, bytes); ser_write(fd, bytes, 2); ser_write(fd, buf, len); - check_resp(fd, "SPI Write"); + //usleep(60000); // wait for bp buffer + check_resp(fd, "spi_write"); // Check that we've completed the write command bytes[0] = NRF24_SPI_RDSR; @@ -491,13 +523,14 @@ void read_hex(int fd, int ip, char *fn) { spi_cmd(fd, cmd, 2, "FSR Register Write"); // Do the Read Operation + printf("starting read operation\n"); if(ip) read_bytes = NRF24_INFO_SZ; else read_bytes = NRF24_FLASH_SZ; - for(pos=0; pos < read_bytes; pos = pos + NRF24_BLOCK_SZ) - spi_read(fd, &(bytes[pos]), NRF24_BLOCK_SZ, pos, "Flash Read"); + for(pos=0; pos < read_bytes; pos = pos + NRF24_PAGE_SZ) + spi_read(fd, &(bytes[pos]), NRF24_PAGE_SZ, pos, "Flash Read"); // Open the output file fout = open(fn, O_RDWR | O_CREAT, 0666); @@ -536,32 +569,49 @@ int write_hex(int fd, char *fn) { cmd_bytes[1] = 0x00; spi_cmd(fd, cmd_bytes, 2, "Set INFEN"); - // Write the data by 1024 byte blocks - for(pos = 0; pos < sz; pos = pos + NRF24_BLOCK_SZ) { + // erase and write the data pages + printf(" erasing: "); + for(pos = 0; pos < sz; pos += NRF24_PAGE_SZ) { // Set WREN to enable writing cmd_bytes[0] = NRF24_SPI_WREN; spi_cmd(fd, cmd_bytes, 1, "Enable Writing"); // Next, we erase the block we're overwriting cmd_bytes[0] = NRF24_SPI_ERASE_PAGE; - cmd_bytes[1] = pos / NRF24_BLOCK_SZ; + cmd_bytes[1] = pos / NRF24_PAGE_SZ; spi_cmd(fd, cmd_bytes, 2, "Erase Page"); - + // Check that we've completed the erase command cmd_bytes[0] = NRF24_SPI_RDSR; result = 0; spi_wait(fd, cmd_bytes, 1, &result, 1, "Waiting for the erase to complete"); - // Write the data - spi_write(fd, &(data[pos]), NRF24_BLOCK_SZ, pos, "Writing to Flash"); + //spi_write(fd, &(data[pos]), NRF24_PAGE_SZ, pos, "Writing to Flash"); + printf(".."); fflush(stdout); + } - + printf("\n"); + //sleep(1); + // do write separately. nrf24lu1 can only handle max 256 bytes PROGRAM cmd, nrf24le1 can handle 1024 + printf(" writing: "); + for(pos = 0; pos < sz; pos += NRF24_PAGE_SZ/2) { + spi_write(fd, &(data[pos]), NRF24_PAGE_SZ/2, pos, "Writing to Flash"); + printf("."); fflush(stdout); + } + printf("\n"); // Read out the data + printf("Verifying flash.\n"); + printf(" reading: "); verify_data = (uint8_t *)calloc(sizeof(uint8_t), NRF24_FLASH_SZ); - for(pos=0; pos < sz; pos = pos + NRF24_BLOCK_SZ) { - spi_read(fd, &(verify_data[pos]), NRF24_BLOCK_SZ, pos, "Flash Read"); + for(pos=0; pos < sz; pos += NRF24_PAGE_SZ) { + if ((sz - pos) > NRF24_PAGE_SZ) + spi_read(fd, &(verify_data[pos]), NRF24_PAGE_SZ, pos, "Flash Read"); + else + spi_read(fd, &(verify_data[pos]), (sz - pos), pos, "Flash Read"); + printf(".."); fflush(stdout); } - + printf("\n"); + printf(" checking data...\n"); // Verfiy that the flash was performed correctly result = 0; for(pos = 0; pos < sz; pos++) { @@ -582,9 +632,16 @@ int write_hex(int fd, char *fn) { int main(int argc, char **argv) { int fd; TRACE_MSG; + if (argc < 2) { + printf("usage: nrfprog PORT [FILE]\n"); + exit(1); + } + + char *port = argv[1]; + char *fname = argv[2]; printf("Opening the Bus Pirate UART\n"); - fd = ser_open("/dev/ttyUSB0"); + fd = ser_open(port); printf("Setting the Bus Pirate to Binary Mode\n"); ser_bp_bin(fd); @@ -596,16 +653,16 @@ int main(int argc, char **argv) { read_hex(fd, 1, "info_page.dat"); // Read/Write the Hex File, if requested - if(argc > 1) { + if(argc > 2) { // If we can't open the file, we're reading out the memory contents into it - if(access(argv[1], R_OK)) { - printf("Reading from the device to %s\n", argv[1]); - read_hex(fd, 0, argv[1]); + if(access(fname, R_OK)) { + printf("Reading from the device to %s\n", fname); + read_hex(fd, 0, fname); // Otherwise, write it out } else { - printf("Writing %s to the device\n", argv[1]); - if(write_hex(fd, argv[1]) == 0) - printf("Write Verified\n"); + printf("Writing %s to the device\n", fname); + if(write_hex(fd, fname) == 0) + printf("Write Verified: OK\n"); } }