Using the second uart on the VS1010

Designing hardware and software for systems that use the VS1010 MP3 Audio DSP Microcontroller.
Post Reply
SpinnakerDesign
User
Posts: 6
Joined: Tue 2020-12-22 3:06

Using the second uart on the VS1010

Post by SpinnakerDesign »

Hi, sorry if this is a repeat post, can't seem to find where my previous one is.

I'm trying to interact with the second UART on the VS1010.

I've created a basic program that should echo anything on UART2 onto the uart0 output to the terminal, but I don't seem to be able to get this to work on the VS1010D devboard.


I based it on this post: www.vsdsp-forum.com/phpbb/viewtopic.php?f=15&t=2435

Any advice would be appreciated.

Code: Select all

/// \file main.c VS1010D VSOS Executable main file
/// This is a starting point for developing VS1010D DLX libraries and executables

#include <vo_stdio.h>
#include <volink.h>     // Linker directives like DLLENTRY
#include <apploader.h>  // RunLibraryFunction etc
#include <vs1010dRom.h>
#include <vo_gpio.h>
#include <vs1010c.h>
#include <playerinfo.h>
#include <string.h>
#include <protocol.h>
#include <spitv.h>
#include <devboard.h>

#define DEFAULTVOLUME 50

#define UART2DIV_NORMAL	8
#define UART2DIV_EOP 	14
#define UART2_RX_INT_VECTOR (u_int16)(0x20 + INTV_UART2_RX)

#define TX2_PIN 0x1a
#define RX2_PIN 0x1b


__y struct FIFOY uart2Fifo;
__y u_int16 uart2FifoBuffer[32];

#pragma interrupt y 0x7e
void UartReceiveInterrupt(void){
	char ch = PERIP(UART2_DATA);
	FIFOYPut(&uart2Fifo, ch);
	//GpioSetPin(0x21,0);
}

void Uart2PutChar(register char c) {
	while(PERIP(UART2_STATUS)&UART_ST_TXFULL) {
		//Delay(1);
	}
	PERIP(UART2_DATA)=c;
}

u_int16 input;

void PrintInterrupts() {
	const char *intName[] = {
		"DAC","USB","XPR","SP0","SP1","NMI","MMS","GP0",
		"GP1","GP2","FCC","I2S","TX0","RX0","TI0","TI1",
		"TI2","RX2","TX2","SRC","DAO","RTC","SRX","STX",
		"POS","PWR","PWM","SAR","na1","na2","na3","na4"
	};
	
	u_int32 h, l;
	u_int16 i;
		
	printf("Interrupts:\n");
	h = ((u_int32)PERIP(INT_ENABLE1_HP) << 16) | PERIP(INT_ENABLE0_HP);
	l = ((u_int32)PERIP(INT_ENABLE1_LP) << 16) | PERIP(INT_ENABLE0_LP);
	for (i=0; i<32; i++) {
		int pri = ((u_int16)l&1) | (((u_int16)h&1)<<1);
		l >>= 1;
		h >>= 1;
		if (pri) {
			u_int16 addr = (u_int16)(ReadIMem((void *)(0x20+i))>>6L);
			printf("%s 0x%02x:0x%04x, pri %d",intName[i],0x20+i,addr,pri);
			printf(" -> %p\n",(void*)((ReadFromProgramRam(0x20+i)>>6L)&0xffff));
		}
 	}
}

ioresult main (char *params) {
	FIFOYInit(&uart2Fifo,uart2FifoBuffer,sizeof(uart2FifoBuffer));
	GpioSetAsPeripheral(RX2_PIN);
	WriteToProgramRam(0x31,ReadFromProgramRam((u_int16)0x7e)); // UART2 handler
	PERIP(INT_ENABLE1_LP) |= INTF1_UART2_RX;
	PrintInterrupts();
	
	
	printf("Hello, World!\n");
	player.volume = DEFAULTVOLUME;
	
	Uart2PutChar('T');
	
	while(1){
		if (!FIFOYEmpty(&uart2Fifo)) {
			input = FIFOYGet(&uart2Fifo);	 

			printf("Received: %c\n", input);
			
			
		}	
	}
	return S_OK;
}

