# Dual-CPU targets (F28P65x) – GPIO direction

**URL:** <https://forum.plexim.com/t/dual-cpu-targets-f28p65x-gpio-direction/3277>\
**Category:** TI C2000\
**Created:** [August 23, 2026, 9:36am UTC](https://forum.plexim.com/t/dual-cpu-targets-f28p65x-gpio-direction/3277 "2026-08-23T09:36:28Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Michael](https://avatars.discourse-cdn.com/v4/letter/m/4bbf92/32.png) [@Michael](https://forum.plexim.com/u/Michael)\
**Post date:** [August 23, 2026, 9:36am UTC](https://forum.plexim.com/t/dual-cpu-targets-f28p65x-gpio-direction/3277/1 "2026-08-23T09:36:28Z")

</div>

# Digital Output assigned to the secondary CPU never drives the pin

# (F28P65x dual-core) – bug, or are we missing something?

## What we are seeing

On a dual-core F28P65x, a Digital Output block assigned to the **secondary  
CPU (CPU2)** does not drive its pin. The model logic itself runs correctly, but  
the pin shows no electrical activity. The exact same model with the same  
block assigned to **CPU1** works perfectly.

Looking at the generated code, we noticed that no  
`GPIO_setDirectionMode(..., GPIO_DIR_MODE_OUT)` call is generated for that  
pin – on either core – so the pin’s direction appears to stay at its reset  
default (input). That would explain the symptom, since writes to the  
output latch have no effect on a pin configured as an input.

We then dug into the Lua sources to understand why, and found something  
that _might_ explain it (see below). However, we are not sure whether this  
is an actual bug or whether we are simply configuring something  
incorrectly – dual-CPU operation is new to us. **If there is a required  
setting or a supported way to do this that we have missed, we would be  
grateful for a pointer.** We are posting the full details in case they are  
useful either way.

## Environment

- PLECS version: [5.0.4]
- TI C2000 Target Support Package: 2.3.2
- Target: TMS320F28P65x (LAUNCHXL-F28P65X), dual-core
- Tested on hardware with F28P65x only.

## Steps to reproduce

We reproduced this with the official demo, without any of our own model  
content:

1. Open the example model `simple_PIL_model.plecs`  
(`tsp_ti_c2000/demos/simple_PIL_model/`).
2. Remove PIL support (PIL is not supported on multi-CPU targets).
3. Move the blink/Digital Output task (which drives GPIO12 in the  
unmodified demo) from CPU1 to CPU2.
4. Build and flash. The LED no longer blinks. Moving the task back to CPU1  
makes it work again.

No other changes are needed – a single Digital Output block on a single  
pin is enough.

## What the generated code looks like

**CPU1 file (`Controller_CPU0_hal.c`)** – the core handoff and the pad  
configuration are generated:

```c
GPIO_setControllerCore(12, GPIO_CORE_CPU2);
...
GPIO_setPadConfig(12, GPIO_PIN_TYPE_STD);

```

**CPU2 file (`Controller_CPU1_hal.c`)** – this is the only line that  
references pin 12 at all:

```c
PLX_DIO_configureOut(DoutHandles[0], 12, &props);

```

`GPIO_setDirectionMode` does not appear in either file (0 occurrences in  
both). As far as we can tell, `PLX_DIO_configureOut()`  
(`tsp_ti_c2000/ccs/28p65x/src/dio_28p65x.c`) only sets up register  
pointers and writes the initial passive value, and `GPIO_setPadConfig()`  
only controls pull-up / open-drain / invert – neither one sets the  
direction.

For comparison, with the same block on CPU1 the generated code does  
contain `GPIO_setDirectionMode(12, GPIO_DIR_MODE_OUT);`.

## What we found in the Lua sources (this is where we may be wrong)

We may well be misreading the code generator, so please take this part  
with a grain of salt – but this is what led us to suspect a gap rather  
than a mistake on our side.

`lua/blocks/syscfg.lua` appears to be the place where  
`GPIO_setDirectionMode()` is emitted, gated by this condition:

```lua
-- GPIO direction may need to be configured by primary or secondary CPU
if (gpio.core == globals.target.getGpioDirConfigCpuNumber(self.cpu)) then
  if gpio.cbx_direction.equals('OUTPUT') then
    f.PostInitCode:append(
      'GPIO_setDirectionMode(%d, GPIO_DIR_MODE_OUT);' % {gpio.unit})
  ...

```

The header comment of that same file describes the intended mechanism:

```auto
Instances of this module are created implicitly in Coder.lua.
For most targets, a single instance is created to generate initialization
code for the primary CPU.
For some targets, a second instance is created to generate initialization
code for the secondary CPU, e.g. for configuring the direction of GPIO.

```

In `lua/Coder.lua`, however, only one `syscfg` instance seems to be  
created for the C28x targets, always for the primary CPU (`cpu = 0`),  
while the F29 (`29H85x`) family gets one instance per CPU:

```lua
if T.targetMatches({'2806x', '2833x', '2837x', '2838x', '28003x',
                     '28004x', '280013x', '28P55x', '28P65x'}) then
    FactoryBlock:makeBlock('syscfg', 0)
elseif T.targetMatches({'29H85x'}) then
  for _, cpu in ipairs(Registry.UsedCpus) do
    FactoryBlock:makeBlock('syscfg', cpu)
  end
...

```

And `getGpioDirConfigCpuNumber()` appears to be overridden only in  
`lua/targets/TI29H85x.lua`:

```lua
function T.getGpioDirConfigCpuNumber(cpu)
  -- on this chip, the GPIO direction is configured by the CPU that owns the GPIO
  return T.getTiCpuNumber(cpu)
end

```

`TI28P65x.lua` has no such override (it does `local T = require('targets.TI28')`), so it would fall back to the base  
implementation in `lua/targets/TI28.lua`:

```lua
function T.getGpioDirConfigCpuNumber(cpu)
  -- default is CPU1
  return 1
end

```

If we read this correctly, that would mean the gating condition always  
evaluates to `gpio.core == 1` on F28P65x. Our pin is registered with  
`core = 2` – this is visible in the generated output itself, since the  
emitted line `GPIO_setControllerCore(12, GPIO_CORE_CPU2)` is produced from  
the format string `'GPIO_CORE_CPU%(core)d'`. With `2 == 1` never being  
true, the direction-mode line would never be emitted, which matches what  
we observe. It would also explain why the CPU1 case works (`core = 1`).

This suggests to us that the per-CPU `syscfg` mechanism described in the  
header comment is implemented for F29H85x but not (yet) for the C28x  
dual-core devices. But again – we may be misreading how the generator  
works.

## Questions

1. Is a Digital Output block on the secondary CPU a supported  
configuration on F28P65x? If not, could the Coder emit a warning or an  
error instead of generating silently non-functional code?
2. If it is supported – is there a setting or an additional block we are  
missing that would cause the direction to be configured?

Thanks a lot in advance – and apologies if we have simply overlooked  
something obvious.

## Update

By using an C-Script one the base task with:

Declation:  
`#ifdef \__TMS320C28XX_\_`  
`extern void GPIO_setDirectionMode(unsigned long pin, int pinIO);`  
`#endif`

Start:  
`#ifdef \__TMS320C28XX_\_`  
`GPIO_setDirectionMode(12, 1); /* 1 = GPIO_DIR_MODE_OUT */;`  
`#endif`

the Blink task on CPU2 works.

---

<div class="post-metadata">

**Author:** ![Munadir\_Ahmed](https://dub1.discourse-cdn.com/flex006/user_avatar/forum.plexim.com/munadir_ahmed/32/1540_2.png) [@Munadir\_Ahmed](https://forum.plexim.com/u/Munadir_Ahmed)\
**Post date:** [August 24, 2026, 4:29pm UTC](https://forum.plexim.com/t/dual-cpu-targets-f28p65x-gpio-direction/3277/2 "2026-08-24T16:29:33Z")

</div>

Hi Michael,

Thanks for the detailed explanation. I believe this was a bug in version 2.3.2 that was fixed in the latest release, version 2.3.3. I would recommend upgrading to the latest version and seeing if that resolves the issue in your setup.

You can use the update manager built into PLECS, or download the latest TSP directly from our website:

> **[TI C2000 Code Generation | Plexim](https://www.plexim.com/download/tsp_c2000)**

Hope this helps!

Munadir

---

<div class="post-metadata">

**Author:** ![Michael](https://avatars.discourse-cdn.com/v4/letter/m/4bbf92/32.png) [@Michael](https://forum.plexim.com/u/Michael)\
**Post date:** [August 25, 2026, 4:41am UTC](https://forum.plexim.com/t/dual-cpu-targets-f28p65x-gpio-direction/3277/3 "2026-08-25T04:41:37Z")

</div>

Hi,

updating the TI C2000 TSP from 2.3.2 to 2.3.3 fixed the issue - the  
Coder now generates GPIO\_setDirectionMode() for pins assigned to the  
secondary CPU.

Thank you for your reply.
