Changeset 1541


Ignore:
Timestamp:
Jun 8, 2012 5:27:47 PM (13 months ago)
Author:
hailfinger
Message:

Bus Pirate buffer management revamp

The buffer management of the Bus Pirate driver has been revamped to use
grow-only buffers with a reasonable initial default size so realloc()
will not have to be called in normal operation. A side effect is the
ability to switch to a static buffer without major hassle.
Handle OOM gracefully.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@…>
Acked-by: Patrick Georgi <patrick@…>

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/buspirate_spi.c

    r1474 r1541  
    4040        /* 115200bps, 8 databits, no parity, 1 stopbit */ 
    4141        sp_fd = sp_openserport(dev, 115200); 
     42        /* FIXME: Error checking */ 
    4243        return 0; 
    4344} 
     
    4950#define sp_flush_incoming(...) 0 
    5051#endif 
     52 
     53static unsigned char *bp_commbuf = NULL; 
     54static int bp_commbufsize = 0; 
     55 
     56static int buspirate_commbuf_grow(int bufsize) 
     57{ 
     58        unsigned char *tmpbuf; 
     59 
     60        /* Never shrink. realloc() calls are expensive. */ 
     61        if (bufsize <= bp_commbufsize) 
     62                return 0; 
     63 
     64        tmpbuf = realloc(bp_commbuf, bufsize); 
     65        if (!tmpbuf) { 
     66                /* Keep the existing buffer because memory is already tight. */ 
     67                msg_perr("Out of memory!\n"); 
     68                return ERROR_OOM; 
     69        } 
     70 
     71        bp_commbuf = tmpbuf; 
     72        bp_commbufsize = bufsize; 
     73        return 0; 
     74} 
    5175 
    5276static int buspirate_sendrecv(unsigned char *buf, unsigned int writecnt, 
     
    117141static int buspirate_spi_shutdown(void *data) 
    118142{ 
    119         unsigned char buf[5]; 
    120         int ret = 0; 
     143        int ret = 0, ret2 = 0; 
     144        /* No need to allocate a buffer here, we know that bp_commbuf is at least DEFAULT_BUFSIZE big. */ 
    121145 
    122146        /* Exit raw SPI mode (enter raw bitbang mode) */ 
    123         buf[0] = 0x00; 
    124         ret = buspirate_sendrecv(buf, 1, 5); 
    125         if (ret) 
    126                 return ret; 
    127         if (memcmp(buf, "BBIO", 4)) { 
     147        bp_commbuf[0] = 0x00; 
     148        ret = buspirate_sendrecv(bp_commbuf, 1, 5); 
     149        if (ret) 
     150                goto out_shutdown; 
     151        if (memcmp(bp_commbuf, "BBIO", 4)) { 
    128152                msg_perr("Entering raw bitbang mode failed!\n"); 
    129                 return 1; 
    130         } 
    131         msg_pdbg("Raw bitbang mode version %c\n", buf[4]); 
    132         if (buf[4] != '1') { 
    133                 msg_perr("Can't handle raw bitbang mode version %c!\n", 
    134                         buf[4]); 
    135                 return 1; 
     153                ret = 1; 
     154                goto out_shutdown; 
     155        } 
     156        msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[4]); 
     157        if (bp_commbuf[4] != '1') { 
     158                msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[4]); 
     159                ret = 1; 
     160                goto out_shutdown; 
    136161        } 
    137162        /* Reset Bus Pirate (return to user terminal) */ 
    138         buf[0] = 0x0f; 
    139         ret = buspirate_sendrecv(buf, 1, 0); 
    140         if (ret) 
    141                 return ret; 
    142  
     163        bp_commbuf[0] = 0x0f; 
     164        ret = buspirate_sendrecv(bp_commbuf, 1, 0); 
     165 
     166out_shutdown: 
    143167        /* Shut down serial port communication */ 
    144         ret = serialport_shutdown(NULL); 
    145         if (ret) 
    146                 return ret; 
    147         msg_pdbg("Bus Pirate shutdown completed.\n"); 
    148  
    149         return 0; 
     168        ret2 = serialport_shutdown(NULL); 
     169        /* Keep the oldest error, it is probably the best indicator. */ 
     170        if (ret2 && !ret) 
     171                ret = ret2; 
     172        bp_commbufsize = 0; 
     173        free(bp_commbuf); 
     174        bp_commbuf = NULL; 
     175        if (ret) 
     176                msg_pdbg("Bus Pirate shutdown failed.\n"); 
     177        else 
     178                msg_pdbg("Bus Pirate shutdown completed.\n"); 
     179 
     180        return ret; 
    150181} 
    151182 
    152183int buspirate_spi_init(void) 
    153184{ 
    154         unsigned char buf[512]; 
    155185        char *dev = NULL; 
    156186        char *speed = NULL; 
     
    182212        msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed].name); 
    183213 
     214        /* Default buffer size is 19: 16 bytes data, 3 bytes control. */ 
     215#define DEFAULT_BUFSIZE (16 + 3) 
     216        bp_commbuf = malloc(DEFAULT_BUFSIZE); 
     217        if (!bp_commbuf) { 
     218                bp_commbufsize = 0; 
     219                msg_perr("Out of memory!\n"); 
     220                return ERROR_OOM; 
     221        } 
     222        bp_commbufsize = DEFAULT_BUFSIZE; 
     223 
    184224        ret = buspirate_serialport_setup(dev); 
    185         if (ret) 
    186                 return ret; 
    187225        free(dev); 
     226        if (ret) { 
     227                bp_commbufsize = 0; 
     228                free(bp_commbuf); 
     229                bp_commbuf = NULL; 
     230                return ret; 
     231        } 
    188232 
    189233        if (register_shutdown(buspirate_spi_shutdown, NULL)) 
     
    193237        for (i = 0; i < 19; i++) { 
    194238                /* Enter raw bitbang mode */ 
    195                 buf[0] = 0x00; 
     239                bp_commbuf[0] = 0x00; 
    196240                /* Send the command, don't read the response. */ 
    197                 ret = buspirate_sendrecv(buf, 1, 0); 
     241                ret = buspirate_sendrecv(bp_commbuf, 1, 0); 
    198242                if (ret) 
    199243                        return ret; 
     
    216260        } 
    217261        /* Enter raw bitbang mode */ 
    218         buf[0] = 0x00; 
    219         ret = buspirate_sendrecv(buf, 1, 5); 
    220         if (ret) 
    221                 return ret; 
    222         if (memcmp(buf, "BBIO", 4)) { 
     262        bp_commbuf[0] = 0x00; 
     263        ret = buspirate_sendrecv(bp_commbuf, 1, 5); 
     264        if (ret) 
     265                return ret; 
     266        if (memcmp(bp_commbuf, "BBIO", 4)) { 
    223267                msg_perr("Entering raw bitbang mode failed!\n"); 
    224268                msg_pdbg("Got %02x%02x%02x%02x%02x\n", 
    225                          buf[0], buf[1], buf[2], buf[3], buf[4]); 
    226                 return 1; 
    227         } 
    228         msg_pdbg("Raw bitbang mode version %c\n", buf[4]); 
    229         if (buf[4] != '1') { 
     269                         bp_commbuf[0], bp_commbuf[1], bp_commbuf[2], 
     270                         bp_commbuf[3], bp_commbuf[4]); 
     271                return 1; 
     272        } 
     273        msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[4]); 
     274        if (bp_commbuf[4] != '1') { 
    230275                msg_perr("Can't handle raw bitbang mode version %c!\n", 
    231                         buf[4]); 
     276                        bp_commbuf[4]); 
    232277                return 1; 
    233278        } 
    234279        /* Enter raw SPI mode */ 
    235         buf[0] = 0x01; 
    236         ret = buspirate_sendrecv(buf, 1, 4); 
    237         if (ret) 
    238                 return ret; 
    239         if (memcmp(buf, "SPI", 3)) { 
     280        bp_commbuf[0] = 0x01; 
     281        ret = buspirate_sendrecv(bp_commbuf, 1, 4); 
     282        if (ret) 
     283                return ret; 
     284        if (memcmp(bp_commbuf, "SPI", 3)) { 
    240285                msg_perr("Entering raw SPI mode failed!\n"); 
    241286                msg_pdbg("Got %02x%02x%02x%02x\n", 
    242                          buf[0], buf[1], buf[2], buf[3]); 
    243                 return 1; 
    244         } 
    245         msg_pdbg("Raw SPI mode version %c\n", buf[3]); 
    246         if (buf[3] != '1') { 
     287                         bp_commbuf[0], bp_commbuf[1], bp_commbuf[2], 
     288                         bp_commbuf[3]); 
     289                return 1; 
     290        } 
     291        msg_pdbg("Raw SPI mode version %c\n", bp_commbuf[3]); 
     292        if (bp_commbuf[3] != '1') { 
    247293                msg_perr("Can't handle raw SPI mode version %c!\n", 
    248                         buf[3]); 
     294                        bp_commbuf[3]); 
    249295                return 1; 
    250296        } 
    251297 
    252298        /* Initial setup (SPI peripherals config): Enable power, CS high, AUX */ 
    253         buf[0] = 0x40 | 0xb; 
    254         ret = buspirate_sendrecv(buf, 1, 1); 
    255         if (ret) 
    256                 return 1; 
    257         if (buf[0] != 0x01) { 
     299        bp_commbuf[0] = 0x40 | 0xb; 
     300        ret = buspirate_sendrecv(bp_commbuf, 1, 1); 
     301        if (ret) 
     302                return 1; 
     303        if (bp_commbuf[0] != 0x01) { 
    258304                msg_perr("Protocol error while setting power/CS/AUX!\n"); 
    259305                return 1; 
     
    261307 
    262308        /* Set SPI speed */ 
    263         buf[0] = 0x60 | spispeed; 
    264         ret = buspirate_sendrecv(buf, 1, 1); 
    265         if (ret) 
    266                 return 1; 
    267         if (buf[0] != 0x01) { 
     309        bp_commbuf[0] = 0x60 | spispeed; 
     310        ret = buspirate_sendrecv(bp_commbuf, 1, 1); 
     311        if (ret) 
     312                return 1; 
     313        if (bp_commbuf[0] != 0x01) { 
    268314                msg_perr("Protocol error while setting SPI speed!\n"); 
    269315                return 1; 
     
    271317         
    272318        /* Set SPI config: output type, idle, clock edge, sample */ 
    273         buf[0] = 0x80 | 0xa; 
    274         ret = buspirate_sendrecv(buf, 1, 1); 
    275         if (ret) 
    276                 return 1; 
    277         if (buf[0] != 0x01) { 
     319        bp_commbuf[0] = 0x80 | 0xa; 
     320        ret = buspirate_sendrecv(bp_commbuf, 1, 1); 
     321        if (ret) 
     322                return 1; 
     323        if (bp_commbuf[0] != 0x01) { 
    278324                msg_perr("Protocol error while setting SPI config!\n"); 
    279325                return 1; 
     
    281327 
    282328        /* De-assert CS# */ 
    283         buf[0] = 0x03; 
    284         ret = buspirate_sendrecv(buf, 1, 1); 
    285         if (ret) 
    286                 return 1; 
    287         if (buf[0] != 0x01) { 
     329        bp_commbuf[0] = 0x03; 
     330        ret = buspirate_sendrecv(bp_commbuf, 1, 1); 
     331        if (ret) 
     332                return 1; 
     333        if (bp_commbuf[0] != 0x01) { 
    288334                msg_perr("Protocol error while raising CS#!\n"); 
    289335                return 1; 
     
    301347                                      unsigned char *readarr) 
    302348{ 
    303         static unsigned char *buf = NULL; 
    304349        unsigned int i = 0; 
    305350        int ret = 0; 
     
    309354 
    310355        /* 3 bytes extra for CS#, len, CS#. */ 
    311         buf = realloc(buf, writecnt + readcnt + 3); 
    312         if (!buf) { 
    313                 msg_perr("Out of memory!\n"); 
    314                 exit(1); // -1 
    315         } 
     356        if (buspirate_commbuf_grow(writecnt + readcnt + 3)) 
     357                return ERROR_OOM; 
    316358 
    317359        /* Assert CS# */ 
    318         buf[i++] = 0x02; 
    319  
    320         buf[i++] = 0x10 | (writecnt + readcnt - 1); 
    321         memcpy(buf + i, writearr, writecnt); 
     360        bp_commbuf[i++] = 0x02; 
     361 
     362        bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1); 
     363        memcpy(bp_commbuf + i, writearr, writecnt); 
    322364        i += writecnt; 
    323         memset(buf + i, 0, readcnt); 
     365        memset(bp_commbuf + i, 0, readcnt); 
    324366 
    325367        i += readcnt; 
    326368        /* De-assert CS# */ 
    327         buf[i++] = 0x03; 
    328  
    329         ret = buspirate_sendrecv(buf, i, i); 
     369        bp_commbuf[i++] = 0x03; 
     370 
     371        ret = buspirate_sendrecv(bp_commbuf, i, i); 
    330372 
    331373        if (ret) { 
     
    334376        } 
    335377 
    336         if (buf[0] != 0x01) { 
     378        if (bp_commbuf[0] != 0x01) { 
    337379                msg_perr("Protocol error while lowering CS#!\n"); 
    338380                return SPI_GENERIC_ERROR; 
    339381        } 
    340382 
    341         if (buf[1] != 0x01) { 
     383        if (bp_commbuf[1] != 0x01) { 
    342384                msg_perr("Protocol error while reading/writing SPI!\n"); 
    343385                return SPI_GENERIC_ERROR; 
    344386        } 
    345387 
    346         if (buf[i - 1] != 0x01) { 
     388        if (bp_commbuf[i - 1] != 0x01) { 
    347389                msg_perr("Protocol error while raising CS#!\n"); 
    348390                return SPI_GENERIC_ERROR; 
     
    350392 
    351393        /* Skip CS#, length, writearr. */ 
    352         memcpy(readarr, buf + 2 + writecnt, readcnt); 
     394        memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt); 
    353395 
    354396        return ret; 
  • trunk/flash.h

    r1540 r1541  
    3737 
    3838/* Error codes */ 
     39#define ERROR_OOM       -100 
    3940#define TIMEOUT_ERROR   -101 
    4041 
Note: See TracChangeset for help on using the changeset viewer.