Ejemplo n.º 1
0
int fifoed_avalon_uart_write (fifoed_avalon_uart_state* sp, const char* ptr, int len, int flags)
{
  int block;
  unsigned int status;
  int count;

  block = !(flags & O_NONBLOCK);
  count = len;

  do
  {
    status = IORD_FIFOED_AVALON_UART_STATUS(sp->base);
   
    if (status & FIFOED_AVALON_UART_STATUS_TRDY_MSK)
    {
      IOWR_FIFOED_AVALON_UART_TXDATA(sp->base, *ptr++);
      count--;
    }
  }
  while (block && count);

  if (count)
  {
    ALT_ERRNO = EWOULDBLOCK;
  }

  return (len - count);
}
Ejemplo n.º 2
0
static void fifoed_avalon_uart_irq(void* context, alt_u32 id)
#endif
{
  alt_u32 status;

  fifoed_avalon_uart_state* sp = (fifoed_avalon_uart_state*) context;
  void* base               = sp->base;

  /*
   * Read the status register in order to determine the cause of the
   * interrupt.
   */

  status = IORD_FIFOED_AVALON_UART_STATUS(base);

  /* Clear any error flags set at the device */

  IOWR_FIFOED_AVALON_UART_STATUS(base, 0);

  /* process a read irq */
 
  if (status & FIFOED_AVALON_UART_STATUS_RRDY_MSK)
  {
    fifoed_avalon_uart_rxirq (sp, status);
  }

  /* process a write irq */

  if (status & (FIFOED_AVALON_UART_STATUS_TRDY_MSK | 
                  FIFOED_AVALON_UART_STATUS_DCTS_MSK))
  {
    fifoed_avalon_uart_txirq (sp, status);
  }
}
Ejemplo n.º 3
0
static void fifoed_avalon_uart_rxirq (fifoed_avalon_uart_state* sp,
                                   alt_u32              status)
{
  alt_u32 next;

  /*
   * In a multi-threaded environment, set the read event flag to indicate
   * that there is data ready. This is only done if the circular buffer was
   * previously empty.
   */
// allow to read as many as it can.
// (KN) fix the erronous status check (should be bit-wise AND rather than logical AND)
// while ( IORD_FIFOED_AVALON_UART_STATUS(sp->base) && FIFOED_AVALON_UART_STATUS_RRDY_MSK){
while ( IORD_FIFOED_AVALON_UART_STATUS(sp->base) & FIFOED_AVALON_UART_STATUS_RRDY_MSK){
  if (sp->rx_end == sp->rx_start)
  {
    ALT_FLAG_POST (sp->events, ALT_UART_READ_RDY, OS_FLAG_SET);
  }

  /* Determine which slot to use next in the circular buffer */

  next = (sp->rx_end + 1) & FIFOED_AVALON_UART_BUF_MSK;

  /* Transfer data from the device to the circular buffer */

  sp->rx_buf[sp->rx_end] = IORD_FIFOED_AVALON_UART_RXDATA(sp->base);

  /* If there was an error, discard the data */

// i have left this in tack but it is not necissarily right.
// next version of the fifo will track the errors in the fifo. 

  if (status & (FIFOED_AVALON_UART_STATUS_PE_MSK | 
                  FIFOED_AVALON_UART_STATUS_FE_MSK))
  {
    return;
  }

  sp->rx_end = next;

  next = (sp->rx_end + 1) & FIFOED_AVALON_UART_BUF_MSK;

  /*
   * If the cicular buffer was full, disable interrupts. Interrupts will be
   * re-enabled when data is removed from the buffer.
   */

  if (next == sp->rx_start)
  {
    sp->ctrl &= ~FIFOED_AVALON_UART_CONTROL_RRDY_MSK;
    IOWR_FIFOED_AVALON_UART_CONTROL(sp->base, sp->ctrl);
  }   
}
}
Ejemplo n.º 4
0
int fifoed_avalon_uart_read (fifoed_avalon_uart_state* sp, char* ptr, int len, int flags)
{
  int block;
  unsigned int status;

  block = !(flags & O_NONBLOCK);
  int i=0;
  do
  {
    status = IORD_FIFOED_AVALON_UART_STATUS(sp->base);

    /* clear any error flags */

    IOWR_FIFOED_AVALON_UART_STATUS(sp->base, 0);

    // actually with the new settings you can read up to length. but we will only read until the fifo is empty
    // if that is not what you what then rewrite this function. 

		
      if (status & FIFOED_AVALON_UART_CONTROL_RRDY_MSK)
      {
        ptr[i] = IORD_FIFOED_AVALON_UART_RXDATA(sp->base);
  
 //	not sure what to really do here
 //       if (!(status & (FIFOED_AVALON_UART_STATUS_PE_MSK | 
 //       FIFOED_AVALON_UART_STATUS_FE_MSK)))
 //       {
 //         return 1;
	    i++; // get the next char if needed
	    if( i== len)
		return i;
	    
//        }
      }
      else  // no chars are ready
      {
#if 0  //9.3.1 patch
	if( i>0)  // we have gotten something return it
	{
		return i;
	}
 
    }
  }
  while (block || (i < len));

  ALT_ERRNO = EWOULDBLOCK;
 
  return 0;
}
Ejemplo n.º 5
0
static void fifoed_avalon_uart_txirq (fifoed_avalon_uart_state* sp,
                                   alt_u32              status)
{
  /* Transfer data if there is some ready to be transfered */

  if (sp->tx_start != sp->tx_end)
  {
    /* 
     * If the device is using flow control (i.e. RTS/CTS), then the
     * transmitter is required to throttle if CTS is high.
     */

    if (!(sp->flags & FIFOED_AVALON_UART_FC) ||
      (status & FIFOED_AVALON_UART_STATUS_CTS_MSK))
    { 

      /*
       * In a multi-threaded environment, set the write event flag to indicate
       * that there is space in the circular buffer. This is only done if the
       * buffer was previously empty.
       */

      if (sp->tx_start == ((sp->tx_end + 1) & FIFOED_AVALON_UART_BUF_MSK))
      { 
        ALT_FLAG_POST (sp->events,
                       ALT_UART_WRITE_RDY,
                       OS_FLAG_SET);
      }

      /* Write the data to the device */
      // updated to allow mutiple writes here if the fifos are enabled.
       while ((sp->tx_start != sp->tx_end) &&
          (IORD_FIFOED_AVALON_UART_STATUS(sp->base) & FIFOED_AVALON_UART_STATUS_TRDY_MSK))
          {
              IOWR_FIFOED_AVALON_UART_TXDATA(sp->base, sp->tx_buf[sp->tx_start]);

              sp->tx_start = (++sp->tx_start) & FIFOED_AVALON_UART_BUF_MSK;
          }

      /*
       * In case the tranmit interrupt had previously been disabled by 
       * detecting a low value on CTS, it is reenabled here.
       */ 

      sp->ctrl |= FIFOED_AVALON_UART_CONTROL_TRDY_MSK;
    }
    else
    {
      /*
       * CTS is low and we are using flow control, so disable the transmit
       * interrupt while we wait for CTS to go high again. This will be 
       * detected using the DCTS interrupt.
       *
       * There is a race condition here. "status" may indicate that 
       * CTS is low, but it actually went high before DCTS was cleared on 
       * the last write to the status register. To avoid this resulting in
       * deadlock, it's necessary to re-check the status register here
       * before throttling.
       */
 
      status = IORD_FIFOED_AVALON_UART_STATUS(sp->base);

      if (!(status & FIFOED_AVALON_UART_STATUS_CTS_MSK))
      {
        sp->ctrl &= ~FIFOED_AVALON_UART_CONTROL_TRDY_MSK;
      }
    }
  }

  /*
   * If the circular buffer is empty, disable the interrupt. This will be
   * re-enabled when new data is placed in the buffer.
   */

  if (sp->tx_start == sp->tx_end)
  {
    sp->ctrl &= ~(FIFOED_AVALON_UART_CONTROL_TRDY_MSK |
                    FIFOED_AVALON_UART_CONTROL_DCTS_MSK);
  }

  IOWR_FIFOED_AVALON_UART_CONTROL(sp->base, sp->ctrl);
}
Ejemplo n.º 6
0
Archivo: main.c Proyecto: gri6507/QMS
int main(void)
{
    // Prepare for UART communication with external world. The default baud rate
    // is 921,600 bps
    IOWR_FIFOED_AVALON_UART_DIVISOR(UART_BASE, BAUD_RATE(921600.0f));

    // Make sure UART interrupts are disabled
    alt_ic_irq_disable(UART_IRQ_INTERRUPT_CONTROLLER_ID, UART_IRQ);

    // Clear the input and output buffers
    FlushRx(UART_BASE);
    FlushTx(UART_BASE);
    
    #define MAX_CMD_LEN 64
    char cmd[MAX_CMD_LEN];
    s8 cmdIndex = 0;

    // Sit in an infinite loop waiting for serial commands
    while(1)
    {
        while (IORD_FIFOED_AVALON_UART_STATUS(UART_BASE) & FIFOED_AVALON_UART_CONTROL_RRDY_MSK)
        {
            // Read the Uart
            char rx = IORD_FIFOED_AVALON_UART_RXDATA(UART_BASE);
            
            // If this is the end of a command, then try to parse it
            if (('\r' == rx) || ('\n' == rx))
            {
                cmd[cmdIndex] = '\0';
                ExecuteCmd(cmd, UART_BASE);
                FlushRx(UART_BASE);
                FlushTx(UART_BASE);
                cmdIndex = 0;
            }
            
            // If this is a backspace
            else if ('\b' == rx)
            {
                SendStr("\b \b", UART_BASE);
                if (cmdIndex > 0)
                    cmdIndex--;
            }
            
            // This is any other character
            else
            {
                // echo the character
                SendChar(rx, UART_BASE);
                
                // Add it to the buffer, if possible, making sure to save the 
                // space for the null terminator (when completing the command)
                if (cmdIndex < (MAX_CMD_LEN - 1))
                    cmd[cmdIndex++] = rx;
                
                // Otherwise, report the error and reset the buffer
                else
                {
                    cmdIndex = 0;
                    SendStr(NO_ANSWER, UART_BASE);
                }
            }
        }
    }
}
Ejemplo n.º 7
0
Archivo: main.c Proyecto: gri6507/QMS
static void ExecuteCmd(const char const *input, const u32 base)
{
    SendStr("\r\n", base);
    
    // Tokenize the command
    #define MAX_CMD_WORDS 4
    char *token[MAX_CMD_WORDS];
    char *cmd = (char *)input;
    u8 numTokens = 0;
    while (1)
    {
        // Skip leading whitespace.
        while ((*cmd) && isspace(*cmd))
            cmd++;

        // If we get here and we are at the end of the string, then the last
        // token must have had trailing white spaces. Let's ignore them
        if (!(*cmd))
            break;

        // If we have exceeded the maximum number of allowable tokens, then
        // return as error
        if (numTokens >= MAX_CMD_WORDS)
        {
            SendStr(NO_ANSWER, base);
            return;
        }

        // Store the token.
        token[numTokens] = cmd;
        numTokens++;

        // Everything that isn't a whitespace is part of the token. Let's make
        // sure it is in UPPER CASE
        while ((*cmd) && (!isspace(*cmd)))
        {
            *cmd = toupper(*cmd);
            cmd++;
        }

        // When we get here, we are just past the current token, either because
        // it ended on a whitespace or because it is the end of the user input.
        // If the former, then let's force a null termination for that token. If
        // the latter, then we are done tokenizing.
        if (!(*cmd))
            break;
        *cmd = '\0';
        cmd++;
    }
    
    if (0 == numTokens)
    {
        SendStr(NO_ANSWER, base);
        return;
    }
    
    // Process the command
    switch (token[0][0])
    {
        case 'R':
        {
            if (2 != numTokens)
                SendStr(NO_ANSWER, base);
            else
            {
                u32 regAddr;
                u32 regValue;
                if (StrToU32(token[1], &regAddr) && RegRead(regAddr, &regValue))
                {
                    SendStr("Y ", base);
                    char regValStr[9];
                    U32ToStr(regValue, regValStr);
                    SendStr(regValStr, base);
                    SendStr("\r\n", base);
                }
                else
                    SendStr(NO_ANSWER, base);
            }
            break;
        }
            
        case 'W':
        {
            if (3 != numTokens)
                SendStr(NO_ANSWER, base);
            else
            {
                u32 regAddr;
                u32 regValue;
                if (StrToU32(token[1], &regAddr) && StrToU32(token[2], &regValue) && RegWrite(regAddr, regValue))
                    SendStr(YES_ANSWER, base);
                else
                    SendStr(NO_ANSWER, base);
            }
            break;
        }
        
        case 'V':
        {
            SendStr("FPGA=0x", base);
            char versionStr[9];
            FpgaRegisters * FPGARegs = (FpgaRegisters *)(REGISTER_BASE | BYPASS_DCACHE_MASK);
            U32ToStr(FPGARegs->fpgaVersion, versionStr);
            SendStr(versionStr, base);
            SendStr(" NIOS=0x", base);
            U32ToStr(NIOS_VERSION, versionStr);
            SendStr(versionStr, base);
            SendStr("\r\n", base);
            break;
        }

        case 'F':
        {
            if (4 != numTokens)
                SendStr(NO_ANSWER, base);
            else
            {
                u32 startAddr;
                u32 length;
                u32 checksum;
                StrToU32(token[1], &startAddr);
                StrToU32(token[2], &length);
                StrToU32(token[3], &checksum);

                // Transfer two chunks to get a full sector worth
				#define FLASH_SECTOR_SIZE (64*1024)
				#define TRANSFER_SIZE     (4*1024)
                u8  buffer[FLASH_SECTOR_SIZE];

                // Validate the requested transfer size
                if (length != TRANSFER_SIZE)
                    SendStr(NO_ANSWER, base);
                else
                {
                    u32 bufferIndex = startAddr % FLASH_SECTOR_SIZE;
                    u32 runningSum = 0;
                    u32 numBytesReceived = 0;

                	// Clear the input buffer
                	FlushRx(base);

                    // Acknowledge that the command is good. This will tell the
                    // sender to actually send the specified number of bytes
                    SendStr(YES_ANSWER, base);

                    // We must receive the correct number of bytes
                    while (true)
                    {
                    	while (IORD_FIFOED_AVALON_UART_STATUS(base) & FIFOED_AVALON_UART_CONTROL_RRDY_MSK)
                    	{
							// Read the Uart
							u8 rx = IORD_FIFOED_AVALON_UART_RXDATA(base);
							runningSum += rx;
							buffer[bufferIndex++] = rx;
							numBytesReceived++;
	                        if (numBytesReceived >= length)
	                            break;
                    	}
                        if (numBytesReceived >= length)
                            break;
                    }

                    // check the checksum
                    if (runningSum != checksum)
                        SendStr(NO_ANSWER, base);
                    else
                    {
                    	// If we don't have a full sector worth of data, then ACK and wait for more
                    	if (bufferIndex != FLASH_SECTOR_SIZE)
                    		SendStr(YES_ANSWER, base);
                    	else
                    	{
                    		u32 totalWriteBufferChecksum = 0;
                    		int i;
                    		for (i=0; i<sizeof(buffer); i++)
                    		{
                    			totalWriteBufferChecksum += buffer[i];
                    		}

							alt_flash_fd* fd = alt_flash_open_dev(SERIAL_FLASH_NAME);
							if (NULL == fd)
								SendStr(NO_ANSWER, base);
							else
							{
								u32 sectorStartAddr = (startAddr / FLASH_SECTOR_SIZE) * FLASH_SECTOR_SIZE;
								if (0 == alt_write_flash(fd, sectorStartAddr, buffer, length))
								{
									memset(buffer, 0x99, sizeof(buffer));
									if (0 == alt_read_flash(fd, sectorStartAddr, buffer, sizeof(buffer)))
									{
			                    		u32 totalReadBufferChecksum = 0;
			                    		for (i=0; i<sizeof(buffer); i++)
			                    		{
			                    			totalReadBufferChecksum += buffer[i];
			                    		}
			                    		if (totalReadBufferChecksum == totalWriteBufferChecksum)
											SendStr(YES_ANSWER, base);
			                    		else
											SendStr(NO_ANSWER, base);
									}
		                    		else
										SendStr(NO_ANSWER, base);
								}
								else
									SendStr(NO_ANSWER, base);

								alt_flash_close_dev(fd);
							}
                    	}
                    }
                }
            }

            break;
        }
            
        default:
            SendStr(NO_ANSWER, base);
            break;
    }
    
    return;
}