How to use 4 Uart in Psoc 4

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
amjoc_4089431
Level 2
Level 2
First like received

Hi,

I am working on CY8C4246AZI-L445 controller and I want use 4 Uarts with receive interrupt.

Whenever I try to add more than 2 uart block in creator it's giving me errors like MAX NUMBER OF MACROCELLS EXCEEDED.I don't understand how to figure out this issue.

I am not using SCB uart ,using another one.

Please help on this asap.

Thanks in advanceIMG_20190326_121038594.jpg

11 Replies
LiDo_2439176
Level 5
Level 5
First question asked 50 replies posted 50 sign-ins

Hi,

as you can see in the component datasheet, page 32, these UARTs are implemented in the UDB blocks.

The maximum UART configuration doesn’t fit in to PSoC 4 device because of maximum number or UDB

macrocells exceeded. There are 8 UDBs, so you can't use more than 2 UART blocks.

Is there any reason for why you don't use UART (SCB mode) ?

Best regards,

Liviu

Hello Liviu,

Thanks for your reply.

Actually, i have used UART in SCB mode but i couldn't generate UART RX

interrupt that is why i am using UDB.

So now i understood that i can't use 4 UART UDB.

Can i use 4 UART in SCB mode with receive interrupt?

If you have any example code,could you please share with me,it would be

helpful for me.

Thanks and regards,

Amit Jori.

On Tue, Mar 26, 2019 at 2:05 PM Liviu Dogaru <community-manager@cypress.com>

0 Likes

Hello Amit Jori,

Yes, you can use 4 UART in SCB mode with receive interrupt.

According to the component datasheet:

The RX buffer size parameter defines the size (in bytes/words) of memory allocated for a receive data buffer. The RX buffer size minimum value is equal to the RX FIFO depth. The RX FIFO is implemented in hardware. Values greater than the RX FIFO depth up to (2^32 – 2) imply usage of the RX FIFO, a circular software buffer controlled by the supplied APIs, and internal ISR. The software buffer size is limited only by the available memory. The interrupt mode is automatically set to internal and the RX FIFO not empty interrupt source is reserved to manage software buffer operation: move data from the RX FIFO into the circular software buffer.

If you still want to handle UART RX interrupt yourself, set Interrupt to External on UART Advanced tab and check RX FIFO not empty.

RX FIFO not empty – At least one data element is available in the RX FIFO to be read.

Best regards,

Liviu

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

Oops, I'm a little bit late ;-(

Anyway let me put my work here 😉

With attached project, I could generate an application and the project could be built.

schematic

000-schematic.JPG

main.c

==================

#include "project.h"

volatile int uart1_flag = 0 ;

volatile int uart2_flag = 0 ;

volatile int uart3_flag = 0 ;

volatile int uart4_flag = 0 ;

CY_ISR(uart1_isr)

{

    isr_1_ClearPending() ;

    uart1_flag = 1 ;

}

CY_ISR(uart2_isr)

{

    isr_2_ClearPending() ;

    uart2_flag = 1 ;

}

CY_ISR(uart3_isr)

{

    isr_3_ClearPending() ;

    uart3_flag = 1 ;   

}

CY_ISR(uart4_isr)

{

    isr_4_ClearPending() ;

    uart4_flag = 1 ;   

}

void init_hardware(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */   

    isr_1_ClearPending() ;

    isr_1_StartEx(uart1_isr) ;

    isr_2_ClearPending() ;

    isr_2_StartEx(uart2_isr) ;

    isr_3_ClearPending() ;

    isr_3_StartEx(uart3_isr) ;

    isr_4_ClearPending() ;

    isr_4_StartEx(uart4_isr) ;

    UART_1_Start() ;

    UART_2_Start() ;

    UART_3_Start() ;

    UART_4_Start() ;

}

int main(void)

{

    init_hardware() ;

    for(;;)

    {

        if (uart1_flag) {

            // do something for uart1

            uart1_flag = 0 ;

        }

        if (uart2_flag) {

            // do something for uart2

            uart2_flag = 0 ;

        }

        if (uart3_flag) {

            // do something for uart3

            uart3_flag = 0 ;

        }

        if (uart4_flag) {

            // do something for uart4

            uart4_flag = 0 ;

        }

    }

}

==================

moto

P.S. In my first post, uart4_isr was clearing isr_3 flags (fixed)

0 Likes

Thank you guys for your response.

I'll try these solutions and let you know the results.

regards,

Amit.

On Wed, Mar 27, 2019 at 5:16 AM Motoo Tanaka <community-manager@cypress.com>

0 Likes
lock attach
Attachments are accessible only for community members.

Hello,

Thank you for your help.

With the help of your suggestions, now I am able to generate UART receive

interrupt using SCB UART.

But, for every received byte, its generating interrupt even I disable that

interrupt.

I want to read the complete string on first received byte interrupt for

that I am doing following steps:

1)Send a string of 5 bytes from Tera Term.

2)Once interrupt is generated for the first byte of string, in isr I

Disable the interrupt then

3)Read remaining 5 bytes.

4)After reading, Enable the Interrupt again to receive the next string.

But the problem is, the controller is generating an interrupt for every

received byte and when I try to read the string, it's giving me the same

character 5 times.

For example. If i send data like "ABCD"

for every character, Interrupt is getting generated, you can see from the

attached image file.

After disabling interrupt it should not generate interrupt till I enable

it, but i don't know what i am missing.

Find attached workspace folder and Please help me on this.

Regards,

Amit.

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

So I modified main.c as follow.

As you are going to have 4 UARTs, I rename each UART depending variables with the number.

main.c

========================

#include "project.h"

#include "stdio.h"

CY_ISR_PROTO(MyRx1Int);          // process Rx interrupt

#define TAB                  '\t'

#define SPACE                ' '

#define CR                   '\r'

#define LF                   '\n'

#ifndef STR_1_LENGTH

#define STR_1_LENGTH           32 /* length for UART command input */

#endif

#ifndef BUF_1_LENGTH

#define BUF_1_LENGTH           128

#endif

volatile char rx_1_buf[BUF_1_LENGTH]  ; /* buffer for UART_RX */

volatile int  rx_1_write_index   = 0 ;

int           rx_1_read_index    = 0 ;

char          str_1_buf[STR_1_LENGTH+1]     ; /* print buffer */

int           str_1_index     = 0 ;

inline int is_delimiter(uint8_t c)

{

    int result = 0 ;

    switch(c) {

// case TAB:   // uncoment this line if you need TAB to be a delimiter

// case SPACE: // uncoment this line if you need SPACE to be a delimiter

    case CR:

    case LF:

        result = 1 ;

        break ;

    }

    return( result ) ;

}

CY_ISR(MyRx1Int)

{

    uint8_t int_flag ;

    UART_1_ClearRxInterruptSource(UART_1_INTR_RX_NOT_EMPTY) ; /* for PSoC 4 */

    if (UART_1_SpiUartGetRxBufferSize()) {

        int_flag = CyEnterCriticalSection() ;

        rx_1_buf[rx_1_write_index] = UART_1_UartGetByte() ;

        rx_1_write_index = (rx_1_write_index + 1) % BUF_1_LENGTH ;

        CyExitCriticalSection(int_flag) ;

    }

}

/*=========================

Main Function

===========================*/

int main(void)

{  

    CyGlobalIntEnable; /* Enable global interrupts. */

    UART_1_SpiUartClearRxBuffer() ;

    isr_1_StartEx(MyRx1Int);

  

 UART_1_Start();

    UART_1_UartPutString("\r\nUART example\r\n");

    for(;;)

    {

        while(rx_1_read_index != rx_1_write_index) {

            if (is_delimiter(rx_1_buf[rx_1_read_index])) {

                str_1_buf[str_1_index] = 0 ;

                UART_1_UartPutString(str_1_buf) ;

                UART_1_UartPutString("\n") ;

                str_1_index = 0 ;

            } else {

                str_1_buf[str_1_index++] = rx_1_buf[rx_1_read_index] ;

                if (str_1_index >= STR_1_LENGTH) {

                    str_1_buf[STR_1_LENGTH] = 0 ;

                    UART_1_UartPutString(str_1_buf) ;

                    str_1_index = 0 ;

                }

            }

            rx_1_read_index = (rx_1_read_index + 1) % BUF_1_LENGTH ;

        }

    }

}

========================

Using CY8CKIT-044 the TeraTerm output looked like

