atmega8 UART- doesn't show character in realterm - avr

Hi i'm new to this and i need help. It's suppose to just show the 'S' in the realterm instead it gives 'null'. What would be the problem? could it be the register? or the code itself?
#include <avr/io.h>
#include <util/delay.h>
void UART_Init(unsigned int ubrr)
{
UBRRH=(unsigned int)(ubrr>>8);
UBRRL=(unsigned int)ubrr;
UCSRA=0x00;
UCSRB=(1<<TXEN)|(1<<RXEN);
UCSRC=(0<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);
}
void UART_Tx(unsigned char chr)
{
while (bit_is_clear(UCSRA,UDRE)){}
UDR=chr;
}
int main(void)
{
UART_Init(95);
DDRD|=0B11111111;
PORTD|=0B11111111;
while(1){
_delay_ms(10);
UART_Tx('S');
}
}
System is running on xtal with 14745600 Hz. Speed on host is 9600 baud. all settings should be 8N1.

You need to set the URSEL when writing to the UCSRC register.
Change
UCSRC=(0<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);
to
UCSRC=(1<<URSEL)|(0<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);
From the data sheet:
The UBRRH Register shares the same I/O location as the UCSRC Register. Therefore some
special consideration must be taken when accessing this I/O location. When doing a write access of this I/O location, the high bit of the value written, the USART Register Select (URSEL) bit, controlswhich one of the two registers that will be written. If URSEL is
zero during a write operation, the UBRRH value will be updated. If URSEL is one, the UCSRC
setting will be updated.
The rest of the code looks fine to me.

change UART_Tx('S'); using UART_Tx("S");

Related

How can I measure how long this Linux interrupt handler takes to run?

I am trying to debug a custom Linux serial driver that is having some issues missing some receive data. It has one interrupt for 4 serial ports, and baud rate is 115200. Firstly I would like to see how to measure how long the interrupt handler takes. I have used perf, but things are just in percent and not seconds. Secondly does anyone see any issues with the below code that can be improved to speed things up?
void serial_interrupt(int irq, void *dev_id)
{
...
// Need to loop through each port to see which port caused the interrupt.
list_for_each(lpNode, &serial_ports)
{
struct serial_port_module *ser_dev = list_entry(lpNode, struct serial_port_module, port_list);
lnIsr = ioread8(ser_dev->membase + ser_dev->chan_num * PORT_OFFSET + SERIAL_ISR);
if (lnIsr & IPM512_RX_INT)
{
while (serialdata_is_data_available(ser_dev)) // equals a ioread8()
{
lcIn = ioread8(ser_dev->membase + ser_dev->chan_num * PORT_OFFSET + SERIAL_RBR);
kfifo_in(&ser_dev->rx_fifo, &lcIn, sizeof(lcIn));
// Notify if anyone is doing a blocking read.
wake_up_interruptible(&ser_dev->read_queue);
}
}
}
}
Use the ftrace API to try to track down your latency issues. It's woth the time to get to know: https://www.kernel.org/doc/Documentation/trace/ftrace.txt
If this is too heavy-weight, what about adding some simple instrumentation yourself? getnstimeofday(struct timespec *ts) is relatively lightweight... with a little code you could output in a sysfs debug file the worst case execution times, some stats on latency of call to this function, worst-case number of bytes available per interrupt... if this number gets near your hardware FIFO size, you're in trouble.
One optimization would be to read the data in batches into a buffer, as long as data is available, then input the entire buffer, then wake up any readers.
while(data_available(dev))
{
buf[cnt++] = ioread8();
}
kfifo_in(fifo, buf, cnt);
wake_up_interruptible();
But execution time of code this simple is not likely to be an issue. You're probably suffering from missed interrupts or unexpected latency of the interrupt handling.

Setting GPIO in MLO does not work

I want to know how to pin multiplex pins in initial phase of boot i.e is in spl(MLO).
What I am trying to do is change the default pin configuration to gpio one, so that I can see high or low on the pin.
On P8 header I tried to change the mode 0 from default 'TIMER4' to gpio2[2] i.e mode 7. So I did this
static struct module_pin_mux gpio2_2_pin_mux[] = {
{OFFSET(gpmc_wen), (MODE(7) | PULLUDEN)},
{-1},
};
and called this function
configure_module_pin_mux(gpio2_2_pin_mux);
in board/ti/am335x/mux.c
I didn't saw any voltage on 7th pin of P8 header?
What is the correct way to do this?
file link : http://textuploader.com/5eh6u
you can search with '?' in the file to see what I added.
P.S
I checked with checking pin mux setting on uart0 and tried to read it if that is same.
So I wrote this in
./arch/arm/cpu/armv7/omap-common/boot-common.c
void spl_board_init(void)
{
/*
* Save the boot parameters passed from romcode.
* We cannot delay the saving further than this,
* to prevent overwrites.
*/
save_omap_boot_params();
unsigned int *mfi;
//control revision register
/* Prepare console output */
mfi = *(unsigned int *)(0x44E10980);
printf("1======> %x\n",mfi);
preloader_console_init();//it will print uboot version date and time information
mfi = *(unsigned int *)(0x44E10980);
printf("2======> %x\n",mfi);
more init code.....
}
I wanted to see this setting done in board/ti/am335x/mux.c
static struct module_pin_mux uart0_pin_mux[] = {
{OFFSET(uart0_rxd), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* UART0_RXD */
{OFFSET(uart0_txd), (MODE(0) | PULLUDEN)}, /* UART0_TXD */
{-1},
}
But it printed value as 37. that means the pin is in GPIO mode.
How is this possible that the pin that should be in mode 0 is in 7th mode?

PIC16F877 + 24LC64 via i2c

My task is to copy first 255 bytes from external EEPROM (24LC64) to internal (PIC16F877) via i2c bus. I've read AN1488, all datasheets, MikroC gide (oh, yes, I'm using MikroC), but hopeless.. Meaning that my code trys to read smtng but then, reading my PIC's eeprom at programmer (which can't read 24LC64, so I don't even know what's on it, but there is smtng defenately and it is different from what i'm getting), and I'm getting all EEPROM filled by "A2" or "A3". My guess is that it's that first addr, by which I'm addressing to 24LC64. Could you pls inspect my code (it's quite small =)) and point me at my misstakes.
char i;
unsigned short Data;
void main(){
PORTB = 0;
TRISB = 0;
I2C1_Init(100000);
PORTB = 0b00000010;
for (i = 0x00; i<0xFF; i++) {
I2C1_Start();
I2C1_Wr(0xA2); //being 1010 001 0
//I'm getting full internal EE filled with what's in brackets from above
I2C1_Wr(0b00000000);
I2C1_Wr(i);
I2C1_Repeated_Start();
I2C1_Wr(0xA3); //being 1010 001 1
Data = I2C1_Rd(0);
I2C1_Stop();
EEPROM_write(i, Data); //How could that 1010 001 0 get into here???
Delay_100ms();
}
PORTB = 0b00000000;
while (1) {
}
}
P.S. I've tryed this with sequantial read, but it "reads" (again that "A2"..) only 1st byte.. So i've posted this one..
P.S.S. I`m working in "hardware", no Proteus involved..
P.S.S.S. I can't test writing, because I have only one 24LC64 with important info on it, so it's even pulld up to Vcc on it's WP pin...
This isn't a specific answer but more of a checklist for I2C comms, since it's difficult to help with your problem without looking at a scope and without delving into the API calls that you've provided.
Check the address of your EEPROM. I2C uses a 7-bit address with a R/W bit appended to the end, so it's easy to make a mistake here.
Check the command sequence that your EEPROM expects to receive for a "data read"
Check how the I2C_ API that you're using deals with acks from the EEPROM. They need to be handled somewhere (usually in an ISR) and it's not obvious where they're dealt with from your example.
Check that you've got the correct pull-ups on SDA and SCL as per the requirements of your design - they're needed for I2C to work.

sending sms using pic16f877a and sim 300

Hi I have a problem in sending message in project, I am using pic16f877a and sim300. the main function runs repeatedly. Some characters are missed in the sent sms.
my program is like this...
void main()//main function
{
Serial_init(); // initialization of serial communication
Send_SMS();
}
void Serial_init()
{
TRISC=0XC0;
TXSTA=0x24;
SPBRG=129; // set baud rate 9600 Hz for 20MHz fosc
RCSTA=0x90;
TXIF=1;
}
void Send_SMS(void)
{
USART_puts("AT\0");
putch1(0x0D);
Delay_ms4M(200);
USART_puts("AT+CMGF=1\0"); // switch into text mode
putch1(0x0D);// ascii of Carriage Return
Delay_ms4M(200);
USART_puts("AT+CMGS=\"9741153218\"\0"); // send sms to the number
putch1(0x0D);
Delay_ms4M(200);
USART_puts("Hi this is working LOL\0"); // SMS text
putch1(0x0A); // new line
Delay_ms4M(200);
putch1(0x0D);
Delay_ms4M(100);
putch1(0x1A); // ascii of 'substitute' i.e end of file
}
void USART_puts(const unsigned char *string)
{
while(*string)
putch1(*string++);
}
void putch1(unsigned char data)
{
while(TXIF==0);
TXREG=data;
}
Please help
additional details: all other programs run properly, but if I call send_sms function, "main" runs repeatedly and several messages are sent with missed characters.
IMHO :
Your chip is resetting. This is the highest probable cause.
Either it is faulty or you have set Watchdog Timer to on somewhere.
For missing characters :
a) Chip resets in the midst of a data transfer.
b) Roule of thumb for usart:
Stop stuffing bytes to usart. Send each byte with a small leading delay like 10-20 microseconds.
The communication is asynchronous, which means the receiver has to synchronize at the beginning of each communication unit which is a byte. To do that receiver brutely uses resources to detect start bit, the length (in time) of it etc. So if you try to send a byte train, you will stall the receiver.
Have you tried the code with another 16F877a ? (to check chip failure)...

Configure Linux I2C Speed

I am using I2C on the Snowball board, running at 400KHz by default and would like to reduce this to 100KHz.
I use the api defined in and configure as follows
m_fd = open(m_filename.c_str(), O_RDWR);
if (ioctl(m_fd, I2C_SLAVE_FORCE, m_addr) < 0)
{
throw I2cError(DeviceConfigFail);
}
Does anyone know how I would go about changing the speed to standard mode.
Thanks
You can change the I2C SCL frequency in your driver's 'struct i2c_gpio_platform_data'.
static struct i2c_gpio_platform_data xyz_i2c_gpio_data = {
.sda_pin = GPIO_XYZ_SDA,
.scl_pin = GPIO_XYZ_SCL,
.udelay = 5, //#udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
....
};
Changing 'udelay' changes your 'xyz' i2c device's clock frequency.
You should change the I2C Frequency in driver source file of the corresponding peripheral (ie: Slave device to which you are communicating through I2C. Example: EEPROM/Camera etc.)
You may find some macro defined in that driver source code... like:
#define EEPROM_I2C_FREQ 400000 //400KHz
Change it to:
#define EEPROM_I2C_FREQ 100000 //100KHz
Only for that corresponding driver, I2C frequency/speed will be changed.

Resources