Hello All,
I am trying to set the buudrate of P4080 UART0, to 115200 for 333Khz DUART INPUT CLOCK.
But the Uboot upon bootup as set UDLB & UMLB to 115,200 as "00D9" i.e., for 400KHz configuration.
I can change every other DUART register value except for (UDLB & UMLB) and also send & receive data 'perfectly' using a "waiit" function ..
Please can any one tell me, where am I going wrong in it?
If I remove this "waiit", then I won't have proper communication, I can see something like 1st character and then 6th ..randomly.
P.S : THROUGH T32 debugger have a checked the value of UDLB1 = D9 & UMLB1 = 00.
And also the communicator computer is set to 115200 as standard & is tested many a times.
Here is my code
int write(int file, char *ptr, int len) {
unsigned int i;
int de =1; // de = 1 for write & de = 0 for read function
initialize_Uart(de);
/* Transmitting a char from UART */
for (i = 0; i < len; ++i, ++ptr)
{
OUT_8(DUART1_UTHR, *ptr);
// waiit(); //TODO: frequency matching is not happening so, either the buffer is getting over written or the receiver is too slow.
}
return len;
}
void waiit(){
int i;
for(i=0;i<99999;i++);
}
void initialize_Uart(int);
void initialize_Uart(int de)
{
#define DUART1_UTHR 0xFE11C500 //transmitter buffer register
#define DUART1_UDLB 0xFE11C500 // to set the baud rate
#define DUART1_UMLB 0xFE11C501 // higher bite of baud rate
#define DUART1_UIER1 0xFE11C501 // Modem interrupt register 00001111
#define DUART1_UFCR1 0xFE11C502 //FIFO control register 1,0,0,0,0,1,1,1
#define DUART1_ULCR1 0xFE11C503 // Line control register, for parity and other checks
#define DUART1_UMCR1 0xFE11C504 // modem control register 0x12 for loop back & ready to send 0x00 to clear these two
#define DUART1_ULSR1 0xFE11C505 // Line status register
#define DUART1_UMSR1 0xFE11C506 // modem status register -> to check if the peripheral device is ready to transmit.
#define DUART1_UDSR1 0xFE11C510 // Check if the buffer is ready to transmit or receive
#if !defined( OUT_8 )
#define OUT_8(p,d) (*(volatile char *)(p) = (char)(d))
#endif
#if !defined( IN_8 )
#define IN_8(p) ((*(volatile char *)(p)))
#endif
if(de==1) /* Initialization of UART port 1 for writing */
{
OUT_8(DUART1_UIER1, 0x00); //disable interrupts
//OUT_8(DUART1_ULCR1, 0x80); // Bank select enable
/*You can change the BAUD RATE HERE, but using default baudrate set by >U-boot is error free */
// OUT_8(DUART1_UDLB, (baud_rate & 0xff));
// OUT_8(DUART1_UMLB, ((baud_rate>>8)& 0xff)); //set the baud rate to 115200
OUT_8(DUART1_UDLB, 0x0000); // VALUE for 00B5
OUT_8(DUART1_UMLB, 0xB500);
OUT_8(DUART1_ULCR1, 0x03); // 8 bit data, 1stop, no parity
OUT_8(DUART1_UMCR1, 0x02); // Ready to send/receive
OUT_8(DUART1_UFCR1, 0x07); // FIFO enable | receiver soft reset | transmitter soft reset
//OUT_8(DUART1_UIER1, 0x0f); // enable interrupts
/* End of Initialization of UART port 1 */
}
if(de==0) /* Initialization of UART port 1 for reading */
{
OUT_8(DUART1_UIER1, 0x00); //disable interrupts
OUT_8(DUART1_UDLB, 0x0000);
OUT_8(DUART1_UMLB, 0xB500);
//OUT_8(DUART1_ULCR1, 0x80); // Bank select enable
//OUT_8(DUART1_UDLB, (baud_rate & 0xff));
//OUT_8(DUART1_UMLB, ((baud_rate>>8)& 0xff)); //set the baud rate to 115200
OUT_8(DUART1_ULCR1, 0x03); // 8 bit data, 1stop, no parity
OUT_8(DUART1_UMCR1, 0x02); // Ready to receive
}
}
Regards,
Sumanth
已解决! 转到解答。
Hi Sumanth,
I investigated your flow and I can successfully read the new values of UDLB/UMLB after a write operation (using CW). In our code, firstly, we read ULCR1 - you can make a try (in the P4080 reference manual, also, there is a note about the order register UART programming - "Set data attributes and control bits in the ULCR, UFCR, UAFR, UMCR, UDLB, and UDMB.").
Regarding the wait() function, from our experience, this is mandatory for some boards (included P4080DS). In our code we make a single read from IVPR register for simulating the wait(). Below, you have our wait() code - we're calling this function with time=1. You can try to make something similar, your for() that simulates the wait() is very time consuming.
void | ||
wait(int time) | ||
{ | ||
short x, *rom_read; | ||
/* Just use IVPR */ | ||
long ivpr = 0; | ||
asm ("mfspr %0, 63" : "=r" (ivpr)); | ||
rom_read = (short *)ivpr; | ||
while (time-- > 0) { | ||
x = *rom_read; | ||
} | ||
return; | ||
} |
Regards,
Marius
Hi Sumanth,
I'm not sure if I understood your problem, but in our CW UART project for P4080DS we're making the same wait() after writing UDLB, UMLB registers -> you can take a look in duart.c file from ${CW_PA}\PA\PA_Support\Serial\Common\duart.c.
...
cnt = GetClockDivider(baud_rate); |
/* set divisor latch count */
OUT8(port + OFFS_LCR, LCR_DBIT8|LCR_STOP1|LCR_PARDIS|LCR_DIVLAT);
IOWAIT();
OUT8(port + OFFS_DLM, cnt >> 8);
IOWAIT();
OUT8(port + OFFS_DLL, cnt );
IOWAIT(); |
...
You can debug this setting up a bp in GetClockDivider using debugger shell after you started the DebugDownload stationary P4080DS project:
bp GetClockDivider
Regards,
Marius
Thank You Marius,
Probably, I didn't describe the problem properly. But, here I'll do it.
The Problem is :
1) Inspite of updating the ULB & MLB registers like this :
OUT_8(DUART1_UDLB, 0x0000);
OUT_8(DUART1_UMLB, 0xB500);
where DUART1_UDLB = 0xFE11C500
and DUART1_UMLB = 0xFE11C501
I am not able to see the value changed in the register on my debugger.
But, When I change the values of other registers I can see the change in the registor value for their respective register.
WHY ONLY THE UDLB & UMLB registers are NOT getting updated ??? Should they be set only in the boot process?
2) I want to remove that wait() function, boz, it is consuming more time than the TICK rate of my RTOS.
How can I do it? is the wait() function very necessary ? I don't think so, if the buad rate is set perfectly.
Regards,
Sumanth
Hi Sumanth,
I investigated your flow and I can successfully read the new values of UDLB/UMLB after a write operation (using CW). In our code, firstly, we read ULCR1 - you can make a try (in the P4080 reference manual, also, there is a note about the order register UART programming - "Set data attributes and control bits in the ULCR, UFCR, UAFR, UMCR, UDLB, and UDMB.").
Regarding the wait() function, from our experience, this is mandatory for some boards (included P4080DS). In our code we make a single read from IVPR register for simulating the wait(). Below, you have our wait() code - we're calling this function with time=1. You can try to make something similar, your for() that simulates the wait() is very time consuming.
void | ||
wait(int time) | ||
{ | ||
short x, *rom_read; | ||
/* Just use IVPR */ | ||
long ivpr = 0; | ||
asm ("mfspr %0, 63" : "=r" (ivpr)); | ||
rom_read = (short *)ivpr; | ||
while (time-- > 0) { | ||
x = *rom_read; | ||
} | ||
return; | ||
} |
Regards,
Marius
Hello Marius,
Thank You very much. I realise the I did the mistake in the order of addressing the registers.
And also, thanks for the wait() function. I really believe this function is logically true & will solve my problem.
Thanking you,
Regards,
Sumanth