001-TeraTerm-log.JPG

moto

P.S. To extract data from the ring buffer, I had to debug a lot and ended up posting this 3rd version 190401B orz

0 Likes

Hi Motoo,

Thanks for your solution!!

And sorry for late update.

#ifndef STR_1_LENGTH

#define STR_1_LENGTH 32 /* length for UART command input */

#endif

#ifndef BUF_1_LENGTH

#define BUF_1_LENGTH 128

#endif

Can I change these buffers size( 32 ,128 )as per my application?

CyEnterCriticalSection() ;

CyExitCriticalSection(int_flag) ;

Can I use these functions to enable and disable particular interrupt?or

Are they used only for enable/disable all interrupts?

Here i will explain you what i want to implement.

I want to use GSM, GPS, RS232, and RS485 for that i require 4 uarts and I

want to use UART Rx interrupt for both RS232 and RS485 to receive data.

And data string which i am going to receive on RS232 and Rs485 is longer

than 100byte or 200 bytes.

For every 1 or 2 sec, i will have a data string from RS485 and i want send

that received data to server using GSM.

In-between transmitting data to gsm and receiving data from GPS if

interrupt comes,is it going to make any problem?

Because for every received byte, interrupt is generating.

As you know,when we send AT command to GSM module, it sends response,so in

between reading response if i get RS485 RX interrupt there is chance that I

might get miss any response byte from GSM.

Can you suggest me how can I take care of interrupt in this situation.

Please help me on this.

Thanks and regards,

Amit.

On Sun, Mar 31, 2019, 7:50 AM Motoo Tanaka <community-manager@cypress.com>

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Dear Amit-san,

> Can I change these buffers size( 32 ,128 )as per my application?

I think so. (you can change them as you like)

But I recommend you to have BUF_LENGTH > STR_LENGTH

so that the UART module will not miss the byte while software can not serve it.

> CyEnterCriticalSection() ;

> CyExitCriticalSection(int_flag) ;

>

> Can I use these functions to enable and disable particular interrupt?or

> Are they used only for enable/disable all interrupts?

This was added to protect the rx_buf[] while unloading the data from UART's rx_buffer.

So if each UART has own rx_buffer (like rx_1_buf, rx_2_buf ..) and

if you are not writing data to that rx_buffer outside of MyRxNInt

this protection may not be necessary, especially, when you need other interrupts to be active.

> And data string which i am going to receive on RS232 and Rs485 is longer

> than 100byte or 200 bytes.

I would recommend you to set the rx_buffer size of UART of RS232 and RS485

longer than the data string, so that missing data will not happen.

When long buffer size is assigned in the Configure of UART,

software ring buffer scheme is used as below.

From the UART Datasheet

===============

The RX buffer size parameter defines the size (in bytes/words) of memory allocated for a receive data buffer. The RX buffer size minimum value is equal to the RX FIFO depth. The RX FIFO is implemented in hardware. Values greater than the RX FIFO depth up to (232 – 2) imply usage of the RX FIFO, a circular software buffer controlled by the supplied APIs, and internal ISR.

===============

> As you know,when we send AT command to GSM module, it sends response,so in

> between reading response if i get RS485 RX interrupt there is chance that I

> might get miss any response byte from GSM.

If you set rx_buffer size for the UART module long enough and the command from RS232 or RX485 won't come without interval missing response should not happen.

Testing should be required to confirm it though.

So I think that  assigning enough long rx_buffer(s) for each UARTs will be necessary for your application.

Best Regards,

4-Apr-2019

Motoo Tanaka

0 Likes

Thanks Motoo for your quick response.

I will make changes and let you know the result.

Regards,

Amit

On Thu, Apr 4, 2019, 12:55 PM Motoo Tanaka <community-manager@cypress.com>

lock attach
Attachments are accessible only for community members.
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

amitjori7,

attached is example of fixed function SCB UART Rx for PSoC4200M (KIT-044M). In this demo, simple text commands (e.g. "R255", "G127", "B10") from UART terminal (like TeraTerm or Putty) are used to control RGB LED intensity. Do not forget to use CR, LF (or both) when sending control commands.

I believe that KIT-044 should fit up to 8 SCB UARTs.

/odissey1

UART_SCB_Rx_01.png


0 Likes