Пример #1
0
// Queue a character for transmission
void jshTransmit(IOEventFlags device, unsigned char data) {
#ifndef LINUX
#ifdef USB
  if (device==EV_USBSERIAL && !jshIsUSBSERIALConnected()) {
    jshTransmitClearDevice(EV_USBSERIAL); // clear out stuff already waiting
    return;
  }
#endif
  if (device==EV_NONE) return;
  unsigned char txHeadNext = (txHead+1)&TXBUFFERMASK;
  if (txHeadNext==txTail) {
    jsiSetBusy(BUSY_TRANSMIT, true);
    while (txHeadNext==txTail) {
      // wait for send to finish as buffer is about to overflow
#ifdef USB
      // just in case USB was unplugged while we were waiting!
      if (!jshIsUSBSERIALConnected()) jshTransmitClearDevice(EV_USBSERIAL);
#endif
    }
    jsiSetBusy(BUSY_TRANSMIT, false);
  }
  txBuffer[txHead].flags = device;
  txBuffer[txHead].data = (char)data;
  txHead = txHeadNext;

  jshUSARTKick(device); // set up interrupts if required

#else // if PC, just put to stdout
  if (device==DEFAULT_CONSOLE_DEVICE) {
    fputc(data, stdout);
    fflush(stdout);
  }
#endif
}
Пример #2
0
/**
 * Queue a character for transmission.
 */
