int main(void) { /* Enable OCP Master Port */ PRUCFG_SYSCFG &= ~SYSCFG_STANDBY_INIT; cxt.magic = FW_MAGIC; while (1) { /* Poll for downcalls */ if(PINTC_SRSR0 & BIT(SYSEV_ARM_TO_PRU0)) { PINTC_SICR = SYSEV_ARM_TO_PRU0; sc_downcall(handle_downcall); } /* Run triggered */ if (state_run == 1) { /* Clear all pending interrupts */ PINTC_SECR0 = 0xFFFFFFFF; resume_other_pru(); run(&cxt, trigger_flags); /* Wait for the previous interrupts to be handled */ while (!(PINTC_SRSR0 & BIT(SYSEV_VR_PRU0_TO_ARM))); while ((PINTC_SRSR0 & BIT(SYSEV_VR_PRU0_TO_ARM))); /* Signal completion */ SIGNAL_EVENT(SYSEV_VR_PRU1_TO_ARM); /* Reset PRU1 and our state */ PCTRL_OTHER(0x0000) &= (u16)~CONTROL_SOFT_RST_N; state_run = 0; trigger_flags = -1; } } }
static int handle_downcall(u32 id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) { switch (id) { case DC_PWM_CONFIG: /* return -EINVAL */ if (arg1 < MIN_PWM_PULSE || arg2 < MIN_PWM_PULSE) return -22; PWM_CMD->cmd = PWM_CMD_MODIFY; PWM_CMD->pwm_nr = arg0; PWM_CMD->u.hilo[0] = arg1; PWM_CMD->u.hilo[1] = arg2; break; case DC_PWM_ENABLE: PWM_CMD->cmd = PWM_CMD_ENABLE; PWM_CMD->pwm_nr = arg0; break; case DC_PWM_DISABLE: PWM_CMD->cmd = PWM_CMD_DISABLE; PWM_CMD->pwm_nr = arg0; break; default: sc_printf("bad downcall with id %d", id); /* error */ return -1; } PWM_CMD->magic = PWM_CMD_MAGIC; SIGNAL_EVENT(SYSEV_THIS_PRU_TO_OTHER_PRU); return 0; }
static int tx_thread(struct pt *pt) { struct vring_desc *vrd = NULL; u32 chunk, i; char *ptr, ch; PT_BEGIN(pt); for (;;) { /* wait until we get the indication (and there's a buffer) */ PT_WAIT_UNTIL(pt, tx_cnt && pru_vring_buf_is_avail(&tx_ring)); vrd = pru_vring_get_next_avail_desc(&tx_ring); /* we don't support VRING_DESC_F_INDIRECT */ BUG_ON(vrd->flags & VRING_DESC_F_INDIRECT); chunk = tx_cnt; if (chunk > vrd->len) chunk = vrd->len; ptr = pa_to_da(vrd->addr); for (i = 0; i < chunk; i++) { ch = tx_buf[tx_out++ & TX_SIZE_MASK]; *ptr++ = ch; } tx_cnt -= chunk; vrd->len = chunk; vrd->flags &= ~VRING_DESC_F_NEXT; /* last */ pru_vring_push_one(&tx_ring, chunk); PT_WAIT_UNTIL(pt, !(PINTC_SRSR0 & BIT(SYSEV_VR_THIS_PRU_TO_ARM))); SIGNAL_EVENT(SYSEV_VR_THIS_PRU_TO_ARM); } PT_YIELD(pt); PT_END(pt); }
static int handle_downcall(u32 id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) { int max_slots = SHARED_MEM[CONFIG_MAX_SLOTS]; switch (id) { case DC_LED_BLANK: blank_slots(arg0); break; case DC_LED_WRITE: write_data(arg0, arg1, arg2); break; case DC_LED_WRITE_BURST: { int i = 0; u32 *data = (u32 *) PRU_LED_DATA; for (i = 0; i < max_slots; i++) { write_data(arg0, i, *data++); } break; } case DC_LED_LATCH: SIGNAL_EVENT(SYSEV_THIS_PRU_TO_OTHER_PRU); break; default: sc_printf("bad downcall with id %d", id); /* error */ return -EINVAL; } /* Allow kernel binding to know of slot count */ *((u32 *) PRU_LED_DATA) = max_slots; return 0; }
static int prompt_thread(struct pt *pt) { static char ch1; static char *pp; static char linebuf[80]; char buf[8]; char *p; static int linesz; static u8 current_universe; u32 val; PT_BEGIN(pt); for (;;) { again: sprintf((char *) &buf, "PRU#%d> ", current_universe); c_puts(buf); linesz = sizeof(linebuf); c_readline(linebuf, linesz); c_puts("\n"); if (linesz == 0) goto again; ch1 = linebuf[0]; pp = ""; PT_WAIT_UNTIL(pt, !(PINTC_SRSR0 & BIT(SYSEV_THIS_PRU_TO_OTHER_PRU))); if (ch1 == '?') { c_puts("Help\n" " s <universe> " "select universe 0-13\n" " b " "blanks slots 1-170\n" " m <val> " "max number of slots per universe 0-169\n" " w <num> <v1>.<v2>.<v3> " "write 24-bit GRB value to slot number\n" " l " "latch data out the PRU1\n"); } else if (ch1 == 's') { p = parse_u32(linebuf + 1, &val); if (val > MAX_UNIVERSES - 1) { pp = "*BAD*\n"; } else { current_universe = val; } } else if (ch1 == 'b') { blank_slots(current_universe); } else if (ch1 == 'm') { p = parse_u32(linebuf + 1, &val); if (val > MAX_SLOTS || val == 0) { pp = "*BAD\n"; } else { SHARED_MEM[CONFIG_MAX_SLOTS] = val; *((u32 *) PRU_LED_DATA) = val; } } else if (ch1 == 'w') { p = parse_u32(linebuf + 1, &val); if (val > MAX_SLOTS) { pp = "*BAD*\n"; } else { u32 rgb_data; p = parse_u24(p, &rgb_data); write_data(current_universe, val, rgb_data); } } else if (ch1 == 'l') { /* * Tell PRU1 to update the LED strings */ SIGNAL_EVENT(SYSEV_THIS_PRU_TO_OTHER_PRU); } else { pp = "*BAD*\n"; } c_puts(pp); } PT_YIELD(pt); PT_END(pt); }
static int event_thread(struct pt *pt) { static struct pru_vring_elem pvre; static u16 idx, count; static u32 rx_len, len; struct vring_desc *vrd; static char *ptr; PT_BEGIN(pt); for (;;) { /* wait until we get the indication */ PT_WAIT_UNTIL(pt, /* pru_signal() && */ (PINTC_SRSR0 & SYSEV_THIS_PRU_INCOMING_MASK) != 0); /* downcall from the host */ if (PINTC_SRSR0 & BIT(SYSEV_ARM_TO_THIS_PRU)) { PINTC_SICR = SYSEV_ARM_TO_THIS_PRU; PT_WAIT_UNTIL(pt, !(PINTC_SRSR0 & BIT(SYSEV_THIS_PRU_TO_OTHER_PRU))); sc_downcall(handle_downcall); } if (PINTC_SRSR0 & BIT(SYSEV_VR_ARM_TO_THIS_PRU)) { PINTC_SICR = SYSEV_VR_ARM_TO_THIS_PRU; while (pru_vring_pop(&rx_ring, &pvre)) { /* process the incoming buffers (??? not used) */ if ((count = pvre.in_num) > 0) { idx = pvre.in_idx; while (count-- > 0) { vrd = pru_vring_desc(&rx_ring, idx); ptr = pa_to_da(vrd->addr); idx++; } } rx_len = 0; /* process the outgoing buffers (this is our RX) */ if (pvre.out_num > 0) { idx = pvre.out_idx; count = pvre.out_num; while (count-- > 0) { vrd = pru_vring_desc(&rx_ring, idx); ptr = pa_to_da(vrd->addr); len = vrd->len; /* put it in the rx buffer (can yield) */ while (len-- > 0) RX_IN(*ptr++); rx_len += vrd->len; idx++; } } pru_vring_push(&rx_ring, &pvre, rx_len); PT_WAIT_UNTIL(pt, !(PINTC_SRSR0 & BIT(SYSEV_VR_THIS_PRU_TO_ARM))); /* VRING PRU -> ARM */ SIGNAL_EVENT(SYSEV_VR_THIS_PRU_TO_ARM); } } if (PINTC_SRSR0 & BIT(SYSEV_OTHER_PRU_TO_THIS_PRU)) { PINTC_SICR = SYSEV_OTHER_PRU_TO_THIS_PRU; } } /* get around warning */ PT_YIELD(pt); PT_END(pt); }
/*******************************************************************************//** * CC2420 thread proc **********************************************************************************/ PROC CC2420_ThreadProc(PARAM Param) { uint16_t Val; uint8_t i,LQI,Byte; int8_t RSSIVal; // request data if(CC2420_OPERATION_IS(PHY_OPERATION_REQUEST_DATA)) { CC2420_STOP_OPERATION(PHY_OPERATION_REQUEST_DATA) // if transmitter is off signal error if(CC2420Defs.State<=CC2420_STATE_IDLE) { SIGNAL_EVENT(PHYLayer_DATA_Confirm(PHY_TRX_OFF)) } // if transmitter is in rx state signal error else if(CC2420Defs.State==CC2420_STATE_RX|| CC2420Defs.State==CC2420_STATE_RX_GOT_SFD|| CC2420Defs.State==CC2420_STATE_RX_REJECT_ALL) { SIGNAL_EVENT(PHYLayer_DATA_Confirm(PHY_RX_ON)) } // everithing is fine, send data else { // if there was tx underflow, then flush tx fifo if(CC2420_SendCommandStrobe(CC2420_SNOP)&(1<<CC2420_STATUS_TX_UNDERFLOW)) { // flush tx buffer CC2420_SendCommandStrobe(CC2420_SFLUSHTX); } // write data to tx fifo SPI_Start(CC2420Defs.SPI); SPI_TxRx(CC2420Defs.SPI,CC2420_TXFIFO,NULL); #ifdef PHY_LAYER_HANDLE_CHECKSUM SPI_TxRx(CC2420Defs.SPI,CC2420Defs.TxLen+2,&Byte); #else SPI_TxRx(CC2420Defs.SPI,CC2420Defs.TxLen,&Byte); #endif for(i=0;i<CC2420Defs.TxLen;++i) { SPI_TxRx(CC2420Defs.SPI,CC2420Defs.TxData[i],NULL); } SPI_Stop(CC2420Defs.SPI); // if there was rx fifo overflow, then flush rx fifo twice if(CC2420_GetRxFIFOOverflow()) { CC2420_SendCommandStrobe(CC2420_SFLUSHRX); CC2420_SendCommandStrobe(CC2420_SFLUSHRX); } // begin transmission CC2420Defs.State = CC2420_STATE_TX; CC2420_SendCommandStrobe(CC2420_STXON); } } // request CCA if(CC2420_OPERATION_IS(PHY_OPERATION_CCA)) { CC2420_STOP_OPERATION(PHY_OPERATION_CCA) // if TRX is off, then return this state if(CC2420Defs.State<=CC2420_STATE_IDLE) { SIGNAL_EVENT(PHYLayer_CCA_Confirm(PHY_TRX_OFF)) } // if tx is on, then return this state else if(CC2420Defs.State==CC2420_STATE_TX|| CC2420Defs.State==CC2420_STATE_TX_GOT_SFD) { SIGNAL_EVENT(PHYLayer_CCA_Confirm(PHY_TX_ON)) } // check CCA and return its state else if(CC2420_GetCCA()) { SIGNAL_EVENT(PHYLayer_CCA_Confirm(PHY_IDLE)) } else { SIGNAL_EVENT(PHYLayer_CCA_Confirm(PHY_BUSY)) } }
static int prompt_thread(struct pt *pt) { static char ch1; static char *pp; static char linebuf[80]; char *p; static int linesz; u32 val; PT_BEGIN(pt); PWM_CMD->magic = PWM_REPLY_MAGIC; for (;;) { again: c_puts("PRU> "); linesz = sizeof(linebuf); c_readline(linebuf, linesz); c_puts("\n"); if (linesz == 0) goto again; ch1 = linebuf[0]; if (ch1 == '?') { c_puts("Help\n" " h <us> set high in us\n" " l <us> set low in us\n"); } else if (ch1 == 'e' || ch1 == 'd') { /* wait until the command is processed */ PT_WAIT_UNTIL(pt, PWM_CMD->magic == PWM_REPLY_MAGIC); if (ch1 == 'e') PWM_CMD->cmd = PWM_CMD_ENABLE; else PWM_CMD->cmd = PWM_CMD_DISABLE; p = parse_u32(linebuf + 1, &val); PWM_CMD->pwm_nr = val; PWM_CMD->magic = PWM_CMD_MAGIC; SIGNAL_EVENT(SYSEV_THIS_PRU_TO_OTHER_PRU); } else if (ch1 == 'm') { /* wait until the command is processed */ PT_WAIT_UNTIL(pt, PWM_CMD->magic == PWM_REPLY_MAGIC); PWM_CMD->cmd = PWM_CMD_MODIFY; p = parse_u32(linebuf + 1, &val); PWM_CMD->pwm_nr = val; p = parse_u32(p, &val); PWM_CMD->u.hilo[0] = val; p = parse_u32(p, &val); PWM_CMD->u.hilo[1] = val; PWM_CMD->magic = PWM_CMD_MAGIC; SIGNAL_EVENT(SYSEV_THIS_PRU_TO_OTHER_PRU); } else { pp = "*BAD*\n"; } c_puts(pp); } PT_YIELD(pt); PT_END(pt); }