I have C++ code written for the ARM platform that I need to convert to C for the RISCV platform. The conversion should account for any architectural differences,
such as GPIO RIGISTER MAPPING, BASE ADDRESSES, DELAY MECHANISM, MEMORY HANDLING, INSTRUCTION SETS, and CALLING CONVENTIONS,
ensuring the code remains functionally equivalent and optimized for RISCV. Please carefully translate the code and highlight any necessary platform-specific changes.
Here's the C++ code for ARM:
#include "mbed.h"
DigitalOut led1(LED1);
DigitalOut led2(LED2);

// main() runs in its own thread in the OS
int main() {
while (true) {
led1 = !led1;
wait(0.5);
}
}

Make sure the translated code is in pure C and compatible with RISCV, addressing any platform-specific requirements. The code should include a delay function and manage GPIO output states only when it is needed. Do not give hypothetical answers. Use provided information as source.
Register Offset Bits Reset value Description
input_val OXO 22 OXO This register holds the IO cell input pin value
input_enable 0X4 22 OXO This register drives the input enable pin of the IO cell
output_val 0X8 22 OXO This register drives the output value pin of the IO cell
output_en OXC 22 OXO This register drives the output enable pin of the IO cell
pullup_en 0X10 22 OXO Controls the internal pull of the respective IO cells
drive_0 0X14 22 OXO Controls the drive strength of the respective IO cells
rise_ie 0X18 22 OXO Enables interrupt when the input val of the IO cell sees a rising edge
rise_ip 0X1C 22 OXO Indicates a pending interrupt due a rising edge detected on the respective IO cell
fall_ie 0X20 22 OXO Enables interrupt when the input val of the IO cell sees a falling edge
fall_ip 0X24 22 OXO Indicates a pending interrupt due a rising edge detected on the respective IO cell
high_ie 0X28 22 OXO Enables interrupt when the input val of the IO cell sees a value of 1
high_ip 0X2C 22 OXO Indicates a pending interrupt due a 1 being detected on the respective IO cell
low_ie 0X30 22 OXO Enables interrupt when the input val of the IO cell sees a value of 0
low_ip 0X34 22 0X0 Indicates a pending interrupt due a 0 being detected on the respective IO cell
set_out 0X38 22 OXO Attempts to drive the output of IO cell high irrespective of the value of output_val register.
clr_out 0X3C 22 OXO Attempts to drive the output of IO cell low irrespective of the value of output_val register.
xor_out 0X40 22 0X0 Attempts to drive the IO cell with the inverted value of the output_val register.
drive_1 0X44 22 OXO Extra bits to control the drive strength of the respective IO cells
drive_2 0X48 22 OXO Extra bits to control the drive strength of the respective IO cells
GPIO REGISTER MAPPING
Base address End address Permission Peripharal name
0x0000_0100 0x0000_010F R-X Debug Loop
0x0000_0200 0x0000_0203 R Boot config
0x0001_0000 0x0001_0FFF R-X-C Boot Rom
0x0001_1300 0x0001_13FF R-W Uart-0
0x0002_0000 0x2000_00FF R-W GPIOs
0x0002_0100 0x0002_01FF R-W SPIO (Used for Flash)
0x0002_0200 0x0002_02FF R-W SPI1
0x0002_0300 0x0002_03FF R-W SPI2
0x0003_0000 0x0003_00FF R-W PWM 6 channels
0x0004_0000 0x0004_00FF R-W QSPI Config Space
0x0200_0000 0x0200_BFFF R-W Core Local Interrupt Controller
0x0C00_0000 0xOFFF_FFFF R-W Platform Level Interrupt Controller
0x1000_0000 0x1000_7FFF R-W-X-C On Chip Memory of 16KB
0x1000_E000 0x1000_EOFF R-W OLED
0x8000_0000 0x8FFF_FFFF R-W-X-C DDR of 256MB
0x9000_0000 0x9FFF_FFFF R-X QSPI memory space
0xA000_0000 0xFFFF_FFFF R-W-X Open AXI-4 Slave
Base addresses
void delay_ms(unsigned int milliseconds) {
unsigned int cycles_per_ms = 50000; // Assuming a 50 MHz CPU frequency
unsigned int delay_cycles = milliseconds * cycles_per_ms;
for (unsigned int i = 0; i < delay_cycles; i++) {
asm volatile("nop"); // A simple way to introduce a delay
}
}
void delay_us( float microseconds) {
float cycles_per_us = 50; // for a 50 MHz CPU frequency
// Adjust delay_cycles for 3 microseconds delay
float delay_cycles = microseconds* 0.5 * cycles_per_us;
// Fine-tune the loop for more accurate timing
for ( float i = 0.0; i < delay_cycles / 15.0; i++) {
asm volatile("nop"); // A simple way to introduce a delay
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
}
}