Accessing hardware components with multi-core application

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Accessing hardware components with multi-core application

844 Views
pmrlcbtcphtzjdq
Contributor III

I am trying to develop an application that uses 3 cores of MPC5748G. Each core needs to have its own freeRTOS and should control a different LED. Kind of a 'hello world' with 3 cores.

I experience a behavior I can't really explain.  All cores initialize the clocks, pins, run a freeRTOS and start the led tasks in the same way. The only difference is that in the Z4_0 core controls PA4 pin (onboard LED), core Z4_1 PA0, and Z2_2 the PC4. I am using different time delays for vTaskDelay to make the leds bink at different time intervals.

If I run the application the LEDs of the first two cores startup and freeze. The only blinking LED is the PC4 of the third core (it has the longest time for vTaskDelay). It keeps on blinking.

If I try debugging, all the cores start with a breakpoint in main(), therefore I can 'unfreeze' any of them. The last core I unfreeze is able to blink its led, however, the other LEDs stop blinking. E.g. If I start the threads in this order: first Z4_0 core, then Z2_2 and Z4_1 as the last, only the PA0 LED would keep on blinking (the Z4_1 core).

I assume there is a conflict when accessing the hardware.

The reference manual (page 394) says that the GPIO registers are 4 bytes long. If I understand it correctly one specific register shouldn't be used by two different cores. I tried to take that into account - in my application I am using GPIOs that are more than 4 bytes apart (PA0, PA4, and PC4). Am I wrong?

I also thought about letting the unused pins for each core uninitialized, but it didn't solve the problem- no matter if the last core has only one pin set up in pin_mux.c it still 'blocks' the other LEDs.

How to control access to hardware with a multicore application? should all the cores have all the hardware components enabled?
thanks a lot for any suggestions. I am attaching my main.c code underneath

 

/* constantly blink a LED on the board */
void vBlinkLEDTask(void* pvParamateres)
{
    for( ;; )
     {

       PINS_DRV_TogglePins(PTA, 0x10) ; //internal PA4

        vTaskDelay( 500 / portTICK_PERIOD_MS );

    }
}

 

int main(void)
{

    /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
    #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();
    #endif
    /*** End of Processor Expert internal initialization. ***/

    /* Initialize and configure clocks */
    CLOCK_SYS_Init(g_clockManConfigsArr, (uint8_t)CLOCK_MANAGER_CONFIG_CNT,       g_clockManCallbacksArr, (uint8_t)CLOCK_MANAGER_CALLBACK_CNT);
    CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);

    /* Initialize pins */
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);

    /* tasks */
    xTaskCreate(vBlinkLEDTask, "blinkLEDTask", 128U, NULL, 1, NULL);

    vTaskStartScheduler();


    /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
    #ifdef PEX_RTOS_START
    PEX_RTOS_START();
    #endif
    /*** End of RTOS startup code. ***/
    for(;;) {
       if(exit_code != 0) {
       break;
       }
    }
    return exit_code;

}

0 Kudos
5 Replies

805 Views
davidtosenovjan
NXP TechSupport
NXP TechSupport

I guess it could be caused by XBAR priorities. You could try to configure selected slaves for round-robin arbitration (AXBSx_CRSn register) mode what gives each core to have equal chance to access SIU registers (over PBRIDGE_A). And over flash slave ports program code is being fetched, so it could possibly affect it as well.

davidtosenovjan_1-1616770679748.png

 

 

 

0 Kudos

780 Views
pmrlcbtcphtzjdq
Contributor III

Thanks for your reply. Unfortunately, this didn't solve the problem. I get stuck with only one core being able to control the LEDs.

What I did:

1. I checked the AXBSx_CRSn Control Register, and the arbitration bits are at the 22 and 23 positions. These two bits need to be set to '01' for a round robin configuration

2. The registers are mapped in MPC5748G.h. There is also a mask defined in the same file. This mask (AXBS_CRS_ARB_MASK) has the value of 0x300 meaning '11 0000 0000' in binary.

