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

Write program for Sensor Controller (CC26xx) #2019

Open
tarakanov opened this issue Dec 24, 2016 · 16 comments
Open

Write program for Sensor Controller (CC26xx) #2019

tarakanov opened this issue Dec 24, 2016 · 16 comments

Comments

@tarakanov
Copy link
Contributor

Hi!
I would like to write sensor handling program for Sensor Controller (AUX) of CC2650. As far as I understand, I need to use Sensor Controller Studio (SCS) to do this. Then I need to write Contiki app for main CPU. And this two programs can interact via semaphores and AUX RAM.

  • Is it correct?
  • Can I write AUX program within Contiki repo (without need of SCS)?
  • If I have SCS generated program, what I need to compile total binary file of Contiki and AUX program (to upload to chip)?
@jonnteolsson
Copy link
Contributor

Yes that is correct. I would suggest to use SCS since it is much easier to use, but it is possible to write programs for the sensor controller without using SCS. The main CPU will need to load the program into the sensor controller RAM. Suggest to look the sensor controller trainings here: ti.com/simplelinkacademy

@tarakanov
Copy link
Contributor Author

Thank you @jonnteolsson. I've managed to write a program in SCS. ADC and event code work well in Task Testing of SCS. Now I need to include this program into Contiki. TI's Simplelink Academy described this process for TI-RTOS, but not for Contiki. What do I need to import these files into Contiki and compile it?

As far as I look through Contiki port of CC26xx, there is mechanism to interact with AUX, but I cannot find any info about including AUX application code to Contiki.

@casaroli
Copy link
Contributor

casaroli commented Dec 28, 2016 via email

@g-oikonomou
Copy link
Contributor

In addition to copying the code to sensor controller RAM and starting the controller, I would suspect you also need code so the main MCU can handle events from the controller. I would also think you'd have to manipulate clocks within AUX so the controller can keep running while the rest of the chip is powered down.

Marco, did you have to do any of that clock and power manipulation?

@casaroli
Copy link
Contributor

casaroli commented Dec 28, 2016 via email

@tsokorai
Copy link

I "sort of" integrated the SC with Contiki, but I'm experiencing some issues.
I'm using the SC UART emulation code, and I'm able to only get about 6-8 chars TX'ed without corruption.
Oddly enough, RX works absolutely perfect.
My test code init (based on cc26xx-demo.c) looks like this:
`static aux_consumer_module_t uart_aux = {
NULL, AUX_WUC_SMPH_CLOCK | AUX_WUC_AIODIO0_CLOCK |
AUX_WUC_AIODIO1_CLOCK | AUX_WUC_TIMER_CLOCK |
AUX_WUC_ANAIF_CLOCK | AUX_WUC_TDCIF_CLOCK |
AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_ADI_CLOCK | AUX_WUC_TDC_CLOCK |
AUX_WUC_ADC_CLOCK | AUX_WUC_REF_CLOCK
};

/---------------------------------------------------------------------------/
PROCESS_THREAD(cc26xx_my_process, ev, data)
{

PROCESS_BEGIN();
printf("CC26XX test v43\n");
// to be used in the alert callback for RX
softuart_event = process_alloc_event();

ti_lib_sys_ctrl_power_everything();

// Stop SC.
ti_lib_aon_wuc_aux_image_invalid();

// Run all clocks at full speed for now.
ti_lib_prcm_inf_clock_configure_set(PRCM_CLOCK_DIV_1, PRCM_RUN_MODE);
ti_lib_prcm_inf_clock_configure_set(PRCM_CLOCK_DIV_1, PRCM_SLEEP_MODE);
ti_lib_prcm_inf_clock_configure_set(PRCM_CLOCK_DIV_1, PRCM_DEEP_SLEEP_MODE);
// clock resources
aux_ctrl_register_consumer(&uart_aux);
AUXWUCClockFreqReq(AUX_WUC_CLOCK_HIFREQ);
AUXWUCPowerCtrl(AUX_WUC_POWER_ACTIVE);
aux_ctrl_power_up();
// AUX domain access
scifOsalEnableAuxDomainAccess();
// Init SC driver
scifInit(&scifDriverSetup);
// Start the UART emulator
scifExecuteTasksOnceNbl(BV(SCIF_UART_EMULATOR_TASK_ID));
// Enable baud rate generation
scifUartSetBaudRate(9600);
// my alert callback
scifOsalRegisterTaskAlertCallback(&uartAlertCallback);
// Enable RX (10 idle bit periods required before enabling start bit detection)
scifUartSetRxFifoThr(SCIF_UART_RX_FIFO_MAX_COUNT / 2);
scifUartSetRxTimeout(10 * 2);
scifUartSetRxEnableReqIdleCount(10 * 2);
scifUartRxEnable(1);

// Enable events (half full RX FIFO or 10 bit period timeout
scifUartSetEventMask(BV_SCIF_UART_ALERT_RX_FIFO_ABOVE_THR | BV_SCIF_UART_ALERT_RX_BYTE_TIMEOUT);

scifUartTxPutChars("Hello how's everything? This is a long string\r\n",47);
`
A bit more of my previous tries is on a post a did on TI's forum:
https://e2e.ti.com/support/wireless_connectivity/zigbee_6lowpan_802-15-4_mac/f/158/p/567025/2088653#2088653
Any ideas of what could be killing my TX? seems like the timer used for baudrate its getting shutdown, but since I declared use of AUX_WUC_TIMER_CLOCK shouldn't it be protected?

