2

I have a receive interrupt issue with ATTINY1626. In pooling mode I can able to receive UART data. But it is not happening by enabling UART RX interrupt. I don't know where I missed some configuration related to interrupts.

Please suggest me if anybody faced and resolved this type of issue.

Below is the code.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/fuse.h>

#define F_CPU 16000000UL / 2
#define FUSE_OSCCFG_16MHZ  (0x7D)

//#define cli()             __asm__ __volatile__ ("cli" ::)         ///< Disables global interrupts
//#define sei()             __asm__ __volatile__ ("sei" ::)         ///< Enables global interrupts

volatile unsigned char gvc_Rxbyte = 0;

FUSES = {
    .WDTCFG     = FUSE_WDTCFG_DEFAULT,
    .BODCFG     = FUSE_BODCFG_DEFAULT,
    .OSCCFG     = FUSE_OSCCFG_16MHZ,    // Run at 16 MHz and Calibration registers of the 20 MHz oscillator are accessible
    .SYSCFG0    = FUSE_SYSCFG0_DEFAULT, // Reset Pin Configured as UPDI
    .SYSCFG1    = FUSE_SYSCFG1_DEFAULT, // start-up time between power-on and code execution
    .APPEND     = 0x14, // FUSE_APPEND_DEFAULT - 4K APP CODE
    .BOOTEND    = 0x04, // FUSE_BOOTEND_DEFAULT - 1K BOOT CODE
};

void send_string(unsigned char uartNo, char *s);

void usart0_init(unsigned long int baudRate)
{
    unsigned int baud = 0;
    cli();
    SREG &=~(1 << 7);
//  PORTMUX.EVSYSROUTEA |= (1 << 1);
    //uint8_t sregBackup = CPU_SREG;
//  cli();
    baud = (F_CPU / baudRate) * 4;  // BAUD = (64 * fCLK_PER) / (S * fBAUD)
    // S is the number of samples per bit
    // Asynchronous Normal mode: S = 16
    // Asynchronous Double-Speed mode: S = 8
    // Synchronous mode: S = 2
    
    USART0.BAUDL = (unsigned char) baud;            // Set the baud rate (USARTn.BAUD).
    USART0.BAUDH = (unsigned char) (baud >> 8);
    
    USART0.CTRLC = 0x03;            // Set the frame format and mode of operation (USARTn.CTRLC).
    //set character size to 8. parity = none. stop bits = 1. async usart.
    PORTB.DIR |= PIN2_bm;           // Configure the TXD pin as an output.
    PORTB.DIR &= ~PIN3_bm;          // Configure the RXD pin as an input.
    
    USART0.CTRLA |=(1<<USART_RXCIE_bp) | (1<<USART_ABEIE_bp);//0x84;
    USART0.CTRLB |=(1<<USART_RXEN_bp)|(1<<USART_TXEN_bp) ;          // Enable the transmitter and the receiver (USARTn.CTRLB).
    
     sei();
}

void usart0WriteByte(unsigned char dataByte)
{
    while(!(USART0.STATUS & USART_DREIF_bm)); // wait till tx register is free
    USART0.TXDATAL = dataByte;              // load data in the tx register
}

unsigned char usart0ReadByte(void)
{
    unsigned char rxByte = 0;
    while(!(USART0.STATUS & USART_RXCIF_bm)); // wait for rx register data
    rxByte = USART0.RXDATAL;                // read data from the rx register
    
    return rxByte;
}

void send_string(unsigned char uartNo, char *s)
{
    while(*s)
    {
        usart0WriteByte(*s);        
        s++;
    }
}

int main(void)
{
    //unsigned char i=0;
    cli();
    
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSC20M_gc | (0<<CLKCTRL_CLKOUT_bp ));    ///< To out the clock on clock out pin
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm );                  ///< To set the clock pre-scaler as DIVIDED BY 2
    
    usart0_init(115200);                ///< Initializing UART0 as debug interface.
    //_PROTECTED_WRITE(CPU_SREG, (1 << CPU_I_bp));  
    //send_string(0, "System Initialized\r\n");
    _delay_ms(1000);
    gvc_Rxbyte = 'B';   
    
    while (1)
    {
         //sei();
        ////gvc_Rxbyte = usart0ReadByte();
        //usart0WriteByte(gvc_Rxbyte);
        //_delay_ms(1000);
    }
}

ISR (USART0_RXC_vect)
{
    if(USART0.STATUS & USART_RXCIF_bm)
    {
        gvc_Rxbyte = USART0.RXDATAL;
    }
    gvc_Rxbyte = USART0.RXDATAL;                // read data from the rx register
    usart0WriteByte(gvc_Rxbyte);    
}
**

I tried enabling the UART RXIE configurations. Enabled Global interrupts. Even the ISR also not calling upon the receive data available on receive buffers.

Hardware path seems ok as the receive functionality working with POOLing mode.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • In addition to answer about reading `RXDATAL` twice, you don't need to check status flag in ISR. As i remember, it's cleared when handler executed. Also calling busy-wait function `usart0WriteByte()` from ISR is ok for debug but generally is not a good idea. – dimich May 30 '23 at 15:05

1 Answers1

2

It seems that you read the USART0.RXDATAL byte twice in your ISR. If your gvc_Rxbyte is 0, it might be because you overwrite it by reading USART0.RXDATAL the second time.

emiled
  • 21
  • 4
  • Welcome to StackOverflow! Please take the [tour] to learn how this site works. -- At first I thought your answer is actually not an answer, because it asks for clarification. Please use a comment at the question for this purpose. -- However, your second paragraph seems to answer the OP's question. You might want to [edit] your answer to enhance it. – the busybee May 30 '23 at 19:47
  • 1
    @thebusybee Thanks for the tip, I edited the answer. Actually I wanted to ask the question in a comment but for that you need 50 reputation ;) – emiled May 31 '23 at 06:22
  • Thanks. Now we will see whether the OP likes your answer. ;-) It will add to your reputation. – the busybee May 31 '23 at 06:26