AN 957: Time-Sensitive Networking for Drive-on-Chip Design Example

ID 683707
Date 10/30/2021
Public
Document Table of Contents

4.2. Creating a Basic C Program for Motor Control

Creating a program to talk to the drive-on-chip subsystem from the Linux system uses the shared memory mechanism implemented during the Qsys system build.

  1. In the C program, set up the memory locations by using defines:
    #define DEBUG_RAM_BASE 0xc4001000
    #define DEBUG_ADDR_SPACE_PER_AXIS 64
    /* Offsets into debug mem */
    #define DOC_DBG_SPEED                   10
    #define DOC_DBG_POSITION                12
    #define DOC_DBG_I_PI_KP                 18
    #define DOC_DBG_I_PI_KI                 19
    #define DOC_DBG_SPEED_PI_KP             20
    #define DOC_DBG_SPEED_PI_KI             21
    #define DOC_DBG_SPEED_SETP0             22
    #define DOC_DBG_POS_SETP0               25
    #define DOC_DBG_WAVE_DEMO_MODE          29
    #define DOC_DBG_POS_SPEED_LIMIT         30
    #define DOC_DBG_POS_PI_KP               31
    #define DOC_DBG_TRACE_DEPTH             58
    

    These parameters are identical to the ones described in the motor control application program (Nios II program)..

  2. Create functions to read and write to the motor control application:
    //Read debug mem
    unsigned int get_motor_param(unsigned int axis, unsigned int param) {
    	return debug_base[axis * DEBUG_ADDR_SPACE_PER_AXIS + param];
    }
    //Write debug mem
    void set_motor_param(unsigned int axis, unsigned int param, unsigned int val) {
    	debug_base[axis * DEBUG_ADDR_SPACE_PER_AXIS + param] = val;
    }
    
  3. In the main map the memory by using the following lines:
    int _fdmem;
    	const char memDevice[] = "/dev/mem";
        _fdmem = open(memDevice, O_RDWR | O_SYNC);
        if (_fdmem < 0) {
        			printf("Failed to open the /dev/mem !\n");
        			return 0;
        		}
        		else {
        				printf("open /dev/mem successful!\n");
        		}
    /* mmap() debug memory */
    	int debug_size = 512;
    	printf("Mapping %i bytes for debug_data\n", debug_size);
    	debug_base = (unsigned int *)(mmap(0, debug_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fdmem, DEBUG_RAM_BASE));
    	if ((void *)debug_base == MAP_FAILED) {
    		printf("Failed to map debug memory\n");
    		return -1;
    	} else {
    			printf("Debug mem base : %x\n", (unsigned int)debug_base);
    	}
    
    
  4. Test the motor movement by reading and writing to the drive-on-chip subsystem, for example to set the motor to the position 100 degrees:
    set_motor_param(0, DOC_DBG_WAVE_DEMO_MODE, 1);  //Set the axis 0 to position mode
    set_motor_param(1, DOC_DBG_WAVE_DEMO_MODE, 1);  //Set the axis 1 to position mode
    set_motor_param(0, DOC_DBG_SPEED_SETP0, 100);   //Set axis 0 pos to 100 degrees
    set_motor_param(1, DOC_DBG_SPEED_SETP0, 100);   //Set axis 1 pos to 100 degrees
  5. In the same way use the function get_motor_param to retrieve information from the drive-on-chip subsystem such as position of the shaft, speed, motor control parameters like Kp, Ki or set the maximum speed limit..
  6. Compile the C program using the following command:
     >> arm-linux-gnueabihf-gcc <program_name>.c -O3 -march=armv7-a
  7. Copy the program to the development board via scp and test the motor control.