void jshTransmit(
    IOEventFlags device, //!< The device to be used for transmission.
    unsigned char data   //!< The character to transmit.
  ) {
  if (device==EV_LOOPBACKA || device==EV_LOOPBACKB) {
    jshPushIOCharEvent(device==EV_LOOPBACKB ? EV_LOOPBACKA : EV_LOOPBACKB, (char)data);
    return;
  }
#ifndef LINUX
#ifdef USB
  if (device==EV_USBSERIAL && !jshIsUSBSERIALConnected()) {
    jshTransmitClearDevice(EV_USBSERIAL); // clear out stuff already waiting
    return;
  }
#endif
#else // if PC, just put to stdout
  if (device==DEFAULT_CONSOLE_DEVICE) {
    fputc(data, stdout);
    fflush(stdout);
    return;
  }
#endif
  // If the device is EV_NONE then there is nowhere to send the data.
  if (device==EV_NONE) return;

  // The txHead global points to the current item in the txBuffer.  Since we are adding a new
  // character, we increment the head pointer.   If it has caught up with the tail, then that means
  // we have filled the array backing the list.  What we do next is to wait for space to free up.
  unsigned char txHeadNext = (unsigned char)((txHead+1)&TXBUFFERMASK);
  if (txHeadNext==txTail) {
    jsiSetBusy(BUSY_TRANSMIT, true);
    bool wasConsoleLimbo = device==EV_LIMBO && jsiGetConsoleDevice()==EV_LIMBO;
    while (txHeadNext==txTail) {
      // wait for send to finish as buffer is about to overflow
#ifdef USB
      // just in case USB was unplugged while we were waiting!
      if (!jshIsUSBSERIALConnected()) jshTransmitClearDevice(EV_USBSERIAL);
#endif
    }
    if (wasConsoleLimbo && jsiGetConsoleDevice()!=EV_LIMBO) {
      /* It was 'Limbo', but now it's not - see jsiOneSecondAfterStartup.
      Basically we must have printed a bunch of stuff to LIMBO and blocked
      with our output buffer full. But then jsiOneSecondAfterStartup
      switches to the right console device and swaps everything we wrote
      over to that device too. Only we're now here, still writing to the
      old device when really we should be writing to the new one. */
      device = jsiGetConsoleDevice();
    }
    jsiSetBusy(BUSY_TRANSMIT, false);
  }
  // Save the device and data for the new character to be transmitted.
  txBuffer[txHead].flags = device;
  txBuffer[txHead].data = data;
  txHead = txHeadNext;

  jshUSARTKick(device); // set up interrupts if required
}
Пример #3
0
int main(void) {
  initHardware();
  int flashy = 0;
  BootloaderState state = BLS_UNDEFINED;
  char currentCommand = 0;

  while (1) {
    if (!jshIsUSBSERIALConnected()) {
      jshPinOutput(LED2_PININDEX, 0);
      // reset, led off
    } else {
      int f = (flashy>>9) & 0x7F;
      if (f&0x40) f=128-f;
      jshPinOutput(LED3_PININDEX, ((flashy++)&0xFF)<f);
      // flash led
      int d = getc();
      if (d>=0) { // if we have data
        if (state==BLS_EXPECT_DATA) {

        } else if (state==BLS_INITED) {
          currentCommand = d;
          state = BLS_COMMAND_FIRST_BYTE;
        } else if (state==BLS_COMMAND_FIRST_BYTE) {
          if (currentCommand == d^0xFF) {
            unsigned int addr,i;
            char chksum, buffer[256];
            unsigned int nBytesMinusOne, nPages;
            // confirmed
            switch (currentCommand) {
            case CMD_GET: // get bootloader info
              putc(ACK);
              putc(5); // 6 bytes
              // now report what we support
              putc(BOOTLOADER_MAJOR_VERSION<<4 | BOOTLOADER_MINOR_VERSION); // Bootloader version
              // list supported commands
              putc(CMD_GET);
              putc(CMD_GET_ID);
              putc(CMD_READ);
              putc(CMD_WRITE);
              putc(CMD_EXTERASE); // erase
              putc(ACK); // last byte
              break;
            case CMD_GET_ID: // get chip ID
              putc(ACK);
              putc(1); // 2 bytes
              // now report what we support
              putc(0x04);
              // 0x30 F1 XL density
              // 0x14 F1 high density
              putc(0x30); // TODO: really?
              putc(ACK); // last byte
              break;
            case CMD_READ: // read memory
              putc(ACK);
              addr = getc_blocking() << 24;
              addr |= getc_blocking()  << 16;
              addr |= getc_blocking()  << 8;
              addr |= getc_blocking();
              chksum = getc_blocking();
              // TODO: check checksum
              putc(ACK);
              setLEDs(2); // green = wait for data
              nBytesMinusOne = getc_blocking();
              chksum = getc_blocking();
              // TODO: check checksum
              putc(ACK);
              for (i=0;i<=nBytesMinusOne;i++)
                putc(((unsigned char*)addr)[i]);
              setLEDs(0); // off
              break;
            case CMD_WRITE: // write memory
              putc(ACK);
              addr = getc_blocking() << 24;
              addr |= getc_blocking()  << 16;
              addr |= getc_blocking()  << 8;
              addr |= getc_blocking();
              chksum = getc_blocking();
              // TODO: check checksum and address&3==0
              putc(ACK);
              setLEDs(2); // green = wait for data
              nBytesMinusOne = getc_blocking();
              for (i=0;i<=nBytesMinusOne;i++)
                buffer[i] = getc_blocking();
              chksum = getc_blocking();
              setLEDs(1); // red = write
              // TODO: check checksum and (nBytesMinusOne+1)&3==0
              FLASH_UnlockBank1();
              for (i=0;i<=nBytesMinusOne;i+=4) {
                unsigned int realaddr = addr+i;
                if (realaddr >= (FLASH_START+BOOTLOADER_SIZE)) // protect bootloader
                  FLASH_ProgramWord(realaddr, *(unsigned int*)&buffer[i]);
              }
              FLASH_LockBank1();
              setLEDs(0); // off
              putc(ACK); //  TODO - could speed up writes by ACKing beforehand if we have space
              break;
            case CMD_EXTERASE: // erase memory
              putc(ACK);
              nPages = getc_blocking() << 8;
              nPages |= getc_blocking();
              chksum = getc_blocking();
              // TODO: check checksum
              if (nPages == 0xFFFF) {
                // all pages (except us!)
                setLEDs(1); // red =  write
                FLASH_UnlockBank1();
                for (i=BOOTLOADER_SIZE;i<FLASH_TOTAL;i+=FLASH_PAGE_SIZE)
                  FLASH_ErasePage((uint32_t)(FLASH_START + i));
                FLASH_LockBank1();
                setLEDs(0); // off
                putc(ACK);
              } else {
                putc(NACK); // not implemented
              }
              break;
            default: // unknown command
              putc(NACK);
              break;
            }
          } else {
            // not correct
            putc(NACK);
          }
          state = BLS_INITED;
        } else {
          switch (d) {
          case 0x7F: // initialisation byte
                     putc(state == BLS_UNDEFINED ? ACK : NACK);
                     state = BLS_INITED;
                     break;
          }
        }
      }
    }
  }
}