Example code for RX65N Envision dev board with GCC RX compiler

There seems to be little example code around for the RX65N Envision kit in general, and even less when using the GCC-RX compiler. I've seen a request or two here for a simple hello world type application. The example app that Renesas supplies for this board using their compiler is complicated and tied in to Emwin, so I've put together a much simpler one for anyone who's interested. It has touch screen and LCD drivers incorporated, all using direct register access, but neatly abstracted away into a simple API. The app reads touch screen coordinates and plots a box on the screen displaying the touch point screen coordinate inside it as text. The main function is effectively this...

system_clock_config();
touch_init();
lcd_init();

lcd_filled_rectangle(0, 0, 480, 272, RED);

while (true)
{
    touched = touch_get_point(&x, &y);
    if (touched)
    {
        if (x < 450 && y < 240)
        {
            lcd_filled_rectangle(x, y, 30, 32, BLACK);
            itoa(x, text, 10);
            lcd_string(x, y, text, WHITE);
            itoa(y, text, 10);
            lcd_string(x, y + 16, text, WHITE);
        }
    }
}

Colours parameters to the lcd_* functions are in 24 bit (RGB888) format even though the display uses 16 bit (RGB565) format and are downsized in the functions. I know this is inefficient, but in demo code it's more intuitive to deal with RGB888 format colours.

I've created an e2studio project (version 7.2.0) and the GCC RX version used is 4.8.4.201803-GNURX. All the project files and source are in in the EnvisionDemo1 folder in github here...

https://github.com/miniwinwm/RenesasEnvisionGCC

If anyone finds this useful I'll do some more examples projects. I also have it working using the cc-rx compiler if anyone is interested in that.

  • Hi John,

    Thanks for sharing this one. Yes, if you can share more application projects for RX65N, that would be very helpful. Thank you very much.

    JB
    RenesasRulz Forum Moderator

    https://renesasrulz.com/
    https://academy.renesas.com/
    https://en-us.knowledgebase.renesas.com/

  • I've added another simple project which writes and reads from the on-chip data flash memory. This project includes a driver for writing a variable length data structure always to the start of the data flash memory (this can easily be changed in the driver code if required). The driver uses direct register access but has a simple API so that the main program is this...

    system_clock_config();

    non_vol_save((uint8_t *)&test_data_1, sizeof(test_data_t));
    non_vol_load((uint8_t *)&test_data_2, sizeof(test_data_t));

    if (memcmp(&test_data_2, &test_data_1, sizeof(test_data_t)) == 0)
    {
        success = true;
    }
    else
    {
        success = false;
    }

    This one is in the EnvisionDemo2 sub-folder in the same Github repo as above.

    Also I've added in the repo's README.md file instructions on how to create a project for the Envision Kit using GCC RX, including instructions on how to change the default stack size from the default 256 to something larger.

  • There's now a 3rd one up. This one sets up GLCDC to use both display buffers. The primary buffer (2) is configured as before as 16bit RGB565 format, but this time the secondary buffer (1) is configured as 1 bit monochrome.

    On running the app the primary colour one is shown most of the time with a simple moving graphic display, but at the same time the LCD API can be used to write text and scroll it to the secondary monochrome buffer (1). This is not shown until the user button is pressed when the buffer shown flips from primary to secondary when the button is pressed. When the button is released it reverts to showing the primary display.

    Thought this could be useful when developing a UI application - show your UI using the primary buffer but log text output to the secondary buffer and flip to it temporarily at any time by pressing the user button.

    The main loop is this...

    while (true)
    {
        i++;
        if (i > 250)
        {
            i = 0;
        }

        // plot and scroll text on gr1
        lcd_string_1(0, 261, "Test text");
        itoa(i, num_buf, 10);
        lcd_string_1(60, 261, num_buf);
        lcd_scroll_display_up_1(10);
        delay_ms(500);

        // simple moving graphic on gr2
        lcd_filled_rectangle_2(0, 0, 480, 272, RED);
        lcd_filled_rectangle_2(i, i, 20, 20, BLUE);
        delay_ms(500);
    }

    Flipping the displayed buffer is done in the button press interrupt handler...

    void INT_Excep_ICU_IRQ13(void)
    {
        if (PORT0.PIDR.BIT.B5 == 0U)
        {
            lcd_select_buffer(1);
        }
        else
        {
            lcd_select_buffer(2);
        }
    }

    The calls to the LCD driver via the lcd_* functions now have a _1 or _2 at the end of the name to set the buffer the output goes to.

  • Another one today, number 4. This is a port of FreeRTOS version 10.2.0 to run on the Envision Kit. It uses the RX600v2 for GCC port layer available on the FreeRTOS website and bits from the FreeRTOS example project for the RX64M processor.

    The example app creates 3 tasks and does a bit of task synchronization between them. Apart from that it does nothing, but the 3 tasks can be seen running using breakpoints and the debugger.

    This is by no means a tested verified port of FreeRTOS to the RX65N, it's just a bit of amateur tinkering, so should be used as demonstration, hobbyist or prototype code only, and not be used in a commercial product.

    It can be found under EnvisionDemo4 in GitHub here...

    github.com/.../RenesasEnvisionGCC

  • Number 5 - real time clock example.

    The Envision Kit does not have a 32.768 kHz crystal fitted to drive the sub-clock, but the main 12 MHz clock can be used, although it's likely to be less accurate.

    This example has drivers written going directly to registers and provides a simple API for initialising the RTC, settings and getting the time, and a simple main program that uses them that looks like this...

    tm_t t1 = {0};
    tm_t t2 = {14, 11, 17, 22, 2, 118};

    system_clock_config();
    rtc_init();
    rtc_set_time(&t2);

    while (true)
    {
        rtc_get_time(&t1);
        delay_us(1000000);
    }

    The driver code shows an example of setting up a software configurable interrupt which is needed when reading the time from the RTC.

    The git link is here...

    https://github.com/miniwinwm/RenesasEnvisionGCC/tree/master/EnvisionDemo5

  • Number 6 is up. This one gets the open source FAT file system library, FatFS, working on the Envision Kit.

    There are some issues with getting FatFS working on this board. Using CC-RX and FIT libraries it's easy - use the Renesas supplied USB host library, the Mass Storage Class library, and even their own cut down version of FatFS, all integrated for you. Without these libraries for GCC, it's not so easy.

    A first alternative is to use the RX65N SD interface with an on-board SD card reader, for which there is board space but no hardware. Unfortunately, the SD card reader Renesas specified is unusual, single manufacturer, and now discontinued. 

    A third solution, and the one used in this example, is to get an external SD card reader with SPI connections designed for Arduino projects (cheaply available from EBay for less than five $£€) and attach it to the Pmod connector CN14. The SPI interface is the easiest to get going from the 3 communications protocols, if the slowest. It runs at 1Mbit per second, so is fine for small slow speed file access.

    A simplistic synchronous SPI driver has been created for this project, using direct register access, for the SPI connections available on the Pmod connector, SCI2. This has been integrated with the SD interface part of FatFS, which means that the full FatFS API can be used once the hardware has been initialized. The default stack size needs to be increased from 256 bytes to 1024 bytes, and will need increasing again if any FatFS objects are local variables.

    The main program to initialize FatFS, create a file, write to it and close it looks like this...

    sci2_spi_init();
    f_mount(&FatFs, "", 0U);
    if (f_open(&Fil, "miniwin.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK)
    {
        f_write(&Fil, "FatFS for Renesas Envision Kit\r\n", 32U, &bytes_written);
        f_close(&Fil);
    }

    The external SPI SD card reader is connected like this (details in the project readme.txt)...

      

    This is only a simple demonstration project. It's not quick, thread safe or asynchronous, and has no error checking, but might be a useful starting point if further features are required. The project is in github here...

    github.com/.../EnvisionDemo6

  • Three more simple examples up...

    EnvisionDemo7 - Creates a compare/match timer and flashes the user LED 

    EnvisionDemo8 - Reads the on-chip temperature sensor and calculates the chip temperature (this is almost always a few degrees higher than the environment temperature because of the heat generated by the processor).

    EnvisionDemo9 - Simple interrupt on both edges of a GPIO change. Pressing the user button changes the state of the user LED.

     

    All at the usual place in Github...  github.com/.../RenesasEnvisionGCC

  • A couple of PWM examples.

    Number 10 uses the simple 8 bit timer in PWM mode to control P55 that's available on the Pmod connector (CN14). By putting a LED in series with a resistor between this connection and the ground line also available on the Pmod connector the brightness of the LED can be varied.

    Number 11 is also PWM, but a bit more complex. This demonstration shows how to use the Multi-Function Timer Pulse Unit 3 module (MTU3) for PWM generation to control the level of the Envision Kit's display's backlight.

    Although this module can do simple PWM output that's not available on the pin that the backlight enable line is on (P66). This pin is only available for MTU3 PWM using one PWM output line of complementary PWM or reset synchronized PWM. Reset synchronized PWM is simpler, so that is used. The MTU3 knows this output as MTIOC7D, and is one of multiple output lines controlled in reset synchronized PWM. The other lines in this example are unused.

    Reset synchronized PWM requires 2 timers to be used, which for this output pin to be controlled need to be timers 6 and 7.

    Buffering of the PWM timing registers is used to keep the timing and counting consistent, although the cycle period is fixed, so it's only the duty value that is changed.

    The code goes straight to I/O registers but a simple API is available to set the backlight percentage. The code in main to control the backlight looks like this...

    backlight_init();

    while (true)
    {
        duty += 1U;
        if (duty > 100U)
        {
            duty = 0U;
        }

        backlight_set(duty);

        delay_us(10000);

    }

  • Number 12 - a DMA example which uses both peripheral triggered and software triggered DMA to send a bitmap to the Envision kit's display.

    This demonstration shows how to use the DMA to copy from memory to memory. The LCD is set up to show 16 bit RGB565 data. A bitmap is included that is in the same format as the display. DMA is used to copy the bitmap data to the display buffer.

    As the bitmap is less wide than the display, to copy the bitmap to the display buffer, non-contiguous DMA is required. The copy process is split into sections where one section is a horizontal line of the bitmap.

    The copy process is initiated by pressing the user button. DMA channel 0 is initialized to start its transfer on a peripheral interrupt. The user button is initialized to create IRQ13 when it is pressed and the DMA channel is configured to be triggered by this interrupt.

    When a line has been copied by DMA a DMA transfer complete interrupt is generated. This updates the destination address to the next line in the display buffer and the next DMA transfer is initiated by software. All subsequent transfers for the remaining bitmap lines are software initiated.

    The example goes directly to registers. When the application is  running press the user button. On each press the bitmap is copied to the display buffer (for 3 presses after which the display is full).

  • Number 13 - an independent watchdog example.

    This example demonstrates the independent watchdog in window mode. The watchdog cycles is set to approximately 4 seconds and the window in which the watchdog is allowed to be kicked is the middle 2 seconds of that period (after 1s, before 3s). Kicking the watchdog outside of that window, or not kicking it at all, causes a reset. After a reset the reset cause is determined and displayed.

    The watchdog is set up to start running automatically at reset. This requires configuring the watchdog in the Option Setting Memory, in register OFS0. The value of the register is hard coded in the e2studio generated file vects.c near the bottom of the file. This file has been edited manually to set this register value.

    The watchdog in this example is kicked by pressing the user button. The state of the watchdog cycle is shown on the LCD. Pressing the user button at the appropriate time according to the message displayed will allow the application to continue. Pressing the button too early or too late according to the messages will cause a reset and restart.

    The text displayed does not scroll. When it reached the bottom of the display - that's it.