Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Microblaze+UART
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
shumerok
Добрый день уважаемые форумчане. В моем проекте два UARTа. Один работает по прерыванию с внешним модулем, второй только в режиме передачи выводит информацию на терминал ноута. Внешний модуль ESP8266. Я передаю ему команду "AT" и должен получить в ответ "OK". А я получаю ту же команду, что отправляю. Хотя ESP точно не может отправить обратно ту же команду. Получается, что в приемный буфер попадают данные из передающего. Проект собран в ISE. Код привожу ниже:
CODE
#include <stdio.h>
#include "xparameters.h"
#include "xil_cache.h"
#include "xbasic_types.h"
#include "xgpio.h"
#include "xil_printf.h"
#include "xuartlite.h"
#include "xintc.h"
#include "xil_exception.h"
#include "xtmrctr.h"

#define UART_ESP XPAR_UARTLITE_1_DEVICE_ID
#define UART_RS232 XPAR_UARTLITE_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define UARTLITE_INT_IRQ_ID XPAR_INTC_0_UARTLITE_1_VEC_ID
#define LED_ID XPAR_GPIO_0_DEVICE_ID
#define TMR_ID XPAR_TMRCTR_0_DEVICE_ID

#define TEST_BUFFER_SIZE 6
// Function prototypes

void SendHandler(void *CallBackRef, unsigned int EventData);
void RecvHandler(void *CallBackRef, unsigned int EventData);
int SetupInterruptSystem(XUartLite *UartLitePtr);
void delay_us(Xuint32 Vremay);
void delay_ms(Xuint32 Vremay);

XUartLite UartLiteESP;
XUartLite UartLiteRS;
XIntc InterruptController;
XGpio LedTest;
XTmrCtr Time;

u8 SendBuffer[6] = {65, 84, 92, 114, 92, 110};
u8 ReceiveBuffer[TEST_BUFFER_SIZE];

u8 TotalReceivedCount;
u8 TotalSentCount;

int main()
{
int Status;
int Index;

XTmrCtr_Initialize(&Time, TMR_ID);
XTmrCtr_SetOptions(&Time, 0, XTC_DOWN_COUNT_OPTION);

delay_ms(1000);
delay_ms(1000);

for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {

ReceiveBuffer[Index] = 0;
}

Status = XUartLite_Initialize(&UartLiteESP,UART_ESP);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
Status = XUartLite_Initialize(&UartLiteRS,UART_RS232);
if(Status == XST_SUCCESS)
{
print("UART Init OK\r\n");
}

Status = XGpio_Initialize(&LedTest, LED_ID);
if (Status == XST_SUCCESS)
{
print(" Initialize GPIO OK\r\n");
}

Status = SetupInterruptSystem(&UartLiteESP);
if (Status == XST_SUCCESS) {
print("Setup INT OK\r\n");
}
XUartLite_SetSendHandler(&UartLiteESP, SendHandler, &UartLiteESP);
XUartLite_SetRecvHandler(&UartLiteESP, RecvHandler, &UartLiteESP);
//XUartLite_ResetFifos(&UartLiteESP);
XUartLite_Recv(&UartLiteESP, ReceiveBuffer, TEST_BUFFER_SIZE);
XUartLite_EnableInterrupt(&UartLiteESP);
XUartLite_Send(&UartLiteESP, SendBuffer, 6);
delay_ms(1);
if (TotalSentCount == 6){
TotalSentCount = 0;
print("Send OK\r\n");
}

while(1){

if (TotalReceivedCount != 0) {
print("Recive");
for (Index = 0; Index < TotalReceivedCount; Index++) {

xil_printf(" %c", ReceiveBuffer[Index]);
}
TotalReceivedCount = 0;
}
}

return(0);
}

void SendHandler(void *CallBackRef, unsigned int EventData)
{
TotalSentCount = EventData;
XUartLite_ResetFifos(&UartLiteESP);
}

void RecvHandler(void *CallBackRef, unsigned int EventData)
{
TotalReceivedCount = EventData;
XUartLite_Recv(&UartLiteESP, ReceiveBuffer, TEST_BUFFER_SIZE);

}

void delay_ms(Xuint32 Vremay)
{
XTmrCtr_SetResetValue(&Time, 0, Vremay * 50000);
XTmrCtr_Start(&Time, 0);
while(!(XTmrCtr_IsExpired(&Time, 0))){}
XTmrCtr_Stop(&Time, 0);
}

