Hi Then,
On Mon, Jan 02, 2017 at 06:26:05PM +0800, then yon wrote:
> Dear Chris,
>
> I tried to apply your solution but i stuck somewhere in middle as the
> handler parameter is diff that cause build error
>
> void shell_task_handler(void *arg)
> static void queue_task_handler(struct os_event *ev)
>
> 1. At os_eventq_init(&shell_task_evq);
>
> 2. At os_task_init(&queue_task, "queue", queue_task_handler, NULL,
> QUEUE_TASK_PRIO, OS_WAIT_FOREVER, queue_stack, QUEUE_STACK_SIZE);
I have attached a copy of main.c which incorporates the "option 1" that
I mentioned in my last email. I also had to make a few other changes to
successfully test this change. I will briefly describe them below.
1. Rename shell_{task,stack,etc.} to data_[...]. This is probably just
to scratch an OCD itch, but I had a hard time with this because the
shell task wasn't actually related to the shell.
2. Don't perform 1,000,000 GPIO writes upfront. When I tested this in
sim, the GPIO writes were taking too long. Since the work task has the
highest priority, this means the mqueue operations never took place.
This could just be a sim thing, though, since sim calls printf on each
GPIO set.
3. Don't allocate the mbuf on the stack; get it from
os_msys_get_pkthdr() instead. This change is analogous to changing a
variable from being automatic (stack) to dynamic via a call to malloc().
It is important that the mbuf is dynamic because:
* It is passed to a different task, so when it gets processed, the
original stack's contents are lost.
* It gets freed via a call to os_mbuf_free_chain(). When you try to
free an mbuf on the stack, you will get a very confusing crash
that will take all day to debug. I'm afraid I know this from
experience :).
4. Don't call shell_init() explicitly. The shell package gets
initialized automatically by the sysinit mechanism.
5. The changes I mentioned earlier:
* Remove the queue_task_evq
* Associate the mqueue with blinky_evq (used to be queue_task_evq).
Thanks,
Chris
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <string.h>
// #include "esb.h"
#include "console/console.h"
#include "shell/shell.h"
#include "syscfg/syscfg.h"
#include "os/queue.h"
#include "os/os_eventq.h"
#include "sysinit/sysinit.h"
#include "os/os.h"
#include "bsp/bsp.h"
#include "hal/hal_gpio.h"
#ifdef ARCH_sim
#include "mcu/mcu_sim.h"
#endif
/* Init all tasks */
volatile int tasks_initialized;
int init_tasks(void);
/* Blinky Task */
#define BLINKY_TASK_PRIO (2)
#define BLINKY_STACK_SIZE OS_STACK_ALIGN(256)
struct os_task blinky_task;
os_stack_t blinky_stack[BLINKY_STACK_SIZE];
/* Work Task */
#define WORK_TASK_PRIO (1)
#define WORK_STACK_SIZE OS_STACK_ALIGN(256)
struct os_task work_task;
os_stack_t work_stack[WORK_STACK_SIZE];
/* Shell Task */
#define DATA_TASK_PRIO (3)
#define DATA_STACK_SIZE OS_STACK_ALIGN(256)
struct os_task data_task;
os_stack_t data_stack[DATA_STACK_SIZE];
/* Queue Task */
struct os_mqueue rxpkt_q;
static int queue_task_rx_data_func(struct os_mbuf *om);
static volatile int g_task1_loops;
struct os_eventq blinky_evq;
/* For LED toggling */
int g_led_pin;
void data_task_handler(void *arg)
{
while(1){
os_eventq_run(&blinky_evq);
}
}
void work_task_handler(void *arg)
{
struct os_task *t;
uint8_t val;
unsigned int i;
g_led_pin = LED_BLINK_PIN;
hal_gpio_init_out(g_led_pin, 1);
i = 0;
while(1){
t = os_sched_get_current_task();
assert(t->t_func == work_task_handler);
/* Do work... */
hal_gpio_write(g_led_pin, 1);
/* Put data into mbuf */
struct os_mbuf *om = os_msys_get_pkthdr(1, 0);
if (om == NULL) {
console_printf("Error: OOM\n");
} else {
val = i;
os_mbuf_append(om, &val, sizeof val);
queue_task_rx_data_func(om);
console_printf("Entered\n");
}
i++;
os_time_delay(0.5*OS_TICKS_PER_SEC);
}
}
void blinky_task_handler(void *arg)
{
struct os_task *t;
g_led_pin = LED_BLINK_PIN;
hal_gpio_init_out(g_led_pin, 1);
while (1) {
t = os_sched_get_current_task();
assert(t->t_func == blinky_task_handler);
++g_task1_loops;
/* Wait one second */
os_time_delay(OS_TICKS_PER_SEC/10);
/* Toggle the LED */
hal_gpio_toggle(g_led_pin);
}
}
void handle_mqueue_event(struct os_event *ev)
{
int i;
struct os_mbuf *om;
/* Drain all packets off queue and process them */
while ((om = os_mqueue_get(&rxpkt_q)) != NULL) {
const uint8_t *data = om->om_data;
int temp_len = om->om_len;
console_printf("Data get: ");
for(i=0; i<temp_len; i++)
console_printf("%02X ", *data++);
console_printf("\n");
os_mbuf_free_chain(om);
}
}
static int queue_task_rx_data_func(struct os_mbuf *om)
{
int rc;
rc = os_mqueue_put(&rxpkt_q, &blinky_evq, om);
if (rc != 0) {
return -1;
}
return 0;
}
/**
* init_tasks
*
* Called by main.c after os_init(). This function performs initializations
* that are required before tasks are running.
*
* @return int 0 success; error otherwise.
*/
int
init_tasks(void)
{
os_task_init(&work_task, "work", work_task_handler, NULL,
WORK_TASK_PRIO, OS_WAIT_FOREVER, work_stack, WORK_STACK_SIZE);
os_task_init(&blinky_task, "blinky", blinky_task_handler, NULL,
BLINKY_TASK_PRIO, OS_WAIT_FOREVER, blinky_stack, BLINKY_STACK_SIZE);
os_task_init(&data_task, "data", data_task_handler, NULL,
DATA_TASK_PRIO, OS_WAIT_FOREVER, data_stack, DATA_STACK_SIZE);
tasks_initialized = 1;
return 0;
}
/**
* main
*
* The main function for the project. This function initializes the os, calls
* init_tasks to initialize tasks (and possibly other objects), then starts the
* OS. We should not return from os start.
*
* @return int NOTE: this function should never return!
*/
int
main(int argc, char **argv)
{
int rc;
#ifdef ARCH_sim
mcu_sim_parse_args(argc, argv);
#endif
sysinit();
/* Initialize eventq for the application task. */
os_eventq_init(&blinky_evq);
/* Initialize mqueue */
os_mqueue_init(&rxpkt_q, &handle_mqueue_event, NULL);
rc = init_tasks();
assert(rc == 0);
/* Set the default eventq for packages that lack a dedicated task. */
os_eventq_dflt_set(&blinky_evq);
os_start();
/* os start should never return. If it does, this should be an error */
assert(0);
return rc;
}