예제 #1
0
static THD_FUNCTION(spi_thread, p) {
  unsigned i;
  SPIDriver *spip = (SPIDriver *)p;
  virtual_timer_t vt;
  uint8_t txbuf[256];
  uint8_t rxbuf[256];

  chRegSetThreadName("SPI overlord");

  chVTObjectInit(&vt);

  /* Prepare transmit pattern.*/
  for (i = 0; i < sizeof(txbuf); i++)
    txbuf[i] = (uint8_t)i;

  /* Continuous transmission.*/
  while (true) {
    /* Starts a VT working as watchdog to catch a malfunction in the SPI
       driver.*/
    chVTSet(&vt, MS2ST(10), tmo, (void *)"SPI timeout");

    spiExchange(spip, sizeof(txbuf), txbuf, rxbuf);

    /* Stops the watchdog.*/
    chVTReset(&vt);
  }
}
예제 #2
0
/**
 * @brief   Create a timer.
 */
osTimerId osTimerCreate(const osTimerDef_t *timer_def,
                        os_timer_type type,
                        void *argument) {

  osTimerId timer = chPoolAlloc(&timpool);
  chVTObjectInit(&timer->vt);
  timer->ptimer = timer_def->ptimer;
  timer->type = type;
  timer->argument = argument;
  return timer;
}
예제 #3
0
/**
 * @brief   Initializes a generic teensy HID debug driver object.
 * @details The HW dependent part of the initialization has to be performed
 *          outside, usually in the hardware initialization code.
 *
 * @param[out] hiddp     pointer to a @p HIDDebugDriver structure
 *
 * @init
 */
void hidDebugObjectInit(HIDDebugDriver *hiddp) {
  hiddp->vmt = &vmt;
  osalEventObjectInit(&hiddp->event);
  hiddp->state = HIDDEBUG_STOP;
  /* TODO: how to make sure the queue is non-existent? */
  /* hiddp->iqueue = (input_queue_t)NULL; */
  hiddp->ib = (uint8_t *)NULL;
  oqObjectInit(&hiddp->oqueue, hiddp->ob, HID_DEBUG_OUTPUT_BUFFER_SIZE, onotify, hiddp);

  /* create the flush timer here as well (TODO: need to clean up/integrate!) */
  chVTObjectInit(&hid_debug_flush_timer);
}
예제 #4
0
/**
 * @brief                   Initializes the sensor read functionallity.
 * 
 * @param[in] srdp          Pointer to the SensorReadDriver object.
 * @param[in] intsenp       Pointer to the interrupt sensor read configuration.
 * @param[in] pollsenp      Pointer to the polled sensor read configuration.
 * @param[in] intsencnt     Number of interrupt driven sensors.
 * @param[in] pollsencnt    Number of polled driven sensors.
 * 
 * @return                  The operation status.
 * @retval MSG_OK           The initialization was successful.
 * @retval MSG_RESET        Something went wrong during the initialization.
 * 
 * @api
 */
msg_t SensorReadInit(SensorReadDriver *srdp,
                     const interrupt_sensor_t *intsenp,
                     const polled_sensor_t *pollsenp,
                     size_t intsencnt,
                     size_t pollsencnt)
{
    chDbgCheck(srdp != NULL);
    chDbgCheck(srdp->state == SRD_UNINITIALIZED);
    chDbgAssert((intsenp == NULL) && (intsencnt != 0),
                "Pointer can't be NULL when the count is > 0");
    chDbgAssert((pollsenp == NULL) && (pollsencnt != 0),
                "Pointer can't be NULL when the count is > 0");
    
    size_t i;
    msg_t retval;

    /* Clear the lookup table */
    for (i = 0; i < EXT_MAX_CHANNELS; i++)
        srdp->expchannel_lookup[i] = -1;

    /* Generate interrupt channel -> array index table */
    for (i = 0; i < intsencnt; i++)
        srdp->expchannel_lookup[intsenp[i].interrupt_channel] = i;

    /* Copy sensor pointers and sizes to driver structures */
    srdp->interrupt_sensor_ptr = intsenp;
    srdp->interrupt_sensor_cnt = intsencnt;
    srdp->polled_sensor_ptr = pollsenp;
    srdp->polled_sensor_cnt = pollsencnt;

    /* Run interrupt sensor initialization */
    for (i = 0; i < intsencnt; i++)
    {
        /* Run sensor initialization with requested params */
        if (intsenp[i].sensor.init_sensor != NULL)
            retval = intsenp[i].sensor.init_sensor(intsenp[i].sensor.params);
        else
            retval = MSG_RESET;

        if (retval != MSG_OK)
            return retval;
    }

    /* Run polled sensor initialization */
    for (i = 0; i < pollsencnt; i++)
    {
        /* Check so the requested rate is plausible */
        if (CH_CFG_ST_FREQUENCY / pollsenp[i].frequency_hz == 0)
            return MSG_TIMEOUT;

        /* Zero the accumulated ticks */
        if (pollsenp[i].accumulator != NULL)
            *(pollsenp[i].accumulator) = 0;

        /* Run sensor initialization with requested params */
        if (pollsenp[i].sensor.init_sensor != NULL)
            retval = pollsenp[i].sensor.init_sensor(pollsenp[i].sensor.params);
        else
            retval = MSG_RESET;

        if (retval != MSG_OK)
            return retval;
        else /* Initialization is OK, initialize the virtual timer */
            chVTObjectInit(pollsenp[i].polling_vt);
    }

    /* Everything OK, transverse the state and start the read thread */
    srdp->state = SRD_STOPPED;

    chThdCreateStatic(waThreadSRD1,
                      sizeof(waThreadSRD1), 
                      SRD_THREAD_PRIORITY, 
                      ThreadSRD1, 
                      srdp);

    return MSG_OK;
}
예제 #5
0
/**
 * @brief Initializes an @p event_timer_t structure.
 *
 * @param[out] etp      the @p event_timer_t structure to be initialized
 * @param[in] time      the interval in system ticks
 */
void evtObjectInit(event_timer_t *etp, systime_t time) {

  chEvtObjectInit(&etp->et_es);
  chVTObjectInit(&etp->et_vt);
  etp->et_interval = time;
}
예제 #6
0
/*
 * Application entry point.
 */