void delay_us(Xuint32 Vremay)
{
XTmrCtr_SetResetValue(&Time, 0, Vremay * 50);
XTmrCtr_Start(&Time, 0);
while(!(XTmrCtr_IsExpired(&Time, 0))){}
XTmrCtr_Stop(&Time, 0);
}

int SetupInterruptSystem(XUartLite *UartLitePtr)
{

int Status;

/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device.
*/
Status = XIntc_Connect(&InterruptController, UARTLITE_INT_IRQ_ID,
(XInterruptHandler)XUartLite_InterruptHandler,
(void*)UartLitePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the UartLite can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* Enable the interrupt for the UartLite device.
*/
XIntc_Enable(&InterruptController, UARTLITE_INT_IRQ_ID);

/*
* Initialize the exception table.
*/
Xil_ExceptionInit();

/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);

/*
* Enable exceptions.
*/
Xil_ExceptionEnable();

return XST_SUCCESS;
}

Помогите кто чем может).
shumerok
Прошу прощения. Сам дурак. Не те символы в ASCII отправлял. Есть дополнительный вопрос: как в режиме прерывания принимать произвольное кол-во байт (неизвестно заранее кол-во). У меня выход из прерывания не происходит, пока буфер не заполнится.
alexadmin
Цитата(shumerok @ Apr 28 2018, 13:12) *
Прошу прощения. Сам дурак. Не те символы в ASCII отправлял. Есть дополнительный вопрос: как в режиме прерывания принимать произвольное кол-во байт (неизвестно заранее кол-во). У меня выход из прерывания не происходит, пока буфер не заполнится.


Принимать по одному байту, складывать в буфер, выходить из прерывания, ждать следующего прерывания.
AVR
Цитата(shumerok @ Apr 28 2018, 13:12) *
У меня выход из прерывания не происходит, пока буфер не заполнится

Я уже давно с микробом не возился, могу не помнить что-то, но где в RecvHandler сброс флага прерывания? Вроде это руками надо делать, разве нет? Или оно прям виснет в этом обработчике? Так оно и должно там сидеть пока все 6 байт не скушает. Надо по 1 принимать, как правильно выше написали.
shumerok
Цитата(alexadmin @ Apr 28 2018, 14:11) *
Принимать по одному байту, складывать в буфер, выходить из прерывания, ждать следующего прерывания.
Спасибо попробую так.

Цитата(AVR @ Apr 28 2018, 14:15) *
Я уже давно с микробом не возился, могу не помнить что-то, но где в RecvHandler сброс флага прерывания? Вроде это руками надо делать, разве нет? Или оно прям виснет в этом обработчике? Так оно и должно там сидеть пока все 6 байт не скушает. Надо по 1 принимать, как правильно выше написали.

Виснет пока не вычитает буфер. Если принимать по одному, то действительно надо сбрасывать флаг.
shumerok
Побайтный прием организовал. Но вылезла другая проблема. В дебаге и через RUN все работает. Зашиваю релиз - не работает. Процессор в релизе крутится, но данные не принимает. Новый код:
CODE

/*
* code.c
*
* Created on: 04.12.2017
* Author: shumer
*/

#include <stdio.h>
#include "xparameters.h"
#include "xil_cache.h"
#include "xbasic_types.h"

#include "xtmrctr.h"
#include "xuartlite.h"
#include "xintc.h"
#include "xil_exception.h"



#define UARTRS_ID XPAR_UARTLITE_1_DEVICE_ID
#define UARTRS_ESP XPAR_UARTLITE_2_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define UARTLITE_INT_IRQ_ID XPAR_INTC_0_UARTLITE_2_VEC_ID
#define TMR_ID XPAR_TMRCTR_0_DEVICE_ID

#define A 65
#define T 84
#define PLUS 43
#define C 67
#define I 73
#define P 80
#define M 77
#define U 85
#define X 88
#define S 83
#define E 69
#define R 82
#define V 86
#define RAVNO 61
#define ZPT 44


#define TEST_BUFFER_SIZE 1
// Function prototypes


void SendHandler(void *CallBackRef, unsigned int EventData);

void RecvHandler(void *CallBackRef, unsigned int EventData);

int SetupInterruptSystem(XUartLite *UartLitePtr);

