contiki-os / contiki

The official git repository for Contiki, the open source OS for the Internet of Things
http://www.contiki-os.org/
Other
3.71k stars 2.58k forks source link

Write program for Sensor Controller (CC26xx) #2019

Open tarakanov opened 7 years ago

tarakanov commented 7 years ago

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.

jonnteolsson commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

You can use SCS to generate a bare-metal code using CCS.

The integration with contiki is very straightforward.

You will see that it will generate an init code (that you can run onde anywhere on contiki) and some interrupts (that can ideally fire events in contiki to signal your application).

We have been using this for a while without any problems with contiki and with other RTOSes.

Marco Casaroli

On Wed, Dec 28, 2016 at 10:43 AM, Semyon Tarakanov <notifications@github.com

wrote:

Thank you @jonnteolsson https://github.com/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.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/contiki-os/contiki/issues/2019#issuecomment-269472189, or mute the thread https://github.com/notifications/unsubscribe-auth/ADszaHFjy9moPwSfd4zUiZOkQhfYw29lks5rMlljgaJpZM4LVLeg .

g-oikonomou commented 7 years ago

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 commented 7 years ago

Hello George.

In my experience, the code generated already does the lpm and clocks initialization

I need to check if there was anything we needed to change in contiki lpm code but I think we didn't.

I do not have a computer available right now for me to check. I will post some instructions on how to do it in january.

BR

On Wed, 28 Dec 2016 at 11:25 George Oikonomou notifications@github.com wrote:

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?

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/contiki-os/contiki/issues/2019#issuecomment-269476639, or mute the thread https://github.com/notifications/unsubscribe-auth/ADszaEI9Bcop7xjSvKmKZEYgQWan2tLnks5rMmNBgaJpZM4LVLeg .

tsokorai commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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?