@tsokorai
Copy link

OK, the code I posted before does indeed work like a charm for UART emulation in Contiki via the Sensor Controller.
My TX issue? dying USB<->UART interface connected to the UART emulation pins; replaced it with another, even with the same chipset, and voilá! It does work flawlessly, so yes, aux_ctrl_register_consumer() does indeed prevent any powerdowns of the required clocks on the SC.
I included all AUX clocks, which I think must be trimmed to what the UART code uses, but it does work.

@tarakanov
Copy link
Contributor Author

tarakanov commented Jan 30, 2017

OK. It is not so easy to do this thing. Here is my two little step. First I write the simplest program for Sensor Controller in SCS and use only Execution Code with one line of code:
gpioSetOutput(AUXIO_O_LED_DP1);
After Code Generation I take these files to Contiki (to platform/srf06-cc26xx/sensortag directory):

scif.c
scif.h
scif_framework.c
scif_framework.h
scif_osal_none.c
scif_osal_none.h

I include them to the build by adding BOARD_SOURCEFILES += scif_framework.c scif_osal_none.c scif.c to Makefile.sensortag file. Then I add a process to Contiki project (I modify cc26xx-demo.c) with this piece of code:

#include "aux-ctrl.h"
#include "scif.h"
#define BV(x)    (1 << (x))

//Other code here

static aux_consumer_module_t blink_aux = {NULL, AUX_WUC_SMPH_CLOCK };
PROCESS_THREAD(cc26xx_demo_process, ev, data)
{
  PROCESS_BEGIN();
  printf("CC26XX demo\n");
  aux_ctrl_register_consumer(&blink_aux);
  scifInit(&scifDriverSetup);
  scifExecuteTasksOnceNbl(BV(SCIF_BLINK_TASK_ID));

// Other code here

Then make TARGET=srf06-cc26xx BOARD_SENSORTAG=1 BOARD=sensortag/cc2650 BOARD_CONF_DEBUGGER_DEVPACK=1. With this code, Sensortag will turn on LED (I attached the LED to DP0 of DevPack board). So I believe it is the minimal integration program.

For my second step I tried to iterate over the Execution Code with schedule. To iterate over Execution Code you need to add fwScheduleTask(1); to schedule next iteration in one tick. The tick time is defined by Contiki by invoking selfStartRtcTicksNow(0x00010000); The tick time is defined in brackets in 16.16 bit format. For example, 0x00010000 is 1 second.
The execution code is (and it works OK in SCS):

U16 buttonState; //attach button to DP0 of DevPack
gpioGetInputValue(AUXIO_I_BUTTON_DP0; buttonState);

if (buttonState == 1) {
  gpioClearOutput(AUXIO_O_LED_DP1);
} else {
  gpioSetOutput(AUXIO_O_LED_DP1);
}
fwScheduleTask(1);

Contiki project code:

#include "aux-ctrl.h"
#include "scif.h"
#define BV(x)    (1 << (x))

//Other code here

static aux_consumer_module_t blink_aux = {NULL, AUX_WUC_SMPH_CLOCK };

PROCESS_THREAD(cc26xx_demo_process, ev, data)
{
  PROCESS_BEGIN();
  printf("CC26XX demo\n");
  aux_ctrl_register_consumer(&blink_aux);
  scifInit(&scifDriverSetup);
  selfStartRtcTicksNow(0x00010000);
  scifExecuteTasksOnceNbl(BV(SCIF_BLINK_TASK_ID));

// Other code here

This code should check button state every 1 second and light the led. But it fails. Actually, if you hit the button while powering the board, SC will see that and will light the LED. It tells that one iteration of Execution code was done. Then something happened - the code failed or schedule failed.
SCS tells that fwScheduleTask() uses AON_RTC channel 2 in continuous compare mode to generate periodical wake-ups for the AUX. Tuning of RTC channel 2 is done via selfStartRtcTicksNow(); and it seems no problem (as from the code). Contiki uses RTC channel 0 and channel 1 (as from soc-rtc.c). Also I believe that Execution code should iterate even without such schedule.

So I am stuck here. Has anybody succeeded with this?

@DaLBr
Copy link

DaLBr commented Mar 9, 2017

hi @tarakanov, I am stuck at the same position in your previous post. I wanted to check if you had made any progress with this?

@tarakanov
Copy link
Contributor Author

I manage to run SC image periodically. Recall, to run Execution code you need to add fwScheduleTask(1) for one tick. The tick time is defined by Contiki by invoking selfStartRtcTicksNow(0x00010000). The tick time is defined in brackets in 16.16 bit format. For example, 0x00010000 is 1 second. After this setup, you need to actually start execution by calling scifStartTasksNbl(BV(SCIF_BLINK_TASK_ID)) with Task name as argument. But do not call scifExecuteTasksOnceNbl as I mention earlier, as it will execute task once and do not setup events for the next iteration. Here is part of the Contiki code:

  PROCESS_BEGIN();
  printf("CC26XX demo\n");
  aux_ctrl_register_consumer(&blink_aux);
  scifInit(&scifDriverSetup);
  scifStartRtcTicksNow(0x00010000);
  scifStartTasksNbl(BV(SCIF_BLINK_TASK_ID));

But it is conflicted with the AON RTC interrupt handler in soc-rtc.c code. RTC software timers uses RTC channel 0 and channel 1 but soc_rtc_isr() is programmed to catch combined event from all three channels (ch0, ch1, ch2) with this command:
ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH1 | AON_RTC_CH2)
And when you properly configure SC image and run it first time, RTC ch2 will raise an event after tick time which will call this routine also. And this routine will disable RTC ch2 with this code:

  if(ti_lib_aon_rtc_event_get(AON_RTC_CH2)) {
    /* after sleep; since a rtimer is already scheduled, do nothing */
    ti_lib_aon_rtc_channel_disable(AON_RTC_CH2);
    HWREG(AON_RTC_BASE + AON_RTC_O_EVFLAGS) = AON_RTC_EVFLAGS_CH2;
  }

I change combine event to this, and soc_rtc_isr will not handle events from ch2:
ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH1)

