Stack Exchange
C macro's argument limiting by argument prefix
I have a set of defined macros as follows.
    #define ARM_FRONT_REG   1
    ..............
    #define ARM_REAR_REG   10
    
    
    #define MOTOR_MAIN_REG   1
    ..............
    #define MOTOR_AUX_REG   3
    
    
    #define MOTOR_REGISTER_ADDRESS(register_offset)      \
         (                                               \
                addr = MOTOR_BASE_ADDR * (1 << BITS_PER_MODULE) + register_offset)                  \                               
          )                                              \
    
    #define ARM_REGISTER_ADDRESS(register_offset)      \
         (                                               \
                addr = ARM_BASE_ADDR * (1 << BITS_PER_MODULE) + register_offset)                  \                               
          )                                              \

I am using macros like
ui_address = ARM_BASE_ADDR (ARM_REAR_REG)
ui_address = MOTOR_REGISTER_ADDRESS (MOTOR_MAIN_REG)

I want to restrict macro usage which is mixed with each other. Is there a way of aborting compiling if macros used as following?
ui_address = ARM_BASE_ADDR (MOTOR_MAIN_REG)
ui_address = MOTOR_REGISTER_ADDRESS (ARM_REAR_REG)

PS :
I have mentioned macros in brief, But actual macros are as below, which used to perform register reads write to Linux driver from user application.
actual struct :
struct hw_register_struct
{
    int  log_level;
    unsigned int reg_addr;
    unsigned int reg_value;
    char    reg_name [MAX_REG_NAME_LENGTH];
    char    application_info [APP_INFO_LENGTH];
};

This macro validates the address is correct per module.
 #define CHECK_ADDR_SUB_MODULE(module_index, sub_module, sub_module_bits, offset, max_reg_count)     
        ({                                                                                              
            unsigned int check_ret = 0;                                                                 
            if(offset >= max_reg_count){                                                               
                hw_register.reg_addr = 0;                                                           
                check_ret = 1;                                                                          
            } else {                                                                                    
                hw_register.reg_addr = (module_index * (1 << BITS_PER_MODULE) + (1 << sub_module_bits) * (sub_module) + offset); 
            }                                                                                           
            check_ret;                                                                                  
        })                                                                                              
    

