-
Notifications
You must be signed in to change notification settings - Fork 15
Porting picoTCP OS
When using picoTCP in combination with an operating system, your system looks roughly like this:
The application can interface with the OS, picotcp, and picotcp-bsd through their respective APIs. You should already be familiar with the API of your OS of choice and the one from picoTCP.
picotcp-bsd is an extra library that will provide POSIX/BSD/Berkeley style sockets, on top of the native picoTCP API, using the OS's facilities.
Porting picoTCP to an operating system basically consists of a few things:
- Writing an interface for picotcp-bsd to the OS.
- Optionally modifying the device driver to play nice with the OS.
- Using the picotcp-bsd interface, instead of native picotcp API.
picotcp-bsd will use a few primitives from your OS, and you should implement wrappers to init/use/destroy these. Namely: mutexes, signals and optionally threads.
void * pico_mutex_init(void);
Used to create a mutex native to the OS, and wraps it in an opaque 'mutex void pointer'. Returns NULL in case of failure.
void pico_mutex_deinit(void * mutex);
Destroys and frees a mutex previously created using pico_mutex_init.
void pico_mutex_lock(void * mutex);
Tries to lock a mutex, and will block without a timeout until it becomes available.
int pico_mutex_lock_timeout(void * mutex, int timeout);
Same as pico_mutex_lock but will give up after timeout, which is specified in milliseconds.
void pico_mutex_unlock(void * mutex);
Unlocks a previously locked mutex.
void * pico_signal_init(void);
Used to create a signal (or semaphore) native to the OS, and wraps it in an opaque 'signal void pointer'. Returns NULL in case of failure.
void pico_signal_deinit(void * signal);
Destroys and frees a signal previously created using pico_signal_init.
void pico_signal_wait(void * signal);
Wait for a signal to be sent, blocking indefinitely until it gets the signal.
int pico_signal_wait_timeout(void * signal, int timeout);
Same as pico_signal_wait but will give up after timeout, which is specified in milliseconds.
void pico_signal_send(void * signal);
Sends a signal, so another thread waiting for this signal gets unblocked.
NOTE: These are actually not used by picotcp-bsd yet, but can provide a nice unified API towards your application when porting across different OSes.
pico_thread_t pico_thread_create(pico_thread_fn thread, void *arg, int stack_size, int prio);
void pico_thread_destroy(pico_thread_t t);
void pico_threads_schedule(void);
void pico_msleep(int ms);
Driver and OS specific. E.g. send a signal/semaphore from the ISR, to wake up a thread that will enqueue packets into the stack.
The picotcp-bsd interface needs to be initialized, after pico_stack_init, using pico_bsd_init. Also, instead of using pico_stack_tick, one should use the picotcp-bsd version instead: pico_bsd_stack_tick.
void main(void)
{
pico_stack_init();
pico_bsd_init();
/* other initialization code */
for (;;) {
pico_bsd_stack_tick();
}
}
After this, a second thread/task can be created, that can use all of the POSIX/BSD/Berkeley socket API function provided by picotcp-bsd.
E.g.:
static int init_server(void)
{
struct sockaddr_in srv = { 0 };
int sock_fd;
srv.sin_family = AF_INET;
srv.sin_addr.s_addr = INADDR_ANY;
srv.sin_port = short_be(7);
sock_fd = pico_newsocket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
panic();
if (pico_bind(sock_fd, (struct sockaddr *)&srv, sizeof(struct sockaddr_in)) < 0)
panic();
if (pico_listen(sock_fd, 2) < 0)
panic();
/* more code */
}
Getting Started
- Setting up the environment
- Testing
- Configuring and compiling
- Running picoTCP on Linux - Deprecated (see setting up)
- Running picoTCP on Windows
Porting
- Build process explained
- Porting the build to another compiler or IDE
- Porting picoTCP to your favorite embedded target
- Porting picoTCP to your favorite Operating System
- Example device driver
Development