/*! * \brief Listen for incoming data from a master. * * If this function returns without error, the bus is blocked. The caller * must immediately process the request and return a response by calling * TwSlaveRespond(). * * \note This function is only available on ATmega128 systems. The * function is not reentrant. * * \param sla Points to a byte variable, which receives the slave * address sent by the master. This can be used by the * caller to determine whether the the interface has been * addressed by a general call or its individual address. * \param rxdata Points to a data buffer where the received data bytes * are stored. * \param rxsiz Specifies the maximum number of data bytes to receive. * \param tmo Timeout in milliseconds. To disable timeout, * set this parameter to NUT_WAIT_INFINITE. * * \return The number of bytes received, -1 in case of an error or timeout. */ int TwSlaveListen(u_char * sla, void *rxdata, u_short rxsiz, u_long tmo) { #ifndef __AVR_ENHANCED__ return -1; #else int rc = -1; NutEnterCritical(); /* Initialize parameters for slave receive. */ tw_sm_err = 0; tw_sr_siz = rxsiz; tw_sr_buf = rxdata; /* * If the interface is currently not busy then enable it for * address recognition. */ if(tw_if_bsy == 0) { u_char twsr = inb(TWSR); if((twsr & 0xF8) == TW_NO_INFO) { if(tw_mt_len || tw_mr_siz) outb(TWCR, _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA)); else outb(TWCR, _BV(TWEA) | _BV(TWEN) | _BV(TWIE)); } } /* Clear the queue. */ //*broken?! NutEventBroadcastAsync(&tw_sr_que); if (tw_sr_que == SIGNALED) { tw_sr_que = 0; } /* Wait for a frame on the slave mode queue. */ if (NutEventWait(&tw_sr_que, tmo)) { NutEnterCritical(); tw_sm_err = TWERR_TIMEOUT; tw_sr_siz = 0; NutExitCritical(); } NutExitCritical(); /* * Return the number of bytes received and the destination slave * address, if no slave error occured. In this case the bus is * blocked. */ if(tw_sm_err == 0) { rc = tw_sr_idx; *sla = tw_sm_sla; } return rc; #endif /* __AVR_ENHANCED__ */ }
/*! * \brief Execute flash controller command. * */ int Avr32FlashcCmd(unsigned int cmd, uint32_t tmo) { int rc = 0; /* Make sure that the previous command has finished. */ while (!flashc_is_ready()) { if (tmo && --tmo < 1) { return -1; } } /* IRQ handlers are located in flash. Disable them. */ NutEnterCritical(); /* Write command. */ outr(AVR32_FLASHC.fcmd, AVR32_FLASHC_FCMD_KEY_KEY | cmd); /* Wait for ready flag set. */ while (!flashc_is_ready()) { if (tmo && --tmo < 1) { rc = -1; break; } } /* Flash command finished. Re-enable IRQ handlers. */ NutExitCritical(); /* Check result. */ if (AVR32_FLASHC.fsr & (AVR32_FLASHC_FSR_LOCKE_MASK | AVR32_FLASHC_FSR_PROGE_MASK)) { rc = -1; } return rc; }
/*! * \brief Register an interrupt handler. * * This function is typically called by device drivers. * * \param irq Interrupt number to be associated with this handler. * \param handler This routine will be called by Nut/OS, when the * specified interrupt occurs. * \param arg Argument to be passed to the interrupt handler. * * \return 0 on success, -1 otherwise. */ int NutRegisterIrqHandler(uint8_t irq, void (*handler) (void *), void *arg) { if (irq >= IRQ_MAX) return -1; NutEnterCritical(); irq_handlers[irq].ir_arg = arg; irq_handlers[irq].ir_handler = handler; NutExitCritical(); return 0; }
uint32_t NutGetTickCount(void) { uint32_t rc; #ifdef __NUT_EMULATION__ struct timeval timeNow; gettimeofday( &timeNow, NULL ); rc = (timeNow.tv_sec - timeStart.tv_sec) * 1000; rc += (timeNow.tv_usec - timeStart.tv_usec) / 1000; #else NutEnterCritical(); rc = nut_ticks; NutExitCritical(); #endif return rc; }
/* * \return 0 on success, -1 in case of any errors. */ static int SendRawByte(AHDLCDCB * dcb, uint8_t ch, uint8_t flush) { /* * If transmit buffer is full, wait until interrupt routine * signals an empty buffer or until a timeout occurs. */ while ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) { if (NutEventWait(&dcb->dcb_tx_rdy, dcb->dcb_wtimeout)) break; } /* * If transmit buffer is still full, we have a write timeout. */ if ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) { return -1; } /* * Buffer has room for more data. Put the byte in the buffer * and increment the write index. */ dcb->dcb_tx_buf[dcb->dcb_wr_idx] = ch; dcb->dcb_wr_idx++; /* * If transmit buffer has become full and the transmitter * is not active, then activate it. */ if (flush || (uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) { NutEnterCritical(); outr(US1_IER, US_TXRDY); NutExitCritical(); } return 0; }
/*! * \brief Send response to a master. * * This function must be called as soon as possible after TwSlaveListen() * returned successfully, even if no data needs to be returned. Not doing * so will completely block the bus. * * \note This function is only available on ATmega128 systems. * * \param txdata Points to the data to transmit. Ignored, if the * number of bytes to transmit is zero. * \param txlen Number of data bytes to transmit. * \param tmo Timeout in milliseconds. To disable timeout, * set this parameter to NUT_WAIT_INFINITE. * * \return The number of bytes transmitted, -1 in case of an error or timeout. */ int TwSlaveRespond(void *txdata, u_short txlen, u_long tmo) { int rc = -1; #ifdef __AVR_ENHANCED__ /* The bus is blocked. No critical section required. */ tw_st_buf = txdata; tw_st_len = txlen; /* * If there is anything to transmit, start the interface. */ if (txlen) { NutEnterCritical(); /* Clear the queue. */ //*broken?! NutEventBroadcastAsync(&tw_st_que); if (tw_st_que == SIGNALED) { tw_st_que = 0; } /* Release the bus, accepting SLA+R. */ outb(TWCR, TWGO | _BV(TWEA)); NutExitCritical(); if (NutEventWait(&tw_st_que, tmo)) { tw_sm_err = TWERR_TIMEOUT; } NutEnterCritical(); tw_st_len = 0; if (tw_sm_err) { tw_sm_error = tw_sm_err; } else { rc = tw_st_idx; } NutExitCritical(); } /* * Nothing to transmit. */ else { u_char twcr; u_char twsr; rc = 0; /* Release the bus, not accepting SLA+R. */ NutEnterCritical(); twcr = inb(TWCR); twsr = inb(TWSR); /* Transmit start condition, if a master transfer is waiting. */ if (tw_mt_len || tw_mr_siz) { outb(TWCR, TWGO | _BV(TWSTA)); } /* Otherwise enter idle state. */ else { tw_if_bsy = 0; outb(TWCR, TWGO); } NutExitCritical(); } #endif /* __AVR_ENHANCED__ */ return rc; }
/*! * \brief Transmit and/or receive data as a master. * * The two-wire serial interface must have been initialized by calling * TwInit() before this function can be used. * * \note This function is only available on ATmega128 systems. * * \param sla Slave address of the destination. This slave address * must be specified as a 7-bit address. For example, the * PCF8574A may be configured to slave addresses from 0x38 * to 0x3F. * \param txdata Points to the data to transmit. Ignored, if the number * of data bytes to transmit is zero. * \param txlen Number of data bytes to transmit. If zero, then the * interface will not send any data to the slave device * and will directly enter the master receive mode. * \param rxdata Points to a buffer, where the received data will be * stored. Ignored, if the maximum number of bytes to * receive is zero. * \param rxsiz Maximum number of bytes to receive. Set to zero, if * no bytes are expected from the slave device. * \param tmo Timeout in milliseconds. To disable timeout, set this * parameter to NUT_WAIT_INFINITE. * * \return The number of bytes received, -1 in case of an error or timeout. */ int TwMasterTransact(u_char sla, CONST void *txdata, u_short txlen, void *rxdata, u_short rxsiz, u_long tmo) { int rc = -1; #ifdef __AVR_ENHANCED__ /* This routine is marked reentrant, so lock the interface. */ if(NutEventWait(&tw_mm_mutex, 500)) { tw_mm_err = TWERR_IF_LOCKED; NutEventPost(&tw_mm_mutex); return -1; } while(tw_if_bsy) { NutSleep(63); } NutEnterCritical(); /* * Set all parameters for master mode. */ tw_mm_sla = sla << 1; tw_mm_err = 0; tw_mt_len = txlen; tw_mt_buf = txdata; tw_mr_siz = rxsiz; tw_mr_buf = rxdata; /* * Send a start condition if the interface is idle. If busy, then * the interrupt routine will automatically initiate the transfer * as soon as the interface becomes ready again. */ if(tw_if_bsy == 0) { u_char twcr = inb(TWCR); u_char twsr = inb(TWSR); if((twsr & 0xF8) == TW_NO_INFO) { if(tw_sr_siz) { outb(TWCR, _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWSTA) | (twcr & _BV(TWSTO))); } else { outb(TWCR, _BV(TWEN) | _BV(TWIE) | _BV(TWSTA) | (twcr & _BV(TWSTO))); } } } /* Clear the queue. */ //*broken?! NutEventBroadcastAsync(&tw_mm_que); if (tw_mm_que == SIGNALED) { tw_mm_que = 0; } NutExitCritical(); /* * Wait for master transmission done. */ rc = -1; if (NutEventWait(&tw_mm_que, tmo)) { tw_mm_error = TWERR_TIMEOUT; } else { NutEnterCritical(); if (tw_mm_err) { tw_mm_error = tw_mm_err; } else { rc = tw_mr_idx; } NutExitCritical(); } /* * Release the interface. */ NutEventPost(&tw_mm_mutex); #endif /* __AVR_ENHANCED__ */ return rc; }