modularized bulk read

sipo
Ondřej Hruška 7 years ago
parent eb58fce25a
commit d8e2d016d2
  1. 6
      TinyFrame/TF_Integration.c
  2. 6
      comm/messages.h
  3. 94
      comm/msg_bulkread.c
  4. 32
      comm/msg_bulkread.h
  5. 12
      tasks/task_msg.c
  6. 120
      units/test/unit_test.c
  7. 4
      utils/macro.h

@ -24,12 +24,6 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, size_t len)
uint16_t chunksize = (uint16_t) MIN(total, CHUNK);
assert_param(USBD_OK == CDC_Transmit_FS((uint8_t *) buff, chunksize));
PUTS("Tx: ");
for(int i=0;i<chunksize; i++) {
PRINTF("%02X ", buff[i]);
}
PUTS("\r\n");
buff += chunksize;
total -= chunksize;
}

@ -33,11 +33,11 @@ enum TF_Types_ {
MSG_LIST_UNITS = 0x20, //!< Get all unit call-signs and names
};
extern TinyFrame *comm;
// Must be after the enum because it's used in the header file.
#include "msg_responses.h"
extern TinyFrame *comm;
#include "msg_bulkread.h"
/**
* Initialize TinyFrame and set up listeners

@ -0,0 +1,94 @@
//
// Created by MightyPork on 2017/12/23.
//
#include "platform.h"
#include <TinyFrame.h>
#include "messages.h"
#include "utils/payload_parser.h"
#include "utils/payload_builder.h"
static uint8_t bulkread_buffer[BULKREAD_MAX_CHUNK];
TF_Result bulkread_lst(TinyFrame *tf, TF_Msg *msg)
{
// this is a final call before timeout, to clean up
if (msg->data == NULL) {
dbg("Bulk rx lst cleanup\r\n");
goto close;
}
struct bulk_read *bulk = msg->userdata;
assert_param(NULL != bulk);
if (msg->type == MSG_BULK_ABORT) {
goto close;
} else if (msg->type == MSG_BULK_READ_POLL) {
PayloadParser pp = pp_start(msg->data, msg->len, NULL);
uint32_t chunk = pp_u32(&pp);
// if past len, say we're done and close
if (bulk->offset >= bulk->len) {
TF_ClearMsg(msg);
msg->frame_id = bulk->frame_id;
msg->type = MSG_BULK_END;
TF_Respond(tf, msg);
goto close;
}
chunk = MIN(chunk, bulk->len - bulk->offset);
chunk = MIN(chunk, BULKREAD_MAX_CHUNK);
bulk->read(bulk->offset, chunk, bulkread_buffer);
TF_ClearMsg(msg);
msg->frame_id = bulk->frame_id;
msg->type = MSG_BULK_DATA;
msg->data = bulkread_buffer;
msg->len = (TF_LEN) chunk;
TF_Respond(tf, msg);
// advance the position pointer
bulk->offset += chunk;
}
msg->userdata = bulk; // We must put it back
return TF_RENEW;
close:
if (msg->userdata) {
free(msg->userdata);
msg->userdata = NULL;
}
return TF_CLOSE;
}
void bulkread_start(TinyFrame *tf, struct bulk_read *bulk)
{
assert_param(bulk);
assert_param(bulk->len);
assert_param(bulk->read);
bulk->offset = 0;
{
uint8_t buf[8];
PayloadBuilder pb = pb_start(buf, 4, NULL);
pb_u32(&pb, bulk->len);
pb_u32(&pb, BULKREAD_MAX_CHUNK);
// We use userdata1 to hold a reference to the bulk transfer
TF_Msg msg = {
.type = MSG_BULK_READ_OFFER,
.frame_id = bulk->frame_id,
.is_response = true, // this ensures the frame_id is not re-generated
.data = buf,
.len = (TF_LEN) pb_length(&pb),
.userdata = bulk,
};
TF_Query(tf, &msg, bulkread_lst, BULK_LST_TIMEOUT_MS);
}
}

@ -0,0 +1,32 @@
//
// Created by MightyPork on 2017/12/23.
//
#ifndef GEX_F072_MSG_BULKREAD_H
#define GEX_F072_MSG_BULKREAD_H
#ifndef GEX_MESSAGES_H
#error "Include messages.h instead!"
#endif
#include <TinyFrame.h>
#define BULK_LST_TIMEOUT_MS 200
#define BULKREAD_MAX_CHUNK 512 // this is a static buffer
typedef void (*bulkread_data_cb)(uint32_t offset, uint32_t len, uint8_t *buffer);
struct bulk_read {
TF_ID frame_id;
bulkread_data_cb read;
uint32_t len;
uint32_t offset;
};
void bulkread_start(TinyFrame *tf, struct bulk_read *bulk);
#endif //GEX_F072_MSG_BULKREAD_H

@ -8,6 +8,15 @@
#include "task_msg.h"
#include "sched_queue.h"
/**
* Process data received from TinyFrame.
* The queue holds received messages or parts of messages,
* copied there by the USB thread.
*
* Since this is a separate thread that handles TF input and runs the listeners,
* TF functions (send, respond) can be called immediately without the need for an
* intermediate queued job.
*/
void TaskMessaging(const void * argument)
{
dbg("> Message queue task started!");
@ -17,9 +26,6 @@ void TaskMessaging(const void * argument)
xQueueReceive(queRxDataHandle, &slot, osWaitForever);
assert_param(slot.len>0 && slot.len<=64); // check the len is within bounds
hexDump("MSG", slot.data, slot.len);
TF_Accept(comm, slot.data, slot.len);
}
}