void delay_us(Xuint32 Vremay);
void delay_ms(Xuint32 Vremay);


XUartLite UartLiteESP;
XUartLite UartLiteRS;
XIntc InterruptController;

XTmrCtr Time;




u8 SendBuffer[4] = {A,T,13,10};
u8 ReceiveBuffer[TEST_BUFFER_SIZE] = {0};
u8 SendBufferRS[6] = {S,E,R,V,13,10};

static volatile int TotalReceivedCount;
static volatile int TotalSentCount;
int flag = 0;
unsigned int RecvByte;
unsigned int SendByte;
int Count = 0;

int main()
{
int Status;
int Index;
int flagSend = 0;

XTmrCtr_Initialize(&Time, TMR_ID);
XTmrCtr_SetOptions(&Time, 0, XTC_DOWN_COUNT_OPTION);

Status = XUartLite_Initialize(&UartLiteESP,UARTRS_ESP);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}

Status = XUartLite_Initialize(&UartLiteRS,UARTRS_ID);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}

Status = SetupInterruptSystem(&UartLiteESP);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

XUartLite_SetSendHandler(&UartLiteESP, SendHandler, &UartLiteESP);
XUartLite_SetRecvHandler(&UartLiteESP, RecvHandler, &UartLiteESP);
XUartLite_EnableInterrupt(&UartLiteESP);
delay_ms(1000);
XIntc_Acknowledge(&InterruptController, UARTLITE_INT_IRQ_ID);

Index = 0;

XUartLite_Send(&UartLiteESP, SendBuffer, 4);

while(1){

if(flag == 1){

SendBufferRS[0] = ReceiveBuffer[0];
XUartLite_Send(&UartLiteRS, SendBufferRS, 1);


/*if(flagSend != 1){
++Index;
}
else{
Index = 0;
flagSend = 0;
}*/
TotalReceivedCount = 0;
flag = 0;

}

}

return(0);
}


void SendHandler(void *CallBackRef, unsigned int EventData)
{
TotalSentCount = EventData;
XIntc_Acknowledge(&InterruptController, UARTLITE_INT_IRQ_ID);

}

void RecvHandler(void *CallBackRef, unsigned int EventData)
{
TotalReceivedCount = EventData;
flag = 1;
//++Count;
XUartLite_Recv(&UartLiteESP, ReceiveBuffer, 1);
XIntc_Acknowledge(&InterruptController, UARTLITE_INT_IRQ_ID);

}

void delay_ms(Xuint32 Vremay)
{
XTmrCtr_SetResetValue(&Time, 0, Vremay * 50000);
XTmrCtr_Start(&Time, 0);
while(!(XTmrCtr_IsExpired(&Time, 0))){}
XTmrCtr_Stop(&Time, 0);
}

void delay_us(Xuint32 Vremay)
{
XTmrCtr_SetResetValue(&Time, 0, Vremay * 50);
XTmrCtr_Start(&Time, 0);
while(!(XTmrCtr_IsExpired(&Time, 0))){}
XTmrCtr_Stop(&Time, 0);
}


int SetupInterruptSystem(XUartLite *UartLitePtr)
{

int Status;


/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}


/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device.
*/
Status = XIntc_Connect(&InterruptController, UARTLITE_INT_IRQ_ID,
(XInterruptHandler)XUartLite_InterruptHandler,
(void*)UartLitePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the UartLite can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}

/*
* Enable the interrupt for the UartLite device.
*/
XIntc_Enable(&InterruptController, UARTLITE_INT_IRQ_ID);

/*
* Initialize the exception table.
*/
Xil_ExceptionInit();

/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);

/*
* Enable exceptions.
*/
Xil_ExceptionEnable();

return XST_SUCCESS;
}

Подозреваю, что есть разница в скорости работы проца в дебаге и релизе. Может кто сталкивался с подобным? Буду благодарен за любую помощь.
shumerok
Проблема решилась вводом задержки в 1мкс в цикле опроса флага прерывания.
Kapsik
Цитата(shumerok @ Apr 28 2018, 13:12) *
Есть дополнительный вопрос: как в режиме прерывания принимать произвольное кол-во байт (неизвестно заранее кол-во). У меня выход из прерывания не происходит, пока буфер не заполнится.

Еще добавлю, что можно почитать про "кольцевой буфер"
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.