int main(void) {
  unsigned i;
  static uint8_t patterns1[4096], patterns2[4096], buf1[4096], buf2[4096];

  /* System initializations.
     - HAL initialization, this also initializes the configured device drivers
       and performs the board-specific initializations.
     - Kernel initialization, the main() function becomes a thread and the
       RTOS is active.*/
  halInit();
  chSysInit();

  /* Creates the blinker thread.*/
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 10,
                    Thread1, NULL);

  /* Activates the ADC1 driver and the temperature sensor.*/
  adcStart(&ADCD1, NULL);
  adcSTM32EnableTSVREFE();

  /* Starts an ADC continuous conversion and its watchdog virtual timer.*/
  chVTSet(&adcvt, MS2ST(10), tmo, (void *)"ADC timeout");
  adcStartConversion(&ADCD1, &adcgrpcfg2, samples2, ADC_GRP2_BUF_DEPTH);

  /* Activating SPI drivers.*/
  spiStart(&SPID1, &hs_spicfg);
  spiStart(&SPID2, &hs_spicfg);
  spiStart(&SPID3, &hs_spicfg);

  /* Starting SPI threads instances.*/
  chThdCreateStatic(waSPI1, sizeof(waSPI1), NORMALPRIO + 1, spi_thread, &SPID1);
  chThdCreateStatic(waSPI2, sizeof(waSPI2), NORMALPRIO + 1, spi_thread, &SPID2);
  chThdCreateStatic(waSPI3, sizeof(waSPI3), NORMALPRIO + 1, spi_thread, &SPID3);

  /* Allocating two DMA2 streams for memory copy operations.*/
  if (dmaStreamAllocate(STM32_DMA2_STREAM6, 0, NULL, NULL))
    chSysHalt("DMA already in use");
  if (dmaStreamAllocate(STM32_DMA2_STREAM7, 0, NULL, NULL))
    chSysHalt("DMA already in use");
  for (i = 0; i < sizeof (patterns1); i++)
    patterns1[i] = (uint8_t)i;
  for (i = 0; i < sizeof (patterns2); i++)
    patterns2[i] = (uint8_t)(i ^ 0xAA);

  /* Normal main() thread activity, it does continues memory copy operations
     using 2 DMA streams at the lowest priority.*/
  while (true) {
    virtual_timer_t vt;

    chVTObjectInit(&vt);

    /* Starts a VT working as watchdog to catch a malfunction in the DMA
       driver.*/
    chVTSet(&vt, MS2ST(10), tmo, (void *)"copy timeout");

    /* Copy pattern 1.*/
    dmaStartMemCopy(STM32_DMA2_STREAM6,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_BYTE |
                                         STM32_DMA_CR_MSIZE_BYTE,
                    patterns1, buf1, sizeof (patterns1));
    dmaStartMemCopy(STM32_DMA2_STREAM7,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_BYTE |
                                         STM32_DMA_CR_MSIZE_BYTE,
                    patterns1, buf2, sizeof (patterns1));
    dmaWaitCompletion(STM32_DMA2_STREAM6);
    dmaWaitCompletion(STM32_DMA2_STREAM7);
    if (memcmp(patterns1, buf1, sizeof (patterns1)))
      chSysHalt("pattern error");
    if (memcmp(patterns1, buf2, sizeof (patterns1)))
      chSysHalt("pattern error");

    /* Copy pattern 2.*/
    dmaStartMemCopy(STM32_DMA2_STREAM6,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_BYTE |
                                         STM32_DMA_CR_MSIZE_BYTE,
                    patterns2, buf1, sizeof (patterns2));
    dmaStartMemCopy(STM32_DMA2_STREAM7,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_BYTE |
                                         STM32_DMA_CR_MSIZE_BYTE,
                    patterns2, buf2, sizeof (patterns2));
    dmaWaitCompletion(STM32_DMA2_STREAM6);
    dmaWaitCompletion(STM32_DMA2_STREAM7);
    if (memcmp(patterns2, buf1, sizeof (patterns2)))
      chSysHalt("pattern error");
    if (memcmp(patterns2, buf2, sizeof (patterns2)))
      chSysHalt("pattern error");

    /* Stops the watchdog.*/
    chVTReset(&vt);

    chThdSleepMilliseconds(2);
  }
  return 0;
}
예제 #7
0
/* Callback for SETUP request on the endpoint 0 (control) */
static bool usb_request_hook_cb(USBDriver *usbp) {
  const USBDescriptor *dp;

  /* usbp->setup fields:
   *  0:   bmRequestType (bitmask)
   *  1:   bRequest
   *  2,3: (LSB,MSB) wValue
   *  4,5: (LSB,MSB) wIndex
   *  6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */

  /* Handle HID class specific requests */
  if(((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
     ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
    switch(usbp->setup[0] & USB_RTYPE_DIR_MASK) {
    case USB_RTYPE_DIR_DEV2HOST:
      switch(usbp->setup[1]) {   /* bRequest */
      case HID_GET_REPORT:
        switch(usbp->setup[4]) {     /* LSB(wIndex) (check MSB==0?) */
        case KEYBOARD_INTERFACE:
#ifdef NKRO_ENABLE
        case NKRO_INTERFACE:
#endif /* NKRO_ENABLE */
          usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
          return TRUE;
          break;

#ifdef MOUSE_ENABLE
        case MOUSE_INTERFACE:
          usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
          return TRUE;
          break;
#endif /* MOUSE_ENABLE */

#ifdef EXTRAKEY_ENABLE
        case EXTRAKEY_INTERFACE:
          if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
            switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
              case REPORT_ID_SYSTEM:
                extra_report_blank[0] = REPORT_ID_SYSTEM;
                usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
                return TRUE;
                break;
              case REPORT_ID_CONSUMER:
                extra_report_blank[0] = REPORT_ID_CONSUMER;
                usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
                return TRUE;
                break;
              default:
                return FALSE;
            }
          } else {
            return FALSE;
          }
          break;
#endif /* EXTRAKEY_ENABLE */

        default:
          usbSetupTransfer(usbp, NULL, 0, NULL);
          return TRUE;
          break;
        }
        break;

      case HID_GET_PROTOCOL:
        if((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) {   /* wIndex */
          usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
          return TRUE;
        }
        break;

      case HID_GET_IDLE:
        usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
        return TRUE;
        break;
      }
      break;

    case USB_RTYPE_DIR_HOST2DEV:
      switch(usbp->setup[1]) {   /* bRequest */
      case HID_SET_REPORT:
        switch(usbp->setup[4]) {       /* LSB(wIndex) (check MSB==0 and wLength==1?) */
        case KEYBOARD_INTERFACE:
#ifdef NKRO_ENABLE
        case NKRO_INTERFACE:
#endif  /* NKRO_ENABLE */
        /* keyboard_led_stats = <read byte from next OUT report>
         * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
          usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
          return TRUE;
          break;
        }
        break;

      case HID_SET_PROTOCOL:
        if((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) {   /* wIndex */
          keyboard_protocol = ((usbp->setup[2]) != 0x00);   /* LSB(wValue) */
#ifdef NKRO_ENABLE
          keymap_config.nkro = !!keyboard_protocol;
          if(!keymap_config.nkro && keyboard_idle) {
#else /* NKRO_ENABLE */
          if(keyboard_idle) {
#endif /* NKRO_ENABLE */
          /* arm the idle timer if boot protocol & idle */
            osalSysLockFromISR();
            chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
            osalSysUnlockFromISR();
          }
        }
        usbSetupTransfer(usbp, NULL, 0, NULL);
        return TRUE;
        break;

      case HID_SET_IDLE:
        keyboard_idle = usbp->setup[3];     /* MSB(wValue) */
        /* arm the timer */
#ifdef NKRO_ENABLE
        if(!keymap_config.nkro && keyboard_idle) {
#else /* NKRO_ENABLE */
        if(keyboard_idle) {
#endif /* NKRO_ENABLE */
          osalSysLockFromISR();
          chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
          osalSysUnlockFromISR();
        }
        usbSetupTransfer(usbp, NULL, 0, NULL);
        return TRUE;
        break;
      }
      break;
    }
  }

  /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
  if((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
    dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
    if(dp == NULL)
      return FALSE;
    usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
    return TRUE;
  }

  for (int i=0;i<NUM_USB_DRIVERS;i++) {
    if (drivers.array[i].config.int_in) {
      // NOTE: Assumes that we only have one serial driver
      return qmkusbRequestsHook(usbp);
    }
  }

  return FALSE;
}

/* Start-of-frame callback */
static void usb_sof_cb(USBDriver *usbp) {
  kbd_sof_cb(usbp);
  osalSysLockFromISR();
  for (int i=0; i<NUM_USB_DRIVERS;i++) {
    qmkusbSOFHookI(&drivers.array[i].driver);
  }
  osalSysUnlockFromISR();
}


/* USB driver configuration */
static const USBConfig usbcfg = {
  usb_event_cb,                 /* USB events callback */
  usb_get_descriptor_cb,        /* Device GET_DESCRIPTOR request callback */
  usb_request_hook_cb,          /* Requests hook callback */
  usb_sof_cb                    /* Start Of Frame callback */
};

/*
 * Initialize the USB driver
 */
void init_usb_driver(USBDriver *usbp) {
  for (int i=0; i<NUM_USB_DRIVERS;i++) {
    QMKUSBDriver* driver = &drivers.array[i].driver;
    drivers.array[i].in_ep_config.in_state = &drivers.array[i].in_ep_state;
    drivers.array[i].out_ep_config.out_state = &drivers.array[i].out_ep_state;
    drivers.array[i].int_ep_config.in_state = &drivers.array[i].int_ep_state;
    qmkusbObjectInit(driver, &drivers.array[i].config);
    qmkusbStart(driver, &drivers.array[i].config);
  }

  /*
   * Activates the USB driver and then the USB bus pull-up on D+.
   * Note, a delay is inserted in order to not have to disconnect the cable
   * after a reset.
   */
  usbDisconnectBus(usbp);
  wait_ms(1500);
  usbStart(usbp, &usbcfg);
  usbConnectBus(usbp);

  chVTObjectInit(&keyboard_idle_timer);
}

/* ---------------------------------------------------------
 *                  Keyboard functions
 * ---------------------------------------------------------
 */
/* keyboard IN callback hander (a kbd report has made it IN) */
void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
  /* STUB */
  (void)usbp;
  (void)ep;
}