@ -95,83 +95,11 @@ enum PinCmd_ {
CMD_BULKREAD = 2,
};
static void job_echo(Job *job)
{
tf_respond_buf(MSG_SUCCESS, job->frame_id, job->buf, job->len);
free(job->buf);
}
const char *longtext = "The history of all hitherto existing societies is the history of class struggles.\n\nFreeman and slave, patrician and plebeian, lord and serf, guild-master and journeyman, in a word, oppressor and oppressed, stood in constant opposition to one another, carried on an uninterrupted, now hidden, now open fight, a fight that each time ended, either in a revolutionary re-constitution of society at large, or in the common ruin of the contending classes.\n\nIn the earlier epochs of history, we find almost everywhere a complicated arrangement of society into various orders, a manifold gradation of social rank. In ancient Rome we have patricians, knights, plebeians, slaves; in the Middle Ages, feudal lords, vassals, guild-masters, journeymen, apprentices, serfs; in almost all of these classes, again, subordinate gradations.\n\nThe modern bourgeois society that has sprouted from the ruins of feudal society has not done away with class antagonisms. It has but established new classes, new conditions of oppression, new forms of struggle in place of the old ones. Our epoch, the epoch of the bourgeoisie, possesses, however, this distinctive feature: it has simplified the class antagonisms. Society as a whole is more and more splitting up into two great hostile camps, into two great classes, directly facing each other: Bourgeoisie and Proletariat.\n\nFrom the serfs of the Middle Ages sprang the chartered burghers of the earliest towns. From these burgesses the first elements of the bourgeoisie were developed.\n\nThe discovery of America, the rounding of the Cape, opened up fresh ground for the rising bourgeoisie. The East-Indian and Chinese markets, the colonisation of America, trade with the colonies, the increase in the means of exchange and in commodities generally, gave to commerce, to navigation, to industry, an impulse never before known, and thereby, to the revolutionary element in the tottering feudal society, a rapid development.\n\nThe feudal system of industry, under which industrial production was monopolised by closed guilds, now no longer sufficed for the growing wants of the new markets. The manufacturing system took its place. The guild-masters were pushed on one side by the manufacturing middle class; division of labour between the different corporate guilds vanished in the face of division of labour in each single workshop.\n\nMeantime the markets kept ever growing, the demand ever rising. Even manufacture no longer sufficed. Thereupon, steam and machinery revolutionised industrial production. The place of manufacture was taken by the giant, Modern Industry, the place of the industrial middle class, by industrial millionaires, the leaders of whole industrial armies, the modern bourgeois.\n\nModern industry has established the world-market, for which the discovery of America paved the way. This market has given an immense development to commerce, to navigation, to communication by land. This development has, in its time, reacted on the extension of industry; and in proportion as industry, commerce, navigation, railways extended, in the same proportion the bourgeoisie developed, increased its capital, and pushed into the background every class handed down from the Middle Ages.\n\nWe see, therefore, how the modern bourgeoisie is itself the product of a long course of development, of a series of revolutions in the modes of production and of exchange.\n\nEach step in the development of the bourgeoisie was accompanied by a corresponding political advance of that class. An oppressed class under the sway of the feudal nobility, an armed and self-governing association in the mediaeval commune; here independent urban republic (as in Italy and Germany), there taxable \"third estate\" of the monarchy (as in France), afterwards, in the period of manufacture proper, serving either the semi-feudal or the absolute monarchy as a counterpoise against the nobility, and, in fact, corner-stone of the great monarchies in general, the bourgeoisie has at last, since the establishment of Modern Industry and of the world-market, conquered for itself, in the modern representative State, exclusive political sway. The executive of the modern State is but a committee for managing the common affairs of the whole bourgeoisie.";
static void job_bulkread_chunk(Job *job)
{
dbg("Tx a chunk of size %d", (int)job->len);
tf_respond_buf(MSG_BULK_DATA, job->frame_id, job->buf, job->len);
}
static void job_bulkread_close(Job *job)
{
dbg("Bulk read close.");
tf_respond_buf(MSG_BULK_END, job->frame_id, NULL, 0);
}
static void job_bulkread_offer(Job *job)
{
uint8_t buf[10];
PayloadBuilder pb = pb_start(buf, 10, NULL);
pb_u32(&pb, job->d32);
static const char *longtext = "The history of all hitherto existing societies is the history of class struggles.\n\nFreeman and slave, patrician and plebeian, lord and serf, guild-master and journeyman, in a word, oppressor and oppressed, stood in constant opposition to one another, carried on an uninterrupted, now hidden, now open fight, a fight that each time ended, either in a revolutionary re-constitution of society at large, or in the common ruin of the contending classes.\n\nIn the earlier epochs of history, we find almost everywhere a complicated arrangement of society into various orders, a manifold gradation of social rank. In ancient Rome we have patricians, knights, plebeians, slaves; in the Middle Ages, feudal lords, vassals, guild-masters, journeymen, apprentices, serfs; in almost all of these classes, again, subordinate gradations.\n\nThe modern bourgeois society that has sprouted from the ruins of feudal society has not done away with class antagonisms. It has but established new classes, new conditions of oppression, new forms of struggle in place of the old ones. Our epoch, the epoch of the bourgeoisie, possesses, however, this distinctive feature: it has simplified the class antagonisms. Society as a whole is more and more splitting up into two great hostile camps, into two great classes, directly facing each other: Bourgeoisie and Proletariat.\n\nFrom the serfs of the Middle Ages sprang the chartered burghers of the earliest towns. From these burgesses the first elements of the bourgeoisie were developed.\n\nThe discovery of America, the rounding of the Cape, opened up fresh ground for the rising bourgeoisie. The East-Indian and Chinese markets, the colonisation of America, trade with the colonies, the increase in the means of exchange and in commodities generally, gave to commerce, to navigation, to industry, an impulse never before known, and thereby, to the revolutionary element in the tottering feudal society, a rapid development.\n\nThe feudal system of industry, under which industrial production was monopolised by closed guilds, now no longer sufficed for the growing wants of the new markets. The manufacturing system took its place. The guild-masters were pushed on one side by the manufacturing middle class; division of labour between the different corporate guilds vanished in the face of division of labour in each single workshop.\n\nMeantime the markets kept ever growing, the demand ever rising. Even manufacture no longer sufficed. Thereupon, steam and machinery revolutionised industrial production. The place of manufacture was taken by the giant, Modern Industry, the place of the industrial middle class, by industrial millionaires, the leaders of whole industrial armies, the modern bourgeois.\n\nModern industry has established the world-market, for which the discovery of America paved the way. This market has given an immense development to commerce, to navigation, to communication by land. This development has, in its time, reacted on the extension of industry; and in proportion as industry, commerce, navigation, railways extended, in the same proportion the bourgeoisie developed, increased its capital, and pushed into the background every class handed down from the Middle Ages.\n\nWe see, therefore, how the modern bourgeoisie is itself the product of a long course of development, of a series of revolutions in the modes of production and of exchange.\n\nEach step in the development of the bourgeoisie was accompanied by a corresponding political advance of that class. An oppressed class under the sway of the feudal nobility, an armed and self-governing association in the mediaeval commune; here independent urban republic (as in Italy and Germany), there taxable \"third estate\" of the monarchy (as in France), afterwards, in the period of manufacture proper, serving either the semi-feudal or the absolute monarchy as a counterpoise against the nobility, and, in fact, corner-stone of the great monarchies in general, the bourgeoisie has at last, since the establishment of Modern Industry and of the world-market, conquered for itself, in the modern representative State, exclusive political sway. The executive of the modern State is but a committee for managing the common affairs of the whole bourgeoisie.";
dbg("Offer bulk xfer of %d bytes", (int)job->d32);
tf_respond_buf(MSG_BULK_READ_OFFER, job->frame_id, buf, (uint32_t) pb_length(&pb));
}
static TF_Result bulkread_lst(TinyFrame *tf, TF_Msg *msg)
static void br_longtext(uint32_t offset, uint32_t len, uint8_t *buffer)
{
if (msg->data == NULL) {
dbg("Bulk rx lst cleanup\r\n");
return TF_CLOSE;
} // this is a final call before timeout, to clean up
if (msg->type == MSG_BULK_READ_POLL) {
uint32_t pos = (uint32_t) msg->userdata2;
uint32_t total = (uint32_t) strlen(longtext); // normally we'd not calculate it here
dbg("BR poll, at %d", (int)pos);
// Say we're done and close if it's over
if (pos >= total) {
Job job = {
.cb = job_bulkread_close,
.frame_id = msg->frame_id
};
scheduleJob(&job, TSK_SCHED_HIGH);
return TF_CLOSE;
}
PayloadParser pp = pp_start(msg->data, msg->len, NULL);
uint32_t chunk = pp_u32(&pp);
chunk = MIN(chunk, total - pos);
// this isn't at all resistant to error, we expect the communication to be lossless
Job job = {
.cb = job_bulkread_chunk,
.frame_id = msg->frame_id,
.buf = (uint8_t *) (longtext + pos),
.len = chunk,
};
scheduleJob(&job, TSK_SCHED_HIGH);
// advance the position pointer
pos += chunk;
msg->userdata2 = (void *) pos;
}
if (msg->type == MSG_BULK_ABORT) {
return TF_CLOSE;
}
return TF_RENEW;
memcpy(buffer, longtext+offset, len);
}
/** Handle a request message */
@ -183,44 +111,24 @@ static bool Tst_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Paylo
switch (command) {
case CMD_PING:
dbg("Ping msg!");
tf_respond_ok(frame_id);
//sched_respond_suc(frame_id);
break;
case CMD_ECHO:;
uint32_t len = (uint32_t) pp_length(pp);
uint8_t *cpy = malloc(len);
memcpy(cpy, pp_tail(pp, NULL), len);
Job job = {
.cb = job_echo,
.frame_id = frame_id,
.buf = cpy,
.len = len,
};
PRINTF("ECHO, len %d: ", (int)len);
PUTSN((char *) cpy, len);
PUTS("\r\n");
scheduleJob(&job, TSK_SCHED_HIGH);
uint32_t len;
const uint8_t *data = pp_tail(pp, &len);
tf_respond_buf(MSG_SUCCESS, frame_id, data, len);
break;
case CMD_BULKREAD:;
TF_Msg msg = {
.frame_id = frame_id,
.userdata = unit, // we'll keep a reference to the unit here
.userdata2 = 0 // and current position here.
};
// in a real scenario, we'd put a malloc'd struct here.
TF_AddIdListener(comm, &msg, bulkread_lst, 500);
Job job2 = {
.cb = job_bulkread_offer,
.frame_id = frame_id,
.d32 = (uint32_t) strlen(longtext),
};
scheduleJob(&job2, TSK_SCHED_HIGH);
struct bulk_read *bulk = malloc(sizeof(struct bulk_read));
assert_param(bulk);
bulk->len = (uint32_t) strlen(longtext);
bulk->frame_id = frame_id;
bulk->read = br_longtext;
bulkread_start(comm, bulk);
break;
default:

@ -35,11 +35,11 @@ extern "C" {
#define KB(size) ((size) * 1024)
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#define ROUND_UP(value, boundary) ((value) + ((boundary) - (value)) % (boundary))

Loading…
Cancel
Save