#define AT91C_BASE_PDC_US0 (AT91_CAST(AT91PS_PDC) 0xFFFB0100) // (PDC_US0) Base Address
#define AT91C_BASE_US0 (AT91_CAST(AT91PS_USART) 0xFFFB0000) // (US0) Base Address
#define AT91C_BASE_PDC_US1 (AT91_CAST(AT91PS_PDC) 0xFFFB4100) // (PDC_US1) Base Address
#define AT91C_BASE_US1 (AT91_CAST(AT91PS_USART) 0xFFFB4000) // (US1) Base Address
#define AT91C_BASE_PDC_US2 (AT91_CAST(AT91PS_PDC) 0xFFFB8100) // (PDC_US2) Base Address
#define AT91C_BASE_US2 (AT91_CAST(AT91PS_USART) 0xFFFB8000) // (US2) Base Address
#define AT91C_BASE_PDC_US3 (AT91_CAST(AT91PS_PDC) 0xFFFBC100) // (PDC_US3) Base Address
#define AT91C_BASE_US3 (AT91_CAST(AT91PS_USART) 0xFFFBC000) // (US3) Base Address
how can i know which of them to use? does US0 is like COM0, US1 like COM1 and so…
which of them to use? and does it matter which socket i use on Hydra board?
What I did was look at the schematic for the Hydra to determine which CPU UART pins are connected to which Gadgeteer Socket on the Hydra board. From that I could determine the AT91C_BASE_US0 maps to NETMF COM2.
To write to the port you put a byte into the Transmitter Holding Register (US_THR), to read you read from the Receiver Holding Register (US_RHR). Of course you should first check that there is data to be read, bit 0 of the US_CSR register indicates that there is data available in the RHR.
Here is the data sheet for the AT91SAM9RL64 mcu used in the Hydra, this is the go to document if you want understand how to effectively work with the peripherals offered by this mcu. http://www.atmel.com/Images/doc6289.pdf
[ol]You are returning a pointer to the local variable ‘p’. Once the function returns the stack space used for the locals is reclaimed and will get clobbered by any subsequent function calls.
The code will have to be lucky to get called at the right time to detect the presence of a character in the buffer
If you do start reading characters you have nothing to prevent you from overwriting the ‘p’ buffer[/ol]
For the first issue I would suggest that you pass the buffer in to the function and also pass the length of the buffer and have the function return the number of bytes read. You can use that length to limit the reads, this will help address point 3 above as well.
int Serial_Read(char *pBuffer, int size) ...
For the second issue, you probably want to loop until the flag indicates there is a character in the holding register then you will fall out of the loop and read the character from the register. To ensure that you do not loop forever, you can limit the number of times the loop will run before giving up and returning 0 bytes read.
@ taylorza - Here is a quick and dirty example, I tested this and it works.
First you need to disable the receive ready interrupt, otherwise .NET will steal the characters from you.
// Disable the receiver interrupt
AT91C_BASE_US0->US_IDR = 0x01;
// Enable the receiver, this is probably not required. I just put it in and did not test without it.
AT91C_BASE_US0->US_CR = 0x10;
Then your code to read from the port, here is a very quick and dirty implementation. It does not timeout it reads up to ‘size’ bytes before returning.
int read_serial(char *pBuffer, int size)
{
int bytesRead = 0;
while ((size - bytesRead) > 0)
{
// Wait for a character to arrive
while ((AT91C_BASE_US0->US_CSR & 1) == 0) ;
// Add the character to the buffer
*pBuffer++ = (char)AT91C_BASE_US0->US_RHR;
bytesRead++;
}
return bytesRead;
}
To call the above function, you can do the following
char buffer[10];
int read = read_serial(buffer, 5);
if (read > 0)
{
buffer[read] = '\0';
debug_print(buffer);
}
This code creates a buffer of 10 chars. Then waits to read 5 character, these are just arbitrary numbers I chose for demonstration purposes, and then echos them back over the serial port.
Note 1: We are doing some nasty things here, so the .NET serial class will most likely stop working on the managed side. But you can send and receive on the native side.
Note 2: You will definitely want to implement the timeout so that you do not block for ever on the read if you do not get any or enough data to match the size passed to the read_serial function.
int read_serial(char *pBuffer, int size, int timeout)
{
int bytesRead = 0;
while (((size - bytesRead) > 0) && (timeout >= 0) )
{
// Wait for a character to arrive
while ( (timeout >= 0) && ((AT91C_BASE_US0->US_CSR & 1) == 0))
timeout--;
// Add the character to the buffer
*pBuffer++ = (char)AT91C_BASE_US0->US_RHR;
bytesRead++;
}
return bytesRead;
}
I am using this function with timeout = 0 and try to read 1 char in loop. The problem is that i think the buffer (AT91C_BASE_US0->US_RHR) doesn’t clear and i read this byte each time i try to read. (unless i write other byte…)
my code look like:
while (true)
{
//do some work..
read_serial(&reciveBuffer[0],1, 0);
//check if got stop command
if (reciveBuffer[0] == STOP_VALUE)
{
//do sonething
}
}
i see that after i sent STOP_VALUE over serial code always insert to this “if”…
maybe i need to “clear” receiver after i read from??
One thing that I see, is that after your timeout expires you are reading the US_RHR register, but I would assume that you timed-out because no character has arrived and therefore reading the register is undefined.