The output of the Print Interrupts function is as follows:
SP1 0x24:0x8d1b, pri 1 -> 0x8d1b
RX0 0x2d:0x9b94, pri 1 -> 0x9b94
TI2 0x30:0x80e9, pri 1 -> 0x80e9
RX2 0x31:0x9bf8, pri 1 -> 0x9bf8
User avatar
Panu
VSDSP Expert
Posts: 2821
Joined: Tue 2010-06-22 13:43

Re: Using the second uart on the VS1010

Post by Panu »

Hi!

Hmm, the code looks quite nice, but I don't see setting of the UART 2 speed anywhere. You might want to try setting it to 115200 bps in case it's just running at the wrong speed. I think the ROM sets it to 460800 by default. Please try:

PERIP(UART2_DIV) = 0x070D;

to set it to 115200.

-Panu
SpinnakerDesign
User
Posts: 6
Joined: Tue 2020-12-22 3:06

Re: Using the second uart on the VS1010

Post by SpinnakerDesign »

Hi Panu,

Thanks for the response, that cleared up the TX of UART1 and that is now working as expected.

It appears that the RX functionality isn't quite working though, when I send a character to UART1, I get a non-printing character on both UART0 and UART1, but

Code: Select all

UartReceiveInterrupt 
does not seem to be called and

Code: Select all

FIFOYEmpty(&uart2Fifo)
remains True.

Anything special that needs to be done to get the RX pin working properly?
User avatar
Panu
VSDSP Expert
Posts: 2821
Joined: Tue 2010-06-22 13:43

Re: Using the second uart on the VS1010

Post by Panu »

Hmm, looking at the output of PrintInterrupts, it still shows all interrupt vectors pointing to ROM. Your interrupt handler would be loaded below 0x1000.

Hmm hmm hmm, so either the vector is not set, or something resets it back to the ROM handler. Try printing the PrintInterrupts list right after copying the vector to 0x31.

-Panu
SpinnakerDesign
User
Posts: 6
Joined: Tue 2020-12-22 3:06

Re: Using the second uart on the VS1010

Post by SpinnakerDesign »

I see the same result regardless of where I put the PrintInterrupt function, so it appears that the vector is not being set. Here is the updated code:

Code: Select all

/// \file main.c VS1010D VSOS Executable main file
/// This is a starting point for developing VS1010D DLX libraries and executables

#include <vo_stdio.h>
#include <volink.h>     // Linker directives like DLLENTRY
#include <apploader.h>  // RunLibraryFunction etc
#include <vs1010dRom.h>
#include <vo_gpio.h>
#include <vs1010c.h>
#include <playerinfo.h>
#include <string.h>
#include <protocol.h>
#include <spitv.h>
#include <devboard.h>

#define DEFAULTVOLUME 50

#define UART2DIV_NORMAL	8
#define UART2DIV_EOP 	14
#define UART2_RX_INT_VECTOR (u_int16)(0x20 + INTV_UART2_RX)

#define TX2_PIN 0x1a
#define RX2_PIN 0x1b


__y struct FIFOY uart2Fifo;
__y u_int16 uart2FifoBuffer[32];



#pragma interrupt y 0x7e
void UartReceiveInterrupt(void){
	char ch = PERIP(UART2_DATA);
	printf("int\n");
	FIFOYPut(&uart2Fifo, ch);
}

void Uart2PutChar(register char c) {
	while(PERIP(UART2_STATUS)&UART_ST_TXFULL) {
		//Delay(1);
	}
	PERIP(UART2_DATA)=c;
}

u_int16 input;

void PrintInterrupts() {
	const char *intName[] = {
		"DAC","USB","XPR","SP0","SP1","NMI","MMS","GP0",
		"GP1","GP2","FCC","I2S","TX0","RX0","TI0","TI1",
		"TI2","RX2","TX2","SRC","DAO","RTC","SRX","STX",
		"POS","PWR","PWM","SAR","na1","na2","na3","na4"
	};
	
	u_int32 h, l;
	u_int16 i;
		
	printf("Interrupts:\n");
	h = ((u_int32)PERIP(INT_ENABLE1_HP) << 16) | PERIP(INT_ENABLE0_HP);
	l = ((u_int32)PERIP(INT_ENABLE1_LP) << 16) | PERIP(INT_ENABLE0_LP);
	for (i=0; i<32; i++) {
		int pri = ((u_int16)l&1) | (((u_int16)h&1)<<1);
		l >>= 1;
		h >>= 1;
		if (pri) {
			u_int16 addr = (u_int16)(ReadIMem((void *)(0x20+i))>>6L);
			printf("%s 0x%02x:0x%04x, pri %d",intName[i],0x20+i,addr,pri);
			printf(" -> %p\n",(void*)((ReadFromProgramRam(0x20+i)>>6L)&0xffff));
		}
 	}
}

ioresult main (char *params) {
	FIFOYInit(&uart2Fifo,uart2FifoBuffer,sizeof(uart2FifoBuffer));
	GpioSetAsPeripheral(RX2_PIN);
	PERIP(UART2_DIV) = 0x070D;
	PERIP(INT_ENABLE1_LP) |= INTF1_UART2_RX;
	WriteToProgramRam(0x31,ReadFromProgramRam((u_int16)0x7e)); // UART2 handler
	PrintInterrupts();
	
	
	printf("Hello, World!\n");
	player.volume = DEFAULTVOLUME;
	
	Uart2PutChar('T');
	Uart2PutChar('E');
	Uart2PutChar('S');
	Uart2PutChar('T');
	printf("Start Test\n");
	while(1){
		printf("Fifo Empty: %d\n", FIFOYEmpty(&uart2Fifo));
		if (!FIFOYEmpty(&uart2Fifo)) {
			input = FIFOYGet(&uart2Fifo);	 

			printf("Received: %c\n ", input);
			Uart2PutChar(input);
			
		}	
		DelayL(10000000);
	}
	return S_OK;
}

User avatar
Panu
VSDSP Expert
Posts: 2821
Joined: Tue 2010-06-22 13:43

Re: Using the second uart on the VS1010

Post by Panu »

Hi!

Ouch! This was a bite from an unexpected tooth, sort of a clash between beauty and reality. You know, pragmatism can be a little bit dirty sometimes.

What happened was that the function UartReceiveInterrupt was already defined in ROM. And the VS1010 linker kind of treats all declared ROM symbols (those found in vs1010d_romabs.txt) as reserved names and it always replaces references to those names with references to ROM symbols. This is out of necessity as there's so little program RAM in the VS1010 and doing it this way reduces code size, because all stuff, such as parts of the C library, that are already in ROM can be silently removed from the RAM objects, allowing complilation for different targets while still producing small binaries for the VS1010. The thing that I'm really sorry about is that the linker, for reasons that would require a rather lengthy explanation, does not detect that it happens, so it also doesn't print out any errors or warnings. Again, I am sorry, but there's nothing I can do about it, at least at the moment. The only thing that can be done is to remove names that you wish to override from vs1010d_romabs.txt on a case by case basis.

What I can do is change the name of your interrupt handler from UartReceiveInterrupt to MyUart2ReceiveInterrupt, which magically makes it work.

Code: Select all

#pragma interrupt y 0x7e
void MyUart2ReceiveInterrupt(void){
	char ch = PERIP(UART2_DATA);
	printf("int\n");
	FIFOYPut(&uart2Fifo, ch);
}
I also included a finalization code that clears the interrupt enable and restores the original handler:

Code: Select all

void fini(void) {
	PERIP(INT_ENABLE1_LP) &= ~INTF1_UART2_RX;
	WriteToProgramRam(0x31,ReadFromProgramRam((u_int16)0x8006)); // Restore original UART2 handler
	printf("Bye!\n");
}
Here's the complete code. A quick test with the developer board seems to work as expected.

Code: Select all

/// \file main.c VS1010D VSOS Executable main file
/// This is a starting point for developing VS1010D DLX libraries and executables

#include <vo_stdio.h>
#include <volink.h>     // Linker directives like DLLENTRY
#include <apploader.h>  // RunLibraryFunction etc
#include <vs1010dRom.h>
#include <vo_gpio.h>
#include <vs1010c.h>
#include <playerinfo.h>
#include <string.h>
#include <protocol.h>
#include <spitv.h>
#include <devboard.h>

#define DEFAULTVOLUME 50

#define UART2DIV_NORMAL	8
#define UART2DIV_EOP 	14
#define UART2_RX_INT_VECTOR (u_int16)(0x20 + INTV_UART2_RX)

#define TX2_PIN 0x1a
#define RX2_PIN 0x1b


__y struct FIFOY uart2Fifo;
__y u_int16 uart2FifoBuffer[32];



#pragma interrupt y 0x7e
void MyUart2ReceiveInterrupt(void){
	char ch = PERIP(UART2_DATA);
	printf("int\n");
	FIFOYPut(&uart2Fifo, ch);
}

void Uart2PutChar(register char c) {
	while(PERIP(UART2_STATUS)&UART_ST_TXFULL) {
		//Delay(1);
	}
	PERIP(UART2_DATA)=c;
}

u_int16 input;

void PrintInterrupts() {
	const char *intName[] = {
		"DAC","USB","XPR","SP0","SP1","NMI","MMS","GP0",
		"GP1","GP2","FCC","I2S","TX0","RX0","TI0","TI1",
		"TI2","RX2","TX2","SRC","DAO","RTC","SRX","STX",
		"POS","PWR","PWM","SAR","na1","na2","na3","na4"
	};
	
	u_int32 h, l;
	u_int16 i;
		
	printf("Interrupts:\n");
	h = ((u_int32)PERIP(INT_ENABLE1_HP) << 16) | PERIP(INT_ENABLE0_HP);
	l = ((u_int32)PERIP(INT_ENABLE1_LP) << 16) | PERIP(INT_ENABLE0_LP);
	for (i=0; i<32; i++) {
		int pri = ((u_int16)l&1) | (((u_int16)h&1)<<1);
		l >>= 1;
		h >>= 1;
		if (pri) {
			u_int16 addr = (u_int16)(ReadIMem((void *)(0x20+i))>>6L);
			printf("%s 0x%02x:0x%04x, pri %d",intName[i],0x20+i,addr,pri);
			printf(" -> %p\n",(void*)((ReadFromProgramRam(0x20+i)>>6L)&0xffff));
		}
 	}
}

ioresult main (char *params) {
	FIFOYInit(&uart2Fifo,uart2FifoBuffer,sizeof(uart2FifoBuffer));
	GpioSetAsPeripheral(RX2_PIN);
	PERIP(UART2_DIV) = 0x070D;
	Disable();
	PERIP(INT_ENABLE1_LP) |= INTF1_UART2_RX;
	printf("\n0x%08lx\n", ReadFromProgramRam((u_int16)0x7e));
	WriteToProgramRam(0x31,ReadFromProgramRam((u_int16)0x7e)); // UART2 handler
	PrintInterrupts();
	Enable();
		
	
	printf("Hello, World!\n");
	player.volume = DEFAULTVOLUME;
	
	Uart2PutChar('T');
	Uart2PutChar('E');
	Uart2PutChar('S');
	Uart2PutChar('T');
	printf("Start Test\n");
	while(1){
		printf("Fifo Empty: %d\n", FIFOYEmpty(&uart2Fifo));
		if (!FIFOYEmpty(&uart2Fifo)) {
			input = FIFOYGet(&uart2Fifo);	 

			printf("Received: %c\n ", input);
			Uart2PutChar(input);
			
		}	
		DelayL(10000000);
	}
	return S_OK;
}


void fini(void) {
	PERIP(INT_ENABLE1_LP) &= ~INTF1_UART2_RX;
	WriteToProgramRam(0x31,ReadFromProgramRam((u_int16)0x8006)); // Restore original UART2 handler
	printf("Bye!\n");
}
Sorry for the unexpected linkage result.

-Panu
Rogier74
User
Posts: 7
Joined: Fri 2021-09-10 15:31

Re: Using the second uart on the VS1010

Post by Rogier74 »

Panu wrote: Tue 2021-01-05 19:38 PERIP(UART2_DIV) = 0x070D; // to set it to 115200.
What is the formula for this calculation of baudrate?

edit: I got it already page 84 on de datasheet http://www.vlsi.fi/fileadmin/datasheets/vs1010ds.pdf
Post Reply