3. I created a new mask that sets the two bits to '01', resulting in '01 0000 0000' in binary.

4. The default value of the CRS register's arbitration field is '00', therefore I assumed that simple bitwise OR of the old register value with the new round robin mask should do the trick.

5. I applied this to the sixth port - on the diagram you showed above the PBRIDGE_A is connected to S6

 

I have few questions:

1. Should I apply this mask to the CBR register of the 6th port of the AXBS type? Is that correct? does this correspond to PBRIDGE_A?

2. Should I set this register in each core of the application? I'm flashing 3 .elf files onto the board, but the Crossbar Switch can be only one. Do I need every .elf file to write this register?

3. The reference manual states that once the CRSn[RO] (first bit of the register) is set then further changes to the register are impossible. I have not been manipulating this register, so I am assuming that this bit has not bet been set.

I would be grateful for any advice.

I am including a piece of code from the MPC5748G.h and my own code.

MPC5748G.h:

/** AXBS - Register Layout Typedef */
typedef struct {
      struct { /* offset: 0x0, array step: 0x100 */
                __IO uint32_t PRS; /**< Priority Registers Slave, array offset: 0x0, array step: 0x100 */
               uint8_t RESERVED_0[12];
               __IO uint32_t CRS; /**< Control Register, array offset: 0x10, array step: 0x100 */
              uint8_t RESERVED_1[236];
              } PORT[AXBS_PORT_COUNT];
     struct { /* offset: 0x800, array step: 0x100 */
              __IO uint32_t MGPCR; /**< Master General Purpose Control Register, array offset: 0x800, array step: 0x100 */
             uint8_t RESERVED_0[252];
             } MGPCR[AXBS_MGPCR_COUNT];
} AXBS_Type, *AXBS_MemMapPtr;

 

/*! @name CRS - Control Register */

#define AXBS_CRS_ARB_MASK                (0x300U)

my own code:

int main(void)
{

#ifdef PEX_RTOS_INIT
PEX_RTOS_INIT();
#endif

/* Initialize and configure clocks */
CLOCK_SYS_Init(g_clockManConfigsArr, (uint8_t)CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, (uint8_t)CLOCK_MANAGER_CALLBACK_CNT);
CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);

/* set the AXBS mask for a round robin resource arbitration, necessary for multi-core LED control */
AXBS_Type AXBS_struct;
uint32_t AXBS_CRS_ARB_MASK_RR = AXBS_CRS_ARB_MASK && 0x100 ; // '01 0000 0000' for round robin
AXBS_struct.PORT[6].CRS |= AXBS_CRS_ARB_MASK_RR; // apply the mask

/* Initialize pins */
PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);

/* tasks */
xTaskCreate(vBlinkLEDTask, "blinkLEDTask", 128U, NULL, 1, NULL);

vTaskStartScheduler();

for(;;) {
    if(exit_code != 0) {
           break;
           }
    }
return exit_code;

}

 

0 Kudos

741 Views
davidtosenovjan
NXP TechSupport
NXP TechSupport

1) You mean CRS register. AXBS_x_CRSn – n is port number. AXBS_0_CRS6 is PBRIDGE_A. But you should set it aslo for ports S0, S1 and S2.

2) Only with booting core.

3) Ideally you should check it with debugger if it is untouched.

I am sorry for delay, I was out of office for two weeks.

0 Kudos

827 Views
davidtosenovjan
NXP TechSupport
NXP TechSupport

Hi,

"The only difference is that in the Z4_0 core controls PA4 pin (onboard LED), core Z4_1 PA4, and Z2_2 the PC4"

Dont you access the same LED?

0 Kudos

820 Views
pmrlcbtcphtzjdq
Contributor III

sorry, typing mistake. I am trying to control 3 different pins.
Z4_0 - PA4

Z4_1 - PA0

Z2_2 - PC4

0 Kudos