Eh, and the attachment... Sorry about that; here it is. On Sun, Jul 26, 2009 at 08:52:33AM +0200, Bas Wijnen wrote: > Hi, > > On Thu, Jul 23, 2009 at 08:51:34AM +0200, Riccardo Mottola wrote: > > I hope we soon get a newer kernel and a basic toolchain, X11 and > > libraries to work on. The 2.4 kernel for example is unsuitable for > > typing. The keyboard inserts random characters. This is incovenient > > both for note taking as well as for small programming. > > I also hope some performance improvment. > > For the kernel I'm writing, Iris, I have a better keyboard driver than > the code in 2.6. On average it responds faster to keys, and it takes > less processor time. I'm writing the details here, so they can be > ported to Linux if anyone is interested. The essential parts are > interrupts: > > - Interrupts on change (currently falling or rising edge, but perhaps > lever interrupts are better) are enabled for all row pins. Between > scans, all columns are set to output 0. The rows are pull-up inputs. > If all inputs are high, no keys are pressed. > - The first key that is pressed will always generate an interrupt. > Therefore, periodic scanning is disabled while no keys are pressed. > This reduces processor time. > - Some other key presses or releases also trigger interrupts (changes in > "are all keys in a row pressed?"). This results in a faster response > to those events than from periodic scanning. > - Finally, I read out an entire port in one go. The kernel uses 8 times > gpio_get_pin, which means 8 reads of the port. Since these are > uncached, this is slower than needed. The same is true for other bulk > register changes, such as setting port direction or data output, but > those are less wasteful (than the data read) in the 2.6 kernel. This > may be insignificant, and has the drawback of requiring either direct > use of the port, or new functions in ops.h. > > For reference, I include the source[0] of my keyboard driver. Things to > keep in mind while reading it: > - I have stripped REG_ from all register definitions. The values > without the prefix are only used by Linux to define the values with > it. AFAICS any reference of a value without REG_ in Linux is a bug in > the kernel. I have no idea why this approach is chosen. > - The code is C++ so that it can use member functions and default > function arguments. It should be readable for anyone who only knows > C, though. > - A lot of original code has been stripped out for clarity. In > particular the parts for other GPIO devices. > > That's it for now. In case of any questions, please ask. > > Thanks, > Bas > > [0] This isn't really the source; I'm using a preprocessor which makes > the source look a bit like Python. I'm posting the preprocessed > source here, because I expect people to be unfamiliar with the > preprocessor. > > -- > I encourage people to send encrypted e-mail (see http://www.gnupg.org). > If you have problems reading my e-mail, use a better reader. > Please send the central message of e-mails as plain text > in the message body, not as HTML and definitely not as MS Word. > Please do not use the MS Word format for attachments either. > For more information, see http://a82-93-13-222.adsl.xs4all.nl/e-mail.html
> _______________________________________________ > Mipsbook-devel mailing list > Mipsbook-devel@linuxtogo.org > http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/mipsbook-devel -- I encourage people to send encrypted e-mail (see http://www.gnupg.org). If you have problems reading my e-mail, use a better reader. Please send the central message of e-mails as plain text in the message body, not as HTML and definitely not as MS Word. Please do not use the MS Word format for attachments either. For more information, see http://a82-93-13-222.adsl.xs4all.nl/e-mail.html
// Iris: micro-kernel for a capability-based operating system. // This file contains parts of boot-programs/gpio.ccp: GPIO driver, controlling all devices without special hardware. // Copyright 2009 Bas Wijnen <wij...@debian.org> // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. class Keyboard { unsigned keys[GPIO_KBD_NUM_COLS]; bool scanning; void parse (unsigned col, unsigned data) { for (unsigned row = 0; row < GPIO_KBD_NUM_ROWS; ++row) { if ((data ^ keys[col]) & (1 << row)) { unsigned code = (col << 3) | row; if (data & (1 << row)) { code |= 0x10000; } event (KEYBOARD_EVENT, code); } } keys[col] = data; // If any keys are pressed, scanning is required. if (data != GPIO_KBD_ROW_MASK) { scanning = true; } } public: bool is_scanning () { return scanning; } void scan () { // Disable interrupts during scan. GPIO_GPIER (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK; // All columns are input. GPIO_GPDIR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK; int const cols[GPIO_KBD_NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }; // Reading these values once means less accesses to (uncached thus slow) ports. unsigned dir = GPIO_GPDIR (GPIO_KBD_COL_PORT) & ~GPIO_KBD_COL_MASK; unsigned dat = GPIO_GPDR (GPIO_KBD_COL_PORT) & ~GPIO_KBD_COL_MASK; unsigned data; for (unsigned col = 0; col < GPIO_KBD_NUM_COLS; ++col) { // clear pin GPIO_GPDR (GPIO_KBD_COL_PORT) = dat; // output GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col]); // Generate events of previous column. Do that now, so there is a short delay for the data to stabilize. if (col != 0) { parse (col - 1, data); } else { // Add a short delay for stabilization. parse (0, keys[0]); // Set scanning to false before first real parse. scanning = false; } data = GPIO_GPDR (GPIO_KBD_ROW_PORT) & GPIO_KBD_ROW_MASK; // set pin GPIO_GPDR (GPIO_KBD_COL_PORT) = dat | (1 << cols[col]); // input GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir; } parse (GPIO_KBD_NUM_COLS - 1, data); // set all to 0. GPIO_GPDR (GPIO_KBD_COL_PORT) = dat; // set all to output. GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | GPIO_KBD_COL_MASK; data = GPIO_GPDR (GPIO_KBD_ROW_PORT); for (unsigned i = 0; i < 8; ++i) { // Set interrupts on change. if (data & (1 << i)) { gpio_irq_fall (GPIO_KBD_ROW_PORT, i); } else { gpio_irq_rise (GPIO_KBD_ROW_PORT, i); } // Clear pending interrupts. GPIO_GPFR (GPIO_KBD_ROW_PORT) |= 1 << i; } // Reenable interrupts. GPIO_GPIER (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK; } Keyboard () { // Set all columns to output without pull-ups when set as input. GPIO_GPPUR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK; GPIO_GPDIR (GPIO_KBD_COL_PORT) |= GPIO_KBD_COL_MASK; // Set all rows to input and enable the pull-ups. GPIO_GPPUR (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK; GPIO_GPDIR (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK; // Detect interrupts on falling edge. for (unsigned i = 0; i < GPIO_KBD_NUM_ROWS; ++i) { gpio_irq_fall (GPIO_KBD_ROW_PORT, i); } // Initialize matrix. for (unsigned i = 0; i < GPIO_KBD_NUM_COLS; ++i) { keys[i] = 0xff; } // Perform initial scan to get real values into matrix and set up the rest. scan (); } }; int main () { // Enable interrupts. GPIO_GPIER (GPIO_KBD_ROW_PORT) = GPIO_KBD_ROW_MASK; register_interrupt (IRQ_GPIO0); // Create a keyboard object. This calls the constructor (Keyboard::Keyboard (), defined above). Keyboard kbd; // Schedule an alarm for performing polls. receiver_set_alarm (__my_receiver, ALARM_INTERVAL); while (true) { Message msg; wait (&msg); switch (msg.protected_data) { case ~0: { // Alarm. if (kbd.is_scanning ()) { kbd.scan (); } receiver_set_alarm (__my_receiver, ALARM_INTERVAL); break; } case IRQ_GPIO0: { // Ack all. GPIO_GPFR (GPIO_KBD_ROW_PORT) = GPIO_KBD_ROW_MASK; // Always scan keyboard on any interrupt. kbd.scan (); // Reregister the interrupt. register_interrupt (IRQ_GPIO0); break; } } } }
signature.asc
Description: Digital signature
_______________________________________________ Mipsbook-devel mailing list Mipsbook-devel@linuxtogo.org http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/mipsbook-devel