void ADCInit(void) { int channel; /* Only init once */ if (ADC_Buffer) return; /* Enable clock int PMC and reset ADC */ outr(PMC_PCER, _BV(ADC_ID)); // Enable ADC clock in PMC outr(ADC_CR, ADC_SWRST); // Reset bus outr(ADC_CR, 0x00); /* Basic configuration: Disable all channels and set mode and prescaler */ outr(ADC_CHDR, ADC_CH0 | ADC_CH1 | ADC_CH2 | ADC_CH3 | ADC_CH4 | ADC_CH5 | ADC_CH6 | ADC_CH7); ADCSetMode(AT91_ADC_INITIAL_MODE); ADCSetPrescale(AT91_ADC_INITIAL_PRESCALE); /* Init adc buffers. One for every channel as we can sample all by automatic sequence */ ADC_Buffer = NutHeapAlloc(sizeof(uint16_t *) * ADC_MAX_CHANNEL); for (channel = 0; channel < ADC_MAX_CHANNEL; channel ++) { ADC_Buffer[channel] = NutHeapAlloc(sizeof(uint16_t) * AT91_ADC_BUF_SIZE + 2); ADC_Buffer[channel][_adc_buf_head] = 0; ADC_Buffer[channel][_adc_buf_tail] = 0; } if (NutRegisterIrqHandler(&sig_ADC, ADCInterrupt, NULL)) { // We do not free buffer as this would cost ROM and is not likely return; } NutIrqEnable(&sig_ADC); }
/*! * \brief Create a new system timer. * * Applications should not call this function. * * \param ticks Specifies the timer interval in system ticks. * \param callback Identifies the function to be called on each * timer interval. * \param arg The argument passed to the callback function. * \param flags If set to TM_ONESHOT, the timer will be stopped * after the first interval. Set to 0 for periodic * timers. * * \return Timer handle if successfull, 0 otherwise. The handle * may be used to release the timer by calling TimerStop. * * \todo Make this local function static or directly integrate it into * NutTimerStartTicks(). */ NUTTIMERINFO * NutTimerCreate(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags) { NUTTIMERINFO *tn; tn = NutHeapAlloc(sizeof(NUTTIMERINFO)); if (tn) { tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume; /* * Periodic timers will reload the tick counter on each timer * intervall. */ if (flags & TM_ONESHOT) { tn->tn_ticks = 0; } else { tn->tn_ticks = ticks; } /* Set callback and callback argument. */ tn->tn_callback = callback; tn->tn_arg = arg; } #ifdef NUTDEBUG if (__os_trf) fprintf(__os_trs, " TIM %p NutTimerCreate\n", tn); #endif return tn; }
/*! * \brief Initialize TWI interface bus. * * The specified slave address is not used here as we don't support twi-slave * on the bitbanging interface * * \param sla Slave address, must be specified as a 7-bit address, * always lower than 128. */ int NutRegisterTwiBus( NUTTWIBUS *bus, uint8_t sla ) { int rc = 0; NUTTWIICB *icb = NULL; /* Check if bus was already registered */ if( bus->bus_icb) { return 0; } /* Allocate ICB for this bus */ icb = NutHeapAlloc(sizeof(NUTTWIICB)); if( icb == NULL) { return rc; } memset( icb, 0, sizeof(NUTTWIICB)); /* Link bus and ICB */ bus->bus_icb = icb; /* Initialize interface hardware */ if (bus->bus_initbus) { rc = bus->bus_initbus(); } /* Initialize mutex semaphores. */ NutEventPost(&bus->bus_mutex); return rc; }
static int NutNetBufAllocData(NBDATA * nbd, u_short size) { if ((nbd->vp = NutHeapAlloc(size)) == 0) { nbd->sz = 0; return -1; } nbd->sz = size; return 0; }
/*! * \brief Allocate memory. * * \param unSize [in] Amount of memory to allocate. * * \return pointer to the allocated memory. * NULL if there is no memory left or you requested 0 size. */ void *MyMalloc(unsigned int unSize) { void *pResult = NULL; if ((unSize != 0) && ((pResult = NutHeapAlloc(unSize)) == NULL)) { LogMsg_P(LOG_ERR, PSTR("No memory [%u]"), unSize); } return (pResult); }
/*! * \brief Write argument list to a stream using a given format. * * Similar to vfprintf() except that the format string is located in * program memory. * * \param stream Pointer to a previously opened stream. * \param fmt Format string in program space containing conversion * specifications. * \param ap List of arguments. * * \return The number of characters written or a negative value to * indicate an error. */ int vfprintf_P(FILE * stream, PGM_P fmt, va_list ap) { int rc; char *rp; size_t rl; rl = strlen_P(fmt) + 1; if ((rp = NutHeapAlloc(rl)) == 0) return -1; memcpy_P(rp, fmt, rl); rc = _putf(_write, stream->iob_fd, rp, ap); NutHeapFree(rp); return rc; }
/*! * \brief Initialize the segmented buffer. * * \param size Number of bytes to allocate for the global buffer. * In systems with banked memory this parameter is * ignored and all banked memory is occupied for the * global buffer. In systems without banked memory, * the specified number of bytes is taken from heap * memory. * * \return Pointer to the first buffer segment or null on failures. */ char *NutSegBufInit(size_t size) { #if NUTBANK_COUNT segbuf_start = (char *)(NUTBANK_START); segbuf_end = (char *)(NUTBANK_START) + NUTBANK_SIZE; segbuf_total = (uint32_t) NUTBANK_COUNT *(uint32_t) NUTBANK_SIZE; #else if (size == 0) size = NutHeapAvailable() / 2; if (segbuf_start) { NutHeapFree(segbuf_start); } if ((segbuf_start = NutHeapAlloc(size)) != NULL) segbuf_end = segbuf_start + size; segbuf_total = size; #endif return NutSegBufReset(); }
int WlanInit(NUTDEVICE * dev) { int nError = ERROR; /* * Check if this is the first call. * Only one init allowed. */ if (dev->dev_dcb == NULL) { dev->dev_dcb = NutHeapAlloc(sizeof(WI_SOFTC)); /* * Have we got the memory ? */ if (dev->dev_dcb != NULL) { /* * Clear NICINFO structure. */ memset(dev->dev_dcb, 0, sizeof(WI_SOFTC)); /* * Check if a card is available */ nError = wlandrv_ProbeDevice(); if (nError == OK) { /* * Check if we can attach the card */ if (wlandrv_Attach(dev) != OK) { nError = ERROR; } else { /* * Now we have all the information, * and can start the device. */ wlandrv_Init(dev); } /* endif wi_attach(dev->dev_dcb) != OK */ } /* HardwareReset() */ } /* endif dev->dev_dcb != NULL */ } /* check first call, dev->dev_dcb == NULL */ return (nError); }
int NutTraceInit(int size, char mode) { if (!trace_isinit) { // start timer1 at CPU frequency/8 and register interrupt service routine outb(TCCR1B, 2); NutRegisterIrqHandler(&sig_OVERFLOW1, NutTraceTimer1IRQ, 0); sbi(TIMSK, TOIE1); trace_isinit = 1; } if (size==0) { size = TRACE_SIZE_DEFAULT; } if (size != trace_size) { // current buffer is not of size that is wanted if (trace_items != 0) { // but memory is already allocated -> free old buffer NutHeapFree(trace_items); } // allocate buffer trace_items = (t_traceitem *)NutHeapAlloc(size * sizeof(t_traceitem)); if (trace_items == 0) { // failed return trace_size = 0; } else { trace_size = size; } } // if (mode == TRACE_MODE_OFF) { // // if terminal-cmd "trace size <val>" is called trace is started in // // default mode // mode = TRACE_MODE_DEFAULT; // } trace_mode = mode; NutTraceClear(); return trace_size; }
/*! * \brief Initialize TWI interface. * * The specified slave address is not used here as we don't support twi-slave * on this architecture for now. * * \param sla Slave address, must be specified as a 7-bit address, * always lower than 128. */ int NutRegisterTwiBus( NUTTWIBUS *bus, uint8_t sla ) { int rc = -1; uint32_t speed = 80000; /* Errata Doc 14574 Rev. 9 Chapter 2.11: Avoid 88kHz to 100kHz */ // uint16_t tmpreg = 0; I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base; NUTTWIICB *icb = NULL; DBGP1_INIT(); DBGP2_INIT(); /* Check if bus was already registered */ if( bus->bus_icb) { return 0; } /* Allocate ICB for this bus */ icb = NutHeapAlloc(sizeof(NUTTWIICB)); if( icb == NULL) { return rc; } memset( icb, 0, sizeof(NUTTWIICB)); /* Link bus and ICB */ bus->bus_icb = icb; if( NutRegisterIrqHandler( bus->bus_sig_ev, TwEventIrq, bus ) ) { free( icb); return rc; } if( NutRegisterIrqHandler( bus->bus_sig_er, TwErrorIrq, bus ) ) { free( icb); return rc; } /* Initialize GPIO Hardware */ if( bus->bus_initbus != NULL) { rc = bus->bus_initbus(); } if( rc) { return rc; } /* Disable and reset this bus */ I2Cx->CR1 &= ~I2C_CR1_PE; I2Cx->CR1 |= I2C_CR1_SWRST; I2Cx->CR1 &= ~I2C_CR1_SWRST; #ifdef I2C_DEFAULT_SPEED if( bus->bus_base == I2C1_BASE) speed = I2CBUS1_DEFAULT_SPEED*1000UL; #endif #ifdef I2CBUS2_DEFAULT_SPEED if( bus->bus_base == I2C2_BASE) speed = I2CBUS2_DEFAULT_SPEED*1000UL; #endif /* Set initial rate. */ if( (rc = NutTwiSetSpeed( bus, speed))) { return rc; } /* Setup 7-Bit Addressing Mode not acknowledged */ I2Cx->OAR1 = 0x4000; /* FIXME: OAR1 Bit 14 is reserved */ #if 0 /* Setup CR1 */ tmpreg = I2Cx->CR1; tmpreg &= ~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE|I2C_CR1_PEC); tmpreg |= I2C_CR1_ACK; // TODO: Set SMBTYPE and SMBUS bits I2Cx->CR1 = tmpreg; /* Setup Interrupts */ tmpreg = I2Cx->CR2; tmpreg |= (I2C_CR2_ITBUFEN|I2C_CR2_ITEVTEN|I2C_CR2_ITERREN); I2Cx->CR2 = tmpreg; #endif I2Cx->CR1 = I2C_CR1_PE; // TODO: Slave Address Setup NutIrqSetPriority(bus->bus_sig_ev, 0); rc = NutIrqEnable(bus->bus_sig_ev); if( rc) { return rc; } NutIrqSetPriority(bus->bus_sig_er, 1); rc = NutIrqEnable(bus->bus_sig_er); if( rc) { return rc; } /* Initialize mutex semaphores. */ NutEventPost(&bus->bus_mutex); return rc; }
/*! \fn AhdlcRx(void *arg) * \brief Asynchronous HDLC receiver thread. * * * Running at high priority. */ THREAD(AhdlcRx, arg) { NUTDEVICE *dev = arg; NUTDEVICE *netdev; AHDLCDCB *dcb = dev->dev_dcb; IFNET *ifn; NETBUF *nb; uint8_t *rxbuf; uint8_t *rxptr; uint16_t rxcnt; uint8_t ch; uint16_t tbx; uint8_t inframe; uint8_t escaped; uint16_t rxfcs; NutThreadSetPriority(9); for (;;) { /* * Reset variables to their initial state */ rxptr = 0; rxcnt = 0; escaped = 0; rxfcs = AHDLC_INITFCS; inframe = 0; for (;;) { /* * Wait until the network interface has been attached. * This will be initiated by the application calling * NutNetIfConfig(), which in turn calls a HDLC_SETIFNET * ioctl() to store the NUTDEVICE pointer of the network * device in dev_icb and trigger an event on dcb_mf_evt. */ while ((netdev = dev->dev_icb) == 0) { if (NutEventWait(&dcb->dcb_mf_evt, 1000) == 0) { NutSleep(100); } } ifn = netdev->dev_icb; dcb->dcb_rtimeout = 1000; inframe = 0; /* * Allocate the receive buffer, if this fails, we are in a * low memory situation. Take a nap and see, if the * situation improved. */ if ((rxbuf = NutHeapAlloc(dcb->dcb_rx_mru)) != 0) { break; } NutSleep(1000); } /* * Signal the link driver that we are up. */ ifn->if_send = AhdlcOutput; netdev->dev_ioctl(netdev, LCP_LOWERUP, 0); for (;;) { /* * If we are still connected to a network, fetch the next * character from the buffer. */ while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) { if (dev->dev_icb == 0) break; // TODO: Check for idle timeout. if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) { continue; } } /* * Leave loop if network interface is detached */ if (dev->dev_icb == 0) break; /* * If RAW mode is active, we are not allowing any data encapsulation * processing. So we just sleep for a while. */ if (dcb->dcb_modeflags & UART_MF_RAWMODE) { /* * It is a must to sleep here, because if we just yield it could create * too much processing in here and stall processing elsewhere. This gives * opportunity to other threads to process incoming data from USART. */ NutSleep(100); continue; } /* * Read next character from input buffer */ ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++]; if (inframe) { if (ch != AHDLC_FLAG) { if (ch == AHDLC_ESCAPE) { escaped = 1; continue; } if (escaped) { ch ^= AHDLC_TRANS; escaped = 0; } /* * Unless the peer lied to us about the negotiated MRU, * we should never get a frame which is too long. If it * happens, toss it away and grab the next incoming one. */ if (rxcnt++ < dcb->dcb_rx_mru) { /* Update calculated checksum and store character in buffer. */ tbx = (uint16_t) ((uint8_t) rxfcs ^ ch) << 1; rxfcs >>= 8; rxfcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1); *rxptr++ = ch; } else inframe = 0; continue; } if (rxcnt > 6 && rxfcs == AHDLC_GOODFCS) { /* * If the frame checksum is valid, create a NETBUF * and pass it to the network specific receive handler. */ rxcnt -= 2; if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) { memcpy(nb->nb_dl.vp, rxbuf, rxcnt); (*ifn->if_recv) (netdev, nb); } } } /* * If frame flag is received, resync frame processing */ if (ch == AHDLC_FLAG) { inframe = 1; escaped = 0; rxptr = rxbuf; rxcnt = 0; rxfcs = AHDLC_INITFCS; } }
/* * \brief Enable the link layer to come up. * * The underlying hardware driver should have established a physical * connection before calling this function. * * \param name Physical device name optionally followed by username * and password, each separated by a slash. * */ static NUTFILE *NutPppOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc) { NUTFILE *fp; uint8_t i; char *cp; char *sp; char pdn[9]; PPPDCB *dcb = dev->dev_dcb; /* Clear our device control block. */ memset(dcb, 0, sizeof(PPPDCB)); /* Get the first part of the name, it specifies the physical device. */ for (cp = (char *) name, i = 0; *cp && *cp != '/' && i < sizeof(pdn) - 1; i++) { pdn[i] = *cp++; } pdn[i] = 0; /* Open the pysical device. */ if ((dcb->dcb_fd = _open(pdn, _O_RDWR | _O_BINARY)) == -1) { return NUTFILE_EOF; } /* * Allocate a file structure to return. */ if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0) { return NUTFILE_EOF; } fp->nf_next = 0; fp->nf_dev = dev; fp->nf_fcb = 0; /* * Extract user name and password and store it in our device control * block. It will be used later by the authentication layer. */ if (*cp == '/') { for (sp = ++cp, i = 0; *sp && *sp != '/'; sp++, i++); if (i) { dcb->dcb_user = NutHeapAlloc(i + 1); for (sp = (char*)dcb->dcb_user; *cp && *cp != '/';) *sp++ = *cp++; *sp = 0; } if (*cp == '/') { for (sp = ++cp, i = 0; *sp && *sp != '/'; sp++, i++); if (i) { dcb->dcb_pass = NutHeapAlloc(i + 1); for (sp = (char*)dcb->dcb_pass; *cp && *cp != '/';) *sp++ = *cp++; *sp = 0; } } } /* Enable all layers to come up. */ IpcpOpen(dev); return fp; }
/*! * \brief Mount a partition. * * Nut/OS doesn't provide specific routines for mounting. Instead routines * for opening files are used. * * Applications should not directly call this function, but use the high * level stdio routines for opening a file. * * \param dev Pointer to the MMC device. * \param name Partition number followed by a slash followed by a name * of the file system device. Both items are optional. If no * file system driver name is given, the first file system * driver found in the list of registered devices will be * used. If no partition number is specified or if partition * zero is given, the first active primary partition will be * used. * \param mode Opening mode. Currently ignored, but * \code _O_RDWR | _O_BINARY \endcode should be used for * compatibility with future enhancements. * \param acc File attributes, ignored. * * \return Pointer to a newly created file pointer to the mounted * partition or NUTFILE_EOF in case of any error. */ static NUTFILE *At91MciMount(NUTDEVICE * dev, CONST char *name, int mode, int acc) { int partno = 0; int i; NUTDEVICE *fsdev; NUTFILE *nfp; MCIFCB *fcb; DOSPART *part; MCIFC *ifc = (MCIFC *) dev->dev_icb; FSCP_VOL_MOUNT mparm; if (At91MciDiscover(ifc)) { errno = ENODEV; return NUTFILE_EOF; } /* Parse the name for a partition number and a file system driver. */ if (*name) { partno = atoi(name); do { name++; } while (*name && *name != '/'); if (*name == '/') { name++; } } #ifdef NUTDEBUG printf("['%s'-PART%d]", name, partno); #endif /* * Check the list of registered devices for the given name of the * files system driver. If none has been specified, get the first * file system driver in the list. Hopefully the application * registered one only. */ for (fsdev = nutDeviceList; fsdev; fsdev = fsdev->dev_next) { if (*name == 0) { if (fsdev->dev_type == IFTYP_FS) { break; } } else if (strcmp(fsdev->dev_name, name) == 0) { break; } } if (fsdev == 0) { #ifdef NUTDEBUG printf("[No FSDriver]"); #endif errno = ENODEV; return NUTFILE_EOF; } if ((fcb = NutHeapAllocClear(sizeof(MCIFCB))) == 0) { errno = ENOMEM; return NUTFILE_EOF; } fcb->fcb_fsdev = fsdev; /* Initialize MMC access mutex semaphore. */ NutEventPost(&mutex); /* Read MBR. */ if (At91MciReadSingle(ifc, 0, fcb->fcb_blkbuf)) { NutHeapFree(fcb); return NUTFILE_EOF; } /* Read partition table. */ part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS]; for (i = 1; i <= 4; i++) { if (partno) { if (i == partno) { /* Found specified partition number. */ fcb->fcb_part = *part; break; } } else if (part->part_state & 0x80) { /* Located first active partition. */ fcb->fcb_part = *part; break; } part++; } if (fcb->fcb_part.part_type == PTYPE_EMPTY) { NutHeapFree(fcb); return NUTFILE_EOF; } if ((nfp = NutHeapAlloc(sizeof(NUTFILE))) == 0) { NutHeapFree(fcb); errno = ENOMEM; return NUTFILE_EOF; } nfp->nf_next = 0; nfp->nf_dev = dev; nfp->nf_fcb = fcb; /* * Mount the file system volume. */ mparm.fscp_bmnt = nfp; mparm.fscp_part_type = fcb->fcb_part.part_type; if (fsdev->dev_ioctl(fsdev, FS_VOL_MOUNT, &mparm)) { At91MciUnmount(nfp); return NUTFILE_EOF; } return nfp; }