Advertisement
Guest User

Untitled

a guest
Jul 3rd, 2013
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.51 KB | None | 0 0
  1. /*
  2.  * testpru
  3.  *
  4.  */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <stdarg.h>
  8. #include <stdio.h>
  9. #include <strings.h>
  10.  
  11. #include "pru_defs.h"
  12.  
  13. #include "linux_types.h"
  14. #include "remoteproc.h"
  15. #include "syscall.h"
  16.  
  17. #include "virtio_ring.h"
  18.  
  19. #include "pt.h"
  20.  
  21. #define DEBUG
  22.  
  23. #ifdef DEBUG
  24. #define BUG_ON(x) \
  25.     do { \
  26.         if (x) { \
  27.             sc_printf("BUG_ON @%s:%d", __FILE__, __LINE__); \
  28.             sc_halt(); \
  29.         } \
  30.     } while(0)
  31. #else
  32. #define BUG_ON(x)
  33. #endif
  34.  
  35. void sc_vprintf(const char *fmt, va_list ap)
  36. {
  37.     static char buf[128];
  38.  
  39.     vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
  40.     buf[sizeof(buf) - 1] = '\0';
  41.     sc_puts(buf);
  42. }
  43.  
  44. void sc_printf(const char *fmt, ...)
  45. {
  46.     va_list ap;
  47.    
  48.      va_start(ap, fmt);
  49.      sc_vprintf(fmt, ap);
  50.      va_end(ap);
  51. }
  52.  
  53. /* PRU clock (200MHz) */
  54. #define PRU_CLK 200000000
  55.  
  56. /* NOTE: Do no use it for larger than 5 secs */
  57. #define PRU_sec(x)  ((u32)(((u64)(x) * PRU_CLK))
  58. #define PRU_ms(x)   ((u32)(((u64)(x) * PRU_CLK) / 1000))
  59. #define PRU_ms_err(x)   ((u32)(((u64)(x) * PRU_CLK) % 1000))
  60. #define PRU_us(x)   ((u32)(((u64)(x) * PRU_CLK) / 1000000))
  61. #define PRU_us_err(x)   ((u32)(((u64)(x) * PRU_CLK) % 1000000))
  62. #define PRU_ns(x)   ((u32)(((u64)(x) * PRU_CLK) / 1000000000))
  63. #define PRU_ns_err(x)   ((u32)(((u64)(x) * PRU_CLK) % 1000000000))
  64.  
  65. struct pru_vring {
  66.     struct vring vr;
  67.     const char *name;
  68.     u32 align;
  69.     u32 notifyid;
  70.  
  71.     u16 num_mask;
  72.     u16 last_avail;
  73.     u16 last_avail_orig;
  74.  
  75.     u16 last_used_idx;
  76.  
  77.     u16 * volatile avail_idx_p;
  78.     u16 * volatile used_idx_p;
  79.     u16 * volatile avail_ring_p;
  80. };
  81.  
  82. struct pru_vring_elem {
  83.  
  84.     u32 out_len;    /* sum length of out descs */
  85.     u16 out_num;    /* number of out descs */
  86.     u16 out_idx;    /* index of first out desc */
  87.  
  88.     u32 in_len; /* sum length on in descs */
  89.     u16 in_num; /* number of in descs */
  90.     u16 in_idx; /* index of first in desc */
  91.  
  92.     u16 idx;    /* first idx */
  93. };
  94.  
  95. static void pru_vring_init(struct pru_vring *pvr, const char *name,
  96.     const struct fw_rsc_vdev_vring *rsc_vring)
  97. {
  98.     vring_init(&pvr->vr, rsc_vring->num,
  99.         (void *)rsc_vring->da, rsc_vring->align);
  100.     pvr->align = rsc_vring->align;
  101.     pvr->notifyid = rsc_vring->notifyid;
  102.     /* verify it's a power of two */
  103.     BUG_ON(rsc_vring->num & (rsc_vring->num - 1));
  104.     pvr->num_mask = rsc_vring->num - 1;
  105.     pvr->last_avail = 0;
  106.     pvr->last_avail_orig = 0;
  107.     pvr->avail_idx_p = &pvr->vr.avail->idx;
  108.     pvr->used_idx_p = &pvr->vr.used->idx;
  109.     pvr->avail_ring_p = pvr->vr.avail->ring;
  110. }
  111.  
  112. static inline u16 pru_vring_avail_idx(struct pru_vring *pvr)
  113. {
  114.     u16 val;
  115.  
  116.     val = *pvr->avail_idx_p;
  117.     // mb();
  118.     return val;
  119. }
  120.  
  121. static inline u16 pru_vring_used_idx(struct pru_vring *pvr)
  122. {
  123.     return *pvr->used_idx_p;
  124. }
  125.  
  126. static inline void pru_vring_used_idx_set(struct pru_vring *pvr, u16 idx)
  127. {
  128.     *pvr->used_idx_p = idx;
  129. }
  130.  
  131. static inline u16 pru_vring_avail_ring(struct pru_vring *pvr, u16 i)
  132. {
  133.     BUG_ON(i >= pvr->vr.num);
  134.     return pvr->avail_ring_p[i];
  135. }
  136.  
  137. static inline struct vring_desc *pru_vring_desc(struct pru_vring *pvr, u16 idx)
  138. {
  139.     return &pvr->vr.desc[idx & pvr->num_mask];
  140. }
  141.  
  142. /* if > num something is very very wrong */
  143. static inline u16 pru_vring_num_heads(struct pru_vring *pvr, u16 idx)
  144. {
  145.     u16 num_heads = pru_vring_avail_idx(pvr) - idx;
  146.  
  147.     BUG_ON(num_heads > pvr->vr.num);
  148.     return num_heads;
  149. }
  150.  
  151. static inline u16 pru_vring_get_head(struct pru_vring *pvr, u16 idx)
  152. {
  153.     u16 head = pru_vring_avail_ring(pvr, idx & pvr->num_mask);
  154.  
  155.     BUG_ON(head >= pvr->vr.num);
  156.     return head;
  157. }
  158.  
  159. static inline u8
  160. pru_vring_buf_is_avail(struct pru_vring *pvr)
  161. {
  162.     return pru_vring_num_heads(pvr, pvr->last_avail) != 0;
  163. }
  164.  
  165. static inline struct vring_desc *
  166. pru_vring_get_next_avail_desc(struct pru_vring *pvr)
  167. {
  168.     return pru_vring_desc(pvr, pru_vring_get_head(pvr, pvr->last_avail++));
  169. }
  170.  
  171. static inline void pru_vring_push_one(struct pru_vring *pvr, u32 len)
  172. {
  173.     u16 old, idx;
  174.     struct vring_used_elem *vru;
  175.  
  176.     /* first fill */
  177.     old = pru_vring_used_idx(pvr);
  178.     idx = old & pvr->num_mask;
  179.  
  180.     vru = &pvr->vr.used->ring[idx];
  181.     vru->id = idx & pvr->num_mask;
  182.     vru->len = len;
  183.  
  184.     /* now update */
  185.     pru_vring_used_idx_set(pvr, ++old);
  186. }
  187.  
  188. static void pru_vring_elem_init(struct pru_vring *pvr,
  189.         struct pru_vring_elem *pvre)
  190. {
  191.     u16 num = pvr->vr.num;
  192.  
  193.     pvre->idx = num;
  194.  
  195.     pvre->out_num = 0;
  196.     pvre->out_idx = num;
  197.     pvre->out_len = 0;
  198.  
  199.     pvre->in_num = 0;
  200.     pvre->in_idx = num;
  201.     pvre->in_len = 0;
  202.  
  203.     /* save in case of rollback */
  204.     pvr->last_avail_orig = pvr->last_avail;
  205. }
  206.  
  207. static int pru_vring_pop(struct pru_vring *pvr, struct pru_vring_elem *pvre)
  208. {
  209.     u16 i, head;
  210.     struct vring_desc *vrd;
  211.  
  212.     if (!pru_vring_num_heads(pvr, pvr->last_avail))
  213.         return 0;
  214.  
  215.     pru_vring_elem_init(pvr, pvre);
  216.  
  217.     /* get head */
  218.     head = pru_vring_get_head(pvr, pvr->last_avail++);
  219.  
  220.     // if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))
  221.     //  pru_vring_avail_event(pvr, pru_vring_avail_idx(pvr));
  222.  
  223.     vrd = pru_vring_desc(pvr, head);
  224.  
  225.     /* we don't support VRING_DESC_F_INDIRECT */
  226.     BUG_ON(vrd->flags & VRING_DESC_F_INDIRECT);
  227.  
  228.     i = head;
  229.  
  230.     pvre->idx = i;
  231.  
  232.     /* loop collecting elements */
  233.     for (;;) {
  234.         if (vrd->flags & VRING_DESC_F_WRITE) {
  235.             if (pvre->in_num++ == 0)
  236.                 pvre->in_idx = i & pvr->num_mask;
  237.             pvre->in_len += vrd->len;
  238.         } else {
  239.             if (pvre->out_num++ == 0)
  240.                 pvre->out_idx = i & pvr->num_mask;
  241.             pvre->out_len += vrd->len;
  242.         }
  243.  
  244.         if (!(vrd->flags & VRING_DESC_F_NEXT))
  245.             break;
  246.  
  247.         /* next descriptor */
  248.         vrd = pru_vring_desc(pvr, ++i);
  249.     }
  250.  
  251.     return pvre->in_num + pvre->out_num;
  252. }
  253.  
  254. static void pru_vring_push(struct pru_vring *pvr,
  255.         const struct pru_vring_elem *pvre, u32 len)
  256. {
  257.     u16 idx, old;
  258.     struct vring_used_elem *used_vring;
  259.  
  260.     /* first fill */
  261.     old = pru_vring_used_idx(pvr);
  262.     idx = old & pvr->num_mask;
  263.  
  264.     used_vring = &pvr->vr.used->ring[idx];
  265.     used_vring->id = pvre->idx & pvr->num_mask;
  266.     used_vring->len = len;
  267.  
  268.     /* now update */
  269.     pru_vring_used_idx_set(pvr, ++old);
  270. }
  271.  
  272. struct pru_vring tx_ring;
  273. struct pru_vring rx_ring;
  274.  
  275. #define DELAY_CYCLES(x) \
  276.     do { \
  277.         unsigned int t = (x); \
  278.         while (--t) { \
  279.             __asm(" "); \
  280.         } \
  281.     } while(0)
  282.  
  283. void dump_vring(const char *name, struct vring *vring, unsigned int align)
  284. {
  285.     struct vring_desc *vd;
  286.     int i, sz;
  287.  
  288.     sz = vring_size(vring->num, align);
  289.     sc_printf("vring %s @0x%x num %d size %d desc=0x%x avail=0x%x used=0x%x",
  290.         name, (unsigned int)vring->desc, vring->num, sz,
  291.         (unsigned int)vring->desc, (unsigned int)vring->avail,
  292.         (unsigned int)vring->used);
  293.  
  294.     for (i = 0; i < vring->num; i++) {
  295.         vd = &vring->desc[i];
  296.         sc_printf(" d#%d: a 0x%x l 0x%x f 0x%x n 0x%x",
  297.             i, (__u32)vd->addr, vd->len, vd->flags, vd->next);
  298.     }
  299.     sc_printf(" avail: flags 0x%x idx 0x%x",
  300.         vring->avail->flags, vring->avail->idx);
  301.  
  302.     for (i = 0; i < vring->num; i++) {
  303.         sc_printf(" a#%d: ring 0x%x", i,
  304.             vring->avail->ring[i]);
  305.     }
  306.     sc_printf(" avail: used_event_idx 0x%x",
  307.         vring->avail->ring[vring->num]);
  308.  
  309.     sc_printf(" used: flags 0x%x idx 0x%x",
  310.         vring->used->flags, vring->used->idx);
  311.     for (i = 0; i < vring->num; i++) {      
  312.         sc_printf(" u#%d: id 0x%x len 0x%x", i,
  313.             vring->used->ring[i].id,
  314.                 vring->used->ring[i].len);
  315.     }
  316.  
  317. }
  318.  
  319. /* event definitions */
  320. #define SYSEV_ARM_TO_PRU0   21
  321. #define SYSEV_ARM_TO_PRU1   22
  322. #define SYSEV_PRU0_TO_ARM   19
  323. #define SYSEV_PRU0_TO_PRU1  17
  324. #define SYSEV_PRU1_TO_ARM   20
  325. #define SYSEV_PRU1_TO_PRU0  19
  326.  
  327. void *resource_get_type(struct resource_table *res, int type, int idx)
  328. {
  329.     struct fw_rsc_hdr *rsc_hdr;
  330.     int i, j;
  331.  
  332.     j = 0;
  333.     for (i = 0; i < res->num; i++) {
  334.         rsc_hdr = (void *)((char *)res + res->offset[i]);
  335.         if (type >= 0 && rsc_hdr->type != type)
  336.             continue;
  337.         if (j == idx)
  338.             return &rsc_hdr->data[0];
  339.     }
  340.  
  341.     return NULL;
  342. }
  343.  
  344. static void handle_event_startup(void)
  345. {
  346.     int i;
  347.     struct resource_table *res;
  348.     struct fw_rsc_vdev *rsc_vdev;
  349.     struct fw_rsc_vdev_vring *rsc_vring;
  350.  
  351.     res = sc_get_cfg_resource_table();
  352.     BUG_ON(res == NULL);
  353.  
  354.     /* get first VDEV resource */
  355.     rsc_vdev = resource_get_type(res, RSC_VDEV, 0);
  356.     BUG_ON(rsc_vdev == NULL);
  357.  
  358.     BUG_ON(rsc_vdev->num_of_vrings < 2);
  359.     for (i = 0, rsc_vring = rsc_vdev->vring; i < 2; i++, rsc_vring++) {
  360.         sc_printf("VR#%d: da=0x%x align=0x%x num=0x%x notifyid=0x%x",
  361.                 i, rsc_vring->da, rsc_vring->align,
  362.                 rsc_vring->num, rsc_vring->notifyid);
  363.     }
  364.  
  365.     pru_vring_init(&tx_ring, "tx", &rsc_vdev->vring[0]);
  366.     pru_vring_init(&rx_ring, "rx", &rsc_vdev->vring[1]);
  367. }
  368.  
  369. #define event_condition() \
  370.     ((__R31 & (1 << 30)) != 0)
  371.  
  372. #define RX_SIZE 32
  373. #define RX_SIZE_MASK (RX_SIZE - 1)
  374. #define TX_SIZE 64
  375. #define TX_SIZE_MASK (TX_SIZE - 1)
  376.  
  377. static u8 rx_in;
  378. static u8 rx_out;
  379. static u8 rx_cnt;
  380. static char rx_buf[RX_SIZE];
  381.  
  382. static u8 tx_in;
  383. static u8 tx_out;
  384. static u8 tx_cnt;
  385. static char tx_buf[TX_SIZE];
  386.  
  387. /* might yield, make sure _ch is static */
  388. #define RX_IN(_ch) \
  389.     do { \
  390.         /* yield while there's no space */ \
  391.         PT_YIELD_UNTIL(pt, rx_cnt < RX_SIZE); \
  392.         rx_buf[rx_in++ & RX_SIZE_MASK] = (_ch); \
  393.         rx_cnt++; \
  394.     } while (0)
  395.  
  396. /* waits until input (bah - no gcc makes me a sad panda) */
  397. #define RX_OUT(_ch) \
  398.     do { \
  399.         PT_WAIT_UNTIL(pt, rx_cnt > 0); \
  400.         rx_cnt--; \
  401.         (_ch) = rx_buf[rx_out++ & RX_SIZE_MASK]; \
  402.     } while (0)
  403.  
  404. /* might yield, make sure _ch is static */
  405. #define TX_IN(_ch) \
  406.     do { \
  407.         /* yield while there's no space */ \
  408.         PT_YIELD_UNTIL(pt, tx_cnt < TX_SIZE); \
  409.         tx_buf[tx_in++ & TX_SIZE_MASK] = (_ch); \
  410.         tx_cnt++; \
  411.     } while (0)
  412.  
  413. /* waits until input (bah - no gcc makes me a sad panda) */
  414. #define TX_OUT(_ch) \
  415.     do { \
  416.         PT_WAIT_UNTIL(pt, tx_cnt > 0); \
  417.         tx_cnt--; \
  418.         (_ch) = tx_buf[tx_out++ & TX_SIZE_MASK]; \
  419.     } while (0)
  420.  
  421. /* non blocking version */
  422. #define TX_OUT_NB(_ch) \
  423.     do { \
  424.         tx_cnt--; \
  425.         (_ch) = tx_buf[tx_out++ & TX_SIZE_MASK]; \
  426.     } while (0)
  427.  
  428. static int event_thread(struct pt *pt)
  429. {
  430.     static struct pru_vring_elem pvre;
  431.     static u16 idx, count;
  432.     static u32 rx_len, len;
  433.     struct vring_desc *vrd;
  434.     static char *ptr;
  435.  
  436.     PT_BEGIN(pt);
  437.  
  438.     for (;;) {
  439.         /* wait until we get the indication */
  440.         PT_WAIT_UNTIL(pt, event_condition());
  441.  
  442.         if (PINTC_SRSR0 & (1 << SYSEV_ARM_TO_PRU0)) {
  443.             PINTC_SICR = SYSEV_ARM_TO_PRU0;
  444.  
  445.             while (pru_vring_pop(&rx_ring, &pvre)) {
  446.  
  447.                 /* process the incoming buffers (??? not used) */
  448.                 if ((count = pvre.in_num) > 0) {
  449.                     idx = pvre.in_idx;
  450.                     while (count-- > 0) {
  451.                         vrd = pru_vring_desc(&rx_ring, idx);
  452.                         ptr = pa_to_da(vrd->addr);
  453.                         idx++;
  454.                     }
  455.                 }
  456.  
  457.                 rx_len = 0;
  458.  
  459.                 /* process the outgoing buffers (this is our RX) */
  460.                 if (pvre.out_num > 0) {
  461.  
  462.                     idx = pvre.out_idx;
  463.                     count = pvre.out_num;
  464.                     while (count-- > 0) {
  465.                         vrd = pru_vring_desc(&rx_ring, idx);
  466.                         ptr = pa_to_da(vrd->addr);
  467.                         len = vrd->len;
  468.  
  469.                         /* put it in the rx buffer (can yield) */
  470.                         while (len-- > 0)
  471.                             RX_IN(*ptr++);
  472.  
  473.                         rx_len += vrd->len;
  474.  
  475.                         idx++;
  476.                     }
  477.                 }
  478.  
  479.                 pru_vring_push(&rx_ring, &pvre, rx_len);
  480.                 /* VRING0 PRU0 -> ARM */
  481.                 SIGNAL_EVENT(25);
  482.             }
  483.         }
  484.  
  485.         if (PINTC_SRSR0 & (1 << SYSEV_PRU1_TO_PRU0)) {
  486.             PINTC_SICR = SYSEV_PRU1_TO_PRU0;
  487.         }
  488.     }
  489.  
  490.     /* get around warning */
  491.     PT_YIELD(pt);
  492.  
  493.     PT_END(pt);
  494. }
  495.  
  496. static void handle_led_startup(void)
  497. {
  498.     /* IEP timer is incrementing by one */
  499.     PIEP_GLOBAL_CFG = GLOBAL_CFG_CNT_ENABLE |
  500.               GLOBAL_CFG_DEFAULT_INC(1) |
  501.               GLOBAL_CFG_CMP_INC(1);
  502.  
  503.     /* delay with the timer */
  504.     PIEP_CMP_CMP0 = PIEP_COUNT + 10;
  505.     PIEP_CMP_STATUS = CMD_STATUS_CMP_HIT(0); /* clear the interrupt */
  506.     PIEP_CMP_CFG |= CMP_CFG_CMP_EN(0);
  507.  
  508. }
  509.  
  510. static u32 led_cycles = PRU_us(100);
  511.  
  512. static void handle_led_event(void)
  513. {
  514.     /* toggle led */
  515.     __R30 ^= (1 << 5);
  516.  
  517.     PIEP_CMP_STATUS = CMD_STATUS_CMP_HIT(0);
  518.     PIEP_CMP_CMP0 += led_cycles;
  519. }
  520.  
  521. #define led_condition() \
  522.     ((PIEP_CMP_STATUS & CMD_STATUS_CMP_HIT(0)) != 0)
  523.  
  524. static int led_thread(struct pt *pt)
  525. {
  526.     PT_BEGIN(pt);
  527.  
  528.     for (;;) {
  529.         /* wait until we get the indication */
  530.         PT_WAIT_UNTIL(pt, led_condition());
  531.  
  532.         handle_led_event();
  533.     }
  534.  
  535.     PT_YIELD(pt);
  536.  
  537.     PT_END(pt);
  538. }
  539.  
  540. #define v_puts(_p, _ch, _str) \
  541.     do { \
  542.         _p = (_str); \
  543.         while ((_ch = *_p++) != '\0') \
  544.             TX_IN(_ch); \
  545.     } while(0)
  546.  
  547. #define v_putc(_ch) TX_IN(_ch)
  548. #define v_getc(_ch) RX_OUT(_ch)
  549.  
  550. static int prompt_thread(struct pt *pt)
  551. {
  552.     static char ch, ch1;
  553.     static char *p;
  554.     static char *pp;
  555.  
  556.     PT_BEGIN(pt);
  557.  
  558.     for (;;) {
  559.         v_puts(p, ch, "PRU> ");
  560.         v_getc(ch1);
  561.         v_putc(ch1);
  562.  
  563.         if (ch1 == '?') {
  564.             pp = "\r\nHelp\r\n";
  565.         } else if (ch1 == '1') {
  566.             led_cycles = PRU_ms(500);
  567.             pp = "\r\n500ms\r\n";
  568.         } else if (ch1 == '2') {
  569.             led_cycles = PRU_ms(100);
  570.             pp = "\r\n100ms\r\n";
  571.         } else if (ch1 == '3') {
  572.             led_cycles = PRU_ms(1);
  573.             pp = "\r\n1ms\r\n";
  574.         } else if (ch1 == '4') {
  575.             led_cycles = PRU_us(500);
  576.             pp = "\r\n500us\r\n";
  577.         } else if (ch1 == '5') {
  578.             led_cycles = PRU_us(250);
  579.             pp = "\r\n500us\r\n";
  580.         } else if (ch1 == '6') {
  581.             led_cycles = PRU_us(100);
  582.             pp = "\r\n100us\r\n";
  583.         } else if (ch1 == '7') {
  584.             led_cycles = PRU_us(10);
  585.             pp = "\r\n10us\r\n";
  586.         } else if (ch1 == '8') {
  587.             led_cycles = PRU_us(1);
  588.             pp = "\r\n1us\r\n";
  589.         } else if (ch1 == '9') {
  590.             led_cycles = PRU_ns(500);
  591.             pp = "\r\n500ns\r\n";
  592.         } else {
  593.             pp = "\r\n*BAD*\r\n";
  594.         }
  595.         v_puts(p, ch, pp);
  596.     }
  597.  
  598.     PT_YIELD(pt);
  599.  
  600.     PT_END(pt);
  601. }
  602.  
  603. static int tx_thread(struct pt *pt)
  604. {
  605.     struct vring_desc *vrd = NULL;
  606.     u32 chunk, i;
  607.     char *ptr, ch;
  608.  
  609.     PT_BEGIN(pt);
  610.  
  611.     for (;;) {
  612.  
  613.         /* wait until we get the indication (and there's a buffer) */
  614.         PT_WAIT_UNTIL(pt, tx_cnt && pru_vring_buf_is_avail(&tx_ring));
  615.  
  616.         vrd = pru_vring_get_next_avail_desc(&tx_ring);
  617.  
  618.         /* we don't support VRING_DESC_F_INDIRECT */
  619.         BUG_ON(vrd->flags & VRING_DESC_F_INDIRECT);
  620.  
  621.         chunk = tx_cnt;
  622.         if (chunk > vrd->len)
  623.             chunk = vrd->len;
  624.  
  625.         ptr = pa_to_da(vrd->addr);
  626.  
  627.         for (i = 0; i < chunk; i++) {
  628.             ch = tx_buf[tx_out++ & TX_SIZE_MASK];
  629.             *ptr++ = ch;
  630.         }
  631.         tx_cnt -= chunk;
  632.         vrd->len = chunk;
  633.         vrd->flags &= ~VRING_DESC_F_NEXT;   /* last */
  634.  
  635.         pru_vring_push_one(&tx_ring, chunk);
  636.  
  637.         /* VRING0 PRU0 -> ARM */
  638.         SIGNAL_EVENT(25);
  639.     }
  640.  
  641.     PT_YIELD(pt);
  642.  
  643.     PT_END(pt);
  644. }
  645.  
  646. static struct pt pt_event;
  647. static struct pt pt_led;
  648. static struct pt pt_prompt;
  649. static struct pt pt_tx;
  650.  
  651. int main(int argc, char *argv[])
  652. {
  653.     /* enable OCP master port */
  654.     PRUCFG_SYSCFG &= ~SYSCFG_STANDBY_INIT;
  655.  
  656.     sc_printf("Using protothreads");
  657.  
  658.     PT_INIT(&pt_event);
  659.     PT_INIT(&pt_led);
  660.     PT_INIT(&pt_prompt);
  661.     PT_INIT(&pt_tx);
  662.  
  663.     handle_event_startup();
  664.     rx_in = rx_out = rx_cnt = 0;
  665.     tx_in = tx_out = tx_cnt = 0;
  666.  
  667.     handle_led_startup();
  668.  
  669.     for (;;) {
  670.         event_thread(&pt_event);
  671.         tx_thread(&pt_tx);
  672.         led_thread(&pt_led);
  673.         prompt_thread(&pt_prompt);
  674.     }
  675. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement