Explorar el Código

Add SinkPPSPeriodicTimer

Now if we make a request for a PPS APDO, the SinkPPSPeriodicTimer is
run, forcing a new request to be made every 10 s.  This is important
because without it, the Source Shall perform a Hard Reset 15 s after the
request is made.
Clara Hobbs hace 6 años
padre
commit
53afb2db42
Se han modificado 4 ficheros con 69 adiciones y 7 borrados
  1. 12
    3
      lib/include/pd.h
  2. 6
    2
      lib/include/pdb_pe.h
  3. 50
    2
      lib/src/policy_engine.c
  4. 1
    0
      lib/src/policy_engine.h

+ 12
- 3
lib/include/pd.h Ver fichero

@@ -142,9 +142,16 @@
142 142
 #define PD_PDO_TYPE (0x3 << PD_PDO_TYPE_SHIFT)
143 143
 
144 144
 /* PDO types */
145
-#define PD_PDO_TYPE_FIXED (0x0 << PD_PDO_TYPE_SHIFT)
146
-#define PD_PDO_TYPE_BATTERY (0x1 << PD_PDO_TYPE_SHIFT)
147
-#define PD_PDO_TYPE_VARIABLE (0x2 << PD_PDO_TYPE_SHIFT)
145
+#define PD_PDO_TYPE_FIXED ((unsigned) (0x0 << PD_PDO_TYPE_SHIFT))
146
+#define PD_PDO_TYPE_BATTERY ((unsigned) (0x1 << PD_PDO_TYPE_SHIFT))
147
+#define PD_PDO_TYPE_VARIABLE ((unsigned) (0x2 << PD_PDO_TYPE_SHIFT))
148
+#define PD_PDO_TYPE_AUGMENTED ((unsigned) (0x3 << PD_PDO_TYPE_SHIFT))
149
+
150
+#define PD_APDO_TYPE_SHIFT 28
151
+#define PD_APDO_TYPE (0x3 << PD_APDO_TYPE_SHIFT)
152
+
153
+/* APDO types */
154
+#define PD_APDO_TYPE_PPS (0x0 << PD_APDO_TYPE_SHIFT)
148 155
 
149 156
 /* PD Source Fixed PDO */
150 157
 #define PD_PDO_SRC_FIXED_DUAL_ROLE_PWR_SHIFT 29
@@ -214,6 +221,7 @@
214 221
 #define PD_RDO_UNCHUNKED_EXT_MSG (1 << PD_RDO_UNCHUNKED_EXT_MSG_SHIFT)
215 222
 
216 223
 #define PD_RDO_OBJPOS_SET(i) (((i) << PD_RDO_OBJPOS_SHIFT) & PD_RDO_OBJPOS)
224
+#define PD_RDO_OBJPOS_GET(msg) (((msg)->obj[0] & PD_RDO_OBJPOS) >> PD_RDO_OBJPOS_SHIFT)
217 225
 
218 226
 /* Fixed and Variable RDO, no GiveBack support */
219 227
 #define PD_RDO_FV_CURRENT_SHIFT 10
@@ -245,6 +253,7 @@
245 253
 #define PD_T_SENDER_RESPONSE MS2ST(27)
246 254
 #define PD_T_SINK_REQUEST MS2ST(100)
247 255
 #define PD_T_TYPEC_SINK_WAIT_CAP MS2ST(465)
256
+#define PD_T_PPS_REQUEST S2ST(10)
248 257
 /* This is actually from Type-C, not Power Delivery, but who cares? */
249 258
 #define PD_T_PD_DEBOUNCE MS2ST(15)
250 259
 

+ 6
- 2
lib/include/pdb_pe.h Ver fichero

@@ -30,9 +30,9 @@
30 30
  * Events for the Policy Engine thread, sent by user code
31 31
  */
32 32
 /* Tell the PE to send a Get_Source_Cap message */
33
-#define PDB_EVT_PE_GET_SOURCE_CAP EVENT_MASK(6)
33
+#define PDB_EVT_PE_GET_SOURCE_CAP EVENT_MASK(7)
34 34
 /* Tell the PE that new power is required */
35
-#define PDB_EVT_PE_NEW_POWER EVENT_MASK(7)
35
+#define PDB_EVT_PE_NEW_POWER EVENT_MASK(8)
36 36
 
37 37
 
38 38
 /*
@@ -60,6 +60,10 @@ struct pdb_pe {
60 60
     int8_t _hard_reset_counter;
61 61
     /* The result of the last Type-C Current match comparison */
62 62
     int8_t _old_tcc_match;
63
+    /* The index of the first PPS APDO */
64
+    uint8_t _pps_index;
65
+    /* Virtual timer for SinkPPSPeriodicTimer */
66
+    virtual_timer_t _sink_pps_periodic_timer;
63 67
     /* Queue for the PE mailbox */
64 68
     msg_t _mailbox_queue[PDB_MSG_POOL_SIZE];
65 69
 };

+ 50
- 2
lib/src/policy_engine.c Ver fichero

@@ -27,6 +27,15 @@
27 27
 #include "fusb302b.h"
28 28
 
29 29
 
