📄 altera_avalon_uart_init.c
字号:
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* *
******************************************************************************/
#include <fcntl.h>
#include "sys/alt_dev.h"
#include "sys/alt_irq.h"
#include "sys/ioctl.h"
#include "sys/alt_errno.h"
#include "altera_avalon_uart.h"
#include "altera_avalon_uart_regs.h"
/*software FSM(finite state machine)*/
/*function pointer array*/
#define _start 0x7e
#define _end 0x7d
unsigned char length;
unsigned char commond;
unsigned char data[20];
unsigned char verify;
unsigned char rd_buffer;
unsigned char state=1;
unsigned char length2;
unsigned char write_ok[]={0x7e,0x01,0x01,0x02,0x7d};
unsigned char write_fail[]={0x7e,0x01,0x02,0x03,0x7d};
/*state:1*/
int s_syn(altera_avalon_uart_state* sp)
{
length=0;
commond=0;
data[20];
verify=0;
length2=0;
altera_avalon_uart_read2(sp,&rd_buffer,1);
if (rd_buffer==_start)
{state=2;}
else
{state=1;}
}
/*state:2*/
int s_len(altera_avalon_uart_state* sp)
{
if(altera_avalon_uart_read2(sp,&rd_buffer,1)==1)
{
length=rd_buffer;
verify=rd_buffer;
state=3;
}
else
{
return;
}
}
/*state:3*/
int s_data(altera_avalon_uart_state* sp)
{
if (length2<length)
{
altera_avalon_uart_read2(sp,&rd_buffer,1);
verify+=rd_buffer;
data[length2]=rd_buffer;
length2++;
}
else
{
state=4;
}
}
/*state:4*/
int s_verify(altera_avalon_uart_state* sp)
{
altera_avalon_uart_read2(sp,&rd_buffer,1);
if(rd_buffer==verify)
{state=5;}
else
{state=1;}
}
/*state:5*/
int s_end(altera_avalon_uart_state* sp)
{
altera_avalon_uart_read2(sp,&rd_buffer,1);
if(rd_buffer==_end)
{state=6;}
else
{state=7;}
}
/*state:6*/
int s_modify_fifo(altera_avalon_uart_state* sp)
{
int i,next;
next=(sp->fifo_end+1)&protocol_buf_depth_mask;
if(next == sp->fifo_start) /*fifo buf is full*/
{state=1;}
else
{
sp->fifo[sp->tx_end][0]=length;
for(i=1;i<=length;i++)
{
sp->fifo[sp->tx_end][i]=data[i];
}
sp->fifo_end = next;
}
state=1;
}
/*state:7*/
int s_retx(altera_avalon_uart_state* sp)
{
altera_avalon_uart_write2(sp,&write_fail,5);
state=1;
}
int (*fsm[7])(altera_avalon_uart_state*)={s_syn,s_len,s_data,s_verify,s_end,s_modify_fifo,s_retx};
//fsm[0]={s_syn,s_len(sp),s_data(sp),s_verify(sp),s_end(sp),s_modify_fifo(sp),s_retx(sp)};
//int s_syn(altera_avalon_uart_state*);
//int s_len(altera_avalon_uart_state*);
//int s_data(altera_avalon_uart_state*);
//int s_verify(altera_avalon_uart_state*);
//int s_end(altera_avalon_uart_state*);
//int s_modify_fifo(altera_avalon_uart_state*);
//int s_retx(altera_avalon_uart_state*);
/*define the protocol start and end word*/
/*used to count the commond and the data byte readed*/
unsigned int prl_com;
unsigned int newduanzu;
int
altera_avalon_uart_read2(altera_avalon_uart_state* sp, char* ptr, int len)
{
alt_irq_context context;
int block;
alt_u32 next;
int count = 0;
/*
* Construct a flag to indicate whether the device is being accessed in
* blocking or non-blocking mode.
*/
/*block = !(flags & O_NONBLOCK);*/
block =1;
/*
* When running in a multi threaded environment, obtain the "read_lock"
* semaphore. This ensures that reading from the device is thread-safe.
*/
ALT_SEM_PEND (sp->read_lock, 0);
/*
* Calculate which slot in the circular buffer is the next one to read
* data from.
*/
next = (sp->rx_start + 1) & ALT_AVALON_UART_BUF_MSK;
/*
* Loop, copying data from the circular buffer to the destination address
* supplied in "ptr". This loop is terminated when the required number of
* bytes have been read. If the circular buffer is empty, and no data has
* been read, then the loop will block (when in blocking mode).
*
* If the circular buffer is empty, and some data has already been
* transferred, or the device is being accessed in non-blocking mode, then
* the loop terminates without necessarily reading all the requested data.
*/
// do
// {
/*
* Read the required amount of data, until the circular buffer runs
* empty
*/
while ((count < len) && (sp->rx_start != sp->rx_end))
{
count++;
*ptr++ = sp->rx_buf[sp->rx_start];
sp->rx_start = (++sp->rx_start) & ALT_AVALON_UART_BUF_MSK;
}
/*
* If no data has been transferred, the circular buffer is empty, and
* this is not a non-blocking access, block waiting for data to arrive.
*/
if (!count && (sp->rx_start == sp->rx_end))
{
if (!block)
{
/* Set errno to indicate the reason we're not returning any data */
ALT_ERRNO = EWOULDBLOCK;
// break;
}
else
{
/* Block waiting for some data to arrive */
/* First, ensure read interrupts are enabled to avoid deadlock */
context = alt_irq_disable_all ();
sp->ctrl |= ALTERA_AVALON_UART_CONTROL_RRDY_MSK;
IOWR_ALTERA_AVALON_UART_CONTROL(sp->base, sp->ctrl);
alt_irq_enable_all (context);
/*
* When running in a multi-threaded mode, we pend on the read event
* flag set in the interrupt service routine. This avoids wasting CPU
* cycles waiting in this thread, when we could be doing something more
* profitable elsewhere.
*/
ALT_FLAG_PEND (sp->events,
ALT_UART_READ_RDY,
OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
0);
}
}
// }
// while (!count && len);
/*
* Now that access to the circular buffer is complete, release the read
* semaphore so that other threads can access the buffer.
*/
ALT_SEM_POST (sp->read_lock);
/*
* Ensure that interrupts are enabled, so that the circular buffer can
* re-fill.
*/
context = alt_irq_disable_all ();
sp->ctrl |= ALTERA_AVALON_UART_CONTROL_RRDY_MSK;
IOWR_ALTERA_AVALON_UART_CONTROL(sp->base, sp->ctrl);
alt_irq_enable_all (context);
/* Return the number of bytes read */
return count;
}
int
altera_avalon_uart_write2(altera_avalon_uart_state* sp, const char* ptr, int len)
{
alt_irq_context context;
int no_block;
alt_u32 next;
int count = len;
/*
* Construct a flag to indicate whether the device is being accessed in
* blocking or non-blocking mode.
*/
/*no_block = (flags & O_NONBLOCK);*/
no_block =0;
/*
* When running in a multi threaded environment, obtain the "write_lock"
* semaphore. This ensures that writing to the device is thread-safe.
*/
ALT_SEM_PEND (sp->write_lock, 0);
/*
* Loop transferring data from the input buffer to the transmit circular
* buffer. The loop is terminated once all the data has been transferred,
* or, (if in non-blocking mode) the buffer becomes full.
*/
while (count)
{
/* Determine the next slot in the buffer to access */
next = (sp->tx_end + 1) & ALT_AVALON_UART_BUF_MSK;
/* block waiting for space if necessary */
if (next == sp->tx_start)
{
if (no_block)
{
/* Set errno to indicate why this function returned early */
ALT_ERRNO = EWOULDBLOCK;
break;
}
else
{
/* Block waiting for space in the circular buffer */
/* First, ensure transmit interrupts are enabled to avoid deadlock */
context = alt_irq_disable_all ();
sp->ctrl |= (ALTERA_AVALON_UART_CONTROL_TRDY_MSK |
ALTERA_AVALON_UART_CONTROL_DCTS_MSK);
IOWR_ALTERA_AVALON_UART_CONTROL(sp->base, sp->ctrl);
alt_irq_enable_all (context);
/* wait for space to come free */
do
{
/*
* When running in a multi-threaded mode, we pend on the write event
* flag set in the interrupt service routine. This avoids wasting CPU
* cycles waiting in this thread, when we could be doing something
* more profitable elsewhere.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -