wiki:Packages/Python

Version 3 (modified by Chris Johns, on 12/11/14 at 03:07:05) (diff)

--

Python

Python is a programming language that can be embedded in user programs giving them the added functionality of a fully featured scripting language. You can find out more about Python by visiting its web site -

http://www.python.org/

Python on RTEMS

Python and RTEMS are a great combination. RTEMS provides you with a stable, scalable real-time operating system on which you build your applications. It also allows you to run low priority threads for monitoring and management functions. SNMP and a webserver are examples of typical services and interfaces you find on embedded devices. These days with more internet integration in embedded real-time products the number of complex protocols grows. Python has an extensive protocol library that can be used by your application to meet these demands. For example you could send an email using SMTP, fetch configuration data from a POP or IMAP email account, or via the HTTP protocol from a web server.

So far I have used on RTEMS the following modules -

  1. The httplib (requires some minor, see Sourceforge Bug #1229646) to read web pages from a number of web servers.
  2. The imaplib to open and read my email INBOX.
  3. The smtplib to send email. I sent email to Joel to say hi. This uses the email package that can handle generating and parsing email.
  4. The os module. I was able to list, change and make directories.

If you use C++ in your application you can use PyCXX to integrate your C++ code to Python. The PyCXX project can be found at http://cxx.sourceforge.net/.

Building Python for RTEMS

The Python used in the follow example is version 2.4.1 built for the Cybertec Microcore Coldfire (5272) board. The instructions should be general enough to work on all supported RTEMS platforms.

RTEMS version is 4.6 but 4.7 will be even easier to support thanks to Ralf's excellent work in cleaning up the RTEMS header files. The RTEMS build is multilib therefore the multilib library install paths are used.

Python running on most modern machines makes use of dynamic loading of code. On Unix this is shared libraries and on Windows this is a DLL. On RTEMS we do not support dynamic loading so we need to build and include in the Python library required modules. Python normally handles this by running a Python program in the new Python interpreter. This program performs a range of checks and determines the modules the platform requires. We cannot do this for RTEMS so we have a list of modules and add them to the generated Makefile.

The build machine is running Fedora Core 3 with a working RTEMS tool set.

  • Fetch the Python source code from the Python web site.
  • Fetch the Python patch from the RTEMS web site (ftp://ftp.rtems.org/pub/rtems/4.6.99.2/contrib/python).
  • Unpack the Python source.
  • Perform a native build for the build machine outside the Python source tree. We need to create a local program call pgen. Python does not cross-compile out of the box and so a simple work around is to build Python for the local machine first and reference it. The pgen program is not used in the cross-compile for RTEMS but no reference results in it trying to be cross-compiled and run which will not succeed.

$ tar jxf Python-2.4.1.tar.bz2 $ mkdir fc3 $ cd fc3 $ ../Python-2.4/configure $ make $ cd ..

$ mkdir m5200 $ cd m5200 $ ../rtems-python.sh m68k m5200 m5200 /opt/rtems

You will end up with a Python library and Python header files ready for your application.

RTEMS Python Application

The Python documentation has a section on embedded Python into an application. It is a good idea to take a look at this documentation.

You can download the examples from the RTEMS ftp site. Unpack into a directory next to your Python source tree.

You will also need to get the current version of the untar.c file from the RTEMS source code. It contains a change to set the modification and access time to the time in the tar file. If you do not do this Python will see each Python source module as not compiled and compile it. The example package provides an updated version.

Example Application

The main function in the application untars the Python library into the internal RAM file system then creates an RTEMS task which runs the Python interpreter. The task is -

void run (rtems''task''argument main_id)
{
  setenv ("PYTHONHOME", "/python", 1);
  setenv ("PYTHONPATH", "/python/lib/python2.4", 1);
#if 0
  setenv ("PYTHONDEBUG", "10", 1);
  setenv ("PYTHONVERBOSE", "10", 1);
#endif

  Py''Main (our''argc, our_argv);

  rtems''event''send ((rtems''id) main''id, RTEMS''EVENT''0);

  rtems''task''delete (RTEMS_SELF);
}

The task picks up the global command line variables. If no command line arguments are provide Python will enter its command line mode and you can enter python commands directly.

Example Build Script

The build script in the example directory -

  1. Builds 3 C files
  2. Run the local Python 2.4 interpreter to compile all the python code. We only need the compiled python code.
  3. Creates a tar file of the compiled Python library code.
  4. Link the example.
  5. Convert to a binary image.
  6. Compress the image. The Cybertec Microcore boot monitor accept gzip and 7zip files.

RTEMS Python Build Script

The script requires you supply 4 options. The options are not checked. You can down the script with the example. See the RTEMS Python Application section.

  1. The RTEMS target. For example m68k for m68k-rtems.
  2. The CPU or BSP label. This is the directory the library and headers are installed into under the RTEMS prefix.
  3. The compiler flags for the CPU. For example the Coldfire 5272 is m5200. This is separared from the CPU name so the processors such the i386 family can be supported.
  4. The prefix is the path the installed RTEMS.

The script does not build in unicode support into Python. If you require unicode support you need remove --disable-unicode from the configure command line and place the unicode modules into the Modules list the script contains. Unicode is disabled as it contains a number of large 64K byte tables. These are not correctly declared as const so end up in the executable and then in the data space.

#! /bin/sh # # Script to build Python for RTEMS. # # Chris Johns # Copyright 2005 Chris Johns (chrisj@…) #

fatal() {

if [ $1 -ne 0 ] ; then

shift echo "error: $*" >&2 exit 1

fi return 0

}

lower='abcdefghijklmnopqrstuvwxyz' upper='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

BASEOBLIBS="Modules\/_bisectmodule.o \

Modules\/_csv.o \ Modules\/_heapqmodule.o \ Modules\/_localemodule.o \ Modules\/_randommodule.o \ Modules\/_ssl.o \ Modules\/_weakref.o \ Modules\/arraymodule.o \ Modules\/binascii.o \ Modules\/cPickle.o \ Modules\/cStringIO.o \ Modules\/cmathmodule.o \ Modules\/collectionsmodule.o \ Modules\/cryptmodule.o \ Modules\/datetimemodule.o \ Modules\/fcntlmodule.o \ Modules\/grpmodule.o \ Modules\/itertoolsmodule.o \ Modules\/mathmodule.o \ Modules\/md5c.o \ Modules\/md5module.o \ Modules\/operator.o \ Modules\/parsermodule.o \ Modules\/pwdmodule.o \ Modules\/regexmodule.o \ Modules\/regexpr.o \ Modules\/selectmodule.o \ Modules\/shamodule.o \ Modules\/socketmodule.o \ Modules\/stropmodule.o \ Modules\/structmodule.o \ Modules\/termios.o \ Modules\/timemodule.o \ Modules\/timingmodule.o \ Modules\/expat\/xmlparse.o \ Modules\/expat\/xmlrole.o \ Modules\/expat\/xmltok.o"

# # Add if you need unicode support. # # Modules\/cjkcodecs\/multibytecodec.o \ # Modules\/unicodedata.o \ #

version=2.4 source=Python-2.4.1

build=$(uname -m)-$(uname -s | sed -e 'y/'$upper'/'$lower'/') target=$1-rtems cpu=$2 cpu_flags=-$3 prefix=$4

CC=${target}-gcc CXX=${target}-g++ AR=${target}-ar CFLAGS="-g -O3 ${cpu_flags}" CPPFLAGS="-I ${prefix}/${target}/lib/include" LDFLAGS="${cpu_flags}" # -Xlinker --no-undefined -Xlinker --allow-multiple-definition" LIBS="-lc -lrtemscpu" LIBDIR="${prefix}/${target}/lib/m5200" INCLUDEDIR="${prefix}/${target}/include" CONFINCLUDEDIR="${prefix}/${target}/include"

echo "CC="${CC}" CXX="${CXX}" AR="${AR}" CFLAGS="${CFLAGS}" CPPFLAGS="${CPPFLAGS}" \

LDFLAGS="${LDFLAGS}" LIBS="${LIBS}" \ ../${source}/configure --host=$target --build=${build} --prefix=${prefix} \ --enable-pgen=../${build}/Parser/pgen --without-doc-strings --disable-unicode"

CC="${CC}" CXX="${CXX}" AR="${AR}" CFLAGS="${CFLAGS}" CPPFLAGS="${CPPFLAGS}" \

LDFLAGS="${LDFLAGS}" LIBS="${LIBS}" \ ../${source}/configure --host=$target --build=${build} --prefix=${prefix} \

--without-doc-strings --disable-unicode \ --enable-pgen=../${build}/Parser/pgen

fatal $? "python configure"

cat Makefile | \

sed -e "s/MODOBJS=/MODOBJS=${BASEOBLIBS}/g" -e "s/MACHDEP=.*/MACHDEP=\tRTEMS/g" > Makefile.tmp

fatal $? "python patch Makefile" rm Makefile && mv Makefile.tmp Makefile fatal $? "python replacing the Makefile"

mkdir -p Modules/cjkcodecs fatal $? "python making Modules/cjkcodecs" mkdir -p Modules/expat fatal $? "python making Modules/expat"

echo "make CFLAGS="${CFLAGS} ${CPPFLAGS}" LDFLAGS="${LDFLAGS}" LIBS="${LIBS}" \

LIBDIR="${LIBDIR}" INCLUDEDIR="${INCLUDEDIR}" CONFINCLUDEDIR="${CONFINCLUDEDIR}" \

all inclinstall libainstall"

make CFLAGS="${CFLAGS} ${CPPFLAGS}" LDFLAGS="${LDFLAGS}" LIBS="${LIBS}" \

LIBDIR="${LIBDIR}" INCLUDEDIR="${INCLUDEDIR}" CONFINCLUDEDIR="${CONFINCLUDEDIR}" \

all inclinstall libainstall

fatal $? "python make and install"

cp ${prefix}/${target}/lib/${cpu}/python${version}/config/libpython${version}.a \

${prefix}/${target}/lib/${cpu}/libpython${version}.a

fatal $? "python move library"

exit 0