30
+static void pe_sink_pps_periodic_timer_cb(void *cfg)
31
+{
32
+    /* Signal the PE thread to make a new PPS request */
33
+    chSysLockFromISR();
34
+    chEvtSignalI(((struct pdb_config *) cfg)->pe.thread, PDB_EVT_PE_PPS_REQUEST);
35
+    chSysUnlockFromISR();
36
+}
37
+
38
+
30 39
 enum policy_engine_state {
31 40
     PESinkStartup,
32 41
     PESinkDiscovery,
@@ -133,6 +142,21 @@ static enum policy_engine_state pe_sink_wait_cap(struct pdb_config *cfg)
133 142
 
134 143
 static enum policy_engine_state pe_sink_eval_cap(struct pdb_config *cfg)
135 144
 {
145
+    /* If we have a message, remember the index of the first PPS APDO so we can
146
+     * check if the request is for a PPS APDO in PE_SNK_Select_Cap. */
147
+    if (cfg->pe._message != NULL) {
148
+        /* Start by assuming we won't find a PPS APDO (set the index greater
149
+         * than the maximum possible) */
150
+        cfg->pe._pps_index = 8;
151
+        /* Search for the first PPS APDO */
152
+        for (int8_t i = 0; i < PD_NUMOBJ_GET(cfg->pe._message); i++) {
153
+            if ((cfg->pe._message->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED
154
+                    && (cfg->pe._message->obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) {
155
+                cfg->pe._pps_index = i + 1;
156
+                break;
157
+            }
158
+        }
159
+    }
136 160
     /* Get a message object for the request if we don't have one already */
137 161
     if (cfg->pe._last_dpm_request == NULL) {
138 162
         cfg->pe._last_dpm_request = chPoolAlloc(&pdb_msg_pool);
@@ -165,6 +189,20 @@ static enum policy_engine_state pe_sink_select_cap(struct pdb_config *cfg)
165 189
         return PESinkHardReset;
166 190
     }
167 191
 
192
+    /* If we're using PD 3.0 */
193
+    if ((cfg->pe.hdr_template & PD_HDR_SPECREV) == PD_SPECREV_3_0) {
194
+        /* If the request was for a PPS APDO, start SinkPPSPeriodicTimer */
195
+        if (PD_RDO_OBJPOS_GET(cfg->pe._last_dpm_request) >= cfg->pe._pps_index) {
196
+            chVTSet(&cfg->pe._sink_pps_periodic_timer, PD_T_PPS_REQUEST,
197
+                    pe_sink_pps_periodic_timer_cb, cfg);
198
+        /* Otherwise, stop SinkPPSPeriodicTimer */
199
+        } else {
200
+            chVTReset(&cfg->pe._sink_pps_periodic_timer);
201
+        }
202
+    }
203
+    /* This will use a virtual timer to send an event flag to this thread after
204
+     * PD_T_PPS_REQUEST */
205
+
168 206
     /* Wait for a response */
169 207
     evt = chEvtWaitAnyTimeout(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET,
170 208
             PD_T_SENDER_RESPONSE);
@@ -278,11 +316,12 @@ static enum policy_engine_state pe_sink_ready(struct pdb_config *cfg)
278 316
     if (cfg->pe._min_power) {
279 317
         evt = chEvtWaitAnyTimeout(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET
280 318
                 | PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_GET_SOURCE_CAP
281
-                | PDB_EVT_PE_NEW_POWER, PD_T_SINK_REQUEST);
319
+                | PDB_EVT_PE_NEW_POWER | PDB_EVT_PE_PPS_REQUEST,
320
+                PD_T_SINK_REQUEST);
282 321
     } else {
283 322
         evt = chEvtWaitAny(PDB_EVT_PE_MSG_RX | PDB_EVT_PE_RESET
284 323
                 | PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_GET_SOURCE_CAP
285
-                | PDB_EVT_PE_NEW_POWER);
324
+                | PDB_EVT_PE_NEW_POWER | PDB_EVT_PE_PPS_REQUEST);
286 325
     }
287 326
 
288 327
     /* If we got reset signaling, transition to default */
@@ -313,6 +352,11 @@ static enum policy_engine_state pe_sink_ready(struct pdb_config *cfg)
313 352
         return PESinkEvalCap;
314 353
     }
315 354
 
355
+    /* If SinkPPSPeriodicTimer ran out, send a new request */
356
+    if (evt & PDB_EVT_PE_PPS_REQUEST) {
357
+        return PESinkSelectCap;
358
+    }
359
+
316 360
     /* If no event was received, the timer ran out. */
317 361
     if (evt == 0) {
318 362
         /* Repeat our Request message */
@@ -720,8 +764,12 @@ static THD_FUNCTION(PolicyEngine, vcfg) {
720 764
 
721 765
     /* Initialize the mailbox */
722 766
     chMBObjectInit(&cfg->pe.mailbox, cfg->pe._mailbox_queue, PDB_MSG_POOL_SIZE);
767
+    /* Initialize the VT for SinkPPSPeriodicTimer */
768
+    chVTObjectInit(&cfg->pe._sink_pps_periodic_timer);
723 769
     /* Initialize the old_tcc_match */
724 770
     cfg->pe._old_tcc_match = -1;
771
+    /* Initialize the pps_index */
772
+    cfg->pe._pps_index = 8;
725 773
     /* Initialize the PD message header template */
726 774
     cfg->pe.hdr_template = PD_DATAROLE_UFP | PD_POWERROLE_SINK;
727 775
 

+ 1
- 0
lib/src/policy_engine.h Ver fichero

@@ -35,6 +35,7 @@
35 35
 #define PDB_EVT_PE_TX_ERR EVENT_MASK(3)
36 36
 #define PDB_EVT_PE_HARD_SENT EVENT_MASK(4)
37 37
 #define PDB_EVT_PE_I_OVRTEMP EVENT_MASK(5)
38
+#define PDB_EVT_PE_PPS_REQUEST EVENT_MASK(6)
38 39
 
39 40
 
40 41
 /*

Loading…
Cancelar
Guardar