This macro assigns the address to the variable in the struct.
    #define SEQUENCER_REGISTER_ADDRESS(register_offset)                                       
        ({                                                                                              
            memset((void *)&hw_register, 0, sizeof(struct hw_register_struct));                 
            if(CHECK_ADDR_SUB_MODULE(MODULE_SEQUENCER, 0, register_offset, SEQ_REG_COUNT)){            
                Logger::Print(ERROR_LEVEL, "Invalid Address | Module : %s | Address : %s", STR(MODULE_SEQUENCER), #register_offset); 
            }                                                                                           
            memcpy(hw_register.reg_name, #register_offset, sizeof(#register_offset));               
            hw_register.reg_addr;                                                                   
        })                                                                                              
    
    

Perform calling the ioctl to Linux driver
    #define WRITE_REGISTER_(register_addr, register_value, func, line, log_level_)
        {                                                                                               
            register_addr;                                                                              
            hw_register.reg_value = register_value;                                                 
            hw_register.log_level = log_level_;                                                     
            snprintf(hw_register.application_info, APP_INFO_LENGTH - 1,"%s:%d", func, line);        
            long ret_ioctl = p_IOCTL->IOCTL<struct hw_register_struct>(IOCTL_WRITE, hw_register);  
            if(unlikely(ret_ioctl != 0))                                                                
            {                                                                                                
                Logger::Print(ERROR_LEVEL, "IOCTL WRITE_REGISTER Failed | Reg: %u, Reg Name [ %s ]", hw_register.reg_addr, hw_register.reg_name);
            }                                                                                           
         }    
    
    
    #define WRITE_REGISTER_INFO(register_addr, register_value) WRITE_REGISTER_(register_addr, register_value, __func__, __LINE__, KERN_INFO_LEVEL)


To do that, you would need some data type information, wouldn't you?  All of your defined constants are essentially integers. so there's no way to distinguish between them.

@RobertHarvey, All the macro definitions are integers.

Why is this  a macro? I am using macros like Why do you set addr = and then set ui_address =? Why set that addr =, what does addr variable do in all this?

In your case, one thing you can do is have the macros taking arguments adding a name prefix to the argument passed. E.g.:
#define ARM_REGISTER_ADDRESS(register_offset)      \
     (                                               \
            addr = ARM_BASE_ADDR * (1 << BITS_PER_MODULE) + ARM_##register_offset)                  \                               
      )

The ## will concatenate ARM_ and the argument passed to the macro. Then you can use it as:
ui_address = ARM_BASE_ADDR (REAR_REG);

And
ui_address = ARM_BASE_ADDR (MAIN_REG);

Would fail because ARM_MAIN_REG doesn't exist (in your case).
But I don't think typechecking even using enums will solve your issue (at least, I am not aware of a compiler option to allow it).

Also, I just realized, addr = probably shouldn't be part of your macros.

If you need to do it in preprocessor, you could use a tag with the variables and then concatenate it with a unique name that will expand to the result, something along:
#define MOTOR_BASE_ADDR  1
#define BITS_PER_MODULE 2

#define ARM_FRONT_REG   (ARM, 1)
#define ARM_REAR_REG    (ARM, 10)

#define MOTOR_MAIN_REG   (MOTOR, 1)
#define MOTOR_AUX_REG    (MOTOR, 3)
    
#define MOTOR_UNIQUE_STRING(x)   x
#define MOTOR_ONLY(a, b)  a##_UNIQUE_STRING(b)
#define MOTOR_REGISTER_ADDRESS(register_offset) \
    ( MOTOR_BASE_ADDR * (1 << BITS_PER_MODULE) + MOTOR_ONLY register_offset )

#define ARM_UNIQUE_STRING_FDASDFSAFDA(x)   x
#define ARM_ONLY(a, b)  a##_UNIQUE_STRING_FDASDFSAFDA(b)
#define ARM_REGISTER_ADDRESS(register_offset) \
    ( ARM_BASE_ADDR * (1 << BITS_PER_MODULE) + ARM_ONLY register_offset )


int main() {
    MOTOR_REGISTER_ADDRESS(MOTOR_MAIN_REG); // all fine
    MOTOR_REGISTER_ADDRESS(ARM_FRONT_REG); // error - sytnax error or ARM_UNIQUE_STRING undeclared
}

Picking a unique tag name and unique string will essentially work as a protecting against strange names. You could pick more unique name for the functions.
You could use actual proper types and use an actual function depending that one structure type can't be converted to another:
struct arm_register { long v; };
static const struct arm_register ARM_FRONT_REG = {1};
struct motor_register { long v; };
static const struct motor_register MOTOR_MAIN_REG = {1};

#define MOTOR_BASE_ADDR  1
#define BITS_PER_MODULE 2

static inline long MOTOR_REGISTER_ADDRESS(struct motor_register register_offset) {
    return MOTOR_BASE_ADDR * (1 << BITS_PER_MODULE) + register_offset.v;
}

int main() {
    MOTOR_REGISTER_ADDRESS(MOTOR_MAIN_REG); // all fine
    MOTOR_REGISTER_ADDRESS(ARM_FRONT_REG); // error - incompatible type
}

# or with _Generic:

#define MOTOR_REGISTER_ADDRESS_2(x) \
    _Generic((x), struct motor_register: MOTOR_BASE_ADDR * (1 << BITS_PER_MODULE) + x.v)
static const int a = MOTOR_REGISTER_ADDRESS_2(MOTOR_MAIN_REG); // all fine
static const int b = MOTOR_REGISTER_ADDRESS_2(ARM_FRONT_REG); // error - _Generic can't be chosen

