PyET
Python Embedded Tools


What is PyET?

Python Embedded Tools (a.k.a. PyET) is a set of Python programs, modules and scripts to aid in the development of embedded systems. Currently there are Python classes to control Background Debug Mode (BDM) pods for Motorola processors and JTAG boundary scan pods, and some examples classes to program the Flash memory of some boards.

The idea is to create in time a complete group of utilities with the benefits of a common scripting language and environment to program, debug, test and deploy a variety of embedded architectures.

PyET was born because we (embedded^cl) were in need of a dynamic, flexible utility framework for our embedded boards which usually run Linux or µClinux. PyET is being released as Libre software under the GNU GPL License.

Supported hardware

Actually, only parallel-port BDM pods for the ColdFire architecture (PyBDM package) and Xilinx-style JTAG cable (PyBSC) are on development. This first release is a demonstration of the capabilities of the proposed framework, and we expect to support more hardware depending on the needs of the development group.

Supported host environments

PyBDM and PyBSC run in PCs under Linux and Win32 systems.

The current Linux module uses ioperm to get direct access to the parallel port, and the popular GiveIO driver is used for the same reason under Windows. A future Linux port will use ioctl calls to perform port access in a cleaner way and, perhaps, target other POSIX platforms and communication ports (yes, we have MacOS X in mind).


Packages

PyET is evolving as a set of independent packages that are going to support a common Python interface. Development is being done in a layered fashion, where the lowest layer is a Python module (binary or not) that controls the hardware, and the topmost layer presents a user-friendly API.

PyBDM, Background Debug Mode for Motorola processors

PyBDM implements a BDM pod interface for Motorola processors. Currently only ColdFire cores are supported through parallel-port BDM pods.

This package is organized in the following modules:

  • ppbdm - low layer BDM pod communication
  • bdmpod - abstraction interface for bdm pods
  • bdmcmd - BDM command layer abstraction
  • bdmcpu - BDM CPU implementation
  • bdmreg - BDM register utilities
  • bdmflash - utilities for Flash programming through BDM

PyBSC, Boundary Scan for IEEE-1149.1 (JTAG) devices

This module is under heavy development right now. We are using this module to configure Xilinx CPLDs and FPGAs present in our boards, through a Xilinx-style parallel port cable. We are planning programming support for some ARM JTAG processors we have in sight for our ARM-based boards.


Download

[2003-07-06] PyBDM preliminary release, pybdm-0.0.2.tar.bz2.


Examples

Here are some simple examples that show the possibilities of the PyET framwework.

A simple PyBDM session

This PyBDM session demonstrates some uses of the PyBDM API with BDM pod, command and cpu interface objects. It also shows how to use the BDM interface to talk to an Intel StrataFlash memory through a bdmflash Python class.

Python 2.2.3 (#42, May 30 2003, 18:12:08) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from pybdm import * # import pybdm
>>> pod = bdmpod(port(0x378)) # create a pod object that talks to ppbdm parallel-port
>>> pod.halt() # halt device
>>> pod.port.get_bit(*nHALT) # check halt bit (inverted)
0
>>> cmd = bdmcmd(pod) # create command layer that talks through pod
>>> my_csr = csr(cmd(RDMREG, CSR)) # a bdm register object
>>> hex(int(my_csr)) # convert to int
'0x1200000'
>>> for i in my_csr.bit: print i, ':', eval('my_csr.'+i) # inspect bits
...
BKD : 0
MAP : 0
UHE : 0
HALT : 0
HRL : 2
TRC : 0
NPL : 0
TRG : 0
EMU : 0
BSTAT : 0
FOF : 0
IPW : 0
BTB : 0
DDC : 0
SSM : 0
PCD : 0
BKPT : 1
>>> for i in range(8): print 'D[%d] = 0x%.8x' % (i, cmd(RDREG, i)) # inspect D registers
...
D[0] = 0xcf41c012
D[1] = 0x06300530
D[2] = 0x0004a406
D[3] = 0xb0320030
D[4] = 0x06060084
D[5] = 0x60844c30
D[6] = 0x22462108
D[7] = 0xd2002229
>>> my_mbar = 0xe0000000
>>> my_rambar = 0x20000000
>>> cmd(WCREG, MBAR, my_mbar+1) # set MBAR register
>>> cmd(WCREG, RAMBAR0, my_rambar+1) # set RAMBAR0 register
>>> dump = cmd(DPL, my_mbar, 128) # dump SIM contents into array of longs
>>> map(hex, dump)
['0x80000f00', '0xffff0000', '0x0', '0x30000000', '0xf000000', '0xf000000', '0xf
000000', '0xf000000', '0x80000f00', '0xffff0000', '0x0', '0x30000000', '0xf00000
0', '0xf000000', '0xf000000', '0xf000000', '0x0', '0xffffffff', '0x0', '0x0', '0
x0', '0x0', '0x0', '0x0', '0x0', '0xffffffff', '0x0', '0x0', '0x0', '0x0', '0x0'
, '0x0', '0x1000000', '0x1840011a', '0x3de0', '0x49060000', '0x81a0000', '0x0',
'0x90000000', '0x10000', '0x10', '0x40090000', '0xc2060010', '0x10', '0x14210000
', '0x10000040', '0x1100', '0xf0000000', '0x44', '0x40', '0x29110000', '0x100001
08', '0x1800', '0x200000', '0x20400044', '0x25c0', '0x0', '0x0', '0x0', '0x0', '
0x0', '0x0', '0x0', '0x0', '0x280000', '0x280000', '0x12000000', '0x3880010', '0
x10240000', '0x20000000', '0x280000', '0x280000', '0x280000', '0x280000', '0x120
00000', '0x3880010', '0x10240000', '0x20000000', '0x280000', '0x280000', '0x0',
'0xffff0000', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0xffff0000', '0x
0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0xffff0000', '0x0', '0x0', '0x0',
 '0x0', '0x0', '0x0', '0x0', '0xffff0000', '0x0', '0x0', '0x0', '0x0', '0x0', '0
x0', '0x0', '0x0', '0x0', '0xff000000', '0xf000000', '0x0', '0x0', '0x0', '0x0',
 '0x0', '0x0', '0x0', '0xf000000', '0xff000000', '0x0', '0x0']
>>> cmd(FLL, my_rambar, range(1024*2/4)) # fill SRAM with increasing 512 longs
>>> dump = cmd(DUMP, LONG, my_rambar, 1024*2/4) # dump SRAM using explicit DUMP command
>>> len(dump) # get length of array
512
>>> dump[0] # get some values
0
>>> dump[1]
1
>>> dump[2]
2
>>> dump[3]
3
>>> dump[64]
64
>>> dump[128]
128
>>> dump[2*1024/4-1]
511
>>> creg = {
...             'CACR': 0x002,
...             'ACR0': 0x004,
...             'ACR1': 0x005,
...             'ACR2': 0x006,
...             'ACR3': 0x007,
...             'VBR': 0x801,
...             'MACSR': 0x804,
...             'MASK': 0x805,
...             'ACC': 0x806,
...             'SR': 0x80e,
...             'PC': 0x80f,
...             'RAMBAR': 0xc04,
...             'MBAR': 0xc0f
...     } # define control register addresses
>>> k = creg.keys(); k.sort()
>>> for i in k: print i, '=', hex(cmd(RCREG, creg[i])) # inspect control registers
...
ACC = 0x74910068
ACR0 = 0x40400000
ACR1 = 0x26880040
ACR2 = 0xb05e4000
ACR3 = 0x8e226000
CACR = 0x0
MACSR = 0x0
MASK = 0xffff3d09
MBAR = 0xe0000001
PC = 0x4f5f6bbe
RAMBAR = 0x20000001
SR = 0x2708
VBR = 0x0
>>> my_flash = 0xf0000000 # board Flash address
>>> cpu = bdmcf5407(pod, my_mbar) # create CF5407 BDM cpu interface object
>>> cpu.pod.halt() # halt device
>>> cpu.MBAR # get MBAR through CPU object layer
-536870911
>>> hex(_) # inspect MBAR
'0xe0000001'
>>> cpu.CSAR0 = (my_flash>>16) & 0xffff,W # configure Flash memory
>>> cpu.CSMR0 = 0x007f0001
>>> cpu.CSCR0 = 0x21c0,W
>>> cpu.DCR = 0x8650,W # configure DRAM memory
>>> cpu.DACR0 = 0x00009600
>>> cpu.DMR0 = 0x03fc0001
>>> cpu.DACR1 = 0x00
>>> cpu.DMR1 = 0x00
>>> sf = strataflash(cpu, my_flash) # create BDM StrataFlash interface object
>>> k = sf.read_codes() # read codes command
>>> dir(k)
['__doc__', '__module__', 'device', 'lock', 'manufacturer']
>>> hex(k.manufacturer) # inspect code contents
'0x89'
>>> hex(k.device)
'0x17'
>>> k.lock
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> k = sf.read_query() # read query command
>>> dir(k)
['__doc__', '__module__', 'alternate_id_code', 'device', 'device_interface', 'de
vice_size', 'erase_block_region1', 'erase_block_regions', 'features', 'major_ver
sion', 'manufacturer', 'minor_version', 'pri', 'primary_algorithm_address', 'pri
mary_id_code', 'qry', 'secondary_algorithm_address', 'write_buffer_size']
>>> hex(k.device_interface) # inspect query contents
'0x2'
>>> hex(k.major_version)
'0x31'
>>> hex(k.minor_version)
'0x32'
>>> hex(k.primary_id_code)
'0x1'
>>> k.pri
'PRI'
>>> k.qry
'QRY'
>>> for i in range(1024): # fill DRAM through CPU object
...     cpu[i*4] = i
...
>>> mem = cpu[0:1024*4:L] # dump using CPU slices interface
>>> mem # print array
array('l', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59
, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79
, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115
, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131
, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147
, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163
, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179
, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195
, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211
, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227
, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243
, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259
, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275
, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291
, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307
, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323
, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339
, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355
, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371
, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387
, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403
, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419
, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435
, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451
, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467
, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483
, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499
, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515
, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531
, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547
, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563
, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579
, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595
, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611
, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627
, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643
, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659
, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675
, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691
, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707
, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723
, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739
, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755
, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771
, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787
, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803
, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819
, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835
, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851
, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867
, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883
, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899
, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915
, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931
, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947
, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963
, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979
, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995
, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009
, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022,
1023])
>>> cpu.pod.reset() # reset device

Using a script to program a StrataFlash memory through BDM

This example uses the pybdm/arch/yazu/yazuprog script that programs through BDM an Intel StrataFlash memory present in a MCF5407-based board.

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ ./yazuprog
Usage: ./yazuprog command [arguments]
        detect: detect flash type
        erase [#b]: erases flash or block #b
        blank [#b]: checks if flash or block #b is blank
        lock [#b]: locks flash block #b
        unlock [#b]: unlocks flash block #b
        flash #o "f": flashes file "f" at offset #o
        dump "f" #o #l: dumps #l bytes from offset #o to file "f"
        reset: resets system

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ ./yazuprog detect
Device is Intel StrataFlash, 8388608 bytes [64 128kB-blocks]
Locks: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ ./yazuprog blank 0
Block 0 not blank

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ ./yazuprog erase 0
Erasing flash block 0

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ ./yazuprog blank 0
Block 0 blank

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ ./yazuprog flash 0 README.txt
Writing to flash... in 0.110000014305 seconds
Verifying data... Flash OK

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ wc README.txt
     12      80     525 README.txt

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ ./yazuprog dump dump.bin 0 525

Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ cat dump.bin
yazú Tools
----------
yazú is a line of embedded^CL boards based on Motorola ColdFire processors.


yazú^5407
--------
The yazú^5407 board consists of a Motorola MCF5407 processor, a Xilinx SpartanII
e FPGA in a PQ208 package, an Asix Ax88796L 10/100Base-T Ethernet controller, an
d a Philips ISP1161A USB controller, among other goodies like RS485 and IrDA. It
 uses Intel StrataFlash memory.

Utilities:
- yazutest: script to configure a yazu^5407 board.
- yazuprog: script to program and test the flash of a yazu^5407 board.
Pablo Bleyer@pbleyer /cygdrive/e/cvs/pybdm/arch/yazu
$ _

PyET resources
  • Project info page
  • CVS repository
  • www.python.org
  • www.mingw.org
  • Dale Robert's GiveIO
  • Local GiveIO + LoadDRV
  • P&E Micro CPUCF cable
  • Bill Mohat's BDM pod
  • Cybertec's BDM pod
  • Jan Cablik's BDM pod
  • Xilinx cable support
  • Altera cable literature
  • PyET's logo, a yellow-billed Magpie (Pica Nuttalli), is courtesy of Daniel Lane from LSU. Along with being an excellent ornithologist and a fine illustrator, Dan is a WINGS Birding Tour leader and collaborates with the BirdingOnThe.Net group. Magpies are also called Piets or Pyets, so now you know how we chose PyET's logo :o) Here you can find more of Dan's artwork.

    Copyright (C) 2003 embedded^cl
    Pablo Bleyer Kocik <pbleyer AT embedded.cl>