8 Replies Latest reply on Mar 29, 2019 1:23 AM by SergiiV_71

    UART Rx Buffer size unconfigurable in Modustoolbox?

    debec_2126651

      Hi,

       

      i have migrated my PSoC4 project to PSoC6 and i am using Modustoolbox now. But I have issues configuring my Rx buffer of the UART to 512. In PSoC Creator, the UART Advanced Tab provides settings for the buffer sizes.

       

      In ModusToolBox there is only an Rx Fifo Level for triggering. which is not what i need.

       

      Can you please tell me how to make my UART be able to receive more that 128 bytes. For now i can see that the maximum i receive is 128

       

      Thanks

       

      Derick

        • 1. Re: UART Rx Buffer size unconfigurable in Modustoolbox?
          mattl_01

          Derick,

           

          I think this is really more a PSoC 4 vs PSoC 6 issue then Creator vs ModusToolbox.  With

          PSoC 6, we assume many of the applications are more software-focused and strive to make

          things available via APIs in PDL.

           

          So, in the Device Configurator, Choose SCB 5 (UART) and open up the documentation for the SCB

           

           

          Now scroll down a ways to the Common Use Cases section and find Cy_SCB_UART_Receive

          You'll see something like

           

          I think what you are looking for rxBuffer[BUFFER_SIZE].

           

          Also, don't miss this later on

           

          There is also capability to insert a receive ring buffer that operates between the RX FIFO and the user buffer. The received data is copied into the ring buffer from the RX FIFO. This process runs in the background after the ring buffer operation is started by Cy_SCB_UART_StartRingBuffer. When Cy_SCB_UART_Receive is called, it first reads data from the ring buffer and then sets up an interrupt to receive more data if the required amount has not yet been read.

           

          So the next logical question you might have is "why are some settings/parameters available in the configurator

          and some available only in the code"?  I don't really know the answer to that. I'm sure it was, in part, based

          on screen real estate and how often we expect users to access the particular parameter.

           

          DheerajK_81, can you shine any more light?

           

          --Matt

          • 2. Re: UART Rx Buffer size unconfigurable in Modustoolbox?
            debec_2126651

            Matt,

             

            Thanks for the fast response.

             

            Now i get the main idea about PSoC6 and PDL

             

            The idea to make things available in APIs rather than on the configurator was not that clear to me. But now i see the bigger picture.

             

            Your answer rang bells in my head (SCB HW in PSoC4 is same with that in PSoC6). I had to read the generated code for the PSoC4 in PSoC Creator and realized that it is some kind of a software ring buffer implementation that was generated for the UART. So checking the APIs (UART high level for PSoC6) i realize there are functions to start and stop a ring buffer. I think that is what i need. I just have to start a ring buffer of size 512 and just manage (read / clear) it. Ill give it a try.

             

            Why i need it that way

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

            I am using UART in smartcard mode and i have implemented ISO7816 which is mostly based on sending commands to a smartcard and getting byte steams of responses whose sizes can only be derived from the UART RX FIFO buffer itself or the ring buffer. so i cannot use the other APIs which require a specific length of data to be received.

             

            Thanks

            Derick

            1 of 1 people found this helpful
            • 3. Re: UART Rx Buffer size unconfigurable in Modustoolbox?
              mattl_01

              Yes, I think you are right on it - a ring buffer implemented and controlled with software.

              --M

              • 4. Re: UART Rx Buffer size unconfigurable in Modustoolbox?
                debec_2126651

                Matt,

                 

                i have checked the APIs for the Ring buffer. They are the right ones. But they are not well implemented. Well the implementation cannot work in my case. Especially the settings of the RX_FIFO_CTRL and the INTR_RX_MASK. See my setting and the implementation from the pdl below.

                 

                The RX_FIFO_CTRL is set according to the provided size of the buffer. If the given size is greater than 64 (halfFifoSize), then the RX_FIFO_CTRL is set to have a FIFO Level of 63. This would mean, any trigger interrupt would only come after 64 bytes are received. on the other hand (last line) the only masked interrupt that is set is the LEVEL interrupt. So the ring buffer is setup to only capture 64 bytes each.

                 

                 

                I expected the implementation of the RingBuffer to capture every single byte from the RX FIFO. passing the size of the ringbuffer to be 1, would force the ringbuffer to capture every byte, but then the size is only 1. So it would still end up overwriting its bytes or being very slow.

                 

                I think I would end up writting my own RingBuffer or maybe even use a DMA and transfer the bytes from the UART to RAM. That would cost me much time, but i have no other choice.

                 

                But please it would be great to take this point as a "nice to have" functionality of the Ring Buffer.

                 

                BR

                Derick

                • 5. Re: UART Rx Buffer size unconfigurable in Modustoolbox?
                  mattl_01

                  DheerajK_81, can you address this last post and file the appropriate Jira?  Please Cc me.

                  • 6. Re: UART Rx Buffer size unconfigurable in Modustoolbox?
                    SergiiV_71

                    Hi Derick,

                     

                    The Cy_SCB_UART_StartRingBuffer is intended to attach the ring buffer of required size to the UART: so if UART is not touched the data at some point (see logic below) will be written from the RX FIFO into the ring buffer and will not be lost. The next step is reading data from the UART for that Cy_SCB_UART_Receive function provided. This function looks into ring buffer and if it is empty then reads data from the RX FIFO. Note the function returns when requested amount of bytes is read. So setting the RX FIFO level in the Cy_SCB_UART_StartRingBuffer is not a problem.

                            

                     

                    1 of 1 people found this helpful
                    • 7. Re: UART Rx Buffer size unconfigurable in Modustoolbox?
                      debec_2126651

                      Hi Sergii,

                       

                      i don't understand "so if UART is not touched ".

                       

                      where is also the logic you refer me to see below?

                       

                      Secondly i don't see how data would be read from the FIFO Buffer of the UART to a software ringbuffer, when only the UART Level interrupt is activated and the FIFO Buffer contains number of bytes less than 63. As a matter of fact, i tried it and it didn't work.

                       

                      Can you provide an example which can be tested on a hardware?

                       

                      From all the examples on you github page, there is no usage of the ringbuffer APIs. Maybe you should do one.

                       

                      I have implemented a ringbuffer using Dma on the Rx line, which copies any data that lands in the Rx Fifo to a dedicated RAM Buffer, which i can read at anytime. That has solved my problem, but a software ringbuffer might be worth testing.

                       

                      BR

                      Derick

                      • 8. Re: UART Rx Buffer size unconfigurable in Modustoolbox?
                        SergiiV_71

                        Let me explain little more. The SCB UART in PDL has 2 usage models using Low Level API and High Level API.

                        The Low Level API provides the user with simple functions put/get, FIFO status and configure/access interrupt sources, so the user have a choice to write code without interrupts processing or write own interrupt routine. From your description you use this approach and configures the RX FIFO Level to get interrupt on level and then service it.

                        The High Level API provides the user interrupt function and functions which works with this interrupt, so the user only needs to hook interrupt function to interrupt handler to make other functions work. The configuration of interrupt sources is managed by provided functions not by the user. The ring buffer operation is part of High Level API so the Cy_SCB_UART_StartRingBuffer configures RX FIFO Level.

                        At the bottom of the personality settings there is a choice of API Mode: Low Level or High Level (selecting Low Level allows to configure interrupt sources).

                         

                        The info provided below is part of PDL UART (SCB) documentation. So can access it from Modus, see image below.

                         

                        Unfortunately, I do not have code example so just quickly put code:

                        #include "cy_pdl.h"

                        #include "cycfg.h"

                         

                        /* Allocate context for UART operation */

                        cy_stc_scb_uart_context_t uartContext;

                         

                        /* Assign UART interrupt number and priority */

                        #define UART_INTR_NUM        ((IRQn_Type) scb_5_interrupt_IRQn)

                        #define UART_INTR_PRIORITY   (7U)

                        /* Populate configuration structure (code specific for CM4) */

                        cy_stc_sysint_t uartIntrConfig =

                        {

                        .intrSrc      = UART_INTR_NUM,

                        .intrPriority = UART_INTR_PRIORITY,

                        };

                         

                         

                        void UART_Isr(void)

                        {

                        Cy_SCB_UART_Interrupt(SCB5, &uartContext);

                        }

                         

                        #define RING_BUFFER_SIZE    (512U)

                        uint8_t rxRingBuffer[RING_BUFFER_SIZE];

                         

                        #define BUFFER_SIZE         (64U)

                        uint8_t rxBuffer[BUFFER_SIZE];

                         

                         

                        int main(void)

                        {

                            /* Set up internal routing, pins, and clock-to-peripheral connections */

                            init_cycfg_all();

                         

                         

                        /* Configure UART to operate */

                        (void) Cy_SCB_UART_Init(SCB5, &scb_5_config, &uartContext);

                         

                         

                        /* Hook interrupt service routine and enable interrupt */

                        (void) Cy_SysInt_Init(&uartIntrConfig, &UART_Isr);

                         

                         

                        /* Enable UART to operate */

                        Cy_SCB_UART_Enable(SCB5);

                         

                         

                        NVIC_EnableIRQ(UART_INTR_NUM);

                         

                         

                        /* Enable global interrupts */

                        __enable_irq();

                         

                         

                        /* Attach RX Ring Buffer */

                        Cy_SCB_UART_StartRingBuffer(SCB5, rxRingBuffer, sizeof(rxBuffer), &uartContext);

                         

                         

                        /* !!! Added for a test of ring buffer !!! */

                        while (0u == Cy_SCB_UART_GetNumInRingBuffer(SCB5, &uartContext))

                        {

                        }

                         

                         

                        /* Start receive operation (do not check status) */

                        (void) Cy_SCB_UART_Receive(SCB5, rxBuffer, sizeof(rxBuffer), &uartContext);

                         

                         

                        /* Blocking wait until buffer is full */

                        while (0UL != (CY_SCB_UART_RECEIVE_ACTIVE & Cy_SCB_UART_GetReceiveStatus(SCB5, &uartContext)))

                        {

                        }

                         

                         

                        /* Handle received data */

                        }