@g-oikonomou please advise here. If Contiki uses only ch0 and ch1 for timers, maybe it is good to remove all uses of ch2 from soc-rtc.c?

@tarakanov
Copy link
Contributor Author

I manage to make an alert to Contiki via events. To alert the main core you need add fwGenAlertInterrupt(); in the Execution Task. When you initialize SC in the Contiki, you need to register callback function for this alert:

  scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);
  scifInit(&scifDriverSetup);

Callback function will allocate event to the process (scinterrupt_test_process in my case):

process_event_t sc_event;
void scTaskAlertCallback(void)
{
    scifClearAlertIntSource();
    sc_event = process_alloc_event();
    process_post(&scinterrupt_test_process, sc_event, NULL);
    scifAckAlertEvents();
}

Then you can identify this event by its name:

    PROCESS_YIELD();
     if (ev == sc_event) {
        printf("Hello from SC\n");
    }

@greg-king5
Copy link

sc_event = process_alloc_event();

That expression must be done only once, in the initiation code. It assigns a unique number that represents those Sensor Controller events.

@greg-king5
Copy link

Hmm ...
Is scTaskAlertCallback() executed during an interrupt? If it is, then it must not use process_post(). Only process_poll() is safe for interrupt handlers.

@g-oikonomou
Copy link
Contributor

If it is, then it must not use process_post(). Only process_poll() is safe for interrupt handlers.

I am not so sure about that, process_post() is asynchronous. The difference is that we can raise a specific event, whereas with process_poll() we always send the same generic "poll" event

@greg-king5
Copy link

greg-king5 commented May 30, 2017

I am not so sure about that, process_post() is asynchronous.

OK. I looked at the code again. Now, I think that you're right. process_post() can "interrupt" do_event() without causing trouble.

@nemehta
Copy link

nemehta commented May 30, 2017

Thanks for your instructions @tarakanov Very Helpful! It seems like you have discovered an incompatibility of contiki with CC1350 AUX. Another way of fixing the problem is by NOT disabling RTC_CH2

if(ti_lib_aon_rtc_event_get(AON_RTC_CH2)) {
/* after sleep; since a rtimer is already scheduled, do nothing */
// ti_lib_aon_rtc_channel_disable(AON_RTC_CH2);
HWREG(AON_RTC_BASE + AON_RTC_O_EVFLAGS) = AON_RTC_EVFLAGS_CH2;
}

I dug a bit deeper and found that aux_ctrl_register_consumer() triggers AONWUC_AUX_WAKEUP, which causes soc_rtc.c to disable AON_RTC_CH2. My question here is that why does contiki (soc-rtc.c) disable AON_RTC_CH2. What it is doing is killing any interrupts from the AUX, immediately after waking it up.

Which leads me to the question - Is it safe to disable AON_RTC_CH2. Does any other code in the contiki environment use it?

alexrayne pushed a commit to alexrayne/contiki that referenced this issue Jul 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants