Atmel xmega USB, Interrupt disabled / enabled / Latenz

OP #3279822
Lesenswert?

Hallo,

ich wühle mich gerade durch das Keyboard-Bespiel aus dem ASF und rätsle 
über die Notwendigkeit des Verriegels des Interruptsystems. Hintergrund: 
ich kann aus anderen Gründe keine allzu lange Zeit im Disabled-Zustand 
zulassen.


Atmel hat da Zugriffsroutinen auf den Keyboardreport definiert, hier mal 
als Beispiel der Modifiereintrag:
1
bool udi_hid_kbd_modifier_up(uint8_t modifier_id)
2
{
3
  irqflags_t flags = cpu_irq_save();
4

5
  // Fill report
6
  udi_hid_kbd_report[0] &= ~(unsigned)modifier_id;
7
  udi_hid_kbd_b_report_valid = true;
8

9
  // Send report
10
  udi_hid_kbd_send_report();
11

12
  cpu_irq_restore(flags);
13
  return true;
14
}
Hier machen sie also cli(), dann das Bit eintragen, dann kommt 
udi_hid_kbd_send_report():
1
static bool udi_hid_kbd_send_report(void)    // runs in disabled int
2
{
3
  if (udi_hid_kbd_b_report_trans_ongoing)
4
    return false;
5
  memcpy(udi_hid_kbd_report_trans, udi_hid_kbd_report,
6
      UDI_HID_KBD_REPORT_SIZE);
7
  udi_hid_kbd_b_report_valid = false;
8
  udi_hid_kbd_b_report_trans_ongoing =
9
      udd_ep_run(  UDI_HID_KBD_EP_IN,
10
              false,
11
              udi_hid_kbd_report_trans,
12
              UDI_HID_KBD_REPORT_SIZE,
13
              udi_hid_kbd_report_sent);
14
  return udi_hid_kbd_b_report_trans_ongoing;
15
}

Hier geht es, wenn möglich, nach udd_ep_run() = Endpoint run. Endpoint 
run ist dann eine länger Geschichte:
1
bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket, uint8_t * buf,
2
    iram_size_t buf_size, udd_callback_trans_t callback)
3
{
4
  udd_ep_job_t *ptr_job;
5
  irqflags_t flags;
6
  UDD_EP_t *ep_ctrl;
7

8
  Assert(udd_ep_is_valid(ep));
9

10
  // Get control & job about this endpoint
11
  ptr_job = udd_ep_get_job(ep);
12
  ep_ctrl = udd_ep_get_ctrl(ep);
13

14
  if (!udd_endpoint_is_enable(ep_ctrl)) {
15
    return false; // Endpoint not allocated
16
  }
17
  if (udd_endpoint_get_type(ep_ctrl)!=USB_EP_TYPE_ISOCHRONOUS_gc
18
    && udd_endpoint_is_stall(ep_ctrl)) {
19
    return false; // Endpoint is halted
20
  }
21
  flags = cpu_irq_save();          // endpoint run
22
  if (ptr_job->busy == true) {
23
    cpu_irq_restore(flags);
24
    return false; // Job already on going
25
  }
26
  ptr_job->busy = true;
27
  cpu_irq_restore(flags);
28

29

30
  // Update Job information
31
  ptr_job->buf = buf;
32
  ptr_job->buf_size = buf_size;
33
  ptr_job->nb_trans = 0;
34
  ptr_job->call_trans = callback;
35
  // Need to enable shortpacket to send a ZLP (buf_size==0)
36
  ptr_job->b_shortpacket = b_shortpacket || (buf_size==0);
37
  ptr_job->b_use_out_cache_buffer = false;
38

39
  // Initialize value to simulate a empty transfer
40
  if (USB_EP_DIR_IN == (ep & USB_EP_DIR_IN)) {
41
    udd_endpoint_in_reset_nb_sent(ep_ctrl);
42
  }
43
  else
44
  {
45
    if ((USB_EP_TYPE_ISOCHRONOUS_gc == udd_endpoint_get_type(ep_ctrl))
46
    && (0 != (buf_size % udd_ep_get_size(ep_ctrl)))) {
47
      // The user must use a buffer size modulo endpoint size
48
      ptr_job->busy = false;
49
      return false;
50
    }
51
    udd_endpoint_out_reset_nb_received(ep_ctrl);
52
    udd_endpoint_out_set_nbbyte(ep_ctrl, 0);
53
  }
54
  // Request next transfer
55
  udd_ep_trans_complet(ep);
56
  return true;
57
}
Hier ist die eigentlich kritische Geschichte, nämlich kontrollieren ob 
ptr_job->busy == true ist, nochmals mit cli()-restore geklammert. 
Brauche ich dann die äußere Verriegelung bei udi_hid_kbd_modifier_up? 
Oder soll die nur reentry verhindern?

Gruß Wolfgang

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren