Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Common neorv32 uart functions #509

Merged
merged 20 commits into from
Mar 4, 2023

Conversation

akaeba
Copy link
Collaborator

@akaeba akaeba commented Feb 25, 2023

Use common UART functions, see #499 for details.

@stnolting
Copy link
Owner

This looks good!

I think it would be cleaner to move all "legacy function wrappers" to sw/lib/include/legacy.h.

What about the neorv32_uart*_available and neorv32_uart*_setup functions? Shouldn't these also be generalized?

@stnolting stnolting added SW software-related coding-style Related to the HW/SW coding style labels Feb 25, 2023
@emb4fun
Copy link
Collaborator

emb4fun commented Feb 26, 2023

I have closed my PR because some of the tests was negative and I do not know why, and could not find the problem.

What about the neorv32_uart*_available and neorv32_uart*_setup functions? Shouldn't these also be generalized?

Yes both functions should also be generalized I think. If you need help, give me a sign.

I would also change two other points.

First: I would like to change the definition for the NEORV32_UART0. At the moment the define looks like:

#define NEORV32_UART0 (*((volatile neorv32_uart_t*) (NEORV32_UART0_BASE)))

I would like to change to:

#define NEORV32_UART0 ((volatile neorv32_uart_t*) (NEORV32_UART0_BASE))

This has the disadvantage that you cannot set the CTRL variable as follows, for example:

NEORV32_UART0.CTRL = 0;

But you have to use the following variant with the "pointer character":

NEORV32_UART0->CTRL = 0;

But this reflects what it really is, a pointer and not a "variable". Yes, that's a bit more work at first, but the changes should only be in the neorv32_uart.c file.

Of course, with this change, the macro must also look slightly different:

#define neorv32_uart1_disable() neorv32_uart_disable(NEORV32_UART0)

Here the "&" character in front of NEORV32_UART0 has now been removed.


Second: I would like to change the new parameter "self" to "UARTx":

void neorv32_uart_enable(volatile neorv32_uart_t *self);

Will be changed to:

void neorv32_uart_enable(volatile neorv32_uart_t *UARTx) ;

And now inside the functions it will look like:

UARTx->CTRL |= ((uint32_t)(1 << UART_CTRL_EN));

That somehow shows better what it is than using "self" here.

@akaeba
Copy link
Collaborator Author

akaeba commented Feb 26, 2023

@emb4fun : let us work together on this PR.

As next I introduce Stephans recommendation to move the c macros to the legacy.h function.

@akaeba
Copy link
Collaborator Author

akaeba commented Feb 26, 2023

This looks good!

I think it would be cleaner to move all "legacy function wrappers" to sw/lib/include/legacy.h.

done in f22bafe

@akaeba
Copy link
Collaborator Author

akaeba commented Feb 26, 2023

Second: I would like to change the new parameter "self" to "UARTx":

@emb4fun : now i work on this.

@akaeba
Copy link
Collaborator Author

akaeba commented Feb 26, 2023

@emb4fun : your second recommendation is implemented in 5c7c6ec.

@akaeba
Copy link
Collaborator Author

akaeba commented Feb 26, 2023

@embfun: i did also a rebase, now the branch should be on main. Therefore the changes of neorv32.h should possible.

@emb4fun
Copy link
Collaborator

emb4fun commented Feb 26, 2023

Hello akaeba,

the changes are looking good so far. But I am missing the first point.
I would like to change the definition for the NEORV32_UART0. At the moment the define looks like:

#define NEORV32_UART0 (*((volatile neorv32_uart_t*) (NEORV32_UART0_BASE)))

I would like to change to:

#define NEORV32_UART0 ((volatile neorv32_uart_t*) (NEORV32_UART0_BASE))

Or do you not want to take over this?

It looks that the following functions was not "translated":

neorv32_uart0_available
neorv32_uart1_available
neorv32_uart0_setup
neorv32_uart1_setup

Should I send you an example for these?

Best regards,
Michael

@akaeba
Copy link
Collaborator Author

akaeba commented Feb 26, 2023

Should I send you an example for these?

Yes please.

@emb4fun
Copy link
Collaborator

emb4fun commented Feb 26, 2023

For neorv32_uart_available the source could look like:

int neorv32_uart_available (volatile neorv32_uart_t *UARTx)
{
   int available = 0;
   
   if( ((int)UARTx == NEORV32_UART0_BASE) && (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART0)) )
   {
      available = 1;
   }
   
   if( ((int)UARTx == NEORV32_UART1_BASE) && (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART1)) )
   {
      available = 1;
   }
   
   return(available);
}

@emb4fun
Copy link
Collaborator

emb4fun commented Feb 26, 2023

What is your problem with the setup functions?

@stnolting
Copy link
Owner

stnolting commented Feb 26, 2023

@emb4fun

Your setup functions proposal looks good! 👍

Second: I would like to change the new parameter "self" to "UARTx":

I agree here.

First: I would like to change the definition for the NEORV32_UART0. At the moment the define looks like: [...]

If we change the way of accessing low-level register to the "pointer style" then the only the UARTs would requires this style while all remaining modules would still require "variable style". I think we should keep this identical across all modules.

However, I like the pointer concept. Maybe we can change that for all modules in a future PR?! 😉

@stnolting stnolting marked this pull request as draft February 26, 2023 17:43
@emb4fun
Copy link
Collaborator

emb4fun commented Feb 26, 2023

@stnolting

we should discuss about the use of "volatile" too.

I think the keyword volatile is used here wrong in this project.
You actually want to achieve that the structure with which you access the device gets the volatile property.
But in case of the UART functions the volatile is used for the UARTx pointer like:

void neorv32_uart_enable(volatile neorv32_uart_t *UARTx);

If I have understood that correctly, only the pointer is volatile here, but not the structure to which the pointer points.
You would have to make the structure itself volatile here:

typedef volatile struct __attribute__((packed,aligned(4))) {
  uint32_t CTRL;  /**< offset 0: control register (#NEORV32_UART_CTRL_enum) */
  uint32_t DATA;  /**< offset 4: data register (#NEORV32_UART_DATA_enum) */
} neorv32_uart_t;

And now the prototype and function can be used without the volatile keyword:

void neorv32_uart_enable(neorv32_uart_t *UARTx);

Or you can also make every single register volatile via __IO. That was the suggestion I had made before #499.

However, I like the pointer concept. Maybe we can change that for all modules in a future PR?! 😉

Be careful with your wishes 😉

@akaeba
Copy link
Collaborator Author

akaeba commented Mar 4, 2023

For neorv32_uart_available the source could look like:

int neorv32_uart_available (volatile neorv32_uart_t *UARTx)
{
   int available = 0;
   
   if( ((int)UARTx == NEORV32_UART0_BASE) && (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART0)) )
   {
      available = 1;
   }
   
   if( ((int)UARTx == NEORV32_UART1_BASE) && (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART1)) )
   {
      available = 1;
   }
   
   return(available);
}

added in 269cc45

@stnolting
Copy link
Owner

Looks good so far! 👍

Only the setup function is still missing, right?

Seems like we have some merge conflicts here... @akaeba can you resolve those after completing your updates? 😉

@akaeba
Copy link
Collaborator Author

akaeba commented Mar 4, 2023

Only the setup function is still missing, right?

Yes, try to use same approach, like in the available functions?

What about the volatile, should I try to implement this approach:

#define __IO	volatile

typedef struct
{
   __IO uint32_t CTRL;
   __IO uint32_t DATA;
} UART_TypeDef;

but only for UART for start, the rest comes with every single change and the sw framework.

Seems like we have some merge conflicts here... @akaeba can you resolve those after completing your updates? 😉

Yes i can try.

@stnolting
Copy link
Owner

Yes, try to use same approach, like in the available functions?

I do not think an if-else is required as you can use the passed pointer for configuring the according control register.

Yes, try to use same approach, like in the available functions?

Right now we all structs are of type typedef volatile struct - I think that is ok for now.

but only for UART for start, the rest comes with every single change and the sw framework.

We can discuss this in a new issue (let's not change too much within a single PR 😉).

Yes i can try.

👍

@akaeba
Copy link
Collaborator Author

akaeba commented Mar 4, 2023

We can discuss this in a new issue (let's not change too much within a single PR 😉).

Perfect, let's bring this PR to main :)

@akaeba
Copy link
Collaborator Author

akaeba commented Mar 4, 2023

I do not think an if-else is required as you can use the passed pointer for configuring the according control register.

the issue is with the UART0_SIM_MODE and UART1_SIM_MODE. In the legacy variant would it be easy. but here i need to distinguish between UART0/1:

#ifdef UART_SIM_MODE
  #warning <UART_SIM_MODE> is obsolete (but still supported for compatibility). Please consider using the new flag <UART0_SIM_MODE>.
#endif
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
  #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only!
  uint32_t sim_mode = 1 << UART_CTRL_SIM_MODE;
#else
  uint32_t sim_mode = 0;
#endif

@stnolting
Copy link
Owner

I made a proposal for this in #499 (reply in thread):

// setup UART0
// ...
uint32_t sim_mode = 0;
#ifdef UART0_SIM_MODE
#warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only!
  if ((uint32_t(&self) == NEORV32_UART0_BASE) then {
    sim_mode = 1 << UART_CTRL_SIM_MODE;
  }
#endif
// ...

@akaeba
Copy link
Collaborator Author

akaeba commented Mar 4, 2023

I made a proposal for this in #499 (reply in thread)

oh, i don't had in mind.

@akaeba
Copy link
Collaborator Author

akaeba commented Mar 4, 2023

@stnolting : I think it's mostly done.

@emb4fun
Copy link
Collaborator

emb4fun commented Mar 4, 2023

Hello akaeba,

please take a look at the definitions too. The UART definitions looks like:

typedef struct attribute((packed,aligned(4))) {
uint32_t CTRL; /< offset 0: control register (#NEORV32_UART_CTRL_enum) */
uint32_t DATA; /
< offset 4: data register (#NEORV32_UART_DATA_enum) */
} neorv32_uart_t;

Here I think the volatile was missing:

typedef volatile struct attribute((packed,aligned(4)))

At the same time, the definition of the UART_POINTER can be changed like:

/** UART0 module base address */
#define NEORV32_UART0_BASE (0xFFFFFFA0U)

/** UART0 module hardware access (#neorv32_uart_t) /
#define NEORV32_UART0 ((neorv32_uart_t
) (NEORV32_UART0_BASE))

/** UART1 module base address */
#define NEORV32_UART1_BASE (0xFFFFFFD0U)

/** UART1 module hardware access (#neorv32_uart_t) /
#define NEORV32_UART1 ((neorv32_uart_t
) (NEORV32_UART1_BASE))

And in case of the prototypes in legacy.h, the

&NEORV32_UART0

can be defined in

NEORV32_UART0

Best regards,
Michael

@akaeba
Copy link
Collaborator Author

akaeba commented Mar 4, 2023

@stnolting : now fails the checks. Could you please check where is the issue, probably a timing issue?

6094755000000 fs - UART1.RX                     -   ERROR - Equality check failed - Got cr. Expected 0.

@stnolting
Copy link
Owner

I'll have a look.

@stnolting
Copy link
Owner

Simulation mode of UART0 is never enabled, which leads to a simulation fail.

I think there is a problem with the code I have posted and the actual definition of the UART structs as (uint32_t) &UARTx does not return the actual base address.

@emb4fun has already converted the type of all "hardware handle structs" to typedef volatile struct. I suggest to to the same here. I'll take care of that if you agree and then we can re-evaluate 😉

@stnolting stnolting marked this pull request as ready for review March 4, 2023 13:20
@akaeba
Copy link
Collaborator Author

akaeba commented Mar 4, 2023

@stnolting great work! Now i think is this branch ready to merge.

@stnolting stnolting merged commit efb94ac into stnolting:main Mar 4, 2023
@akaeba akaeba deleted the common_neorv32_uart_functions branch March 4, 2023 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
coding-style Related to the HW/SW coding style SW software-related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants